All of lore.kernel.org
 help / color / mirror / Atom feed
From: Javier Martinez Canillas <javierm@redhat.com>
To: grub-devel@gnu.org
Cc: Vladimir Serbinenko <phcoder@gmail.com>,
	Daniel Kiper <daniel.kiper@oracle.com>,
	Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>,
	Javier Martinez Canillas <javierm@redhat.com>
Subject: [PATCH v2 3/3] Search for specific config files for netboot
Date: Fri, 18 Oct 2019 09:59:10 +0200	[thread overview]
Message-ID: <20191018075910.31263-4-javierm@redhat.com> (raw)
In-Reply-To: <20191018075910.31263-1-javierm@redhat.com>

From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>

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

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>

---

Changes in v2:
- Add Reviewed-by tag from Daniel Kiper.

 grub-core/net/net.c     | 117 ++++++++++++++++++++++++++++++++++++++++
 grub-core/normal/main.c |  17 ++++--
 include/grub/net.h      |   3 ++
 3 files changed, 133 insertions(+), 4 deletions(-)

diff --git a/grub-core/net/net.c b/grub-core/net/net.c
index d5d726a315e..f066b02ebad 100644
--- a/grub-core/net/net.c
+++ b/grub-core/net/net.c
@@ -1735,6 +1735,123 @@ 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_dprintf ("net", "attempt to fetch config %s\n", config);
+
+        grub_file_t file;
+        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 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 1b03dfd57b9..cdeb58f1a1e 100644
--- a/grub-core/normal/main.c
+++ b/grub-core/normal/main.c
@@ -323,10 +323,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_config_file (config);
 
 	  grub_enter_normal_mode (config);
 	  grub_free (config);
diff --git a/include/grub/net.h b/include/grub/net.h
index 556c54e579f..ff6d347f7da 100644
--- a/include/grub/net.h
+++ b/include/grub/net.h
@@ -578,4 +578,7 @@ extern char *grub_net_default_server;
 
 #define VLANTAG_IDENTIFIER 0x8100
 
+grub_err_t
+grub_net_search_configfile (char *config);
+
 #endif /* ! GRUB_NET_HEADER */
-- 
2.21.0



      parent reply	other threads:[~2019-10-18  7:59 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18  7:59 [PATCH v2 0/3] Search for specific config files using UUID, MAC and IP Javier Martinez Canillas
2019-10-18  7:59 ` [PATCH v2 1/3] Add %X option to printf functions Javier Martinez Canillas
2019-10-18  7:59 ` [PATCH v2 2/3] Set net_<interface>_client{id, uuid} variables from DHCP options Javier Martinez Canillas
2019-10-21 14:40   ` [PATCH v2 2/3] Set net_<interface>_client{id,uuid} " Daniel Kiper
2019-10-22  8:08     ` [PATCH v2 2/3] Set net_<interface>_client{id, uuid} " Javier Martinez Canillas
2019-10-18  7:59 ` Javier Martinez Canillas [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191018075910.31263-4-javierm@redhat.com \
    --to=javierm@redhat.com \
    --cc=daniel.kiper@oracle.com \
    --cc=grub-devel@gnu.org \
    --cc=pfsmorigo@br.ibm.com \
    --cc=phcoder@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.