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