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