|
|
27a4da |
From fc71f52ca2ea207a692b79819502bb1738c5d148 Mon Sep 17 00:00:00 2001
|
|
|
27a4da |
From: Aaron Miller <aaronmiller@fb.com>
|
|
|
27a4da |
Date: Fri, 29 Jul 2016 17:41:38 +0800
|
|
|
27a4da |
Subject: [PATCH 250/260] 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 |
---
|
|
|
27a4da |
grub-core/net/http.c | 25 +++++++++++---
|
|
|
27a4da |
grub-core/net/net.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++------
|
|
|
27a4da |
grub-core/net/tftp.c | 25 +++++++++++---
|
|
|
27a4da |
include/grub/net.h | 1 +
|
|
|
27a4da |
4 files changed, 125 insertions(+), 20 deletions(-)
|
|
|
27a4da |
|
|
|
27a4da |
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
|
|
|
27a4da |
index ef9538c53..e8accbe68 100644
|
|
|
27a4da |
--- a/grub-core/net/http.c
|
|
|
27a4da |
+++ b/grub-core/net/http.c
|
|
|
27a4da |
@@ -289,7 +289,9 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|
|
27a4da |
nb2 = grub_netbuff_alloc (data->chunk_rem);
|
|
|
27a4da |
if (!nb2)
|
|
|
27a4da |
return grub_errno;
|
|
|
27a4da |
- grub_netbuff_put (nb2, data->chunk_rem);
|
|
|
27a4da |
+ err = grub_netbuff_put (nb2, data->chunk_rem);
|
|
|
27a4da |
+ if (err)
|
|
|
27a4da |
+ return grub_errno;
|
|
|
27a4da |
grub_memcpy (nb2->data, nb->data, data->chunk_rem);
|
|
|
27a4da |
if (file->device->net->packs.count >= 20)
|
|
|
27a4da |
{
|
|
|
27a4da |
@@ -312,12 +314,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"
|
|
|
27a4da |
@@ -356,7 +360,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);
|
|
|
27a4da |
@@ -365,6 +369,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,
|
|
|
27a4da |
+ 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")
|
|
|
27a4da |
@@ -391,8 +404,10 @@ 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,
|
|
|
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,
|
|
|
27a4da |
http_err, NULL,
|
|
|
27a4da |
file);
|
|
|
27a4da |
if (!data->sock)
|
|
|
27a4da |
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
|
|
27a4da |
index b3a80ba29..6b4b10ba4 100644
|
|
|
27a4da |
--- a/grub-core/net/net.c
|
|
|
27a4da |
+++ b/grub-core/net/net.c
|
|
|
27a4da |
@@ -462,6 +462,13 @@ 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 |
+
|
|
|
27a4da |
+ if (ptr[0] == '[')
|
|
|
27a4da |
+ {
|
|
|
27a4da |
+ bracketed = 1;
|
|
|
27a4da |
+ ptr++;
|
|
|
27a4da |
+ }
|
|
|
27a4da |
|
|
|
27a4da |
if (ptr[0] == ':' && ptr[1] != ':')
|
|
|
27a4da |
return 0;
|
|
|
27a4da |
@@ -500,6 +507,8 @@ 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);
|
|
|
27a4da |
+ if (bracketed && *ptr == ']')
|
|
|
27a4da |
+ ptr++;
|
|
|
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, ':')))
|
|
|
27a4da |
+ {
|
|
|
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 |
@@ -1396,19 +1473,13 @@ grub_net_open_real (const char *name)
|
|
|
27a4da |
{
|
|
|
27a4da |
grub_net_t ret = grub_zalloc (sizeof (*ret));
|
|
|
27a4da |
if (!ret)
|
|
|
27a4da |
- return NULL;
|
|
|
27a4da |
- ret->protocol = proto;
|
|
|
27a4da |
- if (server)
|
|
|
27a4da |
{
|
|
|
27a4da |
- ret->server = grub_strdup (server);
|
|
|
27a4da |
- if (!ret->server)
|
|
|
27a4da |
- {
|
|
|
27a4da |
- grub_free (ret);
|
|
|
27a4da |
- return NULL;
|
|
|
27a4da |
- }
|
|
|
27a4da |
+ grub_free (host);
|
|
|
27a4da |
+ return NULL;
|
|
|
27a4da |
}
|
|
|
27a4da |
- else
|
|
|
27a4da |
- ret->server = NULL;
|
|
|
27a4da |
+ ret->protocol = proto;
|
|
|
27a4da |
+ ret->port = port;
|
|
|
27a4da |
+ ret->server = host;
|
|
|
27a4da |
ret->fs = &grub_net_fs;
|
|
|
27a4da |
ret->offset = 0;
|
|
|
27a4da |
ret->eof = 0;
|
|
|
27a4da |
@@ -1439,6 +1510,7 @@ grub_net_open_real (const char *name)
|
|
|
27a4da |
grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"),
|
|
|
27a4da |
name);
|
|
|
27a4da |
|
|
|
27a4da |
+ grub_free (host);
|
|
|
27a4da |
return NULL;
|
|
|
27a4da |
}
|
|
|
27a4da |
|
|
|
27a4da |
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
|
|
27a4da |
index 3931884c6..ed12e610f 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)
|
|
|
27a4da |
@@ -345,7 +346,10 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
|
27a4da |
grub_netbuff_reserve (&nb, 1500);
|
|
|
27a4da |
err = grub_netbuff_push (&nb, sizeof (*tftph));
|
|
|
27a4da |
if (err)
|
|
|
27a4da |
- return err;
|
|
|
27a4da |
+ {
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
+ return err;
|
|
|
27a4da |
+ }
|
|
|
27a4da |
|
|
|
27a4da |
tftph = (struct tftphdr *) nb.data;
|
|
|
27a4da |
|
|
|
27a4da |
@@ -383,32 +387,43 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
|
27a4da |
|
|
|
27a4da |
err = grub_netbuff_unput (&nb, nb.tail - (nb.data + hdrlen));
|
|
|
27a4da |
if (err)
|
|
|
27a4da |
- return err;
|
|
|
27a4da |
+ {
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
+ return err;
|
|
|
27a4da |
+ }
|
|
|
27a4da |
|
|
|
27a4da |
file->not_easily_seekable = 1;
|
|
|
27a4da |
file->data = data;
|
|
|
27a4da |
|
|
|
27a4da |
data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
|
|
|
27a4da |
if (!data->pq)
|
|
|
27a4da |
- return grub_errno;
|
|
|
27a4da |
+ {
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
+ return grub_errno;
|
|
|
27a4da |
+ }
|
|
|
27a4da |
|
|
|
27a4da |
grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server);
|
|
|
27a4da |
err = grub_net_resolve_address (file->device->net->server, &addr);
|
|
|
27a4da |
if (err)
|
|
|
27a4da |
{
|
|
|
27a4da |
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 |
+ grub_free (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 |
grub_dprintf("tftp", "connection failed\n");
|
|
|
27a4da |
destroy_pq (data);
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
return grub_errno;
|
|
|
27a4da |
}
|
|
|
27a4da |
|
|
|
27a4da |
@@ -422,6 +437,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
|
27a4da |
{
|
|
|
27a4da |
grub_net_udp_close (data->sock);
|
|
|
27a4da |
destroy_pq (data);
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
return err;
|
|
|
27a4da |
}
|
|
|
27a4da |
grub_net_poll_cards (GRUB_NET_INTERVAL + (i * GRUB_NET_INTERVAL_ADDITION),
|
|
|
27a4da |
@@ -438,6 +454,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
|
27a4da |
{
|
|
|
27a4da |
grub_net_udp_close (data->sock);
|
|
|
27a4da |
destroy_pq (data);
|
|
|
27a4da |
+ grub_free (data);
|
|
|
27a4da |
return grub_errno;
|
|
|
27a4da |
}
|
|
|
27a4da |
|
|
|
27a4da |
diff --git a/include/grub/net.h b/include/grub/net.h
|
|
|
27a4da |
index 0d9213d67..20e699bb0 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;
|
|
|
27a4da |
--
|
|
|
27a4da |
2.13.0
|
|
|
27a4da |
|