]>
Commit | Line | Data |
---|---|---|
8f0e8db7 AM |
1 | diff -up dhcp-4.0.0/common/conflex.c.options dhcp-4.0.0/common/conflex.c |
2 | --- dhcp-4.0.0/common/conflex.c.options 2007-12-29 11:13:51.000000000 -1000 | |
3 | +++ dhcp-4.0.0/common/conflex.c 2007-12-29 11:13:51.000000000 -1000 | |
4 | @@ -769,6 +769,8 @@ intern(char *atom, enum dhcp_token dfv) | |
c494ae74 PZ |
5 | return BALANCE; |
6 | if (!strcasecmp (atom + 1, "ound")) | |
7 | return BOUND; | |
8 | + if (!strcasecmp (atom + 1, "ootp-broadcast-always")) | |
9 | + return BOOTP_BROADCAST_ALWAYS; | |
10 | break; | |
11 | case 'c': | |
12 | if (!strcasecmp (atom + 1, "ase")) | |
8f0e8db7 AM |
13 | diff -up dhcp-4.0.0/includes/dhcpd.h.options dhcp-4.0.0/includes/dhcpd.h |
14 | --- dhcp-4.0.0/includes/dhcpd.h.options 2007-12-29 11:13:51.000000000 -1000 | |
15 | +++ dhcp-4.0.0/includes/dhcpd.h 2007-12-29 11:13:51.000000000 -1000 | |
16 | @@ -1055,6 +1055,9 @@ struct client_config { | |
c494ae74 PZ |
17 | int do_forward_update; /* If nonzero, and if we have the |
18 | information we need, update the | |
19 | A record for the address we get. */ | |
20 | + | |
21 | + int bootp_broadcast_always; /* If nonzero, always set the BOOTP_BROADCAST | |
22 | + flag in requests */ | |
23 | }; | |
24 | ||
25 | /* Per-interface state used in the dhcp client... */ | |
8f0e8db7 AM |
26 | diff -up dhcp-4.0.0/includes/dhctoken.h.options dhcp-4.0.0/includes/dhctoken.h |
27 | --- dhcp-4.0.0/includes/dhctoken.h.options 2007-10-31 09:13:33.000000000 -1000 | |
28 | +++ dhcp-4.0.0/includes/dhctoken.h 2007-12-29 11:13:51.000000000 -1000 | |
53716e04 ER |
29 | @@ -345,7 +345,8 @@ enum dhcp_token { |
30 | RANGE6 = 648, | |
31 | WHITESPACE = 649, | |
32 | TOKEN_ALSO = 650, | |
33 | - AFTER = 651 | |
34 | + AFTER = 651, | |
35 | + BOOTP_BROADCAST_ALWAYS = 652 | |
c494ae74 PZ |
36 | }; |
37 | ||
38 | #define is_identifier(x) ((x) >= FIRST_TOKEN && \ | |
8f0e8db7 AM |
39 | diff -up dhcp-4.0.0/client/dhclient.c.options dhcp-4.0.0/client/dhclient.c |
40 | --- dhcp-4.0.0/client/dhclient.c.options 2007-11-30 11:51:42.000000000 -1000 | |
41 | +++ dhcp-4.0.0/client/dhclient.c 2007-12-29 11:14:15.000000000 -1000 | |
42 | @@ -37,6 +37,12 @@ | |
43 | #include <sys/wait.h> | |
44 | #include <limits.h> | |
c494ae74 PZ |
45 | |
46 | +/* | |
47 | + * Defined in stdio.h when _GNU_SOURCE is set, but we don't want to define | |
48 | + * that when building ISC code. | |
49 | + */ | |
50 | +extern int asprintf(char **strp, const char *fmt, ...); | |
51 | + | |
52 | TIME default_lease_time = 43200; /* 12 hours... */ | |
53 | TIME max_lease_time = 86400; /* 24 hours... */ | |
54 | ||
8f0e8db7 AM |
55 | @@ -75,6 +81,9 @@ int onetry=0; |
56 | int quiet=1; | |
c494ae74 | 57 | int nowait=0; |
8f0e8db7 | 58 | char *mockup_relay = NULL; |
c494ae74 PZ |
59 | +int bootp_broadcast_always = 0; |
60 | + | |
61 | +extern u_int32_t default_requested_options[]; | |
8f0e8db7 AM |
62 | |
63 | static void usage PROTO ((void)); | |
64 | ||
65 | @@ -100,6 +109,15 @@ main(int argc, char **argv) { | |
c494ae74 | 66 | int no_dhclient_script = 0; |
8f0e8db7 | 67 | int local_family_set = 0; |
c494ae74 PZ |
68 | char *s; |
69 | + char *dhcp_client_identifier_arg = NULL; | |
70 | + char *dhcp_host_name_arg = NULL; | |
71 | + char *dhcp_fqdn_arg = NULL; | |
72 | + char *dhcp_vendor_class_identifier_arg = NULL; | |
73 | + char *dhclient_request_options = NULL; | |
74 | + | |
75 | + int timeout_arg = 0; | |
76 | + char *arg_conf = NULL; | |
77 | + int arg_conf_len = 0; | |
78 | ||
8f0e8db7 AM |
79 | /* Initialize client globals. */ |
80 | memset(&default_duid, 0, sizeof(default_duid)); | |
81 | @@ -224,6 +242,88 @@ main(int argc, char **argv) { | |
c494ae74 | 82 | } else if (!strcmp (argv [i], "--version")) { |
8f0e8db7 | 83 | log_info ("isc-dhclient-%s", PACKAGE_VERSION); |
c494ae74 PZ |
84 | exit (0); |
85 | + } else if (!strcmp (argv [i], "-I")) { | |
86 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
87 | + usage (); | |
88 | + return EXIT_FAILURE; | |
89 | + } | |
90 | + | |
8f0e8db7 AM |
91 | + if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) { |
92 | + log_error("-I option dhcp-client-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1); | |
c494ae74 PZ |
93 | + exit(1); |
94 | + } | |
95 | + | |
96 | + dhcp_client_identifier_arg = argv[i]; | |
97 | + } else if (!strcmp (argv [i], "-B")) { | |
98 | + bootp_broadcast_always = 1; | |
99 | + } else if (!strcmp (argv [i], "-H")) { | |
100 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
101 | + usage (); | |
102 | + return EXIT_FAILURE; | |
103 | + } | |
104 | + | |
8f0e8db7 AM |
105 | + if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) { |
106 | + log_error("-H option host-name string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1); | |
c494ae74 PZ |
107 | + exit(1); |
108 | + } | |
109 | + | |
110 | + if (dhcp_host_name_arg != NULL) { | |
111 | + log_error("The -H <host-name> and -F <fqdn> arguments are mutually exclusive"); | |
112 | + exit(1); | |
113 | + } | |
114 | + | |
115 | + dhcp_host_name_arg = argv[i]; | |
116 | + } else if (!strcmp (argv [i], "-F")) { | |
117 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
118 | + usage (); | |
119 | + return EXIT_FAILURE; | |
120 | + } | |
121 | + | |
8f0e8db7 AM |
122 | + if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) { |
123 | + log_error("-F option fqdn.fqdn string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1); | |
c494ae74 PZ |
124 | + exit(1); |
125 | + } | |
126 | + | |
127 | + if (dhcp_fqdn_arg != NULL) { | |
128 | + log_error("Only one -F <fqdn> argument can be specified"); | |
129 | + exit(1); | |
130 | + } | |
131 | + | |
132 | + if (dhcp_host_name_arg != NULL) { | |
133 | + log_error("The -F <fqdn> and -H <host-name> arguments are mutually exclusive"); | |
134 | + exit(1); | |
135 | + } | |
136 | + | |
137 | + dhcp_fqdn_arg = argv[i]; | |
138 | + } else if (!strcmp (argv [i], "-T")) { | |
139 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
140 | + usage (); | |
141 | + return EXIT_FAILURE; | |
142 | + } | |
143 | + | |
144 | + if ((timeout_arg = atoi(argv[i])) <= 0) { | |
145 | + log_error("-T timeout option must be > 0 - bad value: %s",argv[i]); | |
146 | + exit(1); | |
147 | + } | |
148 | + } else if (!strcmp (argv [i], "-V")) { | |
149 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
150 | + usage (); | |
151 | + return EXIT_FAILURE; | |
152 | + } | |
153 | + | |
8f0e8db7 AM |
154 | + if (strlen(argv[i]) >= DHCP_MAX_OPTION_LEN) { |
155 | + log_error("-V option vendor-class-identifier string \"%s\" is too long - maximum length is: %d", argv[i], DHCP_MAX_OPTION_LEN-1); | |
c494ae74 PZ |
156 | + exit(1); |
157 | + } | |
158 | + | |
159 | + dhcp_vendor_class_identifier_arg = argv[i]; | |
160 | + } else if (!strcmp (argv [i], "-R")) { | |
161 | + if ((++i == argc) || (argv[i] == NULL) || (*(argv[i])=='\0')) { | |
162 | + usage (); | |
163 | + return EXIT_FAILURE; | |
164 | + } | |
165 | + | |
166 | + dhclient_request_options=argv[i]; | |
8f0e8db7 AM |
167 | } else if (argv [i][0] == '-') { |
168 | usage (); | |
169 | } else { | |
170 | @@ -370,6 +470,166 @@ main(int argc, char **argv) { | |
c494ae74 PZ |
171 | /* Parse the dhclient.conf file. */ |
172 | read_client_conf (); | |
173 | ||
174 | + /* Parse any extra command line configuration arguments: */ | |
175 | + if ((dhcp_client_identifier_arg != NULL) && (*dhcp_client_identifier_arg != '\0')) { | |
176 | + arg_conf_len = asprintf(&arg_conf, "send dhcp-client-identifier \"%s\";", dhcp_client_identifier_arg); | |
177 | + | |
178 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
179 | + log_fatal("Unable to send -I option dhcp-client-identifier"); | |
180 | + } | |
181 | + | |
182 | + if ((dhcp_host_name_arg != NULL) && (*dhcp_host_name_arg != '\0')) { | |
183 | + if (arg_conf == 0) { | |
184 | + arg_conf_len = asprintf(&arg_conf, "send host-name \"%s\";", dhcp_host_name_arg); | |
185 | + | |
186 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
187 | + log_fatal("Unable to send -H option host-name"); | |
188 | + } else { | |
189 | + char *last_arg_conf = arg_conf; | |
190 | + arg_conf = NULL; | |
191 | + arg_conf_len = asprintf( &arg_conf, "%s\nsend host-name \"%s\";", last_arg_conf, dhcp_host_name_arg); | |
192 | + | |
193 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
194 | + log_fatal("Unable to send -H option host-name"); | |
195 | + | |
196 | + free(last_arg_conf); | |
197 | + } | |
198 | + } | |
199 | + | |
200 | + if ((dhcp_fqdn_arg != NULL) && (*dhcp_fqdn_arg != '\0')) { | |
201 | + if (arg_conf == 0) { | |
202 | + arg_conf_len = asprintf(&arg_conf, "send fqdn.fqdn \"%s\";", dhcp_fqdn_arg); | |
203 | + | |
204 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
205 | + log_fatal("Unable to send -F option fqdn.fqdn"); | |
206 | + } else { | |
207 | + char *last_arg_conf = arg_conf; | |
208 | + arg_conf = NULL; | |
209 | + arg_conf_len = asprintf( &arg_conf, "%s\nsend fqdn.fqdn \"%s\";", last_arg_conf, dhcp_fqdn_arg); | |
210 | + | |
211 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
212 | + log_fatal("Unable to send -F option fqdn.fqdn"); | |
213 | + | |
214 | + free(last_arg_conf); | |
215 | + } | |
216 | + } | |
217 | + | |
218 | + if (timeout_arg) { | |
219 | + if (arg_conf == 0) { | |
220 | + arg_conf_len = asprintf(&arg_conf, "timeout %d;", timeout_arg); | |
221 | + | |
222 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
223 | + log_fatal("Unable to process -T timeout argument"); | |
224 | + } else { | |
225 | + char *last_arg_conf = arg_conf; | |
226 | + arg_conf = NULL; | |
227 | + arg_conf_len = asprintf( &arg_conf, "%s\ntimeout %d;", last_arg_conf, timeout_arg); | |
228 | + | |
229 | + if ((arg_conf == 0) || (arg_conf_len == 0)) | |
230 | + log_fatal("Unable to process -T timeout argument"); | |
231 | + | |
232 | + free(last_arg_conf); | |
233 | + } | |
234 | + } | |
235 | + | |
236 | + if ((dhcp_vendor_class_identifier_arg != NULL) && (*dhcp_vendor_class_identifier_arg != '\0')) { | |
237 | + if (arg_conf == 0) { | |
238 | + arg_conf_len = asprintf(&arg_conf, "send vendor-class-identifier \"%s\";", dhcp_vendor_class_identifier_arg); | |
239 | + | |
240 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
241 | + log_fatal("Unable to send -V option vendor-class-identifier"); | |
242 | + } else { | |
243 | + char *last_arg_conf = arg_conf; | |
244 | + arg_conf = NULL; | |
245 | + arg_conf_len = asprintf(&arg_conf, "%s\nsend vendor-class-identifier \"%s\";", last_arg_conf, dhcp_vendor_class_identifier_arg); | |
246 | + | |
247 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
248 | + log_fatal("Unable to send -V option vendor-class-identifier"); | |
249 | + | |
250 | + free(last_arg_conf); | |
251 | + } | |
252 | + } | |
253 | + | |
254 | + if (dhclient_request_options != NULL) { | |
255 | + if (arg_conf == 0) { | |
256 | + arg_conf_len = asprintf(&arg_conf, "request %s;", dhclient_request_options); | |
257 | + | |
258 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
259 | + log_fatal("Unable to parse -R <request options list> argument"); | |
260 | + } else { | |
261 | + char *last_arg_conf = arg_conf; | |
262 | + arg_conf = NULL; | |
263 | + arg_conf_len = asprintf(&arg_conf, "%s\nrequest %s;", last_arg_conf, dhclient_request_options); | |
264 | + | |
265 | + if ((arg_conf == 0) || (arg_conf_len <= 0)) | |
266 | + log_fatal("Unable to parse -R <request options list> argument"); | |
267 | + | |
268 | + free(last_arg_conf); | |
269 | + } | |
270 | + } | |
271 | + | |
272 | + if (arg_conf) { | |
273 | + if (arg_conf_len == 0) | |
274 | + if ((arg_conf_len = strlen(arg_conf)) == 0) | |
275 | + /* huh ? cannot happen ! */ | |
276 | + log_fatal("Unable to process -I/-H/-F/-T/-V/-R configuration arguments"); | |
277 | + | |
278 | + /* parse the extra dhclient.conf configuration arguments | |
279 | + * into top level config: */ | |
280 | + struct parse *cfile = (struct parse *)0; | |
281 | + const char *val = NULL; | |
282 | + int token; | |
283 | + | |
284 | + status = new_parse (&cfile, -1, arg_conf, arg_conf_len, "extra dhclient -I/-H/-F/-T/-V/-R configuration arguments", 0); | |
285 | + | |
286 | + if ((status != ISC_R_SUCCESS) || (cfile -> warnings_occurred)) | |
287 | + log_fatal("Cannot parse -I/-H/-F/-T/-V/-R configuration arguments !"); | |
288 | + /* more detailed parse failures will be logged */ | |
289 | + | |
290 | + do { | |
291 | + token = peek_token (&val, (unsigned *)0, cfile); | |
292 | + if (token == END_OF_FILE) | |
293 | + break; | |
294 | + | |
295 | + parse_client_statement (cfile, (struct interface_info *)0, &top_level_config); | |
296 | + } while (1); | |
297 | + | |
298 | + if (cfile -> warnings_occurred) | |
299 | + log_fatal ("Cannot parse -I/-H/-F/-T/-V/-R configuration arguments !"); | |
300 | + end_parse (&cfile); | |
301 | + | |
302 | + if (timeout_arg) { | |
303 | + /* we just set the toplevel timeout, but per-client | |
304 | + * timeouts may still be at defaults. Also, it makes no | |
305 | + * sense having the reboot_timeout or backoff_cutoff | |
306 | + * greater than the timeout: | |
307 | + */ | |
308 | + if ((top_level_config.backoff_cutoff == 15) && (top_level_config.backoff_cutoff > (timeout_arg / 2))) | |
309 | + top_level_config.backoff_cutoff = (((unsigned long)(timeout_arg / 2)) == 0) ? timeout_arg : (unsigned long)(timeout_arg / 2); | |
310 | + | |
311 | + for (ip = interfaces; ip; ip = ip -> next) { | |
312 | + if (ip->client->config->timeout == 60) | |
313 | + ip->client->config->timeout = timeout_arg; | |
314 | + | |
315 | + if ((ip->client->config->reboot_timeout == 10) && (ip->client->config->reboot_timeout > ip->client->config->timeout)) | |
316 | + ip->client->config->reboot_timeout = ip->client->config->timeout; | |
c494ae74 PZ |
317 | + if ((ip->client->config->backoff_cutoff == 15) && (ip->client->config->backoff_cutoff > top_level_config.backoff_cutoff)) |
318 | + ip->client->config->backoff_cutoff = top_level_config.backoff_cutoff; | |
319 | + } | |
320 | + } | |
321 | + | |
322 | + if ((dhclient_request_options != 0) && (top_level_config.requested_options != default_requested_options)) { | |
323 | + for (ip = interfaces; ip; ip = ip -> next) { | |
324 | + if (ip->client->config->requested_options == default_requested_options) | |
325 | + ip->client->config->requested_options = top_level_config.requested_options; | |
326 | + } | |
327 | + } | |
328 | + | |
329 | + free(arg_conf); | |
330 | + arg_conf = NULL; | |
331 | + arg_conf_len = 0; | |
332 | + } | |
333 | + | |
334 | /* Parse the lease database. */ | |
335 | read_client_leases (); | |
336 | ||
8f0e8db7 | 337 | @@ -2105,7 +2365,8 @@ void make_discover (client, lease) |
c494ae74 PZ |
338 | client -> packet.xid = random (); |
339 | client -> packet.secs = 0; /* filled in by send_discover. */ | |
340 | ||
341 | - if (can_receive_unicast_unconfigured (client -> interface)) | |
342 | + if ((!(bootp_broadcast_always || client->config->bootp_broadcast_always)) | |
343 | + && can_receive_unicast_unconfigured(client->interface)) | |
344 | client -> packet.flags = 0; | |
345 | else | |
346 | client -> packet.flags = htons (BOOTP_BROADCAST); | |
8f0e8db7 | 347 | @@ -2189,7 +2450,9 @@ void make_request (client, lease) |
c494ae74 PZ |
348 | } else { |
349 | memset (&client -> packet.ciaddr, 0, | |
350 | sizeof client -> packet.ciaddr); | |
351 | - if (can_receive_unicast_unconfigured (client -> interface)) | |
352 | + if ((!(bootp_broadcast_always || | |
353 | + client ->config->bootp_broadcast_always)) && | |
354 | + can_receive_unicast_unconfigured (client -> interface)) | |
355 | client -> packet.flags = 0; | |
356 | else | |
357 | client -> packet.flags = htons (BOOTP_BROADCAST); | |
8f0e8db7 | 358 | @@ -2248,7 +2511,8 @@ void make_decline (client, lease) |
c494ae74 PZ |
359 | client -> packet.hops = 0; |
360 | client -> packet.xid = client -> xid; | |
361 | client -> packet.secs = 0; /* Filled in by send_request. */ | |
362 | - if (can_receive_unicast_unconfigured (client -> interface)) | |
363 | + if ((!(bootp_broadcast_always || client->config-> bootp_broadcast_always)) | |
364 | + && can_receive_unicast_unconfigured (client->interface)) | |
365 | client -> packet.flags = 0; | |
366 | else | |
367 | client -> packet.flags = htons (BOOTP_BROADCAST); | |
8f0e8db7 AM |
368 | diff -up dhcp-4.0.0/client/clparse.c.options dhcp-4.0.0/client/clparse.c |
369 | --- dhcp-4.0.0/client/clparse.c.options 2007-12-08 09:36:00.000000000 -1000 | |
370 | +++ dhcp-4.0.0/client/clparse.c 2007-12-29 11:13:51.000000000 -1000 | |
371 | @@ -132,6 +132,7 @@ isc_result_t read_client_conf () | |
372 | /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache) | |
373 | */ | |
374 | top_level_config.requested_lease = 7200; | |
c494ae74 PZ |
375 | + top_level_config.bootp_broadcast_always = 0; |
376 | ||
377 | group_allocate (&top_level_config.on_receipt, MDL); | |
378 | if (!top_level_config.on_receipt) | |
8f0e8db7 | 379 | @@ -295,7 +296,8 @@ void read_client_leases () |
c494ae74 PZ |
380 | interface-declaration | |
381 | LEASE client-lease-statement | | |
382 | ALIAS client-lease-statement | | |
383 | - KEY key-definition */ | |
384 | + KEY key-definition | | |
385 | + BOOTP_BROADCAST_ALWAYS */ | |
386 | ||
387 | void parse_client_statement (cfile, ip, config) | |
388 | struct parse *cfile; | |
8f0e8db7 | 389 | @@ -685,6 +687,12 @@ void parse_client_statement (cfile, ip, |
c494ae74 PZ |
390 | parse_reject_statement (cfile, config); |
391 | return; | |
392 | ||
393 | + case BOOTP_BROADCAST_ALWAYS: | |
394 | + token = next_token(&val, (unsigned*)0, cfile); | |
395 | + config -> bootp_broadcast_always = 1; | |
396 | + parse_semi (cfile); | |
397 | + return; | |
398 | + | |
399 | default: | |
400 | lose = 0; | |
401 | stmt = (struct executable_statement *)0; |