xref: /netbsd-src/external/mpl/dhcp/dist/client/clparse.c (revision f407d9293b6650aa8c33d6a995f797bb6aaefd90)
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