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