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