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

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