ISC DHCP 4.4.3-P1
A reference DHCPv4 and DHCPv6 implementation
 
Loading...
Searching...
No Matches
clparse.c
Go to the documentation of this file.
1/* clparse.c
2
3 Parser for dhclient config and lease files... */
4
5/*
6 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
8 *
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 *
21 * Internet Systems Consortium, Inc.
22 * PO Box 360
23 * Newmarket, NH 03857 USA
24 * <info@isc.org>
25 * https://www.isc.org/
26 *
27 */
28
29#include "dhcpd.h"
30#include <errno.h>
31
33
34#define NUM_DEFAULT_REQUESTED_OPTS 15
35/* There can be 2 extra requested options for DHCPv4-over-DHCPv6. */
37
38static void parse_client_default_duid(struct parse *cfile);
39static void parse_client6_lease_statement(struct parse *cfile);
40#ifdef DHCPv6
41static struct dhc6_ia *parse_client6_ia_na_statement(struct parse *cfile);
42static struct dhc6_ia *parse_client6_ia_ta_statement(struct parse *cfile);
43static struct dhc6_ia *parse_client6_ia_pd_statement(struct parse *cfile);
44static struct dhc6_addr *parse_client6_iaaddr_statement(struct parse *cfile);
45static struct dhc6_addr *parse_client6_iaprefix_statement(struct parse *cfile);
46#endif /* DHCPv6 */
47
48static void parse_lease_id_format (struct parse *cfile);
49
50extern void discard_duplicate (struct client_lease** lease_list,
51 struct client_lease* lease);
52
53/* client-conf-file :== client-declarations END_OF_FILE
54 client-declarations :== <nil>
55 | client-declaration
56 | client-declarations client-declaration */
57
58isc_result_t read_client_conf ()
59{
60 struct client_config *config;
61 struct interface_info *ip;
62 isc_result_t status;
63 unsigned code;
64
65 /*
66 * TODO: LATER constant is very undescriptive. We should review it and
67 * change it to something more descriptive or even better remove it
68 * completely as it is currently not used.
69 */
70#ifdef LATER
71 struct parse *parse = NULL;
72#endif
73
74 /* Initialize the default request list. */
76
77 /* 1 */
78 code = DHO_SUBNET_MASK;
79 option_code_hash_lookup(&default_requested_options[0],
80 dhcp_universe.code_hash, &code, 0, MDL);
81
82 /* 2 */
84 option_code_hash_lookup(&default_requested_options[1],
85 dhcp_universe.code_hash, &code, 0, MDL);
86
87 /* 3 */
88 code = DHO_TIME_OFFSET;
89 option_code_hash_lookup(&default_requested_options[2],
90 dhcp_universe.code_hash, &code, 0, MDL);
91
92 /* 4 */
93 /* The Classless Static Routes option code MUST appear in the parameter
94 * request list prior to both the Router option code and the Static
95 * Routes option code, if present. (RFC3442)
96 */
98 option_code_hash_lookup(&default_requested_options[3],
99 dhcp_universe.code_hash, &code, 0, MDL);
100
101 /* 5 */
102 code = DHO_DOMAIN_NAME;
103 option_code_hash_lookup(&default_requested_options[4],
104 dhcp_universe.code_hash, &code, 0, MDL);
105
106 /* 6 */
108 option_code_hash_lookup(&default_requested_options[5],
109 dhcp_universe.code_hash, &code, 0, MDL);
110
111 /* 7 */
112 code = DHO_HOST_NAME;
113 option_code_hash_lookup(&default_requested_options[6],
114 dhcp_universe.code_hash, &code, 0, MDL);
115
116 /* 8 */
117 code = D6O_NAME_SERVERS;
118 option_code_hash_lookup(&default_requested_options[7],
119 dhcpv6_universe.code_hash, &code, 0, MDL);
120
121 /* 9 */
122 code = D6O_DOMAIN_SEARCH;
123 option_code_hash_lookup(&default_requested_options[8],
124 dhcpv6_universe.code_hash, &code, 0, MDL);
125
126 /* 10 */
127 code = DHO_NIS_DOMAIN;
128 option_code_hash_lookup(&default_requested_options[9],
129 dhcp_universe.code_hash, &code, 0, MDL);
130
131 /* 11 */
132 code = DHO_NIS_SERVERS;
133 option_code_hash_lookup(&default_requested_options[10],
134 dhcp_universe.code_hash, &code, 0, MDL);
135
136 /* 12 */
137 code = DHO_NTP_SERVERS;
138 option_code_hash_lookup(&default_requested_options[11],
139 dhcp_universe.code_hash, &code, 0, MDL);
140
141 /* 13 */
142 code = DHO_INTERFACE_MTU;
143 option_code_hash_lookup(&default_requested_options[12],
144 dhcp_universe.code_hash, &code, 0, MDL);
145
146 /* 14 */
147 code = DHO_DOMAIN_SEARCH;
148 option_code_hash_lookup(&default_requested_options[13],
149 dhcp_universe.code_hash, &code, 0, MDL);
150
151 /* 15 */
152 code = DHO_ROUTERS;
153 option_code_hash_lookup(&default_requested_options[14],
154 dhcp_universe.code_hash, &code, 0, MDL);
155
156 for (code = 0 ; code < NUM_DEFAULT_REQUESTED_OPTS ; code++) {
157 if (default_requested_options[code] == NULL)
158 log_fatal("Unable to find option definition for "
159 "index %u during default parameter request "
160 "assembly.", code);
161 }
162
163#ifdef DHCP4o6
164 /* DHCPv4-over-DHCPv6 extra requested options in code order */
165 if (dhcpv4_over_dhcpv6 == 1) {
166 /* The DHCP4o6 server option should be requested */
168 option_code_hash_lookup(&default_requested_options[9],
169 dhcpv6_universe.code_hash,
170 &code, 0, MDL);
171 if (default_requested_options[9] == NULL) {
172 log_fatal("Unable to find option definition for "
173 "index %u during default parameter request "
174 "assembly.", code);
175 }
176 } else if (dhcpv4_over_dhcpv6 > 1) {
177 /* Called from run_stateless so the IRT should
178 be requested too */
180 option_code_hash_lookup(&default_requested_options[9],
181 dhcpv6_universe.code_hash,
182 &code, 0, MDL);
183 if (default_requested_options[9] == NULL) {
184 log_fatal("Unable to find option definition for "
185 "index %u during default parameter request "
186 "assembly.", code);
187 }
189 option_code_hash_lookup(&default_requested_options[10],
190 dhcpv6_universe.code_hash,
191 &code, 0, MDL);
192 if (default_requested_options[10] == NULL) {
193 log_fatal("Unable to find option definition for "
194 "index %u during default parameter request "
195 "assembly.", code);
196 }
197 }
198#endif
199
200 /* Initialize the top level client configuration. */
201 memset (&top_level_config, 0, sizeof top_level_config);
202
203 /* Set some defaults... */
204 top_level_config.timeout = 60;
205 top_level_config.select_interval = 0;
206 top_level_config.reboot_timeout = 10;
207 top_level_config.retry_interval = 300;
208 top_level_config.backoff_cutoff = 15;
209 top_level_config.initial_interval = 3;
210 top_level_config.lease_id_format = TOKEN_OCTAL;
211
212 /*
213 * RFC 2131, section 4.4.1 specifies that the client SHOULD wait a
214 * random time between 1 and 10 seconds. However, we choose to not
215 * implement this default. If user is inclined to really have that
216 * delay, he is welcome to do so, using 'initial-delay X;' parameter
217 * in config file.
218 */
219 top_level_config.initial_delay = 0;
220
221 top_level_config.bootp_policy = P_ACCEPT;
224 top_level_config.omapi_port = -1;
225 top_level_config.do_forward_update = 1;
226 /* Requested lease time, used by DHCPv6 (DHCPv4 uses the option cache)
227 */
228 top_level_config.requested_lease = 7200;
229 top_level_config.bootp_broadcast_always = 0;
230
231 group_allocate (&top_level_config.on_receipt, MDL);
232 if (!top_level_config.on_receipt)
233 log_fatal ("no memory for top-level on_receipt group");
234
235 group_allocate (&top_level_config.on_transmission, MDL);
236 if (!top_level_config.on_transmission)
237 log_fatal ("no memory for top-level on_transmission group");
238
240 (struct interface_info *)0,
242
243 if (status != ISC_R_SUCCESS) {
244 ;
245#ifdef LATER
246 /* Set up the standard name service updater routine. */
247 status = new_parse(&parse, -1, default_client_config,
248 sizeof(default_client_config) - 1,
249 "default client configuration", 0);
250 if (status != ISC_R_SUCCESS)
251 log_fatal ("can't begin default client config!");
252 }
253
254 if (parse != NULL) {
255 do {
256 token = peek_token(&val, NULL, cfile);
257 if (token == END_OF_FILE)
258 break;
260 } while (1);
262#endif
263 }
264
265 /* Set up state and config structures for clients that don't
266 have per-interface configuration statements. */
267 config = (struct client_config *)0;
268 for (ip = interfaces; ip; ip = ip -> next) {
269 if (!ip -> client) {
270 ip -> client = (struct client_state *)
271 dmalloc (sizeof (struct client_state), MDL);
272 if (!ip -> client)
273 log_fatal ("no memory for client state.");
274 memset (ip -> client, 0, sizeof *(ip -> client));
275 ip -> client -> interface = ip;
276 }
277
278 if (!ip -> client -> config) {
279 if (!config) {
280 config = (struct client_config *)
281 dmalloc (sizeof (struct client_config),
282 MDL);
283 if (!config)
284 log_fatal ("no memory for client config.");
285 memcpy (config, &top_level_config,
286 sizeof top_level_config);
287 }
288 ip -> client -> config = config;
289 }
290 }
291 return status;
292}
293
294int read_client_conf_file (const char *name, struct interface_info *ip,
295 struct client_config *client)
296{
297 int file;
298 struct parse *cfile;
299 const char *val;
300 int token;
301 isc_result_t status;
302
303 if ((file = open (name, O_RDONLY | O_CLOEXEC)) < 0)
304 return uerr2isc (errno);
305
306 cfile = NULL;
307 status = new_parse(&cfile, file, NULL, 0, path_dhclient_conf, 0);
308 if (status != ISC_R_SUCCESS || cfile == NULL)
309 return status;
310
311 do {
312 token = peek_token (&val, (unsigned *)0, cfile);
313 if (token == END_OF_FILE)
314 break;
315 parse_client_statement (cfile, ip, client);
316 } while (1);
317 skip_token(&val, (unsigned *)0, cfile);
318 status = (cfile -> warnings_occurred
320 : ISC_R_SUCCESS);
321 end_parse (&cfile);
322 return status;
323}
324
325
326/* lease-file :== client-lease-statements END_OF_FILE
327 client-lease-statements :== <nil>
328 | client-lease-statements LEASE client-lease-statement
329 * This routine looks through a lease file and only tries to parse
330 * the duid statements.
331 */
332
334{
335 int file;
336 isc_result_t status;
337 struct parse *cfile;
338 const char *val;
339 int token;
340
341 /* Open the lease file. If we can't open it, just return -
342 we can safely trust the server to remember our state. */
343 if ((file = open (path_dhclient_duid, O_RDONLY)) < 0)
344 return;
345
346 cfile = NULL;
347 status = new_parse(&cfile, file, NULL, 0, path_dhclient_duid, 0);
348 if (status != ISC_R_SUCCESS || cfile == NULL)
349 return;
350
351 while ((token = next_token(&val, NULL, cfile)) != END_OF_FILE) {
352 /*
353 * All we care about is DUIDs - if we get anything else
354 * just toss it and continue looking for DUIDs until we
355 * run out of file.
356 */
357 if (token == DEFAULT_DUID) {
358 parse_client_default_duid(cfile);
359 }
360 }
361
362 end_parse(&cfile);
363}
364
365/* lease-file :== client-lease-statements END_OF_FILE
366 client-lease-statements :== <nil>
367 | client-lease-statements LEASE client-lease-statement */
368
370{
371 int file;
372 isc_result_t status;
373 struct parse *cfile;
374 const char *val;
375 int token;
376
377 /* Open the lease file. If we can't open it, just return -
378 we can safely trust the server to remember our state. */
379 if ((file = open (path_dhclient_db, O_RDONLY | O_CLOEXEC)) < 0)
380 return;
381
382 cfile = NULL;
383 status = new_parse(&cfile, file, NULL, 0, path_dhclient_db, 0);
384 if (status != ISC_R_SUCCESS || cfile == NULL)
385 return;
386
387 do {
388 token = next_token (&val, (unsigned *)0, cfile);
389 if (token == END_OF_FILE)
390 break;
391
392 switch (token) {
393 case DEFAULT_DUID:
394 parse_client_default_duid(cfile);
395 break;
396
397 case LEASE:
399 break;
400
401 case LEASE6:
402 parse_client6_lease_statement(cfile);
403 break;
404
405 default:
406 log_error ("Corrupt lease file - possible data loss!");
407 skip_to_semi (cfile);
408 break;
409 }
410 } while (1);
411
412 end_parse (&cfile);
413}
414
415/* client-declaration :==
416 SEND option-decl |
417 DEFAULT option-decl |
418 SUPERSEDE option-decl |
419 PREPEND option-decl |
420 APPEND option-decl |
421 hardware-declaration |
422 ALSO REQUEST option-list |
423 ALSO REQUIRE option-list |
424 REQUEST option-list |
425 REQUIRE option-list |
426 TIMEOUT number |
427 RETRY number |
428 REBOOT number |
429 SELECT_TIMEOUT number |
430 SCRIPT string |
431 VENDOR_SPACE string |
432 interface-declaration |
433 LEASE client-lease-statement |
434 ALIAS client-lease-statement |
435 KEY key-definition |
436 BOOTP_BROADCAST_ALWAYS */
437
438void parse_client_statement (cfile, ip, config)
439 struct parse *cfile;
440 struct interface_info *ip;
441 struct client_config *config;
442{
443 int token;
444 const char *val;
445 struct option *option = NULL;
446 struct executable_statement *stmt;
447 int lose;
448 char *name;
449 enum policy policy;
450 int known;
451 int tmp, i;
452 isc_result_t status;
453 struct option ***append_list, **new_list, **cat_list;
454
455 switch (peek_token (&val, (unsigned *)0, cfile)) {
456 case INCLUDE:
457 skip_token(&val, (unsigned *)0, cfile);
458 token = next_token (&val, (unsigned *)0, cfile);
459 if (token != STRING) {
460 parse_warn (cfile, "filename string expected.");
461 skip_to_semi (cfile);
462 } else {
463 status = read_client_conf_file (val, ip, config);
464 if (status != ISC_R_SUCCESS)
465 parse_warn (cfile, "%s: bad parse.", val);
466 parse_semi (cfile);
467 }
468 return;
469
470 case KEY:
471 skip_token(&val, (unsigned *)0, cfile);
472 if (ip) {
473 /* This may seem arbitrary, but there's a reason for
474 doing it: the authentication key database is not
475 scoped. If we allow the user to declare a key other
476 than in the outer scope, the user is very likely to
477 believe that the key will only be used in that
478 scope. If the user only wants the key to be used on
479 one interface, because it's known that the other
480 interface may be connected to an insecure net and
481 the secret key is considered sensitive, we don't
482 want to lull them into believing they've gotten
483 their way. This is a bit contrived, but people
484 tend not to be entirely rational about security. */
485 parse_warn (cfile, "key definition not allowed here.");
486 skip_to_semi (cfile);
487 break;
488 }
489 parse_key (cfile);
490 return;
491
492 case TOKEN_ALSO:
493 /* consume ALSO */
494 skip_token(&val, NULL, cfile);
495
496 /* consume type of ALSO list. */
497 token = next_token(&val, NULL, cfile);
498
499 if (token == REQUEST) {
500 append_list = &config->requested_options;
501 } else if (token == REQUIRE) {
502 append_list = &config->required_options;
503 } else {
504 parse_warn(cfile, "expected REQUEST or REQUIRE list");
505 skip_to_semi(cfile);
506 return;
507 }
508
509 /* If there is no list, cut the concat short. */
510 if (*append_list == NULL) {
511 parse_option_list(cfile, append_list);
512 return;
513 }
514
515 /* Count the length of the existing list. */
516 for (i = 0 ; (*append_list)[i] != NULL ; i++)
517 ; /* This space intentionally left blank. */
518
519 /* If there's no codes on the list, cut the concat short. */
520 if (i == 0) {
521 parse_option_list(cfile, append_list);
522 return;
523 }
524
525 tmp = parse_option_list(cfile, &new_list);
526
527 if (tmp == 0 || new_list == NULL)
528 return;
529
530 /* Allocate 'i + tmp' buckets plus a terminator. */
531 cat_list = dmalloc(sizeof(struct option *) * (i + tmp + 1),
532 MDL);
533
534 if (cat_list == NULL) {
535 log_error("Unable to allocate memory for new "
536 "request list.");
537 skip_to_semi(cfile);
538 return;
539 }
540
541 for (i = 0 ; (*append_list)[i] != NULL ; i++)
542 option_reference(&cat_list[i], (*append_list)[i], MDL);
543
544 tmp = i;
545
546 for (i = 0 ; new_list[i] != 0 ; i++)
547 option_reference(&cat_list[tmp++], new_list[i], MDL);
548
549 cat_list[tmp] = 0;
550
551 /* XXX: We cannot free the old list, because it may have been
552 * XXX: assigned from an outer configuration scope (or may be
553 * XXX: the static default setting).
554 */
555 *append_list = cat_list;
556
557 return;
558
559 /* REQUIRE can either start a policy statement or a
560 comma-separated list of names of required options. */
561 case REQUIRE:
562 skip_token(&val, (unsigned *)0, cfile);
563 token = peek_token (&val, (unsigned *)0, cfile);
564 if (token == AUTHENTICATION) {
566 goto do_policy;
567 }
568 parse_option_list (cfile, &config -> required_options);
569 return;
570
571 case IGNORE:
572 skip_token(&val, (unsigned *)0, cfile);
574 goto do_policy;
575
576 case ACCEPT:
577 skip_token(&val, (unsigned *)0, cfile);
579 goto do_policy;
580
581 case PREFER:
582 skip_token(&val, (unsigned *)0, cfile);
584 goto do_policy;
585
586 case DONT:
587 skip_token(&val, (unsigned *)0, cfile);
588 policy = P_DONT;
589 goto do_policy;
590
591 do_policy:
592 token = next_token (&val, (unsigned *)0, cfile);
593 if (token == AUTHENTICATION) {
594 if (policy != P_PREFER &&
595 policy != P_REQUIRE &&
596 policy != P_DONT) {
597 parse_warn (cfile,
598 "invalid authentication policy.");
599 skip_to_semi (cfile);
600 return;
601 }
602 config -> auth_policy = policy;
603 } else if (token != TOKEN_BOOTP) {
604 if (policy != P_PREFER &&
605 policy != P_IGNORE &&
606 policy != P_ACCEPT) {
607 parse_warn (cfile, "invalid bootp policy.");
608 skip_to_semi (cfile);
609 return;
610 }
611 config -> bootp_policy = policy;
612 } else {
613 parse_warn (cfile, "expecting a policy type.");
614 skip_to_semi (cfile);
615 return;
616 }
617 break;
618
619 case OPTION:
620 skip_token(&val, (unsigned *)0, cfile);
621 token = peek_token (&val, (unsigned *)0, cfile);
622 if (token == SPACE) {
623 if (ip) {
624 parse_warn (cfile,
625 "option space definitions %s",
626 " may not be scoped.");
627 skip_to_semi (cfile);
628 break;
629 }
631 return;
632 }
633
634 known = 0;
635 status = parse_option_name(cfile, 1, &known, &option);
636 if (status != ISC_R_SUCCESS || option == NULL)
637 return;
638
639 token = next_token (&val, (unsigned *)0, cfile);
640 if (token != CODE) {
641 parse_warn (cfile, "expecting \"code\" keyword.");
642 skip_to_semi (cfile);
644 return;
645 }
646 if (ip) {
647 parse_warn (cfile,
648 "option definitions may only appear in %s",
649 "the outermost scope.");
650 skip_to_semi (cfile);
652 return;
653 }
654
655 /*
656 * If the option was known, remove it from the code and name
657 * hash tables before redefining it.
658 */
659 if (known) {
660 option_name_hash_delete(option->universe->name_hash,
661 option->name, 0, MDL);
662 option_code_hash_delete(option->universe->code_hash,
663 &option->code, 0, MDL);
664 }
665
668 return;
669
670 case MEDIA:
671 skip_token(&val, (unsigned *)0, cfile);
672 parse_string_list (cfile, &config -> media, 1);
673 return;
674
675 case HARDWARE:
676 skip_token(&val, (unsigned *)0, cfile);
677 if (ip) {
678 parse_hardware_param (cfile, &ip -> hw_address);
679 } else {
680 parse_warn (cfile, "hardware address parameter %s",
681 "not allowed here.");
682 skip_to_semi (cfile);
683 }
684 return;
685
686 case ANYCAST_MAC:
687 skip_token(&val, NULL, cfile);
688 if (ip != NULL) {
689 parse_hardware_param(cfile, &ip->anycast_mac_addr);
690 } else {
691 parse_warn(cfile, "anycast mac address parameter "
692 "not allowed here.");
693 skip_to_semi (cfile);
694 }
695 return;
696
697 case REQUEST:
698 skip_token(&val, (unsigned *)0, cfile);
699 if (config -> requested_options == default_requested_options)
700 config -> requested_options = NULL;
701 parse_option_list (cfile, &config -> requested_options);
702 return;
703
704 case TIMEOUT:
705 skip_token(&val, (unsigned *)0, cfile);
706 parse_lease_time (cfile, &config -> timeout);
707 return;
708
709 case RETRY:
710 skip_token(&val, (unsigned *)0, cfile);
711 parse_lease_time (cfile, &config -> retry_interval);
712 return;
713
714 case SELECT_TIMEOUT:
715 skip_token(&val, (unsigned *)0, cfile);
716 parse_lease_time (cfile, &config -> select_interval);
717 return;
718
719 case OMAPI:
720 skip_token(&val, (unsigned *)0, cfile);
721 token = next_token (&val, (unsigned *)0, cfile);
722 if (token != PORT) {
723 parse_warn (cfile,
724 "unexpected omapi subtype: %s", val);
725 skip_to_semi (cfile);
726 return;
727 }
728 token = next_token (&val, (unsigned *)0, cfile);
729 if (token != NUMBER) {
730 parse_warn (cfile, "invalid port number: `%s'", val);
731 skip_to_semi (cfile);
732 return;
733 }
734 tmp = atoi (val);
735 if (tmp < 0 || tmp > 65535)
736 parse_warn (cfile, "invalid omapi port %d.", tmp);
737 else if (config != &top_level_config)
738 parse_warn (cfile,
739 "omapi port only works at top level.");
740 else
741 config -> omapi_port = tmp;
742 parse_semi (cfile);
743 return;
744
746 skip_token(&val, (unsigned *)0, cfile);
747 token = next_token (&val, (unsigned *)0, cfile);
748 if (!strcasecmp (val, "on") ||
749 !strcasecmp (val, "true"))
750 config -> do_forward_update = 1;
751 else if (!strcasecmp (val, "off") ||
752 !strcasecmp (val, "false"))
753 config -> do_forward_update = 0;
754 else {
755 parse_warn (cfile, "expecting boolean value.");
756 skip_to_semi (cfile);
757 return;
758 }
759 parse_semi (cfile);
760 return;
761
762 case REBOOT:
763 skip_token(&val, (unsigned *)0, cfile);
764 parse_lease_time (cfile, &config -> reboot_timeout);
765 return;
766
767 case BACKOFF_CUTOFF:
768 skip_token(&val, (unsigned *)0, cfile);
769 parse_lease_time (cfile, &config -> backoff_cutoff);
770 return;
771
772 case INITIAL_INTERVAL:
773 skip_token(&val, (unsigned *)0, cfile);
774 parse_lease_time (cfile, &config -> initial_interval);
775 return;
776
777 case INITIAL_DELAY:
778 skip_token(&val, (unsigned *)0, cfile);
779 parse_lease_time (cfile, &config -> initial_delay);
780 return;
781
782 case SCRIPT:
783 skip_token(&val, (unsigned *)0, cfile);
784 parse_string (cfile, &config -> script_name, (unsigned *)0);
785 return;
786
787 case VENDOR:
788 skip_token(&val, (unsigned *)0, cfile);
789 token = next_token (&val, (unsigned *)0, cfile);
790 if (token != OPTION) {
791 parse_warn (cfile, "expecting 'vendor option space'");
792 skip_to_semi (cfile);
793 return;
794 }
795 token = next_token (&val, (unsigned *)0, cfile);
796 if (token != SPACE) {
797 parse_warn (cfile, "expecting 'vendor option space'");
798 skip_to_semi (cfile);
799 return;
800 }
801 token = next_token (&val, (unsigned *)0, cfile);
802 if (!is_identifier (token)) {
803 parse_warn (cfile, "expecting an identifier.");
804 skip_to_semi (cfile);
805 return;
806 }
807 config -> vendor_space_name = dmalloc (strlen (val) + 1, MDL);
808 if (!config -> vendor_space_name)
809 log_fatal ("no memory for vendor option space name.");
810 strcpy (config -> vendor_space_name, val);
811 for (i = 0; i < universe_count; i++)
812 if (!strcmp (universes [i] -> name,
813 config -> vendor_space_name))
814 break;
815 if (i == universe_count) {
816 log_error ("vendor option space %s not found.",
817 config -> vendor_space_name);
818 }
819 parse_semi (cfile);
820 return;
821
822 case INTERFACE:
823 skip_token(&val, (unsigned *)0, cfile);
824 if (ip)
825 parse_warn (cfile, "nested interface declaration.");
826 parse_interface_declaration (cfile, config, (char *)0);
827 return;
828
829 case PSEUDO:
830 skip_token(&val, (unsigned *)0, cfile);
831 token = next_token (&val, (unsigned *)0, cfile);
832 name = dmalloc (strlen (val) + 1, MDL);
833 if (!name)
834 log_fatal ("no memory for pseudo interface name");
835 strcpy (name, val);
836 parse_interface_declaration (cfile, config, name);
837 return;
838
839 case LEASE:
840 skip_token(&val, (unsigned *)0, cfile);
842 return;
843
844 case ALIAS:
845 skip_token(&val, (unsigned *)0, cfile);
847 return;
848
849 case REJECT:
850 skip_token(&val, (unsigned *)0, cfile);
851 parse_reject_statement (cfile, config);
852 return;
853
854 case LEASE_ID_FORMAT:
855 skip_token(&val, (unsigned *)0, cfile);
856 parse_lease_id_format(cfile);
857 break;
858
860 token = next_token(&val, (unsigned*)0, cfile);
861 config -> bootp_broadcast_always = 1;
862 parse_semi (cfile);
863 return;
864
865
866 default:
867 lose = 0;
868 stmt = (struct executable_statement *)0;
869 if (!parse_executable_statement (&stmt,
870 cfile, &lose, context_any)) {
871 if (!lose) {
872 parse_warn (cfile, "expecting a statement.");
873 skip_to_semi (cfile);
874 }
875 } else {
876 struct executable_statement **eptr, *sptr;
877 if (stmt &&
878 (stmt -> op == send_option_statement ||
879 (stmt -> op == on_statement &&
880 (stmt -> data.on.evtypes & ON_TRANSMISSION)))) {
881 eptr = &config -> on_transmission -> statements;
882 if (stmt -> op == on_statement) {
883 sptr = (struct executable_statement *)0;
885 (&sptr,
886 stmt -> data.on.statements, MDL);
888 MDL);
890 sptr,
891 MDL);
893 MDL);
894 }
895 } else
896 eptr = &config -> on_receipt -> statements;
897
898 if (stmt) {
899 for (; *eptr; eptr = &(*eptr) -> next)
900 ;
902 stmt, MDL);
903 }
904 return;
905 }
906 break;
907 }
908 parse_semi (cfile);
909}
910
911/* option-list :== option_name |
912 option_list COMMA option_name */
913
914int
915parse_option_list(struct parse *cfile, struct option ***list)
916{
917 int ix;
918 int token;
919 const char *val;
920 pair p = (pair)0, q = (pair)0, r;
921 struct option *option = NULL;
922 isc_result_t status;
923
924 ix = 0;
925 do {
926 token = peek_token (&val, (unsigned *)0, cfile);
927 if (token == SEMI) {
928 token = next_token (&val, (unsigned *)0, cfile);
929 break;
930 }
931 if (!is_identifier (token)) {
932 parse_warn (cfile, "%s: expected option name.", val);
933 skip_token(&val, (unsigned *)0, cfile);
934 skip_to_semi (cfile);
935 return 0;
936 }
937 status = parse_option_name(cfile, 0, NULL, &option);
938 if (status != ISC_R_SUCCESS || option == NULL) {
939 parse_warn (cfile, "%s: expected option name.", val);
940 return 0;
941 }
942 r = new_pair (MDL);
943 if (!r)
944 log_fatal ("can't allocate pair for option code.");
945 /* XXX: we should probably carry a reference across this */
946 r->car = (caddr_t)option;
948 r -> cdr = (pair)0;
949 if (p)
950 q -> cdr = r;
951 else
952 p = r;
953 q = r;
954 ++ix;
955 token = next_token (&val, (unsigned *)0, cfile);
956 } while (token == COMMA);
957 if (token != SEMI) {
958 parse_warn (cfile, "expecting semicolon.");
959 skip_to_semi (cfile);
960 return 0;
961 }
962 /* XXX we can't free the list here, because we may have copied
963 XXX it from an outer config state. */
964 *list = NULL;
965 if (ix) {
966 *list = dmalloc ((ix + 1) * sizeof(struct option *), MDL);
967 if (!*list)
968 log_error ("no memory for option list.");
969 else {
970 ix = 0;
971 for (q = p; q; q = q -> cdr)
972 option_reference(&(*list)[ix++],
973 (struct option *)q->car, MDL);
974 (*list)[ix] = NULL;
975 }
976 while (p) {
977 q = p -> cdr;
978 free_pair (p, MDL);
979 p = q;
980 }
981 }
982
983 return ix;
984}
985
986/* interface-declaration :==
987 INTERFACE string LBRACE client-declarations RBRACE */
988
989void parse_interface_declaration (cfile, outer_config, name)
990 struct parse *cfile;
991 struct client_config *outer_config;
992 char *name;
993{
994 int token;
995 const char *val;
996 struct client_state *client, **cp;
997 struct interface_info *ip = (struct interface_info *)0;
998
999 token = next_token (&val, (unsigned *)0, cfile);
1000 if (token != STRING) {
1001 parse_warn (cfile, "expecting interface name (in quotes).");
1002 skip_to_semi (cfile);
1003 return;
1004 }
1005
1006 if (!interface_or_dummy (&ip, val))
1007 log_fatal ("Can't allocate interface %s.", val);
1008
1009 /* If we were given a name, this is a pseudo-interface. */
1010 if (name) {
1012 client -> name = name;
1013 client -> interface = ip;
1014 for (cp = &ip -> client; *cp; cp = &((*cp) -> next))
1015 ;
1016 *cp = client;
1017 } else {
1018 if (!ip -> client) {
1019 make_client_state (&ip -> client);
1020 ip -> client -> interface = ip;
1021 }
1022 client = ip -> client;
1023 }
1024
1025 if (!client -> config)
1026 make_client_config (client, outer_config);
1027
1028 ip -> flags &= ~INTERFACE_AUTOMATIC;
1030
1031 token = next_token (&val, (unsigned *)0, cfile);
1032 if (token != LBRACE) {
1033 parse_warn (cfile, "expecting left brace.");
1034 skip_to_semi (cfile);
1035 return;
1036 }
1037
1038 do {
1039 token = peek_token (&val, (unsigned *)0, cfile);
1040 if (token == END_OF_FILE) {
1041 parse_warn (cfile,
1042 "unterminated interface declaration.");
1043 return;
1044 }
1045 if (token == RBRACE)
1046 break;
1047 parse_client_statement (cfile, ip, client -> config);
1048 } while (1);
1049 skip_token(&val, (unsigned *)0, cfile);
1050}
1051
1052int interface_or_dummy (struct interface_info **pi, const char *name)
1053{
1054 struct interface_info *i;
1055 struct interface_info *ip = (struct interface_info *)0;
1056 isc_result_t status;
1057
1058 /* Find the interface (if any) that matches the name. */
1059 for (i = interfaces; i; i = i -> next) {
1060 if (!strcmp (i -> name, name)) {
1061 interface_reference (&ip, i, MDL);
1062 break;
1063 }
1064 }
1065
1066 /* If it's not a real interface, see if it's on the dummy list. */
1067 if (!ip) {
1068 for (ip = dummy_interfaces; ip; ip = ip -> next) {
1069 if (!strcmp (ip -> name, name)) {
1070 interface_reference (&ip, i, MDL);
1071 break;
1072 }
1073 }
1074 }
1075
1076 /* If we didn't find an interface, make a dummy interface as
1077 a placeholder. */
1078 if (!ip) {
1079 if ((status = interface_allocate (&ip, MDL)) != ISC_R_SUCCESS)
1080 log_fatal ("Can't record interface %s: %s",
1081 name, isc_result_totext (status));
1082
1083 if (strlen(name) >= sizeof(ip->name)) {
1084 interface_dereference(&ip, MDL);
1085 return 0;
1086 }
1087 strcpy(ip->name, name);
1088
1089 if (dummy_interfaces) {
1090 interface_reference (&ip -> next,
1092 interface_dereference (&dummy_interfaces, MDL);
1093 }
1094 interface_reference (&dummy_interfaces, ip, MDL);
1095 }
1096 if (pi)
1097 status = interface_reference (pi, ip, MDL);
1098 else
1099 status = ISC_R_FAILURE;
1100 interface_dereference (&ip, MDL);
1101 if (status != ISC_R_SUCCESS)
1102 return 0;
1103 return 1;
1104}
1105
1107 struct client_state **state;
1108{
1109 *state = ((struct client_state *)dmalloc (sizeof **state, MDL));
1110 if (!*state)
1111 log_fatal ("no memory for client state\n");
1112 memset (*state, 0, sizeof **state);
1113}
1114
1116 struct client_state *client;
1117 struct client_config *config;
1118{
1119 client -> config = (((struct client_config *)
1120 dmalloc (sizeof (struct client_config), MDL)));
1121 if (!client -> config)
1122 log_fatal ("no memory for client config\n");
1123 memcpy (client -> config, config, sizeof *config);
1124 if (!clone_group (&client -> config -> on_receipt,
1125 config -> on_receipt, MDL) ||
1126 !clone_group (&client -> config -> on_transmission,
1127 config -> on_transmission, MDL))
1128 log_fatal ("no memory for client state groups.");
1129}
1130
1131/* client-lease-statement :==
1132 LBRACE client-lease-declarations RBRACE
1133
1134 client-lease-declarations :==
1135 <nil> |
1136 client-lease-declaration |
1137 client-lease-declarations client-lease-declaration */
1138
1139
1140void parse_client_lease_statement (cfile, is_static)
1141 struct parse *cfile;
1142 int is_static;
1143{
1144 struct client_lease *lease;
1145 struct interface_info *ip = (struct interface_info *)0;
1146 int token;
1147 const char *val;
1148 struct client_state *client = (struct client_state *)0;
1149
1150 token = next_token (&val, (unsigned *)0, cfile);
1151 if (token != LBRACE) {
1152 parse_warn (cfile, "expecting left brace.");
1153 skip_to_semi (cfile);
1154 return;
1155 }
1156
1157 lease = ((struct client_lease *)
1158 dmalloc (sizeof (struct client_lease), MDL));
1159 if (!lease)
1160 log_fatal ("no memory for lease.\n");
1161 memset (lease, 0, sizeof *lease);
1164 log_fatal ("no memory for lease options.\n");
1165
1166 do {
1167 token = peek_token (&val, (unsigned *)0, cfile);
1168 if (token == END_OF_FILE) {
1169 parse_warn (cfile, "unterminated lease declaration.");
1170 return;
1171 }
1172 if (token == RBRACE)
1173 break;
1174 parse_client_lease_declaration (cfile, lease, &ip, &client);
1175 } while (1);
1176 skip_token(&val, (unsigned *)0, cfile);
1177
1178 /* If the lease declaration didn't include an interface
1179 declaration that we recognized, it's of no use to us. */
1180 if (!ip) {
1182 return;
1183 }
1184
1185 /* Make sure there's a client state structure... */
1186 if (!ip -> client) {
1187 make_client_state (&ip -> client);
1188 ip -> client -> interface = ip;
1189 }
1190 if (!client)
1191 client = ip -> client;
1192
1193 /* If this is an alias lease, it doesn't need to be sorted in. */
1194 if (is_static == 2) {
1195 ip -> client -> alias = lease;
1196 return;
1197 }
1198
1199 /* The new lease may supersede a lease that's not the
1200 active lease but is still on the lease list, so scan the
1201 lease list looking for a lease with the same address, and
1202 if we find it, toss it. We only allow supercession if
1203 the leases originated from the same source. In other words,
1204 either both are from the config file or both are from the lease
1205 file. This keeps us from discarding fallback leases */
1206 discard_duplicate (&client->leases, lease);
1207
1208 /* If this is a preloaded lease, just put it on the list of recorded
1209 leases - don't make it the active lease. */
1210 if (is_static) {
1211 lease -> next = client -> leases;
1212 client -> leases = lease;
1213 return;
1214 }
1215
1216 /* The last lease in the lease file on a particular interface is
1217 the active lease for that interface. Of course, we don't know
1218 what the last lease in the file is until we've parsed the whole
1219 file, so at this point, we assume that the lease we just parsed
1220 is the active lease for its interface. If there's already
1221 an active lease for the interface, and this lease is for the same
1222 ip address, then we just toss the old active lease and replace
1223 it with this one. If this lease is for a different address,
1224 then if the old active lease has expired, we dump it; if not,
1225 we put it on the list of leases for this interface which are
1226 still valid but no longer active. */
1227 if (client -> active) {
1228 if (client -> active -> expiry < cur_time)
1229 destroy_client_lease (client -> active);
1230 else if (client -> active -> address.len ==
1231 lease -> address.len &&
1232 !memcmp (client -> active -> address.iabuf,
1233 lease -> address.iabuf,
1234 lease -> address.len))
1235 destroy_client_lease (client -> active);
1236 else {
1237 client -> active -> next = client -> leases;
1238 client -> leases = client -> active;
1239 }
1240 }
1241 client -> active = lease;
1242
1243 /* phew. */
1244}
1245
1246/* client-lease-declaration :==
1247 BOOTP |
1248 INTERFACE string |
1249 FIXED_ADDR ip_address |
1250 FILENAME string |
1251 SERVER_NAME string |
1252 OPTION option-decl |
1253 RENEW time-decl |
1254 REBIND time-decl |
1255 EXPIRE time-decl |
1256 KEY id */
1257
1258void parse_client_lease_declaration (cfile, lease, ipp, clientp)
1259 struct parse *cfile;
1260 struct client_lease *lease;
1261 struct interface_info **ipp;
1262 struct client_state **clientp;
1263{
1264 int token;
1265 const char *val;
1266 struct interface_info *ip;
1267 struct option_cache *oc;
1268 struct client_state *client = (struct client_state *)0;
1269
1270 switch (next_token (&val, (unsigned *)0, cfile)) {
1271 case KEY:
1272 token = next_token (&val, (unsigned *)0, cfile);
1273 if (token != STRING && !is_identifier (token)) {
1274 parse_warn (cfile, "expecting key name.");
1275 skip_to_semi (cfile);
1276 break;
1277 }
1278 if (omapi_auth_key_lookup_name (&lease -> key, val) !=
1280 parse_warn (cfile, "unknown key %s", val);
1281 parse_semi (cfile);
1282 break;
1283 case TOKEN_BOOTP:
1284 lease -> is_bootp = 1;
1285 break;
1286
1287 case INTERFACE:
1288 token = next_token (&val, (unsigned *)0, cfile);
1289 if (token != STRING) {
1290 parse_warn (cfile,
1291 "expecting interface name (in quotes).");
1292 skip_to_semi (cfile);
1293 break;
1294 }
1295 if (!interface_or_dummy (ipp, val))
1296 log_fatal ("Can't allocate interface %s.", val);
1297 break;
1298
1299 case NAME:
1300 token = next_token (&val, (unsigned *)0, cfile);
1301 ip = *ipp;
1302 if (!ip) {
1303 parse_warn (cfile, "state name precedes interface.");
1304 break;
1305 }
1306 for (client = ip -> client; client; client = client -> next)
1307 if (client -> name && !strcmp (client -> name, val))
1308 break;
1309 if (!client)
1310 parse_warn (cfile,
1311 "lease specified for unknown pseudo.");
1312 *clientp = client;
1313 break;
1314
1315 case FIXED_ADDR:
1316 if (!parse_ip_addr (cfile, &lease -> address))
1317 return;
1318 break;
1319
1320 case MEDIUM:
1321 parse_string_list (cfile, &lease -> medium, 0);
1322 return;
1323
1324 case FILENAME:
1325 parse_string (cfile, &lease -> filename, (unsigned *)0);
1326 return;
1327
1328 case SERVER_NAME:
1329 parse_string (cfile, &lease -> server_name, (unsigned *)0);
1330 return;
1331
1332 case RENEW:
1333 lease -> renewal = parse_date (cfile);
1334 return;
1335
1336 case REBIND:
1337 lease -> rebind = parse_date (cfile);
1338 return;
1339
1340 case EXPIRE:
1341 lease -> expiry = parse_date (cfile);
1342 return;
1343
1344 case OPTION:
1345 oc = (struct option_cache *)0;
1346 if (parse_option_decl (&oc, cfile)) {
1347 save_option(oc->option->universe, lease->options, oc);
1349 }
1350 return;
1351
1352 default:
1353 parse_warn (cfile, "expecting lease declaration.");
1354 skip_to_semi (cfile);
1355 break;
1356 }
1357 token = next_token (&val, (unsigned *)0, cfile);
1358 if (token != SEMI) {
1359 parse_warn (cfile, "expecting semicolon.");
1360 skip_to_semi (cfile);
1361 }
1362}
1363
1364/* Parse a default-duid ""; statement.
1365 */
1366static void
1367parse_client_default_duid(struct parse *cfile)
1368{
1369 struct data_string new_duid;
1370 u_int8_t buf[128];
1371 unsigned len;
1372
1373 len = parse_X(cfile, buf, sizeof(buf));
1374 if (len <= 2) {
1375 parse_warn(cfile, "Invalid DUID contents.");
1376 skip_to_semi(cfile);
1377 return;
1378 }
1379
1380 memset(&new_duid, 0, sizeof(new_duid));
1381 if (!buffer_allocate(&new_duid.buffer, len, MDL)) {
1382 parse_warn(cfile, "Out of memory parsing default DUID.");
1383 skip_to_semi(cfile);
1384 return;
1385 }
1386 new_duid.data = new_duid.buffer->data;
1387 new_duid.len = len;
1388
1389 memcpy(new_duid.buffer->data, buf, len);
1390
1391 /* Rotate the last entry into place. */
1392 if (default_duid.buffer != NULL)
1394 data_string_copy(&default_duid, &new_duid, MDL);
1395 data_string_forget(&new_duid, MDL);
1396
1397 parse_semi(cfile);
1398}
1399
1400/* Parse a lease6 {} construct. The v6 client is a little different
1401 * than the v4 client today, in that it only retains one lease, the
1402 * active lease, and discards any less recent information. It may
1403 * be useful in the future to cache additional information, but it
1404 * is not worth the effort for the moment.
1405 */
1406static void
1407parse_client6_lease_statement(struct parse *cfile)
1408{
1409#if !defined(DHCPv6)
1410 parse_warn(cfile, "No DHCPv6 support.");
1411 skip_to_semi(cfile);
1412#else /* defined(DHCPv6) */
1413 struct option_cache *oc = NULL;
1414 struct dhc6_lease *lease;
1415 struct dhc6_ia **ia;
1416 struct client_state *client = NULL;
1417 struct interface_info *iface = NULL;
1418 struct data_string ds;
1419 const char *val;
1420 unsigned len;
1421 int token, has_ia, no_semi, has_name;
1422
1423 token = next_token(NULL, NULL, cfile);
1424 if (token != LBRACE) {
1425 parse_warn(cfile, "Expecting open curly brace.");
1426 skip_to_semi(cfile);
1427 return;
1428 }
1429
1430 lease = dmalloc(sizeof(*lease), MDL);
1431 if (lease == NULL) {
1432 parse_warn(cfile, "Unable to allocate lease state.");
1433 skip_to_rbrace(cfile, 1);
1434 return;
1435 }
1436
1437 option_state_allocate(&lease->options, MDL);
1438 if (lease->options == NULL) {
1439 parse_warn(cfile, "Unable to allocate option cache.");
1440 skip_to_rbrace(cfile, 1);
1441 dfree(lease, MDL);
1442 return;
1443 }
1444
1445 has_ia = 0;
1446 has_name = 0;
1447 ia = &lease->bindings;
1448 token = next_token(&val, NULL, cfile);
1449 while (token != RBRACE) {
1450 no_semi = 0;
1451
1452 switch(token) {
1453 case IA_NA:
1454 *ia = parse_client6_ia_na_statement(cfile);
1455 if (*ia != NULL) {
1456 ia = &(*ia)->next;
1457 has_ia = 1;
1458 }
1459
1460 no_semi = 1;
1461
1462 break;
1463
1464 case IA_TA:
1465 *ia = parse_client6_ia_ta_statement(cfile);
1466 if (*ia != NULL) {
1467 ia = &(*ia)->next;
1468 has_ia = 1;
1469 }
1470
1471 no_semi = 1;
1472
1473 break;
1474
1475 case IA_PD:
1476 *ia = parse_client6_ia_pd_statement(cfile);
1477 if (*ia != NULL) {
1478 ia = &(*ia)->next;
1479 has_ia = 1;
1480 }
1481
1482 no_semi = 1;
1483
1484 break;
1485
1486 case INTERFACE:
1487 if (iface != NULL) {
1488 parse_warn(cfile, "Multiple interface names?");
1489 skip_to_semi(cfile);
1490 no_semi = 1;
1491 break;
1492 }
1493
1494 token = next_token(&val, &len, cfile);
1495 if (token != STRING) {
1496 strerror:
1497 parse_warn(cfile, "Expecting a string.");
1498 skip_to_semi(cfile);
1499 no_semi = 1;
1500 break;
1501 }
1502
1503 for (iface = interfaces ; iface != NULL ;
1504 iface = iface->next) {
1505 if (strcmp(iface->name, val) == 0)
1506 break;
1507 }
1508
1509 if (iface == NULL) {
1510 parse_warn(cfile, "Unknown interface.");
1511 break;
1512 }
1513
1514 break;
1515
1516 case NAME:
1517 has_name = 1;
1518
1519 if (client != NULL) {
1520 parse_warn(cfile, "Multiple state names?");
1521 skip_to_semi(cfile);
1522 no_semi = 1;
1523 break;
1524 }
1525
1526 if (iface == NULL) {
1527 parse_warn(cfile, "Client name without "
1528 "interface.");
1529 skip_to_semi(cfile);
1530 no_semi = 1;
1531 break;
1532 }
1533
1534 token = next_token(&val, &len, cfile);
1535 if (token != STRING)
1536 goto strerror;
1537
1538 for (client = iface->client ; client != NULL ;
1539 client = client->next) {
1540 if ((client->name != NULL) &&
1541 (strcmp(client->name, val) == 0))
1542 break;
1543 }
1544
1545 if (client == NULL) {
1546 parse_warn(cfile, "Unknown client state %s.",
1547 val);
1548 break;
1549 }
1550
1551 break;
1552
1553 case OPTION:
1554 if (parse_option_decl(&oc, cfile)) {
1556 lease->options, oc);
1558 }
1559 no_semi = 1;
1560 break;
1561
1562 case TOKEN_RELEASED:
1563 case TOKEN_ABANDONED:
1564 lease->released = ISC_TRUE;
1565 break;
1566
1567 default:
1568 parse_warn(cfile, "Unexpected token, %s.", val);
1569 no_semi = 1;
1570 skip_to_semi(cfile);
1571 break;
1572 }
1573
1574 if (!no_semi)
1575 parse_semi(cfile);
1576
1577 token = next_token(&val, NULL, cfile);
1578
1579 if (token == END_OF_FILE) {
1580 parse_warn(cfile, "Unexpected end of file.");
1581 break;
1582 }
1583 }
1584
1585 if (!has_ia) {
1586 log_debug("Lease with no IA's discarded from lease db.");
1588 return;
1589 }
1590
1591 if (iface == NULL)
1592 parse_warn(cfile, "Lease has no interface designation.");
1593 else if (!has_name && (client == NULL)) {
1594 for (client = iface->client ; client != NULL ;
1595 client = client->next) {
1596 if (client->name == NULL)
1597 break;
1598 }
1599 }
1600
1601 if (client == NULL) {
1602 parse_warn(cfile, "No matching client state.");
1604 return;
1605 }
1606
1607 /* Fetch Preference option from option cache. */
1608 memset(&ds, 0, sizeof(ds));
1610 if ((oc != NULL) &&
1611 evaluate_option_cache(&ds, NULL, NULL, NULL, lease->options,
1612 NULL, &global_scope, oc, MDL)) {
1613 if (ds.len != 1) {
1614 log_error("Invalid length of DHCPv6 Preference option "
1615 "(%d != 1)", ds.len);
1616 data_string_forget(&ds, MDL);
1618 return;
1619 } else
1620 lease->pref = ds.data[0];
1621
1622 data_string_forget(&ds, MDL);
1623 }
1624
1625 /* Fetch server-id option from option cache. */
1627 if ((oc == NULL) ||
1628 !evaluate_option_cache(&lease->server_id, NULL, NULL, NULL,
1629 lease->options, NULL, &global_scope, oc,
1630 MDL) ||
1631 (lease->server_id.len == 0)) {
1632 /* This should be impossible... */
1633 log_error("Invalid SERVERID option cache.");
1635 return;
1636 }
1637
1638 if (client->active_lease != NULL)
1640
1641 client->active_lease = lease;
1642#endif /* defined(DHCPv6) */
1643}
1644
1645/* Parse an ia_na object from the client lease.
1646 */
1647#ifdef DHCPv6
1648static struct dhc6_ia *
1649parse_client6_ia_na_statement(struct parse *cfile)
1650{
1651 struct option_cache *oc = NULL;
1652 struct dhc6_ia *ia;
1653 struct dhc6_addr **addr;
1654 const char *val;
1655 int token, no_semi, len;
1656 u_int8_t buf[5];
1657
1658 ia = dmalloc(sizeof(*ia), MDL);
1659 if (ia == NULL) {
1660 parse_warn(cfile, "Out of memory allocating IA_NA state.");
1661 skip_to_semi(cfile);
1662 return NULL;
1663 }
1664 ia->ia_type = D6O_IA_NA;
1665
1666 /* Get IAID. */
1667 len = parse_X(cfile, buf, 5);
1668 if (len == 4) {
1669 memcpy(ia->iaid, buf, 4);
1670 } else {
1671 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1672 skip_to_semi(cfile);
1673 dfree(ia, MDL);
1674 return NULL;
1675 }
1676
1677 token = next_token(NULL, NULL, cfile);
1678 if (token != LBRACE) {
1679 parse_warn(cfile, "Expecting open curly brace.");
1680 skip_to_semi(cfile);
1681 dfree(ia, MDL);
1682 return NULL;
1683 }
1684
1686 if (ia->options == NULL) {
1687 parse_warn(cfile, "Unable to allocate option state.");
1688 skip_to_rbrace(cfile, 1);
1689 dfree(ia, MDL);
1690 return NULL;
1691 }
1692
1693 addr = &ia->addrs;
1694 token = next_token(&val, NULL, cfile);
1695 while (token != RBRACE) {
1696 no_semi = 0;
1697
1698 switch (token) {
1699 case STARTS:
1700 token = next_token(&val, NULL, cfile);
1701 if (token == NUMBER) {
1702 ia->starts = atoi(val);
1703 } else {
1704 parse_warn(cfile, "Expecting a number.");
1705 skip_to_semi(cfile);
1706 no_semi = 1;
1707 }
1708 break;
1709
1710 case RENEW:
1711 token = next_token(&val, NULL, cfile);
1712 if (token == NUMBER) {
1713 ia->renew = atoi(val);
1714 } else {
1715 parse_warn(cfile, "Expecting a number.");
1716 skip_to_semi(cfile);
1717 no_semi = 1;
1718 }
1719 break;
1720
1721 case REBIND:
1722 token = next_token(&val, NULL, cfile);
1723 if (token == NUMBER) {
1724 ia->rebind = atoi(val);
1725 } else {
1726 parse_warn(cfile, "Expecting a number.");
1727 skip_to_semi(cfile);
1728 no_semi = 1;
1729 }
1730 break;
1731
1732 case IAADDR:
1733 *addr = parse_client6_iaaddr_statement(cfile);
1734
1735 if (*addr != NULL)
1736 addr = &(*addr)->next;
1737
1738 no_semi = 1;
1739
1740 break;
1741
1742 case OPTION:
1743 if (parse_option_decl(&oc, cfile)) {
1745 ia->options, oc);
1747 }
1748 no_semi = 1;
1749 break;
1750
1751 default:
1752 parse_warn(cfile, "Unexpected token.");
1753 no_semi = 1;
1754 skip_to_semi(cfile);
1755 break;
1756 }
1757
1758 if (!no_semi)
1759 parse_semi(cfile);
1760
1761 token = next_token(&val, NULL, cfile);
1762
1763 if (token == END_OF_FILE) {
1764 parse_warn(cfile, "Unexpected end of file.");
1765 break;
1766 }
1767 }
1768
1769 return ia;
1770}
1771#endif /* DHCPv6 */
1772
1773/* Parse an ia_ta object from the client lease.
1774 */
1775#ifdef DHCPv6
1776static struct dhc6_ia *
1777parse_client6_ia_ta_statement(struct parse *cfile)
1778{
1779 struct option_cache *oc = NULL;
1780 struct dhc6_ia *ia;
1781 struct dhc6_addr **addr;
1782 const char *val;
1783 int token, no_semi, len;
1784 u_int8_t buf[5];
1785
1786 ia = dmalloc(sizeof(*ia), MDL);
1787 if (ia == NULL) {
1788 parse_warn(cfile, "Out of memory allocating IA_TA state.");
1789 skip_to_semi(cfile);
1790 return NULL;
1791 }
1792 ia->ia_type = D6O_IA_TA;
1793
1794 /* Get IAID. */
1795 len = parse_X(cfile, buf, 5);
1796 if (len == 4) {
1797 memcpy(ia->iaid, buf, 4);
1798 } else {
1799 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1800 skip_to_semi(cfile);
1801 dfree(ia, MDL);
1802 return NULL;
1803 }
1804
1805 token = next_token(NULL, NULL, cfile);
1806 if (token != LBRACE) {
1807 parse_warn(cfile, "Expecting open curly brace.");
1808 skip_to_semi(cfile);
1809 dfree(ia, MDL);
1810 return NULL;
1811 }
1812
1814 if (ia->options == NULL) {
1815 parse_warn(cfile, "Unable to allocate option state.");
1816 skip_to_rbrace(cfile, 1);
1817 dfree(ia, MDL);
1818 return NULL;
1819 }
1820
1821 addr = &ia->addrs;
1822 token = next_token(&val, NULL, cfile);
1823 while (token != RBRACE) {
1824 no_semi = 0;
1825
1826 switch (token) {
1827 case STARTS:
1828 token = next_token(&val, NULL, cfile);
1829 if (token == NUMBER) {
1830 ia->starts = atoi(val);
1831 } else {
1832 parse_warn(cfile, "Expecting a number.");
1833 skip_to_semi(cfile);
1834 no_semi = 1;
1835 }
1836 break;
1837
1838 /* No RENEW or REBIND */
1839
1840 case IAADDR:
1841 *addr = parse_client6_iaaddr_statement(cfile);
1842
1843 if (*addr != NULL)
1844 addr = &(*addr)->next;
1845
1846 no_semi = 1;
1847
1848 break;
1849
1850 case OPTION:
1851 if (parse_option_decl(&oc, cfile)) {
1853 ia->options, oc);
1855 }
1856 no_semi = 1;
1857 break;
1858
1859 default:
1860 parse_warn(cfile, "Unexpected token.");
1861 no_semi = 1;
1862 skip_to_semi(cfile);
1863 break;
1864 }
1865
1866 if (!no_semi)
1867 parse_semi(cfile);
1868
1869 token = next_token(&val, NULL, cfile);
1870
1871 if (token == END_OF_FILE) {
1872 parse_warn(cfile, "Unexpected end of file.");
1873 break;
1874 }
1875 }
1876
1877 return ia;
1878}
1879#endif /* DHCPv6 */
1880
1881/* Parse an ia_pd object from the client lease.
1882 */
1883#ifdef DHCPv6
1884static struct dhc6_ia *
1885parse_client6_ia_pd_statement(struct parse *cfile)
1886{
1887 struct option_cache *oc = NULL;
1888 struct dhc6_ia *ia;
1889 struct dhc6_addr **pref;
1890 const char *val;
1891 int token, no_semi, len;
1892 u_int8_t buf[5];
1893
1894 ia = dmalloc(sizeof(*ia), MDL);
1895 if (ia == NULL) {
1896 parse_warn(cfile, "Out of memory allocating IA_PD state.");
1897 skip_to_semi(cfile);
1898 return NULL;
1899 }
1900 ia->ia_type = D6O_IA_PD;
1901
1902 /* Get IAID. */
1903 len = parse_X(cfile, buf, 5);
1904 if (len == 4) {
1905 memcpy(ia->iaid, buf, 4);
1906 } else {
1907 parse_warn(cfile, "Expecting IAID of length 4, got %d.", len);
1908 skip_to_semi(cfile);
1909 dfree(ia, MDL);
1910 return NULL;
1911 }
1912
1913 token = next_token(NULL, NULL, cfile);
1914 if (token != LBRACE) {
1915 parse_warn(cfile, "Expecting open curly brace.");
1916 skip_to_semi(cfile);
1917 dfree(ia, MDL);
1918 return NULL;
1919 }
1920
1922 if (ia->options == NULL) {
1923 parse_warn(cfile, "Unable to allocate option state.");
1924 skip_to_rbrace(cfile, 1);
1925 dfree(ia, MDL);
1926 return NULL;
1927 }
1928
1929 pref = &ia->addrs;
1930 token = next_token(&val, NULL, cfile);
1931 while (token != RBRACE) {
1932 no_semi = 0;
1933
1934 switch (token) {
1935 case STARTS:
1936 token = next_token(&val, NULL, cfile);
1937 if (token == NUMBER) {
1938 ia->starts = atoi(val);
1939 } else {
1940 parse_warn(cfile, "Expecting a number.");
1941 skip_to_semi(cfile);
1942 no_semi = 1;
1943 }
1944 break;
1945
1946 case RENEW:
1947 token = next_token(&val, NULL, cfile);
1948 if (token == NUMBER) {
1949 ia->renew = atoi(val);
1950 } else {
1951 parse_warn(cfile, "Expecting a number.");
1952 skip_to_semi(cfile);
1953 no_semi = 1;
1954 }
1955 break;
1956
1957 case REBIND:
1958 token = next_token(&val, NULL, cfile);
1959 if (token == NUMBER) {
1960 ia->rebind = atoi(val);
1961 } else {
1962 parse_warn(cfile, "Expecting a number.");
1963 skip_to_semi(cfile);
1964 no_semi = 1;
1965 }
1966 break;
1967
1968 case IAPREFIX:
1969 *pref = parse_client6_iaprefix_statement(cfile);
1970
1971 if (*pref != NULL)
1972 pref = &(*pref)->next;
1973
1974 no_semi = 1;
1975
1976 break;
1977
1978 case OPTION:
1979 if (parse_option_decl(&oc, cfile)) {
1981 ia->options, oc);
1983 }
1984 no_semi = 1;
1985 break;
1986
1987 default:
1988 parse_warn(cfile, "Unexpected token.");
1989 no_semi = 1;
1990 skip_to_semi(cfile);
1991 break;
1992 }
1993
1994 if (!no_semi)
1995 parse_semi(cfile);
1996
1997 token = next_token(&val, NULL, cfile);
1998
1999 if (token == END_OF_FILE) {
2000 parse_warn(cfile, "Unexpected end of file.");
2001 break;
2002 }
2003 }
2004
2005 return ia;
2006}
2007#endif /* DHCPv6 */
2008
2009/* Parse an iaaddr {} structure. */
2010#ifdef DHCPv6
2011static struct dhc6_addr *
2012parse_client6_iaaddr_statement(struct parse *cfile)
2013{
2014 struct option_cache *oc = NULL;
2015 struct dhc6_addr *addr;
2016 const char *val;
2017 int token, no_semi;
2018
2019 addr = dmalloc(sizeof(*addr), MDL);
2020 if (addr == NULL) {
2021 parse_warn(cfile, "Unable to allocate IAADDR state.");
2022 skip_to_semi(cfile);
2023 return NULL;
2024 }
2025
2026 /* Get IP address. */
2027 if (!parse_ip6_addr(cfile, &addr->address)) {
2028 skip_to_semi(cfile);
2029 dfree(addr, MDL);
2030 return NULL;
2031 }
2032
2033 token = next_token(NULL, NULL, cfile);
2034 if (token != LBRACE) {
2035 parse_warn(cfile, "Expecting open curly bracket.");
2036 skip_to_semi(cfile);
2037 dfree(addr, MDL);
2038 return NULL;
2039 }
2040
2042 if (addr->options == NULL) {
2043 parse_warn(cfile, "Unable to allocate option state.");
2044 skip_to_semi(cfile);
2045 dfree(addr, MDL);
2046 return NULL;
2047 }
2048
2049 token = next_token(&val, NULL, cfile);
2050 while (token != RBRACE) {
2051 no_semi = 0;
2052
2053 switch (token) {
2054 case STARTS:
2055 token = next_token(&val, NULL, cfile);
2056 if (token == NUMBER) {
2057 addr->starts = atoi(val);
2058 } else {
2059 parse_warn(cfile, "Expecting a number.");
2060 skip_to_semi(cfile);
2061 no_semi = 1;
2062 }
2063 break;
2064
2065 case PREFERRED_LIFE:
2066 token = next_token(&val, NULL, cfile);
2067 if (token == NUMBER) {
2068 addr->preferred_life = atoi(val);
2069 } else {
2070 parse_warn(cfile, "Expecting a number.");
2071 skip_to_semi(cfile);
2072 no_semi = 1;
2073 }
2074 break;
2075
2076 case MAX_LIFE:
2077 token = next_token(&val, NULL, cfile);
2078 if (token == NUMBER) {
2079 addr->max_life = atoi(val);
2080 } else {
2081 parse_warn(cfile, "Expecting a number.");
2082 skip_to_semi(cfile);
2083 no_semi = 1;
2084 }
2085 break;
2086
2087 case OPTION:
2088 if (parse_option_decl(&oc, cfile)) {
2090 addr->options, oc);
2092 }
2093 no_semi = 1;
2094 break;
2095
2096 default:
2097 parse_warn(cfile, "Unexpected token.");
2098 skip_to_rbrace(cfile, 1);
2099 no_semi = 1;
2100 break;
2101 }
2102
2103 if (!no_semi)
2104 parse_semi(cfile);
2105
2106 token = next_token(&val, NULL, cfile);
2107 if (token == END_OF_FILE) {
2108 parse_warn(cfile, "Unexpected end of file.");
2109 break;
2110 }
2111 }
2112
2113 return addr;
2114}
2115#endif /* DHCPv6 */
2116
2117/* Parse an iaprefix {} structure. */
2118#ifdef DHCPv6
2119static struct dhc6_addr *
2120parse_client6_iaprefix_statement(struct parse *cfile)
2121{
2122 struct option_cache *oc = NULL;
2123 struct dhc6_addr *pref;
2124 const char *val;
2125 int token, no_semi;
2126
2127 pref = dmalloc(sizeof(*pref), MDL);
2128 if (pref == NULL) {
2129 parse_warn(cfile, "Unable to allocate IAPREFIX state.");
2130 skip_to_semi(cfile);
2131 return NULL;
2132 }
2133
2134 /* Get IP prefix. */
2135 if (!parse_ip6_prefix(cfile, &pref->address, &pref->plen)) {
2136 skip_to_semi(cfile);
2137 dfree(pref, MDL);
2138 return NULL;
2139 }
2140
2141 token = next_token(NULL, NULL, cfile);
2142 if (token != LBRACE) {
2143 parse_warn(cfile, "Expecting open curly bracket.");
2144 skip_to_semi(cfile);
2145 dfree(pref, MDL);
2146 return NULL;
2147 }
2148
2150 if (pref->options == NULL) {
2151 parse_warn(cfile, "Unable to allocate option state.");
2152 skip_to_semi(cfile);
2153 dfree(pref, MDL);
2154 return NULL;
2155 }
2156
2157 token = next_token(&val, NULL, cfile);
2158 while (token != RBRACE) {
2159 no_semi = 0;
2160
2161 switch (token) {
2162 case STARTS:
2163 token = next_token(&val, NULL, cfile);
2164 if (token == NUMBER) {
2165 pref->starts = atoi(val);
2166 } else {
2167 parse_warn(cfile, "Expecting a number.");
2168 skip_to_semi(cfile);
2169 no_semi = 1;
2170 }
2171 break;
2172
2173 case PREFERRED_LIFE:
2174 token = next_token(&val, NULL, cfile);
2175 if (token == NUMBER) {
2176 pref->preferred_life = atoi(val);
2177 } else {
2178 parse_warn(cfile, "Expecting a number.");
2179 skip_to_semi(cfile);
2180 no_semi = 1;
2181 }
2182 break;
2183
2184 case MAX_LIFE:
2185 token = next_token(&val, NULL, cfile);
2186 if (token == NUMBER) {
2187 pref->max_life = atoi(val);
2188 } else {
2189 parse_warn(cfile, "Expecting a number.");
2190 skip_to_semi(cfile);
2191 no_semi = 1;
2192 }
2193 break;
2194
2195 case OPTION:
2196 if (parse_option_decl(&oc, cfile)) {
2198 pref->options, oc);
2200 }
2201 no_semi = 1;
2202 break;
2203
2204 default:
2205 parse_warn(cfile, "Unexpected token.");
2206 skip_to_rbrace(cfile, 1);
2207 no_semi = 1;
2208 break;
2209 }
2210
2211 if (!no_semi)
2212 parse_semi(cfile);
2213
2214 token = next_token(&val, NULL, cfile);
2215 if (token == END_OF_FILE) {
2216 parse_warn(cfile, "Unexpected end of file.");
2217 break;
2218 }
2219 }
2220
2221 return pref;
2222}
2223#endif /* DHCPv6 */
2224
2225void parse_string_list (cfile, lp, multiple)
2226 struct parse *cfile;
2227 struct string_list **lp;
2228 int multiple;
2229{
2230 int token;
2231 const char *val;
2232 struct string_list *cur, *tmp;
2233
2234 /* Find the last medium in the media list. */
2235 if (*lp) {
2236 for (cur = *lp; cur -> next; cur = cur -> next)
2237 ;
2238 } else {
2239 cur = (struct string_list *)0;
2240 }
2241
2242 do {
2243 token = next_token (&val, (unsigned *)0, cfile);
2244 if (token != STRING) {
2245 parse_warn (cfile, "Expecting media options.");
2246 skip_to_semi (cfile);
2247 return;
2248 }
2249
2250 tmp = ((struct string_list *)
2251 dmalloc (strlen (val) + sizeof (struct string_list),
2252 MDL));
2253 if (!tmp)
2254 log_fatal ("no memory for string list entry.");
2255
2256 strcpy (tmp -> string, val);
2257 tmp -> next = (struct string_list *)0;
2258
2259 /* Store this medium at the end of the media list. */
2260 if (cur)
2261 cur -> next = tmp;
2262 else
2263 *lp = tmp;
2264 cur = tmp;
2265
2266 token = next_token (&val, (unsigned *)0, cfile);
2267 } while (multiple && token == COMMA);
2268
2269 if (token != SEMI) {
2270 parse_warn (cfile, "expecting semicolon.");
2271 skip_to_semi (cfile);
2272 }
2273}
2274
2275void parse_reject_statement (cfile, config)
2276 struct parse *cfile;
2277 struct client_config *config;
2278{
2279 int token;
2280 const char *val;
2281 struct iaddrmatch match;
2282 struct iaddrmatchlist *list;
2283 int i;
2284
2285 do {
2286 if (!parse_ip_addr_with_subnet (cfile, &match)) {
2287 /* no warn: parser will have reported what's wrong */
2288 skip_to_semi (cfile);
2289 return;
2290 }
2291
2292 /* check mask is not all zeros (because that would
2293 * reject EVERY address). This check could be
2294 * simplified if we assume that the mask *always*
2295 * represents a prefix .. but perhaps it might be
2296 * useful to have a mask which is not a proper prefix
2297 * (perhaps for ipv6?). The following is almost as
2298 * efficient as inspection of match.mask.iabuf[0] when
2299 * it IS a true prefix, and is more general when it is
2300 * not.
2301 */
2302
2303 for (i=0 ; i < match.mask.len ; i++) {
2304 if (match.mask.iabuf[i]) {
2305 break;
2306 }
2307 }
2308
2309 if (i == match.mask.len) {
2310 /* oops we found all zeros */
2311 parse_warn(cfile, "zero-length prefix is not permitted "
2312 "for reject statement");
2313 skip_to_semi(cfile);
2314 return;
2315 }
2316
2317 list = dmalloc(sizeof(struct iaddrmatchlist), MDL);
2318 if (!list)
2319 log_fatal ("no memory for reject list!");
2320
2321 list->match = match;
2322 list->next = config->reject_list;
2323 config->reject_list = list;
2324
2325 token = next_token (&val, (unsigned *)0, cfile);
2326 } while (token == COMMA);
2327
2328 if (token != SEMI) {
2329 parse_warn (cfile, "expecting semicolon.");
2330 skip_to_semi (cfile);
2331 }
2332}
2333
2334/* allow-deny-keyword :== BOOTP
2335 | BOOTING
2336 | DYNAMIC_BOOTP
2337 | UNKNOWN_CLIENTS */
2338
2339int parse_allow_deny (oc, cfile, flag)
2340 struct option_cache **oc;
2341 struct parse *cfile;
2342 int flag;
2343{
2344 parse_warn (cfile, "allow/deny/ignore not permitted here.");
2345 skip_to_semi (cfile);
2346 return 0;
2347}
2348
2349
2350
2365void parse_lease_id_format (struct parse *cfile)
2366{
2367 enum dhcp_token token;
2368 const char *val;
2369
2370 token = next_token(&val, NULL, cfile);
2371 switch(token) {
2372 case TOKEN_OCTAL:
2373 top_level_config.lease_id_format = TOKEN_OCTAL;
2374 break;
2375 case TOKEN_HEX:
2376 top_level_config.lease_id_format = TOKEN_HEX;
2377 break;
2378 default:
2379 parse_warn(cfile, "lease-id-format is invalid: "
2380 " it must be octal or hex.");
2381 skip_to_semi(cfile);
2382 return;
2383 }
2384
2385 log_debug("lease_id_format is: %s",
2386 (top_level_config.lease_id_format == TOKEN_OCTAL
2387 ? "octal" : "hex"));
2388
2389}
struct option * default_requested_options[NUM_DEFAULT_REQUESTED_OPTS+2+1]
Definition clparse.c:36
void read_client_leases()
Definition clparse.c:369
void parse_interface_declaration(struct parse *cfile, struct client_config *outer_config, char *name)
Definition clparse.c:989
isc_result_t read_client_conf()
Definition clparse.c:58
void make_client_config(struct client_state *client, struct client_config *config)
Definition clparse.c:1115
int parse_allow_deny(struct option_cache **oc, struct parse *cfile, int flag)
Definition clparse.c:2339
void make_client_state(struct client_state **state)
Definition clparse.c:1106
void parse_client_statement(struct parse *cfile, struct interface_info *ip, struct client_config *config)
Definition clparse.c:438
void discard_duplicate(struct client_lease **lease_list, struct client_lease *lease)
Definition dhclient.c:3065
void parse_client_lease_statement(struct parse *cfile, int is_static)
Definition clparse.c:1140
#define NUM_DEFAULT_REQUESTED_OPTS
Definition clparse.c:34
int parse_option_list(struct parse *cfile, struct option ***list)
Definition clparse.c:915
void parse_string_list(struct parse *cfile, struct string_list **lp, int multiple)
Definition clparse.c:2225
void read_client_duid()
Definition clparse.c:333
struct client_config top_level_config
Definition clparse.c:32
int read_client_conf_file(const char *name, struct interface_info *ip, struct client_config *client)
Definition clparse.c:294
void parse_reject_statement(struct parse *cfile, struct client_config *config)
Definition clparse.c:2275
int interface_or_dummy(struct interface_info **pi, const char *name)
Definition clparse.c:1052
void parse_client_lease_declaration(struct parse *cfile, struct client_lease *lease, struct interface_info **ipp, struct client_state **clientp)
Definition clparse.c:1258
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
Definition alloc.c:679
int group_allocate(struct group **ptr, const char *file, int line)
Definition alloc.c:145
void free_pair(pair foo, const char *file, int line)
Definition alloc.c:400
void data_string_forget(struct data_string *data, const char *file, int line)
Definition alloc.c:1339
int option_state_allocate(struct option_state **ptr, const char *file, int line)
Definition alloc.c:846
int executable_statement_reference(struct executable_statement **ptr, struct executable_statement *bp, const char *file, int line)
Definition alloc.c:972
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
Definition alloc.c:1323
pair new_pair(char *file, int line) const
Definition alloc.c:379
enum dhcp_token peek_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition conflex.c:443
enum dhcp_token next_token(const char **rval, unsigned *rlen, struct parse *cfile)
Definition conflex.c:369
isc_result_t end_parse(struct parse **cfile)
Definition conflex.c:103
isc_result_t new_parse(struct parse **cfile, int file, char *inbuf, unsigned buflen, const char *name, int eolp)
Definition conflex.c:41
void save_option(struct universe *universe, struct option_state *options, struct option_cache *oc)
Definition options.c:2818
int option_cache_dereference(struct option_cache **ptr, const char *file, int line)
Definition options.c:2953
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
Definition options.c:2503
int parse_string(struct parse *cfile, char **sptr, unsigned *lptr)
Definition parse.c:156
void skip_to_semi(struct parse *cfile)
Definition parse.c:81
int parse_X(struct parse *cfile, u_int8_t *buf, unsigned max)
Definition parse.c:5593
int parse_semi(struct parse *cfile)
Definition parse.c:139
int parse_key(struct parse *cfile)
Definition parse.c:2996
int parse_option_code_definition(struct parse *cfile, struct option *option)
Definition parse.c:1572
int parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen)
Definition parse.c:479
int parse_ip6_addr(struct parse *cfile, struct iaddr *addr)
Definition parse.c:405
int parse_option_decl(struct option_cache **oc, struct parse *cfile)
Definition parse.c:5290
TIME parse_date(struct parse *cfile)
Definition parse.c:1188
void skip_to_rbrace(struct parse *cfile, int brace_count)
Definition parse.c:98
int parse_warn(struct parse *cfile, const char *fmt,...)
Definition parse.c:5643
int parse_ip_addr_with_subnet(struct parse *cfile, struct iaddrmatch *match)
Definition parse.c:522
void parse_hardware_param(struct parse *cfile, struct hardware *hardware)
Definition parse.c:615
void parse_option_space_decl(struct parse *cfile)
Definition parse.c:1349
int parse_ip_addr(struct parse *cfile, struct iaddr *addr)
Definition parse.c:336
int parse_executable_statement(struct executable_statement **result, struct parse *cfile, int *lose, enum expression_context case_context)
Definition parse.c:2133
isc_result_t parse_option_name(struct parse *cfile, int allocate, int *known, struct option **opt)
Definition parse.c:1208
void parse_lease_time(struct parse *cfile, TIME *timep)
Definition parse.c:690
#define ISC_TRUE
Definition data.h:153
int interfaces_requested
Definition dhclient.c:71
int bootp_broadcast_always
Definition dhclient.c:126
const char * path_dhclient_duid
Definition dhclient.c:62
const char * path_dhclient_db
Definition dhclient.c:58
void destroy_client_lease(struct client_lease *lease)
Definition dhclient.c:4181
const char * path_dhclient_conf
Definition dhclient.c:57
struct data_string default_duid
Definition dhclient.c:78
char * path_dhclient_script
Definition dhclient.c:61
#define D6O_INFORMATION_REFRESH_TIME
Definition dhcp6.h:61
#define D6O_DHCP4_O_DHCP6_SERVER
Definition dhcp6.h:117
#define D6O_SERVERID
Definition dhcp6.h:31
#define D6O_IA_PD
Definition dhcp6.h:54
#define D6O_DOMAIN_SEARCH
Definition dhcp6.h:53
#define D6O_NAME_SERVERS
Definition dhcp6.h:52
#define D6O_IA_TA
Definition dhcp6.h:33
#define D6O_IA_NA
Definition dhcp6.h:32
#define D6O_PREFERENCE
Definition dhcp6.h:36
#define DHO_NIS_SERVERS
Definition dhcp.h:130
#define DHO_NTP_SERVERS
Definition dhcp.h:131
#define DHO_NIS_DOMAIN
Definition dhcp.h:129
#define DHO_HOST_NAME
Definition dhcp.h:101
#define DHO_BROADCAST_ADDRESS
Definition dhcp.h:117
#define DHO_DOMAIN_SEARCH
Definition dhcp.h:162
#define DHO_TIME_OFFSET
Definition dhcp.h:91
#define DHO_INTERFACE_MTU
Definition dhcp.h:115
#define DHO_CLASSLESS_STATIC_ROUTES
Definition dhcp.h:163
#define DHO_DOMAIN_NAME
Definition dhcp.h:104
#define DHO_DOMAIN_NAME_SERVERS
Definition dhcp.h:95
#define DHO_ROUTERS
Definition dhcp.h:92
#define DHO_SUBNET_MASK
Definition dhcp.h:90
int omapi_port
Definition dhcpd.c:110
#define skip_token(a, b, c)
Definition dhcpd.h:2192
void dhc6_lease_destroy(struct dhc6_lease **src, const char *file, int line)
#define cur_time
Definition dhcpd.h:2126
struct universe dhcp_universe
#define INTERFACE_AUTOMATIC
Definition dhcpd.h:1425
policy
Definition dhcpd.h:1228
@ P_DONT
Definition dhcpd.h:1228
@ P_ACCEPT
Definition dhcpd.h:1228
@ P_PREFER
Definition dhcpd.h:1228
@ P_IGNORE
Definition dhcpd.h:1228
@ P_REQUIRE
Definition dhcpd.h:1228
const char * file
Definition dhcpd.h:3802
struct interface_info * interfaces
Definition discover.c:42
int dhcpv4_over_dhcpv6
Definition discover.c:51
struct interface_info * dummy_interfaces
Definition discover.c:43
int executable_statement_dereference(struct executable_statement **ptr, const char *file, int line)
Definition execute.c:630
dhcp_token
Definition dhctoken.h:34
@ REBOOT
Definition dhctoken.h:121
@ INITIAL_INTERVAL
Definition dhctoken.h:124
@ LBRACE
Definition dhctoken.h:40
@ DEFAULT_DUID
Definition dhctoken.h:346
@ PSEUDO
Definition dhctoken.h:163
@ TOKEN_OCTAL
Definition dhctoken.h:378
@ RENEW
Definition dhctoken.h:110
@ REQUIRE
Definition dhctoken.h:104
@ NUMBER
Definition dhctoken.h:67
@ FIXED_ADDR
Definition dhctoken.h:63
@ KEY
Definition dhctoken.h:256
@ IAADDR
Definition dhctoken.h:341
@ ALIAS
Definition dhctoken.h:120
@ IA_TA
Definition dhctoken.h:339
@ LEASE
Definition dhctoken.h:75
@ IA_PD
Definition dhctoken.h:340
@ INCLUDE
Definition dhctoken.h:268
@ MEDIA
Definition dhctoken.h:118
@ EXPIRE
Definition dhctoken.h:112
@ REBIND
Definition dhctoken.h:111
@ MEDIUM
Definition dhctoken.h:119
@ TOKEN_ABANDONED
Definition dhctoken.h:122
@ INTERFACE
Definition dhctoken.h:109
@ ACCEPT
Definition dhctoken.h:186
@ PREFER
Definition dhctoken.h:187
@ CODE
Definition dhctoken.h:189
@ PREFERRED_LIFE
Definition dhctoken.h:344
@ SCRIPT
Definition dhctoken.h:108
@ NAME
Definition dhctoken.h:69
@ SEMI
Definition dhctoken.h:35
@ LEASE6
Definition dhctoken.h:343
@ BOOTP_BROADCAST_ALWAYS
Definition dhctoken.h:380
@ RETRY
Definition dhctoken.h:106
@ VENDOR
Definition dhctoken.h:291
@ SELECT_TIMEOUT
Definition dhctoken.h:107
@ END_OF_FILE
Definition dhctoken.h:307
@ PORT
Definition dhctoken.h:173
@ SERVER_NAME
Definition dhctoken.h:89
@ LEASE_ID_FORMAT
Definition dhctoken.h:376
@ IGNORE
Definition dhctoken.h:185
@ RBRACE
Definition dhctoken.h:41
@ REJECT
Definition dhctoken.h:133
@ OPTION
Definition dhctoken.h:64
@ AUTHENTICATION
Definition dhctoken.h:184
@ MAX_LIFE
Definition dhctoken.h:345
@ TIMEOUT
Definition dhctoken.h:105
@ ANYCAST_MAC
Definition dhctoken.h:359
@ OMAPI
Definition dhctoken.h:279
@ DO_FORWARD_UPDATE
Definition dhctoken.h:314
@ DONT
Definition dhctoken.h:188
@ IAPREFIX
Definition dhctoken.h:342
@ REQUEST
Definition dhctoken.h:103
@ SPACE
Definition dhctoken.h:198
@ INITIAL_DELAY
Definition dhctoken.h:364
@ TOKEN_RELEASED
Definition dhctoken.h:273
@ TOKEN_BOOTP
Definition dhctoken.h:277
@ FILENAME
Definition dhctoken.h:62
@ STARTS
Definition dhctoken.h:71
@ TOKEN_HEX
Definition dhctoken.h:377
@ TOKEN_ALSO
Definition dhctoken.h:353
@ BACKOFF_CUTOFF
Definition dhctoken.h:123
@ IA_NA
Definition dhctoken.h:338
@ STRING
Definition dhctoken.h:66
@ COMMA
Definition dhctoken.h:38
@ HARDWARE
Definition dhctoken.h:61
#define is_identifier(x)
Definition dhctoken.h:385
#define ISC_R_SUCCESS
@ known
Definition keama.h:264
@ on_statement
Definition keama.h:175
@ send_option_statement
Definition keama.h:173
int clone_group(struct group **gp, struct group *group, const char *file, int line)
Definition memory.c:130
#define MDL
Definition omapip.h:567
isc_result_t omapi_auth_key_lookup_name(omapi_auth_key_t **, const char *)
Definition auth.c:121
void * dmalloc(size_t, const char *, int)
Definition alloc.c:57
void dfree(void *, const char *, int)
Definition alloc.c:145
isc_result_t uerr2isc(int)
Definition toisc.c:37
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_BADPARSE
Definition result.h:54
#define ON_TRANSMISSION
Definition statement.h:75
struct option ** required_options
Definition dhcpd.h:1243
struct group * on_transmission
Definition dhcpd.h:1241
struct iaddrmatchlist * reject_list
Definition dhcpd.h:1280
struct option ** requested_options
Definition dhcpd.h:1244
struct group * on_receipt
Definition dhcpd.h:1236
unsigned int is_static
Definition dhcpd.h:1152
struct option_state * options
Definition dhcpd.h:1155
char * name
Definition dhcpd.h:1301
struct dhc6_lease * active_lease
Definition dhcpd.h:1334
struct client_config * config
Definition dhcpd.h:1304
struct client_lease * leases
Definition dhcpd.h:1316
enum dhcp_state state
Definition dhcpd.h:1308
struct client_state * next
Definition dhcpd.h:1299
struct string_list * medium
Definition dhcpd.h:1324
unsigned len
Definition tree.h:79
u_int8_t plen
Definition dhcpd.h:1163
u_int32_t preferred_life
Definition dhcpd.h:1172
u_int32_t max_life
Definition dhcpd.h:1173
TIME starts
Definition dhcpd.h:1171
struct dhc6_addr * next
Definition dhcpd.h:1161
struct iaddr address
Definition dhcpd.h:1162
struct option_state * options
Definition dhcpd.h:1175
struct option_state * options
Definition dhcpd.h:1188
struct dhc6_ia * next
Definition dhcpd.h:1179
u_int32_t renew
Definition dhcpd.h:1184
struct dhc6_addr * addrs
Definition dhcpd.h:1186
unsigned char iaid[4]
Definition dhcpd.h:1180
u_int16_t ia_type
Definition dhcpd.h:1181
TIME starts
Definition dhcpd.h:1183
u_int32_t rebind
Definition dhcpd.h:1185
enum executable_statement::statement_op op
union executable_statement::@336221350347175166011011356261373334214214051201 data
struct executable_statement * next
Definition statement.h:31
struct executable_statement * statements
Definition statement.h:69
struct executable_statement::@336221350347175166011011356261373334214214051201::@240325212232200272321314266066265221125200273242 on
unsigned char iabuf[16]
Definition inet.h:33
unsigned len
Definition inet.h:32
struct iaddr mask
Definition inet.h:55
struct iaddrmatch match
Definition inet.h:62
struct iaddrmatchlist * next
Definition inet.h:61
char name[IFNAMSIZ]
Definition dhcpd.h:1408
struct interface_info * next
Definition dhcpd.h:1383
struct client_state * client
Definition dhcpd.h:1432
Definition ip.h:47
Definition dhcpd.h:560
struct option * option
Definition dhcpd.h:389
Definition tree.h:345
unsigned code
Definition tree.h:349
enum option_status status
Definition keama.h:297
struct universe * universe
Definition tree.h:348
const char * name
Definition tree.h:346
Definition dhcpd.h:288
int warnings_occurred
Definition dhcpd.h:326
enum dhcp_token token
Definition dhcpd.h:320
struct string_list * next
Definition dhcpd.h:348
option_name_hash_t * name_hash
Definition tree.h:336
option_code_hash_t * code_hash
Definition tree.h:337
int universe_count
Definition tables.c:976
int option_reference(struct option **dest, struct option *src, const char *file, int line)
Definition tables.c:992
int option_dereference(struct option **dest, const char *file, int line)
Definition tables.c:1014
struct universe dhcpv6_universe
Definition tables.c:351
struct universe ** universes
Definition tables.c:975
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
Definition tree.c:2699
struct binding_scope * global_scope
Definition tree.c:38
struct _pair * pair
@ context_any
Definition tree.h:84