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

8e15ce
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
8e15ce
From: Aaron Miller <aaronmiller@fb.com>
8e15ce
Date: Fri, 29 Jul 2016 17:41:38 +0800
8e15ce
Subject: [PATCH] net: read bracketed ipv6 addrs and port numbers
8e15ce
8e15ce
Allow specifying port numbers for http and tftp paths, and allow ipv6 addresses
8e15ce
to be recognized with brackets around them, which is required to specify a port
8e15ce
number
8e15ce
8e15ce
Signed-off-by: Aaron Miller <aaronmiller@fb.com>
8e15ce
[pjones: various bug fixes]
8e15ce
Signed-off-by: Peter Jones <pjones@redhat.com>
8e15ce
---
8e15ce
 grub-core/net/http.c | 25 ++++++++++++---
8e15ce
 grub-core/net/net.c  | 87 +++++++++++++++++++++++++++++++++++++++++++++++++---
8e15ce
 grub-core/net/tftp.c |  8 +++--
8e15ce
 include/grub/net.h   |  1 +
8e15ce
 4 files changed, 109 insertions(+), 12 deletions(-)
8e15ce
8e15ce
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
8e15ce
index b616cf40b1e..12a2632ea55 100644
8e15ce
--- a/grub-core/net/http.c
8e15ce
+++ b/grub-core/net/http.c
8e15ce
@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
8e15ce
 	  nb2 = grub_netbuff_alloc (data->chunk_rem);
8e15ce
 	  if (!nb2)
8e15ce
 	    return grub_errno;
8e15ce
-	  grub_netbuff_put (nb2, data->chunk_rem);
8e15ce
+	  err = grub_netbuff_put (nb2, data->chunk_rem);
8e15ce
+	  if (err)
8e15ce
+	    return grub_errno;
8e15ce
 	  grub_memcpy (nb2->data, nb->data, data->chunk_rem);
8e15ce
 	  if (file->device->net->packs.count >= 20)
8e15ce
 	    {
8e15ce
@@ -312,12 +314,14 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
8e15ce
   int i;
8e15ce
   struct grub_net_buff *nb;
8e15ce
   grub_err_t err;
8e15ce
+  char* server = file->device->net->server;
8e15ce
+  int port = file->device->net->port;
8e15ce
 
8e15ce
   nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE
8e15ce
 			   + sizeof ("GET ") - 1
8e15ce
 			   + grub_strlen (data->filename)
8e15ce
 			   + sizeof (" HTTP/1.1\r\nHost: ") - 1
8e15ce
-			   + grub_strlen (file->device->net->server)
8e15ce
+			   + grub_strlen (server) + sizeof (":XXXXXXXXXX")
8e15ce
 			   + sizeof ("\r\nUser-Agent: " PACKAGE_STRING
8e15ce
 				     "\r\n") - 1
8e15ce
 			   + sizeof ("Range: bytes=XXXXXXXXXXXXXXXXXXXX"
8e15ce
@@ -356,7 +360,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
8e15ce
 	       sizeof (" HTTP/1.1\r\nHost: ") - 1);
8e15ce
 
8e15ce
   ptr = nb->tail;
8e15ce
-  err = grub_netbuff_put (nb, grub_strlen (file->device->net->server));
8e15ce
+  err = grub_netbuff_put (nb, grub_strlen (server));
8e15ce
   if (err)
8e15ce
     {
8e15ce
       grub_netbuff_free (nb);
8e15ce
@@ -365,6 +369,15 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
8e15ce
   grub_memcpy (ptr, file->device->net->server,
8e15ce
 	       grub_strlen (file->device->net->server));
8e15ce
 
8e15ce
+  if (port)
8e15ce
+    {
8e15ce
+      ptr = nb->tail;
8e15ce
+      grub_snprintf ((char *) ptr,
8e15ce
+	  sizeof (":XXXXXXXXXX"),
8e15ce
+	  ":%d",
8e15ce
+	  port);
8e15ce
+    }
8e15ce
+
8e15ce
   ptr = nb->tail;
8e15ce
   err = grub_netbuff_put (nb, 
8e15ce
 			  sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n")
8e15ce
@@ -390,8 +403,10 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
8e15ce
   grub_netbuff_put (nb, 2);
8e15ce
   grub_memcpy (ptr, "\r\n", 2);
8e15ce
 
8e15ce
-  data->sock = grub_net_tcp_open (file->device->net->server,
8e15ce
-				  HTTP_PORT, http_receive,
8e15ce
+  grub_dprintf ("http", "opening path %s on host %s TCP port %d\n",
8e15ce
+		data->filename, server, port ? port : HTTP_PORT);
8e15ce
+  data->sock = grub_net_tcp_open (server,
8e15ce
+				  port ? port : HTTP_PORT, http_receive,
8e15ce
 				  http_err, NULL,
8e15ce
 				  file);
8e15ce
   if (!data->sock)
8e15ce
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
8e15ce
index a46f82362ed..0ce5e675ed7 100644
8e15ce
--- a/grub-core/net/net.c
8e15ce
+++ b/grub-core/net/net.c
8e15ce
@@ -444,6 +444,13 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
8e15ce
   grub_uint16_t newip[8];
8e15ce
   const char *ptr = val;
8e15ce
   int word, quaddot = -1;
8e15ce
+  int bracketed = 0;
8e15ce
+
8e15ce
+  if (ptr[0] == '[')
8e15ce
+    {
8e15ce
+      bracketed = 1;
8e15ce
+      ptr++;
8e15ce
+    }
8e15ce
 
8e15ce
   if (ptr[0] == ':' && ptr[1] != ':')
8e15ce
     return 0;
8e15ce
@@ -482,6 +489,8 @@ parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest)
8e15ce
       grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0]));
8e15ce
     }
8e15ce
   grub_memcpy (ip, newip, 16);
8e15ce
+  if (bracketed && *ptr == ']')
8e15ce
+    ptr++;
8e15ce
   if (rest)
8e15ce
     *rest = ptr;
8e15ce
   return 1;
8e15ce
@@ -1343,8 +1352,10 @@ grub_net_open_real (const char *name)
8e15ce
 {
8e15ce
   grub_net_app_level_t proto;
8e15ce
   const char *protname, *server;
8e15ce
+  char *host;
8e15ce
   grub_size_t protnamelen;
8e15ce
   int try;
8e15ce
+  int port = 0;
8e15ce
 
8e15ce
   if (grub_strncmp (name, "pxe:", sizeof ("pxe:") - 1) == 0)
8e15ce
     {
8e15ce
@@ -1382,6 +1393,72 @@ grub_net_open_real (const char *name)
8e15ce
       return NULL;
8e15ce
     }  
8e15ce
 
8e15ce
+  char* port_start;
8e15ce
+  /* ipv6 or port specified? */
8e15ce
+  if ((port_start = grub_strchr (server, ':')))
8e15ce
+    {
8e15ce
+      char* ipv6_begin;
8e15ce
+      if((ipv6_begin = grub_strchr (server, '[')))
8e15ce
+	{
8e15ce
+	  char* ipv6_end = grub_strchr (server, ']');
8e15ce
+	  if(!ipv6_end)
8e15ce
+	    {
8e15ce
+	      grub_error (GRUB_ERR_NET_BAD_ADDRESS,
8e15ce
+		      N_("mismatched [ in address"));
8e15ce
+	      return NULL;
8e15ce
+	    }
8e15ce
+	  /* port number after bracketed ipv6 addr */
8e15ce
+	  if(ipv6_end[1] == ':')
8e15ce
+	    {
8e15ce
+	      port = grub_strtoul (ipv6_end + 2, NULL, 10);
8e15ce
+	      if(port > 65535)
8e15ce
+		{
8e15ce
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
8e15ce
+			  N_("bad port number"));
8e15ce
+		  return NULL;
8e15ce
+		}
8e15ce
+	    }
8e15ce
+	  host = grub_strndup (ipv6_begin, (ipv6_end - ipv6_begin) + 1);
8e15ce
+	}
8e15ce
+      else
8e15ce
+	{
8e15ce
+	  if (grub_strchr (port_start + 1, ':'))
8e15ce
+	    {
8e15ce
+	      int iplen = grub_strlen (server);
8e15ce
+	      /* bracket bare ipv6 addrs */
8e15ce
+	      host = grub_malloc (iplen + 3);
8e15ce
+	      if(!host)
8e15ce
+		{
8e15ce
+		  return NULL;
8e15ce
+		}
8e15ce
+	      host[0] = '[';
8e15ce
+	      grub_memcpy (host + 1, server, iplen);
8e15ce
+	      host[iplen + 1] = ']';
8e15ce
+	      host[iplen + 2] = '\0';
8e15ce
+	    }
8e15ce
+	  else
8e15ce
+	    {
8e15ce
+	      /* hostname:port or ipv4:port */
8e15ce
+	      port = grub_strtol (port_start + 1, NULL, 10);
8e15ce
+	      if(port > 65535)
8e15ce
+		{
8e15ce
+		  grub_error (GRUB_ERR_NET_BAD_ADDRESS,
8e15ce
+			  N_("bad port number"));
8e15ce
+		  return NULL;
8e15ce
+		}
8e15ce
+	      host = grub_strndup (server, port_start - server);
8e15ce
+	    }
8e15ce
+	}
8e15ce
+    }
8e15ce
+  else
8e15ce
+    {
8e15ce
+      host = grub_strdup (server);
8e15ce
+    }
8e15ce
+  if (!host)
8e15ce
+    {
8e15ce
+      return NULL;
8e15ce
+    }
8e15ce
+
8e15ce
   for (try = 0; try < 2; try++)
8e15ce
     {
8e15ce
       FOR_NET_APP_LEVEL (proto)
8e15ce
@@ -1391,14 +1468,13 @@ grub_net_open_real (const char *name)
8e15ce
 	  {
8e15ce
 	    grub_net_t ret = grub_zalloc (sizeof (*ret));
8e15ce
 	    if (!ret)
8e15ce
-	      return NULL;
8e15ce
-	    ret->protocol = proto;
8e15ce
-	    ret->server = grub_strdup (server);
8e15ce
-	    if (!ret->server)
8e15ce
 	      {
8e15ce
-		grub_free (ret);
8e15ce
+		grub_free (host);
8e15ce
 		return NULL;
8e15ce
 	      }
8e15ce
+	    ret->protocol = proto;
8e15ce
+	    ret->port = port;
8e15ce
+	    ret->server = host;
8e15ce
 	    ret->fs = &grub_net_fs;
8e15ce
 	    return ret;
8e15ce
 	  }
8e15ce
@@ -1473,6 +1549,7 @@ grub_net_open_real (const char *name)
8e15ce
   grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
8e15ce
 	      name);
8e15ce
 
8e15ce
+  grub_free (host);
8e15ce
   return NULL;
8e15ce
 }
8e15ce
 
8e15ce
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
8e15ce
index 4ab2f5c7357..d54b13f09ff 100644
8e15ce
--- a/grub-core/net/tftp.c
8e15ce
+++ b/grub-core/net/tftp.c
8e15ce
@@ -295,6 +295,7 @@ tftp_open (struct grub_file *file, const char *filename)
8e15ce
   grub_err_t err;
8e15ce
   grub_uint8_t *nbd;
8e15ce
   grub_net_network_level_address_t addr;
8e15ce
+  int port = file->device->net->port;
8e15ce
 
8e15ce
   data = grub_zalloc (sizeof (*data));
8e15ce
   if (!data)
8e15ce
@@ -362,14 +363,17 @@ tftp_open (struct grub_file *file, const char *filename)
8e15ce
   err = grub_net_resolve_address (file->device->net->server, &addr);
8e15ce
   if (err)
8e15ce
     {
8e15ce
-      grub_dprintf("tftp", "Address resolution failed: %d\n", err);
8e15ce
+      grub_dprintf ("tftp", "Address resolution failed: %d\n", err);
8e15ce
+      grub_dprintf ("tftp", "file_size is %llu, block_size is %llu\n",
8e15ce
+		    (unsigned long long)data->file_size,
8e15ce
+		    (unsigned long long)data->block_size);
8e15ce
       grub_free (data);
8e15ce
       return err;
8e15ce
     }
8e15ce
 
8e15ce
   grub_dprintf("tftp", "opening connection\n");
8e15ce
   data->sock = grub_net_udp_open (addr,
8e15ce
-				  TFTP_SERVER_PORT, tftp_receive,
8e15ce
+				  port ? port : TFTP_SERVER_PORT, tftp_receive,
8e15ce
 				  file);
8e15ce
   if (!data->sock)
8e15ce
     {
8e15ce
diff --git a/include/grub/net.h b/include/grub/net.h
8e15ce
index af0404db7e3..d55d505a03a 100644
8e15ce
--- a/include/grub/net.h
8e15ce
+++ b/include/grub/net.h
8e15ce
@@ -273,6 +273,7 @@ typedef struct grub_net
8e15ce
 {
8e15ce
   char *server;
8e15ce
   char *name;
8e15ce
+  int port;
8e15ce
   grub_net_app_level_t protocol;
8e15ce
   grub_net_packets_t packs;
8e15ce
   grub_off_t offset;