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