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

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