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