dcavalca / rpms / grub2

Forked from rpms/grub2 3 years ago
Clone

Blame SOURCES/0167-net-read-bracketed-ipv6-addrs-and-port-numbers.patch

d9d99f
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
d9d99f
From: Aaron Miller <aaronmiller@fb.com>
d9d99f
Date: Fri, 29 Jul 2016 17:41:38 +0800
d9d99f
Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers
d9d99f
d9d99f
Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses
d9d99f
to be recognized with brackets around them, which is required to specify a port
d9d99f
number
d9d99f
---
d9d99f
 grub-core/net/http.c | 21 +++++++++++---
d9d99f
 grub-core/net/net.c  | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++
d9d99f
 grub-core/net/tftp.c |  8 ++++--
d9d99f
 include/grub/net.h   |  1 +
d9d99f
 4 files changed, 101 insertions(+), 6 deletions(-)
d9d99f
d9d99f
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
d9d99f
index 5aa4ad3befc..f182d7b871d 100644
d9d99f
--- a/grub-core/net/http.c
d9d99f
+++ b/grub-core/net/http.c
d9d99f
@@ -312,12 +312,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
d9d99f
   int i;
d9d99f
   struct grub_net_buff *nb;
d9d99f
   grub_err_t err;
d9d99f
+  char* server = file->device->net->server;
d9d99f
+  int port = file->device->net->port;
d9d99f
 
d9d99f
   nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
d9d99f
 			   + sizeof ("GET ") - 1
d9d99f
 			   + grub_strlen (data->filename)
d9d99f
 			   + sizeof (" HTTP/1.1\r\nHost: ") - 1
d9d99f
-			   + grub_strlen (file->device->net->server)
d9d99f
+			   + grub_strlen (server) + sizeof (":XXXXXXXXXX")
d9d99f
 			   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
d9d99f
 				     "\r\n") - 1
d9d99f
 			   + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
d9d99f
@@ -356,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
d9d99f
 	       sizeof (" HTTP/1.1\r\nHost: ") - 1);
d9d99f
 
d9d99f
   ptr = nb->tail;
d9d99f
-  err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
d9d99f
+  err = grub_netbuff_put (nb, grub_strlen (server));
d9d99f
   if (err)
d9d99f
     {
d9d99f
       grub_netbuff_free (nb);
d9d99f
@@ -365,6 +367,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
d9d99f
   grub_memcpy (ptr, file->device->net->server,
d9d99f
 	       grub_strlen (file->device->net->server));
d9d99f
 
d9d99f
+  if (port)
d9d99f
+    {
d9d99f
+      ptr = nb->tail;
d9d99f
+      grub_snprintf ((char *) ptr,
d9d99f
+	  sizeof (":XXXXXXXXXX"),
d9d99f
+	  ":%d",
d9d99f
+	  port);
d9d99f
+    }
d9d99f
+
d9d99f
   ptr = nb->tail;
d9d99f
   err = grub_netbuff_put (nb, 
d9d99f
 			  sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
d9d99f
@@ -390,8 +401,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
d9d99f
   grub_netbuff_put (nb, 2);
d9d99f
   grub_memcpy (ptr, "\r\n", 2);
d9d99f
 
d9d99f
-  data->sock = grub_net_tcp_open (file->device->net->server,
d9d99f
-				  HTTP_PORT, http_receive,
d9d99f
+  grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
d9d99f
+		data->filename, server, port ? port : HTTP_PORT);
d9d99f
+  data->sock = grub_net_tcp_open (server,
d9d99f
+				  port ? port : HTTP_PORT, http_receive,
d9d99f
 				  http_err, http_err,
d9d99f
 				  file);
d9d99f
   if (!data->sock)
d9d99f
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
d9d99f
index 9b8944292c7..1f887d44b32 100644
d9d99f
--- a/grub-core/net/net.c
d9d99f
+++ b/grub-core/net/net.c
d9d99f
@@ -439,6 +439,12 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
d9d99f
   grub_uint16_t newip[8];
d9d99f
   const char *ptr = val;
d9d99f
   int word, quaddot = -1;
d9d99f
+  int bracketed = 0;
d9d99f
+
d9d99f
+  if (ptr[0] == '[') {
d9d99f
+    bracketed = 1;
d9d99f
+    ptr++;
d9d99f
+  }
d9d99f
 
d9d99f
   if (ptr[0] == ':' && ptr[1] != ':')
d9d99f
     return 0;
d9d99f
@@ -477,6 +483,9 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
d9d99f
       grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
d9d99f
     }
d9d99f
   grub_memcpy (ip, newip, 16);
d9d99f
+  if (bracketed && *ptr == ']') {
d9d99f
+    ptr++;
d9d99f
+  }
d9d99f
   if (rest)
d9d99f
     *rest = ptr;
d9d99f
   return 1;
d9d99f
@@ -1336,8 +1345,10 @@ grub_net_open_real (const char *name)
d9d99f
 {
d9d99f
   grub_net_app_level_t proto;
d9d99f
   const char *protname, *server;
d9d99f
+  char *host;
d9d99f
   grub_size_t protnamelen;
d9d99f
   int try;
d9d99f
+  int port = 0;
d9d99f
 
d9d99f
   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
d9d99f
     {
d9d99f
@@ -1375,6 +1386,72 @@ grub_net_open_real (const char *name)
d9d99f
       return NULL;
d9d99f
     }  
d9d99f
 
d9d99f
+  char* port_start;
d9d99f
+  /* ipv6 or port specified? */
d9d99f
+  if ((port_start = grub_strchr (server, ':')))
d9d99f
+  {
d9d99f
+      char* ipv6_begin;
d9d99f
+      if((ipv6_begin = grub_strchr (server, '[')))
d9d99f
+	{
d9d99f
+	  char* ipv6_end = grub_strchr (server, ']');
d9d99f
+	  if(!ipv6_end)
d9d99f
+	    {
d9d99f
+	      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
d9d99f
+		      N_("mismatched [ in address"));
d9d99f
+	      return NULL;
d9d99f
+	    }
d9d99f
+	  /* port number after bracketed ipv6 addr */
d9d99f
+	  if(ipv6_end[1] == ':')
d9d99f
+	    {
d9d99f
+	      port = grub_strtoul (ipv6_end + 2, NULL, 10);
d9d99f
+	      if(port > 65535)
d9d99f
+		{
d9d99f
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
d9d99f
+			  N_("bad port number"));
d9d99f
+		  return NULL;
d9d99f
+		}
d9d99f
+	    }
d9d99f
+	  host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
d9d99f
+	}
d9d99f
+      else
d9d99f
+	{
d9d99f
+	  if (grub_strchr (port_start + 1, ':'))
d9d99f
+	    {
d9d99f
+	      int iplen = grub_strlen (server);
d9d99f
+	      /* bracket bare ipv6 addrs */
d9d99f
+	      host = grub_malloc (iplen + 3);
d9d99f
+	      if(!host)
d9d99f
+		{
d9d99f
+		  return NULL;
d9d99f
+		}
d9d99f
+	      host[0] = '[';
d9d99f
+	      grub_memcpy (host + 1, server, iplen);
d9d99f
+	      host[iplen + 1] = ']';
d9d99f
+	      host[iplen + 2] = '\0';
d9d99f
+	    }
d9d99f
+	  else
d9d99f
+	    {
d9d99f
+	      /* hostname:port or ipv4:port */
d9d99f
+	      port = grub_strtol (port_start + 1, NULL, 10);
d9d99f
+	      if(port > 65535)
d9d99f
+		{
d9d99f
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
d9d99f
+			  N_("bad port number"));
d9d99f
+		  return NULL;
d9d99f
+		}
d9d99f
+	      host = grub_strndup (server, port_start - server);
d9d99f
+	    }
d9d99f
+	}
d9d99f
+    }
d9d99f
+  else
d9d99f
+    {
d9d99f
+      host = grub_strdup (server);
d9d99f
+    }
d9d99f
+  if (!host)
d9d99f
+    {
d9d99f
+      return NULL;
d9d99f
+    }
d9d99f
+
d9d99f
   for (try = 0; try < 2; try++)
d9d99f
     {
d9d99f
       FOR_NET_APP_LEVEL (proto)
d9d99f
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
d9d99f
index f90071353ad..e267af354f4 100644
d9d99f
--- a/grub-core/net/tftp.c
d9d99f
+++ b/grub-core/net/tftp.c
d9d99f
@@ -333,6 +333,7 @@ tftp_open (struct grub_file *file, const char *filename)
d9d99f
   grub_err_t err;
d9d99f
   grub_uint8_t *nbd;
d9d99f
   grub_net_network_level_address_t addr;
d9d99f
+  int port = file->device->net->port;
d9d99f
 
d9d99f
   data = grub_zalloc (sizeof (*data));
d9d99f
   if (!data)
d9d99f
@@ -405,7 +406,10 @@ tftp_open (struct grub_file *file, const char *filename)
d9d99f
   err = grub_net_resolve_address (file->device->net->server, &addr);
d9d99f
   if (err)
d9d99f
     {
d9d99f
-      grub_dprintf("tftp", "Address resolution failed: %d\n", err);
d9d99f
+      grub_dprintf ("tftp", "Address resolution failed: %d\n", err);
d9d99f
+      grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
d9d99f
+		    (unsigned long long)data->file_size,
d9d99f
+		    (unsigned long long)data->block_size);
d9d99f
       destroy_pq (data);
d9d99f
       grub_free (data);
d9d99f
       return err;
d9d99f
@@ -413,7 +417,7 @@ tftp_open (struct grub_file *file, const char *filename)
d9d99f
 
d9d99f
   grub_dprintf("tftp", "opening connection\n");
d9d99f
   data->sock = grub_net_udp_open (addr,
d9d99f
-				  TFTP_SERVER_PORT, tftp_receive,
d9d99f
+				  port ? port : TFTP_SERVER_PORT, tftp_receive,
d9d99f
 				  file);
d9d99f
   if (!data->sock)
d9d99f
     {
d9d99f
diff --git a/include/grub/net.h b/include/grub/net.h
d9d99f
index e9ebc6a1b4f..f4cd86e582f 100644
d9d99f
--- a/include/grub/net.h
d9d99f
+++ b/include/grub/net.h
d9d99f
@@ -273,6 +273,7 @@ typedef struct grub_net
d9d99f
 {
d9d99f
   char *server;
d9d99f
   char *name;
d9d99f
+  int port;
d9d99f
   grub_net_app_level_t protocol;
d9d99f
   grub_net_packets_t packs;
d9d99f
   grub_off_t offset;