]>
Commit | Line | Data |
---|---|---|
50fb4025 JR |
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 |