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

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