The vendor class identifier with the string "HTTPClient" is used to
indicate that the packet is responding to an HTTP boot request. In the
DHCPv4 configuration, the boot_file for HTTP boot specifies the URL of
the boot file, while for PXE boot, it specifies the path to the boot
file. Consequently, the next-server field becomes obsolete, as the HTTP
URL already encodes the server address for the boot file.

In DHCPv6 configuration, no ambiguity in the boot_file, as
dhcp6.bootfile-url is used to specify the URL for both HTTP and PXE boot
files.

This update adds processing for the "HTTPClient" vendor class identifier
in DHCPACK packets, interpreting it as an HTTP format rather than a PXE
format.

Signed-off-by: Ken Lin <ken....@hpe.com>
Signed-off-by: Robbie Harwood <rharw...@redhat.com>
Signed-off-by: Michael Chang <mch...@suse.com>
---
 grub-core/net/bootp.c | 28 +++++++++++++++++++++++++++-
 include/grub/net.h    |  1 +
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
index cca7143e0..8bf0ca782 100644
--- a/grub-core/net/bootp.c
+++ b/grub-core/net/bootp.c
@@ -20,6 +20,7 @@
 #include <grub/env.h>
 #include <grub/i18n.h>
 #include <grub/command.h>
+#include <grub/net.h>
 #include <grub/net/ip.h>
 #include <grub/net/netbuff.h>
 #include <grub/net/udp.h>
@@ -333,6 +334,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
   grub_uint8_t opt_len, overload = 0;
   const char *boot_file = 0, *server_name = 0;
   grub_size_t boot_file_len, server_name_len;
+  char *vci_server_name = NULL;
+  char *vci_boot_file = NULL;
+  char *vci_protocol = NULL;
 
   addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
   addr.ipv4 = bp->your_ip;
@@ -382,6 +386,20 @@ grub_net_configure_by_dhcp_ack (const char *name,
       boot_file_len = sizeof (bp->boot_file);
     }
 
+  opt = find_dhcp_option (bp, size, GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER, 
&opt_len);
+  if (opt && opt_len)
+    {
+      grub_env_set_net_property (name, "vendor_class_identifier", (const char 
*) opt, opt_len);
+      if (grub_strncmp ((const char *) opt, "HTTPClient", opt_len) == 0
+         && dissect_url (bp->boot_file, &vci_protocol, &vci_server_name, 
&vci_boot_file))
+       {
+         server_name = vci_server_name;
+         server_name_len = grub_strlen (vci_server_name);
+         boot_file = vci_boot_file;
+         boot_file_len = grub_strlen (vci_boot_file);
+       }
+    }
+
   if (bp->server_ip)
     {
       grub_snprintf (server_ip, sizeof (server_ip), "%d.%d.%d.%d",
@@ -423,7 +441,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
        }
       if (device && !*device)
        {
-         *device = grub_xasprintf ("tftp,%s", server_name);
+         *device = grub_xasprintf ("%s,%s", vci_protocol ? : "tftp", 
server_name);
          grub_print_error ();
        }
     }
@@ -526,7 +544,12 @@ grub_net_configure_by_dhcp_ack (const char *name,
 
       val = grub_malloc (2 * opt_len + 4 + 1);
       if (!val)
+       {
+         grub_free (vci_protocol);
+         grub_free (vci_boot_file);
+         grub_free (vci_server_name);
           return inter;
+       }
 
       for (i = 0; i < opt_len; i++)
         {
@@ -552,6 +575,9 @@ grub_net_configure_by_dhcp_ack (const char *name,
   else
     grub_errno = GRUB_ERR_NONE;
 
+  grub_free (vci_protocol);
+  grub_free (vci_boot_file);
+  grub_free (vci_server_name);
   return inter;
 }
 
diff --git a/include/grub/net.h b/include/grub/net.h
index 3e2704e3a..e7d75b93a 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -530,6 +530,7 @@ enum
     GRUB_NET_DHCP_MESSAGE_TYPE = 53,
     GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
     GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
+    GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 60,
     GRUB_NET_BOOTP_CLIENT_ID = 61,
     GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
     GRUB_NET_DHCP_BOOTFILE_NAME = 67,
-- 
2.47.1


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to