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

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