xref: /minix/external/bsd/dhcp/dist/common/parse.c (revision fb9c64b2)
1 /*	$NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $	*/
2 /* parse.c
3 
4    Common parser code for dhcpd and dhclient. */
5 
6 /*
7  * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
8  * Copyright (c) 1995-2003 by Internet Software Consortium
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  *   Internet Systems Consortium, Inc.
23  *   950 Charter Street
24  *   Redwood City, CA 94063
25  *   <info@isc.org>
26  *   https://www.isc.org/
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $");
32 
33 #include "dhcpd.h"
34 #include <syslog.h>
35 
36 /* Enumerations can be specified in option formats, and are used for
37    parsing, so we define the routines that manage them here. */
38 
39 struct enumeration *enumerations;
40 
41 void add_enumeration (struct enumeration *enumeration)
42 {
43 	enumeration -> next = enumerations;
44 	enumerations = enumeration;
45 }
46 
47 struct enumeration *find_enumeration (const char *name, int length)
48 {
49 	struct enumeration *e;
50 
51 	for (e = enumerations; e; e = e -> next)
52 		if (strlen (e -> name) == length &&
53 		    !memcmp (e -> name, name, (unsigned)length))
54 			return e;
55 	return (struct enumeration *)0;
56 }
57 
58 struct enumeration_value *find_enumeration_value (const char *name,
59 						  int length,
60 						  unsigned *widthp,
61 						  const char *value)
62 {
63 	struct enumeration *e;
64 	int i;
65 
66 	e = find_enumeration (name, length);
67 	if (e) {
68 		if (widthp != NULL)
69 			*widthp = e->width;
70 		for (i = 0; e -> values [i].name; i++) {
71 			if (!strcmp (value, e -> values [i].name))
72 				return &e -> values [i];
73 		}
74 	}
75 	return (struct enumeration_value *)0;
76 }
77 
78 /* Skip to the semicolon ending the current statement.   If we encounter
79    braces, the matching closing brace terminates the statement.   If we
80    encounter a right brace but haven't encountered a left brace, return
81    leaving the brace in the token buffer for the caller.   If we see a
82    semicolon and haven't seen a left brace, return.   This lets us skip
83    over:
84 
85    	statement;
86 	statement foo bar { }
87 	statement foo bar { statement { } }
88 	statement}
89 
90 	...et cetera. */
91 
92 void skip_to_semi (cfile)
93 	struct parse *cfile;
94 {
95 	skip_to_rbrace (cfile, 0);
96 }
97 
98 void skip_to_rbrace (cfile, brace_count)
99 	struct parse *cfile;
100 	int brace_count;
101 {
102 	enum dhcp_token token;
103 	const char *val;
104 
105 #if defined (DEBUG_TOKEN)
106 	log_error ("skip_to_rbrace: %d\n", brace_count);
107 #endif
108 	do {
109 		token = peek_token (&val, (unsigned *)0, cfile);
110 		if (token == RBRACE) {
111 			skip_token(&val, (unsigned *)0, cfile);
112 			if (brace_count) {
113 				if (!--brace_count)
114 					return;
115 			} else
116 				return;
117 		} else if (token == LBRACE) {
118 			brace_count++;
119 		} else if (token == SEMI && !brace_count) {
120 			skip_token(&val, (unsigned *)0, cfile);
121 			return;
122 		} else if (token == EOL) {
123 			/* EOL only happens when parsing /etc/resolv.conf,
124 			   and we treat it like a semicolon because the
125 			   resolv.conf file is line-oriented. */
126 			skip_token(&val, (unsigned *)0, cfile);
127 			return;
128 		}
129 		token = next_token (&val, (unsigned *)0, cfile);
130 	} while (token != END_OF_FILE);
131 }
132 
133 int parse_semi (cfile)
134 	struct parse *cfile;
135 {
136 	enum dhcp_token token;
137 	const char *val;
138 
139 	token = next_token (&val, (unsigned *)0, cfile);
140 	if (token != SEMI) {
141 		parse_warn (cfile, "semicolon expected.");
142 		skip_to_semi (cfile);
143 		return 0;
144 	}
145 	return 1;
146 }
147 
148 /* string-parameter :== STRING SEMI */
149 
150 int parse_string (cfile, sptr, lptr)
151 	struct parse *cfile;
152 	char **sptr;
153 	unsigned *lptr;
154 {
155 	const char *val;
156 	enum dhcp_token token;
157 	char *s;
158 	unsigned len;
159 
160 	token = next_token (&val, &len, cfile);
161 	if (token != STRING) {
162 		parse_warn (cfile, "expecting a string");
163 		skip_to_semi (cfile);
164 		return 0;
165 	}
166 	s = (char *)dmalloc (len + 1, MDL);
167 	if (!s)
168 		log_fatal ("no memory for string %s.", val);
169 	memcpy (s, val, len + 1);
170 
171 	if (!parse_semi (cfile)) {
172 		dfree (s, MDL);
173 		return 0;
174 	}
175 	if (sptr)
176 		*sptr = s;
177 	else
178 		dfree (s, MDL);
179 	if (lptr)
180 		*lptr = len;
181 	return 1;
182 }
183 
184 /*
185  * hostname :== IDENTIFIER
186  *		| IDENTIFIER DOT
187  *		| hostname DOT IDENTIFIER
188  */
189 
190 char *parse_host_name (cfile)
191 	struct parse *cfile;
192 {
193 	const char *val;
194 	enum dhcp_token token;
195 	unsigned len = 0;
196 	char *s;
197 	char *t;
198 	pair c = (pair)0;
199 	int ltid = 0;
200 
201 	/* Read a dotted hostname... */
202 	do {
203 		/* Read a token, which should be an identifier. */
204 		token = peek_token (&val, (unsigned *)0, cfile);
205 		if (!is_identifier (token) && token != NUMBER)
206 			break;
207 		skip_token(&val, (unsigned *)0, cfile);
208 
209 		/* Store this identifier... */
210 		if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
211 			log_fatal ("can't allocate temp space for hostname.");
212 		strcpy (s, val);
213 		c = cons ((caddr_t)s, c);
214 		len += strlen (s) + 1;
215 		/* Look for a dot; if it's there, keep going, otherwise
216 		   we're done. */
217 		token = peek_token (&val, (unsigned *)0, cfile);
218 		if (token == DOT) {
219 			token = next_token (&val, (unsigned *)0, cfile);
220 			ltid = 1;
221 		} else
222 			ltid = 0;
223 	} while (token == DOT);
224 
225 	/* Should be at least one token. */
226 	if (!len)
227 		return (char *)0;
228 
229 	/* Assemble the hostname together into a string. */
230 	if (!(s = (char *)dmalloc (len + ltid, MDL)))
231 		log_fatal ("can't allocate space for hostname.");
232 	t = s + len + ltid;
233 	*--t = 0;
234 	if (ltid)
235 		*--t = '.';
236 	while (c) {
237 		pair cdr = c -> cdr;
238 		unsigned l = strlen ((char *)(c -> car));
239 		t -= l;
240 		memcpy (t, (char *)(c -> car), l);
241 		/* Free up temp space. */
242 		dfree (c -> car, MDL);
243 		dfree (c, MDL);
244 		c = cdr;
245 		if (t != s)
246 			*--t = '.';
247 	}
248 	return s;
249 }
250 
251 /* ip-addr-or-hostname :== ip-address | hostname
252    ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
253 
254    Parse an ip address or a hostname.   If uniform is zero, put in
255    an expr_substring node to limit hostnames that evaluate to more
256    than one IP address.
257 
258    Note that RFC1123 permits hostnames to consist of all digits,
259    making it difficult to quickly disambiguate them from ip addresses.
260 */
261 
262 int parse_ip_addr_or_hostname (expr, cfile, uniform)
263 	struct expression **expr;
264 	struct parse *cfile;
265 	int uniform;
266 {
267 	const char *val;
268 	enum dhcp_token token;
269 	unsigned char addr [4];
270 	unsigned len = sizeof addr;
271 	char *name;
272 	struct expression *x = (struct expression *)0;
273 	int ipaddr = 0;
274 
275 	token = peek_token (&val, (unsigned *)0, cfile);
276 
277 	if (token == NUMBER) {
278 		/*
279 		 * a hostname may be numeric, but domain names must
280 		 * start with a letter, so we can disambiguate by
281 		 * looking ahead a few tokens.  we save the parse
282 		 * context first, and restore it after we know what
283 		 * we're dealing with.
284 		 */
285 		save_parse_state(cfile);
286 		skip_token(NULL, NULL, cfile);
287 		if (next_token(NULL, NULL, cfile) == DOT &&
288 		    next_token(NULL, NULL, cfile) == NUMBER)
289 			ipaddr = 1;
290 		restore_parse_state(cfile);
291 
292 		if (ipaddr &&
293 		    parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
294 			return make_const_data (expr, addr, len, 0, 1, MDL);
295 
296 	}
297 
298 	if (is_identifier (token) || token == NUMBER) {
299 		name = parse_host_name (cfile);
300 		if (!name)
301 			return 0;
302 		if (!make_host_lookup (expr, name)) {
303 			dfree(name, MDL);
304 			return 0;
305 		}
306 		dfree(name, MDL);
307 		if (!uniform) {
308 			if (!make_limit (&x, *expr, 4))
309 				return 0;
310 			expression_dereference (expr, MDL);
311 			*expr = x;
312 		}
313 	} else {
314 		if (token != RBRACE && token != LBRACE)
315 			token = next_token (&val, (unsigned *)0, cfile);
316 		parse_warn (cfile, "%s (%d): expecting IP address or hostname",
317 			    val, token);
318 		if (token != SEMI)
319 			skip_to_semi (cfile);
320 		return 0;
321 	}
322 
323 	return 1;
324 }
325 
326 /*
327  * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
328  */
329 
330 int parse_ip_addr (cfile, addr)
331 	struct parse *cfile;
332 	struct iaddr *addr;
333 {
334 	addr -> len = 4;
335 	if (parse_numeric_aggregate (cfile, addr -> iabuf,
336 				     &addr -> len, DOT, 10, 8))
337 		return 1;
338 	return 0;
339 }
340 
341 /*
342  * Return true if every character in the string is hexadecimal.
343  */
344 static int
345 is_hex_string(const char *s) {
346 	while (*s != '\0') {
347 		if (!isxdigit((int)*s)) {
348 			return 0;
349 		}
350 		s++;
351 	}
352 	return 1;
353 }
354 
355 /*
356  * ip-address6 :== (complicated set of rules)
357  *
358  * See section 2.2 of RFC 1884 for details.
359  *
360  * We are lazy for this. We pull numbers, names, colons, and dots
361  * together and then throw the resulting string at the inet_pton()
362  * function.
363  */
364 
365 int
366 parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
367 	enum dhcp_token token;
368 	const char *val;
369 	int val_len;
370 
371 	char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
372 	int v6_len;
373 
374 	/*
375 	 * First token is non-raw. This way we eat any whitespace before
376 	 * our IPv6 address begins, like one would expect.
377 	 */
378 	token = peek_token(&val, NULL, cfile);
379 
380 	/*
381 	 * Gather symbols.
382 	 */
383 	v6_len = 0;
384 	for (;;) {
385 		if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
386 		     is_hex_string(val)) ||
387 		    (token == NUMBER) ||
388 		    (token == DOT) ||
389 		    (token == COLON)) {
390 
391 			next_raw_token(&val, NULL, cfile);
392 			val_len = strlen(val);
393 			if ((v6_len + val_len) >= sizeof(v6)) {
394 				parse_warn(cfile, "Invalid IPv6 address.");
395 				skip_to_semi(cfile);
396 				return 0;
397 			}
398 			memcpy(v6+v6_len, val, val_len);
399 			v6_len += val_len;
400 
401 		} else {
402 			break;
403 		}
404 		token = peek_raw_token(&val, NULL, cfile);
405 	}
406 	v6[v6_len] = '\0';
407 
408 	/*
409 	 * Use inet_pton() for actual work.
410 	 */
411 	if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
412 		parse_warn(cfile, "Invalid IPv6 address.");
413 		skip_to_semi(cfile);
414 		return 0;
415 	}
416 	addr->len = 16;
417 	return 1;
418 }
419 
420 /*
421  * Same as parse_ip6_addr() above, but returns the value in the
422  * expression rather than in an address structure.
423  */
424 int
425 parse_ip6_addr_expr(struct expression **expr,
426 		    struct parse *cfile) {
427 	struct iaddr addr;
428 
429 	if (!parse_ip6_addr(cfile, &addr)) {
430 		return 0;
431 	}
432 	return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL);
433 }
434 
435 /*
436  * ip6-prefix :== ip6-address "/" NUMBER
437  */
438 int
439 parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen) {
440 	enum dhcp_token token;
441 	const char *val;
442 	int n;
443 
444 	if (!parse_ip6_addr(cfile, addr)) {
445 		return 0;
446 	}
447 	token = next_token(&val, NULL, cfile);
448 	if (token != SLASH) {
449 		parse_warn(cfile, "Slash expected.");
450 		if (token != SEMI)
451 			skip_to_semi(cfile);
452 		return 0;
453 	}
454 	token = next_token(&val, NULL, cfile);
455 	if (token != NUMBER) {
456 		parse_warn(cfile, "Number expected.");
457 		if (token != SEMI)
458 			skip_to_semi(cfile);
459 		return 0;
460 	}
461 	n = atoi(val);
462 	if ((n < 0) || (n > 128)) {
463 		parse_warn(cfile, "Invalid IPv6 prefix length.");
464 		skip_to_semi(cfile);
465 		return 0;
466 	}
467 	if (!is_cidr_mask_valid(addr, n)) {
468 		parse_warn(cfile, "network mask too short.");
469 		skip_to_semi(cfile);
470 		return 0;
471 	}
472 	*plen = n;
473 	return 1;
474 }
475 
476 /*
477  * ip-address-with-subnet :== ip-address |
478  *                          ip-address "/" NUMBER
479  */
480 
481 int
482 parse_ip_addr_with_subnet(cfile, match)
483 	struct parse *cfile;
484 	struct iaddrmatch *match;
485 {
486 	const char *val, *orig;
487 	enum dhcp_token token;
488 	int prefixlen;
489 	int fflen;
490 	unsigned char newval, warnmask=0;
491 
492 	if (parse_ip_addr(cfile, &match->addr)) {
493 		/* default to host mask */
494 		prefixlen = match->addr.len * 8;
495 
496 		token = peek_token(&val, NULL, cfile);
497 
498 		if (token == SLASH) {
499 			skip_token(&val, NULL, cfile);
500 			token = next_token(&val, NULL, cfile);
501 
502 			if (token != NUMBER) {
503 				parse_warn(cfile, "Invalid CIDR prefix length:"
504 						  " expecting a number.");
505 				return 0;
506 			}
507 
508 			prefixlen = atoi(val);
509 
510 			if (prefixlen < 0 ||
511 			    prefixlen > (match->addr.len * 8)) {
512 				parse_warn(cfile, "subnet prefix is out of "
513 						  "range [0..%d].",
514 						  match->addr.len * 8);
515 				return 0;
516 			}
517 		}
518 
519 		/* construct a suitable mask field */
520 
521 		/* copy length */
522 		match->mask.len = match->addr.len;
523 
524 		/* count of 0xff bytes in mask */
525 		fflen = prefixlen / 8;
526 
527 		/* set leading mask */
528 		memset(match->mask.iabuf, 0xff, fflen);
529 
530 		/* set zeroes */
531 		if (fflen < match->mask.len) {
532 			match->mask.iabuf[fflen] =
533 			    "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8];
534 
535 			memset(match->mask.iabuf+fflen+1, 0x00,
536 			       match->mask.len - fflen - 1);
537 
538 			/* AND-out insignificant bits from supplied netmask. */
539 			orig = piaddr(match->addr);
540 			do {
541 				newval = match->addr.iabuf[fflen] &
542 					 match->mask.iabuf[fflen];
543 
544 				if (newval != match->addr.iabuf[fflen]) {
545 					warnmask = 1;
546 					match->addr.iabuf[fflen] = newval;
547 				}
548 			} while (++fflen < match->mask.len);
549 
550 			if (warnmask) {
551 				log_error("Warning: Extraneous bits removed "
552 					  "in address component of %s/%d.",
553 					  orig, prefixlen);
554 				log_error("New value: %s/%d.",
555 					  piaddr(match->addr), prefixlen);
556 			}
557 		}
558 
559 		return 1;
560 	}
561 
562 	parse_warn(cfile,
563 		   "expecting ip-address or ip-address/prefixlen");
564 
565 	return 0;  /* let caller pick up pieces */
566 }
567 
568 /*
569  * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
570  * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND
571  * Note that INFINIBAND may not be useful for some items, such as classification
572  * as the hardware address won't always be available.
573  */
574 
575 void parse_hardware_param (cfile, hardware)
576 	struct parse *cfile;
577 	struct hardware *hardware;
578 {
579 	const char *val;
580 	enum dhcp_token token;
581 	unsigned hlen;
582 	unsigned char *t;
583 
584 	token = next_token(&val, NULL, cfile);
585 	switch (token) {
586 	      case ETHERNET:
587 		hardware->hbuf[0] = HTYPE_ETHER;
588 		break;
589 	      case TOKEN_RING:
590 		hardware->hbuf[0] = HTYPE_IEEE802;
591 		break;
592 	      case TOKEN_FDDI:
593 		hardware->hbuf[0] = HTYPE_FDDI;
594 		break;
595 	      case TOKEN_INFINIBAND:
596 		hardware->hbuf[0] = HTYPE_INFINIBAND;
597 		break;
598 	      default:
599 		if (!strncmp(val, "unknown-", 8)) {
600 			hardware->hbuf[0] = atoi(&val[8]);
601 		} else {
602 			parse_warn(cfile,
603 				   "expecting a network hardware type");
604 			skip_to_semi(cfile);
605 
606 			return;
607 		}
608 	}
609 
610 	/* Parse the hardware address information.   Technically,
611 	   it would make a lot of sense to restrict the length of the
612 	   data we'll accept here to the length of a particular hardware
613 	   address type.   Unfortunately, there are some broken clients
614 	   out there that put bogus data in the chaddr buffer, and we accept
615 	   that data in the lease file rather than simply failing on such
616 	   clients.   Yuck. */
617 	hlen = 0;
618 	token = peek_token(&val, NULL, cfile);
619 	if (token == SEMI) {
620 		hardware->hlen = 1;
621 		goto out;
622 	}
623 	t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
624 	if (t == NULL) {
625 		hardware->hlen = 1;
626 		return;
627 	}
628 	if (hlen + 1 > sizeof(hardware->hbuf)) {
629 		dfree(t, MDL);
630 		parse_warn(cfile, "hardware address too long");
631 	} else {
632 		hardware->hlen = hlen + 1;
633 		memcpy((unsigned char *)&hardware->hbuf[1], t, hlen);
634 		if (hlen + 1 < sizeof(hardware->hbuf))
635 			memset(&hardware->hbuf[hlen + 1], 0,
636 			       (sizeof(hardware->hbuf)) - hlen - 1);
637 		dfree(t, MDL);
638 	}
639 
640       out:
641 	token = next_token(&val, NULL, cfile);
642 	if (token != SEMI) {
643 		parse_warn(cfile, "expecting semicolon.");
644 		skip_to_semi(cfile);
645 	}
646 }
647 
648 /* lease-time :== NUMBER SEMI */
649 
650 void parse_lease_time (cfile, timep)
651 	struct parse *cfile;
652 	TIME *timep;
653 {
654 	const char *val;
655 	enum dhcp_token token;
656 	u_int32_t num;
657 
658 	token = next_token (&val, (unsigned *)0, cfile);
659 	if (token != NUMBER) {
660 		parse_warn (cfile, "Expecting numeric lease time");
661 		skip_to_semi (cfile);
662 		return;
663 	}
664 	convert_num(cfile, (unsigned char *)&num, val, 10, 32);
665 	/* Unswap the number - convert_num returns stuff in NBO. */
666 	*timep = ntohl(num);
667 
668 	parse_semi (cfile);
669 }
670 
671 /* No BNF for numeric aggregates - that's defined by the caller.  What
672    this function does is to parse a sequence of numbers separated by
673    the token specified in separator.  If max is zero, any number of
674    numbers will be parsed; otherwise, exactly max numbers are
675    expected.  Base and size tell us how to internalize the numbers
676    once they've been tokenized.
677 
678    buf - A pointer to space to return the parsed value, if it is null
679    then the function will allocate space for the return.
680 
681    max - The maximum number of items to store.  If zero there is no
682    maximum.  When buf is null and the function needs to allocate space
683    it will do an allocation of max size at the beginning if max is non
684    zero.  If max is zero then the allocation will be done later, after
685    the function has determined the size necessary for the incoming
686    string.
687 
688    returns NULL on errors or a pointer to the value string on success.
689    The pointer will either be buf if it was non-NULL or newly allocated
690    space if buf was NULL
691  */
692 
693 
694 unsigned char *parse_numeric_aggregate (cfile, buf,
695 					max, separator, base, size)
696 	struct parse *cfile;
697 	unsigned char *buf;
698 	unsigned *max;
699 	int separator;
700 	int base;
701 	unsigned size;
702 {
703 	const char *val;
704 	enum dhcp_token token;
705 	unsigned char *bufp = buf, *s, *t;
706 	unsigned count = 0;
707 	pair c = (pair)0;
708 
709 	if (!bufp && *max) {
710 		bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
711 		if (!bufp)
712 			log_fatal ("no space for numeric aggregate");
713 	}
714 	s = bufp;
715 
716 	do {
717 		if (count) {
718 			token = peek_token (&val, (unsigned *)0, cfile);
719 			if (token != separator) {
720 				if (!*max)
721 					break;
722 				if (token != RBRACE && token != LBRACE)
723 					token = next_token (&val,
724 							    (unsigned *)0,
725 							    cfile);
726 				parse_warn (cfile, "too few numbers.");
727 				if (token != SEMI)
728 					skip_to_semi (cfile);
729 				/* free bufp if it was allocated */
730 				if ((bufp != NULL) && (bufp != buf))
731 					dfree(bufp, MDL);
732 				return (unsigned char *)0;
733 			}
734 			skip_token(&val, (unsigned *)0, cfile);
735 		}
736 		token = next_token (&val, (unsigned *)0, cfile);
737 
738 		if (token == END_OF_FILE) {
739 			parse_warn (cfile, "unexpected end of file");
740 			break;
741 		}
742 
743 		/* Allow NUMBER_OR_NAME if base is 16. */
744 		if (token != NUMBER &&
745 		    (base != 16 || token != NUMBER_OR_NAME)) {
746 			parse_warn (cfile, "expecting numeric value.");
747 			skip_to_semi (cfile);
748 			/* free bufp if it was allocated */
749 			if ((bufp != NULL) && (bufp != buf))
750 				dfree(bufp, MDL);
751 			/* free any linked numbers we may have allocated */
752 			while (c) {
753 				pair cdr = c->cdr;
754 				dfree(c->car, MDL);
755 				dfree(c, MDL);
756 				c = cdr;
757 			}
758 			return (NULL);
759 		}
760 		/* If we can, convert the number now; otherwise, build
761 		   a linked list of all the numbers. */
762 		if (s) {
763 			convert_num (cfile, s, val, base, size);
764 			s += size / 8;
765 		} else {
766 			t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
767 			if (!t)
768 				log_fatal ("no temp space for number.");
769 			strcpy ((char *)t, val);
770 			c = cons ((caddr_t)t, c);
771 		}
772 	} while (++count != *max);
773 
774 	/* If we had to cons up a list, convert it now. */
775 	if (c) {
776 		/*
777 		 * No need to cleanup bufp, to get here we didn't allocate
778 		 * bufp above
779 		 */
780 		bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
781 		if (!bufp)
782 			log_fatal ("no space for numeric aggregate.");
783 		s = bufp + count - size / 8;
784 		*max = count;
785 	}
786 	while (c) {
787 		pair cdr = c -> cdr;
788 		convert_num (cfile, s, (char *)(c -> car), base, size);
789 		s -= size / 8;
790 		/* Free up temp space. */
791 		dfree (c -> car, MDL);
792 		dfree (c, MDL);
793 		c = cdr;
794 	}
795 	return bufp;
796 }
797 
798 void convert_num (cfile, buf, str, base, size)
799 	struct parse *cfile;
800 	unsigned char *buf;
801 	const char *str;
802 	int base;
803 	unsigned size;
804 {
805 	const unsigned char *ptr = (const unsigned char *)str;
806 	int negative = 0;
807 	u_int32_t val = 0;
808 	int tval;
809 	int max;
810 
811 	if (*ptr == '-') {
812 		negative = 1;
813 		++ptr;
814 	}
815 
816 	/* If base wasn't specified, figure it out from the data. */
817 	if (!base) {
818 		if (ptr [0] == '0') {
819 			if (ptr [1] == 'x') {
820 				base = 16;
821 				ptr += 2;
822 			} else if (isascii (ptr [1]) && isdigit (ptr [1])) {
823 				base = 8;
824 				ptr += 1;
825 			} else {
826 				base = 10;
827 			}
828 		} else {
829 			base = 10;
830 		}
831 	}
832 
833 	do {
834 		tval = *ptr++;
835 		/* XXX assumes ASCII... */
836 		if (tval >= 'a')
837 			tval = tval - 'a' + 10;
838 		else if (tval >= 'A')
839 			tval = tval - 'A' + 10;
840 		else if (tval >= '0')
841 			tval -= '0';
842 		else {
843 			parse_warn (cfile, "Bogus number: %s.", str);
844 			break;
845 		}
846 		if (tval >= base) {
847 			parse_warn (cfile,
848 				    "Bogus number %s: digit %d not in base %d",
849 				    str, tval, base);
850 			break;
851 		}
852 		val = val * base + tval;
853 	} while (*ptr);
854 
855 	if (negative)
856 		max = (1 << (size - 1));
857 	else
858 		max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
859 	if (val > max) {
860 		switch (base) {
861 		      case 8:
862 			parse_warn (cfile,
863 				    "%s%lo exceeds max (%d) for precision.",
864 				    negative ? "-" : "",
865 				    (unsigned long)val, max);
866 			break;
867 		      case 16:
868 			parse_warn (cfile,
869 				    "%s%lx exceeds max (%d) for precision.",
870 				    negative ? "-" : "",
871 				    (unsigned long)val, max);
872 			break;
873 		      default:
874 			parse_warn (cfile,
875 				    "%s%lu exceeds max (%d) for precision.",
876 				    negative ? "-" : "",
877 				    (unsigned long)val, max);
878 			break;
879 		}
880 	}
881 
882 	if (negative) {
883 		switch (size) {
884 		      case 8:
885 			*buf = -(unsigned long)val;
886 			break;
887 		      case 16:
888 			putShort (buf, -(long)val);
889 			break;
890 		      case 32:
891 			putLong (buf, -(long)val);
892 			break;
893 		      default:
894 			parse_warn (cfile,
895 				    "Unexpected integer size: %d\n", size);
896 			break;
897 		}
898 	} else {
899 		switch (size) {
900 		      case 8:
901 			*buf = (u_int8_t)val;
902 			break;
903 		      case 16:
904 			putUShort (buf, (u_int16_t)val);
905 			break;
906 		      case 32:
907 			putULong (buf, val);
908 			break;
909 		      default:
910 			parse_warn (cfile,
911 				    "Unexpected integer size: %d\n", size);
912 			break;
913 		}
914 	}
915 }
916 
917 /*
918  * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
919  *		NUMBER COLON NUMBER COLON NUMBER |
920  *          NUMBER NUMBER SLASH NUMBER SLASH NUMBER
921  *		NUMBER COLON NUMBER COLON NUMBER NUMBER |
922  *          EPOCH NUMBER |
923  *	    NEVER
924  *
925  * Dates are stored in UTC or with a timezone offset; first number is day
926  * of week; next is year/month/day; next is hours:minutes:seconds on a
927  * 24-hour clock, followed by the timezone offset in seconds, which is
928  * optional.
929  */
930 
931 /*
932  * just parse the date
933  * any trailing semi must be consumed by the caller of this routine
934  */
935 TIME
936 parse_date_core(cfile)
937 	struct parse *cfile;
938 {
939 	int guess;
940 	int tzoff, year, mon, mday, hour, min, sec;
941 	const char *val;
942 	enum dhcp_token token;
943 	static int months[11] = { 31, 59, 90, 120, 151, 181,
944 				  212, 243, 273, 304, 334 };
945 
946 	/* "never", "epoch" or day of week */
947 	token = peek_token(&val, NULL, cfile);
948 	if (token == NEVER) {
949 		skip_token(&val, NULL, cfile); /* consume NEVER */
950 		return(MAX_TIME);
951 	}
952 
953 	/* This indicates 'local' time format. */
954 	if (token == EPOCH) {
955 		skip_token(&val, NULL, cfile); /* consume EPOCH */
956 		token = peek_token(&val, NULL, cfile);
957 
958 		if (token != NUMBER) {
959 			if (token != SEMI)
960 				skip_token(&val, NULL, cfile);
961 			parse_warn(cfile, "Seconds since epoch expected.");
962 			return((TIME)0);
963 		}
964 
965 		skip_token(&val, NULL, cfile); /* consume number */
966 		guess = atoi(val);
967 
968 		return((TIME)guess);
969 	}
970 
971 	if (token != NUMBER) {
972 		if (token != SEMI)
973 			skip_token(&val, NULL, cfile);
974 		parse_warn(cfile, "numeric day of week expected.");
975 		return((TIME)0);
976 	}
977 	skip_token(&val, NULL, cfile); /* consume day of week */
978         /* we are not using this for anything */
979 
980 	/* Year... */
981 	token = peek_token(&val, NULL, cfile);
982 	if (token != NUMBER) {
983 		if (token != SEMI)
984 			skip_token(&val, NULL, cfile);
985 		parse_warn(cfile, "numeric year expected.");
986 		return((TIME)0);
987 	}
988 	skip_token(&val, NULL, cfile); /* consume year */
989 
990 	/* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
991 	   somebody invents a time machine, I think we can safely disregard
992 	   it.   This actually works around a stupid Y2K bug that was present
993 	   in a very early beta release of dhcpd. */
994 	year = atoi(val);
995 	if (year > 1900)
996 		year -= 1900;
997 
998 	/* Slash separating year from month... */
999 	token = peek_token(&val, NULL, cfile);
1000 	if (token != SLASH) {
1001 		if (token != SEMI)
1002 			skip_token(&val, NULL, cfile);
1003 		parse_warn(cfile,
1004 			   "expected slash separating year from month.");
1005 		return((TIME)0);
1006 	}
1007 	skip_token(&val, NULL, cfile); /* consume SLASH */
1008 
1009 	/* Month... */
1010 	token = peek_token(&val, NULL, cfile);
1011 	if (token != NUMBER) {
1012 		if (token != SEMI)
1013 			skip_token(&val, NULL, cfile);
1014 		parse_warn(cfile, "numeric month expected.");
1015 		return((TIME)0);
1016 	}
1017 	skip_token(&val, NULL, cfile); /* consume month */
1018 	mon = atoi(val) - 1;
1019 
1020 	/* Slash separating month from day... */
1021 	token = peek_token(&val, NULL, cfile);
1022 	if (token != SLASH) {
1023 		if (token != SEMI)
1024 			skip_token(&val, NULL, cfile);
1025 		parse_warn(cfile,
1026 			   "expected slash separating month from day.");
1027 		return((TIME)0);
1028 	}
1029 	skip_token(&val, NULL, cfile); /* consume SLASH */
1030 
1031 	/* Day of month... */
1032 	token = peek_token(&val, NULL, cfile);
1033 	if (token != NUMBER) {
1034 		if (token != SEMI)
1035 			skip_token(&val, NULL, cfile);
1036 		parse_warn(cfile, "numeric day of month expected.");
1037 		return((TIME)0);
1038 	}
1039 	skip_token(&val, NULL, cfile); /* consume day of month */
1040 	mday = atoi(val);
1041 
1042 	/* Hour... */
1043 	token = peek_token(&val, NULL, cfile);
1044 	if (token != NUMBER) {
1045 		if (token != SEMI)
1046 			skip_token(&val, NULL, cfile);
1047 		parse_warn(cfile, "numeric hour expected.");
1048 		return((TIME)0);
1049 	}
1050 	skip_token(&val, NULL, cfile); /* consume hour */
1051 	hour = atoi(val);
1052 
1053 	/* Colon separating hour from minute... */
1054 	token = peek_token(&val, NULL, cfile);
1055 	if (token != COLON) {
1056 		if (token != SEMI)
1057 			skip_token(&val, NULL, cfile);
1058 		parse_warn(cfile,
1059 			   "expected colon separating hour from minute.");
1060 		return((TIME)0);
1061 	}
1062 	skip_token(&val, NULL, cfile); /* consume colon */
1063 
1064 	/* Minute... */
1065 	token = peek_token(&val, NULL, cfile);
1066 	if (token != NUMBER) {
1067 		if (token != SEMI)
1068 			skip_token(&val, NULL, cfile);
1069 		parse_warn(cfile, "numeric minute expected.");
1070 		return((TIME)0);
1071 	}
1072 	skip_token(&val, NULL, cfile); /* consume minute */
1073 	min = atoi(val);
1074 
1075 	/* Colon separating minute from second... */
1076 	token = peek_token(&val, NULL, cfile);
1077 	if (token != COLON) {
1078 		if (token != SEMI)
1079 			skip_token(&val, NULL, cfile);
1080 		parse_warn(cfile,
1081 			   "expected colon separating minute from second.");
1082 		return((TIME)0);
1083 	}
1084 	skip_token(&val, NULL, cfile); /* consume colon */
1085 
1086 	/* Second... */
1087 	token = peek_token(&val, NULL, cfile);
1088 	if (token != NUMBER) {
1089 		if (token != SEMI)
1090 			skip_token(&val, NULL, cfile);
1091 		parse_warn(cfile, "numeric second expected.");
1092 		return((TIME)0);
1093 	}
1094 	skip_token(&val, NULL, cfile); /* consume second */
1095 	sec = atoi(val);
1096 
1097 	tzoff = 0;
1098 	token = peek_token(&val, NULL, cfile);
1099 	if (token == NUMBER) {
1100 		skip_token(&val, NULL, cfile); /* consume tzoff */
1101 		tzoff = atoi(val);
1102 	} else if (token != SEMI) {
1103 		skip_token(&val, NULL, cfile);
1104 		parse_warn(cfile,
1105 			   "Time zone offset or semicolon expected.");
1106 		return((TIME)0);
1107 	}
1108 
1109 	/* Guess the time value... */
1110 	guess = ((((((365 * (year - 70) +	/* Days in years since '70 */
1111 		      (year - 69) / 4 +		/* Leap days since '70 */
1112 		      (mon			/* Days in months this year */
1113 		       ? months [mon - 1]
1114 		       : 0) +
1115 		      (mon > 1 &&		/* Leap day this year */
1116 		       !((year - 72) & 3)) +
1117 		      mday - 1) * 24) +		/* Day of month */
1118 		    hour) * 60) +
1119 		  min) * 60) + sec + tzoff;
1120 
1121 	/* This guess could be wrong because of leap seconds or other
1122 	   weirdness we don't know about that the system does.   For
1123 	   now, we're just going to accept the guess, but at some point
1124 	   it might be nice to do a successive approximation here to
1125 	   get an exact value.   Even if the error is small, if the
1126 	   server is restarted frequently (and thus the lease database
1127 	   is reread), the error could accumulate into something
1128 	   significant. */
1129 
1130 	return((TIME)guess);
1131 }
1132 
1133 /*
1134  * Wrapper to consume the semicolon after the date
1135  * :== date semi
1136  */
1137 
1138 TIME
1139 parse_date(cfile)
1140        struct parse *cfile;
1141 {
1142        TIME guess;
1143        guess = parse_date_core(cfile);
1144 
1145        /* Make sure the date ends in a semicolon... */
1146        if (!parse_semi(cfile))
1147 	       return((TIME)0);
1148        return(guess);
1149 }
1150 
1151 
1152 
1153 /*
1154  * option-name :== IDENTIFIER |
1155  		   IDENTIFIER . IDENTIFIER
1156  */
1157 
1158 isc_result_t
1159 parse_option_name (cfile, allocate, known, opt)
1160 	struct parse *cfile;
1161 	int allocate;
1162 	int *known;
1163 	struct option **opt;
1164 {
1165 	const char *val;
1166 	enum dhcp_token token;
1167 	char *uname;
1168 	struct universe *universe;
1169 	struct option *option;
1170 	unsigned code;
1171 
1172 	if (opt == NULL)
1173 		return DHCP_R_INVALIDARG;
1174 
1175 	token = next_token (&val, (unsigned *)0, cfile);
1176 	if (!is_identifier (token)) {
1177 		parse_warn (cfile,
1178 			    "expecting identifier after option keyword.");
1179 		if (token != SEMI)
1180 			skip_to_semi (cfile);
1181 		return DHCP_R_BADPARSE;
1182 	}
1183 	uname = dmalloc (strlen (val) + 1, MDL);
1184 	if (!uname)
1185 		log_fatal ("no memory for uname information.");
1186 	strcpy (uname, val);
1187 	token = peek_token (&val, (unsigned *)0, cfile);
1188 	if (token == DOT) {
1189 		/* Go ahead and take the DOT token... */
1190 		skip_token(&val, (unsigned *)0, cfile);
1191 
1192 		/* The next token should be an identifier... */
1193 		token = next_token (&val, (unsigned *)0, cfile);
1194 		if (!is_identifier (token)) {
1195 			parse_warn (cfile, "expecting identifier after '.'");
1196 			if (token != SEMI)
1197 				skip_to_semi (cfile);
1198 			return DHCP_R_BADPARSE;
1199 		}
1200 
1201 		/* Look up the option name hash table for the specified
1202 		   uname. */
1203 		universe = (struct universe *)0;
1204 		if (!universe_hash_lookup (&universe, universe_hash,
1205 					   uname, 0, MDL)) {
1206 			parse_warn (cfile, "no option space named %s.", uname);
1207 			skip_to_semi (cfile);
1208 			return ISC_R_NOTFOUND;
1209 		}
1210 	} else {
1211 		/* Use the default hash table, which contains all the
1212 		   standard dhcp option names. */
1213 		val = uname;
1214 		universe = &dhcp_universe;
1215 	}
1216 
1217 	/* Look up the actual option info... */
1218 	option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL);
1219 	option = *opt;
1220 
1221 	/* If we didn't get an option structure, it's an undefined option. */
1222 	if (option) {
1223 		if (known)
1224 			*known = 1;
1225 	/* If the option name is of the form unknown-[decimal], use
1226 	 * the trailing decimal value to find the option definition.
1227 	 * If there is no definition, construct one.  This is to
1228 	 * support legacy use of unknown options in config files or
1229 	 * lease databases.
1230 	 */
1231 	} else if (strncasecmp(val, "unknown-", 8) == 0) {
1232 		code = atoi(val+8);
1233 
1234 		/* Option code 0 is always illegal for us, thanks
1235 		 * to the option decoder.
1236 		 */
1237 		if (code == 0 || code == universe->end) {
1238 			parse_warn(cfile, "Option codes 0 and %u are illegal "
1239 					  "in the %s space.", universe->end,
1240 					  universe->name);
1241 			skip_to_semi(cfile);
1242 			dfree(uname, MDL);
1243 			return ISC_R_FAILURE;
1244 		}
1245 
1246 		/* It's odd to think of unknown option codes as
1247 		 * being known, but this means we know what the
1248 		 * parsed name is talking about.
1249 		 */
1250 		if (known)
1251 			*known = 1;
1252 
1253 		option_code_hash_lookup(opt, universe->code_hash,
1254 					&code, 0, MDL);
1255 		option = *opt;
1256 
1257 		/* If we did not find an option of that code,
1258 		 * manufacture an unknown-xxx option definition.
1259 		 * Its single reference will ensure that it is
1260 		 * deleted once the option is recycled out of
1261 		 * existence (by the parent).
1262 		 */
1263 		if (option == NULL) {
1264 			option = new_option(val, MDL);
1265 			option->universe = universe;
1266 			option->code = code;
1267 			option->format = default_option_format;
1268 			option_reference(opt, option, MDL);
1269 		} else
1270 			log_info("option %s has been redefined as option %s.  "
1271 				 "Please update your configs if neccessary.",
1272 				 val, option->name);
1273 	/* If we've been told to allocate, that means that this
1274 	 * (might) be an option code definition, so we'll create
1275 	 * an option structure and return it for the parent to
1276 	 * decide.
1277 	 */
1278 	} else if (allocate) {
1279 		option = new_option(val, MDL);
1280 		option -> universe = universe;
1281 		option_reference(opt, option, MDL);
1282 	} else {
1283 		parse_warn(cfile, "no option named %s in space %s",
1284 			   val, universe->name);
1285 		skip_to_semi (cfile);
1286 		dfree(uname, MDL);
1287 		return ISC_R_NOTFOUND;
1288 	}
1289 
1290 	/* Free the initial identifier token. */
1291 	dfree (uname, MDL);
1292 	return ISC_R_SUCCESS;
1293 }
1294 
1295 /* IDENTIFIER [WIDTHS] SEMI
1296  *   WIDTHS ~= LENGTH WIDTH NUMBER
1297  *             CODE WIDTH NUMBER
1298  */
1299 
1300 void parse_option_space_decl (cfile)
1301 	struct parse *cfile;
1302 {
1303 	int token;
1304 	const char *val;
1305 	struct universe **ua, *nu;
1306 	char *nu_name;
1307 	int tsize=1, lsize=1, hsize = 0;
1308 
1309 	skip_token(&val, (unsigned *)0, cfile);  /* Discard the SPACE token,
1310 						     which was checked by the
1311 						     caller. */
1312 	token = next_token (&val, (unsigned *)0, cfile);
1313 	if (!is_identifier (token)) {
1314 		parse_warn (cfile, "expecting identifier.");
1315 		skip_to_semi (cfile);
1316 		return;
1317 	}
1318 	nu = new_universe (MDL);
1319 	if (!nu)
1320 		log_fatal ("No memory for new option space.");
1321 
1322 	/* Set up the server option universe... */
1323 	nu_name = dmalloc (strlen (val) + 1, MDL);
1324 	if (!nu_name)
1325 		log_fatal ("No memory for new option space name.");
1326 	strcpy (nu_name, val);
1327 	nu -> name = nu_name;
1328 
1329 	do {
1330 		token = next_token(&val, NULL, cfile);
1331 		switch(token) {
1332 		      case SEMI:
1333 			break;
1334 
1335 		      case CODE:
1336 			token = next_token(&val, NULL, cfile);
1337 			if (token != WIDTH) {
1338 				parse_warn(cfile, "expecting width token.");
1339 				goto bad;
1340 			}
1341 
1342 			token = next_token(&val, NULL, cfile);
1343 			if (token != NUMBER) {
1344 				parse_warn(cfile, "expecting number 1, 2, 4.");
1345 				goto bad;
1346 			}
1347 
1348 			tsize = atoi(val);
1349 
1350 
1351 			switch (tsize) {
1352 			      case 1:
1353 				if (!hsize)
1354 					hsize = BYTE_NAME_HASH_SIZE;
1355 				break;
1356 			      case 2:
1357 				if (!hsize)
1358 					hsize = WORD_NAME_HASH_SIZE;
1359 				break;
1360 			      case 4:
1361 				if (!hsize)
1362 					hsize = QUAD_NAME_HASH_SIZE;
1363 				break;
1364 			      default:
1365 				parse_warn(cfile, "invalid code width (%d), "
1366 					          "expecting a 1, 2 or 4.",
1367 					   tsize);
1368 				goto bad;
1369 			}
1370 			break;
1371 
1372 		      case LENGTH:
1373 			token = next_token(&val, NULL, cfile);
1374 			if (token != WIDTH) {
1375 				parse_warn(cfile, "expecting width token.");
1376 				goto bad;
1377 			}
1378 
1379 			token = next_token(&val, NULL, cfile);
1380 			if (token != NUMBER) {
1381 				parse_warn(cfile, "expecting number 1 or 2.");
1382 				goto bad;
1383 			}
1384 
1385 			lsize = atoi(val);
1386 			if (lsize != 1 && lsize != 2) {
1387 				parse_warn(cfile, "invalid length width (%d) "
1388 						  "expecting 1 or 2.", lsize);
1389 				goto bad;
1390 			}
1391 
1392 			break;
1393 
1394 		      case HASH:
1395 			token = next_token(&val, NULL, cfile);
1396 			if (token != SIZE) {
1397 				parse_warn(cfile, "expecting size token.");
1398 				goto bad;
1399 			}
1400 
1401 			token = next_token(&val, NULL, cfile);
1402 			if (token != NUMBER) {
1403 				parse_warn(cfile, "expecting a 10base number");
1404 				goto bad;
1405 			}
1406 
1407 			/* (2^31)-1 is the highest Mersenne prime we should
1408 			 * probably allow...
1409 			 */
1410 			hsize = atoi(val);
1411 			if (hsize < 0 || hsize > 0x7FFFFFFF) {
1412 				parse_warn(cfile, "invalid hash length: %d",
1413 					   hsize);
1414 				goto bad;
1415 			}
1416 
1417 			break;
1418 
1419 		      default:
1420 			parse_warn(cfile, "Unexpected token.");
1421 		}
1422 	} while (token != SEMI);
1423 
1424 	if (!hsize)
1425 		hsize = DEFAULT_SPACE_HASH_SIZE;
1426 
1427 	nu -> lookup_func = lookup_hashed_option;
1428 	nu -> option_state_dereference = hashed_option_state_dereference;
1429 	nu -> foreach = hashed_option_space_foreach;
1430 	nu -> save_func = save_hashed_option;
1431 	nu -> delete_func = delete_hashed_option;
1432 	nu -> encapsulate = hashed_option_space_encapsulate;
1433 	nu -> decode = parse_option_buffer;
1434 	nu -> length_size = lsize;
1435 	nu -> tag_size = tsize;
1436 	switch(tsize) {
1437 	      case 1:
1438 		nu->get_tag = getUChar;
1439 		nu->store_tag = putUChar;
1440 		break;
1441 	      case 2:
1442 		nu->get_tag = getUShort;
1443 		nu->store_tag = putUShort;
1444 		break;
1445 	      case 4:
1446 		nu->get_tag = getULong;
1447 		nu->store_tag = putULong;
1448 		break;
1449 	      default:
1450 		log_fatal("Impossible condition at %s:%d.", MDL);
1451 	}
1452 	switch(lsize) {
1453 	     case 0:
1454 		nu->get_length = NULL;
1455 		nu->store_length = NULL;
1456 		break;
1457 	     case 1:
1458 		nu->get_length = getUChar;
1459 		nu->store_length = putUChar;
1460 		break;
1461 	     case 2:
1462 		nu->get_length = getUShort;
1463 		nu->store_length = putUShort;
1464 		break;
1465 	     default:
1466 		log_fatal("Impossible condition at %s:%d.", MDL);
1467 	}
1468 	nu -> index = universe_count++;
1469 	if (nu -> index >= universe_max) {
1470 		ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
1471 		if (!ua)
1472 			log_fatal ("No memory to expand option space array.");
1473 		memcpy (ua, universes, universe_max * sizeof *ua);
1474 		universe_max *= 2;
1475 		dfree (universes, MDL);
1476 		universes = ua;
1477 	}
1478 	universes [nu -> index] = nu;
1479 	if (!option_name_new_hash(&nu->name_hash, hsize, MDL) ||
1480 	    !option_code_new_hash(&nu->code_hash, hsize, MDL))
1481 		log_fatal("Can't allocate %s option hash table.", nu->name);
1482 	universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
1483 	return;
1484 
1485     bad:
1486 	dfree(nu_name, MDL);
1487 	dfree(nu, MDL);
1488 }
1489 
1490 /* This is faked up to look good right now.   Ideally, this should do a
1491    recursive parse and allow arbitrary data structure definitions, but for
1492    now it just allows you to specify a single type, an array of single types,
1493    a sequence of types, or an array of sequences of types.
1494 
1495    ocd :== NUMBER EQUALS ocsd SEMI
1496 
1497    ocsd :== ocsd_type |
1498 	    ocsd_type_sequence |
1499 	    ARRAY OF ocsd_simple_type_sequence
1500 
1501    ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1502 
1503    ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1504 
1505    ocsd_types :== ocsd_type |
1506 		  ocsd_types ocsd_type
1507 
1508    ocsd_type :== ocsd_simple_type |
1509 		 ARRAY OF ocsd_simple_type
1510 
1511    ocsd_simple_types :== ocsd_simple_type |
1512 			 ocsd_simple_types ocsd_simple_type
1513 
1514    ocsd_simple_type :== BOOLEAN |
1515 			INTEGER NUMBER |
1516 			SIGNED INTEGER NUMBER |
1517 			UNSIGNED INTEGER NUMBER |
1518 			IP-ADDRESS |
1519 			TEXT |
1520 			STRING |
1521 			ENCAPSULATE identifier */
1522 
1523 int parse_option_code_definition (cfile, option)
1524 	struct parse *cfile;
1525 	struct option *option;
1526 {
1527 	const char *val;
1528 	enum dhcp_token token;
1529 	struct option *oldopt;
1530 	unsigned arrayp = 0;
1531 	int recordp = 0;
1532 	int no_more_in_record = 0;
1533 	char tokbuf [128];
1534 	unsigned tokix = 0;
1535 	char type;
1536 	int is_signed;
1537 	char *s;
1538 	int has_encapsulation = 0;
1539 	struct universe *encapsulated;
1540 
1541 	/* Parse the option code. */
1542 	token = next_token (&val, (unsigned *)0, cfile);
1543 	if (token != NUMBER) {
1544 		parse_warn (cfile, "expecting option code number.");
1545 		skip_to_semi (cfile);
1546 		return 0;
1547 	}
1548 	option -> code = atoi (val);
1549 
1550 	token = next_token (&val, (unsigned *)0, cfile);
1551 	if (token != EQUAL) {
1552 		parse_warn (cfile, "expecting \"=\"");
1553 		skip_to_semi (cfile);
1554 		return 0;
1555 	}
1556 
1557 	/* See if this is an array. */
1558 	token = next_token (&val, (unsigned *)0, cfile);
1559 	if (token == ARRAY) {
1560 		token = next_token (&val, (unsigned *)0, cfile);
1561 		if (token != OF) {
1562 			parse_warn (cfile, "expecting \"of\".");
1563 			skip_to_semi (cfile);
1564 			return 0;
1565 		}
1566 		arrayp = 1;
1567 		token = next_token (&val, (unsigned *)0, cfile);
1568 	}
1569 
1570 	if (token == LBRACE) {
1571 		recordp = 1;
1572 		token = next_token (&val, (unsigned *)0, cfile);
1573 	}
1574 
1575 	/* At this point we're expecting a data type. */
1576       next_type:
1577 	if (has_encapsulation) {
1578 		parse_warn (cfile,
1579 			    "encapsulate must always be the last item.");
1580 		skip_to_semi (cfile);
1581 		return 0;
1582 	}
1583 
1584 	switch (token) {
1585 	      case ARRAY:
1586 		if (arrayp) {
1587 			parse_warn (cfile, "no nested arrays.");
1588 			skip_to_rbrace (cfile, recordp);
1589 			if (recordp)
1590 				skip_to_semi (cfile);
1591 			return 0;
1592 		}
1593 		token = next_token (&val, (unsigned *)0, cfile);
1594 		if (token != OF) {
1595 			parse_warn (cfile, "expecting \"of\".");
1596 			skip_to_semi (cfile);
1597 			return 0;
1598 		}
1599 		arrayp = recordp + 1;
1600 		token = next_token (&val, (unsigned *)0, cfile);
1601 		if ((recordp) && (token == LBRACE)) {
1602 			parse_warn (cfile,
1603 				    "only uniform array inside record.");
1604 			skip_to_rbrace (cfile, recordp + 1);
1605 			skip_to_semi (cfile);
1606 			return 0;
1607 		}
1608 		goto next_type;
1609 	      case BOOLEAN:
1610 		type = 'f';
1611 		break;
1612 	      case INTEGER:
1613 		is_signed = 1;
1614 	      parse_integer:
1615 		token = next_token (&val, (unsigned *)0, cfile);
1616 		if (token != NUMBER) {
1617 			parse_warn (cfile, "expecting number.");
1618 			skip_to_rbrace (cfile, recordp);
1619 			if (recordp)
1620 				skip_to_semi (cfile);
1621 			return 0;
1622 		}
1623 		switch (atoi (val)) {
1624 		      case 8:
1625 			type = is_signed ? 'b' : 'B';
1626 			break;
1627 		      case 16:
1628 			type = is_signed ? 's' : 'S';
1629 			break;
1630 		      case 32:
1631 			type = is_signed ? 'l' : 'L';
1632 			break;
1633 		      default:
1634 			parse_warn (cfile,
1635 				    "%s bit precision is not supported.", val);
1636 			skip_to_rbrace (cfile, recordp);
1637 			if (recordp)
1638 				skip_to_semi (cfile);
1639 			return 0;
1640 		}
1641 		break;
1642 	      case SIGNED:
1643 		is_signed = 1;
1644 	      parse_signed:
1645 		token = next_token (&val, (unsigned *)0, cfile);
1646 		if (token != INTEGER) {
1647 			parse_warn (cfile, "expecting \"integer\" keyword.");
1648 			skip_to_rbrace (cfile, recordp);
1649 			if (recordp)
1650 				skip_to_semi (cfile);
1651 			return 0;
1652 		}
1653 		goto parse_integer;
1654 	      case UNSIGNED:
1655 		is_signed = 0;
1656 		goto parse_signed;
1657 
1658 	      case IP_ADDRESS:
1659 		type = 'I';
1660 		break;
1661 	      case IP6_ADDRESS:
1662 		type = '6';
1663 		break;
1664 	      case DOMAIN_NAME:
1665 		type = 'd';
1666 		goto no_arrays;
1667 	      case DOMAIN_LIST:
1668 		/* Consume optional compression indicator. */
1669 		token = peek_token(&val, NULL, cfile);
1670 		if (token == COMPRESSED) {
1671 			skip_token(&val, NULL, cfile);
1672 			tokbuf[tokix++] = 'D';
1673 			type = 'c';
1674 		} else
1675 			type = 'D';
1676 		goto no_arrays;
1677 	      case TEXT:
1678 		type = 't';
1679 	      no_arrays:
1680 		if (arrayp) {
1681 			parse_warn (cfile, "arrays of text strings not %s",
1682 				    "yet supported.");
1683 			skip_to_rbrace (cfile, recordp);
1684 			if (recordp)
1685 				skip_to_semi (cfile);
1686 			return 0;
1687 		}
1688 		no_more_in_record = 1;
1689 		break;
1690 	      case STRING_TOKEN:
1691 		type = 'X';
1692 		goto no_arrays;
1693 
1694 	      case ENCAPSULATE:
1695 		token = next_token (&val, (unsigned *)0, cfile);
1696 		if (!is_identifier (token)) {
1697 			parse_warn (cfile,
1698 				    "expecting option space identifier");
1699 			skip_to_semi (cfile);
1700 			return 0;
1701 		}
1702 		encapsulated = NULL;
1703 		if (!universe_hash_lookup(&encapsulated, universe_hash,
1704 					  val, strlen(val), MDL)) {
1705 			parse_warn(cfile, "unknown option space %s", val);
1706 			skip_to_semi (cfile);
1707 			return 0;
1708 		}
1709 		if (strlen (val) + tokix + 2 > sizeof (tokbuf))
1710 			goto toobig;
1711 		tokbuf [tokix++] = 'E';
1712 		strcpy (&tokbuf [tokix], val);
1713 		tokix += strlen (val);
1714 		type = '.';
1715 		has_encapsulation = 1;
1716 		break;
1717 
1718 	      case ZEROLEN:
1719 		type = 'Z';
1720 		if (arrayp) {
1721 			parse_warn (cfile, "array incompatible with zerolen.");
1722 			skip_to_rbrace (cfile, recordp);
1723 			if (recordp)
1724 				skip_to_semi (cfile);
1725 			return 0;
1726 		}
1727 		no_more_in_record = 1;
1728 		break;
1729 
1730 	      default:
1731 		parse_warn (cfile, "unknown data type %s", val);
1732 		skip_to_rbrace (cfile, recordp);
1733 		if (recordp)
1734 			skip_to_semi (cfile);
1735 		return 0;
1736 	}
1737 
1738 	if (tokix == sizeof tokbuf) {
1739 	      toobig:
1740 		parse_warn (cfile, "too many types in record.");
1741 		skip_to_rbrace (cfile, recordp);
1742 		if (recordp)
1743 			skip_to_semi (cfile);
1744 		return 0;
1745 	}
1746 	tokbuf [tokix++] = type;
1747 
1748 	if (recordp) {
1749 		token = next_token (&val, (unsigned *)0, cfile);
1750 		if (arrayp > recordp) {
1751 			if (tokix == sizeof tokbuf) {
1752 				parse_warn (cfile,
1753 					    "too many types in record.");
1754 				skip_to_rbrace (cfile, 1);
1755 				skip_to_semi (cfile);
1756 				return 0;
1757 			}
1758 			arrayp = 0;
1759 			tokbuf[tokix++] = 'a';
1760 		}
1761 		if (token == COMMA) {
1762 			if (no_more_in_record) {
1763 				parse_warn (cfile,
1764 					    "%s must be at end of record.",
1765 					    type == 't' ? "text" : "string");
1766 				skip_to_rbrace (cfile, 1);
1767 				if (recordp)
1768 					skip_to_semi (cfile);
1769 				return 0;
1770 			}
1771 			token = next_token (&val, (unsigned *)0, cfile);
1772 			goto next_type;
1773 		}
1774 		if (token != RBRACE) {
1775 			parse_warn (cfile, "expecting right brace.");
1776 			skip_to_rbrace (cfile, 1);
1777 			if (recordp)
1778 				skip_to_semi (cfile);
1779 			return 0;
1780 		}
1781 	}
1782 	if (!parse_semi (cfile)) {
1783 		parse_warn (cfile, "semicolon expected.");
1784 		skip_to_semi (cfile);
1785 		if (recordp)
1786 			skip_to_semi (cfile);
1787 		return 0;
1788 	}
1789 	if (has_encapsulation && arrayp) {
1790 		parse_warn (cfile,
1791 			    "Arrays of encapsulations don't make sense.");
1792 		return 0;
1793 	}
1794 	s = dmalloc(tokix + (arrayp ? 1 : 0) + 1, MDL);
1795 	if (s == NULL) {
1796 		log_fatal("no memory for option format.");
1797 	}
1798 	memcpy(s, tokbuf, tokix);
1799 	if (arrayp) {
1800 		s[tokix++] = (arrayp > recordp) ? 'a' : 'A';
1801 	}
1802 	s[tokix] = '\0';
1803 
1804 	option -> format = s;
1805 
1806 	oldopt = NULL;
1807 	option_code_hash_lookup(&oldopt, option->universe->code_hash,
1808 				&option->code, 0, MDL);
1809 	if (oldopt != NULL) {
1810 		/*
1811 		 * XXX: This illegalizes a configuration syntax that was
1812 		 * valid in 3.0.x, where multiple name->code mappings are
1813 		 * given, but only one code->name mapping survives.  It is
1814 		 * unclear what can or should be done at this point, but it
1815 		 * seems best to retain 3.0.x behaviour for upgrades to go
1816 		 * smoothly.
1817 		 *
1818 		option_name_hash_delete(option->universe->name_hash,
1819 					oldopt->name, 0, MDL);
1820 		 */
1821 		option_code_hash_delete(option->universe->code_hash,
1822 					&oldopt->code, 0, MDL);
1823 
1824 		option_dereference(&oldopt, MDL);
1825 	}
1826 	option_code_hash_add(option->universe->code_hash, &option->code, 0,
1827 			     option, MDL);
1828 	option_name_hash_add(option->universe->name_hash, option->name, 0,
1829 			     option, MDL);
1830 	if (has_encapsulation) {
1831 		/* INSIST(tokbuf[0] == 'E'); */
1832 		/* INSIST(encapsulated != NULL); */
1833 		if (!option_code_hash_lookup(&encapsulated->enc_opt,
1834 					     option->universe->code_hash,
1835 					     &option->code, 0, MDL)) {
1836 			log_fatal("error finding encapsulated option (%s:%d)",
1837 				  MDL);
1838 		}
1839 	}
1840 	return 1;
1841 }
1842 
1843 /*
1844  * base64 :== NUMBER_OR_STRING
1845  */
1846 
1847 int parse_base64 (data, cfile)
1848 	struct data_string *data;
1849 	struct parse *cfile;
1850 {
1851 	const char *val;
1852 	int i, j, k;
1853 	unsigned acc = 0;
1854 	static unsigned char
1855 		from64 [] = {64, 64, 64, 64, 64, 64, 64, 64,  /*  \"#$%&' */
1856 			     64, 64, 64, 62, 64, 64, 64, 63,  /* ()*+,-./ */
1857 			     52, 53, 54, 55, 56, 57, 58, 59,  /* 01234567 */
1858 			     60, 61, 64, 64, 64, 64, 64, 64,  /* 89:;<=>? */
1859 			     64, 0, 1, 2, 3, 4, 5, 6,	      /* @ABCDEFG */
1860 			     7, 8, 9, 10, 11, 12, 13, 14,     /* HIJKLMNO */
1861 			     15, 16, 17, 18, 19, 20, 21, 22,  /* PQRSTUVW */
1862 			     23, 24, 25, 64, 64, 64, 64, 64,  /* XYZ[\]^_ */
1863 			     64, 26, 27, 28, 29, 30, 31, 32,  /* 'abcdefg */
1864 			     33, 34, 35, 36, 37, 38, 39, 40,  /* hijklmno */
1865 			     41, 42, 43, 44, 45, 46, 47, 48,  /* pqrstuvw */
1866 			     49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~  */
1867 	struct string_list *bufs = NULL,
1868 			   *last = NULL,
1869 			   *t;
1870 	int cc = 0;
1871 	int terminated = 0;
1872 	int valid_base64;
1873 
1874 	/* It's possible for a + or a / to cause a base64 quantity to be
1875 	   tokenized into more than one token, so we have to parse them all
1876 	   in before decoding. */
1877 	do {
1878 		unsigned l;
1879 
1880 		(void)next_token(&val, &l, cfile);
1881 		t = dmalloc(l + sizeof(*t), MDL);
1882 		if (t == NULL)
1883 			log_fatal("no memory for base64 buffer.");
1884 		memset(t, 0, (sizeof(*t)) - 1);
1885 		memcpy(t->string, val, l + 1);
1886 		cc += l;
1887 		if (last)
1888 			last->next = t;
1889 		else
1890 			bufs = t;
1891 		last = t;
1892 		(void)peek_token(&val, NULL, cfile);
1893 		valid_base64 = 1;
1894 		for (i = 0; val[i]; i++) {
1895 			/* Check to see if the character is valid.  It
1896 			   may be out of range or within the right range
1897 			   but not used in the mapping */
1898 			if (((val[i] < ' ') || (val[i] > 'z')) ||
1899 			    ((from64[val[i] - ' '] > 63) && (val[i] != '='))) {
1900 				valid_base64 = 0;
1901 				break; /* no need to continue for loop */
1902 			}
1903 		}
1904 	} while (valid_base64);
1905 
1906 	data->len = cc;
1907 	data->len = (data->len * 3) / 4;
1908 	if (!buffer_allocate(&data->buffer, data->len, MDL)) {
1909 		parse_warn (cfile, "can't allocate buffer for base64 data.");
1910 		data->len = 0;
1911 		data->data = NULL;
1912 		goto out;
1913 	}
1914 
1915 	j = k = 0;
1916 	for (t = bufs; t; t = t->next) {
1917 	    for (i = 0; t->string[i]; i++) {
1918 		unsigned foo = t->string[i];
1919 		if (terminated && foo != '=') {
1920 			parse_warn(cfile,
1921 				   "stuff after base64 '=' terminator: %s.",
1922 				   &t->string[i]);
1923 			goto bad;
1924 		}
1925 		if ((foo < ' ') || (foo > 'z')) {
1926 		      bad64:
1927 			parse_warn(cfile,
1928 				   "invalid base64 character %d.",
1929 				   t->string[i]);
1930 		      bad:
1931 			data_string_forget(data, MDL);
1932 			goto out;
1933 		}
1934 		if (foo == '=')
1935 			terminated = 1;
1936 		else {
1937 			foo = from64[foo - ' '];
1938 			if (foo == 64)
1939 				goto bad64;
1940 			acc = (acc << 6) + foo;
1941 			switch (k % 4) {
1942 			      case 0:
1943 				break;
1944 			      case 1:
1945 				data->buffer->data[j++] = (acc >> 4);
1946 				acc = acc & 0x0f;
1947 				break;
1948 
1949 			      case 2:
1950 				data->buffer->data[j++] = (acc >> 2);
1951 				acc = acc & 0x03;
1952 				break;
1953 			      case 3:
1954 				data->buffer->data[j++] = acc;
1955 				acc = 0;
1956 				break;
1957 			}
1958 		}
1959 		k++;
1960 	    }
1961 	}
1962 	if (k % 4) {
1963 		if (acc) {
1964 			parse_warn(cfile,
1965 				   "partial base64 value left over: %d.",
1966 				   acc);
1967 		}
1968 	}
1969 	data->len = j;
1970 	data->data = data->buffer->data;
1971       out:
1972 	for (t = bufs; t; t = last) {
1973 		last = t->next;
1974 		dfree(t, MDL);
1975 	}
1976 	if (data->len)
1977 		return 1;
1978 	else
1979 		return 0;
1980 }
1981 
1982 
1983 /*
1984  * colon-separated-hex-list :== NUMBER |
1985  *				NUMBER COLON colon-separated-hex-list
1986  */
1987 
1988 int parse_cshl (data, cfile)
1989 	struct data_string *data;
1990 	struct parse *cfile;
1991 {
1992 	u_int8_t ibuf [128];
1993 	unsigned ilen = 0;
1994 	unsigned tlen = 0;
1995 	struct option_tag *sl = (struct option_tag *)0;
1996 	struct option_tag *next, **last = &sl;
1997 	enum dhcp_token token;
1998 	const char *val;
1999 	unsigned char *rvp;
2000 
2001 	do {
2002 		token = next_token (&val, (unsigned *)0, cfile);
2003 		if (token != NUMBER && token != NUMBER_OR_NAME) {
2004 			parse_warn (cfile, "expecting hexadecimal number.");
2005 			skip_to_semi (cfile);
2006 			for (; sl; sl = next) {
2007 				next = sl -> next;
2008 				dfree (sl, MDL);
2009 			}
2010 			return 0;
2011 		}
2012 		if (ilen == sizeof ibuf) {
2013 			next = (struct option_tag *)
2014 				dmalloc (ilen - 1 +
2015 					 sizeof (struct option_tag), MDL);
2016 			if (!next)
2017 				log_fatal ("no memory for string list.");
2018 			memcpy (next -> data, ibuf, ilen);
2019 			*last = next;
2020 			last = &next -> next;
2021 			tlen += ilen;
2022 			ilen = 0;
2023 		}
2024 		convert_num (cfile, &ibuf [ilen++], val, 16, 8);
2025 
2026 		token = peek_token (&val, (unsigned *)0, cfile);
2027 		if (token != COLON)
2028 			break;
2029 		skip_token(&val, (unsigned *)0, cfile);
2030 	} while (1);
2031 
2032 	if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
2033 		log_fatal ("no memory to store octet data.");
2034 	data -> data = &data -> buffer -> data [0];
2035 	data -> len = tlen + ilen;
2036 	data -> terminated = 0;
2037 
2038 	rvp = &data -> buffer -> data [0];
2039 	while (sl) {
2040 		next = sl -> next;
2041 		memcpy (rvp, sl -> data, sizeof ibuf);
2042 		rvp += sizeof ibuf;
2043 		dfree (sl, MDL);
2044 		sl = next;
2045 	}
2046 
2047 	memcpy (rvp, ibuf, ilen);
2048 	return 1;
2049 }
2050 
2051 /*
2052  * executable-statements :== executable-statement executable-statements |
2053  *			     executable-statement
2054  *
2055  * executable-statement :==
2056  *	IF if-statement |
2057  * 	ADD class-name SEMI |
2058  *	BREAK SEMI |
2059  *	OPTION option-parameter SEMI |
2060  *	SUPERSEDE option-parameter SEMI |
2061  *	PREPEND option-parameter SEMI |
2062  *	APPEND option-parameter SEMI
2063  */
2064 
2065 int parse_executable_statements (statements, cfile, lose, case_context)
2066 	struct executable_statement **statements;
2067 	struct parse *cfile;
2068 	int *lose;
2069 	enum expression_context case_context;
2070 {
2071 	struct executable_statement **next;
2072 
2073 	next = statements;
2074 	while (parse_executable_statement (next, cfile, lose, case_context))
2075 		next = &((*next) -> next);
2076 	if (!*lose)
2077 		return 1;
2078 	return 0;
2079 }
2080 
2081 int parse_executable_statement (result, cfile, lose, case_context)
2082 	struct executable_statement **result;
2083 	struct parse *cfile;
2084 	int *lose;
2085 	enum expression_context case_context;
2086 {
2087 #if defined(ENABLE_EXECUTE)
2088 	unsigned len;
2089 	struct expression **ep;
2090 #endif
2091 	enum dhcp_token token;
2092 	const char *val;
2093 	struct class *cta;
2094 	struct option *option=NULL;
2095 	struct option_cache *cache;
2096 	int known;
2097 	int flag;
2098 	int i;
2099 	struct dns_zone *zone;
2100 	isc_result_t status;
2101 	char *s;
2102 
2103 	token = peek_token (&val, (unsigned *)0, cfile);
2104 	switch (token) {
2105 	      case DB_TIME_FORMAT:
2106 		skip_token(&val, NULL, cfile);
2107 		token = next_token(&val, NULL, cfile);
2108 		if (token == DEFAULT) {
2109 			db_time_format = DEFAULT_TIME_FORMAT;
2110 		} else if (token == LOCAL) {
2111 			db_time_format = LOCAL_TIME_FORMAT;
2112 		} else {
2113 			parse_warn(cfile, "Expecting 'local' or 'default'.");
2114 			if (token != SEMI)
2115 				skip_to_semi(cfile);
2116 			*lose = 1;
2117 			return 0;
2118 		}
2119 
2120 		token = next_token(&val, NULL, cfile);
2121 		if (token != SEMI) {
2122 			parse_warn(cfile, "Expecting a semicolon.");
2123 			*lose = 1;
2124 			return 0;
2125 		}
2126 
2127 		/* We're done here. */
2128 		return 1;
2129 
2130 	      case IF:
2131 		skip_token(&val, (unsigned *)0, cfile);
2132 		return parse_if_statement (result, cfile, lose);
2133 
2134 	      case TOKEN_ADD:
2135 		skip_token(&val, (unsigned *)0, cfile);
2136 		token = next_token (&val, (unsigned *)0, cfile);
2137 		if (token != STRING) {
2138 			parse_warn (cfile, "expecting class name.");
2139 			skip_to_semi (cfile);
2140 			*lose = 1;
2141 			return 0;
2142 		}
2143 		cta = (struct class *)0;
2144 		status = find_class (&cta, val, MDL);
2145 		if (status != ISC_R_SUCCESS) {
2146 			parse_warn (cfile, "class %s: %s",
2147 				    val, isc_result_totext (status));
2148 			skip_to_semi (cfile);
2149 			*lose = 1;
2150 			return 0;
2151 		}
2152 		if (!parse_semi (cfile)) {
2153 			*lose = 1;
2154 			return 0;
2155 		}
2156 		if (!executable_statement_allocate (result, MDL))
2157 			log_fatal ("no memory for new statement.");
2158 		(*result) -> op = add_statement;
2159 		(*result) -> data.add = cta;
2160 		break;
2161 
2162 	      case BREAK:
2163 		skip_token(&val, (unsigned *)0, cfile);
2164 		if (!parse_semi (cfile)) {
2165 			*lose = 1;
2166 			return 0;
2167 		}
2168 		if (!executable_statement_allocate (result, MDL))
2169 			log_fatal ("no memory for new statement.");
2170 		(*result) -> op = break_statement;
2171 		break;
2172 
2173 	      case SEND:
2174 		skip_token(&val, (unsigned *)0, cfile);
2175 		known = 0;
2176 		status = parse_option_name (cfile, 0, &known, &option);
2177 		if (status != ISC_R_SUCCESS || option == NULL) {
2178 			*lose = 1;
2179 			return 0;
2180 		}
2181 		status = parse_option_statement(result, cfile, 1, option,
2182 						send_option_statement);
2183 		option_dereference(&option, MDL);
2184 		return status;
2185 
2186 	      case SUPERSEDE:
2187 	      case OPTION:
2188 		skip_token(&val, (unsigned *)0, cfile);
2189 		known = 0;
2190 		status = parse_option_name (cfile, 0, &known, &option);
2191 		if (status != ISC_R_SUCCESS || option == NULL) {
2192 			*lose = 1;
2193 			return 0;
2194 		}
2195 		status = parse_option_statement(result, cfile, 1, option,
2196 						supersede_option_statement);
2197 		option_dereference(&option, MDL);
2198 		return status;
2199 
2200 	      case ALLOW:
2201 		flag = 1;
2202 		goto pad;
2203 	      case DENY:
2204 		flag = 0;
2205 		goto pad;
2206 	      case IGNORE:
2207 		flag = 2;
2208 	      pad:
2209 		skip_token(&val, (unsigned *)0, cfile);
2210 		cache = (struct option_cache *)0;
2211 		if (!parse_allow_deny (&cache, cfile, flag))
2212 			return 0;
2213 		if (!executable_statement_allocate (result, MDL))
2214 			log_fatal ("no memory for new statement.");
2215 		(*result) -> op = supersede_option_statement;
2216 		(*result) -> data.option = cache;
2217 		break;
2218 
2219 	      case DEFAULT:
2220 		skip_token(&val, (unsigned *)0, cfile);
2221 		token = peek_token (&val, (unsigned *)0, cfile);
2222 		if (token == COLON)
2223 			goto switch_default;
2224 		known = 0;
2225 		status = parse_option_name (cfile, 0, &known, &option);
2226 		if (status != ISC_R_SUCCESS || option == NULL) {
2227 			*lose = 1;
2228 			return 0;
2229 		}
2230 		status = parse_option_statement(result, cfile, 1, option,
2231 						default_option_statement);
2232 		option_dereference(&option, MDL);
2233 		return status;
2234 
2235 	      case PREPEND:
2236 		skip_token(&val, (unsigned *)0, cfile);
2237 		known = 0;
2238 		status = parse_option_name (cfile, 0, &known, &option);
2239 		if (status != ISC_R_SUCCESS || option == NULL) {
2240 			*lose = 1;
2241 			return 0;
2242 		}
2243 		status = parse_option_statement(result, cfile, 1, option,
2244 						prepend_option_statement);
2245 		option_dereference(&option, MDL);
2246 		return status;
2247 
2248 	      case APPEND:
2249 		skip_token(&val, (unsigned *)0, cfile);
2250 		known = 0;
2251 		status = parse_option_name (cfile, 0, &known, &option);
2252 		if (status != ISC_R_SUCCESS || option == NULL) {
2253 			*lose = 1;
2254 			return 0;
2255 		}
2256 		status = parse_option_statement(result, cfile, 1, option,
2257 						append_option_statement);
2258 		option_dereference(&option, MDL);
2259 		return status;
2260 
2261 	      case ON:
2262 		skip_token(&val, (unsigned *)0, cfile);
2263 		return parse_on_statement (result, cfile, lose);
2264 
2265 	      case SWITCH:
2266 		skip_token(&val, (unsigned *)0, cfile);
2267 		return parse_switch_statement (result, cfile, lose);
2268 
2269 	      case CASE:
2270 		skip_token(&val, (unsigned *)0, cfile);
2271 		if (case_context == context_any) {
2272 			parse_warn (cfile,
2273 				    "case statement in inappropriate scope.");
2274 			*lose = 1;
2275 			skip_to_semi (cfile);
2276 			return 0;
2277 		}
2278 		return parse_case_statement (result,
2279 					     cfile, lose, case_context);
2280 
2281 	      switch_default:
2282 		skip_token(&val, (unsigned *)0, cfile);
2283 		if (case_context == context_any) {
2284 			parse_warn (cfile, "switch default statement in %s",
2285 				    "inappropriate scope.");
2286 
2287 			*lose = 1;
2288 			return 0;
2289 		} else {
2290 			if (!executable_statement_allocate (result, MDL))
2291 				log_fatal ("no memory for default statement.");
2292 			(*result) -> op = default_statement;
2293 			return 1;
2294 		}
2295 
2296 	      case DEFINE:
2297 	      case TOKEN_SET:
2298 		skip_token(&val, (unsigned *)0, cfile);
2299 		if (token == DEFINE)
2300 			flag = 1;
2301 		else
2302 			flag = 0;
2303 
2304 		token = next_token (&val, (unsigned *)0, cfile);
2305 		if (token != NAME && token != NUMBER_OR_NAME) {
2306 			parse_warn (cfile,
2307 				    "%s can't be a variable name", val);
2308 		      badset:
2309 			skip_to_semi (cfile);
2310 			*lose = 1;
2311 			return 0;
2312 		}
2313 
2314 		if (!executable_statement_allocate (result, MDL))
2315 			log_fatal ("no memory for set statement.");
2316 		(*result) -> op = flag ? define_statement : set_statement;
2317 		(*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
2318 		if (!(*result)->data.set.name)
2319 			log_fatal ("can't allocate variable name");
2320 		strcpy ((*result) -> data.set.name, val);
2321 		token = next_token (&val, (unsigned *)0, cfile);
2322 
2323 		if (token == LPAREN) {
2324 			struct string_list *head, *cur, *new;
2325 			struct expression *expr;
2326 			head = cur = (struct string_list *)0;
2327 			do {
2328 				token = next_token (&val,
2329 						    (unsigned *)0, cfile);
2330 				if (token == RPAREN)
2331 					break;
2332 				if (token != NAME && token != NUMBER_OR_NAME) {
2333 					parse_warn (cfile,
2334 						    "expecting argument name");
2335 					skip_to_rbrace (cfile, 0);
2336 					*lose = 1;
2337 					executable_statement_dereference
2338 						(result, MDL);
2339 					return 0;
2340 				}
2341 				new = ((struct string_list *)
2342 				       dmalloc (sizeof (struct string_list) +
2343 						strlen (val), MDL));
2344 				if (!new)
2345 					log_fatal ("can't allocate string.");
2346 				memset (new, 0, sizeof *new);
2347 				strcpy (new -> string, val);
2348 				if (cur) {
2349 					cur -> next = new;
2350 					cur = new;
2351 				} else {
2352 					head = cur = new;
2353 				}
2354 				token = next_token (&val,
2355 						    (unsigned *)0, cfile);
2356 			} while (token == COMMA);
2357 
2358 			if (token != RPAREN) {
2359 				parse_warn (cfile, "expecting right paren.");
2360 			      badx:
2361 				skip_to_semi (cfile);
2362 				*lose = 1;
2363 				executable_statement_dereference (result, MDL);
2364 				return 0;
2365 			}
2366 
2367 			token = next_token (&val, (unsigned *)0, cfile);
2368 			if (token != LBRACE) {
2369 				parse_warn (cfile, "expecting left brace.");
2370 				goto badx;
2371 			}
2372 
2373 			expr = (struct expression *)0;
2374 			if (!(expression_allocate (&expr, MDL)))
2375 				log_fatal ("can't allocate expression.");
2376 			expr -> op = expr_function;
2377 			if (!fundef_allocate (&expr -> data.func, MDL))
2378 				log_fatal ("can't allocate fundef.");
2379 			expr -> data.func -> args = head;
2380 			(*result) -> data.set.expr = expr;
2381 
2382 			if (!(parse_executable_statements
2383 			      (&expr -> data.func -> statements, cfile, lose,
2384 			       case_context))) {
2385 				if (*lose)
2386 					goto badx;
2387 			}
2388 
2389 			token = next_token (&val, (unsigned *)0, cfile);
2390 			if (token != RBRACE) {
2391 				parse_warn (cfile, "expecting rigt brace.");
2392 				goto badx;
2393 			}
2394 		} else {
2395 			if (token != EQUAL) {
2396 				parse_warn (cfile,
2397 					    "expecting '=' in %s statement.",
2398 					    flag ? "define" : "set");
2399 				goto badset;
2400 			}
2401 
2402 			if (!parse_expression (&(*result) -> data.set.expr,
2403 					       cfile, lose, context_any,
2404 					       (struct expression **)0,
2405 					       expr_none)) {
2406 				if (!*lose)
2407 					parse_warn (cfile,
2408 						    "expecting expression.");
2409 				else
2410 					*lose = 1;
2411 				skip_to_semi (cfile);
2412 				executable_statement_dereference (result, MDL);
2413 				return 0;
2414 			}
2415 			if (!parse_semi (cfile)) {
2416 				*lose = 1;
2417 				executable_statement_dereference (result, MDL);
2418 				return 0;
2419 			}
2420 		}
2421 		break;
2422 
2423 	      case UNSET:
2424 		skip_token(&val, (unsigned *)0, cfile);
2425 		token = next_token (&val, (unsigned *)0, cfile);
2426 		if (token != NAME && token != NUMBER_OR_NAME) {
2427 			parse_warn (cfile,
2428 				    "%s can't be a variable name", val);
2429 			skip_to_semi (cfile);
2430 			*lose = 1;
2431 			return 0;
2432 		}
2433 
2434 		if (!executable_statement_allocate (result, MDL))
2435 			log_fatal ("no memory for set statement.");
2436 		(*result) -> op = unset_statement;
2437 		(*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
2438 		if (!(*result)->data.unset)
2439 			log_fatal ("can't allocate variable name");
2440 		strcpy ((*result) -> data.unset, val);
2441 		if (!parse_semi (cfile)) {
2442 			*lose = 1;
2443 			executable_statement_dereference (result, MDL);
2444 			return 0;
2445 		}
2446 		break;
2447 
2448 	      case EVAL:
2449 		skip_token(&val, (unsigned *)0, cfile);
2450 		if (!executable_statement_allocate (result, MDL))
2451 			log_fatal ("no memory for eval statement.");
2452 		(*result) -> op = eval_statement;
2453 
2454 		if (!parse_expression (&(*result) -> data.eval,
2455 				       cfile, lose, context_data, /* XXX */
2456 				       (struct expression **)0, expr_none)) {
2457 			if (!*lose)
2458 				parse_warn (cfile,
2459 					    "expecting data expression.");
2460 			else
2461 				*lose = 1;
2462 			skip_to_semi (cfile);
2463 			executable_statement_dereference (result, MDL);
2464 			return 0;
2465 		}
2466 		if (!parse_semi (cfile)) {
2467 			*lose = 1;
2468 			executable_statement_dereference (result, MDL);
2469 		}
2470 		break;
2471 
2472 	      case EXECUTE:
2473 #ifdef ENABLE_EXECUTE
2474 		skip_token(&val, NULL, cfile);
2475 
2476 		if (!executable_statement_allocate (result, MDL))
2477 			log_fatal ("no memory for execute statement.");
2478 		(*result)->op = execute_statement;
2479 
2480 		token = next_token(&val, NULL, cfile);
2481 		if (token != LPAREN) {
2482 			parse_warn(cfile, "left parenthesis expected.");
2483 			skip_to_semi(cfile);
2484 			*lose = 1;
2485 			return 0;
2486 		}
2487 
2488 		token = next_token(&val, &len, cfile);
2489 		if (token != STRING) {
2490 			parse_warn(cfile, "Expecting a quoted string.");
2491 			skip_to_semi(cfile);
2492 			*lose = 1;
2493 			return 0;
2494 		}
2495 
2496 		(*result)->data.execute.command = dmalloc(len + 1, MDL);
2497 		if ((*result)->data.execute.command == NULL)
2498 			log_fatal("can't allocate command name");
2499 		strcpy((*result)->data.execute.command, val);
2500 
2501 		ep = &(*result)->data.execute.arglist;
2502 		(*result)->data.execute.argc = 0;
2503 
2504 		while((token = next_token(&val, NULL, cfile)) == COMMA) {
2505 			if (!expression_allocate(ep, MDL))
2506 				log_fatal ("can't allocate expression");
2507 
2508  			if (!parse_data_expression (&(*ep) -> data.arg.val,
2509  					       cfile, lose)) {
2510 				if (!*lose) {
2511 					parse_warn (cfile,
2512 						    "expecting expression.");
2513 					*lose = 1;
2514 				}
2515 				skip_to_semi(cfile);
2516 				*lose = 1;
2517 				return 0;
2518 			}
2519 			ep = &(*ep)->data.arg.next;
2520 			(*result)->data.execute.argc++;
2521 		}
2522 
2523 		if (token != RPAREN) {
2524 			parse_warn(cfile, "right parenthesis expected.");
2525 			skip_to_semi(cfile);
2526 			*lose = 1;
2527 			return 0;
2528 		}
2529 
2530 		if (!parse_semi (cfile)) {
2531 			*lose = 1;
2532 			executable_statement_dereference (result, MDL);
2533 		}
2534 #else /* ! ENABLE_EXECUTE */
2535 		parse_warn(cfile, "define ENABLE_EXECUTE in site.h to "
2536 				  "enable execute(); expressions.");
2537 		skip_to_semi(cfile);
2538 		*lose = 1;
2539 		return 0;
2540 #endif /* ENABLE_EXECUTE */
2541 		break;
2542 
2543 	      case RETURN:
2544 		skip_token(&val, (unsigned *)0, cfile);
2545 
2546 		if (!executable_statement_allocate (result, MDL))
2547 			log_fatal ("no memory for return statement.");
2548 		(*result) -> op = return_statement;
2549 
2550 		if (!parse_expression (&(*result) -> data.retval,
2551 				       cfile, lose, context_data,
2552 				       (struct expression **)0, expr_none)) {
2553 			if (!*lose)
2554 				parse_warn (cfile,
2555 					    "expecting data expression.");
2556 			else
2557 				*lose = 1;
2558 			skip_to_semi (cfile);
2559 			executable_statement_dereference (result, MDL);
2560 			return 0;
2561 		}
2562 		if (!parse_semi (cfile)) {
2563 			*lose = 1;
2564 			executable_statement_dereference (result, MDL);
2565 			return 0;
2566 		}
2567 		break;
2568 
2569 	      case LOG:
2570 		skip_token(&val, (unsigned *)0, cfile);
2571 
2572 		if (!executable_statement_allocate (result, MDL))
2573 			log_fatal ("no memory for log statement.");
2574 		(*result) -> op = log_statement;
2575 
2576 		token = next_token (&val, (unsigned *)0, cfile);
2577 		if (token != LPAREN) {
2578 			parse_warn (cfile, "left parenthesis expected.");
2579 			skip_to_semi (cfile);
2580 			*lose = 1;
2581 			return 0;
2582 		}
2583 
2584 		token = peek_token (&val, (unsigned *)0, cfile);
2585 		i = 1;
2586 		if (token == FATAL) {
2587 			(*result) -> data.log.priority = log_priority_fatal;
2588 		} else if (token == ERROR) {
2589 			(*result) -> data.log.priority = log_priority_error;
2590 		} else if (token == TOKEN_DEBUG) {
2591 			(*result) -> data.log.priority = log_priority_debug;
2592 		} else if (token == INFO) {
2593 			(*result) -> data.log.priority = log_priority_info;
2594 		} else {
2595 			(*result) -> data.log.priority = log_priority_debug;
2596 			i = 0;
2597 		}
2598 		if (i) {
2599 			skip_token(&val, (unsigned *)0, cfile);
2600 			token = next_token (&val, (unsigned *)0, cfile);
2601 			if (token != COMMA) {
2602 				parse_warn (cfile, "comma expected.");
2603 				skip_to_semi (cfile);
2604 				*lose = 1;
2605 				return 0;
2606 			}
2607 		}
2608 
2609 		if (!(parse_data_expression
2610 		      (&(*result) -> data.log.expr, cfile, lose))) {
2611 			skip_to_semi (cfile);
2612 			*lose = 1;
2613 			return 0;
2614 		}
2615 
2616 		token = next_token (&val, (unsigned *)0, cfile);
2617 		if (token != RPAREN) {
2618 			parse_warn (cfile, "right parenthesis expected.");
2619 			skip_to_semi (cfile);
2620 			*lose = 1;
2621 			return 0;
2622 		}
2623 
2624 		token = next_token (&val, (unsigned *)0, cfile);
2625 		if (token != SEMI) {
2626 			parse_warn (cfile, "semicolon expected.");
2627 			skip_to_semi (cfile);
2628 			*lose = 1;
2629 			return 0;
2630 		}
2631 		break;
2632 
2633 		/* Not really a statement, but we parse it here anyway
2634 		   because it's appropriate for all DHCP agents with
2635 		   parsers. */
2636 	      case ZONE:
2637 		skip_token(&val, (unsigned *)0, cfile);
2638 		zone = (struct dns_zone *)0;
2639 		if (!dns_zone_allocate (&zone, MDL))
2640 			log_fatal ("no memory for new zone.");
2641 		zone -> name = parse_host_name (cfile);
2642 		if (!zone -> name) {
2643 			parse_warn (cfile, "expecting hostname.");
2644 		      badzone:
2645 			*lose = 1;
2646 			skip_to_semi (cfile);
2647 			dns_zone_dereference (&zone, MDL);
2648 			return 0;
2649 		}
2650 		i = strlen (zone -> name);
2651 		if (zone -> name [i - 1] != '.') {
2652 			s = dmalloc ((unsigned)i + 2, MDL);
2653 			if (!s) {
2654 				parse_warn (cfile, "no trailing '.' on zone");
2655 				goto badzone;
2656 			}
2657 			strcpy (s, zone -> name);
2658 			s [i] = '.';
2659 			s [i + 1] = 0;
2660 			dfree (zone -> name, MDL);
2661 			zone -> name = s;
2662 		}
2663 		if (!parse_zone (zone, cfile))
2664 			goto badzone;
2665 		status = enter_dns_zone (zone);
2666 		if (status != ISC_R_SUCCESS) {
2667 			parse_warn (cfile, "dns zone key %s: %s",
2668 				    zone -> name, isc_result_totext (status));
2669 			dns_zone_dereference (&zone, MDL);
2670 			return 0;
2671 		}
2672 		dns_zone_dereference (&zone, MDL);
2673 		return 1;
2674 
2675 		/* Also not really a statement, but same idea as above. */
2676 	      case KEY:
2677 		skip_token(&val, (unsigned *)0, cfile);
2678 		if (!parse_key (cfile)) {
2679 			*lose = 1;
2680 			return 0;
2681 		}
2682 		return 1;
2683 
2684 	      default:
2685 		if (config_universe && is_identifier (token)) {
2686 			option = (struct option *)0;
2687 			option_name_hash_lookup(&option,
2688 						config_universe->name_hash,
2689 						val, 0, MDL);
2690 			if (option) {
2691 				skip_token(&val, (unsigned *)0, cfile);
2692 				status = parse_option_statement
2693 						(result, cfile, 1, option,
2694 						 supersede_option_statement);
2695 				option_dereference(&option, MDL);
2696 				return status;
2697 			}
2698 		}
2699 
2700 		if (token == NUMBER_OR_NAME || token == NAME) {
2701 			/* This is rather ugly.  Since function calls are
2702 			   data expressions, fake up an eval statement. */
2703 			if (!executable_statement_allocate (result, MDL))
2704 				log_fatal ("no memory for eval statement.");
2705 			(*result) -> op = eval_statement;
2706 
2707 			if (!parse_expression (&(*result) -> data.eval,
2708 					       cfile, lose, context_data,
2709 					       (struct expression **)0,
2710 					       expr_none)) {
2711 				if (!*lose)
2712 					parse_warn (cfile, "expecting "
2713 						    "function call.");
2714 				else
2715 					*lose = 1;
2716 				skip_to_semi (cfile);
2717 				executable_statement_dereference (result, MDL);
2718 				return 0;
2719 			}
2720 			if (!parse_semi (cfile)) {
2721 				*lose = 1;
2722 				executable_statement_dereference (result, MDL);
2723 				return 0;
2724 			}
2725 			break;
2726 		}
2727 
2728 		*lose = 0;
2729 		return 0;
2730 	}
2731 
2732 	return 1;
2733 }
2734 
2735 /* zone-statements :== zone-statement |
2736 		       zone-statement zone-statements
2737    zone-statement :==
2738 	PRIMARY ip-addresses SEMI |
2739 	SECONDARY ip-addresses SEMI |
2740 	PRIMARY6 ip-address6 SEMI |
2741 	SECONDARY6 ip-address6 SEMI |
2742 	key-reference SEMI
2743    ip-addresses :== ip-addr-or-hostname |
2744 		  ip-addr-or-hostname COMMA ip-addresses
2745    key-reference :== KEY STRING |
2746 		    KEY identifier */
2747 
2748 int parse_zone (struct dns_zone *zone, struct parse *cfile)
2749 {
2750 	int token;
2751 	const char *val;
2752 	char *key_name;
2753 	struct option_cache *oc;
2754 	int done = 0;
2755 
2756 	token = next_token (&val, (unsigned *)0, cfile);
2757 	if (token != LBRACE) {
2758 		parse_warn (cfile, "expecting left brace");
2759 		return 0;
2760 	}
2761 
2762 	do {
2763 	    token = peek_token (&val, (unsigned *)0, cfile);
2764 	    switch (token) {
2765 		  case PRIMARY:
2766 		    if (zone -> primary) {
2767 			    parse_warn (cfile,
2768 					"more than one primary.");
2769 			    skip_to_semi (cfile);
2770 			    return 0;
2771 		    }
2772 		    if (!option_cache_allocate (&zone -> primary, MDL))
2773 			    log_fatal ("can't allocate primary option cache.");
2774 		    oc = zone -> primary;
2775 		    goto consemup;
2776 
2777 		  case SECONDARY:
2778 		    if (zone -> secondary) {
2779 			    parse_warn (cfile, "more than one secondary.");
2780 			skip_to_semi (cfile);
2781 			return 0;
2782 		    }
2783 		    if (!option_cache_allocate (&zone -> secondary, MDL))
2784 			    log_fatal ("can't allocate secondary.");
2785 		    oc = zone -> secondary;
2786 		  consemup:
2787 		    skip_token(&val, (unsigned *)0, cfile);
2788 		    do {
2789 			    struct expression *expr = (struct expression *)0;
2790 			    if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2791 				parse_warn (cfile,
2792 					    "expecting IP addr or hostname.");
2793 				skip_to_semi (cfile);
2794 				return 0;
2795 			    }
2796 			    if (oc -> expression) {
2797 				    struct expression *old =
2798 					    (struct expression *)0;
2799 				    expression_reference (&old,
2800 							  oc -> expression,
2801 							  MDL);
2802 				    expression_dereference (&oc -> expression,
2803 							    MDL);
2804 				    if (!make_concat (&oc -> expression,
2805 						      old, expr))
2806 					log_fatal ("no memory for concat.");
2807 				    expression_dereference (&expr, MDL);
2808 				    expression_dereference (&old, MDL);
2809 			    } else {
2810 				    expression_reference (&oc -> expression,
2811 							  expr, MDL);
2812 				    expression_dereference (&expr, MDL);
2813 			    }
2814 			    token = next_token (&val, (unsigned *)0, cfile);
2815 		    } while (token == COMMA);
2816 		    if (token != SEMI) {
2817 			    parse_warn (cfile, "expecting semicolon.");
2818 			    skip_to_semi (cfile);
2819 			    return 0;
2820 		    }
2821 		    break;
2822 
2823 	          case PRIMARY6:
2824 		    if (zone->primary6) {
2825 			    parse_warn(cfile, "more than one primary6.");
2826 			    skip_to_semi(cfile);
2827 			    return (0);
2828 		    }
2829 		    if (!option_cache_allocate (&zone->primary6, MDL))
2830 			    log_fatal("can't allocate primary6 option cache.");
2831 		    oc = zone->primary6;
2832 		    goto consemup6;
2833 
2834 	          case SECONDARY6:
2835 		    if (zone->secondary6) {
2836 			    parse_warn(cfile, "more than one secondary6.");
2837 			    skip_to_semi(cfile);
2838 			    return (0);
2839 		    }
2840 		    if (!option_cache_allocate (&zone->secondary6, MDL))
2841 			    log_fatal("can't allocate secondary6 "
2842 				      "option cache.");
2843 		    oc = zone->secondary6;
2844 	          consemup6:
2845 		    skip_token(&val, NULL, cfile);
2846 		    do {
2847 			    struct expression *expr = NULL;
2848 			    if (parse_ip6_addr_expr(&expr, cfile) == 0) {
2849 				    parse_warn(cfile, "expecting IPv6 addr.");
2850 				    skip_to_semi(cfile);
2851 				    return (0);
2852 			    }
2853 			    if (oc->expression) {
2854 				    struct expression *old = NULL;
2855 				    expression_reference(&old, oc->expression,
2856 							 MDL);
2857 				    expression_dereference(&oc->expression,
2858 							   MDL);
2859 				    if (!make_concat(&oc->expression,
2860 						     old, expr))
2861 					    log_fatal("no memory for concat.");
2862 				    expression_dereference(&expr, MDL);
2863 				    expression_dereference(&old, MDL);
2864 			    } else {
2865 				    expression_reference(&oc->expression,
2866 							 expr, MDL);
2867 				    expression_dereference(&expr, MDL);
2868 			    }
2869 			    token = next_token(&val, NULL, cfile);
2870 		    } while (token == COMMA);
2871 		    if (token != SEMI) {
2872 			    parse_warn(cfile, "expecting semicolon.");
2873 			    skip_to_semi(cfile);
2874 			    return (0);
2875 		    }
2876 		    break;
2877 
2878 		  case KEY:
2879 		    skip_token(&val, (unsigned *)0, cfile);
2880 		    token = peek_token (&val, (unsigned *)0, cfile);
2881 		    if (token == STRING) {
2882 			    skip_token(&val, (unsigned *)0, cfile);
2883 			    key_name = (char *)0;
2884 		    } else {
2885 			    key_name = parse_host_name (cfile);
2886 			    if (!key_name) {
2887 				    parse_warn (cfile, "expecting key name.");
2888 				    skip_to_semi (cfile);
2889 				    return 0;
2890 			    }
2891 			    val = key_name;
2892 		    }
2893 		    if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2894 			ISC_R_SUCCESS)
2895 			    parse_warn (cfile, "unknown key %s", val);
2896 		    if (key_name)
2897 			    dfree (key_name, MDL);
2898 		    if (!parse_semi (cfile))
2899 			    return 0;
2900 		    break;
2901 
2902 		  default:
2903 		    done = 1;
2904 		    break;
2905 	    }
2906 	} while (!done);
2907 
2908 	token = next_token (&val, (unsigned *)0, cfile);
2909 	if (token != RBRACE) {
2910 		parse_warn (cfile, "expecting right brace.");
2911 		return 0;
2912 	}
2913 	return 1;
2914 }
2915 
2916 /* key-statements :== key-statement |
2917 		      key-statement key-statements
2918    key-statement :==
2919 	ALGORITHM host-name SEMI |
2920 	secret-definition SEMI
2921    secret-definition :== SECRET base64val |
2922 			 SECRET STRING */
2923 
2924 int parse_key (struct parse *cfile)
2925 {
2926 	int token;
2927 	const char *val;
2928 	int done = 0;
2929 	struct auth_key *key;
2930 	struct data_string ds;
2931 	isc_result_t status;
2932 	char *s;
2933 
2934 	key = (struct auth_key *)0;
2935 	if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2936 		log_fatal ("no memory for key");
2937 
2938 	token = peek_token (&val, (unsigned *)0, cfile);
2939 	if (token == STRING) {
2940 		skip_token(&val, (unsigned *)0, cfile);
2941 		key -> name = dmalloc (strlen (val) + 1, MDL);
2942 		if (!key -> name)
2943 			log_fatal ("no memory for key name.");
2944 		strcpy (key -> name, val);
2945 
2946 	} else {
2947 		key -> name = parse_host_name (cfile);
2948 		if (!key -> name) {
2949 			parse_warn (cfile, "expecting key name.");
2950 			skip_to_semi (cfile);
2951 			goto bad;
2952 		}
2953 	}
2954 
2955 	token = next_token (&val, (unsigned *)0, cfile);
2956 	if (token != LBRACE) {
2957 		parse_warn (cfile, "expecting left brace");
2958 		goto bad;
2959 	}
2960 
2961 	do {
2962 		token = next_token (&val, (unsigned *)0, cfile);
2963 		switch (token) {
2964 		      case ALGORITHM:
2965 			if (key -> algorithm) {
2966 				parse_warn (cfile,
2967 					    "key %s: too many algorithms",
2968 					    key -> name);
2969 				goto rbad;
2970 			}
2971 			key -> algorithm = parse_host_name (cfile);
2972 			if (!key -> algorithm) {
2973 				parse_warn (cfile,
2974 					    "expecting key algorithm name.");
2975 				goto rbad;
2976 			}
2977 			if (!parse_semi (cfile))
2978 				goto rbad;
2979 			/* If the algorithm name isn't an FQDN, tack on
2980 			   the .SIG-ALG.REG.NET. domain. */
2981 			s = strrchr (key -> algorithm, '.');
2982 			if (!s) {
2983 			    static char add [] = ".SIG-ALG.REG.INT.";
2984 			    s = dmalloc (strlen (key -> algorithm) +
2985 					 sizeof (add), MDL);
2986 			    if (!s) {
2987 				log_error ("no memory for key %s.",
2988 					   "algorithm");
2989 				goto rbad;
2990 			    }
2991 			    strcpy (s, key -> algorithm);
2992 			    strcat (s, add);
2993 			    dfree (key -> algorithm, MDL);
2994 			    key -> algorithm = s;
2995 			} else if (s [1]) {
2996 			    /* If there is no trailing '.', hack one in. */
2997 			    s = dmalloc (strlen (key -> algorithm) + 2, MDL);
2998 			    if (!s) {
2999 				    log_error ("no memory for key %s.",
3000 					       key -> algorithm);
3001 				    goto rbad;
3002 			    }
3003 			    strcpy (s, key -> algorithm);
3004 			    strcat (s, ".");
3005 			    dfree (key -> algorithm, MDL);
3006 			    key -> algorithm = s;
3007 			}
3008 			break;
3009 
3010 		      case SECRET:
3011 			if (key -> key) {
3012 				parse_warn (cfile, "key %s: too many secrets",
3013 					    key -> name);
3014 				goto rbad;
3015 			}
3016 
3017 			memset (&ds, 0, sizeof(ds));
3018 			if (!parse_base64 (&ds, cfile))
3019 				goto rbad;
3020 			status = omapi_data_string_new (&key -> key, ds.len,
3021 							MDL);
3022 			if (status != ISC_R_SUCCESS)
3023 				goto rbad;
3024 			memcpy (key -> key -> value,
3025 				ds.buffer -> data, ds.len);
3026 			data_string_forget (&ds, MDL);
3027 
3028 			if (!parse_semi (cfile))
3029 				goto rbad;
3030 			break;
3031 
3032 		      default:
3033 			done = 1;
3034 			break;
3035 		}
3036 	} while (!done);
3037 	if (token != RBRACE) {
3038 		parse_warn (cfile, "expecting right brace.");
3039 		goto rbad;
3040 	}
3041 	/* Allow the BIND 8 syntax, which has a semicolon after each
3042 	   closing brace. */
3043 	token = peek_token (&val, (unsigned *)0, cfile);
3044 	if (token == SEMI) {
3045 		skip_token(&val, (unsigned *)0, cfile);
3046 	}
3047 
3048 	/* Remember the key. */
3049 	status = omapi_auth_key_enter (key);
3050 	if (status != ISC_R_SUCCESS) {
3051 		parse_warn (cfile, "tsig key %s: %s",
3052 			    key -> name, isc_result_totext (status));
3053 		goto bad;
3054 	}
3055 	omapi_auth_key_dereference (&key, MDL);
3056 	return 1;
3057 
3058       rbad:
3059 	skip_to_rbrace (cfile, 1);
3060       bad:
3061 	omapi_auth_key_dereference (&key, MDL);
3062 	return 0;
3063 }
3064 
3065 /*
3066  * on-statement :== event-types LBRACE executable-statements RBRACE
3067  * event-types :== event-type OR event-types |
3068  *		   event-type
3069  * event-type :== EXPIRY | COMMIT | RELEASE
3070  */
3071 
3072 int parse_on_statement (result, cfile, lose)
3073 	struct executable_statement **result;
3074 	struct parse *cfile;
3075 	int *lose;
3076 {
3077 	enum dhcp_token token;
3078 	const char *val;
3079 
3080 	if (!executable_statement_allocate (result, MDL))
3081 		log_fatal ("no memory for new statement.");
3082 	(*result) -> op = on_statement;
3083 
3084 	do {
3085 		token = next_token (&val, (unsigned *)0, cfile);
3086 		switch (token) {
3087 		      case EXPIRY:
3088 			(*result) -> data.on.evtypes |= ON_EXPIRY;
3089 			break;
3090 
3091 		      case COMMIT:
3092 			(*result) -> data.on.evtypes |= ON_COMMIT;
3093 			break;
3094 
3095 		      case RELEASE:
3096 			(*result) -> data.on.evtypes |= ON_RELEASE;
3097 			break;
3098 
3099 		      case TRANSMISSION:
3100 			(*result) -> data.on.evtypes |= ON_TRANSMISSION;
3101 			break;
3102 
3103 		      default:
3104 			parse_warn (cfile, "expecting a lease event type");
3105 			skip_to_semi (cfile);
3106 			*lose = 1;
3107 			executable_statement_dereference (result, MDL);
3108 			return 0;
3109 		}
3110 		token = next_token (&val, (unsigned *)0, cfile);
3111 	} while (token == OR);
3112 
3113 	/* Semicolon means no statements. */
3114 	if (token == SEMI)
3115 		return 1;
3116 
3117 	if (token != LBRACE) {
3118 		parse_warn (cfile, "left brace expected.");
3119 		skip_to_semi (cfile);
3120 		*lose = 1;
3121 		executable_statement_dereference (result, MDL);
3122 		return 0;
3123 	}
3124 	if (!parse_executable_statements (&(*result) -> data.on.statements,
3125 					  cfile, lose, context_any)) {
3126 		if (*lose) {
3127 			/* Try to even things up. */
3128 			do {
3129 				token = next_token (&val,
3130 						    (unsigned *)0, cfile);
3131 			} while (token != END_OF_FILE && token != RBRACE);
3132 			executable_statement_dereference (result, MDL);
3133 			return 0;
3134 		}
3135 	}
3136 	token = next_token (&val, (unsigned *)0, cfile);
3137 	if (token != RBRACE) {
3138 		parse_warn (cfile, "right brace expected.");
3139 		skip_to_semi (cfile);
3140 		*lose = 1;
3141 		executable_statement_dereference (result, MDL);
3142 		return 0;
3143 	}
3144 	return 1;
3145 }
3146 
3147 /*
3148  * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3149  *
3150  */
3151 
3152 int parse_switch_statement (result, cfile, lose)
3153 	struct executable_statement **result;
3154 	struct parse *cfile;
3155 	int *lose;
3156 {
3157 	enum dhcp_token token;
3158 	const char *val;
3159 
3160 	if (!executable_statement_allocate (result, MDL))
3161 		log_fatal ("no memory for new statement.");
3162 	(*result) -> op = switch_statement;
3163 
3164 	token = next_token (&val, (unsigned *)0, cfile);
3165 	if (token != LPAREN) {
3166 		parse_warn (cfile, "expecting left brace.");
3167 	      pfui:
3168 		*lose = 1;
3169 		skip_to_semi (cfile);
3170 	      gnorf:
3171 		executable_statement_dereference (result, MDL);
3172 		return 0;
3173 	}
3174 
3175 	if (!parse_expression (&(*result) -> data.s_switch.expr,
3176 			       cfile, lose, context_data_or_numeric,
3177 			       (struct expression **)0, expr_none)) {
3178 		if (!*lose) {
3179 			parse_warn (cfile,
3180 				    "expecting data or numeric expression.");
3181 			goto pfui;
3182 		}
3183 		goto gnorf;
3184 	}
3185 
3186 	token = next_token (&val, (unsigned *)0, cfile);
3187 	if (token != RPAREN) {
3188 		parse_warn (cfile, "right paren expected.");
3189 		goto pfui;
3190 	}
3191 
3192 	token = next_token (&val, (unsigned *)0, cfile);
3193 	if (token != LBRACE) {
3194 		parse_warn (cfile, "left brace expected.");
3195 		goto pfui;
3196 	}
3197 	if (!(parse_executable_statements
3198 	      (&(*result) -> data.s_switch.statements, cfile, lose,
3199 	       (is_data_expression ((*result) -> data.s_switch.expr)
3200 		? context_data : context_numeric)))) {
3201 		if (*lose) {
3202 			skip_to_rbrace (cfile, 1);
3203 			executable_statement_dereference (result, MDL);
3204 			return 0;
3205 		}
3206 	}
3207 	token = next_token (&val, (unsigned *)0, cfile);
3208 	if (token != RBRACE) {
3209 		parse_warn (cfile, "right brace expected.");
3210 		goto pfui;
3211 	}
3212 	return 1;
3213 }
3214 
3215 /*
3216  * case-statement :== CASE expr COLON
3217  *
3218  */
3219 
3220 int parse_case_statement (result, cfile, lose, case_context)
3221 	struct executable_statement **result;
3222 	struct parse *cfile;
3223 	int *lose;
3224 	enum expression_context case_context;
3225 {
3226 	enum dhcp_token token;
3227 	const char *val;
3228 
3229 	if (!executable_statement_allocate (result, MDL))
3230 		log_fatal ("no memory for new statement.");
3231 	(*result) -> op = case_statement;
3232 
3233 	if (!parse_expression (&(*result) -> data.c_case,
3234 			       cfile, lose, case_context,
3235 			       (struct expression **)0, expr_none))
3236 	{
3237 		if (!*lose) {
3238 			parse_warn (cfile, "expecting %s expression.",
3239 				    (case_context == context_data
3240 				     ? "data" : "numeric"));
3241 		}
3242 	      pfui:
3243 		*lose = 1;
3244 		skip_to_semi (cfile);
3245 		executable_statement_dereference (result, MDL);
3246 		return 0;
3247 	}
3248 
3249 	token = next_token (&val, (unsigned *)0, cfile);
3250 	if (token != COLON) {
3251 		parse_warn (cfile, "colon expected.");
3252 		goto pfui;
3253 	}
3254 	return 1;
3255 }
3256 
3257 /*
3258  * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3259  *						else-statement
3260  *
3261  * else-statement :== <null> |
3262  *		      ELSE LBRACE executable-statements RBRACE |
3263  *		      ELSE IF if-statement |
3264  *		      ELSIF if-statement
3265  */
3266 
3267 int parse_if_statement (result, cfile, lose)
3268 	struct executable_statement **result;
3269 	struct parse *cfile;
3270 	int *lose;
3271 {
3272 	enum dhcp_token token;
3273 	const char *val;
3274 	int parenp;
3275 
3276 	if (!executable_statement_allocate (result, MDL))
3277 		log_fatal ("no memory for if statement.");
3278 
3279 	(*result) -> op = if_statement;
3280 
3281 	token = peek_token (&val, (unsigned *)0, cfile);
3282 	if (token == LPAREN) {
3283 		parenp = 1;
3284 		skip_token(&val, (unsigned *)0, cfile);
3285 	} else
3286 		parenp = 0;
3287 
3288 
3289 	if (!parse_boolean_expression (&(*result) -> data.ie.expr,
3290 				       cfile, lose)) {
3291 		if (!*lose)
3292 			parse_warn (cfile, "boolean expression expected.");
3293 		executable_statement_dereference (result, MDL);
3294 		*lose = 1;
3295 		return 0;
3296 	}
3297 #if defined (DEBUG_EXPRESSION_PARSE)
3298 	print_expression ("if condition", (*result) -> data.ie.expr);
3299 #endif
3300 	if (parenp) {
3301 		token = next_token (&val, (unsigned *)0, cfile);
3302 		if (token != RPAREN) {
3303 			parse_warn (cfile, "expecting right paren.");
3304 			*lose = 1;
3305 			executable_statement_dereference (result, MDL);
3306 			return 0;
3307 		}
3308 	}
3309 	token = next_token (&val, (unsigned *)0, cfile);
3310 	if (token != LBRACE) {
3311 		parse_warn (cfile, "left brace expected.");
3312 		skip_to_semi (cfile);
3313 		*lose = 1;
3314 		executable_statement_dereference (result, MDL);
3315 		return 0;
3316 	}
3317 	if (!parse_executable_statements (&(*result) -> data.ie.tc,
3318 					  cfile, lose, context_any)) {
3319 		if (*lose) {
3320 			/* Try to even things up. */
3321 			do {
3322 				token = next_token (&val,
3323 						    (unsigned *)0, cfile);
3324 			} while (token != END_OF_FILE && token != RBRACE);
3325 			executable_statement_dereference (result, MDL);
3326 			return 0;
3327 		}
3328 	}
3329 	token = next_token (&val, (unsigned *)0, cfile);
3330 	if (token != RBRACE) {
3331 		parse_warn (cfile, "right brace expected.");
3332 		skip_to_semi (cfile);
3333 		*lose = 1;
3334 		executable_statement_dereference (result, MDL);
3335 		return 0;
3336 	}
3337 	token = peek_token (&val, (unsigned *)0, cfile);
3338 	if (token == ELSE) {
3339 		skip_token(&val, (unsigned *)0, cfile);
3340 		token = peek_token (&val, (unsigned *)0, cfile);
3341 		if (token == IF) {
3342 			skip_token(&val, (unsigned *)0, cfile);
3343 			if (!parse_if_statement (&(*result) -> data.ie.fc,
3344 						 cfile, lose)) {
3345 				if (!*lose)
3346 					parse_warn (cfile,
3347 						    "expecting if statement");
3348 				executable_statement_dereference (result, MDL);
3349 				*lose = 1;
3350 				return 0;
3351 			}
3352 		} else if (token != LBRACE) {
3353 			parse_warn (cfile, "left brace or if expected.");
3354 			skip_to_semi (cfile);
3355 			*lose = 1;
3356 			executable_statement_dereference (result, MDL);
3357 			return 0;
3358 		} else {
3359 			skip_token(&val, (unsigned *)0, cfile);
3360 			if (!(parse_executable_statements
3361 			      (&(*result) -> data.ie.fc,
3362 			       cfile, lose, context_any))) {
3363 				executable_statement_dereference (result, MDL);
3364 				return 0;
3365 			}
3366 			token = next_token (&val, (unsigned *)0, cfile);
3367 			if (token != RBRACE) {
3368 				parse_warn (cfile, "right brace expected.");
3369 				skip_to_semi (cfile);
3370 				*lose = 1;
3371 				executable_statement_dereference (result, MDL);
3372 				return 0;
3373 			}
3374 		}
3375 	} else if (token == ELSIF) {
3376 		skip_token(&val, (unsigned *)0, cfile);
3377 		if (!parse_if_statement (&(*result) -> data.ie.fc,
3378 					 cfile, lose)) {
3379 			if (!*lose)
3380 				parse_warn (cfile,
3381 					    "expecting conditional.");
3382 			executable_statement_dereference (result, MDL);
3383 			*lose = 1;
3384 			return 0;
3385 		}
3386 	} else
3387 		(*result) -> data.ie.fc = (struct executable_statement *)0;
3388 
3389 	return 1;
3390 }
3391 
3392 /*
3393  * boolean_expression :== CHECK STRING |
3394  *  			  NOT boolean-expression |
3395  *			  data-expression EQUAL data-expression |
3396  *			  data-expression BANG EQUAL data-expression |
3397  *			  data-expression REGEX_MATCH data-expression |
3398  *			  boolean-expression AND boolean-expression |
3399  *			  boolean-expression OR boolean-expression
3400  *			  EXISTS OPTION-NAME
3401  */
3402 
3403 int parse_boolean_expression (expr, cfile, lose)
3404 	struct expression **expr;
3405 	struct parse *cfile;
3406 	int *lose;
3407 {
3408 	/* Parse an expression... */
3409 	if (!parse_expression (expr, cfile, lose, context_boolean,
3410 			       (struct expression **)0, expr_none))
3411 		return 0;
3412 
3413 	if (!is_boolean_expression (*expr) &&
3414 	    (*expr) -> op != expr_variable_reference &&
3415 	    (*expr) -> op != expr_funcall) {
3416 		parse_warn (cfile, "Expecting a boolean expression.");
3417 		*lose = 1;
3418 		expression_dereference (expr, MDL);
3419 		return 0;
3420 	}
3421 	return 1;
3422 }
3423 
3424 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3425 
3426 int parse_boolean (cfile)
3427 	struct parse *cfile;
3428 {
3429 	const char *val;
3430 	int rv;
3431 
3432         (void)next_token(&val, NULL, cfile);
3433 	if (!strcasecmp (val, "true")
3434 	    || !strcasecmp (val, "on"))
3435 		rv = 1;
3436 	else if (!strcasecmp (val, "false")
3437 		 || !strcasecmp (val, "off"))
3438 		rv = 0;
3439 	else {
3440 		parse_warn (cfile,
3441 			    "boolean value (true/false/on/off) expected");
3442 		skip_to_semi (cfile);
3443 		return 0;
3444 	}
3445 	parse_semi (cfile);
3446 	return rv;
3447 }
3448 
3449 
3450 /*
3451  * data_expression :== SUBSTRING LPAREN data-expression COMMA
3452  *					numeric-expression COMMA
3453  *					numeric-expression RPAREN |
3454  *		       CONCAT LPAREN data-expression COMMA
3455  *					data-expression RPAREN
3456  *		       SUFFIX LPAREN data_expression COMMA
3457  *		       		     numeric-expression RPAREN |
3458  *		       LCASE LPAREN data_expression RPAREN |
3459  *		       UCASE LPAREN data_expression RPAREN |
3460  *		       OPTION option_name |
3461  *		       HARDWARE |
3462  *		       PACKET LPAREN numeric-expression COMMA
3463  *				     numeric-expression RPAREN |
3464  *		       V6RELAY LPAREN numeric-expression COMMA
3465  *				      data-expression RPAREN |
3466  *		       STRING |
3467  *		       colon_separated_hex_list
3468  */
3469 
3470 int parse_data_expression (expr, cfile, lose)
3471 	struct expression **expr;
3472 	struct parse *cfile;
3473 	int *lose;
3474 {
3475 	/* Parse an expression... */
3476 	if (!parse_expression (expr, cfile, lose, context_data,
3477 			       (struct expression **)0, expr_none))
3478 		return 0;
3479 
3480 	if (!is_data_expression (*expr) &&
3481 	    (*expr) -> op != expr_variable_reference &&
3482 	    (*expr) -> op != expr_funcall) {
3483 		expression_dereference (expr, MDL);
3484 		parse_warn (cfile, "Expecting a data expression.");
3485 		*lose = 1;
3486 		return 0;
3487 	}
3488 	return 1;
3489 }
3490 
3491 /*
3492  * numeric-expression :== EXTRACT_INT LPAREN data-expression
3493  *					     COMMA number RPAREN |
3494  *			  NUMBER
3495  */
3496 
3497 int parse_numeric_expression (expr, cfile, lose)
3498 	struct expression **expr;
3499 	struct parse *cfile;
3500 	int *lose;
3501 {
3502 	/* Parse an expression... */
3503 	if (!parse_expression (expr, cfile, lose, context_numeric,
3504 			       (struct expression **)0, expr_none))
3505 		return 0;
3506 
3507 	if (!is_numeric_expression (*expr) &&
3508 	    (*expr) -> op != expr_variable_reference &&
3509 	    (*expr) -> op != expr_funcall) {
3510 		expression_dereference (expr, MDL);
3511 		parse_warn (cfile, "Expecting a numeric expression.");
3512 		*lose = 1;
3513 		return 0;
3514 	}
3515 	return 1;
3516 }
3517 
3518 /* Parse a subexpression that does not contain a binary operator. */
3519 
3520 int parse_non_binary (expr, cfile, lose, context)
3521 	struct expression **expr;
3522 	struct parse *cfile;
3523 	int *lose;
3524 	enum expression_context context;
3525 {
3526 	enum dhcp_token token;
3527 	const char *val;
3528 	struct collection *col;
3529 	struct expression *nexp, **ep;
3530 	int known;
3531 	char *cptr;
3532 	isc_result_t status;
3533 	unsigned len;
3534 
3535 	token = peek_token (&val, (unsigned *)0, cfile);
3536 
3537 	/* Check for unary operators... */
3538 	switch (token) {
3539 	      case CHECK:
3540 		skip_token(&val, (unsigned *)0, cfile);
3541 		token = next_token (&val, (unsigned *)0, cfile);
3542 		if (token != STRING) {
3543 			parse_warn (cfile, "string expected.");
3544 			skip_to_semi (cfile);
3545 			*lose = 1;
3546 			return 0;
3547 		}
3548 		for (col = collections; col; col = col -> next)
3549 			if (!strcmp (col -> name, val))
3550 				break;
3551 		if (!col) {
3552 			parse_warn (cfile, "unknown collection.");
3553 			*lose = 1;
3554 			return 0;
3555 		}
3556 		if (!expression_allocate (expr, MDL))
3557 			log_fatal ("can't allocate expression");
3558 		(*expr) -> op = expr_check;
3559 		(*expr) -> data.check = col;
3560 		break;
3561 
3562 	      case TOKEN_NOT:
3563 		skip_token(&val, NULL, cfile);
3564 		if (!expression_allocate (expr, MDL))
3565 			log_fatal ("can't allocate expression");
3566 		(*expr)->op = expr_not;
3567 		if (!parse_non_binary (&(*expr)->data.not,
3568 				       cfile, lose, context_boolean)) {
3569 			if (!*lose) {
3570 				parse_warn (cfile, "expression expected");
3571 				skip_to_semi (cfile);
3572 			}
3573 			*lose = 1;
3574 			expression_dereference (expr, MDL);
3575 			return (0);
3576 		}
3577 		if (!is_boolean_expression ((*expr) -> data.not)) {
3578 			*lose = 1;
3579 			parse_warn (cfile, "boolean expression expected");
3580 			skip_to_semi (cfile);
3581 			expression_dereference (expr, MDL);
3582 			return 0;
3583 		}
3584 		break;
3585 
3586 	      case LPAREN:
3587 		skip_token(&val, (unsigned *)0, cfile);
3588 		if (!parse_expression (expr, cfile, lose, context,
3589 				       (struct expression **)0, expr_none)) {
3590 			if (!*lose) {
3591 				parse_warn (cfile, "expression expected");
3592 				skip_to_semi (cfile);
3593 			}
3594 			*lose = 1;
3595 			return 0;
3596 		}
3597 		token = next_token (&val, (unsigned *)0, cfile);
3598 		if (token != RPAREN) {
3599 			*lose = 1;
3600 			parse_warn (cfile, "right paren expected");
3601 			skip_to_semi (cfile);
3602 			return 0;
3603 		}
3604 		break;
3605 
3606 	      case EXISTS:
3607 		skip_token(&val, NULL, cfile);
3608 		if (!expression_allocate (expr, MDL))
3609 			log_fatal ("can't allocate expression");
3610 		(*expr)->op = expr_exists;
3611 		known = 0;
3612 		/* Pass reference directly to expression structure. */
3613 		status = parse_option_name(cfile, 0, &known,
3614 					   &(*expr)->data.option);
3615 		if (status != ISC_R_SUCCESS ||
3616 		    (*expr)->data.option == NULL) {
3617 			*lose = 1;
3618 			expression_dereference (expr, MDL);
3619 			return (0);
3620 		}
3621 		break;
3622 
3623 	      case STATIC:
3624 		skip_token(&val, (unsigned *)0, cfile);
3625 		if (!expression_allocate (expr, MDL))
3626 			log_fatal ("can't allocate expression");
3627 		(*expr) -> op = expr_static;
3628 		break;
3629 
3630 	      case KNOWN:
3631 		skip_token(&val, (unsigned *)0, cfile);
3632 		if (!expression_allocate (expr, MDL))
3633 			log_fatal ("can't allocate expression");
3634 		(*expr) -> op = expr_known;
3635 		break;
3636 
3637 	      case SUBSTRING:
3638 		skip_token(&val, (unsigned *)0, cfile);
3639 		if (!expression_allocate (expr, MDL))
3640 			log_fatal ("can't allocate expression");
3641 		(*expr) -> op = expr_substring;
3642 
3643 		token = next_token (&val, (unsigned *)0, cfile);
3644 		if (token != LPAREN) {
3645 		      nolparen:
3646 			expression_dereference (expr, MDL);
3647 			parse_warn (cfile, "left parenthesis expected.");
3648 			*lose = 1;
3649 			return 0;
3650 		}
3651 
3652 		if (!parse_data_expression (&(*expr) -> data.substring.expr,
3653 					    cfile, lose)) {
3654 		      nodata:
3655 			expression_dereference (expr, MDL);
3656 			if (!*lose) {
3657 				parse_warn (cfile,
3658 					    "expecting data expression.");
3659 				skip_to_semi (cfile);
3660 				*lose = 1;
3661 			}
3662 			return 0;
3663 		}
3664 
3665 		token = next_token (&val, (unsigned *)0, cfile);
3666 		if (token != COMMA) {
3667 		      nocomma:
3668 			expression_dereference (expr, MDL);
3669 			parse_warn (cfile, "comma expected.");
3670 			*lose = 1;
3671 
3672 			return 0;
3673 		}
3674 
3675 		if (!parse_numeric_expression
3676 		    (&(*expr) -> data.substring.offset,cfile, lose)) {
3677 		      nonum:
3678 			if (!*lose) {
3679 				parse_warn (cfile,
3680 					    "expecting numeric expression.");
3681 				skip_to_semi (cfile);
3682 				*lose = 1;
3683 			}
3684 			expression_dereference (expr, MDL);
3685 			return 0;
3686 		}
3687 
3688 		token = next_token (&val, (unsigned *)0, cfile);
3689 		if (token != COMMA)
3690 			goto nocomma;
3691 
3692 		if (!parse_numeric_expression
3693 		    (&(*expr) -> data.substring.len, cfile, lose))
3694 			goto nonum;
3695 
3696 		token = next_token (&val, (unsigned *)0, cfile);
3697 		if (token != RPAREN) {
3698 		      norparen:
3699 			parse_warn (cfile, "right parenthesis expected.");
3700 			*lose = 1;
3701 			expression_dereference (expr, MDL);
3702 			return 0;
3703 		}
3704 		break;
3705 
3706 	      case SUFFIX:
3707 		skip_token(&val, (unsigned *)0, cfile);
3708 		if (!expression_allocate (expr, MDL))
3709 			log_fatal ("can't allocate expression");
3710 		(*expr) -> op = expr_suffix;
3711 
3712 		token = next_token (&val, (unsigned *)0, cfile);
3713 		if (token != LPAREN)
3714 			goto nolparen;
3715 
3716 		if (!parse_data_expression (&(*expr) -> data.suffix.expr,
3717 					    cfile, lose))
3718 			goto nodata;
3719 
3720 		token = next_token (&val, (unsigned *)0, cfile);
3721 		if (token != COMMA)
3722 			goto nocomma;
3723 
3724 		if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
3725 					       cfile, lose))
3726 			goto nonum;
3727 
3728 		token = next_token (&val, (unsigned *)0, cfile);
3729 		if (token != RPAREN)
3730 			goto norparen;
3731 		break;
3732 
3733 	      case LCASE:
3734 		skip_token(&val, (unsigned *)0, cfile);
3735 		if (!expression_allocate(expr, MDL))
3736 			log_fatal ("can't allocate expression");
3737 		(*expr)->op = expr_lcase;
3738 
3739 		token = next_token(&val, (unsigned *)0, cfile);
3740 		if (token != LPAREN)
3741 			goto nolparen;
3742 
3743 		if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
3744 			goto nodata;
3745 
3746 		token = next_token(&val, (unsigned *)0, cfile);
3747 		if (token != RPAREN)
3748 			goto norparen;
3749 		break;
3750 
3751 	      case UCASE:
3752 		skip_token(&val, (unsigned *)0, cfile);
3753 		if (!expression_allocate(expr, MDL))
3754 			log_fatal ("can't allocate expression");
3755 		(*expr)->op = expr_ucase;
3756 
3757 		token = next_token (&val, (unsigned *)0, cfile);
3758 		if (token != LPAREN)
3759 			goto nolparen;
3760 
3761 		if (!parse_data_expression(&(*expr)->data.ucase,
3762 					   cfile, lose))
3763 			goto nodata;
3764 
3765 		token = next_token(&val, (unsigned *)0, cfile);
3766 		if (token != RPAREN)
3767 			goto norparen;
3768 		break;
3769 
3770 	      case CONCAT:
3771 		skip_token(&val, (unsigned *)0, cfile);
3772 		if (!expression_allocate (expr, MDL))
3773 			log_fatal ("can't allocate expression");
3774 		(*expr) -> op = expr_concat;
3775 
3776 		token = next_token (&val, (unsigned *)0, cfile);
3777 		if (token != LPAREN)
3778 			goto nolparen;
3779 
3780 		if (!parse_data_expression (&(*expr) -> data.concat [0],
3781 					    cfile, lose))
3782 			goto nodata;
3783 
3784 		token = next_token (&val, (unsigned *)0, cfile);
3785 		if (token != COMMA)
3786 			goto nocomma;
3787 
3788 	      concat_another:
3789 		if (!parse_data_expression (&(*expr) -> data.concat [1],
3790 					    cfile, lose))
3791 			goto nodata;
3792 
3793 		token = next_token (&val, (unsigned *)0, cfile);
3794 
3795 		if (token == COMMA) {
3796 			nexp = (struct expression *)0;
3797 			if (!expression_allocate (&nexp, MDL))
3798 				log_fatal ("can't allocate at CONCAT2");
3799 			nexp -> op = expr_concat;
3800 			expression_reference (&nexp -> data.concat [0],
3801 					      *expr, MDL);
3802 			expression_dereference (expr, MDL);
3803 			expression_reference (expr, nexp, MDL);
3804 			expression_dereference (&nexp, MDL);
3805 			goto concat_another;
3806 		}
3807 
3808 		if (token != RPAREN)
3809 			goto norparen;
3810 		break;
3811 
3812 	      case BINARY_TO_ASCII:
3813 		skip_token(&val, (unsigned *)0, cfile);
3814 		if (!expression_allocate (expr, MDL))
3815 			log_fatal ("can't allocate expression");
3816 		(*expr) -> op = expr_binary_to_ascii;
3817 
3818 		token = next_token (&val, (unsigned *)0, cfile);
3819 		if (token != LPAREN)
3820 			goto nolparen;
3821 
3822 		if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3823 					       cfile, lose))
3824 			goto nodata;
3825 
3826 		token = next_token (&val, (unsigned *)0, cfile);
3827 		if (token != COMMA)
3828 			goto nocomma;
3829 
3830 		if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3831 					       cfile, lose))
3832 			goto nodata;
3833 
3834 		token = next_token (&val, (unsigned *)0, cfile);
3835 		if (token != COMMA)
3836 			goto nocomma;
3837 
3838 		if (!parse_data_expression (&(*expr) -> data.b2a.separator,
3839 					    cfile, lose))
3840 			goto nodata;
3841 
3842 		token = next_token (&val, (unsigned *)0, cfile);
3843 		if (token != COMMA)
3844 			goto nocomma;
3845 
3846 		if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3847 					    cfile, lose))
3848 			goto nodata;
3849 
3850 		token = next_token (&val, (unsigned *)0, cfile);
3851 		if (token != RPAREN)
3852 			goto norparen;
3853 		break;
3854 
3855 	      case REVERSE:
3856 		skip_token(&val, (unsigned *)0, cfile);
3857 		if (!expression_allocate (expr, MDL))
3858 			log_fatal ("can't allocate expression");
3859 		(*expr) -> op = expr_reverse;
3860 
3861 		token = next_token (&val, (unsigned *)0, cfile);
3862 		if (token != LPAREN)
3863 			goto nolparen;
3864 
3865 		if (!(parse_numeric_expression
3866 		      (&(*expr) -> data.reverse.width, cfile, lose)))
3867 			goto nodata;
3868 
3869 		token = next_token (&val, (unsigned *)0, cfile);
3870 		if (token != COMMA)
3871 			goto nocomma;
3872 
3873 		if (!(parse_data_expression
3874 		      (&(*expr) -> data.reverse.buffer, cfile, lose)))
3875 			goto nodata;
3876 
3877 		token = next_token (&val, (unsigned *)0, cfile);
3878 		if (token != RPAREN)
3879 			goto norparen;
3880 		break;
3881 
3882 	      case PICK:
3883 		/* pick (a, b, c) actually produces an internal representation
3884 		   that looks like pick (a, pick (b, pick (c, nil))). */
3885 		skip_token(&val, (unsigned *)0, cfile);
3886 		if (!(expression_allocate (expr, MDL)))
3887 			log_fatal ("can't allocate expression");
3888 
3889 		token = next_token (&val, (unsigned *)0, cfile);
3890 		if (token != LPAREN)
3891 			goto nolparen;
3892 
3893 		nexp = (struct expression *)0;
3894 		expression_reference (&nexp, *expr, MDL);
3895 		do {
3896 		    nexp -> op = expr_pick_first_value;
3897 		    if (!(parse_data_expression
3898 			  (&nexp -> data.pick_first_value.car,
3899 			   cfile, lose)))
3900 			goto nodata;
3901 
3902 		    token = next_token (&val, (unsigned *)0, cfile);
3903 		    if (token == COMMA) {
3904 			struct expression *foo = (struct expression *)0;
3905 			if (!expression_allocate (&foo, MDL))
3906 			    log_fatal ("can't allocate expr");
3907 			expression_reference
3908 				(&nexp -> data.pick_first_value.cdr, foo, MDL);
3909 			expression_dereference (&nexp, MDL);
3910 			expression_reference (&nexp, foo, MDL);
3911 			expression_dereference (&foo, MDL);
3912 		    }
3913 		} while (token == COMMA);
3914 		expression_dereference (&nexp, MDL);
3915 
3916 		if (token != RPAREN)
3917 			goto norparen;
3918 		break;
3919 
3920 	      case OPTION:
3921 	      case CONFIG_OPTION:
3922 		if (!expression_allocate (expr, MDL))
3923 			log_fatal ("can't allocate expression");
3924 		(*expr) -> op = (token == OPTION
3925 				 ? expr_option
3926 				 : expr_config_option);
3927 		skip_token(&val, (unsigned *)0, cfile);
3928 		known = 0;
3929 		/* Pass reference directly to expression structure. */
3930 		status = parse_option_name(cfile, 0, &known,
3931 					   &(*expr)->data.option);
3932 		if (status != ISC_R_SUCCESS ||
3933 		    (*expr)->data.option == NULL) {
3934 			*lose = 1;
3935 			expression_dereference (expr, MDL);
3936 			return 0;
3937 		}
3938 		break;
3939 
3940 	      case HARDWARE:
3941 		skip_token(&val, (unsigned *)0, cfile);
3942 		if (!expression_allocate (expr, MDL))
3943 			log_fatal ("can't allocate expression");
3944 		(*expr) -> op = expr_hardware;
3945 		break;
3946 
3947 	      case LEASED_ADDRESS:
3948 		skip_token(&val, (unsigned *)0, cfile);
3949 		if (!expression_allocate (expr, MDL))
3950 			log_fatal ("can't allocate expression");
3951 		(*expr) -> op = expr_leased_address;
3952 		break;
3953 
3954 	      case CLIENT_STATE:
3955 		skip_token(&val, (unsigned *)0, cfile);
3956 		if (!expression_allocate (expr, MDL))
3957 			log_fatal ("can't allocate expression");
3958 		(*expr) -> op = expr_client_state;
3959 		break;
3960 
3961 	      case FILENAME:
3962 		skip_token(&val, (unsigned *)0, cfile);
3963 		if (!expression_allocate (expr, MDL))
3964 			log_fatal ("can't allocate expression");
3965 		(*expr) -> op = expr_filename;
3966 		break;
3967 
3968 	      case SERVER_NAME:
3969 		skip_token(&val, (unsigned *)0, cfile);
3970 		if (!expression_allocate (expr, MDL))
3971 			log_fatal ("can't allocate expression");
3972 		(*expr) -> op = expr_sname;
3973 		break;
3974 
3975 	      case LEASE_TIME:
3976 		skip_token(&val, (unsigned *)0, cfile);
3977 		if (!expression_allocate (expr, MDL))
3978 			log_fatal ("can't allocate expression");
3979 		(*expr) -> op = expr_lease_time;
3980 		break;
3981 
3982 	      case TOKEN_NULL:
3983 		skip_token(&val, (unsigned *)0, cfile);
3984 		if (!expression_allocate (expr, MDL))
3985 			log_fatal ("can't allocate expression");
3986 		(*expr) -> op = expr_null;
3987 		break;
3988 
3989 	      case HOST_DECL_NAME:
3990 		skip_token(&val, (unsigned *)0, cfile);
3991 		if (!expression_allocate (expr, MDL))
3992 			log_fatal ("can't allocate expression");
3993 		(*expr) -> op = expr_host_decl_name;
3994 		break;
3995 
3996 	      case PACKET:
3997 		skip_token(&val, (unsigned *)0, cfile);
3998 		if (!expression_allocate (expr, MDL))
3999 			log_fatal ("can't allocate expression");
4000 		(*expr) -> op = expr_packet;
4001 
4002 		token = next_token (&val, (unsigned *)0, cfile);
4003 		if (token != LPAREN)
4004 			goto nolparen;
4005 
4006 		if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
4007 					       cfile, lose))
4008 			goto nonum;
4009 
4010 		token = next_token (&val, (unsigned *)0, cfile);
4011 		if (token != COMMA)
4012 			goto nocomma;
4013 
4014 		if (!parse_numeric_expression (&(*expr) -> data.packet.len,
4015 					       cfile, lose))
4016 			goto nonum;
4017 
4018 		token = next_token (&val, (unsigned *)0, cfile);
4019 		if (token != RPAREN)
4020 			goto norparen;
4021 		break;
4022 
4023 	      case STRING:
4024 		skip_token(&val, &len, cfile);
4025 		if (!make_const_data (expr, (const unsigned char *)val,
4026 				      len, 1, 1, MDL))
4027 			log_fatal ("can't make constant string expression.");
4028 		break;
4029 
4030 	      case EXTRACT_INT:
4031 		skip_token(&val, (unsigned *)0, cfile);
4032 		token = next_token (&val, (unsigned *)0, cfile);
4033 		if (token != LPAREN) {
4034 			parse_warn (cfile, "left parenthesis expected.");
4035 			*lose = 1;
4036 			return 0;
4037 		}
4038 
4039 		if (!expression_allocate (expr, MDL))
4040 			log_fatal ("can't allocate expression");
4041 
4042 		if (!parse_data_expression (&(*expr) -> data.extract_int,
4043 					    cfile, lose)) {
4044 			if (!*lose) {
4045 				parse_warn (cfile,
4046 					    "expecting data expression.");
4047 				skip_to_semi (cfile);
4048 				*lose = 1;
4049 			}
4050 			expression_dereference (expr, MDL);
4051 			return 0;
4052 		}
4053 
4054 		token = next_token (&val, (unsigned *)0, cfile);
4055 		if (token != COMMA) {
4056 			parse_warn (cfile, "comma expected.");
4057 			*lose = 1;
4058 			expression_dereference (expr, MDL);
4059 			return 0;
4060 		}
4061 
4062 		token = next_token (&val, (unsigned *)0, cfile);
4063 		if (token != NUMBER) {
4064 			parse_warn (cfile, "number expected.");
4065 			*lose = 1;
4066 			expression_dereference (expr, MDL);
4067 			return 0;
4068 		}
4069 		switch (atoi (val)) {
4070 		      case 8:
4071 			(*expr) -> op = expr_extract_int8;
4072 			break;
4073 
4074 		      case 16:
4075 			(*expr) -> op = expr_extract_int16;
4076 			break;
4077 
4078 		      case 32:
4079 			(*expr) -> op = expr_extract_int32;
4080 			break;
4081 
4082 		      default:
4083 			parse_warn (cfile,
4084 				    "unsupported integer size %d", atoi (val));
4085 			*lose = 1;
4086 			skip_to_semi (cfile);
4087 			expression_dereference (expr, MDL);
4088 			return 0;
4089 		}
4090 
4091 		token = next_token (&val, (unsigned *)0, cfile);
4092 		if (token != RPAREN) {
4093 			parse_warn (cfile, "right parenthesis expected.");
4094 			*lose = 1;
4095 			expression_dereference (expr, MDL);
4096 			return 0;
4097 		}
4098 		break;
4099 
4100 	      case ENCODE_INT:
4101 		skip_token(&val, (unsigned *)0, cfile);
4102 		token = next_token (&val, (unsigned *)0, cfile);
4103 		if (token != LPAREN) {
4104 			parse_warn (cfile, "left parenthesis expected.");
4105 			*lose = 1;
4106 			return 0;
4107 		}
4108 
4109 		if (!expression_allocate (expr, MDL))
4110 			log_fatal ("can't allocate expression");
4111 
4112 		if (!parse_numeric_expression (&(*expr) -> data.encode_int,
4113 					       cfile, lose)) {
4114 			parse_warn (cfile, "expecting numeric expression.");
4115 			skip_to_semi (cfile);
4116 			*lose = 1;
4117 			expression_dereference (expr, MDL);
4118 			return 0;
4119 		}
4120 
4121 		token = next_token (&val, (unsigned *)0, cfile);
4122 		if (token != COMMA) {
4123 			parse_warn (cfile, "comma expected.");
4124 			*lose = 1;
4125 			expression_dereference (expr, MDL);
4126 			return 0;
4127 		}
4128 
4129 		token = next_token (&val, (unsigned *)0, cfile);
4130 		if (token != NUMBER) {
4131 			parse_warn (cfile, "number expected.");
4132 			*lose = 1;
4133 			expression_dereference (expr, MDL);
4134 			return 0;
4135 		}
4136 		switch (atoi (val)) {
4137 		      case 8:
4138 			(*expr) -> op = expr_encode_int8;
4139 			break;
4140 
4141 		      case 16:
4142 			(*expr) -> op = expr_encode_int16;
4143 			break;
4144 
4145 		      case 32:
4146 			(*expr) -> op = expr_encode_int32;
4147 			break;
4148 
4149 		      default:
4150 			parse_warn (cfile,
4151 				    "unsupported integer size %d", atoi (val));
4152 			*lose = 1;
4153 			skip_to_semi (cfile);
4154 			expression_dereference (expr, MDL);
4155 			return 0;
4156 		}
4157 
4158 		token = next_token (&val, (unsigned *)0, cfile);
4159 		if (token != RPAREN) {
4160 			parse_warn (cfile, "right parenthesis expected.");
4161 			*lose = 1;
4162 			expression_dereference (expr, MDL);
4163 			return 0;
4164 		}
4165 		break;
4166 
4167 	      case NUMBER:
4168 		/* If we're in a numeric context, this should just be a
4169 		   number, by itself. */
4170 		if (context == context_numeric ||
4171 		    context == context_data_or_numeric) {
4172 			skip_token(&val, (unsigned *)0, cfile);
4173 			if (!expression_allocate (expr, MDL))
4174 				log_fatal ("can't allocate expression");
4175 			(*expr) -> op = expr_const_int;
4176 			(*expr) -> data.const_int = atoi (val);
4177 			break;
4178 		}
4179 
4180 	      case NUMBER_OR_NAME:
4181 		if (!expression_allocate (expr, MDL))
4182 			log_fatal ("can't allocate expression");
4183 
4184 		(*expr) -> op = expr_const_data;
4185 		if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4186 			expression_dereference (expr, MDL);
4187 			return 0;
4188 		}
4189 		break;
4190 
4191 	      case NS_FORMERR:
4192 		known = FORMERR;
4193 		goto ns_const;
4194 	      ns_const:
4195 		skip_token(&val, (unsigned *)0, cfile);
4196 		if (!expression_allocate (expr, MDL))
4197 			log_fatal ("can't allocate expression");
4198 		(*expr) -> op = expr_const_int;
4199 		(*expr) -> data.const_int = known;
4200 		break;
4201 
4202 	      case NS_NOERROR:
4203 		known = ISC_R_SUCCESS;
4204 		goto ns_const;
4205 
4206 	      case NS_NOTAUTH:
4207 		known = DHCP_R_NOTAUTH;
4208 		goto ns_const;
4209 
4210 	      case NS_NOTIMP:
4211 		known = ISC_R_NOTIMPLEMENTED;
4212 		goto ns_const;
4213 
4214 	      case NS_NOTZONE:
4215 		known = DHCP_R_NOTZONE;
4216 		goto ns_const;
4217 
4218 	      case NS_NXDOMAIN:
4219 		known = DHCP_R_NXDOMAIN;
4220 		goto ns_const;
4221 
4222 	      case NS_NXRRSET:
4223 		known = DHCP_R_NXRRSET;
4224 		goto ns_const;
4225 
4226 	      case NS_REFUSED:
4227 		known = DHCP_R_REFUSED;
4228 		goto ns_const;
4229 
4230 	      case NS_SERVFAIL:
4231 		known = DHCP_R_SERVFAIL;
4232 		goto ns_const;
4233 
4234 	      case NS_YXDOMAIN:
4235 		known = DHCP_R_YXDOMAIN;
4236 		goto ns_const;
4237 
4238 	      case NS_YXRRSET:
4239 		known = DHCP_R_YXRRSET;
4240 		goto ns_const;
4241 
4242 	      case BOOTING:
4243 		known = S_INIT;
4244 		goto ns_const;
4245 
4246 	      case REBOOT:
4247 		known = S_REBOOTING;
4248 		goto ns_const;
4249 
4250 	      case SELECT:
4251 		known = S_SELECTING;
4252 		goto ns_const;
4253 
4254 	      case REQUEST:
4255 		known = S_REQUESTING;
4256 		goto ns_const;
4257 
4258 	      case BOUND:
4259 		known = S_BOUND;
4260 		goto ns_const;
4261 
4262 	      case RENEW:
4263 		known = S_RENEWING;
4264 		goto ns_const;
4265 
4266 	      case REBIND:
4267 		known = S_REBINDING;
4268 		goto ns_const;
4269 
4270 	      case DEFINED:
4271 		skip_token(&val, (unsigned *)0, cfile);
4272 		token = next_token (&val, (unsigned *)0, cfile);
4273 		if (token != LPAREN)
4274 			goto nolparen;
4275 
4276 		token = next_token (&val, (unsigned *)0, cfile);
4277 		if (token != NAME && token != NUMBER_OR_NAME) {
4278 			parse_warn (cfile, "%s can't be a variable name", val);
4279 			skip_to_semi (cfile);
4280 			*lose = 1;
4281 			return 0;
4282 		}
4283 
4284 		if (!expression_allocate (expr, MDL))
4285 			log_fatal ("can't allocate expression");
4286 		(*expr) -> op = expr_variable_exists;
4287 		(*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
4288 		if (!(*expr)->data.variable)
4289 			log_fatal ("can't allocate variable name");
4290 		strcpy ((*expr) -> data.variable, val);
4291 		token = next_token (&val, (unsigned *)0, cfile);
4292 		if (token != RPAREN)
4293 			goto norparen;
4294 		break;
4295 
4296 		/* This parses 'gethostname()'. */
4297 	      case GETHOSTNAME:
4298 		skip_token(&val, NULL, cfile);
4299 		if (!expression_allocate(expr, MDL))
4300 			log_fatal("can't allocate expression");
4301 		(*expr)->op = expr_gethostname;
4302 
4303 		token = next_token(NULL, NULL, cfile);
4304 		if (token != LPAREN)
4305 			goto nolparen;
4306 
4307 		token = next_token(NULL, NULL, cfile);
4308 		if (token != RPAREN)
4309 			goto norparen;
4310 		break;
4311 
4312 	      case GETHOSTBYNAME:
4313 		skip_token(&val, NULL, cfile);
4314 		token = next_token(NULL, NULL, cfile);
4315 		if (token != LPAREN)
4316 			goto nolparen;
4317 
4318 		/* The argument is a quoted string. */
4319 		token = next_token(&val, NULL, cfile);
4320 		if (token != STRING) {
4321 			parse_warn(cfile, "Expecting quoted literal: "
4322 					  "\"foo.example.com\"");
4323 			skip_to_semi(cfile);
4324 			*lose = 1;
4325 			return 0;
4326 		}
4327 		if (!make_host_lookup(expr, val))
4328 			log_fatal("Error creating gethostbyname() internal "
4329 				  "record. (%s:%d)", MDL);
4330 
4331 		token = next_token(NULL, NULL, cfile);
4332 		if (token != RPAREN)
4333 			goto norparen;
4334 		break;
4335 
4336 	      case V6RELAY:
4337 		skip_token(&val, NULL, cfile);
4338 		if (!expression_allocate (expr, MDL))
4339 			log_fatal ("can't allocate expression");
4340 		(*expr)->op = expr_v6relay;
4341 
4342 		token = next_token (&val, NULL, cfile);
4343 		if (token != LPAREN)
4344 			goto nolparen;
4345 
4346 		if (!parse_numeric_expression (&(*expr)->data.v6relay.relay,
4347 						cfile, lose))
4348 			goto nodata;
4349 
4350 		token = next_token (&val, NULL, cfile);
4351 		if (token != COMMA)
4352 			goto nocomma;
4353 
4354 		if (!parse_data_expression (&(*expr)->data.v6relay.roption,
4355 					    cfile, lose))
4356 			goto nodata;
4357 
4358 		token = next_token (&val, NULL, cfile);
4359 
4360 		if (token != RPAREN)
4361 			goto norparen;
4362 		break;
4363 
4364 		/* Not a valid start to an expression... */
4365 	      default:
4366 		if (token != NAME && token != NUMBER_OR_NAME)
4367 			return 0;
4368 
4369 		skip_token(&val, (unsigned *)0, cfile);
4370 
4371 		/* Save the name of the variable being referenced. */
4372 		cptr = dmalloc (strlen (val) + 1, MDL);
4373 		if (!cptr)
4374 			log_fatal ("can't allocate variable name");
4375 		strcpy (cptr, val);
4376 
4377 		/* Simple variable reference, as far as we can tell. */
4378 		token = peek_token (&val, (unsigned *)0, cfile);
4379 		if (token != LPAREN) {
4380 			if (!expression_allocate (expr, MDL))
4381 				log_fatal ("can't allocate expression");
4382 			(*expr) -> op = expr_variable_reference;
4383 			(*expr) -> data.variable = cptr;
4384 			break;
4385 		}
4386 
4387 		skip_token(&val, (unsigned *)0, cfile);
4388 		if (!expression_allocate (expr, MDL))
4389 			log_fatal ("can't allocate expression");
4390 		(*expr) -> op = expr_funcall;
4391 		(*expr) -> data.funcall.name = cptr;
4392 
4393 		/* Now parse the argument list. */
4394 		ep = &(*expr) -> data.funcall.arglist;
4395 		do {
4396 			if (!expression_allocate (ep, MDL))
4397 				log_fatal ("can't allocate expression");
4398 			(*ep) -> op = expr_arg;
4399 			if (!parse_expression (&(*ep) -> data.arg.val,
4400 					       cfile, lose, context_any,
4401 					       (struct expression **)0,
4402 					       expr_none)) {
4403 				if (!*lose) {
4404 					parse_warn (cfile,
4405 						    "expecting expression.");
4406 					*lose = 1;
4407 				}
4408 				skip_to_semi (cfile);
4409 				expression_dereference (expr, MDL);
4410 				return 0;
4411 			}
4412 			ep = &((*ep) -> data.arg.next);
4413 			token = next_token (&val, (unsigned *)0, cfile);
4414 		} while (token == COMMA);
4415 		if (token != RPAREN) {
4416 			parse_warn (cfile, "Right parenthesis expected.");
4417 			skip_to_semi (cfile);
4418 			*lose = 1;
4419 			expression_dereference (expr, MDL);
4420 			return 0;
4421 		}
4422 		break;
4423 	}
4424 	return 1;
4425 }
4426 
4427 /* Parse an expression. */
4428 
4429 int parse_expression (expr, cfile, lose, context, plhs, binop)
4430 	struct expression **expr;
4431 	struct parse *cfile;
4432 	int *lose;
4433 	enum expression_context context;
4434 	struct expression **plhs;
4435 	enum expr_op binop;
4436 {
4437 	enum dhcp_token token;
4438 	const char *val;
4439 	struct expression *rhs = (struct expression *)0, *tmp;
4440 	struct expression *lhs = (struct expression *)0;
4441 	enum expr_op next_op;
4442 	enum expression_context
4443 		lhs_context = context_any,
4444 		rhs_context = context_any;
4445 
4446 	/* Consume the left hand side we were passed. */
4447 	if (plhs) {
4448 		expression_reference (&lhs, *plhs, MDL);
4449 		expression_dereference (plhs, MDL);
4450 	}
4451 
4452       new_rhs:
4453 	if (!parse_non_binary (&rhs, cfile, lose, context)) {
4454 		/* If we already have a left-hand side, then it's not
4455 		   okay for there not to be a right-hand side here, so
4456 		   we need to flag it as an error. */
4457 		if (lhs) {
4458 			if (!*lose) {
4459 				parse_warn (cfile,
4460 					    "expecting right-hand side.");
4461 				*lose = 1;
4462 				skip_to_semi (cfile);
4463 			}
4464 			expression_dereference (&lhs, MDL);
4465 		}
4466 		return 0;
4467 	}
4468 
4469 	/* At this point, rhs contains either an entire subexpression,
4470 	   or at least a left-hand-side.   If we do not see a binary token
4471 	   as the next token, we're done with the expression. */
4472 
4473 	token = peek_token (&val, (unsigned *)0, cfile);
4474 	switch (token) {
4475 	      case BANG:
4476 		skip_token(&val, (unsigned *)0, cfile);
4477 		token = peek_token (&val, (unsigned *)0, cfile);
4478 		if (token != EQUAL) {
4479 			parse_warn (cfile, "! in boolean context without =");
4480 			*lose = 1;
4481 			skip_to_semi (cfile);
4482 			if (lhs)
4483 				expression_dereference (&lhs, MDL);
4484 			return 0;
4485 		}
4486 		next_op = expr_not_equal;
4487 		context = expression_context (rhs);
4488 		break;
4489 
4490 	      case EQUAL:
4491 		next_op = expr_equal;
4492 		context = expression_context (rhs);
4493 		break;
4494 
4495 	      case TILDE:
4496 #ifdef HAVE_REGEX_H
4497 		skip_token(&val, NULL, cfile);
4498 		token = peek_token(&val, NULL, cfile);
4499 
4500 		if (token == TILDE)
4501 			next_op = expr_iregex_match;
4502 		else if (token == EQUAL)
4503 			next_op = expr_regex_match;
4504 		else {
4505 			parse_warn(cfile, "expecting ~= or ~~ operator");
4506 			*lose = 1;
4507 			skip_to_semi(cfile);
4508 			if (lhs)
4509 				expression_dereference(&lhs, MDL);
4510 			return 0;
4511 		}
4512 
4513 		context = expression_context(rhs);
4514 #else
4515 		parse_warn(cfile, "No support for regex operator.");
4516 		*lose = 1;
4517 		skip_to_semi(cfile);
4518 		if (lhs != NULL)
4519 			expression_dereference(&lhs, MDL);
4520 		return 0;
4521 #endif
4522 		break;
4523 
4524 	      case AND:
4525 		next_op = expr_and;
4526 		context = expression_context (rhs);
4527 		break;
4528 
4529 	      case OR:
4530 		next_op = expr_or;
4531 		context = expression_context (rhs);
4532 		break;
4533 
4534 	      case PLUS:
4535 		next_op = expr_add;
4536 		context = expression_context (rhs);
4537 		break;
4538 
4539 	      case MINUS:
4540 		next_op = expr_subtract;
4541 		context = expression_context (rhs);
4542 		break;
4543 
4544 	      case SLASH:
4545 		next_op = expr_divide;
4546 		context = expression_context (rhs);
4547 		break;
4548 
4549 	      case ASTERISK:
4550 		next_op = expr_multiply;
4551 		context = expression_context (rhs);
4552 		break;
4553 
4554 	      case PERCENT:
4555 		next_op = expr_remainder;
4556 		context = expression_context (rhs);
4557 		break;
4558 
4559 	      case AMPERSAND:
4560 		next_op = expr_binary_and;
4561 		context = expression_context (rhs);
4562 		break;
4563 
4564 	      case PIPE:
4565 		next_op = expr_binary_or;
4566 		context = expression_context (rhs);
4567 		break;
4568 
4569 	      case CARET:
4570 		next_op = expr_binary_xor;
4571 		context = expression_context (rhs);
4572 		break;
4573 
4574 	      default:
4575 		next_op = expr_none;
4576 	}
4577 
4578 	/* If we have no lhs yet, we just parsed it. */
4579 	if (!lhs) {
4580 		/* If there was no operator following what we just parsed,
4581 		   then we're done - return it. */
4582 		if (next_op == expr_none) {
4583 			*expr = rhs;
4584 			return 1;
4585 		}
4586 		lhs = rhs;
4587 		rhs = (struct expression *)0;
4588 		binop = next_op;
4589 		skip_token(&val, (unsigned *)0, cfile);
4590 		goto new_rhs;
4591 	}
4592 
4593 	/* If the next binary operator is of greater precedence than the
4594 	 * current operator, then rhs we have parsed so far is actually
4595 	 * the lhs of the next operator.  To get this value, we have to
4596 	 * recurse.
4597 	 */
4598 	if (binop != expr_none && next_op != expr_none &&
4599 	    op_precedence (binop, next_op) < 0) {
4600 
4601 		/* Eat the subexpression operator token, which we pass to
4602 		 * parse_expression...we only peek()'d earlier.
4603 		 */
4604 		skip_token(&val, (unsigned *)0, cfile);
4605 
4606 		/* Continue parsing of the right hand side with that token. */
4607 		tmp = rhs;
4608 		rhs = (struct expression *)0;
4609 		if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4610 				       &tmp, next_op)) {
4611 			if (!*lose) {
4612 				parse_warn (cfile,
4613 					    "expecting a subexpression");
4614 				*lose = 1;
4615 			}
4616 			return 0;
4617 		}
4618 		next_op = expr_none;
4619 	}
4620 
4621 	if (binop != expr_none) {
4622 	  rhs_context = expression_context(rhs);
4623 	  lhs_context = expression_context(lhs);
4624 
4625 	  if ((rhs_context != context_any) && (lhs_context != context_any) &&
4626 			(rhs_context != lhs_context)) {
4627 	    parse_warn (cfile, "illegal expression relating different types");
4628 	    skip_to_semi (cfile);
4629 	    expression_dereference (&rhs, MDL);
4630 	    expression_dereference (&lhs, MDL);
4631 	    *lose = 1;
4632 	    return 0;
4633 	  }
4634 
4635 	  switch(binop) {
4636 	    case expr_not_equal:
4637 	    case expr_equal:
4638 		if ((rhs_context != context_data_or_numeric) &&
4639 		    (rhs_context != context_data) &&
4640 		    (rhs_context != context_numeric) &&
4641 		    (rhs_context != context_any)) {
4642 			parse_warn (cfile, "expecting data/numeric expression");
4643 			skip_to_semi (cfile);
4644 			expression_dereference (&rhs, MDL);
4645 			*lose = 1;
4646 			return 0;
4647 		}
4648 		break;
4649 
4650 	    case expr_regex_match:
4651 #ifdef HAVE_REGEX_H
4652 		if (expression_context(rhs) != context_data) {
4653 			parse_warn(cfile, "expecting data expression");
4654 			skip_to_semi(cfile);
4655 			expression_dereference(&rhs, MDL);
4656 			*lose = 1;
4657 			return 0;
4658 		}
4659 #else
4660 		/* It should not be possible to attempt to parse the right
4661 		 * hand side of an operator there is no support for.
4662 		 */
4663 		log_fatal("Impossible condition at %s:%d.", MDL);
4664 #endif
4665 		break;
4666 
4667 	    case expr_and:
4668 	    case expr_or:
4669 		if ((rhs_context != context_boolean) &&
4670 		    (rhs_context != context_any)) {
4671 			parse_warn (cfile, "expecting boolean expressions");
4672 			skip_to_semi (cfile);
4673 			expression_dereference (&rhs, MDL);
4674 			*lose = 1;
4675 			return 0;
4676 		}
4677 		break;
4678 
4679 	    case expr_add:
4680 	    case expr_subtract:
4681 	    case expr_divide:
4682 	    case expr_multiply:
4683 	    case expr_remainder:
4684 	    case expr_binary_and:
4685 	    case expr_binary_or:
4686 	    case expr_binary_xor:
4687 		if ((rhs_context != context_numeric) &&
4688 		    (rhs_context != context_any)) {
4689 			parse_warn (cfile, "expecting numeric expressions");
4690                         skip_to_semi (cfile);
4691                         expression_dereference (&rhs, MDL);
4692                         *lose = 1;
4693                         return 0;
4694 		}
4695 		break;
4696 
4697 	    default:
4698 		break;
4699 	  }
4700 	}
4701 
4702 	/* Now, if we didn't find a binary operator, we're done parsing
4703 	   this subexpression, so combine it with the preceding binary
4704 	   operator and return the result. */
4705 	if (next_op == expr_none) {
4706 		if (!expression_allocate (expr, MDL))
4707 			log_fatal ("Can't allocate expression!");
4708 
4709 		(*expr) -> op = binop;
4710 		/* All the binary operators' data union members
4711 		   are the same, so we'll cheat and use the member
4712 		   for the equals operator. */
4713 		(*expr) -> data.equal [0] = lhs;
4714 		(*expr) -> data.equal [1] = rhs;
4715 		return 1;
4716 	}
4717 
4718 	/* Eat the operator token - we now know it was a binary operator... */
4719 	skip_token(&val, (unsigned *)0, cfile);
4720 
4721 	/* Now combine the LHS and the RHS using binop. */
4722 	tmp = (struct expression *)0;
4723 	if (!expression_allocate (&tmp, MDL))
4724 		log_fatal ("No memory for equal precedence combination.");
4725 
4726 	/* Store the LHS and RHS. */
4727 	tmp -> data.equal [0] = lhs;
4728 	tmp -> data.equal [1] = rhs;
4729 	tmp -> op = binop;
4730 
4731 	lhs = tmp;
4732 	tmp = (struct expression *)0;
4733 	rhs = (struct expression *)0;
4734 
4735 	/* Recursions don't return until we have parsed the end of the
4736 	   expression, so if we recursed earlier, we can now return what
4737 	   we got. */
4738 	if (next_op == expr_none) {
4739 		*expr = lhs;
4740 		return 1;
4741 	}
4742 
4743 	binop = next_op;
4744 	goto new_rhs;
4745 }
4746 
4747 
4748 int parse_option_data (expr, cfile, lookups, option)
4749 struct expression **expr;
4750 struct parse *cfile;
4751 int lookups;
4752 struct option *option;
4753 {
4754 	const char *val;
4755 	const char *fmt = NULL;
4756 	struct expression *tmp;
4757 	enum dhcp_token token;
4758 
4759 	do {
4760 		/*
4761                  * Set a flag if this is an array of a simple type (i.e.,
4762                  * not an array of pairs of IP addresses, or something like
4763                  * that.
4764                  */
4765 		int uniform = 0;
4766 
4767 	      and_again:
4768 		/* Set fmt to start of format for 'A' and one char back
4769 		 * for 'a'.
4770 		 */
4771 		if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a'))
4772 			fmt -= 1;
4773 		else if ((fmt == NULL) || (*fmt == 'A'))
4774 			fmt = option->format;
4775 
4776 		/* 'a' means always uniform */
4777 		if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a'))
4778 			uniform = 1;
4779 
4780 		do {
4781 			if ((*fmt == 'A') || (*fmt == 'a'))
4782 				break;
4783 			if (*fmt == 'o') {
4784 				/* consume the optional flag */
4785 				fmt++;
4786 				continue;
4787 			}
4788 
4789 			if (fmt[1] == 'o') {
4790 				/*
4791 				 * A value for the current format is
4792 				 * optional - check to see if the next
4793 				 * token is a semi-colon if so we don't
4794 				 * need to parse it and doing so would
4795 				 * consume the semi-colon which our
4796 				 * caller is expecting to parse
4797 				 */
4798 				token = peek_token(&val, (unsigned *)0,
4799 						   cfile);
4800 				if (token == SEMI) {
4801 					fmt++;
4802 					continue;
4803 				}
4804 			}
4805 
4806 			tmp = *expr;
4807 			*expr = NULL;
4808 
4809 			if (!parse_option_token(expr, cfile, &fmt, tmp,
4810 						uniform, lookups)) {
4811 				if (fmt [1] != 'o') {
4812 					if (tmp)
4813 						expression_dereference (&tmp,
4814 									MDL);
4815 					return 0;
4816 				}
4817 				*expr = tmp;
4818 				tmp = NULL;
4819 			}
4820 			if (tmp)
4821 				expression_dereference (&tmp, MDL);
4822 
4823 			fmt++;
4824 		} while (*fmt != '\0');
4825 
4826 		if ((*fmt == 'A') || (*fmt == 'a')) {
4827 			token = peek_token (&val, (unsigned *)0, cfile);
4828 			/* Comma means: continue with next element in array */
4829 			if (token == COMMA) {
4830 				skip_token(&val, (unsigned *)0, cfile);
4831 				continue;
4832 			}
4833 			/* no comma: end of array.
4834 			   'A' or end of string means: leave the loop */
4835 			if ((*fmt == 'A') || (fmt[1] == '\0'))
4836 				break;
4837 			/* 'a' means: go on with next char */
4838 			if (*fmt == 'a') {
4839 				fmt++;
4840 				goto and_again;
4841 			}
4842 		}
4843 	} while ((*fmt == 'A') || (*fmt == 'a'));
4844 
4845         return 1;
4846 }
4847 
4848 /* option-statement :== identifier DOT identifier <syntax> SEMI
4849 		      | identifier <syntax> SEMI
4850 
4851    Option syntax is handled specially through format strings, so it
4852    would be painful to come up with BNF for it.   However, it always
4853    starts as above and ends in a SEMI. */
4854 
4855 int parse_option_statement (result, cfile, lookups, option, op)
4856 	struct executable_statement **result;
4857 	struct parse *cfile;
4858 	int lookups;
4859 	struct option *option;
4860 	enum statement_op op;
4861 {
4862 	const char *val;
4863 	enum dhcp_token token;
4864 	struct expression *expr = (struct expression *)0;
4865 	int lose;
4866 
4867 	token = peek_token (&val, (unsigned *)0, cfile);
4868 	if ((token == SEMI) && (option->format[0] != 'Z')) {
4869 		/* Eat the semicolon... */
4870 		/*
4871 		 * XXXSK: I'm not sure why we should ever get here, but we
4872 		 * 	  do during our startup. This confuses things if
4873 		 * 	  we are parsing a zero-length option, so don't
4874 		 * 	  eat the semicolon token in that case.
4875 		 */
4876 		skip_token(&val, (unsigned *)0, cfile);
4877 	} else if (token == EQUAL) {
4878 		/* Eat the equals sign. */
4879 		skip_token(&val, (unsigned *)0, cfile);
4880 
4881 		/* Parse a data expression and use its value for the data. */
4882 		if (!parse_data_expression (&expr, cfile, &lose)) {
4883 			/* In this context, we must have an executable
4884 			   statement, so if we found something else, it's
4885 			   still an error. */
4886 			if (!lose) {
4887 				parse_warn (cfile,
4888 					    "expecting a data expression.");
4889 				skip_to_semi (cfile);
4890 			}
4891 			return 0;
4892 		}
4893 	} else {
4894 		if (! parse_option_data(&expr, cfile, lookups, option))
4895 			return 0;
4896 	}
4897 
4898 	if (!parse_semi (cfile))
4899 		return 0;
4900 	if (!executable_statement_allocate (result, MDL))
4901 		log_fatal ("no memory for option statement.");
4902 
4903         (*result)->op = op;
4904 	if (expr && !option_cache (&(*result)->data.option,
4905 				   NULL, expr, option, MDL))
4906 		log_fatal ("no memory for option cache");
4907 
4908 	if (expr)
4909 		expression_dereference (&expr, MDL);
4910 
4911 	return 1;
4912 }
4913 
4914 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4915 	struct expression **rv;
4916 	struct parse *cfile;
4917 	const char **fmt;
4918 	struct expression *expr;
4919 	int uniform;
4920 	int lookups;
4921 {
4922 	const char *val;
4923 	enum dhcp_token token;
4924 	struct expression *t = (struct expression *)0;
4925 	unsigned char buf [4];
4926 	unsigned len;
4927 	struct iaddr addr;
4928 	int compress;
4929 	isc_boolean_t freeval = ISC_FALSE;
4930 	const char *f, *g;
4931 	struct enumeration_value *e;
4932 
4933 	switch (**fmt) {
4934 	      case 'U':
4935 		token = next_token (&val, &len, cfile);
4936 		if (!is_identifier (token)) {
4937 			if ((*fmt) [1] != 'o') {
4938 				parse_warn (cfile, "expecting identifier.");
4939 				if (token != SEMI)
4940 					skip_to_semi (cfile);
4941 			}
4942 			return 0;
4943 		}
4944 		if (!make_const_data (&t, (const unsigned char *)val,
4945 				      len, 1, 1, MDL))
4946 			log_fatal ("No memory for %s", val);
4947 		break;
4948 
4949 	      case 'E':
4950 		g = strchr (*fmt, '.');
4951 		if (!g) {
4952 			parse_warn (cfile,
4953 				    "malformed encapsulation format (bug!)");
4954 			skip_to_semi (cfile);
4955 			return 0;
4956 		}
4957 		*fmt = g;
4958 		/* FALL THROUGH */
4959 		/* to get string value for the option */
4960 	      case 'X':
4961 		token = peek_token (&val, (unsigned *)0, cfile);
4962 		if (token == NUMBER_OR_NAME || token == NUMBER) {
4963 			if (!expression_allocate (&t, MDL))
4964 				return 0;
4965 			if (!parse_cshl (&t -> data.const_data, cfile)) {
4966 				expression_dereference (&t, MDL);
4967 				return 0;
4968 			}
4969 			t -> op = expr_const_data;
4970 		} else {
4971 			token = next_token (&val, &len, cfile);
4972 
4973 			if(token == STRING) {
4974 				if (!make_const_data (&t,
4975 						(const unsigned char *)val,
4976 							len, 1, 1, MDL))
4977 					log_fatal ("No memory for \"%s\"", val);
4978 			} else {
4979                                 if ((*fmt) [1] != 'o') {
4980 				        parse_warn (cfile, "expecting string "
4981 					            "or hexadecimal data.");
4982 				        skip_to_semi (cfile);
4983                                 }
4984 				return 0;
4985 			}
4986 		}
4987 		break;
4988 
4989               case 'D': /* Domain list... */
4990 		if ((*fmt)[1] == 'c') {
4991 			compress = 1;
4992 			/* Skip the compress-flag atom. */
4993 			(*fmt)++;
4994 		} else
4995 			compress = 0;
4996 
4997 		t = parse_domain_list(cfile, compress);
4998 
4999 		if (!t) {
5000 			if ((*fmt)[1] != 'o')
5001 				skip_to_semi(cfile);
5002 			return 0;
5003 		}
5004 
5005 		break;
5006 
5007 	      case 'd': /* Domain name... */
5008 		val = parse_host_name (cfile);
5009 		if (!val) {
5010 			parse_warn (cfile, "not a valid domain name.");
5011 			skip_to_semi (cfile);
5012 			return 0;
5013 		}
5014 		len = strlen (val);
5015 		freeval = ISC_TRUE;
5016 		goto make_string;
5017 
5018 	      case 't': /* Text string... */
5019 		token = next_token (&val, &len, cfile);
5020 		if (token != STRING && !is_identifier (token)) {
5021 			if ((*fmt) [1] != 'o') {
5022 				parse_warn (cfile, "expecting string.");
5023 				if (token != SEMI)
5024 					skip_to_semi (cfile);
5025 			}
5026 			return 0;
5027 		}
5028 	      make_string:
5029 		if (!make_const_data (&t, (const unsigned char *)val,
5030 				      len, 1, 1, MDL))
5031 			log_fatal ("No memory for concatenation");
5032 		if (freeval == ISC_TRUE) {
5033 			dfree((char *)val, MDL);
5034 			freeval = ISC_FALSE;
5035 			POST(freeval);
5036 		}
5037 		break;
5038 
5039 	      case 'N':
5040 		f = (*fmt) + 1;
5041 		g = strchr (*fmt, '.');
5042 		if (!g) {
5043 			parse_warn (cfile, "malformed %s (bug!)",
5044 				    "enumeration format");
5045 		      foo:
5046 			skip_to_semi (cfile);
5047 			return 0;
5048 		}
5049 		*fmt = g;
5050 		token = next_token (&val, (unsigned *)0, cfile);
5051 		if (!is_identifier (token)) {
5052 			parse_warn (cfile,
5053 				    "identifier expected");
5054 			goto foo;
5055 		}
5056 		e = find_enumeration_value (f, (*fmt) - f, &len, val);
5057 		if (!e) {
5058 			parse_warn (cfile, "unknown value");
5059 			goto foo;
5060 		}
5061 		if (!make_const_data (&t, &e -> value, len, 0, 1, MDL))
5062 			return 0;
5063 		break;
5064 
5065 	      case 'I': /* IP address or hostname. */
5066 		if (lookups) {
5067 			if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
5068 				return 0;
5069 		} else {
5070 			if (!parse_ip_addr (cfile, &addr))
5071 				return 0;
5072 			if (!make_const_data (&t, addr.iabuf, addr.len,
5073 					      0, 1, MDL))
5074 				return 0;
5075 		}
5076 		break;
5077 
5078 	      case '6': /* IPv6 address. */
5079 		if (!parse_ip6_addr(cfile, &addr)) {
5080 			return 0;
5081 		}
5082 		if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
5083 			return 0;
5084 		}
5085 		break;
5086 
5087 	      case 'T':	/* Lease interval. */
5088 		token = next_token (&val, (unsigned *)0, cfile);
5089 		if (token != INFINITE)
5090 			goto check_number;
5091 		putLong (buf, -1);
5092 		if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5093 			return 0;
5094 		break;
5095 
5096 	      case 'L': /* Unsigned 32-bit integer... */
5097 	      case 'l':	/* Signed 32-bit integer... */
5098 		token = next_token (&val, (unsigned *)0, cfile);
5099 	      check_number:
5100 		if ((token != NUMBER) && (token != NUMBER_OR_NAME)) {
5101 		      need_number:
5102 			if ((*fmt) [1] != 'o') {
5103 				parse_warn (cfile, "expecting number.");
5104 				if (token != SEMI)
5105 					skip_to_semi (cfile);
5106 			}
5107 			return 0;
5108 		}
5109 		convert_num (cfile, buf, val, 0, 32);
5110 		if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5111 			return 0;
5112 		break;
5113 
5114 	      case 's':	/* Signed 16-bit integer. */
5115 	      case 'S':	/* Unsigned 16-bit integer. */
5116 		token = next_token (&val, (unsigned *)0, cfile);
5117 		if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5118 			goto need_number;
5119 		convert_num (cfile, buf, val, 0, 16);
5120 		if (!make_const_data (&t, buf, 2, 0, 1, MDL))
5121 			return 0;
5122 		break;
5123 
5124 	      case 'b':	/* Signed 8-bit integer. */
5125 	      case 'B':	/* Unsigned 8-bit integer. */
5126 		token = next_token (&val, (unsigned *)0, cfile);
5127 		if ((token != NUMBER) && (token != NUMBER_OR_NAME))
5128 			goto need_number;
5129 		convert_num (cfile, buf, val, 0, 8);
5130 		if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5131 			return 0;
5132 		break;
5133 
5134 	      case 'f': /* Boolean flag. */
5135 		token = next_token (&val, (unsigned *)0, cfile);
5136 		if (!is_identifier (token)) {
5137 			if ((*fmt) [1] != 'o')
5138 				parse_warn (cfile, "expecting identifier.");
5139 		      bad_flag:
5140 			if ((*fmt) [1] != 'o') {
5141 				if (token != SEMI)
5142 					skip_to_semi (cfile);
5143 			}
5144 			return 0;
5145 		}
5146 		if (!strcasecmp (val, "true")
5147 		    || !strcasecmp (val, "on"))
5148 			buf [0] = 1;
5149 		else if (!strcasecmp (val, "false")
5150 			 || !strcasecmp (val, "off"))
5151 			buf [0] = 0;
5152 		else if (!strcasecmp (val, "ignore"))
5153 			buf [0] = 2;
5154 		else {
5155 			if ((*fmt) [1] != 'o')
5156 				parse_warn (cfile, "expecting boolean.");
5157 			goto bad_flag;
5158 		}
5159 		if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5160 			return 0;
5161 		break;
5162 
5163 	      case 'Z': /* Zero-length option. */
5164 		token = peek_token (&val, (unsigned *)0, cfile);
5165 		if (token != SEMI) {
5166 			parse_warn(cfile, "semicolon expected.");
5167 			skip_to_semi(cfile);
5168 		}
5169 		buf[0] = '\0';
5170 		if (!make_const_data(&t,        /* expression */
5171 				     buf,       /* buffer */
5172 				     0,         /* length */
5173 				     0,         /* terminated */
5174 				     1,         /* allocate */
5175 				     MDL))
5176 			return 0;
5177 		break;
5178 
5179 	      default:
5180 		parse_warn (cfile, "Bad format '%c' in parse_option_token.",
5181 			    **fmt);
5182 		skip_to_semi (cfile);
5183 		return 0;
5184 	}
5185 	if (expr) {
5186 		if (!make_concat (rv, expr, t))
5187 			return 0;
5188 	} else
5189 		expression_reference (rv, t, MDL);
5190 	expression_dereference (&t, MDL);
5191 	return 1;
5192 }
5193 
5194 int parse_option_decl (oc, cfile)
5195 	struct option_cache **oc;
5196 	struct parse *cfile;
5197 {
5198 	const char *val;
5199 	int token;
5200 	u_int8_t buf [4];
5201 	u_int8_t hunkbuf [1024];
5202 	unsigned hunkix = 0;
5203 	const char *fmt, *f;
5204 	struct option *option=NULL;
5205 	struct iaddr ip_addr;
5206 	u_int8_t *dp;
5207 	const u_int8_t *cdp;
5208 	unsigned len;
5209 	int nul_term = 0;
5210 	struct buffer *bp;
5211 	int known = 0;
5212 	int compress;
5213 	struct expression *express = NULL;
5214 	struct enumeration_value *e;
5215 	isc_result_t status;
5216 
5217 	status = parse_option_name (cfile, 0, &known, &option);
5218 	if (status != ISC_R_SUCCESS || option == NULL)
5219 		return 0;
5220 
5221 	fmt = option->format;
5222 
5223 	/* Parse the option data... */
5224 	do {
5225 		for (; *fmt; fmt++) {
5226 			if (*fmt == 'A') {
5227 				/* 'A' is an array of records, start at
5228 				 *  the beginning
5229 				 */
5230 				fmt = option->format;
5231 				break;
5232 			}
5233 
5234 			if (*fmt == 'a') {
5235 				/* 'a' is an array of the last field,
5236 				 * back up one format character
5237 				 */
5238 				fmt--;
5239 				break;
5240 			}
5241 			if (*fmt == 'o' && fmt != option -> format)
5242 				continue;
5243 			switch (*fmt) {
5244 			      case 'E':
5245 				fmt = strchr (fmt, '.');
5246 				if (!fmt) {
5247 					parse_warn (cfile,
5248 						    "malformed %s (bug!)",
5249 						    "encapsulation format");
5250 					goto parse_exit;
5251 				}
5252 				/* FALL THROUGH */
5253 				/* to get string value for the option */
5254 			      case 'X':
5255 				len = parse_X (cfile, &hunkbuf [hunkix],
5256 					       sizeof hunkbuf - hunkix);
5257 				hunkix += len;
5258 				break;
5259 
5260 			      case 't': /* Text string... */
5261 				token = peek_token (&val,
5262 						    &len, cfile);
5263 				if (token == SEMI && fmt[1] == 'o') {
5264 					fmt++;
5265 					break;
5266 				}
5267 				token = next_token (&val,
5268 						    &len, cfile);
5269 				if (token != STRING) {
5270 					parse_warn (cfile,
5271 						    "expecting string.");
5272 					goto parse_exit;
5273 				}
5274 				if (hunkix + len + 1 > sizeof hunkbuf) {
5275 					parse_warn (cfile,
5276 						    "option data buffer %s",
5277 						    "overflow");
5278 					goto parse_exit;
5279 				}
5280 				memcpy (&hunkbuf [hunkix], val, len + 1);
5281 				nul_term = 1;
5282 				hunkix += len;
5283 				break;
5284 
5285 			      case 'D':
5286 				if (fmt[1] == 'c') {
5287 					compress = 1;
5288 					fmt++;
5289 				} else
5290 					compress = 0;
5291 
5292 				express = parse_domain_list(cfile, compress);
5293 
5294 				if (express == NULL)
5295 					goto exit;
5296 
5297 				if (express->op != expr_const_data) {
5298 					parse_warn(cfile, "unexpected "
5299 							  "expression");
5300 					goto parse_exit;
5301 				}
5302 
5303 				len = express->data.const_data.len;
5304 				cdp = express->data.const_data.data;
5305 
5306 				if ((hunkix + len) > sizeof(hunkbuf)) {
5307 					parse_warn(cfile, "option data buffer "
5308 							  "overflow");
5309 					goto parse_exit;
5310 				}
5311 				memcpy(&hunkbuf[hunkix], cdp, len);
5312 				hunkix += len;
5313 
5314 				expression_dereference(&express, MDL);
5315 				break;
5316 
5317 			      case 'N':
5318 				f = fmt + 1;
5319 				fmt = strchr (fmt, '.');
5320 				if (!fmt) {
5321 					parse_warn (cfile,
5322 						    "malformed %s (bug!)",
5323 						    "enumeration format");
5324 					goto parse_exit;
5325 				}
5326 				token = next_token (&val,
5327 						    (unsigned *)0, cfile);
5328 				if (!is_identifier (token)) {
5329 					parse_warn (cfile,
5330 						    "identifier expected");
5331 					goto parse_exit;
5332 				}
5333 				e = find_enumeration_value (f, fmt - f,
5334 							    &len, val);
5335 				if (!e) {
5336 					parse_warn (cfile,
5337 						    "unknown value");
5338 					goto parse_exit;
5339 				}
5340 				dp = &e -> value;
5341 				goto alloc;
5342 
5343 			      case '6':
5344 				if (!parse_ip6_addr(cfile, &ip_addr))
5345 					goto exit;
5346 				len = ip_addr.len;
5347 				dp = ip_addr.iabuf;
5348 				goto alloc;
5349 
5350 			      case 'I': /* IP address. */
5351 				if (!parse_ip_addr (cfile, &ip_addr))
5352 					goto exit;
5353 				len = ip_addr.len;
5354 				dp = ip_addr.iabuf;
5355 
5356 			      alloc:
5357 				if (hunkix + len > sizeof hunkbuf) {
5358 					parse_warn (cfile,
5359 						    "option data buffer %s",
5360 						    "overflow");
5361 					goto parse_exit;
5362 				}
5363 				memcpy (&hunkbuf [hunkix], dp, len);
5364 				hunkix += len;
5365 				break;
5366 
5367 			      case 'L': /* Unsigned 32-bit integer... */
5368 			      case 'l':	/* Signed 32-bit integer... */
5369 				token = next_token (&val,
5370 						    (unsigned *)0, cfile);
5371 				if ((token != NUMBER) &&
5372 				    (token != NUMBER_OR_NAME)) {
5373 				      need_number:
5374 					parse_warn (cfile,
5375 						    "expecting number.");
5376 					if (token != SEMI)
5377 						goto parse_exit;
5378 					else
5379 						goto exit;
5380 				}
5381 				convert_num (cfile, buf, val, 0, 32);
5382 				len = 4;
5383 				dp = buf;
5384 				goto alloc;
5385 
5386 			      case 's':	/* Signed 16-bit integer. */
5387 			      case 'S':	/* Unsigned 16-bit integer. */
5388 				token = next_token (&val,
5389 						    (unsigned *)0, cfile);
5390 				if ((token != NUMBER) &&
5391 				    (token != NUMBER_OR_NAME))
5392 					goto need_number;
5393 				convert_num (cfile, buf, val, 0, 16);
5394 				len = 2;
5395 				dp = buf;
5396 				goto alloc;
5397 
5398 			      case 'b':	/* Signed 8-bit integer. */
5399 			      case 'B':	/* Unsigned 8-bit integer. */
5400 				token = next_token (&val,
5401 						    (unsigned *)0, cfile);
5402 				if ((token != NUMBER) &&
5403 				    (token != NUMBER_OR_NAME))
5404 					goto need_number;
5405 				convert_num (cfile, buf, val, 0, 8);
5406 				len = 1;
5407 				dp = buf;
5408 				goto alloc;
5409 
5410 			      case 'f': /* Boolean flag. */
5411 				token = next_token (&val,
5412 						    (unsigned *)0, cfile);
5413 				if (!is_identifier (token)) {
5414 					parse_warn (cfile,
5415 						    "expecting identifier.");
5416 				      bad_flag:
5417 					if (token != SEMI)
5418 						goto parse_exit;
5419 					else
5420 						goto exit;
5421 				}
5422 				if (!strcasecmp (val, "true")
5423 				    || !strcasecmp (val, "on"))
5424 					buf [0] = 1;
5425 				else if (!strcasecmp (val, "false")
5426 					 || !strcasecmp (val, "off"))
5427 					buf [0] = 0;
5428 				else {
5429 					parse_warn (cfile,
5430 						    "expecting boolean.");
5431 					goto bad_flag;
5432 				}
5433 				len = 1;
5434 				dp = buf;
5435 				goto alloc;
5436 
5437 			      case 'Z':	/* Zero-length option */
5438 				token = peek_token(&val, (unsigned *)0, cfile);
5439 				if (token != SEMI) {
5440 					parse_warn(cfile,
5441 						   "semicolon expected.");
5442 					goto parse_exit;
5443 				}
5444 				len = 0;
5445 				buf[0] = '\0';
5446 				break;
5447 
5448 			      default:
5449 				log_error ("parse_option_param: Bad format %c",
5450 				      *fmt);
5451 				goto parse_exit;
5452 			}
5453 		}
5454 		token = next_token (&val, (unsigned *)0, cfile);
5455 	} while (*fmt && token == COMMA);
5456 
5457 	if (token != SEMI) {
5458 		parse_warn (cfile, "semicolon expected.");
5459 		goto parse_exit;
5460 	}
5461 
5462 	bp = (struct buffer *)0;
5463 	if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
5464 		log_fatal ("no memory to store option declaration.");
5465 	memcpy (bp -> data, hunkbuf, hunkix + nul_term);
5466 
5467 	if (!option_cache_allocate (oc, MDL))
5468 		log_fatal ("out of memory allocating option cache.");
5469 
5470 	(*oc) -> data.buffer = bp;
5471 	(*oc) -> data.data = &bp -> data [0];
5472 	(*oc) -> data.terminated = nul_term;
5473 	(*oc) -> data.len = hunkix;
5474 	option_reference(&(*oc)->option, option, MDL);
5475 	option_dereference(&option, MDL);
5476 	return 1;
5477 
5478 parse_exit:
5479 	if (express != NULL)
5480 		expression_dereference(&express, MDL);
5481 	skip_to_semi (cfile);
5482 exit:
5483 	option_dereference(&option, MDL);
5484 
5485 	return 0;
5486 }
5487 
5488 /* Consider merging parse_cshl into this. */
5489 
5490 int parse_X (cfile, buf, max)
5491 	struct parse *cfile;
5492 	u_int8_t *buf;
5493 	unsigned max;
5494 {
5495 	int token;
5496 	const char *val;
5497 	unsigned len;
5498 
5499 	token = peek_token (&val, (unsigned *)0, cfile);
5500 	if (token == NUMBER_OR_NAME || token == NUMBER) {
5501 		len = 0;
5502 		do {
5503 			token = next_token (&val, (unsigned *)0, cfile);
5504 			if (token != NUMBER && token != NUMBER_OR_NAME) {
5505 				parse_warn (cfile,
5506 					    "expecting hexadecimal constant.");
5507 				skip_to_semi (cfile);
5508 				return 0;
5509 			}
5510 			convert_num (cfile, &buf [len], val, 16, 8);
5511 			if (len++ > max) {
5512 				parse_warn (cfile,
5513 					    "hexadecimal constant too long.");
5514 				skip_to_semi (cfile);
5515 				return 0;
5516 			}
5517 			token = peek_token (&val, (unsigned *)0, cfile);
5518 			if (token == COLON)
5519 				token = next_token (&val,
5520 						    (unsigned *)0, cfile);
5521 		} while (token == COLON);
5522 		val = (char *)buf;
5523 	} else if (token == STRING) {
5524 		skip_token(&val, &len, cfile);
5525 		if (len + 1 > max) {
5526 			parse_warn (cfile, "string constant too long.");
5527 			skip_to_semi (cfile);
5528 			return 0;
5529 		}
5530 		memcpy (buf, val, len + 1);
5531 	} else {
5532 		parse_warn (cfile, "expecting string or hexadecimal data");
5533 		skip_to_semi (cfile);
5534 		return 0;
5535 	}
5536 	return len;
5537 }
5538 
5539 int parse_warn (struct parse *cfile, const char *fmt, ...)
5540 {
5541 	va_list list;
5542 	char lexbuf [256];
5543 	char mbuf [1024];
5544 	char fbuf [1024];
5545 	unsigned i, lix;
5546 
5547 	do_percentm (mbuf, fmt);
5548 	/* %Audit% This is log output. %2004.06.17,Safe%
5549 	 * If we truncate we hope the user can get a hint from the log.
5550 	 */
5551 	snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
5552 		  cfile -> tlname, cfile -> lexline, mbuf);
5553 
5554 	va_start (list, fmt);
5555 	vsnprintf (mbuf, sizeof mbuf, fbuf, list);
5556 	va_end (list);
5557 
5558 	lix = 0;
5559 	for (i = 0;
5560 	     cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
5561 		if (lix < (sizeof lexbuf) - 1)
5562 			lexbuf [lix++] = ' ';
5563 		if (cfile -> token_line [i] == '\t') {
5564 			for (; lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
5565 				lexbuf [lix] = ' ';
5566 		}
5567 	}
5568 	lexbuf [lix] = 0;
5569 
5570 #ifndef DEBUG
5571 	syslog (log_priority | LOG_ERR, "%s", mbuf);
5572 	syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
5573 	if (cfile -> lexchar < 81)
5574 		syslog (log_priority | LOG_ERR, "%s^", lexbuf);
5575 #endif
5576 
5577 	if (log_perror) {
5578 		IGNORE_RET (write (STDERR_FILENO, mbuf, strlen (mbuf)));
5579 		IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5580 		IGNORE_RET (write (STDERR_FILENO, cfile -> token_line,
5581 				   strlen (cfile -> token_line)));
5582 		IGNORE_RET (write (STDERR_FILENO, "\n", 1));
5583 		if (cfile -> lexchar < 81)
5584 			IGNORE_RET (write (STDERR_FILENO, lexbuf, lix));
5585 		IGNORE_RET (write (STDERR_FILENO, "^\n", 2));
5586 	}
5587 
5588 	cfile -> warnings_occurred = 1;
5589 
5590 	return 0;
5591 }
5592 
5593 struct expression *
5594 parse_domain_list(struct parse *cfile, int compress)
5595 {
5596 	const char *val;
5597 	enum dhcp_token token = SEMI;
5598 	struct expression *t = NULL;
5599 	unsigned len, clen = 0;
5600 	int result;
5601 	unsigned char compbuf[256 * NS_MAXCDNAME];
5602 	const unsigned char *dnptrs[256], **lastdnptr;
5603 
5604 	memset(compbuf, 0, sizeof(compbuf));
5605 	memset(dnptrs, 0, sizeof(dnptrs));
5606 	dnptrs[0] = compbuf;
5607 	lastdnptr = &dnptrs[255];
5608 
5609 	do {
5610 		/* Consume the COMMA token if peeked. */
5611 		if (token == COMMA)
5612 			skip_token(&val, NULL, cfile);
5613 
5614 		/* Get next (or first) value. */
5615 		token = next_token(&val, &len, cfile);
5616 
5617 		if (token != STRING) {
5618 			parse_warn(cfile, "Expecting a domain string.");
5619 			return NULL;
5620 		}
5621 
5622 		/* If compression pointers are enabled, compress.  If not,
5623 		 * just pack the names in series into the buffer.
5624 		 */
5625 		if (compress) {
5626 			result = MRns_name_compress(val, compbuf + clen,
5627 						    sizeof(compbuf) - clen,
5628 						    dnptrs, lastdnptr);
5629 
5630 			if (result < 0) {
5631 				parse_warn(cfile, "Error compressing domain "
5632 						  "list: %m");
5633 				return NULL;
5634 			}
5635 
5636 			clen += result;
5637 		} else {
5638 			result = MRns_name_pton(val, compbuf + clen,
5639 						sizeof(compbuf) - clen);
5640 
5641 			/* result == 1 means the input was fully qualified.
5642 			 * result == 0 means the input wasn't.
5643 			 * result == -1 means bad things.
5644 			 */
5645 			if (result < 0) {
5646 				parse_warn(cfile, "Error assembling domain "
5647 						  "list: %m");
5648 				return NULL;
5649 			}
5650 
5651 			/*
5652 			 * We need to figure out how many bytes to increment
5653 			 * our buffer pointer since pton doesn't tell us.
5654 			 */
5655 			while (compbuf[clen] != 0)
5656 				clen += compbuf[clen] + 1;
5657 
5658 			/* Count the last label (0). */
5659 			clen++;
5660 		}
5661 
5662 		if (clen > sizeof(compbuf))
5663 			log_fatal("Impossible error at %s:%d", MDL);
5664 
5665 		token = peek_token(&val, NULL, cfile);
5666 	} while (token == COMMA);
5667 
5668 	if (!make_const_data(&t, compbuf, clen, 1, 1, MDL))
5669 		log_fatal("No memory for domain list object.");
5670 
5671 	return t;
5672 }
5673 
5674