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

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