63f1a9
From 7b6d6e50bea268456d55806cb21d49cbc01c10d1 Mon Sep 17 00:00:00 2001
63f1a9
From: Michael Chang <mchang@suse.com>
63f1a9
Date: Thu, 14 Jul 2016 18:45:14 +0800
31cddd
Subject: [PATCH] bootp: Add processing DHCPACK packet from HTTP Boot
63f1a9
63f1a9
The vendor class identifier with the string "HTTPClient" is used to denote the
63f1a9
packet as responding to HTTP boot request. In DHCP4 config, the filename for
63f1a9
HTTP boot is the URL of the boot file while for PXE boot it is the path to the
63f1a9
boot file. As a consequence, the next-server becomes obseleted because the HTTP
63f1a9
URL already contains the server address for the boot file. For DHCP6 config,
63f1a9
there's no difference definition in existing config as dhcp6.bootfile-url can
63f1a9
be used to specify URL for both HTTP and PXE boot file.
63f1a9
63f1a9
This patch adds processing for "HTTPClient" vendor class identifier in DHCPACK
63f1a9
packet by treating it as HTTP format, not as the PXE format.
63f1a9
63f1a9
Signed-off-by: Michael Chang <mchang@suse.com>
63f1a9
Signed-off-by: Ken Lin <ken.lin@hpe.com>
63f1a9
---
63f1a9
 grub-core/net/bootp.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++--
63f1a9
 include/grub/net.h    |  1 +
63f1a9
 2 files changed, 66 insertions(+), 2 deletions(-)
63f1a9
63f1a9
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
63f1a9
index 6995f986744..902e5a60154 100644
63f1a9
--- a/grub-core/net/bootp.c
63f1a9
+++ b/grub-core/net/bootp.c
63f1a9
@@ -254,6 +254,11 @@ parse_dhcp_vendor (const char *name, const void *vend, int limit, int *mask)
63f1a9
                                      taglength);
63f1a9
           break;
63f1a9
 
63f1a9
+        case GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER:
63f1a9
+          grub_env_set_net_property (name, "vendor_class_identifier", (const char *) ptr,
63f1a9
+                                     taglength);
63f1a9
+	  break;
63f1a9
+
63f1a9
 	case GRUB_NET_BOOTP_EXTENSIONS_PATH:
63f1a9
           grub_env_set_net_property (name, "extensionspath", (const char *) ptr,
63f1a9
                                      taglength);
63f1a9
@@ -362,6 +367,66 @@ grub_net_configure_by_dhcp_ack (const char *name,
63f1a9
     }
63f1a9
 #endif
63f1a9
 
63f1a9
+  if (size > OFFSET_OF (vendor, bp))
63f1a9
+    {
63f1a9
+      char *cidvar;
63f1a9
+      const char *cid;
63f1a9
+
63f1a9
+      parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
63f1a9
+      cidvar = grub_xasprintf ("net_%s_%s", name, "vendor_class_identifier");
63f1a9
+      cid = grub_env_get (cidvar);
63f1a9
+      grub_free (cidvar);
63f1a9
+
63f1a9
+      if (cid && grub_strcmp (cid, "HTTPClient") == 0)
63f1a9
+	{
63f1a9
+	  char *proto, *ip, *pa;
63f1a9
+
63f1a9
+	  if (!dissect_url (bp->boot_file, &proto, &ip, &pa))
63f1a9
+	    return inter;
63f1a9
+
63f1a9
+	  grub_env_set_net_property (name, "boot_file", pa, grub_strlen (pa));
63f1a9
+	  if (is_def)
63f1a9
+	    {
63f1a9
+	      grub_net_default_server = grub_strdup (ip);
63f1a9
+	      grub_env_set ("net_default_interface", name);
63f1a9
+	      grub_env_export ("net_default_interface");
63f1a9
+	    }
63f1a9
+	  if (device && !*device)
63f1a9
+	    {
63f1a9
+	      *device = grub_xasprintf ("%s,%s", proto, ip);
63f1a9
+	      grub_print_error ();
63f1a9
+	    }
63f1a9
+	  if (path)
63f1a9
+	    {
63f1a9
+	      *path = grub_strdup (pa);
63f1a9
+	      grub_print_error ();
63f1a9
+	      if (*path)
63f1a9
+		{
63f1a9
+		  char *slash;
63f1a9
+		  slash = grub_strrchr (*path, '/');
63f1a9
+		  if (slash)
63f1a9
+		    *slash = 0;
63f1a9
+		  else
63f1a9
+		    **path = 0;
63f1a9
+		}
63f1a9
+	    }
63f1a9
+	  grub_net_add_ipv4_local (inter, mask);
63f1a9
+	  inter->dhcp_ack = grub_malloc (size);
63f1a9
+	  if (inter->dhcp_ack)
63f1a9
+	    {
63f1a9
+	      grub_memcpy (inter->dhcp_ack, bp, size);
63f1a9
+	      inter->dhcp_acklen = size;
63f1a9
+	    }
63f1a9
+	  else
63f1a9
+	    grub_errno = GRUB_ERR_NONE;
63f1a9
+
63f1a9
+	  grub_free (proto);
63f1a9
+	  grub_free (ip);
63f1a9
+	  grub_free (pa);
63f1a9
+	  return inter;
63f1a9
+	}
63f1a9
+    }
63f1a9
+
63f1a9
   if (size > OFFSET_OF (boot_file, bp))
63f1a9
     grub_env_set_net_property (name, "boot_file", bp->boot_file,
63f1a9
                                sizeof (bp->boot_file));
63f1a9
@@ -426,8 +491,6 @@ grub_net_configure_by_dhcp_ack (const char *name,
63f1a9
 	    **path = 0;
63f1a9
 	}
63f1a9
     }
63f1a9
-  if (size > OFFSET_OF (vendor, bp))
63f1a9
-    parse_dhcp_vendor (name, &bp->vendor, size - OFFSET_OF (vendor, bp), &mask);
63f1a9
   grub_net_add_ipv4_local (inter, mask);
63f1a9
   
63f1a9
   inter->dhcp_ack = grub_malloc (size);
63f1a9
diff --git a/include/grub/net.h b/include/grub/net.h
63f1a9
index 373ad1080cf..1c7c3ecb6ab 100644
63f1a9
--- a/include/grub/net.h
63f1a9
+++ b/include/grub/net.h
63f1a9
@@ -519,6 +519,7 @@ enum
63f1a9
     GRUB_NET_BOOTP_DOMAIN = 0x0f,
63f1a9
     GRUB_NET_BOOTP_ROOT_PATH = 0x11,
63f1a9
     GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
63f1a9
+    GRUB_NET_BOOTP_VENDOR_CLASS_IDENTIFIER = 0x3C,
63f1a9
     GRUB_NET_BOOTP_CLIENT_ID = 0x3d,
63f1a9
     GRUB_NET_BOOTP_CLIENT_UUID = 0x61,
63f1a9
     GRUB_NET_BOOTP_END = 0xff