grub2/0026-Search-for-specific-config-file-for-netboot.patch
Javier Martinez Canillas 7e98da058f
Cleanup our patchset to reduce the number of patches
This change reorganizes and cleanups our patches to reduce the patch number
from 314 patches to 187. That's achieved by dropping patches that are later
reverted and squashing fixes for earlier patches that introduced features.

There are no code changes and the diff with upstream is the same before and
after the cleanup. Having fewer patches makes easier to manage the patchset
and also will ease to rebase them on top of the latest grub-2.04 release.

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
2019-07-16 12:30:06 +02:00

200 lines
6.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Tue, 27 Nov 2012 17:22:07 -0200
Subject: [PATCH] Search for specific config file for netboot
This patch implements a search for a specific configuration when the config
file is on a remoteserver. It uses the following order:
1) DHCP client UUID option.
2) MAC address (in lower case hexadecimal with dash separators);
3) IP (in upper case hexadecimal) or IPv6;
4) The original grub.cfg file.
This procedure is similar to what is used by pxelinux and yaboot:
http://www.syslinux.org/wiki/index.php/PXELINUX#config
This should close the bugzilla:
https://bugzilla.redhat.com/show_bug.cgi?id=873406
---
grub-core/net/net.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++
grub-core/normal/main.c | 18 ++++++--
include/grub/net.h | 3 ++
3 files changed, 135 insertions(+), 4 deletions(-)
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index 10773fc3435..0769bf850d3 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1735,6 +1735,124 @@ grub_net_restore_hw (void)
return GRUB_ERR_NONE;
}
+grub_err_t
+grub_net_search_configfile (char *config)
+{
+ grub_size_t config_len;
+ char *suffix;
+
+ auto int search_through (grub_size_t num_tries, grub_size_t slice_size);
+ int search_through (grub_size_t num_tries, grub_size_t slice_size)
+ {
+ while (num_tries-- > 0)
+ {
+ grub_dprintf ("net", "probe %s\n", config);
+
+ grub_file_t file;
+ file = grub_file_open (config);
+
+ if (file)
+ {
+ grub_file_close (file);
+ grub_dprintf ("net", "found!\n");
+ return 0;
+ }
+ else
+ {
+ if (grub_errno == GRUB_ERR_IO)
+ grub_errno = GRUB_ERR_NONE;
+ }
+
+ if (grub_strlen (suffix) < slice_size)
+ break;
+
+ config[grub_strlen (config) - slice_size] = '\0';
+ }
+
+ return 1;
+ }
+
+ config_len = grub_strlen (config);
+ config[config_len] = '-';
+ suffix = config + config_len + 1;
+
+ struct grub_net_network_level_interface *inf;
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ /* By the Client UUID. */
+
+ char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) +
+ sizeof ("_clientuuid") + 1];
+ grub_snprintf (client_uuid_var, sizeof (client_uuid_var),
+ "net_%s_clientuuid", inf->name);
+
+ const char *client_uuid;
+ client_uuid = grub_env_get (client_uuid_var);
+
+ if (client_uuid)
+ {
+ grub_strcpy (suffix, client_uuid);
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+ }
+
+ /* By the MAC address. */
+
+ /* Add ethernet type */
+ grub_strcpy (suffix, "01-");
+
+ grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3);
+
+ char *ptr;
+ for (ptr = suffix; *ptr; ptr++)
+ if (*ptr == ':')
+ *ptr = '-';
+
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+
+ /* By IP address */
+
+ switch ((&inf->address)->type)
+ {
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
+ {
+ grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4);
+ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \
+ ((n >> 24) & 0xff), ((n >> 16) & 0xff), \
+ ((n >> 8) & 0xff), ((n >> 0) & 0xff));
+
+ if (search_through (8, 1) == 0) return GRUB_ERR_NONE;
+ break;
+ }
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
+ {
+ char buf[GRUB_NET_MAX_STR_ADDR_LEN];
+ struct grub_net_network_level_address base;
+ base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+ grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16);
+ grub_net_addr_to_str (&base, buf);
+
+ for (ptr = buf; *ptr; ptr++)
+ if (*ptr == ':')
+ *ptr = '-';
+
+ grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf);
+ if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
+ break;
+ }
+ case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
+ return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
+ default:
+ return grub_error (GRUB_ERR_BUG,
+ "unsupported address type %d", (&inf->address)->type);
+ }
+ }
+
+ /* Remove the remaining minus sign at the end. */
+ config[config_len] = '\0';
+
+ return GRUB_ERR_NONE;
+}
+
static struct grub_preboot *fini_hnd;
static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
index 759c475c4d9..b2654ef62e8 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -33,6 +33,7 @@
#include <grub/charset.h>
#include <grub/script_sh.h>
#include <grub/bufio.h>
+#include <grub/net.h>
#ifdef GRUB_MACHINE_IEEE1275
#include <grub/ieee1275/ieee1275.h>
#endif
@@ -365,10 +366,19 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
prefix = grub_env_get ("prefix");
if (prefix)
- {
- config = grub_xasprintf ("%s/grub.cfg", prefix);
- if (! config)
- goto quit;
+ {
+ grub_size_t config_len;
+ config_len = grub_strlen (prefix) +
+ sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ config = grub_malloc (config_len);
+
+ if (! config)
+ goto quit;
+
+ grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
+
+ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
+ grub_net_search_configfile (config);
grub_enter_normal_mode (config);
grub_free (config);
diff --git a/include/grub/net.h b/include/grub/net.h
index e266bae23f4..50d62ab0c8c 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -566,4 +566,7 @@ extern char *grub_net_default_server;
#define VLANTAG_IDENTIFIER 0x8100
+grub_err_t
+grub_net_search_configfile (char *config);
+
#endif /* ! GRUB_NET_HEADER */