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

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