mirror of
https://git.proxmox.com/git/grub2
synced 2025-10-24 19:49:22 +00:00
If we don't have writable grubenv, recordfail doesn't work, which means our quickboot behavior - with a timeout of 0 - leaves the user without a reliable way to access the boot menu if they're on UEFI, because unlike BIOS, UEFI does not support checking the state of modifier keys (i.e. holding down shift at boot is not detectable). Handle this corner case by always using a non-zero timeout on EFI when save_env doesn't work. Reuse GRUB_RECORDFAIL_TIMEOUT to avoid introducing another variable.
255 lines
7.1 KiB
Diff
255 lines
7.1 KiB
Diff
From 969aca16c8fd59d6cb41c39ea1626b8d1e910560 Mon Sep 17 00:00:00 2001
|
|
From: Aaron Miller <aaronmiller@fb.com>
|
|
Date: Thu, 27 Oct 2016 17:39:49 -0400
|
|
Subject: 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
|
|
|
|
Patch-Name: net-read-bracketed-ipv6-addr.patch
|
|
---
|
|
grub-core/net/http.c | 21 ++++++++--
|
|
grub-core/net/net.c | 93 +++++++++++++++++++++++++++++++++++++++++---
|
|
grub-core/net/tftp.c | 6 ++-
|
|
include/grub/net.h | 1 +
|
|
4 files changed, 110 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
|
|
index 5aa4ad3be..f182d7b87 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")
|
|
@@ -390,8 +401,10 @@ 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,
|
|
+ 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 d5d726a31..b917a75d5 100644
|
|
--- a/grub-core/net/net.c
|
|
+++ b/grub-core/net/net.c
|
|
@@ -437,6 +437,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;
|
|
@@ -475,6 +481,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;
|
|
@@ -1260,8 +1269,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)
|
|
{
|
|
@@ -1299,6 +1310,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)
|
|
@@ -1308,15 +1385,19 @@ grub_net_open_real (const char *name)
|
|
{
|
|
grub_net_t ret = grub_zalloc (sizeof (*ret));
|
|
if (!ret)
|
|
- return NULL;
|
|
- ret->protocol = proto;
|
|
- ret->server = grub_strdup (server);
|
|
- if (!ret->server)
|
|
+ grub_free (host);
|
|
+ if (host)
|
|
{
|
|
- grub_free (ret);
|
|
- return NULL;
|
|
+ ret->server = grub_strdup (host);
|
|
+ if (!ret->server)
|
|
+ {
|
|
+ grub_free (ret);
|
|
+ return NULL;
|
|
+ }
|
|
}
|
|
ret->fs = &grub_net_fs;
|
|
+ ret->protocol = proto;
|
|
+ ret->port = port;
|
|
return ret;
|
|
}
|
|
}
|
|
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
|
index 7d90bf66e..a0817a075 100644
|
|
--- a/grub-core/net/tftp.c
|
|
+++ b/grub-core/net/tftp.c
|
|
@@ -314,6 +314,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)
|
|
@@ -382,13 +383,16 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
err = grub_net_resolve_address (file->device->net->server, &addr);
|
|
if (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);
|
|
grub_free (data);
|
|
return err;
|
|
}
|
|
|
|
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 4a9069a14..cc114286e 100644
|
|
--- a/include/grub/net.h
|
|
+++ b/include/grub/net.h
|
|
@@ -270,6 +270,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;
|