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