What is the problem with main grub.cfg just including the files based on
environment variables?

On Tue, 29 Oct 2019, 15:16 Javier Martinez Canillas, <javi...@redhat.com>
wrote:

> From: Paulo Flabiano Smorigo <pfsmor...@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 <pfsmor...@br.ibm.com>
> Signed-off-by: Javier Martinez Canillas <javi...@redhat.com>
> Reviewed-by: Daniel Kiper <daniel.ki...@oracle.com>
>
> ---
>
> Changes in v5:
> - Don't mix varible declarations and code.
> - Don't use variable length arrays.
> - Fix coding style issues.
> - Fix function prototype.
> - Include missing <grub/net.h> header.
>
> Changes in v4: None
> Changes in v3:
> - Add Reviewed-by tag from Daniel Kiper.
>
> Changes in v2: None
>
>  grub-core/net/net.c     | 131 ++++++++++++++++++++++++++++++++++++++++
>  grub-core/normal/main.c |  19 ++++--
>  include/grub/net.h      |   2 +
>  3 files changed, 148 insertions(+), 4 deletions(-)
>
> diff --git grub-core/net/net.c grub-core/net/net.c
> index d5d726a315e..f82ac15b4ec 100644
> --- grub-core/net/net.c
> +++ grub-core/net/net.c
> @@ -1735,6 +1735,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;
> diff --git grub-core/normal/main.c grub-core/normal/main.c
> index 1b03dfd57b9..ba579e75072 100644
> --- grub-core/normal/main.c
> +++ 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>
> @@ -323,10 +324,20 @@ 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 include/grub/net.h include/grub/net.h
> index c00b0ab117c..7ae4b6bd805 100644
> --- include/grub/net.h
> +++ include/grub/net.h
> @@ -569,6 +569,8 @@ grub_net_add_dns_server (const struct
> grub_net_network_level_address *s);
>  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;
>
> --
> 2.21.0
>
>
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to