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

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