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.
200 lines
6.2 KiB
200 lines
6.2 KiB
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 f2e723bd409..578e057e18f 100644 |
|
--- a/grub-core/net/net.c |
|
+++ b/grub-core/net/net.c |
|
@@ -1702,6 +1702,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 f72844c9f37..85d2a2862d4 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 59e5975b11f..88fc71ceffe 100644 |
|
--- a/include/grub/net.h |
|
+++ b/include/grub/net.h |
|
@@ -542,4 +542,7 @@ extern char *grub_net_default_server; |
|
|
|
#define VLANTAG_IDENTIFIER 0x8100 |
|
|
|
+grub_err_t |
|
+grub_net_search_configfile (char *config); |
|
+ |
|
#endif /* ! GRUB_NET_HEADER */
|
|
|