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