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