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

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