1 /* confpars.c
2 
3    Parser for dhcpd config file... */
4 
5 /*
6  * Copyright (c) 2004-2019 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  *   Internet Systems Consortium, Inc.
22  *   950 Charter Street
23  *   Redwood City, CA 94063
24  *   <info@isc.org>
25  *   https://www.isc.org/
26  *
27  */
28 
29 /*! \file server/confpars.c */
30 
31 #include "dhcpd.h"
32 
33 static unsigned char global_host_once = 1;
34 
35 static int parse_binding_value(struct parse *cfile,
36 				struct binding_value *value);
37 
38 static void parse_authoring_byte_order (struct parse *cfile);
39 static void parse_lease_id_format (struct parse *cfile);
40 #ifdef DHCPv6
41 static int parse_iaid_duid(struct parse *cfile, struct ia_xx** ia,
42 			   u_int32_t *iaid, const char* file, int line);
43 #endif
44 
45 #if defined (TRACING)
46 trace_type_t *trace_readconf_type;
47 trace_type_t *trace_readleases_type;
48 
parse_trace_setup()49 void parse_trace_setup ()
50 {
51 	trace_readconf_type = trace_type_register ("readconf", (void *)0,
52 						   trace_conf_input,
53 						   trace_conf_stop, MDL);
54 	trace_readleases_type = trace_type_register ("readleases", (void *)0,
55 						     trace_conf_input,
56 						     trace_conf_stop, MDL);
57 }
58 #endif
59 
60 /* conf-file :== parameters declarations END_OF_FILE
61    parameters :== <nil> | parameter | parameters parameter
62    declarations :== <nil> | declaration | declarations declaration */
63 
readconf()64 isc_result_t readconf ()
65 {
66 	isc_result_t res;
67 
68 	res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
69 #if defined(LDAP_CONFIGURATION)
70 	if (res != ISC_R_SUCCESS)
71 		return (res);
72 
73 	return ldap_read_config ();
74 #else
75 	return (res);
76 #endif
77 }
78 
read_conf_file(const char * filename,struct group * group,int group_type,int leasep)79 isc_result_t read_conf_file (const char *filename, struct group *group,
80 			     int group_type, int leasep)
81 {
82 	int file;
83 	struct parse *cfile;
84 	isc_result_t status;
85 #if defined (TRACING)
86 	char *fbuf, *dbuf;
87 	off_t flen;
88 	int result;
89 	unsigned tflen, ulen;
90 	trace_type_t *ttype;
91 
92 	if (leasep)
93 		ttype = trace_readleases_type;
94 	else
95 		ttype = trace_readconf_type;
96 
97 	/* If we're in playback, we need to snarf the contents of the
98 	   named file out of the playback file rather than trying to
99 	   open and read it. */
100 	if (trace_playback ()) {
101 		dbuf = (char *)0;
102 		tflen = 0;
103 		status = trace_get_file (ttype, filename, &tflen, &dbuf);
104 		if (status != ISC_R_SUCCESS)
105 			return status;
106 		ulen = tflen;
107 
108 		/* What we get back is filename\0contents, where contents is
109 		   terminated just by the length.  So we figure out the length
110 		   of the filename, and subtract that and the NUL from the
111 		   total length to get the length of the contents of the file.
112 		   We make fbuf a pointer to the contents of the file, and
113 		   leave dbuf as it is so we can free it later. */
114 		tflen = strlen (dbuf);
115 		ulen = ulen - tflen - 1;
116 		fbuf = dbuf + tflen + 1;
117 		goto memfile;
118 	}
119 #endif
120 
121 	if ((file = open (filename, O_RDONLY)) < 0) {
122 		if (leasep) {
123 			log_error ("Can't open lease database %s: %m --",
124 				   path_dhcpd_db);
125 			log_error ("  check for failed database %s!",
126 				   "rewrite attempt");
127 			log_error ("Please read the dhcpd.leases manual%s",
128 				   " page if you");
129 			log_fatal ("don't know what to do about this.");
130 		} else {
131 			log_fatal ("Can't open %s: %m", filename);
132 		}
133 	}
134 
135 	cfile = (struct parse *)0;
136 #if defined (TRACING)
137 	flen = lseek (file, (off_t)0, SEEK_END);
138 	if (flen < 0) {
139 	      boom:
140 		log_fatal ("Can't lseek on %s: %m", filename);
141 	}
142 	if (lseek (file, (off_t)0, SEEK_SET) < 0)
143 		goto boom;
144 	/* Can't handle files greater than 2^31-1. */
145 	if (flen > 0x7FFFFFFFUL)
146 		log_fatal ("%s: file is too long to buffer.", filename);
147 	ulen = flen;
148 
149 	/* Allocate a buffer that will be what's written to the tracefile,
150 	   and also will be what we parse from. */
151 	tflen = strlen (filename);
152 	dbuf = dmalloc (ulen + tflen + 1, MDL);
153 	if (!dbuf)
154 		log_fatal ("No memory for %s (%d bytes)",
155 			   filename, ulen);
156 
157 	/* Copy the name into the beginning, nul-terminated. */
158 	strcpy (dbuf, filename);
159 
160 	/* Load the file in after the NUL. */
161 	fbuf = dbuf + tflen + 1;
162 	result = read (file, fbuf, ulen);
163 	if (result < 0)
164 		log_fatal ("Can't read in %s: %m", filename);
165 	if (result != ulen)
166 		log_fatal ("%s: short read of %d bytes instead of %d.",
167 			   filename, ulen, result);
168 	close (file);
169       memfile:
170 	/* If we're recording, write out the filename and file contents. */
171 	if (trace_record ())
172 		trace_write_packet (ttype, ulen + tflen + 1, dbuf, MDL);
173 	status = new_parse(&cfile, -1, fbuf, ulen, filename, 0); /* XXX */
174 #else
175 	status = new_parse(&cfile, file, NULL, 0, filename, 0);
176 #endif
177 	if (status != ISC_R_SUCCESS || cfile == NULL)
178 		return status;
179 
180 	if (leasep)
181 		status = lease_file_subparse (cfile);
182 	else
183 		status = conf_file_subparse (cfile, group, group_type);
184 	end_parse (&cfile);
185 #if defined (TRACING)
186 	dfree (dbuf, MDL);
187 #endif
188 	return status;
189 }
190 
191 #if defined (TRACING)
trace_conf_input(trace_type_t * ttype,unsigned len,char * data)192 void trace_conf_input (trace_type_t *ttype, unsigned len, char *data)
193 {
194 	char *fbuf;
195 	unsigned flen;
196 	unsigned tflen;
197 	struct parse *cfile = (struct parse *)0;
198 	static int postconf_initialized;
199 	static int leaseconf_initialized;
200 	isc_result_t status;
201 
202 	/* Do what's done above, except that we don't have to read in the
203 	   data, because it's already been read for us. */
204 	tflen = strlen (data);
205 	flen = len - tflen - 1;
206 	fbuf = data + tflen + 1;
207 
208 	/* If we're recording, write out the filename and file contents. */
209 	if (trace_record ())
210 		trace_write_packet (ttype, len, data, MDL);
211 
212 	status = new_parse(&cfile, -1, fbuf, flen, data, 0);
213 	if (status == ISC_R_SUCCESS || cfile != NULL) {
214 		if (ttype == trace_readleases_type)
215 			lease_file_subparse (cfile);
216 		else
217 			conf_file_subparse (cfile, root_group, ROOT_GROUP);
218 		end_parse (&cfile);
219 	}
220 
221 	/* Postconfiguration needs to be done after the config file
222 	   has been loaded. */
223 	if (!postconf_initialized && ttype == trace_readconf_type) {
224 		postconf_initialization (0);
225 		postconf_initialized = 1;
226 	}
227 
228 	if (!leaseconf_initialized && ttype == trace_readleases_type) {
229 		db_startup (0);
230 		leaseconf_initialized = 1;
231 		postdb_startup ();
232 	}
233 }
234 
trace_conf_stop(trace_type_t * ttype)235 void trace_conf_stop (trace_type_t *ttype) { }
236 #endif
237 
238 /* conf-file :== parameters declarations END_OF_FILE
239    parameters :== <nil> | parameter | parameters parameter
240    declarations :== <nil> | declaration | declarations declaration */
241 
conf_file_subparse(struct parse * cfile,struct group * group,int group_type)242 isc_result_t conf_file_subparse (struct parse *cfile, struct group *group,
243 				 int group_type)
244 {
245 	const char *val;
246 	enum dhcp_token token;
247 	int declaration = 0;
248 	int status;
249 
250 	do {
251 		token = peek_token (&val, (unsigned *)0, cfile);
252 		if (token == END_OF_FILE)
253 			break;
254 		declaration = parse_statement (cfile, group, group_type,
255 					       (struct host_decl *)0,
256 					       declaration);
257 	} while (1);
258 	skip_token(&val, (unsigned *)0, cfile);
259 
260 	status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
261 	return status;
262 }
263 
264 /* lease-file :== lease-declarations END_OF_FILE
265    lease-statements :== <nil>
266    		     | lease-declaration
267 		     | lease-declarations lease-declaration */
268 
lease_file_subparse(struct parse * cfile)269 isc_result_t lease_file_subparse (struct parse *cfile)
270 {
271 	const char *val;
272 	enum dhcp_token token;
273 	isc_result_t status;
274 
275 	do {
276 		token = next_token (&val, (unsigned *)0, cfile);
277 		if (token == END_OF_FILE)
278 			break;
279 		if (token == LEASE) {
280 			struct lease *lease = (struct lease *)0;
281 			if (parse_lease_declaration (&lease, cfile)) {
282 				enter_lease (lease);
283 				lease_dereference (&lease, MDL);
284 			} else
285 				parse_warn (cfile,
286 					    "possibly corrupt lease file");
287 		} else if (token == IA_NA) {
288 			parse_ia_na_declaration(cfile);
289 		} else if (token == IA_TA) {
290 			parse_ia_ta_declaration(cfile);
291 		} else if (token == IA_PD) {
292 			parse_ia_pd_declaration(cfile);
293 		} else if (token == CLASS) {
294 			parse_class_declaration(0, cfile, root_group,
295 						CLASS_TYPE_CLASS);
296 		} else if (token == SUBCLASS) {
297 			parse_class_declaration(0, cfile, root_group,
298 						CLASS_TYPE_SUBCLASS);
299 		} else if (token == HOST) {
300 			parse_host_declaration (cfile, root_group);
301 		} else if (token == GROUP) {
302 			parse_group_declaration (cfile, root_group);
303 #if defined (FAILOVER_PROTOCOL)
304 		} else if (token == FAILOVER) {
305 			parse_failover_state_declaration
306 				(cfile, (dhcp_failover_state_t *)0);
307 #endif
308 #ifdef DHCPv6
309 		} else if (token == SERVER_DUID) {
310 			parse_server_duid(cfile);
311 #endif /* DHCPv6 */
312 		} else if (token == AUTHORING_BYTE_ORDER) {
313 			parse_authoring_byte_order(cfile);
314 		} else {
315 			log_error ("Corrupt lease file - possible data loss!");
316 			skip_to_semi (cfile);
317 		}
318 
319 	} while (1);
320 
321 	status = cfile->warnings_occurred ? DHCP_R_BADPARSE : ISC_R_SUCCESS;
322 	return status;
323 }
324 
325 /* statement :== parameter | declaration
326 
327    parameter :== DEFAULT_LEASE_TIME lease_time
328 	       | MAX_LEASE_TIME lease_time
329 	       | DYNAMIC_BOOTP_LEASE_CUTOFF date
330 	       | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
331 	       | BOOT_UNKNOWN_CLIENTS boolean
332 	       | ONE_LEASE_PER_CLIENT boolean
333 	       | GET_LEASE_HOSTNAMES boolean
334 	       | USE_HOST_DECL_NAME boolean
335 	       | NEXT_SERVER ip-addr-or-hostname SEMI
336 	       | option_parameter
337 	       | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
338 	       | FILENAME string-parameter
339 	       | SERVER_NAME string-parameter
340 	       | hardware-parameter
341 	       | fixed-address-parameter
342 	       | ALLOW allow-deny-keyword
343 	       | DENY allow-deny-keyword
344 	       | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
345 	       | AUTHORITATIVE
346 	       | NOT AUTHORITATIVE
347 
348    declaration :== host-declaration
349 		 | group-declaration
350 		 | shared-network-declaration
351 		 | subnet-declaration
352 		 | VENDOR_CLASS class-declaration
353 		 | USER_CLASS class-declaration
354 		 | RANGE address-range-declaration */
355 
parse_statement(cfile,group,type,host_decl,declaration)356 int parse_statement (cfile, group, type, host_decl, declaration)
357 	struct parse *cfile;
358 	struct group *group;
359 	int type;
360 	struct host_decl *host_decl;
361 	int declaration;
362 {
363 	enum dhcp_token token;
364 	const char *val;
365 	struct shared_network *share;
366 	char *n;
367 	struct hardware hardware;
368 	struct executable_statement *et, *ep;
369 	struct option *option = NULL;
370 	struct option_cache *cache;
371 	int lose;
372 	int known;
373 	isc_result_t status;
374 	unsigned code;
375 
376 	token = peek_token (&val, (unsigned *)0, cfile);
377 
378 	switch (token) {
379 	      case INCLUDE:
380 		skip_token(&val, (unsigned *)0, cfile);
381 		token = next_token (&val, (unsigned *)0, cfile);
382 		if (token != STRING) {
383 			parse_warn (cfile, "filename string expected.");
384 			skip_to_semi (cfile);
385 		} else {
386 			status = read_conf_file (val, group, type, 0);
387 			if (status != ISC_R_SUCCESS)
388 				parse_warn (cfile, "%s: bad parse.", val);
389 			parse_semi (cfile);
390 		}
391 		return 1;
392 
393 	      case HOST:
394 		skip_token(&val, (unsigned *)0, cfile);
395 		if (type != HOST_DECL && type != CLASS_DECL) {
396 			if (global_host_once &&
397 			    (type == SUBNET_DECL || type == SHARED_NET_DECL)) {
398 				global_host_once = 0;
399 				log_error("WARNING: Host declarations are "
400 					  "global.  They are not limited to "
401 					  "the scope you declared them in.");
402 			}
403 
404 			parse_host_declaration (cfile, group);
405 		} else {
406 			parse_warn (cfile,
407 				    "host declarations not allowed here.");
408 			skip_to_semi (cfile);
409 		}
410 		return 1;
411 
412 	      case GROUP:
413 		skip_token(&val, (unsigned *)0, cfile);
414 		if (type != HOST_DECL && type != CLASS_DECL)
415 			parse_group_declaration (cfile, group);
416 		else {
417 			parse_warn (cfile,
418 				    "group declarations not allowed here.");
419 			skip_to_semi (cfile);
420 		}
421 		return 1;
422 
423 	      case SHARED_NETWORK:
424 		skip_token(&val, (unsigned *)0, cfile);
425 		if (type == SHARED_NET_DECL ||
426 		    type == HOST_DECL ||
427 		    type == SUBNET_DECL ||
428 		    type == CLASS_DECL) {
429 			parse_warn (cfile, "shared-network parameters not %s.",
430 				    "allowed here");
431 			skip_to_semi (cfile);
432 			break;
433 		}
434 
435 		parse_shared_net_declaration (cfile, group);
436 		return 1;
437 
438 	      case SUBNET:
439 	      case SUBNET6:
440 		skip_token(&val, (unsigned *)0, cfile);
441 		if (type == HOST_DECL || type == SUBNET_DECL ||
442 		    type == CLASS_DECL) {
443 			parse_warn (cfile,
444 				    "subnet declarations not allowed here.");
445 			skip_to_semi (cfile);
446 			return 1;
447 		}
448 
449 		/* If we're in a subnet declaration, just do the parse. */
450 		if (group->shared_network != NULL) {
451 			if (token == SUBNET) {
452 				parse_subnet_declaration(cfile,
453 							 group->shared_network);
454 			} else {
455 				parse_subnet6_declaration(cfile,
456 							 group->shared_network);
457 			}
458 			break;
459 		}
460 
461 		/*
462 		 * Otherwise, cons up a fake shared network structure
463 		 * and populate it with the lone subnet...because the
464 		 * intention most likely is to refer to the entire link
465 		 * by shorthand, any configuration inside the subnet is
466 		 * actually placed in the shared-network's group.
467 		 */
468 
469 		share = NULL;
470 		status = shared_network_allocate (&share, MDL);
471 		if (status != ISC_R_SUCCESS)
472 			log_fatal ("Can't allocate shared subnet: %s",
473 				   isc_result_totext (status));
474 		if (!clone_group (&share -> group, group, MDL))
475 			log_fatal ("Can't allocate group for shared net");
476 		shared_network_reference (&share -> group -> shared_network,
477 					  share, MDL);
478 
479 		/*
480 		 * This is an implicit shared network, not explicit in
481 		 * the config.
482 		 */
483 		share->flags |= SHARED_IMPLICIT;
484 
485 		if (token == SUBNET) {
486 			parse_subnet_declaration(cfile, share);
487 		} else {
488 			parse_subnet6_declaration(cfile, share);
489 		}
490 
491 		/* share -> subnets is the subnet we just parsed. */
492 		if (share->subnets) {
493 			interface_reference(&share->interface,
494 					    share->subnets->interface,
495 					    MDL);
496 
497 			/* Make the shared network name from network number. */
498 			if (token == SUBNET) {
499 				n = piaddrmask(&share->subnets->net,
500 					       &share->subnets->netmask);
501 			} else {
502 				n = piaddrcidr(&share->subnets->net,
503 					       share->subnets->prefix_len);
504 			}
505 
506 			share->name = strdup(n);
507 
508 			if (share->name == NULL)
509 				log_fatal("Out of memory allocating default "
510 					  "shared network name (\"%s\").", n);
511 
512 			/* Copy the authoritative parameter from the subnet,
513 			   since there is no opportunity to declare it here. */
514 			share->group->authoritative =
515 				share->subnets->group->authoritative;
516 			enter_shared_network(share);
517 		}
518 		shared_network_dereference(&share, MDL);
519 		return 1;
520 
521 	      case VENDOR_CLASS:
522 		skip_token(&val, (unsigned *)0, cfile);
523 		if (type == CLASS_DECL) {
524 			parse_warn (cfile,
525 				    "class declarations not allowed here.");
526 			skip_to_semi (cfile);
527 			break;
528 		}
529 		parse_class_declaration(NULL, cfile, group, CLASS_TYPE_VENDOR);
530 		return 1;
531 
532 	      case USER_CLASS:
533 		skip_token(&val, (unsigned *)0, cfile);
534 		if (type == CLASS_DECL) {
535 			parse_warn (cfile,
536 				    "class declarations not allowed here.");
537 			skip_to_semi (cfile);
538 			break;
539 		}
540 		parse_class_declaration(NULL, cfile, group, CLASS_TYPE_USER);
541 		return 1;
542 
543 	      case CLASS:
544 		skip_token(&val, (unsigned *)0, cfile);
545 		if (type == CLASS_DECL) {
546 			parse_warn (cfile,
547 				    "class declarations not allowed here.");
548 			skip_to_semi (cfile);
549 			break;
550 		}
551 		parse_class_declaration(NULL, cfile, group, CLASS_TYPE_CLASS);
552 		return 1;
553 
554 	      case SUBCLASS:
555 		skip_token(&val, (unsigned *)0, cfile);
556 		if (type == CLASS_DECL) {
557 			parse_warn (cfile,
558 				    "class declarations not allowed here.");
559 			skip_to_semi (cfile);
560 			break;
561 		}
562 		parse_class_declaration(NULL, cfile, group,
563 					CLASS_TYPE_SUBCLASS);
564 		return 1;
565 
566 	      case HARDWARE:
567 		skip_token(&val, (unsigned *)0, cfile);
568 		memset (&hardware, 0, sizeof hardware);
569 		if (host_decl && memcmp(&hardware, &(host_decl->interface),
570 					sizeof(hardware)) != 0) {
571 			parse_warn(cfile, "Host %s hardware address already "
572 					  "configured.", host_decl->name);
573 			break;
574 		}
575 
576 		parse_hardware_param (cfile, &hardware);
577 		if (host_decl)
578 			host_decl -> interface = hardware;
579 		else
580 			parse_warn (cfile, "hardware address parameter %s",
581 				    "not allowed here.");
582 		break;
583 
584 	      case FIXED_ADDR:
585 	      case FIXED_ADDR6:
586 		skip_token(&val, NULL, cfile);
587 		cache = NULL;
588 		if (parse_fixed_addr_param(&cache, cfile, token)) {
589 			if (host_decl) {
590 				if (host_decl->fixed_addr) {
591 					option_cache_dereference(&cache, MDL);
592 					parse_warn(cfile,
593 						   "Only one fixed address "
594 						   "declaration per host.");
595 				} else {
596 					host_decl->fixed_addr = cache;
597 				}
598 			} else {
599 				parse_warn(cfile,
600 					   "fixed-address parameter not "
601 					   "allowed here.");
602 				option_cache_dereference(&cache, MDL);
603 			}
604 		}
605 		break;
606 
607 	      case POOL:
608 		skip_token(&val, (unsigned *)0, cfile);
609 		if (type == POOL_DECL) {
610 			parse_warn (cfile, "pool declared within pool.");
611 			skip_to_semi(cfile);
612 		} else if (type != SUBNET_DECL && type != SHARED_NET_DECL) {
613 			parse_warn (cfile, "pool declared outside of network");
614 			skip_to_semi(cfile);
615 		} else
616 			parse_pool_statement (cfile, group, type);
617 
618 		return declaration;
619 
620 	      case RANGE:
621 		skip_token(&val, (unsigned *)0, cfile);
622 		if (type != SUBNET_DECL || !group -> subnet) {
623 			parse_warn (cfile,
624 				    "range declaration not allowed here.");
625 			skip_to_semi (cfile);
626 			return declaration;
627 		}
628 		parse_address_range (cfile, group, type, (struct pool *)0,
629 				     (struct lease **)0);
630 		return declaration;
631 
632 #ifdef DHCPv6
633 	      case RANGE6:
634 		skip_token(NULL, NULL, cfile);
635 	        if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
636 			parse_warn (cfile,
637 				    "range6 declaration not allowed here.");
638 			skip_to_semi(cfile);
639 			return declaration;
640 		}
641 	      	parse_address_range6(cfile, group, NULL);
642 		return declaration;
643 
644 	      case PREFIX6:
645 		skip_token(NULL, NULL, cfile);
646 		if ((type != SUBNET_DECL) || (group->subnet == NULL)) {
647 			parse_warn (cfile,
648 				    "prefix6 declaration not allowed here.");
649 			skip_to_semi(cfile);
650 			return declaration;
651 		}
652 	      	parse_prefix6(cfile, group, NULL);
653 		return declaration;
654 
655 	      case FIXED_PREFIX6:
656 		skip_token(&val, NULL, cfile);
657 		if (!host_decl) {
658 			parse_warn (cfile,
659 				    "fixed-prefix6 declaration not "
660 				    "allowed here.");
661 			skip_to_semi(cfile);
662 			break;
663 		}
664 		parse_fixed_prefix6(cfile, host_decl);
665 		break;
666 
667 	      case POOL6:
668 		skip_token(&val, NULL, cfile);
669 		if (type == POOL_DECL) {
670 			parse_warn (cfile, "pool6 declared within pool.");
671 			skip_to_semi(cfile);
672 		} else if (type != SUBNET_DECL) {
673 			parse_warn (cfile, "pool6 declared outside of network");
674 			skip_to_semi(cfile);
675 		} else
676 			parse_pool6_statement (cfile, group, type);
677 
678 		return declaration;
679 
680 #endif /* DHCPv6 */
681 
682 	      case TOKEN_NOT:
683 		skip_token(&val, (unsigned *)0, cfile);
684 		token = next_token (&val, (unsigned *)0, cfile);
685 		switch (token) {
686 		      case AUTHORITATIVE:
687 			group -> authoritative = 0;
688 			goto authoritative;
689 		      default:
690 			parse_warn (cfile, "expecting assertion");
691 			skip_to_semi (cfile);
692 			break;
693 		}
694 		break;
695 	      case AUTHORITATIVE:
696 		skip_token(&val, (unsigned *)0, cfile);
697 		group -> authoritative = 1;
698 	      authoritative:
699 		if (type == HOST_DECL)
700 			parse_warn (cfile, "authority makes no sense here.");
701 		parse_semi (cfile);
702 		break;
703 
704 		/* "server-identifier" is a special hack, equivalent to
705 		   "option dhcp-server-identifier". */
706 	      case SERVER_IDENTIFIER:
707 		code = DHO_DHCP_SERVER_IDENTIFIER;
708 		if (!option_code_hash_lookup(&option, dhcp_universe.code_hash,
709 					     &code, 0, MDL))
710 			log_fatal("Server identifier not in hash (%s:%d).",
711 				  MDL);
712 		skip_token(&val, (unsigned *)0, cfile);
713 		goto finish_option;
714 
715 	      case OPTION:
716 		skip_token(&val, (unsigned *)0, cfile);
717 		token = peek_token (&val, (unsigned *)0, cfile);
718 		if (token == SPACE) {
719 			if (type != ROOT_GROUP) {
720 				parse_warn (cfile,
721 					    "option space definitions %s",
722 					    "may not be scoped.");
723 				skip_to_semi (cfile);
724 				break;
725 			}
726 			parse_option_space_decl (cfile);
727 			return declaration;
728 		}
729 
730 		known = 0;
731 		status = parse_option_name(cfile, 1, &known, &option);
732 		if (status == ISC_R_SUCCESS) {
733 			token = peek_token (&val, (unsigned *)0, cfile);
734 			if (token == CODE) {
735 				if (type != ROOT_GROUP) {
736 					parse_warn (cfile,
737 						    "option definitions%s",
738 						    " may not be scoped.");
739 					skip_to_semi (cfile);
740 					option_dereference(&option, MDL);
741 					break;
742 				}
743 				skip_token(&val, (unsigned *)0, cfile);
744 
745 				/*
746 				 * If the option was known, remove it from the
747 				 * code and name hashes before redefining it.
748 				 */
749 				if (known) {
750 					option_name_hash_delete(
751 						option->universe->name_hash,
752 							option->name, 0, MDL);
753 					option_code_hash_delete(
754 						option->universe->code_hash,
755 							&option->code, 0, MDL);
756 				}
757 
758 				parse_option_code_definition(cfile, option);
759 				option_dereference(&option, MDL);
760 				return declaration;
761 			}
762 
763 			/* If this wasn't an option code definition, don't
764 			   allow an unknown option. */
765 			if (!known) {
766 				parse_warn (cfile, "unknown option %s.%s",
767 					    option -> universe -> name,
768 					    option -> name);
769 				skip_to_semi (cfile);
770 				option_dereference(&option, MDL);
771 				return declaration;
772 			}
773 
774 		      finish_option:
775 			et = (struct executable_statement *)0;
776 			if (!parse_option_statement
777 				(&et, cfile, 1, option,
778 				 supersede_option_statement)) {
779 				option_dereference(&option, MDL);
780 				return declaration;
781 			}
782 
783 			option_dereference(&option, MDL);
784 			goto insert_statement;
785 		} else
786 			return declaration;
787 
788 		break;
789 
790 	      case FAILOVER:
791 		if (type != ROOT_GROUP && type != SHARED_NET_DECL) {
792 			parse_warn (cfile, "failover peers may only be %s",
793 				    "defined in shared-network");
794 			log_error ("declarations and the outer scope.");
795 			skip_to_semi (cfile);
796 			break;
797 		}
798 		token = next_token (&val, (unsigned *)0, cfile);
799 #if defined (FAILOVER_PROTOCOL)
800 		parse_failover_peer (cfile, group, type);
801 #else
802 		parse_warn (cfile, "No failover support.");
803 		skip_to_semi (cfile);
804 #endif
805 		break;
806 
807 #ifdef DHCPv6
808 	      case SERVER_DUID:
809 		parse_server_duid_conf(cfile);
810 		break;
811 #endif /* DHCPv6 */
812 
813 	      case LEASE_ID_FORMAT:
814 		token = next_token (&val, (unsigned *)0, cfile);
815 		parse_lease_id_format(cfile);
816 		break;
817 
818 	      case PERCENT:
819 		/* Used by the MA so simply ignore... */
820 		skip_to_semi (cfile);
821 		break;
822 
823 	      default:
824 		et = (struct executable_statement *)0;
825 		lose = 0;
826 		if (!parse_executable_statement (&et, cfile, &lose,
827 						 context_any)) {
828 			if (!lose) {
829 				if (declaration)
830 					parse_warn (cfile,
831 						    "expecting a declaration");
832 				else
833 					parse_warn (cfile,
834 						    "expecting a parameter %s",
835 						    "or declaration");
836 				skip_to_semi (cfile);
837 			}
838 			return declaration;
839 		}
840 		if (!et)
841 			return declaration;
842 	      insert_statement:
843 		if (group -> statements) {
844 			int multi = 0;
845 
846 			/* If this set of statements is only referenced
847 			   by this group, just add the current statement
848 			   to the end of the chain. */
849 			for (ep = group -> statements; ep -> next;
850 			     ep = ep -> next)
851 				if (ep -> refcnt > 1) /* XXX */
852 					multi = 1;
853 			if (!multi) {
854 				executable_statement_reference (&ep -> next,
855 								et, MDL);
856 				executable_statement_dereference (&et, MDL);
857 				return declaration;
858 			}
859 
860 			/* Otherwise, make a parent chain, and put the
861 			   current group statements first and the new
862 			   statement in the next pointer. */
863 			ep = (struct executable_statement *)0;
864 			if (!executable_statement_allocate (&ep, MDL))
865 				log_fatal ("No memory for statements.");
866 			ep -> op = statements_statement;
867 			executable_statement_reference (&ep -> data.statements,
868 							group -> statements,
869 							MDL);
870 			executable_statement_reference (&ep -> next, et, MDL);
871 			executable_statement_dereference (&group -> statements,
872 							  MDL);
873 			executable_statement_reference (&group -> statements,
874 							ep, MDL);
875 			executable_statement_dereference (&ep, MDL);
876 		} else {
877 			executable_statement_reference (&group -> statements,
878 							et, MDL);
879 		}
880 		executable_statement_dereference (&et, MDL);
881 		return declaration;
882 	}
883 
884 	return 0;
885 }
886 
887 #if defined (FAILOVER_PROTOCOL)
parse_failover_peer(cfile,group,type)888 void parse_failover_peer (cfile, group, type)
889 	struct parse *cfile;
890 	struct group *group;
891 	int type;
892 {
893 	enum dhcp_token token;
894 	const char *val;
895 	dhcp_failover_state_t *peer;
896 	u_int32_t *tp;
897 	char *name;
898 	u_int32_t split;
899 	u_int8_t hba [32];
900 	unsigned hba_len = sizeof hba;
901 	int i;
902 	struct expression *expr;
903 	isc_result_t status;
904 	dhcp_failover_config_t *cp;
905 
906 	token = next_token (&val, (unsigned *)0, cfile);
907 	if (token != PEER) {
908 		parse_warn (cfile, "expecting \"peer\"");
909 		skip_to_semi (cfile);
910 		return;
911 	}
912 
913 	token = next_token (&val, (unsigned *)0, cfile);
914 	if (is_identifier (token) || token == STRING) {
915 		name = dmalloc (strlen (val) + 1, MDL);
916 		if (!name)
917 			log_fatal ("no memory for peer name %s", val);
918 		strcpy (name, val);
919 	} else {
920 		parse_warn (cfile, "expecting failover peer name.");
921 		skip_to_semi (cfile);
922 		return;
923 	}
924 
925 	/* See if there's a peer declaration by this name. */
926 	peer = (dhcp_failover_state_t *)0;
927 	find_failover_peer (&peer, name, MDL);
928 
929 	token = next_token (&val, (unsigned *)0, cfile);
930 	if (token == SEMI) {
931 		if (type != SHARED_NET_DECL)
932 			parse_warn (cfile, "failover peer reference not %s",
933 				    "in shared-network declaration");
934 		else {
935 			if (!peer) {
936 				parse_warn (cfile, "reference to unknown%s%s",
937 					    " failover peer ", name);
938                                 dfree (name, MDL);
939 				return;
940 			}
941 			dhcp_failover_state_reference
942 				(&group -> shared_network -> failover_peer,
943 				 peer, MDL);
944 		}
945 		dhcp_failover_state_dereference (&peer, MDL);
946                 dfree (name, MDL);
947 		return;
948 	} else if (token == STATE) {
949 		if (!peer) {
950 			parse_warn (cfile, "state declaration for unknown%s%s",
951 				    " failover peer ", name);
952                         dfree (name, MDL);
953 			return;
954 		}
955 		parse_failover_state_declaration (cfile, peer);
956 		dhcp_failover_state_dereference (&peer, MDL);
957                 dfree (name, MDL);
958 		return;
959 	} else if (token != LBRACE) {
960 		parse_warn (cfile, "expecting left brace");
961 		skip_to_semi (cfile);
962 	}
963 
964 	/* Make sure this isn't a redeclaration. */
965 	if (peer) {
966 		parse_warn (cfile, "redeclaration of failover peer %s", name);
967 		skip_to_rbrace (cfile, 1);
968 		dhcp_failover_state_dereference (&peer, MDL);
969                 dfree (name, MDL);
970 		return;
971 	}
972 
973 	status = dhcp_failover_state_allocate (&peer, MDL);
974 	if (status != ISC_R_SUCCESS)
975 		log_fatal ("Can't allocate failover peer %s: %s",
976 			   name, isc_result_totext (status));
977 
978 	/* Save the name. */
979 	peer -> name = name;
980 
981 	do {
982 		cp = &peer -> me;
983 	      peer:
984 		token = next_token (&val, (unsigned *)0, cfile);
985 		switch (token) {
986 		      case RBRACE:
987 			break;
988 
989 		      case PRIMARY:
990 			peer -> i_am = primary;
991 			break;
992 
993 		      case SECONDARY:
994 			peer -> i_am = secondary;
995 			if (peer -> hba)
996 				parse_warn (cfile,
997 					    "secondary may not define %s",
998 					    "load balance settings.");
999 			break;
1000 
1001 		      case PEER:
1002 			cp = &peer -> partner;
1003 			goto peer;
1004 
1005 		      case ADDRESS:
1006 			expr = (struct expression *)0;
1007 			if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
1008 				skip_to_rbrace (cfile, 1);
1009 				dhcp_failover_state_dereference (&peer, MDL);
1010 				return;
1011 			}
1012 			option_cache (&cp -> address,
1013 				      (struct data_string *)0, expr,
1014 				      (struct option *)0, MDL);
1015 			expression_dereference (&expr, MDL);
1016 			break;
1017 
1018 		      case PORT:
1019 			token = next_token (&val, (unsigned *)0, cfile);
1020 			if (token != NUMBER) {
1021 				parse_warn (cfile, "expecting number");
1022 				skip_to_rbrace (cfile, 1);
1023 			}
1024 			cp -> port = atoi (val);
1025 			break;
1026 
1027 		      case MAX_LEASE_MISBALANCE:
1028 			tp = &peer->max_lease_misbalance;
1029 			goto parse_idle;
1030 
1031 		      case MAX_LEASE_OWNERSHIP:
1032 			tp = &peer->max_lease_ownership;
1033 			goto parse_idle;
1034 
1035 		      case MAX_BALANCE:
1036 			tp = &peer->max_balance;
1037 			goto parse_idle;
1038 
1039 		      case MIN_BALANCE:
1040 			tp = &peer->min_balance;
1041 			goto parse_idle;
1042 
1043 		      case AUTO_PARTNER_DOWN:
1044 			tp = &peer->auto_partner_down;
1045 			goto parse_idle;
1046 
1047 		      case MAX_RESPONSE_DELAY:
1048 			tp = &cp -> max_response_delay;
1049 		      parse_idle:
1050 			token = next_token (&val, (unsigned *)0, cfile);
1051 			if (token != NUMBER) {
1052 				parse_warn (cfile, "expecting number.");
1053 				skip_to_rbrace (cfile, 1);
1054 				dhcp_failover_state_dereference (&peer, MDL);
1055 				return;
1056 			}
1057 			*tp = atoi (val);
1058 			break;
1059 
1060 		      case MAX_UNACKED_UPDATES:
1061 			tp = &cp -> max_flying_updates;
1062 			goto parse_idle;
1063 
1064 		      case MCLT:
1065 			tp = &peer -> mclt;
1066 			goto parse_idle;
1067 
1068 		      case HBA:
1069 			hba_len = 32;
1070 			if (peer -> i_am == secondary)
1071 				parse_warn (cfile,
1072 					    "secondary may not define %s",
1073 					    "load balance settings.");
1074 			if (!parse_numeric_aggregate (cfile, hba, &hba_len,
1075 						      COLON, 16, 8)) {
1076 				skip_to_rbrace (cfile, 1);
1077 				dhcp_failover_state_dereference (&peer, MDL);
1078 				return;
1079 			}
1080 			if (hba_len != 32) {
1081 				parse_warn (cfile,
1082 					    "HBA must be exactly 32 bytes.");
1083 				break;
1084 			}
1085 		      make_hba:
1086 			peer -> hba = dmalloc (32, MDL);
1087 			if (!peer -> hba) {
1088 				dfree (peer -> name, MDL);
1089 				dfree (peer, MDL);
1090 			}
1091 			memcpy (peer -> hba, hba, 32);
1092 			break;
1093 
1094 		      case SPLIT:
1095 			token = next_token (&val, (unsigned *)0, cfile);
1096 			if (peer -> i_am == secondary)
1097 				parse_warn (cfile,
1098 					    "secondary may not define %s",
1099 					    "load balance settings.");
1100 			if (token != NUMBER) {
1101 				parse_warn (cfile, "expecting number");
1102 				skip_to_rbrace (cfile, 1);
1103 				dhcp_failover_state_dereference (&peer, MDL);
1104 				return;
1105 			}
1106 			split = atoi (val);
1107 			if (split > 256) {
1108 				parse_warn (cfile, "split must be between "
1109                                                    "0 and 256, inclusive");
1110 			} else {
1111 				memset (hba, 0, sizeof hba);
1112 				for (i = 0; i < split; i++) {
1113 					if (i < split)
1114 						hba [i / 8] |= (1 << (i & 7));
1115 				}
1116 				goto make_hba;
1117 			}
1118 			break;
1119 
1120 		      case LOAD:
1121 			token = next_token (&val, (unsigned *)0, cfile);
1122 			if (token != BALANCE) {
1123 				parse_warn (cfile, "expecting 'balance'");
1124 			      badload:
1125 				skip_to_rbrace (cfile, 1);
1126 				break;
1127 			}
1128 			token = next_token (&val, (unsigned *)0, cfile);
1129 			if (token != TOKEN_MAX) {
1130 				parse_warn (cfile, "expecting 'max'");
1131 				goto badload;
1132 			}
1133 			token = next_token (&val, (unsigned *)0, cfile);
1134 			if (token != SECONDS) {
1135 				parse_warn (cfile, "expecting 'secs'");
1136 				goto badload;
1137 			}
1138 			token = next_token (&val, (unsigned *)0, cfile);
1139 			if (token != NUMBER) {
1140 				parse_warn (cfile, "expecting number");
1141 				goto badload;
1142 			}
1143 			peer -> load_balance_max_secs = atoi (val);
1144 			break;
1145 
1146 		      default:
1147 			parse_warn (cfile,
1148 				    "invalid statement in peer declaration");
1149 			skip_to_rbrace (cfile, 1);
1150 			dhcp_failover_state_dereference (&peer, MDL);
1151 			return;
1152 		}
1153 		if (token != RBRACE && !parse_semi (cfile)) {
1154 			skip_to_rbrace (cfile, 1);
1155 			dhcp_failover_state_dereference (&peer, MDL);
1156 			return;
1157 		}
1158 	} while (token != RBRACE);
1159 
1160 	/* me.address can be null; the failover link initiate code tries to
1161 	 * derive a reasonable address to use.
1162 	 */
1163 	if (!peer -> partner.address)
1164 		parse_warn (cfile, "peer address may not be omitted");
1165 
1166 	if (!peer->me.port)
1167 		peer->me.port = DEFAULT_FAILOVER_PORT;
1168 	if (!peer->partner.port)
1169 		peer->partner.port = DEFAULT_FAILOVER_PORT;
1170 
1171 	if (peer -> i_am == primary) {
1172 	    if (!peer -> hba) {
1173 		parse_warn (cfile,
1174 			    "primary failover server must have hba or split.");
1175 	    } else if (!peer -> mclt) {
1176 		parse_warn (cfile,
1177 			    "primary failover server must have mclt.");
1178 	    }
1179 	}
1180 
1181 	if (!peer->max_lease_misbalance)
1182 		peer->max_lease_misbalance = DEFAULT_MAX_LEASE_MISBALANCE;
1183 	if (!peer->max_lease_ownership)
1184 		peer->max_lease_ownership = DEFAULT_MAX_LEASE_OWNERSHIP;
1185 	if (!peer->max_balance)
1186 		peer->max_balance = DEFAULT_MAX_BALANCE_TIME;
1187 	if (!peer->min_balance)
1188 		peer->min_balance = DEFAULT_MIN_BALANCE_TIME;
1189 	if (!peer->me.max_flying_updates)
1190 		peer->me.max_flying_updates = DEFAULT_MAX_FLYING_UPDATES;
1191 	if (!peer->me.max_response_delay)
1192 		peer->me.max_response_delay = DEFAULT_MAX_RESPONSE_DELAY;
1193 
1194 	if (type == SHARED_NET_DECL)
1195 		group->shared_network->failover_peer = peer;
1196 
1197 	/* Set the initial state. */
1198 	peer->me.state = recover;
1199 	peer->me.stos = cur_time;
1200 	peer->partner.state = unknown_state;
1201 	peer->partner.stos = cur_time;
1202 
1203 	status = enter_failover_peer (peer);
1204 	if (status != ISC_R_SUCCESS)
1205 		parse_warn (cfile, "failover peer %s: %s",
1206 			    peer -> name, isc_result_totext (status));
1207 	dhcp_failover_state_dereference (&peer, MDL);
1208 }
1209 
parse_failover_state_declaration(struct parse * cfile,dhcp_failover_state_t * peer)1210 void parse_failover_state_declaration (struct parse *cfile,
1211 				       dhcp_failover_state_t *peer)
1212 {
1213 	enum dhcp_token token;
1214 	const char *val;
1215 	char *name;
1216 	dhcp_failover_state_t *state;
1217 	dhcp_failover_config_t *cp;
1218 
1219 	if (!peer) {
1220 		token = next_token (&val, (unsigned *)0, cfile);
1221 		if (token != PEER) {
1222 			parse_warn (cfile, "expecting \"peer\"");
1223 			skip_to_semi (cfile);
1224 			return;
1225 		}
1226 
1227 		token = next_token (&val, (unsigned *)0, cfile);
1228 		if (is_identifier (token) || token == STRING) {
1229 			name = dmalloc (strlen (val) + 1, MDL);
1230 			if (!name)
1231 				log_fatal ("failover peer name %s: no memory",
1232 					   val);
1233 			strcpy (name, val);
1234 		} else {
1235 			parse_warn (cfile, "expecting failover peer name.");
1236 			skip_to_semi (cfile);
1237 			return;
1238 		}
1239 
1240 		/* See if there's a peer declaration by this name. */
1241 		state = (dhcp_failover_state_t *)0;
1242 		find_failover_peer (&state, name, MDL);
1243 		if (!state) {
1244 			parse_warn (cfile, "unknown failover peer: %s", name);
1245 			skip_to_semi (cfile);
1246 			return;
1247 		}
1248 
1249 		token = next_token (&val, (unsigned *)0, cfile);
1250 		if (token != STATE) {
1251 			parse_warn (cfile, "expecting 'state'");
1252 			if (token != SEMI)
1253 				skip_to_semi (cfile);
1254 			return;
1255 		}
1256 	} else {
1257 		state = (dhcp_failover_state_t *)0;
1258 		dhcp_failover_state_reference (&state, peer, MDL);
1259 	}
1260 	token = next_token (&val, (unsigned *)0, cfile);
1261 	if (token != LBRACE) {
1262 		parse_warn (cfile, "expecting left brace");
1263 		if (token != SEMI)
1264 			skip_to_semi (cfile);
1265 		dhcp_failover_state_dereference (&state, MDL);
1266 		return;
1267 	}
1268 	do {
1269 		token = next_token (&val, (unsigned *)0, cfile);
1270 		switch (token) {
1271 		      case RBRACE:
1272 			break;
1273 		      case MY:
1274 			cp = &state -> me;
1275 		      do_state:
1276 			token = next_token (&val, (unsigned *)0, cfile);
1277 			if (token != STATE) {
1278 				parse_warn (cfile, "expecting 'state'");
1279 				goto bogus;
1280 			}
1281 			parse_failover_state (cfile,
1282 					      &cp -> state, &cp -> stos);
1283 			break;
1284 
1285 		      case PARTNER:
1286 			cp = &state -> partner;
1287 			goto do_state;
1288 
1289 		      case MCLT:
1290 			if (state -> i_am == primary) {
1291 				parse_warn (cfile,
1292 					    "mclt not valid for primary");
1293 				goto bogus;
1294 			}
1295 			token = next_token (&val, (unsigned *)0, cfile);
1296 			if (token != NUMBER) {
1297 				parse_warn (cfile, "expecting a number.");
1298 				goto bogus;
1299 			}
1300 			state -> mclt = atoi (val);
1301 			parse_semi (cfile);
1302 			break;
1303 
1304 		      default:
1305 			parse_warn (cfile, "expecting state setting.");
1306 		      bogus:
1307 			skip_to_rbrace (cfile, 1);
1308 			dhcp_failover_state_dereference (&state, MDL);
1309 			return;
1310 		}
1311 	} while (token != RBRACE);
1312 	dhcp_failover_state_dereference (&state, MDL);
1313 }
1314 
parse_failover_state(cfile,state,stos)1315 void parse_failover_state (cfile, state, stos)
1316 	struct parse *cfile;
1317 	enum failover_state *state;
1318 	TIME *stos;
1319 {
1320 	enum dhcp_token token;
1321 	const char *val;
1322 	enum failover_state state_in;
1323 	TIME stos_in;
1324 
1325 	token = next_token (&val, (unsigned *)0, cfile);
1326 	switch (token) {
1327 	      case UNKNOWN_STATE:
1328 		state_in = unknown_state;
1329 		break;
1330 
1331 	      case PARTNER_DOWN:
1332 		state_in = partner_down;
1333 		break;
1334 
1335 	      case NORMAL:
1336 		state_in = normal;
1337 		break;
1338 
1339 	      case COMMUNICATIONS_INTERRUPTED:
1340 		state_in = communications_interrupted;
1341 		break;
1342 
1343 	      case CONFLICT_DONE:
1344 		state_in = conflict_done;
1345 		break;
1346 
1347 	      case RESOLUTION_INTERRUPTED:
1348 		state_in = resolution_interrupted;
1349 		break;
1350 
1351 	      case POTENTIAL_CONFLICT:
1352 		state_in = potential_conflict;
1353 		break;
1354 
1355 	      case RECOVER:
1356 		state_in = recover;
1357 		break;
1358 
1359 	      case RECOVER_WAIT:
1360 		state_in = recover_wait;
1361 		break;
1362 
1363 	      case RECOVER_DONE:
1364 		state_in = recover_done;
1365 		break;
1366 
1367 	      case SHUTDOWN:
1368 		state_in = shut_down;
1369 		break;
1370 
1371 	      case PAUSED:
1372 		state_in = paused;
1373 		break;
1374 
1375 	      case STARTUP:
1376 		state_in = startup;
1377 		break;
1378 
1379 	      default:
1380 		parse_warn (cfile, "unknown failover state");
1381 		skip_to_semi (cfile);
1382 		return;
1383 	}
1384 
1385 	token = next_token (&val, (unsigned *)0, cfile);
1386 	if (token == SEMI) {
1387 		stos_in = cur_time;
1388 	} else {
1389 		if (token != AT) {
1390 			parse_warn (cfile, "expecting \"at\"");
1391 			skip_to_semi (cfile);
1392 			return;
1393 		}
1394 
1395 		stos_in = parse_date (cfile);
1396 		if (!stos_in)
1397 			return;
1398 	}
1399 
1400 	/* Now that we've apparently gotten a clean parse, we
1401 	   can trust that this is a state that was fully committed to
1402 	   disk, so we can install it. */
1403 	*stos = stos_in;
1404 	*state = state_in;
1405 }
1406 #endif /* defined (FAILOVER_PROTOCOL) */
1407 
1408 /*!
1409  * \brief Parses an authoring-byte-order statement
1410  *
1411  * A valid statement looks like this:
1412  *
1413  *	authoring-byte-order :==
1414  *		PARSE_BYTE_ORDER TOKEN_LITTLE_ENDIAN | TOKEN_BIG_ENDIAN ;
1415  *
1416  * If the global, authoring_byte_order is not zero, then either the statement
1417  * has already been parsed or the function, parse_byte_order_uint32, has
1418  * been called which set it to the default.  In either case, this is invalid
1419  * so we'll log it and bail.
1420  *
1421  * If the value is different from the current server's byte order, then we'll
1422  * log that fact and set authoring_byte_order to given value. This causes all
1423  * invocations of the function, parse_byte_order_uint32, to perform byte-order
1424  * conversion before returning the value.
1425  *
1426  * \param cfile the current parse file
1427  *
1428 */
parse_authoring_byte_order(struct parse * cfile)1429 void parse_authoring_byte_order (struct parse *cfile)
1430 {
1431 	enum dhcp_token token;
1432 	const char *val;
1433 	unsigned int len;
1434 
1435 	/* Either we've seen it already or it's after the first lease */
1436 	if (authoring_byte_order != 0) {
1437 		parse_warn (cfile,
1438 			    "authoring-byte-order specified too late.\n"
1439 			    "It must occur before the first lease in file\n");
1440 		skip_to_semi (cfile);
1441 		return;
1442 	}
1443 
1444 	token = next_token(&val, (unsigned *)0, cfile);
1445 	switch(token) {
1446 	case TOKEN_LITTLE_ENDIAN:
1447 		authoring_byte_order =  LITTLE_ENDIAN;
1448 		break;
1449 	case TOKEN_BIG_ENDIAN:
1450 		authoring_byte_order =  BIG_ENDIAN;
1451 		break;
1452 	default:
1453 		parse_warn(cfile, "authoring-byte-order is invalid: "
1454                                    " it must be big-endian or little-endian.");
1455 		skip_to_semi(cfile);
1456 		return;
1457 	}
1458 
1459 	if (authoring_byte_order != DHCP_BYTE_ORDER)  {
1460 		log_error ("WARNING: Lease file authored using different"
1461                            " byte order, will attempt to convert");
1462 	}
1463 
1464         token = next_token(&val, &len, cfile);
1465         if (token != SEMI) {
1466                 parse_warn(cfile, "corrupt lease file; expecting a semicolon");
1467                 skip_to_semi(cfile);
1468                 return;
1469         }
1470 }
1471 
1472 /*!
1473  * \brief Parses a lease-id-format statement
1474  *
1475  * A valid statement looks like this:
1476  *
1477  *	lease-id-format :==
1478  *		LEASE_ID_FORMAT TOKEN_OCTAL | TOKEN_HEX ;
1479  *
1480  * This function is used to parse the lease-id-format statement. It sets the
1481  * global variable, lease_id_format.
1482  *
1483  * \param cfile the current parse file
1484  *
1485 */
parse_lease_id_format(struct parse * cfile)1486 void parse_lease_id_format (struct parse *cfile)
1487 {
1488 	enum dhcp_token token;
1489 	const char *val;
1490 	unsigned int len;
1491 
1492 	token = next_token(&val, NULL, cfile);
1493 	switch(token) {
1494 	case TOKEN_OCTAL:
1495 		lease_id_format = TOKEN_OCTAL;
1496 		break;
1497 	case TOKEN_HEX:
1498 		lease_id_format = TOKEN_HEX;
1499 		break;
1500 	default:
1501 		parse_warn(cfile, "lease-id-format is invalid: "
1502                                    " it must be octal or hex.");
1503 		skip_to_semi(cfile);
1504 		return;
1505 	}
1506 
1507 	log_debug("lease_id_format is: %s",
1508 		  lease_id_format == TOKEN_OCTAL ? "octal" : "hex");
1509 
1510         token = next_token(&val, &len, cfile);
1511         if (token != SEMI) {
1512                 parse_warn(cfile, "corrupt lease file; expecting a semicolon");
1513                 skip_to_semi(cfile);
1514                 return;
1515         }
1516 }
1517 
1518 /*!
1519  *
1520  * \brief Parse allow and deny statements
1521  *
1522  * This function handles the common processing code for permit and deny
1523  * statements in the parse_pool_statement and parse_pool6_statement functions.
1524  * It reads in the configuration and constructs a new permit structure that it
1525  * attachs to the permit_head passed in from the caller.
1526  *
1527  * The allow or deny token should already be consumed, this function expects
1528  * one of the following:
1529  *   known-clients;
1530  *   unknown-clients;
1531  *   known clients;
1532  *   unknown clients;
1533  *   authenticated clients;
1534  *   unauthenticated clients;
1535  *   all clients;
1536  *   dynamic bootp clients;
1537  *   members of <class name>;
1538  *   after <date>;
1539  *
1540  * \param[in] cfile       = the configuration file being parsed
1541  * \param[in] permit_head = the head of the permit list (permit or prohibit)
1542  *			    to which to attach the newly created  permit structure
1543  * \param[in] is_allow    = 1 if this is being invoked for an allow statement
1544  *			  = 0 if this is being invoked for a deny statement
1545  * \param[in] valid_from   = pointers to the time values from the enclosing pool
1546  * \param[in] valid_until    or pond structure. One of them will be filled in if
1547  *			     the configuration includes an "after" clause
1548  */
1549 
get_permit(cfile,permit_head,is_allow,valid_from,valid_until)1550 void get_permit(cfile, permit_head, is_allow, valid_from, valid_until)
1551 	struct parse *cfile;
1552 	struct permit **permit_head;
1553 	int is_allow;
1554 	TIME *valid_from, *valid_until;
1555 {
1556 	enum dhcp_token token;
1557 	struct permit *permit;
1558 	const char *val;
1559 	int need_clients = 1;
1560 	TIME t;
1561 
1562 	/* Create our permit structure */
1563 	permit = new_permit(MDL);
1564 	if (!permit)
1565 		log_fatal ("no memory for permit");
1566 
1567 	token = next_token(&val, NULL, cfile);
1568 	switch (token) {
1569 	      case UNKNOWN:
1570 		permit->type = permit_unknown_clients;
1571 		break;
1572 
1573 	      case KNOWN_CLIENTS:
1574 		need_clients = 0;
1575 		permit->type = permit_known_clients;
1576 		break;
1577 
1578 	      case UNKNOWN_CLIENTS:
1579 		need_clients = 0;
1580 		permit->type = permit_unknown_clients;
1581 		break;
1582 
1583 	      case KNOWN:
1584 		permit->type = permit_known_clients;
1585 		break;
1586 
1587 	      case AUTHENTICATED:
1588 		permit->type = permit_authenticated_clients;
1589 		break;
1590 
1591 	      case UNAUTHENTICATED:
1592 		permit->type = permit_unauthenticated_clients;
1593 		break;
1594 
1595 	      case ALL:
1596 		permit->type = permit_all_clients;
1597 		break;
1598 
1599 	      case DYNAMIC:
1600 		permit->type = permit_dynamic_bootp_clients;
1601 		if (next_token (&val, NULL, cfile) != TOKEN_BOOTP) {
1602 			parse_warn (cfile, "expecting \"bootp\"");
1603 			skip_to_semi (cfile);
1604 			free_permit (permit, MDL);
1605 			return;
1606 		}
1607 		break;
1608 
1609 	      case MEMBERS:
1610 		need_clients = 0;
1611 		if (next_token (&val, NULL, cfile) != OF) {
1612 			parse_warn (cfile, "expecting \"of\"");
1613 			skip_to_semi (cfile);
1614 			free_permit (permit, MDL);
1615 			return;
1616 		}
1617 		if (next_token (&val, NULL, cfile) != STRING) {
1618 			parse_warn (cfile, "expecting class name.");
1619 			skip_to_semi (cfile);
1620 			free_permit (permit, MDL);
1621 			return;
1622 		}
1623 		permit->type = permit_class;
1624 		permit->class = NULL;
1625 		find_class(&permit->class, val, MDL);
1626 		if (!permit->class)
1627 			parse_warn(cfile, "no such class: %s", val);
1628 		break;
1629 
1630 	      case AFTER:
1631 		need_clients = 0;
1632 		if (*valid_from || *valid_until) {
1633 			parse_warn(cfile, "duplicate \"after\" clause.");
1634 			skip_to_semi(cfile);
1635 			free_permit(permit, MDL);
1636 			return;
1637 		}
1638 		t = parse_date_core(cfile);
1639 		permit->type = permit_after;
1640 		permit->after = t;
1641 		if (is_allow) {
1642 			*valid_from = t;
1643 		} else {
1644 			*valid_until = t;
1645 		}
1646 		break;
1647 
1648 	      default:
1649 		parse_warn (cfile, "expecting permit type.");
1650 		skip_to_semi (cfile);
1651 		free_permit (permit, MDL);
1652 		return;
1653 	}
1654 
1655 	/*
1656 	 * The need_clients flag is set if we are expecting the
1657 	 * CLIENTS token
1658 	 */
1659 	if ((need_clients != 0)  &&
1660 	    (next_token (&val, NULL, cfile) != CLIENTS)) {
1661 		parse_warn (cfile, "expecting \"clients\"");
1662 		skip_to_semi (cfile);
1663 		free_permit (permit, MDL);
1664 		return;
1665 	}
1666 
1667 	while (*permit_head)
1668 		permit_head = &((*permit_head)->next);
1669 	*permit_head = permit;
1670 	parse_semi (cfile);
1671 
1672 	return;
1673 }
1674 
1675 /* Permit_list_match returns 1 if every element of the permit list in lhs
1676    also appears in rhs.   Note that this doesn't by itself mean that the
1677    two lists are equal - to check for equality, permit_list_match has to
1678    return 1 with (list1, list2) and with (list2, list1). */
1679 
permit_list_match(struct permit * lhs,struct permit * rhs)1680 int permit_list_match (struct permit *lhs, struct permit *rhs)
1681 {
1682 	struct permit *plp, *prp;
1683 	int matched;
1684 
1685 	if (!lhs)
1686 		return 1;
1687 	if (!rhs)
1688 		return 0;
1689 	for (plp = lhs; plp; plp = plp -> next) {
1690 		matched = 0;
1691 		for (prp = rhs; prp; prp = prp -> next) {
1692 			if (prp -> type == plp -> type &&
1693 			    (prp -> type != permit_class ||
1694 			     prp -> class == plp -> class)) {
1695 				matched = 1;
1696 				break;
1697 			}
1698 		}
1699 		if (!matched)
1700 			return 0;
1701 	}
1702 	return 1;
1703 }
1704 
1705 /*!
1706  *
1707  * \brief Parse a pool statement
1708  *
1709  * Pool statements are used to group declarations and permit & deny information
1710  * with a specific address range.  They must be declared within a shared network
1711  * or subnet and there may be multiple pools withing a shared network or subnet.
1712  * Each pool may have a different set of permit or deny options.
1713  *
1714  * \param[in] cfile = the configuration file being parsed
1715  * \param[in] group = the group structure for this pool
1716  * \param[in] type  = the type of the enclosing statement.  This must be
1717  *		      SHARED_NET_DECL or SUBNET_DECL for this function.
1718  *
1719  * \return
1720  * void - This function either parses the statement and updates the structures
1721  *        or it generates an error message and possible halts the program if
1722  *        it encounters a problem.
1723  */
parse_pool_statement(cfile,group,type)1724 void parse_pool_statement (cfile, group, type)
1725 	struct parse *cfile;
1726 	struct group *group;
1727 	int type;
1728 {
1729 	enum dhcp_token token;
1730 	const char *val;
1731 	int done = 0;
1732 	struct pool *pool, **p, *pp;
1733 	int declaration = 0;
1734 	isc_result_t status;
1735 	struct lease *lpchain = NULL, *lp;
1736 
1737 	pool = NULL;
1738 	status = pool_allocate(&pool, MDL);
1739 	if (status != ISC_R_SUCCESS)
1740 		log_fatal ("no memory for pool: %s",
1741 			   isc_result_totext (status));
1742 
1743 	if (type == SUBNET_DECL)
1744 		shared_network_reference(&pool->shared_network,
1745 					 group->subnet->shared_network,
1746 					 MDL);
1747 	else if (type == SHARED_NET_DECL)
1748 		shared_network_reference(&pool->shared_network,
1749 					 group->shared_network, MDL);
1750 	else {
1751 		parse_warn(cfile, "Dynamic pools are only valid inside "
1752 				  "subnet or shared-network statements.");
1753 		skip_to_semi(cfile);
1754 		return;
1755 	}
1756 
1757 	if (pool->shared_network == NULL ||
1758             !clone_group(&pool->group, pool->shared_network->group, MDL))
1759 		log_fatal("can't clone pool group.");
1760 
1761 #if defined (FAILOVER_PROTOCOL)
1762 	/* Inherit the failover peer from the shared network. */
1763 	if (pool->shared_network->failover_peer)
1764 	    dhcp_failover_state_reference
1765 		    (&pool->failover_peer,
1766 		     pool->shared_network->failover_peer, MDL);
1767 #endif
1768 
1769 	if (!parse_lbrace(cfile)) {
1770 		pool_dereference(&pool, MDL);
1771 		return;
1772 	}
1773 
1774 	do {
1775 		token = peek_token(&val, NULL, cfile);
1776 		switch (token) {
1777 		      case TOKEN_NO:
1778 			skip_token(&val, NULL, cfile);
1779 			token = next_token(&val, NULL, cfile);
1780 			if (token != FAILOVER ||
1781 			    (token = next_token(&val, NULL, cfile)) != PEER) {
1782 				parse_warn(cfile,
1783 					   "expecting \"failover peer\".");
1784 				skip_to_semi(cfile);
1785 				continue;
1786 			}
1787 #if defined (FAILOVER_PROTOCOL)
1788 			if (pool->failover_peer)
1789 				dhcp_failover_state_dereference
1790 					(&pool->failover_peer, MDL);
1791 #endif
1792 			break;
1793 
1794 #if defined (FAILOVER_PROTOCOL)
1795 		      case FAILOVER:
1796 			skip_token(&val, NULL, cfile);
1797 			token = next_token (&val, NULL, cfile);
1798 			if (token != PEER) {
1799 				parse_warn(cfile, "expecting 'peer'.");
1800 				skip_to_semi(cfile);
1801 				break;
1802 			}
1803 			token = next_token(&val, NULL, cfile);
1804 			if (token != STRING) {
1805 				parse_warn(cfile, "expecting string.");
1806 				skip_to_semi(cfile);
1807 				break;
1808 			}
1809 			if (pool->failover_peer)
1810 				dhcp_failover_state_dereference
1811 					(&pool->failover_peer, MDL);
1812 			status = find_failover_peer(&pool->failover_peer,
1813 						    val, MDL);
1814 			if (status != ISC_R_SUCCESS)
1815 				parse_warn(cfile,
1816 					   "failover peer %s: %s", val,
1817 					   isc_result_totext (status));
1818 			else
1819 				pool->failover_peer->pool_count++;
1820 			parse_semi(cfile);
1821 			break;
1822 #endif
1823 
1824 		      case RANGE:
1825 			skip_token(&val, NULL, cfile);
1826 			parse_address_range (cfile, group, type,
1827 					     pool, &lpchain);
1828 			break;
1829 		      case ALLOW:
1830 			skip_token(&val, NULL, cfile);
1831 			get_permit(cfile, &pool->permit_list, 1,
1832 				   &pool->valid_from, &pool->valid_until);
1833 			break;
1834 
1835 		      case DENY:
1836 			skip_token(&val, NULL, cfile);
1837 			get_permit(cfile, &pool->prohibit_list, 0,
1838 				   &pool->valid_from, &pool->valid_until);
1839 			break;
1840 
1841 		      case RBRACE:
1842 			skip_token(&val, NULL, cfile);
1843 			done = 1;
1844 			break;
1845 
1846 		      case END_OF_FILE:
1847 			/*
1848 			 * We can get to END_OF_FILE if, for instance,
1849 			 * the parse_statement() reads all available tokens
1850 			 * and leaves us at the end.
1851 			 */
1852 			parse_warn(cfile, "unexpected end of file");
1853 			goto cleanup;
1854 
1855 		      default:
1856 			declaration = parse_statement(cfile, pool->group,
1857 						      POOL_DECL, NULL,
1858 						       declaration);
1859 			break;
1860 		}
1861 	} while (!done);
1862 
1863 	/* See if there's already a pool into which we can merge this one. */
1864 	for (pp = pool->shared_network->pools; pp; pp = pp->next) {
1865 		if (pp->group->statements != pool->group->statements)
1866 			continue;
1867 #if defined (FAILOVER_PROTOCOL)
1868 		if (pool->failover_peer != pp->failover_peer)
1869 			continue;
1870 #endif
1871 		if (!permit_list_match(pp->permit_list,
1872 				       pool->permit_list) ||
1873 		    !permit_list_match(pool->permit_list,
1874 				       pp->permit_list) ||
1875 		    !permit_list_match(pp->prohibit_list,
1876 				       pool->prohibit_list) ||
1877 		    !permit_list_match(pool->prohibit_list,
1878 				       pp->prohibit_list))
1879 			continue;
1880 
1881 		/* Okay, we can merge these two pools.    All we have to
1882 		   do is fix up the leases, which all point to their pool. */
1883 		for (lp = lpchain; lp; lp = lp->next) {
1884 			pool_dereference(&lp->pool, MDL);
1885 			pool_reference(&lp->pool, pp, MDL);
1886 		}
1887 
1888 #if defined (BINARY_LEASES)
1889 		/* If we are doing binary leases we also need to add the
1890 		 * addresses in for leasechain allocation.
1891 		 */
1892 		pp->lease_count += pool->lease_count;
1893 #endif
1894 
1895 		break;
1896 	}
1897 
1898 	/* If we didn't succeed in merging this pool into another, put
1899 	   it on the list. */
1900 	if (!pp) {
1901 		p = &pool->shared_network->pools;
1902 		for (; *p; p = &((*p)->next))
1903 			;
1904 		pool_reference(p, pool, MDL);
1905 	}
1906 
1907 	/* Don't allow a pool declaration with no addresses, since it is
1908 	   probably a configuration error. */
1909 	if (!lpchain) {
1910 		parse_warn(cfile, "Pool declaration with no address range.");
1911 		log_error("Pool declarations must always contain at least");
1912 		log_error("one range statement.");
1913 	}
1914 
1915 cleanup:
1916 	/* Dereference the lease chain. */
1917 	lp = NULL;
1918 	while (lpchain) {
1919 		lease_reference(&lp, lpchain, MDL);
1920 		lease_dereference(&lpchain, MDL);
1921 		if (lp->next) {
1922 			lease_reference(&lpchain, lp->next, MDL);
1923 			lease_dereference(&lp->next, MDL);
1924 			lease_dereference(&lp, MDL);
1925 		}
1926 	}
1927 	pool_dereference(&pool, MDL);
1928 }
1929 
1930 /* Expect a left brace; if there isn't one, skip over the rest of the
1931    statement and return zero; otherwise, return 1. */
1932 
parse_lbrace(cfile)1933 int parse_lbrace (cfile)
1934 	struct parse *cfile;
1935 {
1936 	enum dhcp_token token;
1937 	const char *val;
1938 
1939 	token = next_token (&val, (unsigned *)0, cfile);
1940 	if (token != LBRACE) {
1941 		parse_warn (cfile, "expecting left brace.");
1942 		skip_to_semi (cfile);
1943 		return 0;
1944 	}
1945 	return 1;
1946 }
1947 
1948 
1949 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1950 
parse_host_declaration(cfile,group)1951 void parse_host_declaration (cfile, group)
1952 	struct parse *cfile;
1953 	struct group *group;
1954 {
1955 	const char *val;
1956 	enum dhcp_token token;
1957 	struct host_decl *host;
1958 	char *name;
1959 	int declaration = 0;
1960 	int dynamicp = 0;
1961 	int deleted = 0;
1962 	isc_result_t status;
1963 	int known;
1964 	struct option *option;
1965 	struct expression *expr = NULL;
1966 
1967 	name = parse_host_name (cfile);
1968 	if (!name) {
1969 		parse_warn (cfile, "expecting a name for host declaration.");
1970 		skip_to_semi (cfile);
1971 		return;
1972 	}
1973 
1974 	host = (struct host_decl *)0;
1975 	status = host_allocate (&host, MDL);
1976 	if (status != ISC_R_SUCCESS)
1977 		log_fatal ("can't allocate host decl struct %s: %s",
1978 			   name, isc_result_totext (status));
1979 	host -> name = name;
1980 	if (!clone_group (&host -> group, group, MDL)) {
1981 		log_fatal ("can't clone group for host %s", name);
1982 	      boom:
1983 		host_dereference (&host, MDL);
1984 		return;
1985 	}
1986 
1987 	if (!parse_lbrace (cfile))
1988 		goto boom;
1989 
1990 	do {
1991 		token = peek_token (&val, (unsigned *)0, cfile);
1992 		if (token == RBRACE) {
1993 			skip_token(&val, (unsigned *)0, cfile);
1994 			break;
1995 		}
1996 		if (token == END_OF_FILE) {
1997 			skip_token(&val, (unsigned *)0, cfile);
1998 			parse_warn (cfile, "unexpected end of file");
1999 			break;
2000 		}
2001 		/* If the host declaration was created by the server,
2002 		   remember to save it. */
2003 		if (token == DYNAMIC) {
2004 			dynamicp = 1;
2005 			skip_token(&val, (unsigned *)0, cfile);
2006 			if (!parse_semi (cfile))
2007 				break;
2008 			continue;
2009 		}
2010 		/* If the host declaration was created by the server,
2011 		   remember to save it. */
2012 		if (token == TOKEN_DELETED) {
2013 			deleted = 1;
2014 			skip_token(&val, (unsigned *)0, cfile);
2015 			if (!parse_semi (cfile))
2016 				break;
2017 			continue;
2018 		}
2019 
2020 		if (token == GROUP) {
2021 			struct group_object *go;
2022 			skip_token(&val, (unsigned *)0, cfile);
2023 			token = next_token (&val, (unsigned *)0, cfile);
2024 			if (token != STRING && !is_identifier (token)) {
2025 				parse_warn (cfile,
2026 					    "expecting string or identifier.");
2027 				skip_to_rbrace (cfile, 1);
2028 				break;
2029 			}
2030 			go = (struct group_object *)0;
2031 			if (!group_hash_lookup (&go, group_name_hash,
2032 						val, strlen (val), MDL)) {
2033 			    parse_warn (cfile, "unknown group %s in host %s",
2034 					val, host -> name);
2035 			} else {
2036 				if (host -> named_group)
2037 					group_object_dereference
2038 						(&host -> named_group, MDL);
2039 				group_object_reference (&host -> named_group,
2040 							go, MDL);
2041 				group_object_dereference (&go, MDL);
2042 			}
2043 			if (!parse_semi (cfile))
2044 				break;
2045 			continue;
2046 		}
2047 
2048 		if (token == UID) {
2049 			const char *s;
2050 			unsigned char *t = 0;
2051 			unsigned len;
2052 
2053 			skip_token(&val, (unsigned *)0, cfile);
2054 			if (host->client_identifier.len != 0) {
2055 				char buf[256];
2056 				print_hex_or_string(host->client_identifier.len,
2057 						   host->client_identifier.data,
2058 						   sizeof(buf) - 1, buf);
2059 				parse_warn(cfile,
2060 					   "Host '%s' already has a uid '%s'",
2061 					   host->name, buf);
2062 				skip_to_rbrace(cfile, 1);
2063 				break;
2064 			}
2065 
2066 			/* See if it's a string or a cshl. */
2067 			token = peek_token (&val, (unsigned *)0, cfile);
2068 			if (token == STRING) {
2069 				skip_token(&val, &len, cfile);
2070 				s = val;
2071 				host -> client_identifier.terminated = 1;
2072 			} else {
2073 				len = 0;
2074 				t = parse_numeric_aggregate
2075 					(cfile,
2076 					 (unsigned char *)0, &len, ':', 16, 8);
2077 				if (!t) {
2078 					parse_warn (cfile,
2079 						    "expecting hex list.");
2080 					skip_to_semi (cfile);
2081 				}
2082 				s = (const char *)t;
2083 			}
2084 			if (!buffer_allocate
2085 			    (&host -> client_identifier.buffer,
2086 			     len + host -> client_identifier.terminated, MDL))
2087 				log_fatal ("no memory for uid for host %s.",
2088 					   host -> name);
2089 			host -> client_identifier.data =
2090 				host -> client_identifier.buffer -> data;
2091 			host -> client_identifier.len = len;
2092 			memcpy (host -> client_identifier.buffer -> data, s,
2093 				len + host -> client_identifier.terminated);
2094 			if (t)
2095 				dfree (t, MDL);
2096 
2097 			if (!parse_semi (cfile))
2098 				break;
2099 			continue;
2100 		}
2101 
2102 		if (token == HOST_IDENTIFIER) {
2103 			if (host->host_id_option != NULL) {
2104 				parse_warn(cfile,
2105 					   "only one host-identifier allowed "
2106 					   "per host");
2107 				skip_to_rbrace(cfile, 1);
2108 				break;
2109 			}
2110 	      		skip_token(&val, NULL, cfile);
2111 			token = next_token(&val, NULL, cfile);
2112 			if (token == V6RELOPT) {
2113 				token = next_token(&val, NULL, cfile);
2114 				if (token != NUMBER) {
2115 					parse_warn(cfile,
2116 						   "host-identifier v6relopt "
2117 						   "must have a number");
2118 					skip_to_rbrace(cfile, 1);
2119 					break;
2120 				}
2121 				host->relays = atoi(val);
2122 				if (host->relays < 0) {
2123 					parse_warn(cfile,
2124 						   "host-identifier v6relopt "
2125 						   "must have a number >= 0");
2126 					skip_to_rbrace(cfile, 1);
2127 					break;
2128 				}
2129 			} else if (token != OPTION) {
2130 				parse_warn(cfile,
2131 					   "host-identifier must be an option"
2132 					   " or v6relopt");
2133 				skip_to_rbrace(cfile, 1);
2134 				break;
2135 			}
2136 			known = 0;
2137 			option = NULL;
2138 			status = parse_option_name(cfile, 1, &known, &option);
2139 			if ((status != ISC_R_SUCCESS) || (option == NULL)) {
2140 				break;
2141 			}
2142 			if (!known) {
2143 				parse_warn(cfile, "unknown option %s.%s",
2144 					   option->universe->name,
2145 					   option->name);
2146 				skip_to_rbrace(cfile, 1);
2147 				break;
2148 			}
2149 
2150                         if (! parse_option_data(&expr, cfile, 1, option)) {
2151 		        	skip_to_rbrace(cfile, 1);
2152 		        	option_dereference(&option, MDL);
2153 		        	break;
2154                         }
2155 
2156 			if (!parse_semi(cfile)) {
2157 				skip_to_rbrace(cfile, 1);
2158 				expression_dereference(&expr, MDL);
2159 				option_dereference(&option, MDL);
2160 				break;
2161 			}
2162 
2163 			option_reference(&host->host_id_option, option, MDL);
2164 			option_dereference(&option, MDL);
2165 			data_string_copy(&host->host_id,
2166 					 &expr->data.const_data, MDL);
2167 			expression_dereference(&expr, MDL);
2168 			continue;
2169 		}
2170 
2171 		declaration = parse_statement(cfile, host->group, HOST_DECL,
2172                                               host, declaration);
2173 	} while (1);
2174 
2175 	if (deleted) {
2176 		struct host_decl *hp = (struct host_decl *)0;
2177 		if (host_hash_lookup (&hp, host_name_hash,
2178 				      (unsigned char *)host -> name,
2179 				      strlen (host -> name), MDL)) {
2180 			delete_host (hp, 0);
2181 			host_dereference (&hp, MDL);
2182 		}
2183 	} else {
2184 		if (host -> named_group && host -> named_group -> group) {
2185 			if (host -> group -> statements ||
2186 			    (host -> group -> authoritative !=
2187 			     host -> named_group -> group -> authoritative)) {
2188 				if (host -> group -> next)
2189 				    group_dereference (&host -> group -> next,
2190 						       MDL);
2191 				group_reference (&host -> group -> next,
2192 						 host -> named_group -> group,
2193 						 MDL);
2194 			} else {
2195 				group_dereference (&host -> group, MDL);
2196 				group_reference (&host -> group,
2197 						 host -> named_group -> group,
2198 						 MDL);
2199 			}
2200 		}
2201 
2202 		if (dynamicp)
2203 			host -> flags |= HOST_DECL_DYNAMIC;
2204 		else
2205 			host -> flags |= HOST_DECL_STATIC;
2206 
2207 		status = enter_host (host, dynamicp, 0);
2208 		if (status != ISC_R_SUCCESS)
2209 			parse_warn (cfile, "host %s: %s", host -> name,
2210 				    isc_result_totext (status));
2211 	}
2212 	host_dereference (&host, MDL);
2213 }
2214 
2215 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
2216 */
2217 
parse_class_declaration(cp,cfile,group,type)2218 int parse_class_declaration (cp, cfile, group, type)
2219 	struct class **cp;
2220 	struct parse *cfile;
2221 	struct group *group;
2222 	int type;
2223 {
2224 	const char *val;
2225 	enum dhcp_token token;
2226 	struct class *class = NULL, *pc = NULL;
2227 	int declaration = 0;
2228 	int lose = 0;
2229 	struct data_string data;
2230 	char *name;
2231 	const char *tname;
2232 	struct executable_statement *stmt = NULL;
2233 	int new = 1;
2234 	isc_result_t status = ISC_R_FAILURE;
2235 	int matchedonce = 0;
2236 	int submatchedonce = 0;
2237 	unsigned code;
2238 
2239 	token = next_token (&val, NULL, cfile);
2240 	if (token != STRING) {
2241 		parse_warn (cfile, "Expecting class name");
2242 		skip_to_semi (cfile);
2243 		return 0;
2244 	}
2245 
2246 	/* See if there's already a class with the specified name. */
2247 	find_class (&pc, val, MDL);
2248 
2249 	/* If it is a class, we're updating it.  If it's any of the other
2250 	 * types (subclass, vendor or user class), the named class is a
2251 	 * reference to the parent class so its mandatory.
2252 	 */
2253 	if (pc && (type == CLASS_TYPE_CLASS)) {
2254 		class_reference(&class, pc, MDL);
2255 		new = 0;
2256 		class_dereference(&pc, MDL);
2257 	} else if (!pc && (type != CLASS_TYPE_CLASS)) {
2258 		parse_warn(cfile, "no class named %s", val);
2259 		skip_to_semi(cfile);
2260 		return 0;
2261 	}
2262 
2263 	/* The old vendor-class and user-class declarations had an implicit
2264 	   match.   We don't do the implicit match anymore.   Instead, for
2265 	   backward compatibility, we have an implicit-vendor-class and an
2266 	   implicit-user-class.   vendor-class and user-class declarations
2267 	   are turned into subclasses of the implicit classes, and the
2268 	   submatch expression of the implicit classes extracts the contents of
2269 	   the vendor class or user class. */
2270 	if ((type == CLASS_TYPE_VENDOR) || (type == CLASS_TYPE_USER)) {
2271 		data.len = strlen (val);
2272 		data.buffer = NULL;
2273 		if (!buffer_allocate (&data.buffer, data.len + 1, MDL))
2274 			log_fatal ("no memory for class name.");
2275 		data.data = &data.buffer -> data [0];
2276 		data.terminated = 1;
2277 
2278 		tname = (type == CLASS_TYPE_VENDOR) ?
2279 		  "implicit-vendor-class" : "implicit-user-class";
2280 
2281 	} else if (type == CLASS_TYPE_CLASS) {
2282 		tname = val;
2283 	} else {
2284 		tname = NULL;
2285 	}
2286 
2287 	if (tname) {
2288 		name = dmalloc (strlen (tname) + 1, MDL);
2289 		if (!name)
2290 			log_fatal ("No memory for class name %s.", tname);
2291 		strcpy (name, tname);
2292 	} else
2293 		name = NULL;
2294 
2295 	/* If this is a straight subclass, parse the hash string. */
2296 	if (type == CLASS_TYPE_SUBCLASS) {
2297 		token = peek_token (&val, NULL, cfile);
2298 		if (token == STRING) {
2299 			skip_token(&val, &data.len, cfile);
2300 			data.buffer = NULL;
2301 
2302 			if (!buffer_allocate (&data.buffer,
2303 					      data.len + 1, MDL)) {
2304 				if (pc)
2305 					class_dereference (&pc, MDL);
2306 
2307 				return 0;
2308 			}
2309 			data.terminated = 1;
2310 			data.data = &data.buffer -> data [0];
2311 			memcpy ((char *)data.buffer -> data, val,
2312 				data.len + 1);
2313 		} else if (token == NUMBER_OR_NAME || token == NUMBER) {
2314 			memset (&data, 0, sizeof data);
2315 			if (!parse_cshl (&data, cfile)) {
2316 				if (pc)
2317 					class_dereference (&pc, MDL);
2318 				return 0;
2319 			}
2320 		} else {
2321 			parse_warn (cfile, "Expecting string or hex list.");
2322 			if (pc)
2323 				class_dereference (&pc, MDL);
2324 			return 0;
2325 		}
2326 	}
2327 
2328 	/* See if there's already a class in the hash table matching the
2329 	   hash data. */
2330 	if (type != CLASS_TYPE_CLASS)
2331 		class_hash_lookup (&class, pc -> hash,
2332 				   (const char *)data.data, data.len, MDL);
2333 
2334 	/* If we didn't find an existing class, allocate a new one. */
2335 	if (!class) {
2336 		/* Allocate the class structure... */
2337 		if (type == CLASS_TYPE_SUBCLASS) {
2338 			status = subclass_allocate (&class, MDL);
2339 		} else {
2340 			status = class_allocate (&class, MDL);
2341 		}
2342 		if (pc) {
2343 			group_reference (&class -> group, pc -> group, MDL);
2344 			class_reference (&class -> superclass, pc, MDL);
2345 			class -> lease_limit = pc -> lease_limit;
2346 			if (class -> lease_limit) {
2347 				class -> billed_leases =
2348 					dmalloc (class -> lease_limit *
2349 						 sizeof (struct lease *), MDL);
2350 				if (!class -> billed_leases)
2351 					log_fatal ("no memory for billing");
2352 				memset (class -> billed_leases, 0,
2353 					(class -> lease_limit *
2354 					 sizeof (struct lease *)));
2355 			}
2356 			data_string_copy (&class -> hash_string, &data, MDL);
2357 			if (!pc -> hash &&
2358 			    !class_new_hash (&pc->hash, SCLASS_HASH_SIZE, MDL))
2359 				log_fatal ("No memory for subclass hash.");
2360 			class_hash_add (pc -> hash,
2361 					(const char *)class -> hash_string.data,
2362 					class -> hash_string.len,
2363 					(void *)class, MDL);
2364 		} else {
2365 			if (class->group)
2366 				group_dereference(&class->group, MDL);
2367 			if (!clone_group (&class -> group, group, MDL))
2368 				log_fatal ("no memory to clone class group.");
2369 		}
2370 
2371 		/* If this is an implicit vendor or user class, add a
2372 		   statement that causes the vendor or user class ID to
2373 		   be sent back in the reply. */
2374 		if (type == CLASS_TYPE_VENDOR || type == CLASS_TYPE_USER) {
2375 			stmt = NULL;
2376 			if (!executable_statement_allocate (&stmt, MDL))
2377 				log_fatal ("no memory for class statement.");
2378 			stmt -> op = supersede_option_statement;
2379 			if (option_cache_allocate (&stmt -> data.option,
2380 						   MDL)) {
2381 				stmt -> data.option -> data = data;
2382 				code = (type == CLASS_TYPE_VENDOR)
2383 					? DHO_VENDOR_CLASS_IDENTIFIER
2384 					: DHO_USER_CLASS;
2385 				option_code_hash_lookup(
2386 						&stmt->data.option->option,
2387 							dhcp_universe.code_hash,
2388 							&code, 0, MDL);
2389 			}
2390 			class -> statements = stmt;
2391 		}
2392 
2393 		/* Save the name, if there is one. */
2394 		if (class->name != NULL)
2395 			dfree(class->name, MDL);
2396 		class->name = name;
2397 	}
2398 
2399 	if (type != CLASS_TYPE_CLASS)
2400 		data_string_forget(&data, MDL);
2401 
2402 	/* Spawned classes don't have to have their own settings. */
2403 	if (class -> superclass) {
2404 		token = peek_token (&val, NULL, cfile);
2405 		if (token == SEMI) {
2406 			skip_token(&val, NULL, cfile);
2407 
2408 			if (cp)
2409 				status = class_reference (cp, class, MDL);
2410 			class_dereference (&class, MDL);
2411 			if (pc)
2412 				class_dereference (&pc, MDL);
2413 			return cp ? (status == ISC_R_SUCCESS) : 1;
2414 		}
2415 		/* Give the subclass its own group. */
2416 		if (!clone_group (&class -> group, class -> group, MDL))
2417 			log_fatal ("can't clone class group.");
2418 
2419 	}
2420 
2421 	if (!parse_lbrace (cfile)) {
2422 		class_dereference (&class, MDL);
2423 		if (pc)
2424 			class_dereference (&pc, MDL);
2425 		return 0;
2426 	}
2427 
2428 	do {
2429 		token = peek_token (&val, NULL, cfile);
2430 		if (token == RBRACE) {
2431 			skip_token(&val, NULL, cfile);
2432 			break;
2433 		} else if (token == END_OF_FILE) {
2434 			skip_token(&val, NULL, cfile);
2435 			parse_warn (cfile, "unexpected end of file");
2436 			break;
2437 		} else if (token == DYNAMIC) {
2438 			class->flags |= CLASS_DECL_DYNAMIC;
2439 			skip_token(&val, NULL, cfile);
2440 			if (!parse_semi (cfile))
2441 				break;
2442 			continue;
2443 		} else if (token == TOKEN_DELETED) {
2444 			class->flags |= CLASS_DECL_DELETED;
2445 			skip_token(&val, NULL, cfile);
2446 			if (!parse_semi (cfile))
2447 				break;
2448 			continue;
2449 		} else if (token == MATCH) {
2450 			if (pc) {
2451 				parse_warn (cfile,
2452 					    "invalid match in subclass.");
2453 				skip_to_semi (cfile);
2454 				break;
2455 			}
2456 			skip_token(&val, NULL, cfile);
2457 			token = peek_token (&val, NULL, cfile);
2458 			if (token != IF)
2459 				goto submatch;
2460 			skip_token(&val, NULL, cfile);
2461 			if (matchedonce) {
2462 				parse_warn(cfile, "A class may only have "
2463 						  "one 'match if' clause.");
2464 				skip_to_semi(cfile);
2465 				break;
2466 			}
2467 			matchedonce = 1;
2468 			if (class->expr)
2469 				expression_dereference(&class->expr, MDL);
2470 			if (!parse_boolean_expression (&class->expr, cfile,
2471 						       &lose)) {
2472 				if (!lose) {
2473 					parse_warn (cfile,
2474 						    "expecting boolean expr.");
2475 					skip_to_semi (cfile);
2476 				}
2477 			} else {
2478 #if defined (DEBUG_EXPRESSION_PARSE)
2479 				print_expression ("class match",
2480 						  class -> expr);
2481 #endif
2482 				parse_semi (cfile);
2483 			}
2484 		} else if (token == SPAWN) {
2485 			skip_token(&val, NULL, cfile);
2486 			if (pc) {
2487 				parse_warn (cfile,
2488 					    "invalid spawn in subclass.");
2489 				skip_to_semi (cfile);
2490 				break;
2491 			}
2492 			class -> spawning = 1;
2493 			token = next_token (&val, NULL, cfile);
2494 			if (token != WITH) {
2495 				parse_warn (cfile,
2496 					    "expecting with after spawn");
2497 				skip_to_semi (cfile);
2498 				break;
2499 			}
2500 		      submatch:
2501 			if (submatchedonce) {
2502 				parse_warn (cfile,
2503 					    "can't override existing %s.",
2504 					    "submatch/spawn");
2505 				skip_to_semi (cfile);
2506 				break;
2507 			}
2508 			submatchedonce = 1;
2509 			if (class->submatch)
2510 				expression_dereference(&class->submatch, MDL);
2511 			if (!parse_data_expression (&class -> submatch,
2512 						    cfile, &lose)) {
2513 				if (!lose) {
2514 					parse_warn (cfile,
2515 						    "expecting data expr.");
2516 					skip_to_semi (cfile);
2517 				}
2518 			} else {
2519 #if defined (DEBUG_EXPRESSION_PARSE)
2520 				print_expression ("class submatch",
2521 						  class -> submatch);
2522 #endif
2523 				parse_semi (cfile);
2524 			}
2525 		} else if (token == LEASE) {
2526 			skip_token(&val, NULL, cfile);
2527 			token = next_token (&val, NULL, cfile);
2528 			if (token != LIMIT) {
2529 				parse_warn (cfile, "expecting \"limit\"");
2530 				if (token != SEMI)
2531 					skip_to_semi (cfile);
2532 				break;
2533 			}
2534 			token = next_token (&val, NULL, cfile);
2535 			if (token != NUMBER) {
2536 				parse_warn (cfile, "expecting a number");
2537 				if (token != SEMI)
2538 					skip_to_semi (cfile);
2539 				break;
2540 			}
2541 			class -> lease_limit = atoi (val);
2542 			if (class->billed_leases)
2543 				dfree(class->billed_leases, MDL);
2544 			class -> billed_leases =
2545 				dmalloc (class -> lease_limit *
2546 					 sizeof (struct lease *), MDL);
2547 			if (!class -> billed_leases)
2548 				log_fatal ("no memory for billed leases.");
2549 			memset (class -> billed_leases, 0,
2550 				(class -> lease_limit *
2551 				 sizeof (struct lease *)));
2552 			have_billing_classes = 1;
2553 			parse_semi (cfile);
2554 		} else {
2555 			declaration = parse_statement (cfile, class -> group,
2556 						       CLASS_DECL, NULL,
2557 						       declaration);
2558 		}
2559 	} while (1);
2560 
2561 	if (class->flags & CLASS_DECL_DELETED) {
2562 		if (type == CLASS_TYPE_CLASS) {
2563 			struct class *theclass = NULL;
2564 
2565 			status = find_class(&theclass, class->name, MDL);
2566 			if (status == ISC_R_SUCCESS) {
2567 				delete_class(theclass, 0);
2568 				class_dereference(&theclass, MDL);
2569 			}
2570 		} else {
2571 			class_hash_delete(pc->hash,
2572 					  (char *)class->hash_string.data,
2573 					  class->hash_string.len, MDL);
2574 		}
2575 	} else if (type == CLASS_TYPE_CLASS && new) {
2576 		if (!collections -> classes)
2577 			class_reference (&collections -> classes, class, MDL);
2578 		else {
2579 			struct class *c;
2580 			for (c = collections -> classes;
2581 			     c -> nic; c = c -> nic)
2582 				;
2583 			class_reference (&c -> nic, class, MDL);
2584 		}
2585 	}
2586 
2587 	if (cp)				/* should always be 0??? */
2588 		status = class_reference (cp, class, MDL);
2589 	class_dereference (&class, MDL);
2590 	if (pc)
2591 		class_dereference (&pc, MDL);
2592 	return cp ? (status == ISC_R_SUCCESS) : 1;
2593 }
2594 
2595 /* shared-network-declaration :==
2596 			hostname LBRACE declarations parameters RBRACE */
2597 
parse_shared_net_declaration(cfile,group)2598 void parse_shared_net_declaration (cfile, group)
2599 	struct parse *cfile;
2600 	struct group *group;
2601 {
2602 	const char *val;
2603 	enum dhcp_token token;
2604 	struct shared_network *share;
2605 	char *name;
2606 	int declaration = 0;
2607 	isc_result_t status;
2608 
2609 	share = (struct shared_network *)0;
2610 	status = shared_network_allocate (&share, MDL);
2611 	if (status != ISC_R_SUCCESS)
2612 		log_fatal ("Can't allocate shared subnet: %s",
2613 			   isc_result_totext (status));
2614 	if (clone_group (&share -> group, group, MDL) == 0) {
2615 		log_fatal ("Can't clone group for shared net");
2616 	}
2617 	shared_network_reference (&share -> group -> shared_network,
2618 				  share, MDL);
2619 
2620 	/* Get the name of the shared network... */
2621 	token = peek_token (&val, (unsigned *)0, cfile);
2622 	if (token == STRING) {
2623 		skip_token(&val, (unsigned *)0, cfile);
2624 
2625 		if (val [0] == 0) {
2626 			parse_warn (cfile, "zero-length shared network name");
2627 			val = "<no-name-given>";
2628 		}
2629 		name = dmalloc (strlen (val) + 1, MDL);
2630 		if (!name)
2631 			log_fatal ("no memory for shared network name");
2632 		strcpy (name, val);
2633 	} else {
2634 		name = parse_host_name (cfile);
2635 		if (!name) {
2636 			parse_warn (cfile,
2637 				     "expecting a name for shared-network");
2638 			skip_to_semi (cfile);
2639 			shared_network_dereference (&share, MDL);
2640 			return;
2641 		}
2642 	}
2643 	share -> name = name;
2644 
2645 	if (!parse_lbrace (cfile)) {
2646 		shared_network_dereference (&share, MDL);
2647 		return;
2648 	}
2649 
2650 	do {
2651 		token = peek_token (&val, (unsigned *)0, cfile);
2652 		if (token == RBRACE) {
2653 			skip_token(&val, (unsigned *)0, cfile);
2654 			if (!share -> subnets)
2655 				parse_warn (cfile,
2656 					    "empty shared-network decl");
2657 			else
2658 				enter_shared_network (share);
2659 			shared_network_dereference (&share, MDL);
2660 			return;
2661 		} else if (token == END_OF_FILE) {
2662 			skip_token(&val, (unsigned *)0, cfile);
2663 			parse_warn (cfile, "unexpected end of file");
2664 			break;
2665 		} else if (token == INTERFACE) {
2666 			skip_token(&val, (unsigned *)0, cfile);
2667 			token = next_token (&val, (unsigned *)0, cfile);
2668 			new_shared_network_interface (cfile, share, val);
2669 			if (!parse_semi (cfile))
2670 				break;
2671 			continue;
2672 		}
2673 
2674 		declaration = parse_statement (cfile, share -> group,
2675 					       SHARED_NET_DECL,
2676 					       (struct host_decl *)0,
2677 					       declaration);
2678 	} while (1);
2679 	shared_network_dereference (&share, MDL);
2680 }
2681 
2682 
2683 static int
common_subnet_parsing(struct parse * cfile,struct shared_network * share,struct subnet * subnet)2684 common_subnet_parsing(struct parse *cfile,
2685 		      struct shared_network *share,
2686 		      struct subnet *subnet) {
2687 	enum dhcp_token token;
2688 	struct subnet *t, *u;
2689 	const char *val;
2690 	int declaration = 0;
2691 
2692 	enter_subnet(subnet);
2693 
2694 	if (!parse_lbrace(cfile)) {
2695 		subnet_dereference(&subnet, MDL);
2696 		return 0;
2697 	}
2698 
2699 	do {
2700 		token = peek_token(&val, NULL, cfile);
2701 		if (token == RBRACE) {
2702 			skip_token(&val, NULL, cfile);
2703 			break;
2704 		} else if (token == END_OF_FILE) {
2705 			skip_token(&val, NULL, cfile);
2706 			parse_warn (cfile, "unexpected end of file");
2707 			break;
2708 		} else if (token == INTERFACE) {
2709 			skip_token(&val, NULL, cfile);
2710 			token = next_token(&val, NULL, cfile);
2711 			new_shared_network_interface(cfile, share, val);
2712 			if (!parse_semi(cfile))
2713 				break;
2714 			continue;
2715 		}
2716 		declaration = parse_statement(cfile, subnet->group,
2717 					      SUBNET_DECL,
2718 					      NULL,
2719 					      declaration);
2720 	} while (1);
2721 
2722 	/* Add the subnet to the list of subnets in this shared net. */
2723 	if (share->subnets == NULL) {
2724 		subnet_reference(&share->subnets, subnet, MDL);
2725 	} else {
2726 		u = NULL;
2727 		for (t = share->subnets; t->next_sibling; t = t->next_sibling) {
2728 			if (subnet_inner_than(subnet, t, 0)) {
2729 				subnet_reference(&subnet->next_sibling, t, MDL);
2730 				if (u) {
2731 					subnet_dereference(&u->next_sibling,
2732 							   MDL);
2733 					subnet_reference(&u->next_sibling,
2734 							 subnet, MDL);
2735 				} else {
2736 					subnet_dereference(&share->subnets,
2737 							   MDL);
2738 					subnet_reference(&share->subnets,
2739 							 subnet, MDL);
2740 				}
2741 				subnet_dereference(&subnet, MDL);
2742 				return 1;
2743 			}
2744 			u = t;
2745 		}
2746 		subnet_reference(&t->next_sibling, subnet, MDL);
2747 	}
2748 	subnet_dereference(&subnet, MDL);
2749 	return 1;
2750 }
2751 
2752 /* subnet-declaration :==
2753 	net NETMASK netmask RBRACE parameters declarations LBRACE */
2754 
parse_subnet_declaration(cfile,share)2755 void parse_subnet_declaration (cfile, share)
2756 	struct parse *cfile;
2757 	struct shared_network *share;
2758 {
2759 	const char *val;
2760 	enum dhcp_token token;
2761 	struct subnet *subnet;
2762 	struct iaddr iaddr;
2763 	unsigned char addr [4];
2764 	unsigned len = sizeof addr;
2765 	isc_result_t status;
2766 
2767 	subnet = (struct subnet *)0;
2768 	status = subnet_allocate (&subnet, MDL);
2769 	if (status != ISC_R_SUCCESS)
2770 		log_fatal ("Allocation of new subnet failed: %s",
2771 			   isc_result_totext (status));
2772 	shared_network_reference (&subnet -> shared_network, share, MDL);
2773 
2774 	/*
2775 	 * If our parent shared network was implicitly created by the software,
2776 	 * and not explicitly configured by the user, then we actually put all
2777 	 * configuration scope in the parent (the shared network and subnet
2778 	 * share the same {}-level scope).
2779 	 *
2780 	 * Otherwise, we clone the parent group and continue as normal.
2781 	 */
2782 	if (share->flags & SHARED_IMPLICIT) {
2783 		group_reference(&subnet->group, share->group, MDL);
2784 	} else {
2785 		if (!clone_group(&subnet->group, share->group, MDL)) {
2786 			log_fatal("Allocation of group for new subnet failed.");
2787 		}
2788 	}
2789 	subnet_reference (&subnet -> group -> subnet, subnet, MDL);
2790 
2791 	/* Get the network number... */
2792 	if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2793 		subnet_dereference (&subnet, MDL);
2794 		return;
2795 	}
2796 	memcpy (iaddr.iabuf, addr, len);
2797 	iaddr.len = len;
2798 	subnet -> net = iaddr;
2799 
2800 	token = next_token (&val, (unsigned *)0, cfile);
2801 	if (token != NETMASK) {
2802 		parse_warn (cfile, "Expecting netmask");
2803 		skip_to_semi (cfile);
2804 		subnet_dereference (&subnet, MDL);
2805 		return;
2806 	}
2807 
2808 	/* Get the netmask... */
2809 	if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
2810 		subnet_dereference (&subnet, MDL);
2811 		return;
2812 	}
2813 	memcpy (iaddr.iabuf, addr, len);
2814 	iaddr.len = len;
2815 	subnet -> netmask = iaddr;
2816 
2817 	/* Validate the network number/netmask pair. */
2818 	if (host_addr (subnet -> net, subnet -> netmask)) {
2819 		char *maskstr;
2820 
2821 		/* dup it, since piaddr is re-entrant */
2822 		maskstr = strdup (piaddr (subnet -> netmask));
2823 		if (maskstr == NULL) {
2824 			log_fatal("Allocation of subnet maskstr failed: %s",
2825 			    piaddr (subnet -> net));
2826 		}
2827 
2828 		parse_warn (cfile,
2829 		   "subnet %s netmask %s: bad subnet number/mask combination.",
2830 			    piaddr (subnet -> net), maskstr);
2831 		free(maskstr);
2832 		subnet_dereference (&subnet, MDL);
2833 		skip_to_semi (cfile);
2834 		return;
2835 	}
2836 
2837 	common_subnet_parsing(cfile, share, subnet);
2838 }
2839 
2840 /* subnet6-declaration :==
2841 	net / bits RBRACE parameters declarations LBRACE */
2842 
2843 void
parse_subnet6_declaration(struct parse * cfile,struct shared_network * share)2844 parse_subnet6_declaration(struct parse *cfile, struct shared_network *share) {
2845 #if !defined(DHCPv6)
2846 	parse_warn(cfile, "No DHCPv6 support.");
2847 	skip_to_semi(cfile);
2848 #else /* defined(DHCPv6) */
2849 	struct subnet *subnet;
2850 	isc_result_t status;
2851 	enum dhcp_token token;
2852 	const char *val;
2853 	char *endp;
2854 	int ofs;
2855 	const static int mask[] = { 0x00, 0x80, 0xC0, 0xE0,
2856 				    0xF0, 0xF8, 0xFC, 0xFE };
2857 	struct iaddr iaddr;
2858 
2859 #if defined(DHCP4o6)
2860         if ((local_family != AF_INET6) && !dhcpv4_over_dhcpv6) {
2861                 parse_warn(cfile, "subnet6 statement is only supported "
2862 				  "in DHCPv6 and DHCPv4o6 modes.");
2863                 skip_to_semi(cfile);
2864                 return;
2865         }
2866 #else /* defined(DHCP4o6) */
2867 	if (local_family != AF_INET6) {
2868                 parse_warn(cfile, "subnet6 statement is only supported "
2869 				  "in DHCPv6 mode.");
2870                 skip_to_semi(cfile);
2871                 return;
2872         }
2873 #endif /* !defined(DHCP4o6) */
2874 
2875 	subnet = NULL;
2876 	status = subnet_allocate(&subnet, MDL);
2877 	if (status != ISC_R_SUCCESS) {
2878 		log_fatal("Allocation of new subnet failed: %s",
2879 			  isc_result_totext(status));
2880 	}
2881 	shared_network_reference(&subnet->shared_network, share, MDL);
2882 
2883 	/*
2884 	 * If our parent shared network was implicitly created by the software,
2885 	 * and not explicitly configured by the user, then we actually put all
2886 	 * configuration scope in the parent (the shared network and subnet
2887 	 * share the same {}-level scope).
2888 	 *
2889 	 * Otherwise, we clone the parent group and continue as normal.
2890 	 */
2891 	if (share->flags & SHARED_IMPLICIT) {
2892 		group_reference(&subnet->group, share->group, MDL);
2893 	} else {
2894 		if (!clone_group(&subnet->group, share->group, MDL)) {
2895 			log_fatal("Allocation of group for new subnet failed.");
2896 		}
2897 	}
2898 	subnet_reference(&subnet->group->subnet, subnet, MDL);
2899 
2900 	if (!parse_ip6_addr(cfile, &subnet->net)) {
2901 		subnet_dereference(&subnet, MDL);
2902 		return;
2903 	}
2904 
2905 	token = next_token(&val, NULL, cfile);
2906 	if (token != SLASH) {
2907 		parse_warn(cfile, "Expecting a '/'.");
2908 		subnet_dereference(&subnet, MDL);
2909 		skip_to_semi(cfile);
2910 		return;
2911 	}
2912 
2913 	token = next_token(&val, NULL, cfile);
2914 	if (token != NUMBER) {
2915 		parse_warn(cfile, "Expecting a number.");
2916 		subnet_dereference(&subnet, MDL);
2917 		skip_to_semi(cfile);
2918 		return;
2919 	}
2920 
2921 	subnet->prefix_len = strtol(val, &endp, 10);
2922 	if ((subnet->prefix_len < 0) ||
2923 	    (subnet->prefix_len > 128) ||
2924 	    (*endp != '\0')) {
2925 	    	parse_warn(cfile, "Expecting a number between 0 and 128.");
2926 		subnet_dereference(&subnet, MDL);
2927 		skip_to_semi(cfile);
2928 		return;
2929 	}
2930 
2931 	if (!is_cidr_mask_valid(&subnet->net, subnet->prefix_len)) {
2932 		parse_warn(cfile, "New subnet mask too short.");
2933 		subnet_dereference(&subnet, MDL);
2934 		skip_to_semi(cfile);
2935 		return;
2936 	}
2937 
2938 	/*
2939 	 * Create a netmask.
2940 	 */
2941 	subnet->netmask.len = 16;
2942 	ofs = subnet->prefix_len / 8;
2943 	if (ofs < subnet->netmask.len) {
2944 		subnet->netmask.iabuf[ofs] = mask[subnet->prefix_len % 8];
2945 	}
2946 	while (--ofs >= 0) {
2947 		subnet->netmask.iabuf[ofs] = 0xFF;
2948 	}
2949 
2950 	/* Validate the network number/netmask pair. */
2951 	iaddr = subnet_number(subnet->net, subnet->netmask);
2952 	if (memcmp(&iaddr, &subnet->net, 16) != 0) {
2953 		parse_warn(cfile,
2954 		   "subnet %s/%d: prefix not long enough for address.",
2955 			    piaddr(subnet->net), subnet->prefix_len);
2956 		subnet_dereference(&subnet, MDL);
2957 		skip_to_semi(cfile);
2958 		return;
2959 	}
2960 
2961 	if (!common_subnet_parsing(cfile, share, subnet)) {
2962 		return;
2963 	}
2964 #endif /* defined(DHCPv6) */
2965 }
2966 
2967 /* group-declaration :== RBRACE parameters declarations LBRACE */
2968 
parse_group_declaration(cfile,group)2969 void parse_group_declaration (cfile, group)
2970 	struct parse *cfile;
2971 	struct group *group;
2972 {
2973 	const char *val;
2974 	enum dhcp_token token;
2975 	struct group *g;
2976 	int declaration = 0;
2977 	struct group_object *t = NULL;
2978 	isc_result_t status;
2979 	char *name = NULL;
2980 	int deletedp = 0;
2981 	int dynamicp = 0;
2982 	int staticp = 0;
2983 
2984 	g = NULL;
2985 	if (!clone_group(&g, group, MDL))
2986 		log_fatal("no memory for explicit group.");
2987 
2988 	token = peek_token(&val, NULL, cfile);
2989 	if (is_identifier (token) || token == STRING) {
2990 		skip_token(&val, NULL, cfile);
2991 
2992 		name = dmalloc(strlen(val) + 1, MDL);
2993 		if (!name)
2994 			log_fatal("no memory for group decl name %s", val);
2995 		strcpy(name, val);
2996 	}
2997 
2998 	if (!parse_lbrace(cfile)) {
2999 		group_dereference(&g, MDL);
3000 		return;
3001 	}
3002 
3003 	do {
3004 		token = peek_token(&val, NULL, cfile);
3005 		if (token == RBRACE) {
3006 			skip_token(&val, NULL, cfile);
3007 			break;
3008 		} else if (token == END_OF_FILE) {
3009 			skip_token(&val, NULL, cfile);
3010 			parse_warn(cfile, "unexpected end of file");
3011 			break;
3012 		} else if (token == TOKEN_DELETED) {
3013 			skip_token(&val, NULL, cfile);
3014 			parse_semi(cfile);
3015 			deletedp = 1;
3016 		} else if (token == DYNAMIC) {
3017 			skip_token(&val, NULL, cfile);
3018 			parse_semi(cfile);
3019 			dynamicp = 1;
3020 		} else if (token == STATIC) {
3021 			skip_token(&val, NULL, cfile);
3022 			parse_semi(cfile);
3023 			staticp = 1;
3024 		}
3025 		declaration = parse_statement(cfile, g, GROUP_DECL,
3026 					      NULL, declaration);
3027 	} while (1);
3028 
3029 	if (name) {
3030 		if (deletedp) {
3031 			if (group_name_hash) {
3032 				t = NULL;
3033 				if (group_hash_lookup(&t, group_name_hash,
3034 						      name,
3035 						      strlen(name), MDL)) {
3036 					delete_group(t, 0);
3037 				}
3038 			}
3039 		} else {
3040 			t = NULL;
3041 			status = group_object_allocate(&t, MDL);
3042 			if (status != ISC_R_SUCCESS)
3043 				log_fatal("no memory for group decl %s: %s",
3044 					  val, isc_result_totext(status));
3045 			group_reference(&t->group, g, MDL);
3046 			t->name = name;
3047 			/* no need to include deletedp as it's handled above */
3048 			t->flags = ((staticp ? GROUP_OBJECT_STATIC : 0) |
3049 				    (dynamicp ? GROUP_OBJECT_DYNAMIC : 0));
3050 			supersede_group(t, 0);
3051 		}
3052 		if (t != NULL)
3053 			group_object_dereference(&t, MDL);
3054 	}
3055 }
3056 
3057 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
3058    ip-addrs-or-hostnames :== ip-addr-or-hostname
3059 			   | ip-addrs-or-hostnames ip-addr-or-hostname */
3060 
3061 int
parse_fixed_addr_param(struct option_cache ** oc,struct parse * cfile,enum dhcp_token type)3062 parse_fixed_addr_param(struct option_cache **oc,
3063 		       struct parse *cfile,
3064 		       enum dhcp_token type) {
3065 	int parse_ok;
3066 	const char *val;
3067 	enum dhcp_token token;
3068 	struct expression *expr = NULL;
3069 	struct expression *tmp, *new;
3070 	int status;
3071 
3072 	do {
3073 		tmp = NULL;
3074 		if (type == FIXED_ADDR) {
3075 			parse_ok = parse_ip_addr_or_hostname(&tmp, cfile, 1);
3076 		} else {
3077 			/* INSIST(type == FIXED_ADDR6); */
3078 			parse_ok = parse_ip6_addr_expr(&tmp, cfile);
3079 		}
3080 		if (parse_ok) {
3081 			if (expr != NULL) {
3082 				new = NULL;
3083 				status = make_concat(&new, expr, tmp);
3084 				expression_dereference(&expr, MDL);
3085 				expression_dereference(&tmp, MDL);
3086 				if (!status) {
3087 					return 0;
3088 				}
3089 				expr = new;
3090 			} else {
3091 				expr = tmp;
3092 			}
3093 		} else {
3094 			if (expr != NULL) {
3095 				expression_dereference (&expr, MDL);
3096 			}
3097 			return 0;
3098 		}
3099 		token = peek_token(&val, NULL, cfile);
3100 		if (token == COMMA) {
3101 			token = next_token(&val, NULL, cfile);
3102 		}
3103 	} while (token == COMMA);
3104 
3105 	if (!parse_semi(cfile)) {
3106 		if (expr) {
3107 			expression_dereference (&expr, MDL);
3108 		}
3109 		return 0;
3110 	}
3111 
3112 	status = option_cache(oc, NULL, expr, NULL, MDL);
3113 	expression_dereference(&expr, MDL);
3114 	return status;
3115 }
3116 
3117 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
3118 
3119    lease_parameters :== <nil>
3120 		      | lease_parameter
3121 		      | lease_parameters lease_parameter
3122 
3123    lease_parameter :== STARTS date
3124 		     | ENDS date
3125 		     | TIMESTAMP date
3126 		     | HARDWARE hardware-parameter
3127 		     | UID hex_numbers SEMI
3128 		     | HOSTNAME hostname SEMI
3129 		     | CLIENT_HOSTNAME hostname SEMI
3130 		     | CLASS identifier SEMI
3131 		     | DYNAMIC_BOOTP SEMI */
3132 
parse_lease_declaration(struct lease ** lp,struct parse * cfile)3133 int parse_lease_declaration (struct lease **lp, struct parse *cfile)
3134 {
3135 	const char *val;
3136 	enum dhcp_token token;
3137 	unsigned char addr [4];
3138 	unsigned len = sizeof addr;
3139 	int seenmask = 0;
3140 	int seenbit;
3141 	char tbuf [32];
3142 	struct lease *lease;
3143 	struct executable_statement *on;
3144 	int lose;
3145 	TIME t;
3146 	int noequal, newbinding;
3147 	struct binding *binding;
3148 	struct binding_value *nv;
3149 	isc_result_t status;
3150 	struct option_cache *oc;
3151 	pair *p;
3152 	binding_state_t new_state;
3153 	unsigned buflen = 0;
3154 	struct class *class;
3155 
3156 	lease = (struct lease *)0;
3157 	status = lease_allocate (&lease, MDL);
3158 	if (status != ISC_R_SUCCESS)
3159 		return 0;
3160 
3161 	/* Get the address for which the lease has been issued. */
3162 	if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8)) {
3163 		lease_dereference (&lease, MDL);
3164 		return 0;
3165 	}
3166 	memcpy (lease -> ip_addr.iabuf, addr, len);
3167 	lease -> ip_addr.len = len;
3168 
3169 	if (!parse_lbrace (cfile)) {
3170 		lease_dereference (&lease, MDL);
3171 		return 0;
3172 	}
3173 
3174 	do {
3175 		token = next_token (&val, (unsigned *)0, cfile);
3176 		if (token == RBRACE)
3177 			break;
3178 		else if (token == END_OF_FILE) {
3179 			parse_warn (cfile, "unexpected end of file");
3180 			break;
3181 		}
3182 		strncpy (tbuf, val, sizeof tbuf);
3183 		tbuf [(sizeof tbuf) - 1] = 0;
3184 
3185 		/* Parse any of the times associated with the lease. */
3186 		switch (token) {
3187 		      case STARTS:
3188 		      case ENDS:
3189 		      case TIMESTAMP:
3190 		      case TSTP:
3191 		      case TSFP:
3192 		      case ATSFP:
3193 		      case CLTT:
3194 			t = parse_date (cfile);
3195 			switch (token) {
3196 			      case STARTS:
3197 				seenbit = 1;
3198 				lease -> starts = t;
3199 				break;
3200 
3201 			      case ENDS:
3202 				seenbit = 2;
3203 				lease -> ends = t;
3204 				break;
3205 
3206 			      case TSTP:
3207 				seenbit = 65536;
3208 				lease -> tstp = t;
3209 				break;
3210 
3211 			      case TSFP:
3212 				seenbit = 131072;
3213 				lease -> tsfp = t;
3214 				break;
3215 
3216 			      case ATSFP:
3217 				seenbit = 262144;
3218 				lease->atsfp = t;
3219 				break;
3220 
3221 			      case CLTT:
3222 				seenbit = 524288;
3223 				lease -> cltt = t;
3224 				break;
3225 
3226 			      default: /* for gcc, we'll never get here. */
3227 				log_fatal ("Impossible error at %s:%d.", MDL);
3228 				return 0;
3229 			}
3230 			break;
3231 
3232 			/* Colon-separated hexadecimal octets... */
3233 		      case UID:
3234 			seenbit = 8;
3235 			token = peek_token (&val, (unsigned *)0, cfile);
3236 			if (token == STRING) {
3237 				unsigned char *tuid;
3238 				skip_token(&val, &buflen, cfile);
3239 				if (buflen < sizeof lease -> uid_buf) {
3240 					tuid = lease -> uid_buf;
3241 					lease -> uid_max =
3242 						sizeof lease -> uid_buf;
3243 				} else {
3244 					tuid = ((unsigned char *)
3245 						dmalloc (buflen, MDL));
3246 					if (!tuid) {
3247 						log_error ("no space for uid");
3248 						lease_dereference (&lease,
3249 								   MDL);
3250 						return 0;
3251 					}
3252 					lease -> uid_max = buflen;
3253 				}
3254 				lease -> uid_len = buflen;
3255 				memcpy (tuid, val, lease -> uid_len);
3256 				lease -> uid = tuid;
3257 			} else {
3258 				buflen = 0;
3259 				lease -> uid = (parse_numeric_aggregate
3260 						(cfile, (unsigned char *)0,
3261 						 &buflen, ':', 16, 8));
3262 				if (!lease -> uid) {
3263 					lease_dereference (&lease, MDL);
3264 					return 0;
3265 				}
3266 				lease -> uid_len = buflen;
3267 				lease -> uid_max = buflen;
3268 				if (lease -> uid_len == 0) {
3269 					lease -> uid = (unsigned char *)0;
3270 					parse_warn (cfile, "zero-length uid");
3271 					seenbit = 0;
3272 					parse_semi (cfile);
3273 					break;
3274 				}
3275 			}
3276 			parse_semi (cfile);
3277 			if (!lease -> uid) {
3278 				log_fatal ("No memory for lease uid");
3279 			}
3280 			break;
3281 
3282 		      case CLASS:
3283 			seenbit = 32;
3284 			token = next_token (&val, (unsigned *)0, cfile);
3285 			if (!is_identifier (token)) {
3286 				if (token != SEMI)
3287 					skip_to_rbrace (cfile, 1);
3288 				lease_dereference (&lease, MDL);
3289 				return 0;
3290 			}
3291 			parse_semi (cfile);
3292 			/* for now, we aren't using this. */
3293 			break;
3294 
3295 		      case HARDWARE:
3296 			seenbit = 64;
3297 			parse_hardware_param (cfile,
3298 					      &lease -> hardware_addr);
3299 			break;
3300 
3301 		      case TOKEN_RESERVED:
3302 			seenbit = 0;
3303 			lease->flags |= RESERVED_LEASE;
3304 			parse_semi(cfile);
3305 			break;
3306 
3307 		      case DYNAMIC_BOOTP:
3308 			seenbit = 0;
3309 			lease -> flags |= BOOTP_LEASE;
3310 			parse_semi (cfile);
3311 			break;
3312 
3313 			/* XXX: Reverse compatibility? */
3314 		      case TOKEN_ABANDONED:
3315 			seenbit = 256;
3316 			lease -> binding_state = FTS_ABANDONED;
3317 			lease -> next_binding_state = FTS_ABANDONED;
3318 			parse_semi (cfile);
3319 			break;
3320 
3321 		      case TOKEN_NEXT:
3322 			seenbit = 128;
3323 			token = next_token (&val, (unsigned *)0, cfile);
3324 			if (token != BINDING) {
3325 				parse_warn (cfile, "expecting 'binding'");
3326 				skip_to_semi (cfile);
3327 				break;
3328 			}
3329 			goto do_binding_state;
3330 
3331 		      case REWIND:
3332 			seenbit = 512;
3333 			token = next_token(&val, NULL, cfile);
3334 			if (token != BINDING) {
3335 				parse_warn(cfile, "expecting 'binding'");
3336 				skip_to_semi(cfile);
3337 				break;
3338 			}
3339 			goto do_binding_state;
3340 
3341 		      case BINDING:
3342 			seenbit = 256;
3343 
3344 		      do_binding_state:
3345 			token = next_token (&val, (unsigned *)0, cfile);
3346 			if (token != STATE) {
3347 				parse_warn (cfile, "expecting 'state'");
3348 				skip_to_semi (cfile);
3349 				break;
3350 			}
3351 			token = next_token (&val, (unsigned *)0, cfile);
3352 			switch (token) {
3353 			      case TOKEN_ABANDONED:
3354 				new_state = FTS_ABANDONED;
3355 				break;
3356 			      case TOKEN_FREE:
3357 				new_state = FTS_FREE;
3358 				break;
3359 			      case TOKEN_ACTIVE:
3360 				new_state = FTS_ACTIVE;
3361 				break;
3362 			      case TOKEN_EXPIRED:
3363 				new_state = FTS_EXPIRED;
3364 				break;
3365 			      case TOKEN_RELEASED:
3366 				new_state = FTS_RELEASED;
3367 				break;
3368 			      case TOKEN_RESET:
3369 				new_state = FTS_RESET;
3370 				break;
3371 			      case TOKEN_BACKUP:
3372 				new_state = FTS_BACKUP;
3373 				break;
3374 
3375 				/* RESERVED and BOOTP states preserved for
3376 				 * compatibleness with older versions.
3377 				 */
3378 			      case TOKEN_RESERVED:
3379 				new_state = FTS_ACTIVE;
3380 				lease->flags |= RESERVED_LEASE;
3381 				break;
3382 			      case TOKEN_BOOTP:
3383 				new_state = FTS_ACTIVE;
3384 				lease->flags |= BOOTP_LEASE;
3385 				break;
3386 
3387 			      default:
3388 				parse_warn (cfile,
3389 					    "%s: expecting a binding state.",
3390 					    val);
3391 				skip_to_semi (cfile);
3392 				return 0;
3393 			}
3394 
3395 			if (seenbit == 256) {
3396 				lease -> binding_state = new_state;
3397 
3398 				/*
3399 				 * Apply default/conservative next/rewind
3400 				 * binding states if they haven't been set
3401 				 * yet.  These defaults will be over-ridden if
3402 				 * they are set later in parsing.
3403 				 */
3404 				if (!(seenmask & 128))
3405 				    lease->next_binding_state = new_state;
3406 
3407 				/* The most conservative rewind state. */
3408 				if (!(seenmask & 512))
3409 				    lease->rewind_binding_state = new_state;
3410 			} else if (seenbit == 128)
3411 				lease -> next_binding_state = new_state;
3412 			else if (seenbit == 512)
3413 				lease->rewind_binding_state = new_state;
3414 			else
3415 				log_fatal("Impossible condition at %s:%d.",
3416 					  MDL);
3417 
3418 			parse_semi (cfile);
3419 			break;
3420 
3421 		      case CLIENT_HOSTNAME:
3422 			seenbit = 1024;
3423 			token = peek_token (&val, (unsigned *)0, cfile);
3424 			if (token == STRING) {
3425 				if (!parse_string (cfile,
3426 						   &lease -> client_hostname,
3427 						   (unsigned *)0)) {
3428 					lease_dereference (&lease, MDL);
3429 					return 0;
3430 				}
3431 			} else {
3432 				lease -> client_hostname =
3433 					parse_host_name (cfile);
3434 				if (lease -> client_hostname)
3435 					parse_semi (cfile);
3436 				else {
3437 					parse_warn (cfile,
3438 						    "expecting a hostname.");
3439 					skip_to_semi (cfile);
3440 					lease_dereference (&lease, MDL);
3441 					return 0;
3442 				}
3443 			}
3444 			break;
3445 
3446 		      case BILLING:
3447 			seenbit = 2048;
3448 			class = (struct class *)0;
3449 			token = next_token (&val, (unsigned *)0, cfile);
3450 			if (token == CLASS) {
3451 				token = next_token (&val,
3452 						    (unsigned *)0, cfile);
3453 				if (token != STRING) {
3454 					parse_warn (cfile, "expecting string");
3455 					if (token != SEMI)
3456 						skip_to_semi (cfile);
3457 					token = BILLING;
3458 					break;
3459 				}
3460 				if (lease -> billing_class)
3461 				    class_dereference (&lease -> billing_class,
3462 						       MDL);
3463 				find_class (&class, val, MDL);
3464 				if (!class)
3465 					parse_warn (cfile,
3466 						    "unknown class %s", val);
3467 				parse_semi (cfile);
3468 			} else if (token == SUBCLASS) {
3469 				if (lease -> billing_class)
3470 				    class_dereference (&lease -> billing_class,
3471 						       MDL);
3472 				parse_class_declaration(&class, cfile, NULL,
3473 							CLASS_TYPE_SUBCLASS);
3474 			} else {
3475 				parse_warn (cfile, "expecting \"class\"");
3476 				if (token != SEMI)
3477 					skip_to_semi (cfile);
3478 			}
3479 			if (class) {
3480 				class_reference (&lease -> billing_class,
3481 						 class, MDL);
3482 				class_dereference (&class, MDL);
3483 			}
3484 			break;
3485 
3486 		      case ON:
3487 			on = (struct executable_statement *)0;
3488 			lose = 0;
3489 			if (!parse_on_statement (&on, cfile, &lose)) {
3490 				skip_to_rbrace (cfile, 1);
3491 				lease_dereference (&lease, MDL);
3492 				return 0;
3493 			}
3494 			seenbit = 0;
3495 			if ((on->data.on.evtypes & ON_EXPIRY) &&
3496 			    on->data.on.statements) {
3497 				seenbit |= 16384;
3498 				executable_statement_reference
3499 					(&lease->on_star.on_expiry,
3500 					 on->data.on.statements, MDL);
3501 			}
3502 			if ((on->data.on.evtypes & ON_RELEASE) &&
3503 			    on->data.on.statements) {
3504 				seenbit |= 32768;
3505 				executable_statement_reference
3506 					(&lease->on_star.on_release,
3507 					 on->data.on.statements, MDL);
3508 			}
3509 			executable_statement_dereference (&on, MDL);
3510 			break;
3511 
3512 		      case OPTION:
3513 		      case SUPERSEDE:
3514 			noequal = 0;
3515 			seenbit = 0;
3516 			oc = (struct option_cache *)0;
3517 			if (parse_option_decl (&oc, cfile)) {
3518 			    if (oc -> option -> universe !=
3519 				&agent_universe) {
3520 				    parse_warn (cfile,
3521 						"agent option expected.");
3522 				    option_cache_dereference (&oc, MDL);
3523 				    break;
3524 			    }
3525 			    if (!lease -> agent_options &&
3526 				!(option_chain_head_allocate
3527 				  (&lease -> agent_options, MDL))) {
3528 				log_error ("no memory to stash agent option");
3529 				break;
3530 			    }
3531 			    for (p = &lease -> agent_options -> first;
3532 				 *p; p = &((*p) -> cdr))
3533 				    ;
3534 			    *p = cons (0, 0);
3535 			    option_cache_reference (((struct option_cache **)
3536 						     &((*p) -> car)), oc, MDL);
3537 			    option_cache_dereference (&oc, MDL);
3538 			}
3539 			break;
3540 
3541 		      case TOKEN_SET:
3542 			noequal = 0;
3543 
3544 			token = next_token (&val, (unsigned *)0, cfile);
3545 			if (token != NAME && token != NUMBER_OR_NAME) {
3546 				parse_warn (cfile,
3547 					    "%s can't be a variable name",
3548 					    val);
3549 			      badset:
3550 				skip_to_semi (cfile);
3551 				lease_dereference (&lease, MDL);
3552 				return 0;
3553 			}
3554 
3555 			seenbit = 0;
3556 		      special_set:
3557 			if (lease -> scope)
3558 				binding = find_binding (lease -> scope, val);
3559 			else
3560 				binding = (struct binding *)0;
3561 
3562 			if (!binding) {
3563 			    if (!lease -> scope)
3564 				if (!(binding_scope_allocate
3565 				      (&lease -> scope, MDL)))
3566 					log_fatal ("no memory for scope");
3567 			    binding = dmalloc (sizeof *binding, MDL);
3568 			    if (!binding)
3569 				    log_fatal ("No memory for lease %s.",
3570 					       "binding");
3571 			    memset (binding, 0, sizeof *binding);
3572 			    binding -> name =
3573 				    dmalloc (strlen (val) + 1, MDL);
3574 			    if (!binding -> name)
3575 				    log_fatal ("No memory for binding %s.",
3576 					       "name");
3577 			    strcpy (binding -> name, val);
3578 			    newbinding = 1;
3579 			} else  {
3580 			    newbinding = 0;
3581 			}
3582 
3583 			nv = NULL;
3584 			if (!binding_value_allocate(&nv, MDL))
3585 				log_fatal("no memory for binding value.");
3586 
3587 			if (!noequal) {
3588 			    token = next_token (&val, (unsigned *)0, cfile);
3589 			    if (token != EQUAL) {
3590 				parse_warn (cfile,
3591 					    "expecting '=' in set statement.");
3592 				binding_value_dereference(&nv, MDL);
3593 				if (newbinding) {
3594 					dfree(binding->name, MDL);
3595 					dfree(binding, MDL);
3596 				}
3597 				goto badset;
3598 			    }
3599 			}
3600 
3601 			if (!parse_binding_value(cfile, nv)) {
3602 				binding_value_dereference(&nv, MDL);
3603 				lease_dereference(&lease, MDL);
3604 				if (newbinding) {
3605 					dfree(binding->name, MDL);
3606 					dfree(binding, MDL);
3607 				}
3608 				return 0;
3609 			}
3610 
3611 			if (newbinding) {
3612 				binding_value_reference(&binding->value,
3613 							nv, MDL);
3614 				binding->next = lease->scope->bindings;
3615 				lease->scope->bindings = binding;
3616 			} else {
3617 				binding_value_dereference(&binding->value, MDL);
3618 				binding_value_reference(&binding->value,
3619 							nv, MDL);
3620 			}
3621 
3622 			binding_value_dereference(&nv, MDL);
3623 			parse_semi(cfile);
3624 			break;
3625 
3626 			/* case NAME: */
3627 		      default:
3628 			if (!strcasecmp (val, "ddns-fwd-name")) {
3629 				seenbit = 4096;
3630 				noequal = 1;
3631 				goto special_set;
3632 			} else if (!strcasecmp (val, "ddns-rev-name")) {
3633 				seenbit = 8192;
3634 				noequal = 1;
3635 				goto special_set;
3636 			} else
3637 				parse_warn(cfile, "Unexpected configuration "
3638 						  "directive.");
3639 			skip_to_semi (cfile);
3640 			seenbit = 0;
3641 			lease_dereference (&lease, MDL);
3642 			return 0;
3643 		}
3644 
3645 		if (seenmask & seenbit) {
3646 			parse_warn (cfile,
3647 				    "Too many %s parameters in lease %s\n",
3648 				    tbuf, piaddr (lease -> ip_addr));
3649 		} else
3650 			seenmask |= seenbit;
3651 
3652 	} while (1);
3653 
3654 	/* If no binding state is specified, make one up. */
3655 	if (!(seenmask & 256)) {
3656 		if (lease->ends > cur_time ||
3657 		    lease->on_star.on_expiry || lease->on_star.on_release)
3658 			lease->binding_state = FTS_ACTIVE;
3659 #if defined (FAILOVER_PROTOCOL)
3660 		else if (lease->pool && lease->pool->failover_peer)
3661 			lease->binding_state = FTS_EXPIRED;
3662 #endif
3663 		else
3664 			lease->binding_state = FTS_FREE;
3665 		if (lease->binding_state == FTS_ACTIVE) {
3666 #if defined (FAILOVER_PROTOCOL)
3667 			if (lease->pool && lease->pool->failover_peer)
3668 				lease->next_binding_state = FTS_EXPIRED;
3669 			else
3670 #endif
3671 				lease->next_binding_state = FTS_FREE;
3672 		} else
3673 			lease->next_binding_state = lease->binding_state;
3674 
3675 		/* The most conservative rewind state implies no rewind. */
3676 		lease->rewind_binding_state = lease->binding_state;
3677 	}
3678 
3679 	if (!(seenmask & 65536))
3680 		lease->tstp = lease->ends;
3681 
3682 	lease_reference (lp, lease, MDL);
3683 	lease_dereference (&lease, MDL);
3684 	return 1;
3685 }
3686 
3687 /* Parse the right side of a 'binding value'.
3688  *
3689  * set foo = "bar"; is a string
3690  * set foo = false; is a boolean
3691  * set foo = %31; is a numeric value.
3692  */
3693 static int
parse_binding_value(struct parse * cfile,struct binding_value * value)3694 parse_binding_value(struct parse *cfile, struct binding_value *value)
3695 {
3696 	struct data_string *data;
3697 	unsigned char *s;
3698 	const char *val;
3699 	unsigned buflen;
3700 	int token;
3701 
3702 	if ((cfile == NULL) || (value == NULL))
3703 		log_fatal("Invalid arguments at %s:%d.", MDL);
3704 
3705 	token = peek_token(&val, NULL, cfile);
3706 	if (token == STRING) {
3707 		skip_token(&val, &buflen, cfile);
3708 
3709 		value->type = binding_data;
3710 		value->value.data.len = buflen;
3711 
3712 		data = &value->value.data;
3713 
3714 		if (!buffer_allocate(&data->buffer, buflen + 1, MDL))
3715 			log_fatal ("No memory for binding.");
3716 
3717 		memcpy(data->buffer->data, val, buflen + 1);
3718 
3719 		data->data = data->buffer->data;
3720 		data->terminated = 1;
3721 	} else if (token == NUMBER_OR_NAME) {
3722 		value->type = binding_data;
3723 
3724 		data = &value->value.data;
3725 		s = parse_numeric_aggregate(cfile, NULL, &data->len,
3726 					    ':', 16, 8);
3727 		if (s == NULL) {
3728 			skip_to_semi(cfile);
3729 			return 0;
3730 		}
3731 
3732 		if (data->len) {
3733 			if (!buffer_allocate(&data->buffer, data->len + 1,
3734 					     MDL))
3735 				log_fatal("No memory for binding.");
3736 
3737 			memcpy(data->buffer->data, s, data->len);
3738 			data->data = data->buffer->data;
3739 
3740 			dfree (s, MDL);
3741 		}
3742 	} else if (token == PERCENT) {
3743 		skip_token(&val, NULL, cfile);
3744 		token = next_token(&val, NULL, cfile);
3745 		if (token != NUMBER) {
3746 			parse_warn(cfile, "expecting decimal number.");
3747 			if (token != SEMI)
3748 				skip_to_semi(cfile);
3749 			return 0;
3750 		}
3751 		value->type = binding_numeric;
3752 		value->value.intval = atol(val);
3753 	} else if (token == NAME) {
3754 		token = next_token(&val, NULL, cfile);
3755 		value->type = binding_boolean;
3756 		if (!strcasecmp(val, "true"))
3757 			value->value.boolean = 1;
3758 		else if (!strcasecmp(val, "false"))
3759 			value->value.boolean = 0;
3760 		else {
3761 			parse_warn(cfile, "expecting true or false");
3762 			if (token != SEMI)
3763 				skip_to_semi(cfile);
3764 			return 0;
3765 		}
3766 	} else {
3767 		parse_warn (cfile, "expecting a constant value.");
3768 		if (token != SEMI)
3769 			skip_to_semi (cfile);
3770 		return 0;
3771 	}
3772 
3773 	return 1;
3774 }
3775 
3776 /* address-range-declaration :== ip-address ip-address SEMI
3777 			       | DYNAMIC_BOOTP ip-address ip-address SEMI */
3778 
parse_address_range(cfile,group,type,inpool,lpchain)3779 void parse_address_range (cfile, group, type, inpool, lpchain)
3780 	struct parse *cfile;
3781 	struct group *group;
3782 	int type;
3783 	struct pool *inpool;
3784 	struct lease **lpchain;
3785 {
3786 	struct iaddr low, high, net;
3787 	unsigned char addr [4];
3788 	unsigned len = sizeof addr;
3789 	enum dhcp_token token;
3790 	const char *val;
3791 	int dynamic = 0;
3792 	struct subnet *subnet;
3793 	struct shared_network *share;
3794 	struct pool *pool;
3795 	isc_result_t status;
3796 
3797 	if ((token = peek_token (&val,
3798 				 (unsigned *)0, cfile)) == DYNAMIC_BOOTP) {
3799 		skip_token(&val, (unsigned *)0, cfile);
3800 		dynamic = 1;
3801 	}
3802 
3803 	/* Get the bottom address in the range... */
3804 	if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3805 		return;
3806 	memcpy (low.iabuf, addr, len);
3807 	low.len = len;
3808 
3809 	/* Only one address? */
3810 	token = peek_token (&val, (unsigned *)0, cfile);
3811 	if (token == SEMI)
3812 		high = low;
3813 	else {
3814 	/* Get the top address in the range... */
3815 		if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
3816 			return;
3817 		memcpy (high.iabuf, addr, len);
3818 		high.len = len;
3819 	}
3820 
3821 	token = next_token (&val, (unsigned *)0, cfile);
3822 	if (token != SEMI) {
3823 		parse_warn (cfile, "semicolon expected.");
3824 		skip_to_semi (cfile);
3825 		return;
3826 	}
3827 
3828 	if (type == SUBNET_DECL) {
3829 		subnet = group -> subnet;
3830 		share = subnet -> shared_network;
3831 	} else {
3832 		share = group -> shared_network;
3833 		for (subnet = share -> subnets;
3834 		     subnet; subnet = subnet -> next_sibling) {
3835 			net = subnet_number (low, subnet -> netmask);
3836 			if (addr_eq (net, subnet -> net))
3837 				break;
3838 		}
3839 		if (!subnet) {
3840 			parse_warn (cfile, "address range not on network %s",
3841 				    group -> shared_network -> name);
3842 			log_error ("Be sure to place pool statement after %s",
3843 				   "related subnet declarations.");
3844 			return;
3845 		}
3846 	}
3847 
3848 	if (!inpool) {
3849 		struct pool *last = (struct pool *)0;
3850 
3851 		/* If we're permitting dynamic bootp for this range,
3852 		   then look for a pool with an empty prohibit list and
3853 		   a permit list with one entry that permits all clients. */
3854 		for (pool = share -> pools; pool; pool = pool -> next) {
3855 			if ((!dynamic && !pool -> permit_list &&
3856 			     pool -> prohibit_list &&
3857 			     !pool -> prohibit_list -> next &&
3858 			     (pool -> prohibit_list -> type ==
3859 			      permit_dynamic_bootp_clients)) ||
3860 			    (dynamic && !pool -> prohibit_list &&
3861 			     pool -> permit_list &&
3862 			     !pool -> permit_list -> next &&
3863 			     (pool -> permit_list -> type ==
3864 			      permit_all_clients))) {
3865   				break;
3866 			}
3867 			last = pool;
3868 		}
3869 
3870 		/* If we didn't get a pool, make one. */
3871 		if (!pool) {
3872 			struct permit *p;
3873 			status = pool_allocate (&pool, MDL);
3874 			if (status != ISC_R_SUCCESS)
3875 				log_fatal ("no memory for ad-hoc pool: %s",
3876 					   isc_result_totext (status));
3877 			p = new_permit (MDL);
3878 			if (!p)
3879 				log_fatal ("no memory for ad-hoc permit.");
3880 
3881 			/* Dynamic pools permit all clients.   Otherwise
3882 			   we prohibit BOOTP clients. */
3883 			if (dynamic) {
3884 				p -> type = permit_all_clients;
3885 				pool -> permit_list = p;
3886 			} else {
3887 				p -> type = permit_dynamic_bootp_clients;
3888 				pool -> prohibit_list = p;
3889 			}
3890 
3891 			if (share -> pools)
3892 				pool_reference (&last -> next, pool, MDL);
3893 			else
3894 				pool_reference (&share -> pools, pool, MDL);
3895 			shared_network_reference (&pool -> shared_network,
3896 						  share, MDL);
3897 			if (!clone_group (&pool -> group, share -> group, MDL))
3898 				log_fatal ("no memory for anon pool group.");
3899 		} else {
3900 			pool = (struct pool *)0;
3901 			if (last)
3902 				pool_reference (&pool, last, MDL);
3903 			else
3904 				pool_reference (&pool, share -> pools, MDL);
3905 		}
3906 	} else {
3907 		pool = (struct pool *)0;
3908 		pool_reference (&pool, inpool, MDL);
3909 	}
3910 
3911 #if defined (FAILOVER_PROTOCOL)
3912 	if (pool -> failover_peer && dynamic) {
3913 		/* Doctor, do you think I'm overly sensitive
3914 		   about getting bug reports I can't fix? */
3915 		parse_warn (cfile, "dynamic-bootp flag is %s",
3916 			    "not permitted for address");
3917 		log_error ("range declarations where there is a failover");
3918 		log_error ("peer in scope.   If you wish to declare an");
3919 		log_error ("address range from which dynamic bootp leases");
3920 		log_error ("can be allocated, please declare it within a");
3921 		log_error ("pool declaration that also contains the \"no");
3922 		log_error ("failover\" statement.   The failover protocol");
3923 		log_error ("itself does not permit dynamic bootp - this");
3924 		log_error ("is not a limitation specific to the ISC DHCP");
3925 		log_error ("server.   Please don't ask me to defend this");
3926 		log_error ("until you have read and really tried %s",
3927 			   "to understand");
3928 		log_error ("the failover protocol specification.");
3929 
3930 		/* We don't actually bomb at this point - instead,
3931 		   we let parse_lease_file notice the error and
3932 		   bomb at that point - it's easier. */
3933 	}
3934 #endif /* FAILOVER_PROTOCOL */
3935 
3936 	/* Create the new address range... */
3937 	new_address_range (cfile, low, high, subnet, pool, lpchain);
3938 	pool_dereference (&pool, MDL);
3939 }
3940 
3941 #ifdef DHCPv6
3942 static void
add_ipv6_pool_to_subnet(struct subnet * subnet,u_int16_t type,struct iaddr * lo_addr,int bits,int units,struct ipv6_pond * pond)3943 add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
3944 			struct iaddr *lo_addr, int bits, int units,
3945 			struct ipv6_pond *pond) {
3946 	struct ipv6_pool *pool;
3947 	struct in6_addr tmp_in6_addr;
3948 	int num_pools;
3949 	struct ipv6_pool **tmp;
3950 
3951 	/*
3952 	 * Create our pool.
3953 	 */
3954 	if (lo_addr->len != sizeof(tmp_in6_addr)) {
3955 		log_fatal("Internal error: Attempt to add non-IPv6 address "
3956 			  "to IPv6 shared network.");
3957 	}
3958 	memcpy(&tmp_in6_addr, lo_addr->iabuf, sizeof(tmp_in6_addr));
3959 	pool = NULL;
3960 	if (ipv6_pool_allocate(&pool, type, &tmp_in6_addr,
3961 			       bits, units, MDL) != ISC_R_SUCCESS) {
3962 		log_fatal("Out of memory");
3963 	}
3964 
3965 	/*
3966 	 * Add to our global IPv6 pool set.
3967 	 */
3968 	if (add_ipv6_pool(pool) != ISC_R_SUCCESS) {
3969 		log_fatal ("Out of memory");
3970 	}
3971 
3972 	/*
3973 	 * Link the pool to its network.
3974 	 */
3975 	pool->subnet = NULL;
3976 	subnet_reference(&pool->subnet, subnet, MDL);
3977 	pool->shared_network = NULL;
3978 	shared_network_reference(&pool->shared_network,
3979 				 subnet->shared_network, MDL);
3980 	pool->ipv6_pond = NULL;
3981 	ipv6_pond_reference(&pool->ipv6_pond, pond, MDL);
3982 
3983 	/*
3984 	 * Increase our array size for ipv6_pools in the pond
3985 	 */
3986 	if (pond->ipv6_pools == NULL) {
3987 		num_pools = 0;
3988 	} else {
3989 		num_pools = 0;
3990 		while (pond->ipv6_pools[num_pools] != NULL) {
3991 			num_pools++;
3992 		}
3993 	}
3994 	tmp = dmalloc(sizeof(struct ipv6_pool *) * (num_pools + 2), MDL);
3995 	if (tmp == NULL) {
3996 		log_fatal("Out of memory");
3997 	}
3998 	if (num_pools > 0) {
3999 		memcpy(tmp, pond->ipv6_pools,
4000 		       sizeof(struct ipv6_pool *) * num_pools);
4001 	}
4002 	if (pond->ipv6_pools != NULL) {
4003 		dfree(pond->ipv6_pools, MDL);
4004 	}
4005 	pond->ipv6_pools = tmp;
4006 
4007 	/*
4008 	 * Record this pool in our array of pools for this shared network.
4009 	 */
4010 	ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL);
4011 	pond->ipv6_pools[num_pools+1] = NULL;
4012 
4013 	/* Update the number of elements in the pond.  Conveniently
4014 	 * we have the total size of the block in bits and the amount
4015 	 * we would allocate per element in units.  For an address units
4016 	 * will always be 128, for a prefix it will be something else.
4017 	 *
4018 	 * We need to make sure the number of elements isn't too large
4019 	 * to track.  If so, we flag it to avoid wasting time with log
4020 	 * threshold logic.  We also emit a log stating that log-threshold
4021 	 * will be disabled for the shared-network but that's done
4022 	 * elsewhere via report_log_threshold().
4023 	 *
4024 	*/
4025 
4026 	/* Only bother if we aren't already flagged as jumbo */
4027 	if (pond->jumbo_range == 0) {
4028 		if ((units - bits) > (sizeof(isc_uint64_t) * 8)) {
4029 			pond->jumbo_range = 1;
4030 			pond->num_total = POND_TRACK_MAX;
4031 		}
4032 		else {
4033 			isc_uint64_t space_left
4034 				= POND_TRACK_MAX - pond->num_total;
4035 			isc_uint64_t addon
4036 				= (isc_uint64_t)(1) << (units - bits);
4037 
4038 			if (addon > space_left) {
4039 				pond->jumbo_range = 1;
4040 				pond->num_total = POND_TRACK_MAX;
4041 			} else {
4042 				pond->num_total += addon;
4043 			}
4044 		}
4045 	}
4046 }
4047 
4048 /*!
4049  *
4050  * \brief Find or create a default pond
4051  *
4052  * Find or create an ipv6_pond on which to attach the ipv6_pools.  We
4053  * check the shared network to see if there is a general purpose
4054  * entry - this will have an empty prohibit list and a permit list
4055  * with a single entry that permits all clients.  If the shared
4056  * network doesn't have one of them create it and attach it to
4057  * the shared network and the return argument.
4058  *
4059  * This function is used when we have a range6 or prefix6 statement
4060  * inside a subnet6 statement but outside of a pool6 statement.
4061  * This routine constructs the missing ipv6_pond structure so
4062  * we always have
4063  * shared_network -> ipv6_pond -> ipv6_pool
4064  *
4065  * \param[in] group     = a pointer to the group structure from which
4066  *                        we can find the subnet and shared netowrk
4067  *                        structures
4068  * \param[out] ret_pond = a pointer to space for the pointer to
4069  *                        the structure to return
4070  *
4071  * \return
4072  * void
4073  */
4074 static void
add_ipv6_pond_to_network(struct group * group,struct ipv6_pond ** ret_pond)4075 add_ipv6_pond_to_network(struct group *group,
4076 			 struct ipv6_pond **ret_pond) {
4077 
4078 	struct ipv6_pond *pond = NULL, *last = NULL;
4079 	struct permit *p;
4080 	isc_result_t status;
4081 	struct shared_network *shared = group->subnet->shared_network;
4082 
4083 	for (pond = shared->ipv6_pond; pond; pond = pond->next) {
4084 		if ((pond->group->statements == group->statements) &&
4085 		    (pond->prohibit_list == NULL) &&
4086 		    (pond->permit_list != NULL) &&
4087 		    (pond->permit_list->next == NULL) &&
4088 		    (pond->permit_list->type == permit_all_clients)) {
4089 			ipv6_pond_reference(ret_pond, pond, MDL);
4090 			return;
4091 		}
4092 		last = pond;
4093 	}
4094 
4095 	/* no pond available, make one */
4096 	status = ipv6_pond_allocate(&pond, MDL);
4097 	if (status != ISC_R_SUCCESS)
4098 		log_fatal ("no memory for ad-hoc ipv6 pond: %s",
4099 			   isc_result_totext (status));
4100 	p = new_permit (MDL);
4101 	if (p == NULL)
4102 		log_fatal ("no memory for ad-hoc ipv6 permit.");
4103 
4104 	/* we permit all clients */
4105 	p->type = permit_all_clients;
4106 	pond->permit_list = p;
4107 
4108 	/* and attach the pond to the return argument and the shared network */
4109 	ipv6_pond_reference(ret_pond, pond, MDL);
4110 
4111 	if (shared->ipv6_pond)
4112 		ipv6_pond_reference(&last->next, pond, MDL);
4113 	else
4114 		ipv6_pond_reference(&shared->ipv6_pond, pond, MDL);
4115 
4116 	shared_network_reference(&pond->shared_network, shared, MDL);
4117 	if (!clone_group (&pond->group, group, MDL))
4118 		log_fatal ("no memory for anon pool group.");
4119 
4120 	ipv6_pond_dereference(&pond, MDL);
4121 	return;
4122 }
4123 
4124 
4125 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
4126 			       | ip-address6 SLASH number SEMI
4127 			       | ip-address6 [SLASH number] TEMPORARY SEMI */
4128 
4129 void
parse_address_range6(struct parse * cfile,struct group * group,struct ipv6_pond * inpond)4130 parse_address_range6(struct parse *cfile,
4131 		     struct group *group,
4132 		     struct ipv6_pond *inpond) {
4133 	struct iaddr lo, hi;
4134 	int bits;
4135 	enum dhcp_token token;
4136 	const char *val;
4137 	struct iaddrcidrnetlist *nets, net;
4138 	struct iaddrcidrnetlist *p;
4139 	u_int16_t type = D6O_IA_NA;
4140 	struct ipv6_pond *pond = NULL;
4141 
4142         if (local_family != AF_INET6) {
4143                 parse_warn(cfile, "range6 statement is only supported "
4144 				  "in DHCPv6 mode.");
4145                 skip_to_semi(cfile);
4146                 return;
4147         }
4148 
4149 	/* This is enforced by the caller, this is just a sanity check. */
4150 	if (group->subnet == NULL)
4151 		log_fatal("Impossible condition at %s:%d.", MDL);
4152 
4153 	/*
4154 	 * Read starting address.
4155 	 */
4156 	if (!parse_ip6_addr(cfile, &lo)) {
4157 		return;
4158 	}
4159 
4160 	/* Make sure starting address is within the subnet */
4161 	if (!addr_eq(group->subnet->net,
4162 		     subnet_number(lo, group->subnet->netmask))) {
4163 		parse_warn(cfile, "range6 start address is outside the subnet");
4164                 skip_to_semi(cfile);
4165 		return;
4166 	}
4167 
4168 	/*
4169 	 * zero out the net entry in case we use it
4170 	 */
4171 	memset(&net, 0, sizeof(net));
4172 	net.cidrnet.lo_addr = lo;
4173 
4174 	/*
4175 	 * See if we we're using range or CIDR notation or TEMPORARY
4176 	 */
4177 	token = peek_token(&val, NULL, cfile);
4178 	if (token == SLASH) {
4179 		/*
4180 		 * '/' means CIDR notation, so read the bits we want.
4181 		 */
4182 		skip_token(NULL, NULL, cfile);
4183 		token = next_token(&val, NULL, cfile);
4184 		if (token != NUMBER) {
4185 			parse_warn(cfile, "expecting number");
4186 			skip_to_semi(cfile);
4187 			return;
4188 		}
4189 		net.cidrnet.bits = atoi(val);
4190 		bits = net.cidrnet.bits;
4191 		if ((bits < 0) || (bits > 128)) {
4192 			parse_warn(cfile, "networks have 0 to 128 bits");
4193 			skip_to_semi(cfile);
4194 			return;
4195 		}
4196 		if (bits < group->subnet->prefix_len) {
4197 			parse_warn(cfile,
4198 				   "network mask smaller than subnet mask");
4199 			skip_to_semi(cfile);
4200 			return;
4201 		}
4202 		if (!is_cidr_mask_valid(&net.cidrnet.lo_addr, bits)) {
4203 			parse_warn(cfile, "network mask too short");
4204 			skip_to_semi(cfile);
4205 			return;
4206 		}
4207 		/*
4208 		 * can be temporary (RFC 4941 like)
4209 		 */
4210 		token = peek_token(&val, NULL, cfile);
4211 		if (token == TEMPORARY) {
4212 			if (bits < 64)
4213 				parse_warn(cfile, "temporary mask too short");
4214 			if (bits == 128)
4215 				parse_warn(cfile, "temporary singleton?");
4216 			skip_token(NULL, NULL, cfile);
4217 			type = D6O_IA_TA;
4218 		}
4219 
4220 		nets = &net;
4221 
4222 	} else if (token == TEMPORARY) {
4223 		/*
4224 		 * temporary (RFC 4941)
4225 		 */
4226 		type = D6O_IA_TA;
4227 		skip_token(NULL, NULL, cfile);
4228 		net.cidrnet.bits = 64;
4229 		if (!is_cidr_mask_valid(&net.cidrnet.lo_addr,
4230 					net.cidrnet.bits)) {
4231 			parse_warn(cfile, "network mask too short");
4232 			skip_to_semi(cfile);
4233 			return;
4234 		}
4235 
4236 		nets = &net;
4237 
4238 	} else {
4239 		/*
4240 		 * No '/', so we are looking for the end address of
4241 		 * the IPv6 pool.
4242 		 */
4243 		if (!parse_ip6_addr(cfile, &hi)) {
4244 			return;
4245 		}
4246 
4247 		/* Make sure ending address is within the subnet */
4248 		if (!addr_eq(group->subnet->net,
4249 			     subnet_number(hi, group->subnet->netmask))) {
4250 			parse_warn(cfile,
4251 				   "range6 end address is outside the subnet");
4252 			skip_to_semi(cfile);
4253 			return;
4254 		}
4255 
4256 		/*
4257 		 * Convert our range to a set of CIDR networks.
4258 		 */
4259 		nets = NULL;
4260 		if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4261 			log_fatal("Error converting range to CIDR networks");
4262 		}
4263 
4264 	}
4265 
4266 	/*
4267 	 * See if we have a pond for this set of pools.
4268 	 * If the caller supplied one we use it, otherwise
4269 	 * check the shared network
4270 	 */
4271 
4272 	if (inpond != NULL) {
4273 		ipv6_pond_reference(&pond, inpond, MDL);
4274 	} else {
4275 		add_ipv6_pond_to_network(group, &pond);
4276 	}
4277 
4278 	/* Now that we have a pond add the nets we have parsed */
4279 	for (p=nets; p != NULL; p=p->next) {
4280 		add_ipv6_pool_to_subnet(group->subnet, type,
4281 					&p->cidrnet.lo_addr,
4282 					p->cidrnet.bits, 128, pond);
4283 	}
4284 
4285 	/* if we allocated a list free it now */
4286 	if (nets != &net)
4287 		free_iaddrcidrnetlist(&nets);
4288 
4289 	ipv6_pond_dereference(&pond, MDL);
4290 
4291 	token = next_token(NULL, NULL, cfile);
4292 	if (token != SEMI) {
4293 		parse_warn(cfile, "semicolon expected.");
4294 		skip_to_semi(cfile);
4295 		return;
4296 	}
4297 }
4298 
4299 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4300 
4301 void
parse_prefix6(struct parse * cfile,struct group * group,struct ipv6_pond * inpond)4302 parse_prefix6(struct parse *cfile,
4303 	      struct group *group,
4304 	      struct ipv6_pond *inpond) {
4305 	struct iaddr lo, hi;
4306 	int bits;
4307 	enum dhcp_token token;
4308 	const char *val;
4309 	struct iaddrcidrnetlist *nets;
4310 	struct iaddrcidrnetlist *p;
4311 	struct ipv6_pond *pond = NULL;
4312 
4313 	if (local_family != AF_INET6) {
4314 		parse_warn(cfile, "prefix6 statement is only supported "
4315 				  "in DHCPv6 mode.");
4316 		skip_to_semi(cfile);
4317 		return;
4318 	}
4319 
4320 	/* This is enforced by the caller, so it's just a sanity check. */
4321 	if (group->subnet == NULL)
4322 		log_fatal("Impossible condition at %s:%d.", MDL);
4323 
4324 	/*
4325 	 * Read starting and ending address.
4326 	 */
4327 	if (!parse_ip6_addr(cfile, &lo)) {
4328 		return;
4329 	}
4330 
4331 #if 0
4332 	/* Prefixes are not required to be within the subnet, but I'm not
4333 	 * entirely sure that we won't want to revive this code as a warning
4334 	 * in the future so I'm ifdeffing it
4335 	 */
4336 
4337 	/* Make sure starting prefix is within the subnet */
4338 	if (!addr_eq(group->subnet->net,
4339 		     subnet_number(lo, group->subnet->netmask))) {
4340 			      parse_warn(cfile, "prefix6 start prefix"
4341                                                 " is outside the subnet");
4342 			      skip_to_semi(cfile);
4343 		return;
4344 	}
4345 #endif
4346 
4347 	if (!parse_ip6_addr(cfile, &hi)) {
4348 		return;
4349 	}
4350 
4351 #if 0
4352 	/* Prefixes are not required to be within the subnet, but I'm not
4353 	 * entirely sure that we won't want to revive this code as a warning
4354 	 * in the future so I'm ifdeffing it
4355 	 */
4356 
4357 	/* Make sure ending prefix is within the subnet */
4358 	if (!addr_eq(group->subnet->net,
4359 		     subnet_number(hi, group->subnet->netmask))) {
4360 			      parse_warn(cfile, "prefix6 end prefix"
4361                                                 " is outside the subnet");
4362 			      skip_to_semi(cfile);
4363 		return;
4364 	}
4365 #endif
4366 
4367 	/*
4368 	 * Next is '/' number ';'.
4369 	 */
4370 	token = next_token(NULL, NULL, cfile);
4371 	if (token != SLASH) {
4372 		parse_warn(cfile, "expecting '/'");
4373 		if (token != SEMI)
4374 			skip_to_semi(cfile);
4375 		return;
4376 	}
4377 	token = next_token(&val, NULL, cfile);
4378 	if (token != NUMBER) {
4379 		parse_warn(cfile, "expecting number");
4380 		if (token != SEMI)
4381 			skip_to_semi(cfile);
4382 		return;
4383 	}
4384 	bits = atoi(val);
4385 	if ((bits <= 0) || (bits >= 128)) {
4386 		parse_warn(cfile, "networks have 0 to 128 bits (exclusive)");
4387 		return;
4388 	}
4389 
4390 #if 0
4391 	/* Prefixes are not required to be within the subnet, but I'm not
4392 	 * entirely sure that we won't want to revive this code as a warning
4393 	 * in the future so I'm ifdeffing it
4394 	 */
4395 
4396 	if (bits < group->subnet->prefix_len) {
4397 		parse_warn(cfile, "network mask smaller than subnet mask");
4398 		skip_to_semi(cfile);
4399 		return;
4400 	}
4401 #endif
4402 
4403 	if (!is_cidr_mask_valid(&lo, bits) ||
4404 	    !is_cidr_mask_valid(&hi, bits)) {
4405 		parse_warn(cfile, "network mask too short");
4406 		skip_to_semi(cfile);
4407 		return;
4408 	}
4409 	token = next_token(NULL, NULL, cfile);
4410 	if (token != SEMI) {
4411 		parse_warn(cfile, "semicolon expected.");
4412 		skip_to_semi(cfile);
4413 		return;
4414 	}
4415 
4416 	/*
4417 	 * Convert our range to a set of CIDR networks.
4418 	 */
4419 	nets = NULL;
4420 	if (range2cidr(&nets, &lo, &hi) != ISC_R_SUCCESS) {
4421 		log_fatal("Error converting prefix to CIDR");
4422 	}
4423 
4424 	/*
4425 	 * See if we have a pond for this set of pools.
4426 	 * If the caller supplied one we use it, otherwise
4427 	 * check the shared network
4428 	 */
4429 
4430 	if (inpond != NULL) {
4431 		ipv6_pond_reference(&pond, inpond, MDL);
4432 	} else {
4433 		add_ipv6_pond_to_network(group, &pond);
4434 	}
4435 
4436 	for (p = nets; p != NULL; p = p->next) {
4437 		/* Normalize and check. */
4438 		if (p->cidrnet.bits == 128) {
4439 			p->cidrnet.bits = bits;
4440 		}
4441 		if (p->cidrnet.bits > bits) {
4442 			parse_warn(cfile, "impossible mask length");
4443 			continue;
4444 		}
4445 		add_ipv6_pool_to_subnet(group->subnet, D6O_IA_PD,
4446 					&p->cidrnet.lo_addr,
4447 					p->cidrnet.bits, bits, pond);
4448 	}
4449 
4450 	free_iaddrcidrnetlist(&nets);
4451 }
4452 
4453 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4454 
4455 void
parse_fixed_prefix6(struct parse * cfile,struct host_decl * host_decl)4456 parse_fixed_prefix6(struct parse *cfile, struct host_decl *host_decl) {
4457 	struct iaddrcidrnetlist *ia, **h;
4458 	enum dhcp_token token;
4459 	const char *val;
4460 
4461 	/*
4462 	 * Get the head of the fixed-prefix list.
4463 	 */
4464 	h = &host_decl->fixed_prefix;
4465 
4466 	/*
4467 	 * Walk to the end.
4468 	 */
4469 	while (*h != NULL) {
4470 		h = &((*h)->next);
4471 	}
4472 
4473 	/*
4474 	 * Allocate a new iaddrcidrnetlist structure.
4475 	 */
4476 	ia = dmalloc(sizeof(*ia), MDL);
4477 	if (!ia) {
4478 		log_fatal("Out of memory");
4479 	}
4480 
4481 	/*
4482 	 * Parse it.
4483 	 */
4484 	if (!parse_ip6_addr(cfile, &ia->cidrnet.lo_addr)) {
4485 		dfree(ia, MDL);
4486 		return;
4487 	}
4488 	token = next_token(NULL, NULL, cfile);
4489 	if (token != SLASH) {
4490 		dfree(ia, MDL);
4491 		parse_warn(cfile, "expecting '/'");
4492 		if (token != SEMI)
4493 			skip_to_semi(cfile);
4494 		return;
4495 	}
4496 	token = next_token(&val, NULL, cfile);
4497 	if (token != NUMBER) {
4498 		dfree(ia, MDL);
4499 		parse_warn(cfile, "expecting number");
4500 		if (token != SEMI)
4501 			skip_to_semi(cfile);
4502 		return;
4503 	}
4504 	token = next_token(NULL, NULL, cfile);
4505 	if (token != SEMI) {
4506 		dfree(ia, MDL);
4507 		parse_warn(cfile, "semicolon expected.");
4508 		skip_to_semi(cfile);
4509 		return;
4510 	}
4511 
4512 	/*
4513 	 * Fill it.
4514 	 */
4515 	ia->cidrnet.bits = atoi(val);
4516 	if ((ia->cidrnet.bits < 0) || (ia->cidrnet.bits > 128)) {
4517 		dfree(ia, MDL);
4518 		parse_warn(cfile, "networks have 0 to 128 bits");
4519 		return;
4520 	}
4521 	if (!is_cidr_mask_valid(&ia->cidrnet.lo_addr, ia->cidrnet.bits)) {
4522 		dfree(ia, MDL);
4523 		parse_warn(cfile, "network mask too short");
4524 		return;
4525 	}
4526 
4527 	/*
4528 	 * Store it.
4529 	 */
4530 	*h = ia;
4531 	return;
4532 }
4533 
4534 /*!
4535  *
4536  * \brief Parse a pool6 statement
4537  *
4538  * Pool statements are used to group declarations and permit & deny information
4539  * with a specific address range.  They must be declared within a shared network
4540  * or subnet and there may be multiple pools withing a shared network or subnet.
4541  * Each pool may have a different set of permit or deny options.
4542  *
4543  * \param[in] cfile = the configuration file being parsed
4544  * \param[in] group = the group structure for this pool
4545  * \param[in] type  = the type of the enclosing statement.  This must be
4546  *		      SUBNET_DECL for this function.
4547  *
4548  * \return
4549  * void - This function either parses the statement and updates the structures
4550  *        or it generates an error message and possible halts the program if
4551  *        it encounters a problem.
4552  */
parse_pool6_statement(cfile,group,type)4553 void parse_pool6_statement (cfile, group, type)
4554 	struct parse *cfile;
4555 	struct group *group;
4556 	int type;
4557 {
4558 	enum dhcp_token token;
4559 	const char *val;
4560 	int done = 0;
4561 	struct ipv6_pond *pond, **p;
4562 	int declaration = 0;
4563 	isc_result_t status;
4564 
4565 	pond = NULL;
4566 	status = ipv6_pond_allocate(&pond, MDL);
4567 	if (status != ISC_R_SUCCESS)
4568 		log_fatal("no memory for pool6: %s",
4569 			  isc_result_totext (status));
4570 
4571 	if (type == SUBNET_DECL)
4572 		shared_network_reference(&pond->shared_network,
4573 					 group->subnet->shared_network,
4574 					 MDL);
4575 	else {
4576 		parse_warn(cfile, "pool6s are only valid inside "
4577 				  "subnet statements.");
4578 		ipv6_pond_dereference(&pond, MDL);
4579 		skip_to_semi(cfile);
4580 		return;
4581 	}
4582 
4583 	if (clone_group(&pond->group, group, MDL) == 0)
4584 		log_fatal("can't clone pool6 group.");
4585 
4586 	if (parse_lbrace(cfile) == 0) {
4587 		ipv6_pond_dereference(&pond, MDL);
4588 		return;
4589 	}
4590 
4591 	do {
4592 		token = peek_token(&val, NULL, cfile);
4593 		switch (token) {
4594 		      case RANGE6:
4595 			skip_token(NULL, NULL, cfile);
4596 			parse_address_range6(cfile, group, pond);
4597 			break;
4598 
4599 		      case PREFIX6:
4600 			skip_token(NULL, NULL, cfile);
4601 			parse_prefix6(cfile, group, pond);
4602 			break;
4603 
4604 		      case ALLOW:
4605 			skip_token(NULL, NULL, cfile);
4606 			get_permit(cfile, &pond->permit_list, 1,
4607 				   &pond->valid_from, &pond->valid_until);
4608 			break;
4609 
4610 		      case DENY:
4611 			skip_token(NULL, NULL, cfile);
4612 			get_permit(cfile, &pond->prohibit_list, 0,
4613 				   &pond->valid_from, &pond->valid_until);
4614 			break;
4615 
4616 		      case RBRACE:
4617 			skip_token(&val, NULL, cfile);
4618 			done = 1;
4619 			break;
4620 
4621 		      case END_OF_FILE:
4622 			/*
4623 			 * We can get to END_OF_FILE if, for instance,
4624 			 * the parse_statement() reads all available tokens
4625 			 * and leaves us at the end.
4626 			 */
4627 			parse_warn(cfile, "unexpected end of file");
4628 			goto cleanup;
4629 
4630 		      default:
4631 			declaration = parse_statement(cfile, pond->group,
4632 						      POOL_DECL, NULL,
4633 						      declaration);
4634 			break;
4635 		}
4636 	} while (!done);
4637 
4638 	/*
4639 	 * A possible optimization is to see if this pond can be merged into
4640 	 * an already existing pond.  But I'll pass on that for now as we need
4641 	 * to repoint the leases to the other pond which is annoying. SAR
4642 	 */
4643 
4644 	/*
4645 	 * Add this pond to the list (will need updating if we add the
4646 	 * optimization).
4647 	 */
4648 
4649 	p = &pond->shared_network->ipv6_pond;
4650 	for (; *p; p = &((*p)->next))
4651 		;
4652 	ipv6_pond_reference(p, pond, MDL);
4653 
4654 	/* Don't allow a pool6 declaration with no addresses or
4655 	   prefixes, since it is probably a configuration error. */
4656 	if (pond->ipv6_pools == NULL) {
4657 		parse_warn (cfile, "Pool6 declaration with no %s.",
4658 			    "address range6 or prefix6");
4659 		log_error ("Pool6 declarations must always contain at least");
4660 		log_error ("one range6 or prefix6 statement.");
4661 	}
4662 
4663 cleanup:
4664 	ipv6_pond_dereference(&pond, MDL);
4665 }
4666 
4667 
4668 
4669 #endif /* DHCPv6 */
4670 
4671 /* allow-deny-keyword :== BOOTP
4672    			| BOOTING
4673 			| DYNAMIC_BOOTP
4674 			| UNKNOWN_CLIENTS */
4675 
parse_allow_deny(oc,cfile,flag)4676 int parse_allow_deny (oc, cfile, flag)
4677 	struct option_cache **oc;
4678 	struct parse *cfile;
4679 	int flag;
4680 {
4681 	enum dhcp_token token;
4682 	const char *val;
4683 	unsigned char rf = flag;
4684 	unsigned code;
4685 	struct option *option = NULL;
4686 	struct expression *data = (struct expression *)0;
4687 	int status;
4688 
4689 	if (!make_const_data (&data, &rf, 1, 0, 1, MDL))
4690 		return 0;
4691 
4692 	token = next_token (&val, (unsigned *)0, cfile);
4693 	switch (token) {
4694 	      case TOKEN_BOOTP:
4695 		code = SV_ALLOW_BOOTP;
4696 		break;
4697 
4698 	      case BOOTING:
4699 		code = SV_ALLOW_BOOTING;
4700 		break;
4701 
4702 	      case DYNAMIC_BOOTP:
4703 		code = SV_DYNAMIC_BOOTP;
4704 		break;
4705 
4706 	      case UNKNOWN_CLIENTS:
4707 		code = SV_BOOT_UNKNOWN_CLIENTS;
4708 		break;
4709 
4710 	      case DUPLICATES:
4711 		code = SV_DUPLICATES;
4712 		break;
4713 
4714 	      case DECLINES:
4715 		code= SV_DECLINES;
4716 		break;
4717 
4718 	      case CLIENT_UPDATES:
4719 		code = SV_CLIENT_UPDATES;
4720 		break;
4721 
4722 	      case LEASEQUERY:
4723 		code = SV_LEASEQUERY;
4724 		break;
4725 
4726 	      default:
4727 		parse_warn (cfile, "expecting allow/deny key");
4728 		skip_to_semi (cfile);
4729 		expression_dereference (&data, MDL);
4730 		return 0;
4731 	}
4732 	/* Reference on option is passed to option cache. */
4733 	if (!option_code_hash_lookup(&option, server_universe.code_hash,
4734 				     &code, 0, MDL))
4735 		log_fatal("Unable to find server option %u (%s:%d).",
4736 			  code, MDL);
4737 	status = option_cache(oc, NULL, data, option, MDL);
4738 	expression_dereference (&data, MDL);
4739 	parse_semi (cfile);
4740 	return status;
4741 }
4742 
4743 void
parse_ia_na_declaration(struct parse * cfile)4744 parse_ia_na_declaration(struct parse *cfile) {
4745 #if !defined(DHCPv6)
4746 	parse_warn(cfile, "No DHCPv6 support.");
4747 	skip_to_semi(cfile);
4748 #else /* defined(DHCPv6) */
4749 	enum dhcp_token token;
4750 	struct ia_xx *ia = NULL;
4751 	const char *val;
4752 	struct ia_xx *old_ia;
4753 	u_int32_t iaid;
4754 	struct iaddr iaddr;
4755 	binding_state_t state;
4756 	u_int32_t prefer;
4757 	u_int32_t valid;
4758 	TIME end_time;
4759 	struct iasubopt *iaaddr;
4760 	struct ipv6_pool *pool;
4761 	char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4762 	isc_boolean_t newbinding;
4763 	struct binding_scope *scope = NULL;
4764 	struct binding *bnd;
4765 	struct binding_value *nv = NULL;
4766 	struct executable_statement *on_star[2] = {NULL, NULL};
4767 	int lose, i;
4768 
4769         if (local_family != AF_INET6) {
4770                 parse_warn(cfile, "IA_NA is only supported in DHCPv6 mode.");
4771                 skip_to_semi(cfile);
4772                 return;
4773         }
4774 
4775 	if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
4776 		return;
4777 	}
4778 
4779 	ia->ia_type = D6O_IA_NA;
4780 
4781 	token = next_token(&val, NULL, cfile);
4782 	if (token != LBRACE) {
4783 		parse_warn(cfile, "corrupt lease file; expecting left brace");
4784 		skip_to_semi(cfile);
4785 		ia_dereference(&ia, MDL);
4786 		return;
4787 	}
4788 
4789 	for (;;) {
4790 		token = next_token(&val, NULL, cfile);
4791 		if (token == RBRACE) break;
4792 
4793 		if (token == CLTT) {
4794 			ia->cltt = parse_date (cfile);
4795 			continue;
4796 		}
4797 
4798 		if (token != IAADDR) {
4799 			parse_warn(cfile, "corrupt lease file; "
4800 					  "expecting IAADDR or right brace");
4801 			skip_to_semi(cfile);
4802 			return;
4803 		}
4804 
4805 		if (!parse_ip6_addr(cfile, &iaddr)) {
4806 			parse_warn(cfile, "corrupt lease file; "
4807 					  "expecting IPv6 address");
4808 			skip_to_semi(cfile);
4809 			return;
4810 		}
4811 
4812 		token = next_token(&val, NULL, cfile);
4813 		if (token != LBRACE) {
4814 			parse_warn(cfile, "corrupt lease file; "
4815 					  "expecting left brace");
4816 			skip_to_semi(cfile);
4817 			return;
4818 		}
4819 
4820 		state = FTS_LAST+1;
4821 		prefer = valid = 0;
4822 		end_time = -1;
4823 		for (;;) {
4824 			token = next_token(&val, NULL, cfile);
4825 			if (token == RBRACE) break;
4826 
4827 			switch(token) {
4828 			     case END_OF_FILE:
4829 			        /* We hit the end of file and don't know
4830 				 * what parts of the lease we may be missing
4831 				 * don't try to salvage the lease
4832 			         */
4833 				parse_warn(cfile, "corrupt lease file; "
4834 					   "unexpected end of file");
4835 				return;
4836 
4837 				/* Lease binding state. */
4838 			     case BINDING:
4839 				token = next_token(&val, NULL, cfile);
4840 				if (token != STATE) {
4841 					parse_warn(cfile, "corrupt lease file; "
4842 							  "expecting state");
4843 					skip_to_semi(cfile);
4844 					return;
4845 				}
4846 				token = next_token(&val, NULL, cfile);
4847 				switch (token) {
4848 					case TOKEN_ABANDONED:
4849 						state = FTS_ABANDONED;
4850 						break;
4851 					case TOKEN_FREE:
4852 						state = FTS_FREE;
4853 						break;
4854 					case TOKEN_ACTIVE:
4855 						state = FTS_ACTIVE;
4856 						break;
4857 					case TOKEN_EXPIRED:
4858 						state = FTS_EXPIRED;
4859 						break;
4860 					case TOKEN_RELEASED:
4861 						state = FTS_RELEASED;
4862 						break;
4863 					default:
4864 						parse_warn(cfile,
4865 							   "corrupt lease "
4866 							   "file; "
4867 					    		   "expecting a "
4868 							   "binding state.");
4869 						skip_to_semi(cfile);
4870 						return;
4871 				}
4872 
4873 				token = next_token(&val, NULL, cfile);
4874 				if (token != SEMI) {
4875 					parse_warn(cfile, "corrupt lease file; "
4876 							  "expecting "
4877 							  "semicolon.");
4878 				}
4879 				break;
4880 
4881 				/* Lease preferred lifetime. */
4882 			      case PREFERRED_LIFE:
4883 				token = next_token(&val, NULL, cfile);
4884 				if (token != NUMBER) {
4885 					parse_warn(cfile, "%s is not a valid "
4886 							  "preferred time",
4887 						   val);
4888 					skip_to_semi(cfile);
4889 					continue;
4890 				}
4891 				prefer = atoi (val);
4892 
4893 				/*
4894 				 * Currently we peek for the semi-colon to
4895 				 * allow processing of older lease files that
4896 				 * don't have the semi-colon.  Eventually we
4897 				 * should remove the peeking code.
4898 				 */
4899 				token = peek_token(&val, NULL, cfile);
4900 				if (token == SEMI) {
4901 					skip_token(&val, NULL, cfile);
4902 				} else {
4903 					parse_warn(cfile,
4904 						   "corrupt lease file; "
4905 						   "expecting semicolon.");
4906 				}
4907 				break;
4908 
4909 				/* Lease valid lifetime. */
4910 			      case MAX_LIFE:
4911 				token = next_token(&val, NULL, cfile);
4912 				if (token != NUMBER) {
4913 					parse_warn(cfile, "%s is not a valid "
4914 							  "max time",
4915 						   val);
4916 					skip_to_semi(cfile);
4917 					continue;
4918 				}
4919 				valid = atoi (val);
4920 
4921 				/*
4922 				 * Currently we peek for the semi-colon to
4923 				 * allow processing of older lease files that
4924 				 * don't have the semi-colon.  Eventually we
4925 				 * should remove the peeking code.
4926 				 */
4927 				token = peek_token(&val, NULL, cfile);
4928 				if (token == SEMI) {
4929 					skip_token(&val, NULL, cfile);
4930 				} else {
4931 					parse_warn(cfile,
4932 						   "corrupt lease file; "
4933 						   "expecting semicolon.");
4934 				}
4935 				break;
4936 
4937 				/* Lease expiration time. */
4938 			      case ENDS:
4939 				end_time = parse_date(cfile);
4940 				break;
4941 
4942 				/* Lease binding scopes. */
4943 			      case TOKEN_SET:
4944 				token = next_token(&val, NULL, cfile);
4945 				if ((token != NAME) &&
4946 				    (token != NUMBER_OR_NAME)) {
4947 					parse_warn(cfile, "%s is not a valid "
4948 							  "variable name",
4949 						   val);
4950 					skip_to_semi(cfile);
4951 					continue;
4952 				}
4953 
4954 				if (scope != NULL)
4955 					bnd = find_binding(scope, val);
4956 				else {
4957 					if (!binding_scope_allocate(&scope,
4958 								    MDL)) {
4959 						log_fatal("Out of memory for "
4960 							  "lease binding "
4961 							  "scope.");
4962 					}
4963 
4964 					bnd = NULL;
4965 				}
4966 
4967 				if (bnd == NULL) {
4968 					bnd = dmalloc(sizeof(*bnd),
4969 							  MDL);
4970 					if (bnd == NULL) {
4971 						log_fatal("No memory for "
4972 							  "lease binding.");
4973 					}
4974 
4975 					bnd->name = dmalloc(strlen(val) + 1,
4976 							    MDL);
4977 					if (bnd->name == NULL) {
4978 						log_fatal("No memory for "
4979 							  "binding name.");
4980 					}
4981 					strcpy(bnd->name, val);
4982 
4983 					newbinding = ISC_TRUE;
4984 				} else {
4985 					newbinding = ISC_FALSE;
4986 				}
4987 
4988 				if (!binding_value_allocate(&nv, MDL)) {
4989 					log_fatal("no memory for binding "
4990 						  "value.");
4991 				}
4992 
4993 				token = next_token(NULL, NULL, cfile);
4994 				if (token != EQUAL) {
4995 					parse_warn(cfile, "expecting '=' in "
4996 							  "set statement.");
4997 					goto binding_err;
4998 				}
4999 
5000 				if (!parse_binding_value(cfile, nv)) {
5001 				      binding_err:
5002 					binding_value_dereference(&nv, MDL);
5003 					binding_scope_dereference(&scope, MDL);
5004 					return;
5005 				}
5006 
5007 				if (newbinding) {
5008 					binding_value_reference(&bnd->value,
5009 								nv, MDL);
5010 					bnd->next = scope->bindings;
5011 					scope->bindings = bnd;
5012 				} else {
5013 					binding_value_dereference(&bnd->value,
5014 								  MDL);
5015 					binding_value_reference(&bnd->value,
5016 								nv, MDL);
5017 				}
5018 
5019 				binding_value_dereference(&nv, MDL);
5020 				parse_semi(cfile);
5021 				break;
5022 
5023 			      case ON:
5024 				lose = 0;
5025 				/*
5026 				 * Depending on the user config we may
5027 				 * have one or two on statements.  We
5028 				 * need to save information about both
5029 				 * of them until we allocate the
5030 				 * iasubopt to hold them.
5031 				 */
5032 				if (on_star[0] == NULL) {
5033 					if (!parse_on_statement (&on_star[0],
5034 								 cfile,
5035 								 &lose)) {
5036 						parse_warn(cfile,
5037 							   "corrupt lease "
5038 							   "file; bad ON "
5039 							   "statement");
5040 						skip_to_rbrace (cfile, 1);
5041 						return;
5042 					}
5043 				} else {
5044 					if (!parse_on_statement (&on_star[1],
5045 								 cfile,
5046 								 &lose)) {
5047 						parse_warn(cfile,
5048 							   "corrupt lease "
5049 							   "file; bad ON "
5050 							   "statement");
5051 						skip_to_rbrace (cfile, 1);
5052 						return;
5053 					}
5054 				}
5055 
5056 				break;
5057 
5058 			      default:
5059 				parse_warn(cfile, "corrupt lease file; "
5060 						  "expecting ia_na contents, "
5061 						  "got '%s'", val);
5062 				skip_to_semi(cfile);
5063 				continue;
5064 			}
5065 		}
5066 
5067 		if (state == FTS_LAST+1) {
5068 			parse_warn(cfile, "corrupt lease file; "
5069 					  "missing state in iaaddr");
5070 			return;
5071 		}
5072 		if (end_time == -1) {
5073 			parse_warn(cfile, "corrupt lease file; "
5074 					  "missing end time in iaaddr");
5075 			return;
5076 		}
5077 
5078 		iaaddr = NULL;
5079 		if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5080 			log_fatal("Out of memory.");
5081 		}
5082 		memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5083 		iaaddr->plen = 0;
5084 		iaaddr->state = state;
5085 		iaaddr->prefer = prefer;
5086 		iaaddr->valid = valid;
5087 		if (iaaddr->state == FTS_RELEASED)
5088 			iaaddr->hard_lifetime_end_time = end_time;
5089 
5090 		if (scope != NULL) {
5091 			binding_scope_reference(&iaaddr->scope, scope, MDL);
5092 			binding_scope_dereference(&scope, MDL);
5093 		}
5094 
5095 		/*
5096 		 * Check on both on statements.  Because of how we write the
5097 		 * lease file we know which is which if we have two but it's
5098 		 * easier to write the code to be independent.  We do assume
5099 		 * that the statements won't overlap.
5100 		 */
5101 		for (i = 0;
5102 		     (i < 2) && on_star[i] != NULL ;
5103 		     i++) {
5104 			if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5105 			    on_star[i]->data.on.statements) {
5106 				executable_statement_reference
5107 					(&iaaddr->on_star.on_expiry,
5108 					 on_star[i]->data.on.statements, MDL);
5109 			}
5110 			if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5111 			    on_star[i]->data.on.statements) {
5112 				executable_statement_reference
5113 					(&iaaddr->on_star.on_release,
5114 					 on_star[i]->data.on.statements, MDL);
5115 			}
5116 			executable_statement_dereference (&on_star[i], MDL);
5117 		}
5118 
5119 		/* find the pool this address is in */
5120 		pool = NULL;
5121 		if (find_ipv6_pool(&pool, D6O_IA_NA,
5122 				   &iaaddr->addr) != ISC_R_SUCCESS) {
5123 			inet_ntop(AF_INET6, &iaaddr->addr,
5124 				  addr_buf, sizeof(addr_buf));
5125 			log_error("No pool found for IA_NA address %s",
5126 				  addr_buf);
5127 			iasubopt_dereference(&iaaddr, MDL);
5128 			continue;
5129 		}
5130 #ifdef EUI_64
5131 		if ((pool->ipv6_pond->use_eui_64) &&
5132 		    (!valid_for_eui_64_pool(pool, &ia->iaid_duid, IAID_LEN,
5133 					    &iaaddr->addr))) {
5134 			log_error("Non EUI-64 lease in EUI-64 pool: %s"
5135 				  " discarding it",
5136 				  pin6_addr(&iaaddr->addr));
5137 			iasubopt_dereference(&iaaddr, MDL);
5138 			continue;
5139 		}
5140 #endif
5141 
5142 		/* remove old information */
5143 		if (cleanup_lease6(ia_na_active, pool,
5144 				   iaaddr, ia) != ISC_R_SUCCESS) {
5145 			inet_ntop(AF_INET6, &iaaddr->addr,
5146 				  addr_buf, sizeof(addr_buf));
5147 			parse_warn(cfile, "duplicate na lease for address %s",
5148 				   addr_buf);
5149 		}
5150 
5151 		/*
5152 		 * if we like the lease we add it to our various structues
5153 		 * otherwise we leave it and it will get cleaned when we
5154 		 * do the iasubopt_dereference.
5155 		 */
5156 		if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5157 			ia_add_iasubopt(ia, iaaddr, MDL);
5158 			ia_reference(&iaaddr->ia, ia, MDL);
5159 			add_lease6(pool, iaaddr, end_time);
5160 		}
5161 
5162 		iasubopt_dereference(&iaaddr, MDL);
5163 		ipv6_pool_dereference(&pool, MDL);
5164 	}
5165 
5166 	/*
5167 	 * If we have an existing record for this IA_NA, remove it.
5168 	 */
5169 	old_ia = NULL;
5170 	if (ia_hash_lookup(&old_ia, ia_na_active,
5171 			   (unsigned char *)ia->iaid_duid.data,
5172 			   ia->iaid_duid.len, MDL)) {
5173 		ia_hash_delete(ia_na_active,
5174 			       (unsigned char *)ia->iaid_duid.data,
5175 			       ia->iaid_duid.len, MDL);
5176 		ia_dereference(&old_ia, MDL);
5177 	}
5178 
5179 	/*
5180 	 * If we have addresses, add this, otherwise don't bother.
5181 	 */
5182 	if (ia->num_iasubopt > 0) {
5183 		ia_hash_add(ia_na_active,
5184 			    (unsigned char *)ia->iaid_duid.data,
5185 			    ia->iaid_duid.len, ia, MDL);
5186 	}
5187 	ia_dereference(&ia, MDL);
5188 #endif /* defined(DHCPv6) */
5189 }
5190 
5191 void
parse_ia_ta_declaration(struct parse * cfile)5192 parse_ia_ta_declaration(struct parse *cfile) {
5193 #if !defined(DHCPv6)
5194 	parse_warn(cfile, "No DHCPv6 support.");
5195 	skip_to_semi(cfile);
5196 #else /* defined(DHCPv6) */
5197 	enum dhcp_token token;
5198 	struct ia_xx *ia = NULL;
5199 	const char *val;
5200 	struct ia_xx *old_ia;
5201 	u_int32_t iaid;
5202 	struct iaddr iaddr;
5203 	binding_state_t state;
5204 	u_int32_t prefer;
5205 	u_int32_t valid;
5206 	TIME end_time;
5207 	struct iasubopt *iaaddr;
5208 	struct ipv6_pool *pool;
5209 	char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5210 	isc_boolean_t newbinding;
5211 	struct binding_scope *scope = NULL;
5212 	struct binding *bnd;
5213 	struct binding_value *nv = NULL;
5214 	struct executable_statement *on_star[2] = {NULL, NULL};
5215 	int lose, i;
5216 
5217         if (local_family != AF_INET6) {
5218                 parse_warn(cfile, "IA_TA is only supported in DHCPv6 mode.");
5219                 skip_to_semi(cfile);
5220                 return;
5221         }
5222 
5223 	if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5224 		return;
5225 	}
5226 
5227 	ia->ia_type = D6O_IA_TA;
5228 
5229 	token = next_token(&val, NULL, cfile);
5230 	if (token != LBRACE) {
5231 		parse_warn(cfile, "corrupt lease file; expecting left brace");
5232 		skip_to_semi(cfile);
5233 		ia_dereference(&ia, MDL);
5234 		return;
5235 	}
5236 
5237 	for (;;) {
5238 		token = next_token(&val, NULL, cfile);
5239 		if (token == RBRACE) break;
5240 
5241 		if (token == CLTT) {
5242 			ia->cltt = parse_date (cfile);
5243 			continue;
5244 		}
5245 
5246 		if (token != IAADDR) {
5247 			parse_warn(cfile, "corrupt lease file; "
5248 					  "expecting IAADDR or right brace");
5249 			skip_to_semi(cfile);
5250 			return;
5251 		}
5252 
5253 		if (!parse_ip6_addr(cfile, &iaddr)) {
5254 			parse_warn(cfile, "corrupt lease file; "
5255 					  "expecting IPv6 address");
5256 			skip_to_semi(cfile);
5257 			return;
5258 		}
5259 
5260 		token = next_token(&val, NULL, cfile);
5261 		if (token != LBRACE) {
5262 			parse_warn(cfile, "corrupt lease file; "
5263 					  "expecting left brace");
5264 			skip_to_semi(cfile);
5265 			return;
5266 		}
5267 
5268 		state = FTS_LAST+1;
5269 		prefer = valid = 0;
5270 		end_time = -1;
5271 		for (;;) {
5272 			token = next_token(&val, NULL, cfile);
5273 			if (token == RBRACE) break;
5274 
5275 			switch(token) {
5276 			     case END_OF_FILE:
5277 			        /* We hit the end of file and don't know
5278 				 * what parts of the lease we may be missing
5279 				 * don't try to salvage the lease
5280 			         */
5281 				parse_warn(cfile, "corrupt lease file; "
5282 					   "unexpected end of file");
5283 				return;
5284 
5285 				/* Lease binding state. */
5286 			     case BINDING:
5287 				token = next_token(&val, NULL, cfile);
5288 				if (token != STATE) {
5289 					parse_warn(cfile, "corrupt lease file; "
5290 							  "expecting state");
5291 					skip_to_semi(cfile);
5292 					return;
5293 				}
5294 				token = next_token(&val, NULL, cfile);
5295 				switch (token) {
5296 					case TOKEN_ABANDONED:
5297 						state = FTS_ABANDONED;
5298 						break;
5299 					case TOKEN_FREE:
5300 						state = FTS_FREE;
5301 						break;
5302 					case TOKEN_ACTIVE:
5303 						state = FTS_ACTIVE;
5304 						break;
5305 					case TOKEN_EXPIRED:
5306 						state = FTS_EXPIRED;
5307 						break;
5308 					case TOKEN_RELEASED:
5309 						state = FTS_RELEASED;
5310 						break;
5311 					default:
5312 						parse_warn(cfile,
5313 							   "corrupt lease "
5314 							   "file; "
5315 					    		   "expecting a "
5316 							   "binding state.");
5317 						skip_to_semi(cfile);
5318 						return;
5319 				}
5320 
5321 				token = next_token(&val, NULL, cfile);
5322 				if (token != SEMI) {
5323 					parse_warn(cfile, "corrupt lease file; "
5324 							  "expecting "
5325 							  "semicolon.");
5326 				}
5327 				break;
5328 
5329 				/* Lease preferred lifetime. */
5330 			      case PREFERRED_LIFE:
5331 				token = next_token(&val, NULL, cfile);
5332 				if (token != NUMBER) {
5333 					parse_warn(cfile, "%s is not a valid "
5334 							  "preferred time",
5335 						   val);
5336 					skip_to_semi(cfile);
5337 					continue;
5338 				}
5339 				prefer = atoi (val);
5340 
5341 				/*
5342 				 * Currently we peek for the semi-colon to
5343 				 * allow processing of older lease files that
5344 				 * don't have the semi-colon.  Eventually we
5345 				 * should remove the peeking code.
5346 				 */
5347 				token = peek_token(&val, NULL, cfile);
5348 				if (token == SEMI) {
5349 					skip_token(&val, NULL, cfile);
5350 				} else {
5351 					parse_warn(cfile,
5352 						   "corrupt lease file; "
5353 						   "expecting semicolon.");
5354 				}
5355 				break;
5356 
5357 				/* Lease valid lifetime. */
5358 			      case MAX_LIFE:
5359 				token = next_token(&val, NULL, cfile);
5360 				if (token != NUMBER) {
5361 					parse_warn(cfile, "%s is not a valid "
5362 							  "max time",
5363 						   val);
5364 					skip_to_semi(cfile);
5365 					continue;
5366 				}
5367 				valid = atoi (val);
5368 
5369 				/*
5370 				 * Currently we peek for the semi-colon to
5371 				 * allow processing of older lease files that
5372 				 * don't have the semi-colon.  Eventually we
5373 				 * should remove the peeking code.
5374 				 */
5375 				token = peek_token(&val, NULL, cfile);
5376 				if (token == SEMI) {
5377 					skip_token(&val, NULL, cfile);
5378 				} else {
5379 					parse_warn(cfile,
5380 						   "corrupt lease file; "
5381 						   "expecting semicolon.");
5382 				}
5383 				break;
5384 
5385 				/* Lease expiration time. */
5386 			      case ENDS:
5387 				end_time = parse_date(cfile);
5388 				break;
5389 
5390 				/* Lease binding scopes. */
5391 			      case TOKEN_SET:
5392 				token = next_token(&val, NULL, cfile);
5393 				if ((token != NAME) &&
5394 				    (token != NUMBER_OR_NAME)) {
5395 					parse_warn(cfile, "%s is not a valid "
5396 							  "variable name",
5397 						   val);
5398 					skip_to_semi(cfile);
5399 					continue;
5400 				}
5401 
5402 				if (scope != NULL)
5403 					bnd = find_binding(scope, val);
5404 				else {
5405 					if (!binding_scope_allocate(&scope,
5406 								    MDL)) {
5407 						log_fatal("Out of memory for "
5408 							  "lease binding "
5409 							  "scope.");
5410 					}
5411 
5412 					bnd = NULL;
5413 				}
5414 
5415 				if (bnd == NULL) {
5416 					bnd = dmalloc(sizeof(*bnd),
5417 							  MDL);
5418 					if (bnd == NULL) {
5419 						log_fatal("No memory for "
5420 							  "lease binding.");
5421 					}
5422 
5423 					bnd->name = dmalloc(strlen(val) + 1,
5424 							    MDL);
5425 					if (bnd->name == NULL) {
5426 						log_fatal("No memory for "
5427 							  "binding name.");
5428 					}
5429 					strcpy(bnd->name, val);
5430 
5431 					newbinding = ISC_TRUE;
5432 				} else {
5433 					newbinding = ISC_FALSE;
5434 				}
5435 
5436 				if (!binding_value_allocate(&nv, MDL)) {
5437 					log_fatal("no memory for binding "
5438 						  "value.");
5439 				}
5440 
5441 				token = next_token(NULL, NULL, cfile);
5442 				if (token != EQUAL) {
5443 					parse_warn(cfile, "expecting '=' in "
5444 							  "set statement.");
5445 					goto binding_err;
5446 				}
5447 
5448 				if (!parse_binding_value(cfile, nv)) {
5449 				      binding_err:
5450 					binding_value_dereference(&nv, MDL);
5451 					binding_scope_dereference(&scope, MDL);
5452 					return;
5453 				}
5454 
5455 				if (newbinding) {
5456 					binding_value_reference(&bnd->value,
5457 								nv, MDL);
5458 					bnd->next = scope->bindings;
5459 					scope->bindings = bnd;
5460 				} else {
5461 					binding_value_dereference(&bnd->value,
5462 								  MDL);
5463 					binding_value_reference(&bnd->value,
5464 								nv, MDL);
5465 				}
5466 
5467 				binding_value_dereference(&nv, MDL);
5468 				parse_semi(cfile);
5469 				break;
5470 
5471 			      case ON:
5472 				lose = 0;
5473 				/*
5474 				 * Depending on the user config we may
5475 				 * have one or two on statements.  We
5476 				 * need to save information about both
5477 				 * of them until we allocate the
5478 				 * iasubopt to hold them.
5479 				 */
5480 				if (on_star[0] == NULL) {
5481 					if (!parse_on_statement (&on_star[0],
5482 								 cfile,
5483 								 &lose)) {
5484 						parse_warn(cfile,
5485 							   "corrupt lease "
5486 							   "file; bad ON "
5487 							   "statement");
5488 						skip_to_rbrace (cfile, 1);
5489 						return;
5490 					}
5491 				} else {
5492 					if (!parse_on_statement (&on_star[1],
5493 								 cfile,
5494 								 &lose)) {
5495 						parse_warn(cfile,
5496 							   "corrupt lease "
5497 							   "file; bad ON "
5498 							   "statement");
5499 						skip_to_rbrace (cfile, 1);
5500 						return;
5501 					}
5502 				}
5503 
5504 				break;
5505 
5506 			      default:
5507 				parse_warn(cfile, "corrupt lease file; "
5508 						  "expecting ia_ta contents, "
5509 						  "got '%s'", val);
5510 				skip_to_semi(cfile);
5511 				continue;
5512 			}
5513 		}
5514 
5515 		if (state == FTS_LAST+1) {
5516 			parse_warn(cfile, "corrupt lease file; "
5517 					  "missing state in iaaddr");
5518 			return;
5519 		}
5520 		if (end_time == -1) {
5521 			parse_warn(cfile, "corrupt lease file; "
5522 					  "missing end time in iaaddr");
5523 			return;
5524 		}
5525 
5526 		iaaddr = NULL;
5527 		if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) {
5528 			log_fatal("Out of memory.");
5529 		}
5530 		memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr));
5531 		iaaddr->plen = 0;
5532 		iaaddr->state = state;
5533 		iaaddr->prefer = prefer;
5534 		iaaddr->valid = valid;
5535 		if (iaaddr->state == FTS_RELEASED)
5536 			iaaddr->hard_lifetime_end_time = end_time;
5537 
5538 		if (scope != NULL) {
5539 			binding_scope_reference(&iaaddr->scope, scope, MDL);
5540 			binding_scope_dereference(&scope, MDL);
5541 		}
5542 
5543 		/*
5544 		 * Check on both on statements.  Because of how we write the
5545 		 * lease file we know which is which if we have two but it's
5546 		 * easier to write the code to be independent.  We do assume
5547 		 * that the statements won't overlap.
5548 		 */
5549 		for (i = 0;
5550 		     (i < 2) && on_star[i] != NULL ;
5551 		     i++) {
5552 			if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5553 			    on_star[i]->data.on.statements) {
5554 				executable_statement_reference
5555 					(&iaaddr->on_star.on_expiry,
5556 					 on_star[i]->data.on.statements, MDL);
5557 			}
5558 			if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5559 			    on_star[i]->data.on.statements) {
5560 				executable_statement_reference
5561 					(&iaaddr->on_star.on_release,
5562 					 on_star[i]->data.on.statements, MDL);
5563 			}
5564 			executable_statement_dereference (&on_star[i], MDL);
5565 		}
5566 
5567 		/* find the pool this address is in */
5568 		pool = NULL;
5569 		if (find_ipv6_pool(&pool, D6O_IA_TA,
5570 				   &iaaddr->addr) != ISC_R_SUCCESS) {
5571 			inet_ntop(AF_INET6, &iaaddr->addr,
5572 				  addr_buf, sizeof(addr_buf));
5573 			log_error("No pool found for IA_TA address %s",
5574 				  addr_buf);
5575 			iasubopt_dereference(&iaaddr, MDL);
5576 			continue;
5577 		}
5578 
5579 		/* remove old information */
5580 		if (cleanup_lease6(ia_ta_active, pool,
5581 				   iaaddr, ia) != ISC_R_SUCCESS) {
5582 			inet_ntop(AF_INET6, &iaaddr->addr,
5583 				  addr_buf, sizeof(addr_buf));
5584 			parse_warn(cfile, "duplicate ta lease for address %s",
5585 				   addr_buf);
5586 		}
5587 
5588 		/*
5589 		 * if we like the lease we add it to our various structues
5590 		 * otherwise we leave it and it will get cleaned when we
5591 		 * do the iasubopt_dereference.
5592 		 */
5593 		if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
5594 			ia_add_iasubopt(ia, iaaddr, MDL);
5595 			ia_reference(&iaaddr->ia, ia, MDL);
5596 			add_lease6(pool, iaaddr, end_time);
5597 		}
5598 
5599 		ipv6_pool_dereference(&pool, MDL);
5600 		iasubopt_dereference(&iaaddr, MDL);
5601 	}
5602 
5603 	/*
5604 	 * If we have an existing record for this IA_TA, remove it.
5605 	 */
5606 	old_ia = NULL;
5607 	if (ia_hash_lookup(&old_ia, ia_ta_active,
5608 			   (unsigned char *)ia->iaid_duid.data,
5609 			   ia->iaid_duid.len, MDL)) {
5610 		ia_hash_delete(ia_ta_active,
5611 			       (unsigned char *)ia->iaid_duid.data,
5612 			       ia->iaid_duid.len, MDL);
5613 		ia_dereference(&old_ia, MDL);
5614 	}
5615 
5616 	/*
5617 	 * If we have addresses, add this, otherwise don't bother.
5618 	 */
5619 	if (ia->num_iasubopt > 0) {
5620 		ia_hash_add(ia_ta_active,
5621 			    (unsigned char *)ia->iaid_duid.data,
5622 			    ia->iaid_duid.len, ia, MDL);
5623 	}
5624 	ia_dereference(&ia, MDL);
5625 #endif /* defined(DHCPv6) */
5626 }
5627 
5628 void
parse_ia_pd_declaration(struct parse * cfile)5629 parse_ia_pd_declaration(struct parse *cfile) {
5630 #if !defined(DHCPv6)
5631 	parse_warn(cfile, "No DHCPv6 support.");
5632 	skip_to_semi(cfile);
5633 #else /* defined(DHCPv6) */
5634 	enum dhcp_token token;
5635 	struct ia_xx *ia = NULL;
5636 	const char *val;
5637 	struct ia_xx *old_ia;
5638 	u_int32_t iaid;
5639 	struct iaddr iaddr;
5640 	u_int8_t plen;
5641 	binding_state_t state;
5642 	u_int32_t prefer;
5643 	u_int32_t valid;
5644 	TIME end_time;
5645 	struct iasubopt *iapref;
5646 	struct ipv6_pool *pool;
5647 	char addr_buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5648 	isc_boolean_t newbinding;
5649 	struct binding_scope *scope = NULL;
5650 	struct binding *bnd;
5651 	struct binding_value *nv = NULL;
5652 	struct executable_statement *on_star[2] = {NULL, NULL};
5653 	int lose, i;
5654 
5655         if (local_family != AF_INET6) {
5656                 parse_warn(cfile, "IA_PD is only supported in DHCPv6 mode.");
5657                 skip_to_semi(cfile);
5658                 return;
5659         }
5660 
5661 	if (!parse_iaid_duid(cfile, &ia, &iaid, MDL)) {
5662 		return;
5663 	}
5664 
5665 	ia->ia_type = D6O_IA_PD;
5666 
5667 	token = next_token(&val, NULL, cfile);
5668 	if (token != LBRACE) {
5669 		parse_warn(cfile, "corrupt lease file; expecting left brace");
5670 		skip_to_semi(cfile);
5671 		ia_dereference(&ia, MDL);
5672 		return;
5673 	}
5674 
5675 	for (;;) {
5676 		token = next_token(&val, NULL, cfile);
5677 		if (token == RBRACE) break;
5678 
5679 		if (token == CLTT) {
5680 			ia->cltt = parse_date (cfile);
5681 			continue;
5682 		}
5683 
5684 		if (token != IAPREFIX) {
5685 			parse_warn(cfile, "corrupt lease file; expecting "
5686 				   "IAPREFIX or right brace");
5687 			skip_to_semi(cfile);
5688 			return;
5689 		}
5690 
5691 		if (!parse_ip6_prefix(cfile, &iaddr, &plen)) {
5692 			parse_warn(cfile, "corrupt lease file; "
5693 					  "expecting IPv6 prefix");
5694 			skip_to_semi(cfile);
5695 			return;
5696 		}
5697 
5698 		token = next_token(&val, NULL, cfile);
5699 		if (token != LBRACE) {
5700 			parse_warn(cfile, "corrupt lease file; "
5701 					  "expecting left brace");
5702 			skip_to_semi(cfile);
5703 			return;
5704 		}
5705 
5706 		state = FTS_LAST+1;
5707 		prefer = valid = 0;
5708 		end_time = -1;
5709 		for (;;) {
5710 			token = next_token(&val, NULL, cfile);
5711 			if (token == RBRACE) break;
5712 
5713 			switch(token) {
5714 			     case END_OF_FILE:
5715 			        /* We hit the end of file and don't know
5716 				 * what parts of the lease we may be missing
5717 				 * don't try to salvage the lease
5718 			         */
5719 				parse_warn(cfile, "corrupt lease file; "
5720 					   "unexpected end of file");
5721 				return;
5722 
5723 				/* Prefix binding state. */
5724 			     case BINDING:
5725 				token = next_token(&val, NULL, cfile);
5726 				if (token != STATE) {
5727 					parse_warn(cfile, "corrupt lease file; "
5728 							  "expecting state");
5729 					skip_to_semi(cfile);
5730 					return;
5731 				}
5732 				token = next_token(&val, NULL, cfile);
5733 				switch (token) {
5734 					case TOKEN_ABANDONED:
5735 						state = FTS_ABANDONED;
5736 						break;
5737 					case TOKEN_FREE:
5738 						state = FTS_FREE;
5739 						break;
5740 					case TOKEN_ACTIVE:
5741 						state = FTS_ACTIVE;
5742 						break;
5743 					case TOKEN_EXPIRED:
5744 						state = FTS_EXPIRED;
5745 						break;
5746 					case TOKEN_RELEASED:
5747 						state = FTS_RELEASED;
5748 						break;
5749 					default:
5750 						parse_warn(cfile,
5751 							   "corrupt lease "
5752 							   "file; "
5753 					    		   "expecting a "
5754 							   "binding state.");
5755 						skip_to_semi(cfile);
5756 						return;
5757 				}
5758 
5759 				token = next_token(&val, NULL, cfile);
5760 				if (token != SEMI) {
5761 					parse_warn(cfile, "corrupt lease file; "
5762 							  "expecting "
5763 							  "semicolon.");
5764 				}
5765 				break;
5766 
5767 				/* Lease preferred lifetime. */
5768 			      case PREFERRED_LIFE:
5769 				token = next_token(&val, NULL, cfile);
5770 				if (token != NUMBER) {
5771 					parse_warn(cfile, "%s is not a valid "
5772 							  "preferred time",
5773 						   val);
5774 					skip_to_semi(cfile);
5775 					continue;
5776 				}
5777 				prefer = atoi (val);
5778 
5779 				/*
5780 				 * Currently we peek for the semi-colon to
5781 				 * allow processing of older lease files that
5782 				 * don't have the semi-colon.  Eventually we
5783 				 * should remove the peeking code.
5784 				 */
5785 				token = peek_token(&val, NULL, cfile);
5786 				if (token == SEMI) {
5787 					skip_token(&val, NULL, cfile);
5788 				} else {
5789 					parse_warn(cfile,
5790 						   "corrupt lease file; "
5791 						   "expecting semicolon.");
5792 				}
5793 				break;
5794 
5795 				/* Lease valid lifetime. */
5796 			      case MAX_LIFE:
5797 				token = next_token(&val, NULL, cfile);
5798 				if (token != NUMBER) {
5799 					parse_warn(cfile, "%s is not a valid "
5800 							  "max time",
5801 						   val);
5802 					skip_to_semi(cfile);
5803 					continue;
5804 				}
5805 				valid = atoi (val);
5806 
5807 				/*
5808 				 * Currently we peek for the semi-colon to
5809 				 * allow processing of older lease files that
5810 				 * don't have the semi-colon.  Eventually we
5811 				 * should remove the peeking code.
5812 				 */
5813 				token = peek_token(&val, NULL, cfile);
5814 				if (token == SEMI) {
5815 					skip_token(&val, NULL, cfile);
5816 				} else {
5817 					parse_warn(cfile,
5818 						   "corrupt lease file; "
5819 						   "expecting semicolon.");
5820 				}
5821 				break;
5822 
5823 				/* Prefix expiration time. */
5824 			      case ENDS:
5825 				end_time = parse_date(cfile);
5826 				break;
5827 
5828 				/* Prefix binding scopes. */
5829 			      case TOKEN_SET:
5830 				token = next_token(&val, NULL, cfile);
5831 				if ((token != NAME) &&
5832 				    (token != NUMBER_OR_NAME)) {
5833 					parse_warn(cfile, "%s is not a valid "
5834 							  "variable name",
5835 						   val);
5836 					skip_to_semi(cfile);
5837 					continue;
5838 				}
5839 
5840 				if (scope != NULL)
5841 					bnd = find_binding(scope, val);
5842 				else {
5843 					if (!binding_scope_allocate(&scope,
5844 								    MDL)) {
5845 						log_fatal("Out of memory for "
5846 							  "lease binding "
5847 							  "scope.");
5848 					}
5849 
5850 					bnd = NULL;
5851 				}
5852 
5853 				if (bnd == NULL) {
5854 					bnd = dmalloc(sizeof(*bnd),
5855 							  MDL);
5856 					if (bnd == NULL) {
5857 						log_fatal("No memory for "
5858 							  "prefix binding.");
5859 					}
5860 
5861 					bnd->name = dmalloc(strlen(val) + 1,
5862 							    MDL);
5863 					if (bnd->name == NULL) {
5864 						log_fatal("No memory for "
5865 							  "binding name.");
5866 					}
5867 					strcpy(bnd->name, val);
5868 
5869 					newbinding = ISC_TRUE;
5870 				} else {
5871 					newbinding = ISC_FALSE;
5872 				}
5873 
5874 				if (!binding_value_allocate(&nv, MDL)) {
5875 					log_fatal("no memory for binding "
5876 						  "value.");
5877 				}
5878 
5879 				token = next_token(NULL, NULL, cfile);
5880 				if (token != EQUAL) {
5881 					parse_warn(cfile, "expecting '=' in "
5882 							  "set statement.");
5883 					goto binding_err;
5884 				}
5885 
5886 				if (!parse_binding_value(cfile, nv)) {
5887 				      binding_err:
5888 					binding_value_dereference(&nv, MDL);
5889 					binding_scope_dereference(&scope, MDL);
5890 					return;
5891 				}
5892 
5893 				if (newbinding) {
5894 					binding_value_reference(&bnd->value,
5895 								nv, MDL);
5896 					bnd->next = scope->bindings;
5897 					scope->bindings = bnd;
5898 				} else {
5899 					binding_value_dereference(&bnd->value,
5900 								  MDL);
5901 					binding_value_reference(&bnd->value,
5902 								nv, MDL);
5903 				}
5904 
5905 				binding_value_dereference(&nv, MDL);
5906 				parse_semi(cfile);
5907 				break;
5908 
5909 			      case ON:
5910 				lose = 0;
5911 				/*
5912 				 * Depending on the user config we may
5913 				 * have one or two on statements.  We
5914 				 * need to save information about both
5915 				 * of them until we allocate the
5916 				 * iasubopt to hold them.
5917 				 */
5918 				if (on_star[0] == NULL) {
5919 					if (!parse_on_statement (&on_star[0],
5920 								 cfile,
5921 								 &lose)) {
5922 						parse_warn(cfile,
5923 							   "corrupt lease "
5924 							   "file; bad ON "
5925 							   "statement");
5926 						skip_to_rbrace (cfile, 1);
5927 						return;
5928 					}
5929 				} else {
5930 					if (!parse_on_statement (&on_star[1],
5931 								 cfile,
5932 								 &lose)) {
5933 						parse_warn(cfile,
5934 							   "corrupt lease "
5935 							   "file; bad ON "
5936 							   "statement");
5937 						skip_to_rbrace (cfile, 1);
5938 						return;
5939 					}
5940 				}
5941 
5942 				break;
5943 
5944 			      default:
5945 				parse_warn(cfile, "corrupt lease file; "
5946 						  "expecting ia_pd contents, "
5947 						  "got '%s'", val);
5948 				skip_to_semi(cfile);
5949 				continue;
5950 			}
5951 		}
5952 
5953 		if (state == FTS_LAST+1) {
5954 			parse_warn(cfile, "corrupt lease file; "
5955 					  "missing state in iaprefix");
5956 			return;
5957 		}
5958 		if (end_time == -1) {
5959 			parse_warn(cfile, "corrupt lease file; "
5960 					  "missing end time in iaprefix");
5961 			return;
5962 		}
5963 
5964 		iapref = NULL;
5965 		if (iasubopt_allocate(&iapref, MDL) != ISC_R_SUCCESS) {
5966 			log_fatal("Out of memory.");
5967 		}
5968 		memcpy(&iapref->addr, iaddr.iabuf, sizeof(iapref->addr));
5969 		iapref->plen = plen;
5970 		iapref->state = state;
5971 		iapref->prefer = prefer;
5972 		iapref->valid = valid;
5973 		if (iapref->state == FTS_RELEASED)
5974 			iapref->hard_lifetime_end_time = end_time;
5975 
5976 		if (scope != NULL) {
5977 			binding_scope_reference(&iapref->scope, scope, MDL);
5978 			binding_scope_dereference(&scope, MDL);
5979 		}
5980 
5981 		/*
5982 		 * Check on both on statements.  Because of how we write the
5983 		 * lease file we know which is which if we have two but it's
5984 		 * easier to write the code to be independent.  We do assume
5985 		 * that the statements won't overlap.
5986 		 */
5987 		for (i = 0;
5988 		     (i < 2) && on_star[i] != NULL ;
5989 		     i++) {
5990 			if ((on_star[i]->data.on.evtypes & ON_EXPIRY) &&
5991 			    on_star[i]->data.on.statements) {
5992 				executable_statement_reference
5993 					(&iapref->on_star.on_expiry,
5994 					 on_star[i]->data.on.statements, MDL);
5995 			}
5996 			if ((on_star[i]->data.on.evtypes & ON_RELEASE) &&
5997 			    on_star[i]->data.on.statements) {
5998 				executable_statement_reference
5999 					(&iapref->on_star.on_release,
6000 					 on_star[i]->data.on.statements, MDL);
6001 			}
6002 			executable_statement_dereference (&on_star[i], MDL);
6003 		}
6004 
6005 		/* Find the pool this address is in. We need to check prefix
6006 		 * lengths too in case the pool has been reconfigured. */
6007 		pool = NULL;
6008 		if ((find_ipv6_pool(&pool, D6O_IA_PD,
6009 				   &iapref->addr) != ISC_R_SUCCESS) ||
6010 		     (pool->units != iapref->plen)) {
6011 			inet_ntop(AF_INET6, &iapref->addr,
6012 				  addr_buf, sizeof(addr_buf));
6013 			log_error("No pool found for prefix %s/%d", addr_buf,
6014 				  iapref->plen);
6015 			iasubopt_dereference(&iapref, MDL);
6016 			continue;
6017 		}
6018 
6019 		/* remove old information */
6020 		if (cleanup_lease6(ia_pd_active, pool,
6021 				   iapref, ia) != ISC_R_SUCCESS) {
6022 			inet_ntop(AF_INET6, &iapref->addr,
6023 				  addr_buf, sizeof(addr_buf));
6024 			parse_warn(cfile, "duplicate pd lease for address %s",
6025 				   addr_buf);
6026 		}
6027 
6028 		/*
6029 		 * if we like the lease we add it to our various structues
6030 		 * otherwise we leave it and it will get cleaned when we
6031 		 * do the iasubopt_dereference.
6032 		 */
6033 		if ((state == FTS_ACTIVE) || (state == FTS_ABANDONED)) {
6034 			ia_add_iasubopt(ia, iapref, MDL);
6035 			ia_reference(&iapref->ia, ia, MDL);
6036 			add_lease6(pool, iapref, end_time);
6037 		}
6038 
6039 		ipv6_pool_dereference(&pool, MDL);
6040 		iasubopt_dereference(&iapref, MDL);
6041 	}
6042 
6043 	/*
6044 	 * If we have an existing record for this IA_PD, remove it.
6045 	 */
6046 	old_ia = NULL;
6047 	if (ia_hash_lookup(&old_ia, ia_pd_active,
6048 			   (unsigned char *)ia->iaid_duid.data,
6049 			   ia->iaid_duid.len, MDL)) {
6050 		ia_hash_delete(ia_pd_active,
6051 			       (unsigned char *)ia->iaid_duid.data,
6052 			       ia->iaid_duid.len, MDL);
6053 		ia_dereference(&old_ia, MDL);
6054 	}
6055 
6056 	/*
6057 	 * If we have prefixes, add this, otherwise don't bother.
6058 	 */
6059 	if (ia->num_iasubopt > 0) {
6060 		ia_hash_add(ia_pd_active,
6061 			    (unsigned char *)ia->iaid_duid.data,
6062 			    ia->iaid_duid.len, ia, MDL);
6063 	}
6064 	ia_dereference(&ia, MDL);
6065 #endif /* defined(DHCPv6) */
6066 }
6067 
6068 #ifdef DHCPv6
6069 /*
6070  * When we parse a server-duid statement in a lease file, we are
6071  * looking at the saved server DUID from a previous run. In this case
6072  * we expect it to be followed by the binary representation of the
6073  * DUID stored in a string:
6074  *
6075  * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
6076  *
6077  * OR as a hex string of digits:
6078  *
6079  * server-duid 00:01:00:01:1e:68:b3:db:0a:00:27:00:00:02;
6080  */
6081 void
parse_server_duid(struct parse * cfile)6082 parse_server_duid(struct parse *cfile) {
6083 	struct data_string duid;
6084 	unsigned char bytes[128];  /* Maximum valid DUID is 128 */
6085 	unsigned int len;
6086 
6087 	len = parse_X(cfile, bytes, sizeof(bytes));
6088 	if (len <= 2) {
6089 		parse_warn(cfile, "Invalid duid contents");
6090 		skip_to_semi(cfile);
6091 		return;
6092 	}
6093 
6094 	memset(&duid, 0x0, sizeof(duid));
6095 	if (!buffer_allocate(&duid.buffer, len, MDL)) {
6096 		log_fatal("parse_server_duid: out of memory");
6097 	}
6098 
6099 	memcpy(duid.buffer->data, bytes, len);
6100 	duid.len = len;
6101 	duid.data = duid.buffer->data;
6102 
6103 	set_server_duid(&duid);
6104 	data_string_forget(&duid, MDL);
6105 
6106 	parse_semi(cfile);
6107 }
6108 
6109 /*
6110  * When we parse a server-duid statement in a config file, we will
6111  * have the type of the server DUID to generate, and possibly the
6112  * actual value defined.
6113  *
6114  * server-duid llt;
6115  * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
6116  * server-duid ll;
6117  * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
6118  * server-duid en 2495 "enterprise-specific-identifier-1234";
6119  */
6120 void
parse_server_duid_conf(struct parse * cfile)6121 parse_server_duid_conf(struct parse *cfile) {
6122 	enum dhcp_token token;
6123 	const char *val;
6124 	unsigned int len;
6125 	u_int32_t enterprise_number;
6126 	int ll_type;
6127 	struct data_string ll_addr;
6128 	u_int32_t llt_time;
6129 	struct data_string duid;
6130 	int duid_type_num;
6131 
6132 	/*
6133 	 * Consume the SERVER_DUID token.
6134 	 */
6135 	skip_token(NULL, NULL, cfile);
6136 
6137 	/*
6138 	 * Obtain the DUID type.
6139 	 */
6140 	token = next_token(&val, NULL, cfile);
6141 
6142 	/*
6143 	 * Enterprise is the easiest - enterprise number and raw data
6144 	 * are required.
6145 	 */
6146 	if (token == EN) {
6147 		/*
6148 		 * Get enterprise number and identifier.
6149 		 */
6150 		token = next_token(&val, NULL, cfile);
6151 		if (token != NUMBER) {
6152 			parse_warn(cfile, "enterprise number expected");
6153 			skip_to_semi(cfile);
6154 			return;
6155 		}
6156 		enterprise_number = atoi(val);
6157 
6158 		token = next_token(&val, &len, cfile);
6159 		if (token != STRING) {
6160 			parse_warn(cfile, "identifier expected");
6161 			skip_to_semi(cfile);
6162 			return;
6163 		}
6164 
6165 		/*
6166 		 * Save the DUID.
6167 		 */
6168 		memset(&duid, 0, sizeof(duid));
6169         	duid.len = 2 + 4 + len;
6170         	if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6171 			log_fatal("Out of memory storing DUID");
6172 		}
6173 		duid.data = (unsigned char *)duid.buffer->data;
6174 		putUShort(duid.buffer->data, DUID_EN);
6175  		putULong(duid.buffer->data + 2, enterprise_number);
6176 		memcpy(duid.buffer->data + 6, val, len);
6177 
6178 		set_server_duid(&duid);
6179 		data_string_forget(&duid, MDL);
6180 	}
6181 
6182 	/*
6183 	 * Next easiest is the link-layer DUID. It consists only of
6184 	 * the LL directive, or optionally the specific value to use.
6185 	 *
6186 	 * If we have LL only, then we set the type. If we have the
6187 	 * value, then we set the actual DUID.
6188 	 */
6189 	else if (token == LL) {
6190 		if (peek_token(NULL, NULL, cfile) == SEMI) {
6191 			set_server_duid_type(DUID_LL);
6192 		} else {
6193 			/*
6194 			 * Get our hardware type and address.
6195 			 */
6196 			token = next_token(NULL, NULL, cfile);
6197 			switch (token) {
6198 			      case ETHERNET:
6199 				ll_type = HTYPE_ETHER;
6200 				break;
6201 			      case TOKEN_RING:
6202 				ll_type = HTYPE_IEEE802;
6203 				break;
6204 			      case TOKEN_FDDI:
6205 				ll_type = HTYPE_FDDI;
6206 				break;
6207 			      default:
6208 				parse_warn(cfile, "hardware type expected");
6209 				skip_to_semi(cfile);
6210 				return;
6211 			}
6212 			memset(&ll_addr, 0, sizeof(ll_addr));
6213 			if (!parse_cshl(&ll_addr, cfile)) {
6214 				return;
6215 			}
6216 
6217 			/*
6218 			 * Save the DUID.
6219 			 */
6220 			memset(&duid, 0, sizeof(duid));
6221 			duid.len = 2 + 2 + ll_addr.len;
6222         		if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6223 				log_fatal("Out of memory storing DUID");
6224 			}
6225 			duid.data = (unsigned char *)duid.buffer->data;
6226 			putUShort(duid.buffer->data, DUID_LL);
6227  			putUShort(duid.buffer->data + 2, ll_type);
6228 			memcpy(duid.buffer->data + 4,
6229 			       ll_addr.data, ll_addr.len);
6230 
6231 			set_server_duid(&duid);
6232 			data_string_forget(&duid, MDL);
6233 			data_string_forget(&ll_addr, MDL);
6234 		}
6235 	}
6236 
6237 	/*
6238 	 * Finally the link-layer DUID plus time. It consists only of
6239 	 * the LLT directive, or optionally the specific value to use.
6240 	 *
6241 	 * If we have LLT only, then we set the type. If we have the
6242 	 * value, then we set the actual DUID.
6243 	 */
6244 	else if (token == LLT) {
6245 		if (peek_token(NULL, NULL, cfile) == SEMI) {
6246 			set_server_duid_type(DUID_LLT);
6247 		} else {
6248 			/*
6249 			 * Get our hardware type, timestamp, and address.
6250 			 */
6251 			token = next_token(NULL, NULL, cfile);
6252 			switch (token) {
6253 			      case ETHERNET:
6254 				ll_type = HTYPE_ETHER;
6255 				break;
6256 			      case TOKEN_RING:
6257 				ll_type = HTYPE_IEEE802;
6258 				break;
6259 			      case TOKEN_FDDI:
6260 				ll_type = HTYPE_FDDI;
6261 				break;
6262 			      default:
6263 				parse_warn(cfile, "hardware type expected");
6264 				skip_to_semi(cfile);
6265 				return;
6266 			}
6267 
6268 			token = next_token(&val, NULL, cfile);
6269 			if (token != NUMBER) {
6270 				parse_warn(cfile, "timestamp expected");
6271 				skip_to_semi(cfile);
6272 				return;
6273 			}
6274 			llt_time = atoi(val);
6275 
6276 			memset(&ll_addr, 0, sizeof(ll_addr));
6277 			if (!parse_cshl(&ll_addr, cfile)) {
6278 				return;
6279 			}
6280 
6281 			/*
6282 			 * Save the DUID.
6283 			 */
6284 			memset(&duid, 0, sizeof(duid));
6285 			duid.len = 2 + 2 + 4 + ll_addr.len;
6286         		if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6287 				log_fatal("Out of memory storing DUID");
6288 			}
6289 			duid.data = (unsigned char *)duid.buffer->data;
6290 			putUShort(duid.buffer->data, DUID_LLT);
6291  			putUShort(duid.buffer->data + 2, ll_type);
6292  			putULong(duid.buffer->data + 4, llt_time);
6293 			memcpy(duid.buffer->data + 8,
6294 			       ll_addr.data, ll_addr.len);
6295 
6296 			set_server_duid(&duid);
6297 			data_string_forget(&duid, MDL);
6298 			data_string_forget(&ll_addr, MDL);
6299 		}
6300 	}
6301 
6302 	/*
6303 	 * If users want they can use a number for DUID types.
6304 	 * This is useful for supporting future, not-yet-defined
6305 	 * DUID types.
6306 	 *
6307 	 * In this case, they have to put in the complete value.
6308 	 *
6309 	 * This also works for existing DUID types of course.
6310 	 */
6311 	else if (token == NUMBER) {
6312 		duid_type_num = atoi(val);
6313 
6314 		token = next_token(&val, &len, cfile);
6315 		if (token != STRING) {
6316 			parse_warn(cfile, "identifier expected");
6317 			skip_to_semi(cfile);
6318 			return;
6319 		}
6320 
6321 		/*
6322 		 * Save the DUID.
6323 		 */
6324 		memset(&duid, 0, sizeof(duid));
6325         	duid.len = 2 + len;
6326         	if (!buffer_allocate(&duid.buffer, duid.len, MDL)) {
6327 			log_fatal("Out of memory storing DUID");
6328 		}
6329 		duid.data = (unsigned char *)duid.buffer->data;
6330 		putUShort(duid.buffer->data, duid_type_num);
6331 		memcpy(duid.buffer->data + 2, val, len);
6332 
6333 		set_server_duid(&duid);
6334 		data_string_forget(&duid, MDL);
6335 	}
6336 
6337 	/*
6338 	 * Anything else is an error.
6339 	 */
6340 	else {
6341 		parse_warn(cfile, "DUID type of LLT, EN, or LL expected");
6342 		skip_to_semi(cfile);
6343 		return;
6344 	}
6345 
6346 	/*
6347 	 * Finally consume our trailing semicolon.
6348 	 */
6349 	token = next_token(NULL, NULL, cfile);
6350 	if (token != SEMI) {
6351 		parse_warn(cfile, "semicolon expected");
6352 		skip_to_semi(cfile);
6353 	}
6354 }
6355 
6356 /*!
6357  * \brief Creates a byte-order corrected uint32 from a buffer
6358  *
6359  * This function creates an integer value from a buffer, converting from
6360  * the byte order specified by authoring-byte-order to the current server's
6361  * byte order if they are different. The conversion works in either direction.
6362  *
6363  * If the parameter, authoring-byte-order hasn't yet been encountered we will
6364  * emit a warning and then default the byte order to match the current server's
6365  * byte order (i.e. no conversion will done).
6366  *
6367  * \param source buffer containing the "raw" four byte data
6368  * \return uint32_t containing the corrected value
6369 */
parse_byte_order_uint32(const void * source)6370 uint32_t parse_byte_order_uint32(const void *source) {
6371 	uint32_t value;
6372 
6373 	/* use memcpy to avoid any alignment monkey business */
6374 	memcpy(&value, source, 4);
6375 
6376 	if (authoring_byte_order == 0) {
6377 		log_error ("WARNING: "
6378                             "authoring-byte-order not in the lease file.\n"
6379                             "Assuming file byte order matches this server.\n");
6380 		authoring_byte_order = DHCP_BYTE_ORDER;
6381 	}
6382 
6383 	if (authoring_byte_order != DHCP_BYTE_ORDER) {
6384 		value = (((value >> 24) & 0xff) | // move byte 3 to byte 0
6385                     ((value << 8) & 0xff0000) | // move byte 1 to byte 2
6386                     ((value >> 8) & 0xff00) | // move byte 2 to byte 1
6387                     ((value << 24) & 0xff000000)); // byte 0 to byte 3
6388 	}
6389 
6390 	return (value);
6391 }
6392 
6393 /* !brief Parses an iaid/duid string into an iaid and struct ia
6394  *
6395  * Given a string containing the iaid-duid value read from the file,
6396  * and using the format specified by input lease-id-format, convert
6397  * it into an IAID value and an ia_xx struct.
6398  *
6399  * \param cfile - file being parsed
6400  * \param ia - pointer in which to store the allocated ia_xx struct
6401  * \param iaid - pointer in which to return the IAID value
6402  * \param file - source file name of invocation
6403  * \param line - line numbe of invocation
6404  *
6405  * \return 0 if parsing fails, non-zero otherwise
6406 */
6407 int
parse_iaid_duid(struct parse * cfile,struct ia_xx ** ia,u_int32_t * iaid,const char * file,int line)6408 parse_iaid_duid(struct parse* cfile, struct ia_xx** ia, u_int32_t *iaid,
6409 	const char* file, int line) {
6410         unsigned char bytes[132];  /* Maximum valid IAID-DUID is 132 */
6411         unsigned int len;
6412 
6413 	if (!ia) {
6414 		log_error("parse_iaid_duid: ia ptr cannot be null");
6415 		return (0);
6416 	}
6417 
6418 	*ia = NULL;
6419         len = parse_X(cfile, bytes, sizeof(bytes));
6420         if (len <= 5) {
6421 		parse_warn(cfile, "corrupt lease file; "
6422 			   "iaid+ia_xx string too short");
6423                 skip_to_semi(cfile);
6424                 return (0);
6425         }
6426 
6427 	/* Extract the IAID from the front */
6428 	*iaid = parse_byte_order_uint32(bytes);
6429 
6430 	/* Instantiate the ia_xx */
6431 	if (ia_allocate(ia, *iaid, (const char*)bytes + 4, len - 4, file, line)
6432 	    != ISC_R_SUCCESS) {
6433 		log_fatal("parse_iaid_duid:Out of memory.");
6434 	}
6435 
6436 	return (1);
6437 }
6438 
6439 #endif /* DHCPv6 */
6440 
6441