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

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