Blame SOURCES/0257-bootp-Add-processing-DHCPACK-packet-from-HTTP-Boot.patch

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