File 0003-normal-main-Search-for-specific-config-files-for-net.patch of Package grub2.19555
From cb2f15c544895e1f3d540dd39d36c4611bdf5b7b Mon Sep 17 00:00:00 2001
From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Date: Wed, 22 Jan 2020 12:01:55 +0100
Subject: [PATCH] normal/main: Search for specific config files 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
It is enabled by default but can be disabled by setting the environment
variable "feature_net_search_cfg" to "n" in an embedded configuration.
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=873406
Signed-off-by: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
---
grub-core/net/net.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++
grub-core/normal/main.c | 26 ++++++++--
include/grub/net.h | 2 +
3 files changed, 155 insertions(+), 4 deletions(-)
Index: grub-2.04/grub-core/net/net.c
===================================================================
--- grub-2.04.orig/grub-core/net/net.c
+++ grub-2.04/grub-core/net/net.c
@@ -1814,6 +1814,137 @@ grub_net_restore_hw (void)
return GRUB_ERR_NONE;
}
+grub_err_t
+grub_net_search_config_file (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_file_t file;
+
+ grub_dprintf ("net", "attempt to fetch config %s\n", config);
+
+ file = grub_file_open (config, GRUB_FILE_TYPE_CONFIG);
+
+ if (file)
+ {
+ grub_file_close (file);
+ 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 *ptr;
+ int client_uuid_len;
+ char *client_uuid_var;
+ const char *client_uuid;
+
+ client_uuid_len = sizeof ("net_") + grub_strlen (inf->name) +
+ sizeof ("_clientuuid") + 1;
+
+ client_uuid_var = grub_zalloc (client_uuid_len);
+ if (!client_uuid_var)
+ return grub_errno;
+
+ grub_snprintf (client_uuid_var, client_uuid_len,
+ "net_%s_clientuuid", inf->name);
+
+ client_uuid = grub_env_get (client_uuid_var);
+ grub_free (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);
+
+ 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;
Index: grub-2.04/grub-core/normal/main.c
===================================================================
--- grub-2.04.orig/grub-core/normal/main.c
+++ grub-2.04/grub-core/normal/main.c
@@ -18,6 +18,7 @@
*/
#include <grub/kernel.h>
+#include <grub/net.h>
#include <grub/normal.h>
#include <grub/dl.h>
#include <grub/misc.h>
@@ -341,10 +342,27 @@ grub_cmd_normal (struct grub_command *cm
prefix = grub_env_get ("prefix");
if (prefix)
- {
- config = grub_xasprintf ("%s/grub.cfg", prefix);
- if (! config)
- goto quit;
+ {
+ grub_size_t config_len;
+ int disable_net_search = 0;
+ const char *net_search_cfg;
+
+ 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);
+
+ net_search_cfg = grub_env_get ("feature_net_search_cfg");
+ if (net_search_cfg && net_search_cfg[0] == 'n')
+ disable_net_search = 1;
+
+ if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0 &&
+ !disable_net_search)
+ grub_net_search_config_file (config);
grub_enter_normal_mode (config);
grub_free (config);
Index: grub-2.04/include/grub/net.h
===================================================================
--- grub-2.04.orig/include/grub/net.h
+++ grub-2.04/include/grub/net.h
@@ -641,6 +641,8 @@ grub_net_add_dns_server (const struct gr
void
grub_net_remove_dns_server (const struct grub_net_network_level_address *s);
+grub_err_t
+grub_net_search_config_file (char *config);
extern char *grub_net_default_server;