]> TLD Linux GIT Repositories - packages/grub2.git/blob - search-for-specific-config-file-for-netboot.patch
- grub2 from PLD
[packages/grub2.git] / search-for-specific-config-file-for-netboot.patch
1 From 38d458ddd69cb7dd6e7f58f9e9f3197c6b6184f3 Mon Sep 17 00:00:00 2001
2 From: Paulo Flabiano Smorigo <pfsmorigo@br.ibm.com>
3 Date: Tue, 27 Nov 2012 17:22:07 -0200
4 Subject: [PATCH 3/3] Search for specific config file for netboot
5
6 This patch implements a search for a specific configuration when the config
7 file is on a remoteserver. It uses the following order:
8    1) DHCP client UUID option.
9    2) MAC address (in lower case hexadecimal with dash separators);
10    3) IP (in upper case hexadecimal) or IPv6;
11    4) The original grub.cfg file.
12
13 This procedure is similar to what is used by pxelinux and yaboot:
14 http://www.syslinux.org/wiki/index.php/PXELINUX#config
15
16 This should close the bugzilla:
17 https://bugzilla.redhat.com/show_bug.cgi?id=873406
18 ---
19  grub-core/net/net.c     |  118 +++++++++++++++++++++++++++++++++++++++++++++++
20  grub-core/normal/main.c |   18 ++++++--
21  include/grub/net.h      |    3 ++
22  3 files changed, 135 insertions(+), 4 deletions(-)
23
24 diff --git a/grub-core/net/net.c b/grub-core/net/net.c
25 index 01c5d32..49c32c5 100644
26 --- a/grub-core/net/net.c
27 +++ b/grub-core/net/net.c
28 @@ -1548,6 +1548,124 @@ grub_net_restore_hw (void)
29    return GRUB_ERR_NONE;
30  }
31  
32 +grub_err_t
33 +grub_net_search_configfile (char *config)
34 +{
35 +  grub_size_t config_len;
36 +  char *suffix;
37 +
38 +  auto int search_through (grub_size_t num_tries, grub_size_t slice_size);
39 +  int search_through (grub_size_t num_tries, grub_size_t slice_size)
40 +    {
41 +      while (num_tries-- > 0)
42 +        {
43 +         grub_dprintf ("net", "probe %s\n", config);
44 +
45 +          grub_file_t file;
46 +          file = grub_file_open (config);
47 +
48 +          if (file)
49 +            {
50 +              grub_file_close (file);
51 +              grub_dprintf ("net", "found!\n");
52 +              return 0;
53 +            }
54 +          else
55 +            {
56 +              if (grub_errno == GRUB_ERR_IO)
57 +                grub_errno = GRUB_ERR_NONE;
58 +            }
59 +
60 +          if (grub_strlen (suffix) < slice_size)
61 +            break;
62 +
63 +          config[grub_strlen (config) - slice_size] = '\0';
64 +        }
65 +
66 +      return 1;
67 +    }
68 +
69 +  config_len = grub_strlen (config);
70 +  config[config_len] = '-';
71 +  suffix = config + config_len + 1;
72 +
73 +  struct grub_net_network_level_interface *inf;
74 +  FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
75 +    {
76 +      /* By the Client UUID. */
77 +
78 +      char client_uuid_var[sizeof ("net_") + grub_strlen (inf->name) +
79 +                           sizeof ("_clientuuid") + 1];
80 +      grub_snprintf (client_uuid_var, sizeof (client_uuid_var),
81 +                     "net_%s_clientuuid", inf->name);
82 +
83 +      const char *client_uuid;
84 +      client_uuid = grub_env_get (client_uuid_var);
85 +
86 +      if (client_uuid)
87 +        {
88 +          grub_strcpy (suffix, client_uuid);
89 +          if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
90 +        }
91 +
92 +      /* By the MAC address. */
93 +
94 +      /* Add ethernet type */
95 +      grub_strcpy (suffix, "01-");
96 +
97 +      grub_net_hwaddr_to_str (&inf->hwaddress, suffix + 3);
98 +
99 +      char *ptr;
100 +      for (ptr = suffix; *ptr; ptr++)
101 +        if (*ptr == ':')
102 +          *ptr = '-';
103 +
104 +      if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
105 +
106 +      /* By IP address */
107 +
108 +      switch ((&inf->address)->type)
109 +        {
110 +        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
111 +            {
112 +              grub_uint32_t n = grub_be_to_cpu32 ((&inf->address)->ipv4);
113 +              grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%02X%02X%02X%02X", \
114 +                             ((n >> 24) & 0xff), ((n >> 16) & 0xff), \
115 +                             ((n >> 8) & 0xff), ((n >> 0) & 0xff));
116 +
117 +              if (search_through (8, 1) == 0) return GRUB_ERR_NONE;
118 +              break;
119 +            }
120 +        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
121 +            {
122 +              char buf[GRUB_NET_MAX_STR_ADDR_LEN];
123 +              struct grub_net_network_level_address base;
124 +              base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
125 +              grub_memcpy (&base.ipv6, ((&inf->address)->ipv6), 16);
126 +              grub_net_addr_to_str (&base, buf);
127 +
128 +              for (ptr = buf; *ptr; ptr++)
129 +                if (*ptr == ':')
130 +                  *ptr = '-';
131 +
132 +              grub_snprintf (suffix, GRUB_NET_MAX_STR_ADDR_LEN, "%s", buf);
133 +              if (search_through (1, 0) == 0) return GRUB_ERR_NONE;
134 +              break;
135 +            }
136 +        case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
137 +          return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
138 +        default:
139 +          return grub_error (GRUB_ERR_BUG,
140 +                             "unsupported address type %d", (&inf->address)->type);
141 +        }
142 +    }
143 +
144 +  /* Remove the remaining minus sign at the end. */
145 +  config[config_len] = '\0';
146 +
147 +  return GRUB_ERR_NONE;
148 +}
149 +
150  static struct grub_preboot *fini_hnd;
151  
152  static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
153 diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
154 index aa0b3e5..cc519a5 100644
155 --- a/grub-core/normal/main.c
156 +++ b/grub-core/normal/main.c
157 @@ -32,6 +32,7 @@
158  #include <grub/i18n.h>
159  #include <grub/charset.h>
160  #include <grub/script_sh.h>
161 +#include <grub/net.h>
162  
163  GRUB_MOD_LICENSE ("GPLv3+");
164  
165 @@ -379,10 +380,19 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
166  
167        prefix = grub_env_get ("prefix");
168        if (prefix)
169 -       {
170 -         config = grub_xasprintf ("%s/grub.cfg", prefix);
171 -         if (! config)
172 -           goto quit;
173 +        {
174 +          grub_size_t config_len;
175 +          config_len = grub_strlen (prefix) +
176 +                      sizeof ("/grub.cfg-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
177 +          config = grub_malloc (config_len);
178 +
179 +          if (! config)
180 +            goto quit;
181 +
182 +          grub_snprintf (config, config_len, "%s/grub.cfg", prefix);
183 +
184 +          if (grub_strncmp (prefix + 1, "tftp", sizeof ("tftp") - 1) == 0)
185 +            grub_net_search_configfile (config);
186  
187           grub_enter_normal_mode (config);
188           grub_free (config);
189 diff --git a/include/grub/net.h b/include/grub/net.h
190 index 45348dd..09b8d56 100644
191 --- a/include/grub/net.h
192 +++ b/include/grub/net.h
193 @@ -534,6 +534,9 @@ extern char *grub_net_default_server;
194  #define GRUB_NET_TRIES 40
195  #define GRUB_NET_INTERVAL 400
196
197  #define VLANTAG_IDENTIFIER 0x8100
198  
199 +grub_err_t
200 +grub_net_search_configfile (char *config);
201 +
202  #endif /* ! GRUB_NET_HEADER */
203 -- 
204 1.7.10.4
205