Upgrade isc-dhcp, e.g. dhclient.
[dragonfly.git] / contrib / isc-dhcp / common / parse.c
1 /* parse.c
2
3    Common parser code for dhcpd and dhclient. */
4
5 /*
6  * Copyright (c) 1995-2002 Internet Software Consortium.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of The Internet Software Consortium nor the names
19  *    of its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED.  IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * This software has been written for the Internet Software Consortium
37  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38  * To learn more about the Internet Software Consortium, see
39  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
40  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
41  * ``http://www.nominum.com''.
42  * 
43  * $Id: parse.c,v 1.104.2.14 2003/07/25 19:36:11 dhankins Exp $ Copyright (c) 1995-2002 The Internet Software Consortium.  All rights reserved.
44  * $DragonFly: src/contrib/isc-dhcp/common/Attic/parse.c,v 1.2 2003/10/11 21:14:17 dillon Exp $
45  */
46
47
48 #include "dhcpd.h"
49
50 /* Enumerations can be specified in option formats, and are used for
51    parsing, so we define the routines that manage them here. */
52
53 struct enumeration *enumerations;
54
55 void add_enumeration (struct enumeration *enumeration)
56 {
57         enumeration -> next = enumerations;
58         enumerations = enumeration;
59 }
60
61 struct enumeration *find_enumeration (const char *name, int length)
62 {
63         struct enumeration *e;
64
65         for (e = enumerations; e; e = e -> next)
66                 if (strlen (e -> name) == length &&
67                     !memcmp (e -> name, name, (unsigned)length))
68                         return e;
69         return (struct enumeration *)0;
70 }
71
72 struct enumeration_value *find_enumeration_value (const char *name,
73                                                   int length,
74                                                   const char *value)
75 {
76         struct enumeration *e;
77         int i;
78
79         e = find_enumeration (name, length);
80         if (e) {
81                 for (i = 0; e -> values [i].name; i++) {
82                         if (!strcmp (value, e -> values [i].name))
83                                 return &e -> values [i];
84                 }
85         }
86         return (struct enumeration_value *)0;
87 }
88
89 /* Skip to the semicolon ending the current statement.   If we encounter
90    braces, the matching closing brace terminates the statement.   If we
91    encounter a right brace but haven't encountered a left brace, return
92    leaving the brace in the token buffer for the caller.   If we see a
93    semicolon and haven't seen a left brace, return.   This lets us skip
94    over:
95
96         statement;
97         statement foo bar { }
98         statement foo bar { statement { } }
99         statement}
100  
101         ...et cetera. */
102
103 void skip_to_semi (cfile)
104         struct parse *cfile;
105 {
106         skip_to_rbrace (cfile, 0);
107 }
108
109 void skip_to_rbrace (cfile, brace_count)
110         struct parse *cfile;
111         int brace_count;
112 {
113         enum dhcp_token token;
114         const char *val;
115
116 #if defined (DEBUG_TOKEN)
117         log_error ("skip_to_rbrace: %d\n", brace_count);
118 #endif
119         do {
120                 token = peek_token (&val, (unsigned *)0, cfile);
121                 if (token == RBRACE) {
122                         token = next_token (&val, (unsigned *)0, cfile);
123                         if (brace_count) {
124                                 if (!--brace_count)
125                                         return;
126                         } else
127                                 return;
128                 } else if (token == LBRACE) {
129                         brace_count++;
130                 } else if (token == SEMI && !brace_count) {
131                         token = next_token (&val, (unsigned *)0, cfile);
132                         return;
133                 } else if (token == EOL) {
134                         /* EOL only happens when parsing /etc/resolv.conf,
135                            and we treat it like a semicolon because the
136                            resolv.conf file is line-oriented. */
137                         token = next_token (&val, (unsigned *)0, cfile);
138                         return;
139                 }
140                 token = next_token (&val, (unsigned *)0, cfile);
141         } while (token != END_OF_FILE);
142 }
143
144 int parse_semi (cfile)
145         struct parse *cfile;
146 {
147         enum dhcp_token token;
148         const char *val;
149
150         token = next_token (&val, (unsigned *)0, cfile);
151         if (token != SEMI) {
152                 parse_warn (cfile, "semicolon expected.");
153                 skip_to_semi (cfile);
154                 return 0;
155         }
156         return 1;
157 }
158
159 /* string-parameter :== STRING SEMI */
160
161 int parse_string (cfile, sptr, lptr)
162         struct parse *cfile;
163         char **sptr;
164         unsigned *lptr;
165 {
166         const char *val;
167         enum dhcp_token token;
168         char *s;
169         unsigned len;
170
171         token = next_token (&val, &len, cfile);
172         if (token != STRING) {
173                 parse_warn (cfile, "expecting a string");
174                 skip_to_semi (cfile);
175                 return 0;
176         }
177         s = (char *)dmalloc (len + 1, MDL);
178         if (!s)
179                 log_fatal ("no memory for string %s.", val);
180         memcpy (s, val, len + 1);
181
182         if (!parse_semi (cfile)) {
183                 dfree (s, MDL);
184                 return 0;
185         }
186         if (sptr)
187                 *sptr = s;
188         else
189                 dfree (s, MDL);
190         if (lptr)
191                 *lptr = len;
192         return 1;
193 }
194
195 /*
196  * hostname :== IDENTIFIER
197  *              | IDENTIFIER DOT
198  *              | hostname DOT IDENTIFIER
199  */
200
201 char *parse_host_name (cfile)
202         struct parse *cfile;
203 {
204         const char *val;
205         enum dhcp_token token;
206         unsigned len = 0;
207         char *s;
208         char *t;
209         pair c = (pair)0;
210         int ltid = 0;
211         
212         /* Read a dotted hostname... */
213         do {
214                 /* Read a token, which should be an identifier. */
215                 token = peek_token (&val, (unsigned *)0, cfile);
216                 if (!is_identifier (token) && token != NUMBER)
217                         break;
218                 token = next_token (&val, (unsigned *)0, cfile);
219
220                 /* Store this identifier... */
221                 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
222                         log_fatal ("can't allocate temp space for hostname.");
223                 strcpy (s, val);
224                 c = cons ((caddr_t)s, c);
225                 len += strlen (s) + 1;
226                 /* Look for a dot; if it's there, keep going, otherwise
227                    we're done. */
228                 token = peek_token (&val, (unsigned *)0, cfile);
229                 if (token == DOT) {
230                         token = next_token (&val, (unsigned *)0, cfile);
231                         ltid = 1;
232                 } else
233                         ltid = 0;
234         } while (token == DOT);
235
236         /* Should be at least one token. */
237         if (!len)
238                 return (char *)0;
239
240         /* Assemble the hostname together into a string. */
241         if (!(s = (char *)dmalloc (len + ltid, MDL)))
242                 log_fatal ("can't allocate space for hostname.");
243         t = s + len + ltid;
244         *--t = 0;
245         if (ltid)
246                 *--t = '.';
247         while (c) {
248                 pair cdr = c -> cdr;
249                 unsigned l = strlen ((char *)(c -> car));
250                 t -= l;
251                 memcpy (t, (char *)(c -> car), l);
252                 /* Free up temp space. */
253                 dfree (c -> car, MDL);
254                 dfree (c, MDL);
255                 c = cdr;
256                 if (t != s)
257                         *--t = '.';
258         }
259         return s;
260 }
261
262 /* ip-addr-or-hostname :== ip-address | hostname
263    ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
264    
265    Parse an ip address or a hostname.   If uniform is zero, put in
266    an expr_substring node to limit hostnames that evaluate to more
267    than one IP address. */
268
269 int parse_ip_addr_or_hostname (expr, cfile, uniform)
270         struct expression **expr;
271         struct parse *cfile;
272         int uniform;
273 {
274         const char *val;
275         enum dhcp_token token;
276         unsigned char addr [4];
277         unsigned len = sizeof addr;
278         char *name;
279         struct expression *x = (struct expression *)0;
280
281         token = peek_token (&val, (unsigned *)0, cfile);
282         if (is_identifier (token)) {
283                 name = parse_host_name (cfile);
284                 if (!name)
285                         return 0;
286                 if (!make_host_lookup (expr, name)) {
287                         dfree(name, MDL);
288                         return 0;
289                 }
290                 dfree(name, MDL);
291                 if (!uniform) {
292                         if (!make_limit (&x, *expr, 4))
293                                 return 0;
294                         expression_dereference (expr, MDL);
295                         *expr = x;
296                 }
297         } else if (token == NUMBER) {
298                 if (!parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
299                         return 0;
300                 return make_const_data (expr, addr, len, 0, 1, MDL);
301         } else {
302                 if (token != RBRACE && token != LBRACE)
303                         token = next_token (&val, (unsigned *)0, cfile);
304                 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
305                             val, token);
306                 if (token != SEMI)
307                         skip_to_semi (cfile);
308                 return 0;
309         }
310
311         return 1;
312 }       
313         
314 /*
315  * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
316  */
317
318 int parse_ip_addr (cfile, addr)
319         struct parse *cfile;
320         struct iaddr *addr;
321 {
322         const char *val;
323         enum dhcp_token token;
324
325         addr -> len = 4;
326         if (parse_numeric_aggregate (cfile, addr -> iabuf,
327                                      &addr -> len, DOT, 10, 8))
328                 return 1;
329         return 0;
330 }       
331
332 /*
333  * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
334  * hardware-type :== ETHERNET | TOKEN_RING | FDDI
335  */
336
337 void parse_hardware_param (cfile, hardware)
338         struct parse *cfile;
339         struct hardware *hardware;
340 {
341         const char *val;
342         enum dhcp_token token;
343         unsigned hlen;
344         unsigned char *t;
345
346         token = next_token (&val, (unsigned *)0, cfile);
347         switch (token) {
348               case ETHERNET:
349                 hardware -> hbuf [0] = HTYPE_ETHER;
350                 break;
351               case TOKEN_RING:
352                 hardware -> hbuf [0] = HTYPE_IEEE802;
353                 break;
354               case FDDI:
355                 hardware -> hbuf [0] = HTYPE_FDDI;
356                 break;
357               default:
358                 if (!strncmp (val, "unknown-", 8)) {
359                         hardware -> hbuf [0] = atoi (&val [8]);
360                 } else {
361                         parse_warn (cfile,
362                                     "expecting a network hardware type");
363                         skip_to_semi (cfile);
364
365                         return;
366                 }
367         }
368
369         /* Parse the hardware address information.   Technically,
370            it would make a lot of sense to restrict the length of the
371            data we'll accept here to the length of a particular hardware
372            address type.   Unfortunately, there are some broken clients
373            out there that put bogus data in the chaddr buffer, and we accept
374            that data in the lease file rather than simply failing on such
375            clients.   Yuck. */
376         hlen = 0;
377         token = peek_token (&val, (unsigned *)0, cfile);
378         if (token == SEMI) {
379                 hardware -> hlen = 1;
380                 goto out;
381         }
382         t = parse_numeric_aggregate (cfile, (unsigned char *)0, &hlen,
383                                      COLON, 16, 8);
384         if (!t) {
385                 hardware -> hlen = 1;
386                 return;
387         }
388         if (hlen + 1 > sizeof hardware -> hbuf) {
389                 dfree (t, MDL);
390                 parse_warn (cfile, "hardware address too long");
391         } else {
392                 hardware -> hlen = hlen + 1;
393                 memcpy ((unsigned char *)&hardware -> hbuf [1], t, hlen);
394                 if (hlen + 1 < sizeof hardware -> hbuf)
395                         memset (&hardware -> hbuf [hlen + 1], 0,
396                                 (sizeof hardware -> hbuf) - hlen - 1);
397                 dfree (t, MDL);
398         }
399         
400       out:
401         token = next_token (&val, (unsigned *)0, cfile);
402         if (token != SEMI) {
403                 parse_warn (cfile, "expecting semicolon.");
404                 skip_to_semi (cfile);
405         }
406 }
407
408 /* lease-time :== NUMBER SEMI */
409
410 void parse_lease_time (cfile, timep)
411         struct parse *cfile;
412         TIME *timep;
413 {
414         const char *val;
415         enum dhcp_token token;
416
417         token = next_token (&val, (unsigned *)0, cfile);
418         if (token != NUMBER) {
419                 parse_warn (cfile, "Expecting numeric lease time");
420                 skip_to_semi (cfile);
421                 return;
422         }
423         convert_num (cfile, (unsigned char *)timep, val, 10, 32);
424         /* Unswap the number - convert_num returns stuff in NBO. */
425         *timep = ntohl (*timep); /* XXX */
426
427         parse_semi (cfile);
428 }
429
430 /* No BNF for numeric aggregates - that's defined by the caller.  What
431    this function does is to parse a sequence of numbers seperated by
432    the token specified in seperator.  If max is zero, any number of
433    numbers will be parsed; otherwise, exactly max numbers are
434    expected.  Base and size tell us how to internalize the numbers
435    once they've been tokenized. */
436
437 unsigned char *parse_numeric_aggregate (cfile, buf,
438                                         max, seperator, base, size)
439         struct parse *cfile;
440         unsigned char *buf;
441         unsigned *max;
442         int seperator;
443         int base;
444         unsigned size;
445 {
446         const char *val;
447         enum dhcp_token token;
448         unsigned char *bufp = buf, *s, *t;
449         unsigned count = 0;
450         pair c = (pair)0;
451
452         if (!bufp && *max) {
453                 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
454                 if (!bufp)
455                         log_fatal ("no space for numeric aggregate");
456                 s = 0;
457         } else
458                 s = bufp;
459
460         do {
461                 if (count) {
462                         token = peek_token (&val, (unsigned *)0, cfile);
463                         if (token != seperator) {
464                                 if (!*max)
465                                         break;
466                                 if (token != RBRACE && token != LBRACE)
467                                         token = next_token (&val,
468                                                             (unsigned *)0,
469                                                             cfile);
470                                 parse_warn (cfile, "too few numbers.");
471                                 if (token != SEMI)
472                                         skip_to_semi (cfile);
473                                 return (unsigned char *)0;
474                         }
475                         token = next_token (&val, (unsigned *)0, cfile);
476                 }
477                 token = next_token (&val, (unsigned *)0, cfile);
478
479                 if (token == END_OF_FILE) {
480                         parse_warn (cfile, "unexpected end of file");
481                         break;
482                 }
483
484                 /* Allow NUMBER_OR_NAME if base is 16. */
485                 if (token != NUMBER &&
486                     (base != 16 || token != NUMBER_OR_NAME)) {
487                         parse_warn (cfile, "expecting numeric value.");
488                         skip_to_semi (cfile);
489                         return (unsigned char *)0;
490                 }
491                 /* If we can, convert the number now; otherwise, build
492                    a linked list of all the numbers. */
493                 if (s) {
494                         convert_num (cfile, s, val, base, size);
495                         s += size / 8;
496                 } else {
497                         t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
498                         if (!t)
499                                 log_fatal ("no temp space for number.");
500                         strcpy ((char *)t, val);
501                         c = cons ((caddr_t)t, c);
502                 }
503         } while (++count != *max);
504
505         /* If we had to cons up a list, convert it now. */
506         if (c) {
507                 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
508                 if (!bufp)
509                         log_fatal ("no space for numeric aggregate.");
510                 s = bufp + count - size / 8;
511                 *max = count;
512         }
513         while (c) {
514                 pair cdr = c -> cdr;
515                 convert_num (cfile, s, (char *)(c -> car), base, size);
516                 s -= size / 8;
517                 /* Free up temp space. */
518                 dfree (c -> car, MDL);
519                 dfree (c, MDL);
520                 c = cdr;
521         }
522         return bufp;
523 }
524
525 void convert_num (cfile, buf, str, base, size)
526         struct parse *cfile;
527         unsigned char *buf;
528         const char *str;
529         int base;
530         unsigned size;
531 {
532         const char *ptr = str;
533         int negative = 0;
534         u_int32_t val = 0;
535         int tval;
536         int max;
537
538         if (*ptr == '-') {
539                 negative = 1;
540                 ++ptr;
541         }
542
543         /* If base wasn't specified, figure it out from the data. */
544         if (!base) {
545                 if (ptr [0] == '0') {
546                         if (ptr [1] == 'x') {
547                                 base = 16;
548                                 ptr += 2;
549                         } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
550                                 base = 8;
551                                 ptr += 1;
552                         } else {
553                                 base = 10;
554                         }
555                 } else {
556                         base = 10;
557                 }
558         }
559
560         do {
561                 tval = *ptr++;
562                 /* XXX assumes ASCII... */
563                 if (tval >= 'a')
564                         tval = tval - 'a' + 10;
565                 else if (tval >= 'A')
566                         tval = tval - 'A' + 10;
567                 else if (tval >= '0')
568                         tval -= '0';
569                 else {
570                         parse_warn (cfile, "Bogus number: %s.", str);
571                         break;
572                 }
573                 if (tval >= base) {
574                         parse_warn (cfile,
575                                     "Bogus number %s: digit %d not in base %d",
576                                     str, tval, base);
577                         break;
578                 }
579                 val = val * base + tval;
580         } while (*ptr);
581
582         if (negative)
583                 max = (1 << (size - 1));
584         else
585                 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
586         if (val > max) {
587                 switch (base) {
588                       case 8:
589                         parse_warn (cfile,
590                                     "%s%lo exceeds max (%d) for precision.",
591                                     negative ? "-" : "",
592                                     (unsigned long)val, max);
593                         break;
594                       case 16:
595                         parse_warn (cfile,
596                                     "%s%lx exceeds max (%d) for precision.",
597                                     negative ? "-" : "",
598                                     (unsigned long)val, max);
599                         break;
600                       default:
601                         parse_warn (cfile,
602                                     "%s%lu exceeds max (%d) for precision.",
603                                     negative ? "-" : "",
604                                     (unsigned long)val, max);
605                         break;
606                 }
607         }
608
609         if (negative) {
610                 switch (size) {
611                       case 8:
612                         *buf = -(unsigned long)val;
613                         break;
614                       case 16:
615                         putShort (buf, -(long)val);
616                         break;
617                       case 32:
618                         putLong (buf, -(long)val);
619                         break;
620                       default:
621                         parse_warn (cfile,
622                                     "Unexpected integer size: %d\n", size);
623                         break;
624                 }
625         } else {
626                 switch (size) {
627                       case 8:
628                         *buf = (u_int8_t)val;
629                         break;
630                       case 16:
631                         putUShort (buf, (u_int16_t)val);
632                         break;
633                       case 32:
634                         putULong (buf, val);
635                         break;
636                       default:
637                         parse_warn (cfile,
638                                     "Unexpected integer size: %d\n", size);
639                         break;
640                 }
641         }
642 }
643
644 /*
645  * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER 
646  *              NUMBER COLON NUMBER COLON NUMBER SEMI |
647  *          NUMBER NUMBER SLASH NUMBER SLASH NUMBER 
648  *              NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
649  *          NEVER
650  *
651  * Dates are stored in GMT or with a timezone offset; first number is day
652  * of week; next is year/month/day; next is hours:minutes:seconds on a
653  * 24-hour clock, followed by the timezone offset in seconds, which is
654  * optional.
655  */
656
657 TIME parse_date (cfile)
658         struct parse *cfile;
659 {
660         struct tm tm;
661         int guess;
662         int tzoff, wday, year, mon, mday, hour, min, sec;
663         const char *val;
664         enum dhcp_token token;
665         static int months [11] = { 31, 59, 90, 120, 151, 181,
666                                           212, 243, 273, 304, 334 };
667
668         /* Day of week, or "never"... */
669         token = next_token (&val, (unsigned *)0, cfile);
670         if (token == NEVER) {
671                 if (!parse_semi (cfile))
672                         return 0;
673                 return MAX_TIME;
674         }
675
676         if (token != NUMBER) {
677                 parse_warn (cfile, "numeric day of week expected.");
678                 if (token != SEMI)
679                         skip_to_semi (cfile);
680                 return (TIME)0;
681         }
682         wday = atoi (val);
683
684         /* Year... */
685         token = next_token (&val, (unsigned *)0, cfile);
686         if (token != NUMBER) {
687                 parse_warn (cfile, "numeric year expected.");
688                 if (token != SEMI)
689                         skip_to_semi (cfile);
690                 return (TIME)0;
691         }
692
693         /* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until
694            somebody invents a time machine, I think we can safely disregard
695            it.   This actually works around a stupid Y2K bug that was present
696            in a very early beta release of dhcpd. */
697         year = atoi (val);
698         if (year > 1900)
699                 year -= 1900;
700
701         /* Slash seperating year from month... */
702         token = next_token (&val, (unsigned *)0, cfile);
703         if (token != SLASH) {
704                 parse_warn (cfile,
705                             "expected slash seperating year from month.");
706                 if (token != SEMI)
707                         skip_to_semi (cfile);
708                 return (TIME)0;
709         }
710
711         /* Month... */
712         token = next_token (&val, (unsigned *)0, cfile);
713         if (token != NUMBER) {
714                 parse_warn (cfile, "numeric month expected.");
715                 if (token != SEMI)
716                         skip_to_semi (cfile);
717                 return (TIME)0;
718         }
719         mon = atoi (val) - 1;
720
721         /* Slash seperating month from day... */
722         token = next_token (&val, (unsigned *)0, cfile);
723         if (token != SLASH) {
724                 parse_warn (cfile,
725                             "expected slash seperating month from day.");
726                 if (token != SEMI)
727                         skip_to_semi (cfile);
728                 return (TIME)0;
729         }
730
731         /* Month... */
732         token = next_token (&val, (unsigned *)0, cfile);
733         if (token != NUMBER) {
734                 parse_warn (cfile, "numeric day of month expected.");
735                 if (token != SEMI)
736                         skip_to_semi (cfile);
737                 return (TIME)0;
738         }
739         mday = atoi (val);
740
741         /* Hour... */
742         token = next_token (&val, (unsigned *)0, cfile);
743         if (token != NUMBER) {
744                 parse_warn (cfile, "numeric hour expected.");
745                 if (token != SEMI)
746                         skip_to_semi (cfile);
747                 return (TIME)0;
748         }
749         hour = atoi (val);
750
751         /* Colon seperating hour from minute... */
752         token = next_token (&val, (unsigned *)0, cfile);
753         if (token != COLON) {
754                 parse_warn (cfile,
755                             "expected colon seperating hour from minute.");
756                 if (token != SEMI)
757                         skip_to_semi (cfile);
758                 return (TIME)0;
759         }
760
761         /* Minute... */
762         token = next_token (&val, (unsigned *)0, cfile);
763         if (token != NUMBER) {
764                 parse_warn (cfile, "numeric minute expected.");
765                 if (token != SEMI)
766                         skip_to_semi (cfile);
767                 return (TIME)0;
768         }
769         min = atoi (val);
770
771         /* Colon seperating minute from second... */
772         token = next_token (&val, (unsigned *)0, cfile);
773         if (token != COLON) {
774                 parse_warn (cfile,
775                             "expected colon seperating hour from minute.");
776                 if (token != SEMI)
777                         skip_to_semi (cfile);
778                 return (TIME)0;
779         }
780
781         /* Minute... */
782         token = next_token (&val, (unsigned *)0, cfile);
783         if (token != NUMBER) {
784                 parse_warn (cfile, "numeric minute expected.");
785                 if (token != SEMI)
786                         skip_to_semi (cfile);
787                 return (TIME)0;
788         }
789         sec = atoi (val);
790
791         token = peek_token (&val, (unsigned *)0, cfile);
792         if (token == NUMBER) {
793                 token = next_token (&val, (unsigned *)0, cfile);
794                 tzoff = atoi (val);
795         } else
796                 tzoff = 0;
797
798         /* Make sure the date ends in a semicolon... */
799         if (!parse_semi (cfile))
800                 return 0;
801
802         /* Guess the time value... */
803         guess = ((((((365 * (year - 70) +       /* Days in years since '70 */
804                       (year - 69) / 4 +         /* Leap days since '70 */
805                       (mon                      /* Days in months this year */
806                        ? months [mon - 1]
807                        : 0) +
808                       (mon > 1 &&               /* Leap day this year */
809                        !((year - 72) & 3)) +
810                       mday - 1) * 24) +         /* Day of month */
811                     hour) * 60) +
812                   min) * 60) + sec + tzoff;
813
814         /* This guess could be wrong because of leap seconds or other
815            weirdness we don't know about that the system does.   For
816            now, we're just going to accept the guess, but at some point
817            it might be nice to do a successive approximation here to
818            get an exact value.   Even if the error is small, if the
819            server is restarted frequently (and thus the lease database
820            is reread), the error could accumulate into something
821            significant. */
822
823         return guess;
824 }
825
826 /*
827  * option-name :== IDENTIFIER |
828                    IDENTIFIER . IDENTIFIER
829  */
830
831 struct option *parse_option_name (cfile, allocate, known)
832         struct parse *cfile;
833         int allocate;
834         int *known;
835 {
836         const char *val;
837         enum dhcp_token token;
838         char *uname;
839         struct universe *universe;
840         struct option *option;
841
842         token = next_token (&val, (unsigned *)0, cfile);
843         if (!is_identifier (token)) {
844                 parse_warn (cfile,
845                             "expecting identifier after option keyword.");
846                 if (token != SEMI)
847                         skip_to_semi (cfile);
848                 return (struct option *)0;
849         }
850         uname = dmalloc (strlen (val) + 1, MDL);
851         if (!uname)
852                 log_fatal ("no memory for uname information.");
853         strcpy (uname, val);
854         token = peek_token (&val, (unsigned *)0, cfile);
855         if (token == DOT) {
856                 /* Go ahead and take the DOT token... */
857                 token = next_token (&val, (unsigned *)0, cfile);
858
859                 /* The next token should be an identifier... */
860                 token = next_token (&val, (unsigned *)0, cfile);
861                 if (!is_identifier (token)) {
862                         parse_warn (cfile, "expecting identifier after '.'");
863                         if (token != SEMI)
864                                 skip_to_semi (cfile);
865                         return (struct option *)0;
866                 }
867
868                 /* Look up the option name hash table for the specified
869                    uname. */
870                 universe = (struct universe *)0;
871                 if (!universe_hash_lookup (&universe, universe_hash,
872                                            uname, 0, MDL)) {
873                         parse_warn (cfile, "no option space named %s.", uname);
874                         skip_to_semi (cfile);
875                         return (struct option *)0;
876                 }
877         } else {
878                 /* Use the default hash table, which contains all the
879                    standard dhcp option names. */
880                 val = uname;
881                 universe = &dhcp_universe;
882         }
883
884         /* Look up the actual option info... */
885         option = (struct option *)0;
886         option_hash_lookup (&option, universe -> hash, val, 0, MDL);
887
888         /* If we didn't get an option structure, it's an undefined option. */
889         if (option) {
890                 if (known)
891                         *known = 1;
892         } else {
893                 /* If we've been told to allocate, that means that this
894                    (might) be an option code definition, so we'll create
895                    an option structure just in case. */
896                 if (allocate) {
897                         option = new_option (MDL);
898                         if (val == uname)
899                                 option -> name = val;
900                         else {
901                                 char *s;
902                                 dfree (uname, MDL);
903                                 s = dmalloc (strlen (val) + 1, MDL);
904                                 if (!s)
905                                     log_fatal ("no memory for option %s.%s",
906                                                universe -> name, val);
907                                 strcpy (s, val);
908                                 option -> name = s;
909                         }
910                         option -> universe = universe;
911                         option -> code = 0;
912                         return option;
913                 }
914                 if (val == uname)
915                         parse_warn (cfile, "no option named %s", val);
916                 else
917                         parse_warn (cfile, "no option named %s in space %s",
918                                     val, uname);
919                 skip_to_semi (cfile);
920                 return (struct option *)0;
921         }
922
923         /* Free the initial identifier token. */
924         dfree (uname, MDL);
925         return option;
926 }
927
928 /* IDENTIFIER SEMI */
929
930 void parse_option_space_decl (cfile)
931         struct parse *cfile;
932 {
933         int token;
934         const char *val;
935         struct universe **ua, *nu;
936         char *s;
937
938         next_token (&val, (unsigned *)0, cfile);  /* Discard the SPACE token,
939                                                      which was checked by the
940                                                      caller. */
941         token = next_token (&val, (unsigned *)0, cfile);
942         if (!is_identifier (token)) {
943                 parse_warn (cfile, "expecting identifier.");
944                 skip_to_semi (cfile);
945                 return;
946         }
947         nu = new_universe (MDL);
948         if (!nu)
949                 log_fatal ("No memory for new option space.");
950
951         /* Set up the server option universe... */
952         s = dmalloc (strlen (val) + 1, MDL);
953         if (!s)
954                 log_fatal ("No memory for new option space name.");
955         strcpy (s, val);
956         nu -> name = s;
957         nu -> lookup_func = lookup_hashed_option;
958         nu -> option_state_dereference =
959                 hashed_option_state_dereference;
960         nu -> foreach = hashed_option_space_foreach;
961         nu -> save_func = save_hashed_option;
962         nu -> delete_func = delete_hashed_option;
963         nu -> encapsulate = hashed_option_space_encapsulate;
964         nu -> decode = parse_option_buffer;
965         nu -> length_size = 1;
966         nu -> tag_size = 1;
967         nu -> store_tag = putUChar;
968         nu -> store_length = putUChar;
969         nu -> index = universe_count++;
970         if (nu -> index >= universe_max) {
971                 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
972                 if (!ua)
973                         log_fatal ("No memory to expand option space array.");
974                 memcpy (ua, universes, universe_max * sizeof *ua);
975                 universe_max *= 2;
976                 dfree (universes, MDL);
977                 universes = ua;
978         }
979         universes [nu -> index] = nu;
980         option_new_hash (&nu -> hash, 1, MDL);
981         if (!nu -> hash)
982                 log_fatal ("Can't allocate %s option hash table.", nu -> name);
983         universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
984         parse_semi (cfile);
985 }
986
987 /* This is faked up to look good right now.   Ideally, this should do a
988    recursive parse and allow arbitrary data structure definitions, but for
989    now it just allows you to specify a single type, an array of single types,
990    a sequence of types, or an array of sequences of types.
991
992    ocd :== NUMBER EQUALS ocsd SEMI
993
994    ocsd :== ocsd_type |
995             ocsd_type_sequence |
996             ARRAY OF ocsd_simple_type_sequence
997
998    ocsd_type_sequence :== LBRACE ocsd_types RBRACE
999
1000    ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1001
1002    ocsd_types :== ocsd_type |
1003                   ocsd_types ocsd_type
1004
1005    ocsd_type :== ocsd_simple_type |
1006                  ARRAY OF ocsd_simple_type
1007
1008    ocsd_simple_types :== ocsd_simple_type |
1009                          ocsd_simple_types ocsd_simple_type
1010
1011    ocsd_simple_type :== BOOLEAN |
1012                         INTEGER NUMBER |
1013                         SIGNED INTEGER NUMBER |
1014                         UNSIGNED INTEGER NUMBER |
1015                         IP-ADDRESS |
1016                         TEXT |
1017                         STRING |
1018                         ENCAPSULATE identifier */
1019
1020 int parse_option_code_definition (cfile, option)
1021         struct parse *cfile;
1022         struct option *option;
1023 {
1024         const char *val;
1025         enum dhcp_token token;
1026         unsigned arrayp = 0;
1027         int recordp = 0;
1028         int no_more_in_record = 0;
1029         char tokbuf [128];
1030         unsigned tokix = 0;
1031         char type;
1032         int code;
1033         int is_signed;
1034         char *s;
1035         int has_encapsulation = 0;
1036         
1037         /* Parse the option code. */
1038         token = next_token (&val, (unsigned *)0, cfile);
1039         if (token != NUMBER) {
1040                 parse_warn (cfile, "expecting option code number.");
1041                 skip_to_semi (cfile);
1042                 return 0;
1043         }
1044         option -> code = atoi (val);
1045
1046         token = next_token (&val, (unsigned *)0, cfile);
1047         if (token != EQUAL) {
1048                 parse_warn (cfile, "expecting \"=\"");
1049                 skip_to_semi (cfile);
1050                 return 0;
1051         }
1052
1053         /* See if this is an array. */
1054         token = next_token (&val, (unsigned *)0, cfile);
1055         if (token == ARRAY) {
1056                 token = next_token (&val, (unsigned *)0, cfile);
1057                 if (token != OF) {
1058                         parse_warn (cfile, "expecting \"of\".");
1059                         skip_to_semi (cfile);
1060                         return 0;
1061                 }
1062                 arrayp = 1;
1063                 token = next_token (&val, (unsigned *)0, cfile);
1064         }
1065
1066         if (token == LBRACE) {
1067                 recordp = 1;
1068                 token = next_token (&val, (unsigned *)0, cfile);
1069         }
1070
1071         /* At this point we're expecting a data type. */
1072       next_type:
1073         if (has_encapsulation) {
1074                 parse_warn (cfile,
1075                             "encapsulate must always be the last item.");
1076                 skip_to_semi (cfile);
1077                 return 0;
1078         }
1079
1080         switch (token) {
1081               case ARRAY:
1082                 if (arrayp) {
1083                         parse_warn (cfile, "no nested arrays.");
1084                         skip_to_rbrace (cfile, recordp);
1085                         if (recordp)
1086                                 skip_to_semi (cfile);
1087                         return 0;
1088                 }
1089                 token = next_token (&val, (unsigned *)0, cfile);
1090                 if (token != OF) {
1091                         parse_warn (cfile, "expecting \"of\".");
1092                         skip_to_semi (cfile);
1093                         return 0;
1094                 }
1095                 arrayp = recordp + 1;
1096                 token = next_token (&val, (unsigned *)0, cfile);
1097                 if ((recordp) && (token == LBRACE)) {
1098                         parse_warn (cfile,
1099                                     "only uniform array inside record.");
1100                         skip_to_rbrace (cfile, recordp + 1);
1101                         skip_to_semi (cfile);
1102                         return 0;
1103                 }
1104                 goto next_type;
1105               case BOOLEAN:
1106                 type = 'f';
1107                 break;
1108               case INTEGER:
1109                 is_signed = 1;
1110               parse_integer:
1111                 token = next_token (&val, (unsigned *)0, cfile);
1112                 if (token != NUMBER) {
1113                         parse_warn (cfile, "expecting number.");
1114                         skip_to_rbrace (cfile, recordp);
1115                         if (recordp)
1116                                 skip_to_semi (cfile);
1117                         return 0;
1118                 }
1119                 switch (atoi (val)) {
1120                       case 8:
1121                         type = is_signed ? 'b' : 'B';
1122                         break;
1123                       case 16:
1124                         type = is_signed ? 's' : 'S';
1125                         break;
1126                       case 32:
1127                         type = is_signed ? 'l' : 'L';
1128                         break;
1129                       default:
1130                         parse_warn (cfile,
1131                                     "%s bit precision is not supported.", val);
1132                         skip_to_rbrace (cfile, recordp);
1133                         if (recordp)
1134                                 skip_to_semi (cfile);
1135                         return 0;
1136                 }
1137                 break;
1138               case SIGNED:
1139                 is_signed = 1;
1140               parse_signed:
1141                 token = next_token (&val, (unsigned *)0, cfile);
1142                 if (token != INTEGER) {
1143                         parse_warn (cfile, "expecting \"integer\" keyword.");
1144                         skip_to_rbrace (cfile, recordp);
1145                         if (recordp)
1146                                 skip_to_semi (cfile);
1147                         return 0;
1148                 }
1149                 goto parse_integer;
1150               case UNSIGNED:
1151                 is_signed = 0;
1152                 goto parse_signed;
1153
1154               case IP_ADDRESS:
1155                 type = 'I';
1156                 break;
1157               case DOMAIN_NAME:
1158                 type = 'd';
1159                 goto no_arrays;
1160               case TEXT:
1161                 type = 't';
1162               no_arrays:
1163                 if (arrayp) {
1164                         parse_warn (cfile, "arrays of text strings not %s",
1165                                     "yet supported.");
1166                         skip_to_rbrace (cfile, recordp);
1167                         if (recordp)
1168                                 skip_to_semi (cfile);
1169                         return 0;
1170                 }
1171                 no_more_in_record = 1;
1172                 break;
1173               case STRING_TOKEN:
1174                 type = 'X';
1175                 goto no_arrays;
1176
1177               case ENCAPSULATE:
1178                 token = next_token (&val, (unsigned *)0, cfile);
1179                 if (!is_identifier (token)) {
1180                         parse_warn (cfile,
1181                                     "expecting option space identifier");
1182                         skip_to_semi (cfile);
1183                         return 0;
1184                 }
1185                 if (strlen (val) + tokix + 2 > sizeof (tokbuf))
1186                         goto toobig;
1187                 tokbuf [tokix++] = 'E';
1188                 strcpy (&tokbuf [tokix], val);
1189                 tokix += strlen (val);
1190                 type = '.';
1191                 has_encapsulation = 1;
1192                 break;
1193
1194               default:
1195                 parse_warn (cfile, "unknown data type %s", val);
1196                 skip_to_rbrace (cfile, recordp);
1197                 if (recordp)
1198                         skip_to_semi (cfile);
1199                 return 0;
1200         }
1201
1202         if (tokix == sizeof tokbuf) {
1203               toobig:
1204                 parse_warn (cfile, "too many types in record.");
1205                 skip_to_rbrace (cfile, recordp);
1206                 if (recordp)
1207                         skip_to_semi (cfile);
1208                 return 0;
1209         }
1210         tokbuf [tokix++] = type;
1211
1212         if (recordp) {
1213                 token = next_token (&val, (unsigned *)0, cfile);
1214                 if (arrayp > recordp) {
1215                         if (tokix == sizeof tokbuf) {
1216                                 parse_warn (cfile,
1217                                             "too many types in record.");
1218                                 skip_to_rbrace (cfile, 1);
1219                                 skip_to_semi (cfile);
1220                                 return 0;
1221                         }
1222                         arrayp = 0;
1223                         tokbuf[tokix++] = 'a';
1224                 }
1225                 if (token == COMMA) {
1226                         if (no_more_in_record) {
1227                                 parse_warn (cfile,
1228                                             "%s must be at end of record.",
1229                                             type == 't' ? "text" : "string");
1230                                 skip_to_rbrace (cfile, 1);
1231                                 if (recordp)
1232                                         skip_to_semi (cfile);
1233                                 return 0;
1234                         }
1235                         token = next_token (&val, (unsigned *)0, cfile);
1236                         goto next_type;
1237                 }
1238                 if (token != RBRACE) {
1239                         parse_warn (cfile, "expecting right brace.");
1240                         skip_to_rbrace (cfile, 1);
1241                         if (recordp)
1242                                 skip_to_semi (cfile);
1243                         return 0;
1244                 }
1245         }
1246         if (!parse_semi (cfile)) {
1247                 parse_warn (cfile, "semicolon expected.");
1248                 skip_to_semi (cfile);
1249                 if (recordp)
1250                         skip_to_semi (cfile);
1251                 return 0;
1252         }
1253         if (has_encapsulation && arrayp) {
1254                 parse_warn (cfile,
1255                             "Arrays of encapsulations don't make sense.");
1256                 return 0;
1257         }
1258         if (has_encapsulation && tokbuf [0] == 'E')
1259                 has_encapsulation = 0;
1260         s = dmalloc (tokix +
1261                      (arrayp ? 1 : 0) +
1262                      (has_encapsulation ? 1 : 0) + 1, MDL);
1263         if (!s)
1264                 log_fatal ("no memory for option format.");
1265         if (has_encapsulation)
1266                 s [0] = 'e';
1267         memcpy (s + has_encapsulation, tokbuf, tokix);
1268         tokix += has_encapsulation;
1269         if (arrayp)
1270                 s [tokix++] = (arrayp > recordp) ? 'a' : 'A';
1271         s [tokix] = 0;
1272         option -> format = s;
1273         if (option -> universe -> options [option -> code]) {
1274                 /* XXX Free the option, but we can't do that now because they
1275                    XXX may start out static. */
1276         }
1277         option -> universe -> options [option -> code] = option;
1278         option_hash_add (option -> universe -> hash,
1279                          (const char *)option -> name,
1280                          0, option, MDL);
1281         return 1;
1282 }
1283
1284 /*
1285  * base64 :== NUMBER_OR_STRING
1286  */
1287
1288 int parse_base64 (data, cfile)
1289         struct data_string *data;
1290         struct parse *cfile;
1291 {
1292         enum dhcp_token token;
1293         const char *val;
1294         int i, j, k;
1295         unsigned acc = 0;
1296         static unsigned char
1297                 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64,  /*  \"#$%&' */
1298                              64, 64, 64, 62, 64, 64, 64, 63,  /* ()*+,-./ */
1299                              52, 53, 54, 55, 56, 57, 58, 59,  /* 01234567 */
1300                              60, 61, 64, 64, 64, 64, 64, 64,  /* 89:;<=>? */
1301                              64, 0, 1, 2, 3, 4, 5, 6,         /* @ABCDEFG */
1302                              7, 8, 9, 10, 11, 12, 13, 14,     /* HIJKLMNO */
1303                              15, 16, 17, 18, 19, 20, 21, 22,  /* PQRSTUVW */
1304                              23, 24, 25, 64, 64, 64, 64, 64,  /* XYZ[\]^_ */
1305                              64, 26, 27, 28, 29, 30, 31, 32,  /* 'abcdefg */
1306                              33, 34, 35, 36, 37, 38, 39, 40,  /* hijklmno */
1307                              41, 42, 43, 44, 45, 46, 47, 48,  /* pqrstuvw */
1308                              49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~  */
1309         struct string_list *bufs = (struct string_list *)0,
1310                            *last = (struct string_list *)0,
1311                            *t;
1312         int cc = 0;
1313         int terminated = 0;
1314         
1315         /* It's possible for a + or a / to cause a base64 quantity to be
1316            tokenized into more than one token, so we have to parse them all
1317            in before decoding. */
1318         do {
1319                 unsigned l;
1320
1321                 token = next_token (&val, &l, cfile);
1322                 t = dmalloc (l + sizeof *t, MDL);
1323                 if (!t)
1324                         log_fatal ("no memory for base64 buffer.");
1325                 memset (t, 0, (sizeof *t) - 1);
1326                 memcpy (t -> string, val, l + 1);
1327                 cc += l;
1328                 if (last)
1329                         last -> next = t;
1330                 else
1331                         bufs = t;
1332                 last = t;
1333                 token = peek_token (&val, (unsigned *)0, cfile);
1334         } while (token == NUMBER_OR_NAME || token == NAME || token == EQUAL ||
1335                  token == NUMBER || token == PLUS || token == SLASH ||
1336                  token == STRING);
1337
1338         data -> len = cc;
1339         data -> len = (data -> len * 3) / 4;
1340         if (!buffer_allocate (&data -> buffer, data -> len, MDL)) {
1341                 parse_warn (cfile, "can't allocate buffer for base64 data.");
1342                 data -> len = 0;
1343                 data -> data = (unsigned char *)0;
1344                 return 0;
1345         }
1346                 
1347         j = k = 0;
1348         for (t = bufs; t; t = t -> next) {
1349             for (i = 0; t -> string [i]; i++) {
1350                 unsigned foo = t -> string [i];
1351                 if (terminated && foo != '=') {
1352                         parse_warn (cfile,
1353                                     "stuff after base64 '=' terminator: %s.",
1354                                     &t -> string [i]);
1355                         goto bad;
1356                 }
1357                 if (foo < ' ' || foo > 'z') {
1358                       bad64:
1359                         parse_warn (cfile,
1360                                     "invalid base64 character %d.",
1361                                     t -> string [i]);
1362                       bad:
1363                         data_string_forget (data, MDL);
1364                         goto out;
1365                 }
1366                 if (foo == '=')
1367                         terminated = 1;
1368                 else {
1369                         foo = from64 [foo - ' '];
1370                         if (foo == 64)
1371                                 goto bad64;
1372                         acc = (acc << 6) + foo;
1373                         switch (k % 4) {
1374                               case 0:
1375                                 break;
1376                               case 1:
1377                                 data -> buffer -> data [j++] = (acc >> 4);
1378                                 acc = acc & 0x0f;
1379                                 break;
1380                                 
1381                               case 2:
1382                                 data -> buffer -> data [j++] = (acc >> 2);
1383                                 acc = acc & 0x03;
1384                                 break;
1385                               case 3:
1386                                 data -> buffer -> data [j++] = acc;
1387                                 acc = 0;
1388                                 break;
1389                         }
1390                 }
1391                 k++;
1392             }
1393         }
1394         if (k % 4) {
1395                 if (acc) {
1396                         parse_warn (cfile,
1397                                     "partial base64 value left over: %d.",
1398                                     acc);
1399                 }
1400         }
1401         data -> len = j;
1402         data -> data = data -> buffer -> data;
1403       out:
1404         for (t = bufs; t; t = last) {
1405                 last = t -> next;
1406                 dfree (t, MDL);
1407         }
1408         if (data -> len)
1409                 return 1;
1410         else
1411                 return 0;
1412 }
1413
1414
1415 /*
1416  * colon-seperated-hex-list :== NUMBER |
1417  *                              NUMBER COLON colon-seperated-hex-list
1418  */
1419
1420 int parse_cshl (data, cfile)
1421         struct data_string *data;
1422         struct parse *cfile;
1423 {
1424         u_int8_t ibuf [128];
1425         unsigned ilen = 0;
1426         unsigned tlen = 0;
1427         struct option_tag *sl = (struct option_tag *)0;
1428         struct option_tag *next, **last = &sl;
1429         enum dhcp_token token;
1430         const char *val;
1431         unsigned char *rvp;
1432
1433         do {
1434                 token = next_token (&val, (unsigned *)0, cfile);
1435                 if (token != NUMBER && token != NUMBER_OR_NAME) {
1436                         parse_warn (cfile, "expecting hexadecimal number.");
1437                         skip_to_semi (cfile);
1438                         for (; sl; sl = next) {
1439                                 next = sl -> next;
1440                                 dfree (sl, MDL);
1441                         }
1442                         return 0;
1443                 }
1444                 if (ilen == sizeof ibuf) {
1445                         next = (struct option_tag *)
1446                                 dmalloc (ilen - 1 +
1447                                          sizeof (struct option_tag), MDL);
1448                         if (!next)
1449                                 log_fatal ("no memory for string list.");
1450                         memcpy (next -> data, ibuf, ilen);
1451                         *last = next;
1452                         last = &next -> next;
1453                         tlen += ilen;
1454                         ilen = 0;
1455                 }
1456                 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
1457
1458                 token = peek_token (&val, (unsigned *)0, cfile);
1459                 if (token != COLON)
1460                         break;
1461                 token = next_token (&val, (unsigned *)0, cfile);
1462         } while (1);
1463
1464         if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
1465                 log_fatal ("no memory to store octet data.");
1466         data -> data = &data -> buffer -> data [0];
1467         data -> len = tlen + ilen;
1468         data -> terminated = 0;
1469
1470         rvp = &data -> buffer -> data [0];
1471         while (sl) {
1472                 next = sl -> next;
1473                 memcpy (rvp, sl -> data, sizeof ibuf);
1474                 rvp += sizeof ibuf;
1475                 dfree (sl, MDL);
1476                 sl = next;
1477         }
1478         
1479         memcpy (rvp, ibuf, ilen);
1480         return 1;
1481 }
1482
1483 /*
1484  * executable-statements :== executable-statement executable-statements |
1485  *                           executable-statement
1486  *
1487  * executable-statement :==
1488  *      IF if-statement |
1489  *      ADD class-name SEMI |
1490  *      BREAK SEMI |
1491  *      OPTION option-parameter SEMI |
1492  *      SUPERSEDE option-parameter SEMI |
1493  *      PREPEND option-parameter SEMI |
1494  *      APPEND option-parameter SEMI
1495  */
1496
1497 int parse_executable_statements (statements, cfile, lose, case_context)
1498         struct executable_statement **statements;
1499         struct parse *cfile;
1500         int *lose;
1501         enum expression_context case_context;
1502 {
1503         struct executable_statement **next;
1504
1505         next = statements;
1506         while (parse_executable_statement (next, cfile, lose, case_context))
1507                 next = &((*next) -> next);
1508         if (!*lose)
1509                 return 1;
1510         return 0;
1511 }
1512
1513 int parse_executable_statement (result, cfile, lose, case_context)
1514         struct executable_statement **result;
1515         struct parse *cfile;
1516         int *lose;
1517         enum expression_context case_context;
1518 {
1519         enum dhcp_token token;
1520         const char *val;
1521         struct executable_statement base;
1522         struct class *cta;
1523         struct option *option;
1524         struct option_cache *cache;
1525         int known;
1526         int flag;
1527         int i;
1528         struct dns_zone *zone;
1529         isc_result_t status;
1530         char *s;
1531
1532         token = peek_token (&val, (unsigned *)0, cfile);
1533         switch (token) {
1534               case IF:
1535                 next_token (&val, (unsigned *)0, cfile);
1536                 return parse_if_statement (result, cfile, lose);
1537
1538               case TOKEN_ADD:
1539                 token = next_token (&val, (unsigned *)0, cfile);
1540                 token = next_token (&val, (unsigned *)0, cfile);
1541                 if (token != STRING) {
1542                         parse_warn (cfile, "expecting class name.");
1543                         skip_to_semi (cfile);
1544                         *lose = 1;
1545                         return 0;
1546                 }
1547                 cta = (struct class *)0;
1548                 status = find_class (&cta, val, MDL);
1549                 if (status != ISC_R_SUCCESS) {
1550                         parse_warn (cfile, "class %s: %s",
1551                                     val, isc_result_totext (status));
1552                         skip_to_semi (cfile);
1553                         *lose = 1;
1554                         return 0;
1555                 }
1556                 if (!parse_semi (cfile)) {
1557                         *lose = 1;
1558                         return 0;
1559                 }
1560                 if (!executable_statement_allocate (result, MDL))
1561                         log_fatal ("no memory for new statement.");
1562                 (*result) -> op = add_statement;
1563                 (*result) -> data.add = cta;
1564                 break;
1565
1566               case BREAK:
1567                 token = next_token (&val, (unsigned *)0, cfile);
1568                 if (!parse_semi (cfile)) {
1569                         *lose = 1;
1570                         return 0;
1571                 }
1572                 if (!executable_statement_allocate (result, MDL))
1573                         log_fatal ("no memory for new statement.");
1574                 (*result) -> op = break_statement;
1575                 break;
1576
1577               case SEND:
1578                 token = next_token (&val, (unsigned *)0, cfile);
1579                 known = 0;
1580                 option = parse_option_name (cfile, 0, &known);
1581                 if (!option) {
1582                         *lose = 1;
1583                         return 0;
1584                 }
1585                 return parse_option_statement (result, cfile, 1, option,
1586                                                send_option_statement);
1587
1588               case SUPERSEDE:
1589               case OPTION:
1590                 token = next_token (&val, (unsigned *)0, cfile);
1591                 known = 0;
1592                 option = parse_option_name (cfile, 0, &known);
1593                 if (!option) {
1594                         *lose = 1;
1595                         return 0;
1596                 }
1597                 return parse_option_statement (result, cfile, 1, option,
1598                                                supersede_option_statement);
1599
1600               case ALLOW:
1601                 flag = 1;
1602                 goto pad;
1603               case DENY:
1604                 flag = 0;
1605                 goto pad;
1606               case IGNORE:
1607                 flag = 2;
1608               pad:
1609                 token = next_token (&val, (unsigned *)0, cfile);
1610                 cache = (struct option_cache *)0;
1611                 if (!parse_allow_deny (&cache, cfile, flag))
1612                         return 0;
1613                 if (!executable_statement_allocate (result, MDL))
1614                         log_fatal ("no memory for new statement.");
1615                 (*result) -> op = supersede_option_statement;
1616                 (*result) -> data.option = cache;
1617                 break;
1618
1619               case DEFAULT:
1620                 token = next_token (&val, (unsigned *)0, cfile);
1621                 token = peek_token (&val, (unsigned *)0, cfile);
1622                 if (token == COLON)
1623                         goto switch_default;
1624                 known = 0;
1625                 option = parse_option_name (cfile, 0, &known);
1626                 if (!option) {
1627                         *lose = 1;
1628                         return 0;
1629                 }
1630                 return parse_option_statement (result, cfile, 1, option,
1631                                                default_option_statement);
1632
1633               case PREPEND:
1634                 token = next_token (&val, (unsigned *)0, cfile);
1635                 known = 0;
1636                 option = parse_option_name (cfile, 0, &known);
1637                 if (!option) {
1638                         *lose = 1;
1639                         return 0;
1640                 }
1641                 return parse_option_statement (result, cfile, 1, option,
1642                                                prepend_option_statement);
1643
1644               case APPEND:
1645                 token = next_token (&val, (unsigned *)0, cfile);
1646                 known = 0;
1647                 option = parse_option_name (cfile, 0, &known);
1648                 if (!option) {
1649                         *lose = 1;
1650                         return 0;
1651                 }
1652                 return parse_option_statement (result, cfile, 1, option,
1653                                                append_option_statement);
1654
1655               case ON:
1656                 token = next_token (&val, (unsigned *)0, cfile);
1657                 return parse_on_statement (result, cfile, lose);
1658                         
1659               case SWITCH:
1660                 token = next_token (&val, (unsigned *)0, cfile);
1661                 return parse_switch_statement (result, cfile, lose);
1662
1663               case CASE:
1664                 token = next_token (&val, (unsigned *)0, cfile);
1665                 if (case_context == context_any) {
1666                         parse_warn (cfile,
1667                                     "case statement in inappropriate scope.");
1668                         *lose = 1;
1669                         skip_to_semi (cfile);
1670                         return 0;
1671                 }
1672                 return parse_case_statement (result,
1673                                              cfile, lose, case_context);
1674
1675               switch_default:
1676                 token = next_token (&val, (unsigned *)0, cfile);
1677                 if (case_context == context_any) {
1678                         parse_warn (cfile, "switch default statement in %s",
1679                                     "inappropriate scope.");
1680                 
1681                         *lose = 1;
1682                         return 0;
1683                 } else {
1684                         if (!executable_statement_allocate (result, MDL))
1685                                 log_fatal ("no memory for default statement.");
1686                         (*result) -> op = default_statement;
1687                         return 1;
1688                 }
1689                         
1690               case DEFINE:
1691               case TOKEN_SET:
1692                 token = next_token (&val, (unsigned *)0, cfile);
1693                 if (token == DEFINE)
1694                         flag = 1;
1695                 else
1696                         flag = 0;
1697
1698                 token = next_token (&val, (unsigned *)0, cfile);
1699                 if (token != NAME && token != NUMBER_OR_NAME) {
1700                         parse_warn (cfile,
1701                                     "%s can't be a variable name", val);
1702                       badset:
1703                         skip_to_semi (cfile);
1704                         *lose = 1;
1705                         return 0;
1706                 }
1707
1708                 if (!executable_statement_allocate (result, MDL))
1709                         log_fatal ("no memory for set statement.");
1710                 (*result) -> op = flag ? define_statement : set_statement;
1711                 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
1712                 if (!(*result)->data.set.name)
1713                         log_fatal ("can't allocate variable name");
1714                 strcpy ((*result) -> data.set.name, val);
1715                 token = next_token (&val, (unsigned *)0, cfile);
1716
1717                 if (token == LPAREN) {
1718                         struct string_list *head, *cur, *new;
1719                         struct expression *expr;
1720                         head = cur = (struct string_list *)0;
1721                         do {
1722                                 token = next_token (&val,
1723                                                     (unsigned *)0, cfile);
1724                                 if (token == RPAREN)
1725                                         break;
1726                                 if (token != NAME && token != NUMBER_OR_NAME) {
1727                                         parse_warn (cfile,
1728                                                     "expecting argument name");
1729                                         skip_to_rbrace (cfile, 0);
1730                                         *lose = 1;
1731                                         executable_statement_dereference
1732                                                 (result, MDL);
1733                                         return 0;
1734                                 }
1735                                 new = ((struct string_list *)
1736                                        dmalloc (sizeof (struct string_list) +
1737                                                 strlen (val), MDL));
1738                                 if (!new)
1739                                         log_fatal ("can't allocate string.");
1740                                 memset (new, 0, sizeof *new);
1741                                 strcpy (new -> string, val);
1742                                 if (cur) {
1743                                         cur -> next = new;
1744                                         cur = new;
1745                                 } else {
1746                                         head = cur = new;
1747                                 }
1748                                 token = next_token (&val,
1749                                                     (unsigned *)0, cfile);
1750                         } while (token == COMMA);
1751
1752                         if (token != RPAREN) {
1753                                 parse_warn (cfile, "expecting right paren.");
1754                               badx:
1755                                 skip_to_semi (cfile);
1756                                 *lose = 1;
1757                                 executable_statement_dereference (result, MDL);
1758                                 return 0;
1759                         }
1760
1761                         token = next_token (&val, (unsigned *)0, cfile);
1762                         if (token != LBRACE) {
1763                                 parse_warn (cfile, "expecting left brace.");
1764                                 goto badx;
1765                         }
1766
1767                         expr = (struct expression *)0;
1768                         if (!(expression_allocate (&expr, MDL)))
1769                                 log_fatal ("can't allocate expression.");
1770                         expr -> op = expr_function;
1771                         if (!fundef_allocate (&expr -> data.func, MDL))
1772                                 log_fatal ("can't allocate fundef.");
1773                         expr -> data.func -> args = head;
1774                         (*result) -> data.set.expr = expr;
1775
1776                         if (!(parse_executable_statements
1777                               (&expr -> data.func -> statements, cfile, lose,
1778                                case_context))) {
1779                                 if (*lose)
1780                                         goto badx;
1781                         }
1782
1783                         token = next_token (&val, (unsigned *)0, cfile);
1784                         if (token != RBRACE) {
1785                                 parse_warn (cfile, "expecting rigt brace.");
1786                                 goto badx;
1787                         }
1788                 } else {
1789                         if (token != EQUAL) {
1790                                 parse_warn (cfile,
1791                                             "expecting '=' in %s statement.",
1792                                             flag ? "define" : "set");
1793                                 goto badset;
1794                         }
1795
1796                         if (!parse_expression (&(*result) -> data.set.expr,
1797                                                cfile, lose, context_any,
1798                                                (struct expression **)0,
1799                                                expr_none)) {
1800                                 if (!*lose)
1801                                         parse_warn (cfile,
1802                                                     "expecting expression.");
1803                                 else
1804                                         *lose = 1;
1805                                 skip_to_semi (cfile);
1806                                 executable_statement_dereference (result, MDL);
1807                                 return 0;
1808                         }
1809                         if (!parse_semi (cfile)) {
1810                                 *lose = 1;
1811                                 executable_statement_dereference (result, MDL);
1812                                 return 0;
1813                         }
1814                 }
1815                 break;
1816
1817               case UNSET:
1818                 token = next_token (&val, (unsigned *)0, cfile);
1819
1820                 token = next_token (&val, (unsigned *)0, cfile);
1821                 if (token != NAME && token != NUMBER_OR_NAME) {
1822                         parse_warn (cfile,
1823                                     "%s can't be a variable name", val);
1824                       badunset:
1825                         skip_to_semi (cfile);
1826                         *lose = 1;
1827                         return 0;
1828                 }
1829
1830                 if (!executable_statement_allocate (result, MDL))
1831                         log_fatal ("no memory for set statement.");
1832                 (*result) -> op = unset_statement;
1833                 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
1834                 if (!(*result)->data.unset)
1835                         log_fatal ("can't allocate variable name");
1836                 strcpy ((*result) -> data.unset, val);
1837                 if (!parse_semi (cfile)) {
1838                         *lose = 1;
1839                         executable_statement_dereference (result, MDL);
1840                         return 0;
1841                 }
1842                 break;
1843
1844               case EVAL:
1845                 token = next_token (&val, (unsigned *)0, cfile);
1846
1847                 if (!executable_statement_allocate (result, MDL))
1848                         log_fatal ("no memory for eval statement.");
1849                 (*result) -> op = eval_statement;
1850
1851                 if (!parse_expression (&(*result) -> data.eval,
1852                                        cfile, lose, context_data, /* XXX */
1853                                        (struct expression **)0, expr_none)) {
1854                         if (!*lose)
1855                                 parse_warn (cfile,
1856                                             "expecting data expression.");
1857                         else
1858                                 *lose = 1;
1859                         skip_to_semi (cfile);
1860                         executable_statement_dereference (result, MDL);
1861                         return 0;
1862                 }
1863                 if (!parse_semi (cfile)) {
1864                         *lose = 1;
1865                         executable_statement_dereference (result, MDL);
1866                 }
1867                 break;
1868
1869               case RETURN:
1870                 token = next_token (&val, (unsigned *)0, cfile);
1871
1872                 if (!executable_statement_allocate (result, MDL))
1873                         log_fatal ("no memory for return statement.");
1874                 (*result) -> op = return_statement;
1875
1876                 if (!parse_expression (&(*result) -> data.retval,
1877                                        cfile, lose, context_data,
1878                                        (struct expression **)0, expr_none)) {
1879                         if (!*lose)
1880                                 parse_warn (cfile,
1881                                             "expecting data expression.");
1882                         else
1883                                 *lose = 1;
1884                         skip_to_semi (cfile);
1885                         executable_statement_dereference (result, MDL);
1886                         return 0;
1887                 }
1888                 if (!parse_semi (cfile)) {
1889                         *lose = 1;
1890                         executable_statement_dereference (result, MDL);
1891                         return 0;
1892                 }
1893                 break;
1894
1895               case LOG:
1896                 token = next_token (&val, (unsigned *)0, cfile);
1897
1898                 if (!executable_statement_allocate (result, MDL))
1899                         log_fatal ("no memory for log statement.");
1900                 (*result) -> op = log_statement;
1901
1902                 token = next_token (&val, (unsigned *)0, cfile);
1903                 if (token != LPAREN) {
1904                         parse_warn (cfile, "left parenthesis expected.");
1905                         skip_to_semi (cfile);
1906                         *lose = 1;
1907                         return 0;
1908                 }
1909
1910                 token = peek_token (&val, (unsigned *)0, cfile);
1911                 i = 1;
1912                 if (token == FATAL) {
1913                         (*result) -> data.log.priority = log_priority_fatal;
1914                 } else if (token == ERROR) {
1915                         (*result) -> data.log.priority = log_priority_error;
1916                 } else if (token == TOKEN_DEBUG) {
1917                         (*result) -> data.log.priority = log_priority_debug;
1918                 } else if (token == INFO) {
1919                         (*result) -> data.log.priority = log_priority_info;
1920                 } else {
1921                         (*result) -> data.log.priority = log_priority_debug;
1922                         i = 0;
1923                 }
1924                 if (i) {
1925                         token = next_token (&val, (unsigned *)0, cfile);
1926                         token = next_token (&val, (unsigned *)0, cfile);
1927                         if (token != COMMA) {
1928                                 parse_warn (cfile, "comma expected.");
1929                                 skip_to_semi (cfile);
1930                                 *lose = 1;
1931                                 return 0;
1932                         }
1933                 }
1934
1935                 if (!(parse_data_expression
1936                       (&(*result) -> data.log.expr, cfile, lose))) {
1937                         skip_to_semi (cfile);
1938                         *lose = 1;
1939                         return 0;
1940                 }
1941
1942                 token = next_token (&val, (unsigned *)0, cfile);
1943                 if (token != RPAREN) {
1944                         parse_warn (cfile, "right parenthesis expected.");
1945                         skip_to_semi (cfile);
1946                         *lose = 1;
1947                         return 0;
1948                 }
1949
1950                 token = next_token (&val, (unsigned *)0, cfile);
1951                 if (token != SEMI) {
1952                         parse_warn (cfile, "semicolon expected.");
1953                         skip_to_semi (cfile);
1954                         *lose = 1;
1955                         return 0;
1956                 }
1957                 break;
1958                         
1959                 /* Not really a statement, but we parse it here anyway
1960                    because it's appropriate for all DHCP agents with
1961                    parsers. */
1962               case ZONE:
1963                 token = next_token (&val, (unsigned *)0, cfile);
1964                 zone = (struct dns_zone *)0;
1965                 if (!dns_zone_allocate (&zone, MDL))
1966                         log_fatal ("no memory for new zone.");
1967                 zone -> name = parse_host_name (cfile);
1968                 if (!zone -> name) {
1969                         parse_warn (cfile, "expecting hostname.");
1970                       badzone:
1971                         *lose = 1;
1972                         skip_to_semi (cfile);
1973                         dns_zone_dereference (&zone, MDL);
1974                         return 0;
1975                 }
1976                 i = strlen (zone -> name);
1977                 if (zone -> name [i - 1] != '.') {
1978                         s = dmalloc ((unsigned)i + 2, MDL);
1979                         if (!s) {
1980                                 parse_warn (cfile, "no trailing '.' on zone");
1981                                 goto badzone;
1982                         }
1983                         strcpy (s, zone -> name);
1984                         s [i] = '.';
1985                         s [i + 1] = 0;
1986                         dfree (zone -> name, MDL);
1987                         zone -> name = s;
1988                 }
1989                 if (!parse_zone (zone, cfile))
1990                         goto badzone;
1991                 status = enter_dns_zone (zone);
1992                 if (status != ISC_R_SUCCESS) {
1993                         parse_warn (cfile, "dns zone key %s: %s",
1994                                     zone -> name, isc_result_totext (status));
1995                         dns_zone_dereference (&zone, MDL);
1996                         return 0;
1997                 }
1998                 dns_zone_dereference (&zone, MDL);
1999                 return 1;
2000                 
2001                 /* Also not really a statement, but same idea as above. */
2002               case KEY:
2003                 token = next_token (&val, (unsigned *)0, cfile);
2004                 if (!parse_key (cfile)) {
2005                         *lose = 1;
2006                         return 0;
2007                 }
2008                 return 1;
2009
2010               default:
2011                 if (config_universe && is_identifier (token)) {
2012                         option = (struct option *)0;
2013                         option_hash_lookup (&option, config_universe -> hash,
2014                                             val, 0, MDL);
2015                         if (option) {
2016                                 token = next_token (&val,
2017                                                     (unsigned *)0, cfile);
2018                                 return parse_option_statement
2019                                         (result, cfile, 1, option,
2020                                          supersede_option_statement);
2021                         }
2022                 }
2023
2024                 if (token == NUMBER_OR_NAME || token == NAME) {
2025                         /* This is rather ugly.  Since function calls are
2026                            data expressions, fake up an eval statement. */
2027                         if (!executable_statement_allocate (result, MDL))
2028                                 log_fatal ("no memory for eval statement.");
2029                         (*result) -> op = eval_statement;
2030
2031                         if (!parse_expression (&(*result) -> data.eval,
2032                                                cfile, lose, context_data,
2033                                                (struct expression **)0,
2034                                                expr_none)) {
2035                                 if (!*lose)
2036                                         parse_warn (cfile, "expecting "
2037                                                     "function call.");
2038                                 else
2039                                         *lose = 1;
2040                                 skip_to_semi (cfile);
2041                                 executable_statement_dereference (result, MDL);
2042                                 return 0;
2043                         }
2044                         if (!parse_semi (cfile)) {
2045                                 *lose = 1;
2046                                 executable_statement_dereference (result, MDL);
2047                                 return 0;
2048                         }
2049                         break;
2050                 }
2051
2052                 *lose = 0;
2053                 return 0;
2054         }
2055
2056         return 1;
2057 }
2058
2059 /* zone-statements :== zone-statement |
2060                        zone-statement zone-statements
2061    zone-statement :==
2062         PRIMARY ip-addresses SEMI |
2063         SECONDARY ip-addresses SEMI |
2064         key-reference SEMI
2065    ip-addresses :== ip-addr-or-hostname |
2066                   ip-addr-or-hostname COMMA ip-addresses
2067    key-reference :== KEY STRING |
2068                     KEY identifier */
2069
2070 int parse_zone (struct dns_zone *zone, struct parse *cfile)
2071 {
2072         int token;
2073         const char *val;
2074         char *key_name;
2075         struct option_cache *oc;
2076         int done = 0;
2077
2078         token = next_token (&val, (unsigned *)0, cfile);
2079         if (token != LBRACE) {
2080                 parse_warn (cfile, "expecting left brace");
2081                 return 0;
2082         }
2083
2084         do {
2085             token = peek_token (&val, (unsigned *)0, cfile);
2086             switch (token) {
2087                   case PRIMARY:
2088                     if (zone -> primary) {
2089                             parse_warn (cfile,
2090                                         "more than one primary.");
2091                             skip_to_semi (cfile);
2092                             return 0;
2093                     }
2094                     if (!option_cache_allocate (&zone -> primary, MDL))
2095                             log_fatal ("can't allocate primary option cache.");
2096                     oc = zone -> primary;
2097                     goto consemup;
2098                     
2099                   case SECONDARY:
2100                     if (zone -> secondary) {
2101                             parse_warn (cfile, "more than one secondary.");
2102                         skip_to_semi (cfile);
2103                         return 0;
2104                     }
2105                     if (!option_cache_allocate (&zone -> secondary, MDL))
2106                             log_fatal ("can't allocate secondary.");
2107                     oc = zone -> secondary;
2108                   consemup:
2109                     token = next_token (&val, (unsigned *)0, cfile);
2110                     do {
2111                             struct expression *expr = (struct expression *)0;
2112                             if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2113                                 parse_warn (cfile,
2114                                             "expecting IP addr or hostname.");
2115                                 skip_to_semi (cfile);
2116                                 return 0;
2117                             }
2118                             if (oc -> expression) {
2119                                     struct expression *old =
2120                                             (struct expression *)0;
2121                                     expression_reference (&old,
2122                                                           oc -> expression,
2123                                                           MDL);
2124                                     expression_dereference (&oc -> expression,
2125                                                             MDL);
2126                                     if (!make_concat (&oc -> expression,
2127                                                       old, expr))
2128                                         log_fatal ("no memory for concat.");
2129                                     expression_dereference (&expr, MDL);
2130                                     expression_dereference (&old, MDL);
2131                             } else {
2132                                     expression_reference (&oc -> expression,
2133                                                           expr, MDL);
2134                                     expression_dereference (&expr, MDL);
2135                             }
2136                             token = next_token (&val, (unsigned *)0, cfile);
2137                     } while (token == COMMA);
2138                     if (token != SEMI) {
2139                             parse_warn (cfile, "expecting semicolon.");
2140                             skip_to_semi (cfile);
2141                             return 0;
2142                     }
2143                     break;
2144
2145                   case KEY:
2146                     token = next_token (&val, (unsigned *)0, cfile);
2147                     token = peek_token (&val, (unsigned *)0, cfile);
2148                     if (token == STRING) {
2149                             token = next_token (&val, (unsigned *)0, cfile);
2150                             key_name = (char *)0;
2151                     } else {
2152                             key_name = parse_host_name (cfile);
2153                             if (!key_name) {
2154                                     parse_warn (cfile, "expecting key name.");
2155                                     skip_to_semi (cfile);
2156                                     return 0;
2157                             }
2158                             val = key_name;
2159                     }
2160                     if (omapi_auth_key_lookup_name (&zone -> key, val) !=
2161                         ISC_R_SUCCESS)
2162                             parse_warn (cfile, "unknown key %s", val);
2163                     if (key_name)
2164                             dfree (key_name, MDL);
2165                     if (!parse_semi (cfile))
2166                             return 0;
2167                     break;
2168                     
2169                   default:
2170                     done = 1;
2171                     break;
2172             }
2173         } while (!done);
2174
2175         token = next_token (&val, (unsigned *)0, cfile);
2176         if (token != RBRACE) {
2177                 parse_warn (cfile, "expecting right brace.");
2178                 return 0;
2179         }
2180         return 1;
2181 }
2182
2183 /* key-statements :== key-statement |
2184                       key-statement key-statements
2185    key-statement :==
2186         ALGORITHM host-name SEMI |
2187         secret-definition SEMI
2188    secret-definition :== SECRET base64val |
2189                          SECRET STRING */
2190
2191 int parse_key (struct parse *cfile)
2192 {
2193         int token;
2194         const char *val;
2195         int done = 0;
2196         struct auth_key *key;
2197         struct data_string ds;
2198         isc_result_t status;
2199         char *s;
2200
2201         key = (struct auth_key *)0;
2202         if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2203                 log_fatal ("no memory for key");
2204
2205         token = peek_token (&val, (unsigned *)0, cfile);
2206         if (token == STRING) {
2207                 token = next_token (&val, (unsigned *)0, cfile);
2208                 key -> name = dmalloc (strlen (val) + 1, MDL);
2209                 if (!key -> name)
2210                         log_fatal ("no memory for key name.");
2211                 strcpy (key -> name, val);
2212
2213         } else {
2214                 key -> name = parse_host_name (cfile);
2215                 if (!key -> name) {
2216                         parse_warn (cfile, "expecting key name.");
2217                         skip_to_semi (cfile);
2218                         goto bad;
2219                 }
2220         }
2221
2222         token = next_token (&val, (unsigned *)0, cfile);
2223         if (token != LBRACE) {
2224                 parse_warn (cfile, "expecting left brace");
2225                 goto bad;
2226         }
2227
2228         do {
2229                 token = next_token (&val, (unsigned *)0, cfile);
2230                 switch (token) {
2231                       case ALGORITHM:
2232                         if (key -> algorithm) {
2233                                 parse_warn (cfile,
2234                                             "key %s: too many algorithms",
2235                                             key -> name);
2236                                 goto rbad;
2237                         }
2238                         key -> algorithm = parse_host_name (cfile);
2239                         if (!key -> algorithm) {
2240                                 parse_warn (cfile,
2241                                             "expecting key algorithm name.");
2242                                 goto rbad;
2243                         }
2244                         if (!parse_semi (cfile))
2245                                 goto rbad;
2246                         /* If the algorithm name isn't an FQDN, tack on
2247                            the .SIG-ALG.REG.NET. domain. */
2248                         s = strrchr (key -> algorithm, '.');
2249                         if (!s) {
2250                             static char add [] = ".SIG-ALG.REG.INT.";
2251                             s = dmalloc (strlen (key -> algorithm) +
2252                                          sizeof (add), MDL);
2253                             if (!s) {
2254                                 log_error ("no memory for key %s.",
2255                                            "algorithm");
2256                                 goto rbad;
2257                             }
2258                             strcpy (s, key -> algorithm);
2259                             strcat (s, add);
2260                             dfree (key -> algorithm, MDL);
2261                             key -> algorithm = s;
2262                         } else if (s [1]) {
2263                             /* If there is no trailing '.', hack one in. */
2264                             s = dmalloc (strlen (key -> algorithm) + 2, MDL);
2265                             if (!s) {
2266                                     log_error ("no memory for key %s.",
2267                                                key -> algorithm);
2268                                     goto rbad;
2269                             }
2270                             strcpy (s, key -> algorithm);
2271                             strcat (s, ".");
2272                             dfree (key -> algorithm, MDL);
2273                             key -> algorithm = s;
2274                         }
2275                         break;
2276
2277                       case SECRET:
2278                         if (key -> key) {
2279                                 parse_warn (cfile, "key %s: too many secrets",
2280                                             key -> name);
2281                                 goto rbad;
2282                         }
2283
2284                         memset (&ds, 0, sizeof(ds));
2285                         if (!parse_base64 (&ds, cfile))
2286                                 goto rbad;
2287                         status = omapi_data_string_new (&key -> key, ds.len,
2288                                                         MDL);
2289                         if (status != ISC_R_SUCCESS)
2290                                 goto rbad;
2291                         memcpy (key -> key -> value,
2292                                 ds.buffer -> data, ds.len);
2293                         data_string_forget (&ds, MDL);
2294
2295                         if (!parse_semi (cfile))
2296                                 goto rbad;
2297                         break;
2298
2299                       default:
2300                         done = 1;
2301                         break;
2302                 }
2303         } while (!done);
2304         if (token != RBRACE) {
2305                 parse_warn (cfile, "expecting right brace.");
2306                 goto rbad;
2307         }
2308         /* Allow the BIND 8 syntax, which has a semicolon after each
2309            closing brace. */
2310         token = peek_token (&val, (unsigned *)0, cfile);
2311         if (token == SEMI)
2312                 token = next_token (&val, (unsigned *)0, cfile);
2313
2314         /* Remember the key. */
2315         status = omapi_auth_key_enter (key);
2316         if (status != ISC_R_SUCCESS) {
2317                 parse_warn (cfile, "tsig key %s: %s",
2318                             key -> name, isc_result_totext (status));
2319                 goto bad;
2320         }
2321         omapi_auth_key_dereference (&key, MDL);
2322         return 1;
2323
2324       rbad:
2325         skip_to_rbrace (cfile, 1);
2326       bad:
2327         omapi_auth_key_dereference (&key, MDL);
2328         return 0;
2329 }
2330
2331 /*
2332  * on-statement :== event-types LBRACE executable-statements RBRACE
2333  * event-types :== event-type OR event-types |
2334  *                 event-type
2335  * event-type :== EXPIRY | COMMIT | RELEASE
2336  */
2337
2338 int parse_on_statement (result, cfile, lose)
2339         struct executable_statement **result;
2340         struct parse *cfile;
2341         int *lose;
2342 {
2343         enum dhcp_token token;
2344         const char *val;
2345
2346         if (!executable_statement_allocate (result, MDL))
2347                 log_fatal ("no memory for new statement.");
2348         (*result) -> op = on_statement;
2349
2350         do {
2351                 token = next_token (&val, (unsigned *)0, cfile);
2352                 switch (token) {
2353                       case EXPIRY:
2354                         (*result) -> data.on.evtypes |= ON_EXPIRY;
2355                         break;
2356                 
2357                       case COMMIT:
2358                         (*result) -> data.on.evtypes |= ON_COMMIT;
2359                         break;
2360                         
2361                       case RELEASE:
2362                         (*result) -> data.on.evtypes |= ON_RELEASE;
2363                         break;
2364                         
2365                       case TRANSMISSION:
2366                         (*result) -> data.on.evtypes |= ON_TRANSMISSION;
2367                         break;
2368
2369                       default:
2370                         parse_warn (cfile, "expecting a lease event type");
2371                         skip_to_semi (cfile);
2372                         *lose = 1;
2373                         executable_statement_dereference (result, MDL);
2374                         return 0;
2375                 }
2376                 token = next_token (&val, (unsigned *)0, cfile);
2377         } while (token == OR);
2378                 
2379         /* Semicolon means no statements. */
2380         if (token == SEMI)
2381                 return 1;
2382
2383         if (token != LBRACE) {
2384                 parse_warn (cfile, "left brace expected.");
2385                 skip_to_semi (cfile);
2386                 *lose = 1;
2387                 executable_statement_dereference (result, MDL);
2388                 return 0;
2389         }
2390         if (!parse_executable_statements (&(*result) -> data.on.statements,
2391                                           cfile, lose, context_any)) {
2392                 if (*lose) {
2393                         /* Try to even things up. */
2394                         do {
2395                                 token = next_token (&val,
2396                                                     (unsigned *)0, cfile);
2397                         } while (token != END_OF_FILE && token != RBRACE);
2398                         executable_statement_dereference (result, MDL);
2399                         return 0;
2400                 }
2401         }
2402         token = next_token (&val, (unsigned *)0, cfile);
2403         if (token != RBRACE) {
2404                 parse_warn (cfile, "right brace expected.");
2405                 skip_to_semi (cfile);
2406                 *lose = 1;
2407                 executable_statement_dereference (result, MDL);
2408                 return 0;
2409         }
2410         return 1;
2411 }
2412
2413 /*
2414  * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2415  *
2416  */
2417
2418 int parse_switch_statement (result, cfile, lose)
2419         struct executable_statement **result;
2420         struct parse *cfile;
2421         int *lose;
2422 {
2423         enum dhcp_token token;
2424         const char *val;
2425
2426         if (!executable_statement_allocate (result, MDL))
2427                 log_fatal ("no memory for new statement.");
2428         (*result) -> op = switch_statement;
2429
2430         token = next_token (&val, (unsigned *)0, cfile);
2431         if (token != LPAREN) {
2432                 parse_warn (cfile, "expecting left brace.");
2433               pfui:
2434                 *lose = 1;
2435                 skip_to_semi (cfile);
2436               gnorf:
2437                 executable_statement_dereference (result, MDL);
2438                 return 0;
2439         }
2440
2441         if (!parse_expression (&(*result) -> data.s_switch.expr,
2442                                cfile, lose, context_data_or_numeric,
2443                                (struct expression **)0, expr_none)) {
2444                 if (!*lose) {
2445                         parse_warn (cfile,
2446                                     "expecting data or numeric expression.");
2447                         goto pfui;
2448                 }
2449                 goto gnorf;
2450         }
2451
2452         token = next_token (&val, (unsigned *)0, cfile);
2453         if (token != RPAREN) {
2454                 parse_warn (cfile, "right paren expected.");
2455                 goto pfui;
2456         }
2457
2458         token = next_token (&val, (unsigned *)0, cfile);
2459         if (token != LBRACE) {
2460                 parse_warn (cfile, "left brace expected.");
2461                 goto pfui;
2462         }
2463         if (!(parse_executable_statements
2464               (&(*result) -> data.s_switch.statements, cfile, lose,
2465                (is_data_expression ((*result) -> data.s_switch.expr)
2466                 ? context_data : context_numeric)))) {
2467                 if (*lose) {
2468                         skip_to_rbrace (cfile, 1);
2469                         executable_statement_dereference (result, MDL);
2470                         return 0;
2471                 }
2472         }
2473         token = next_token (&val, (unsigned *)0, cfile);
2474         if (token != RBRACE) {
2475                 parse_warn (cfile, "right brace expected.");
2476                 goto pfui;
2477         }
2478         return 1;
2479 }
2480
2481 /*
2482  * case-statement :== CASE expr COLON
2483  *
2484  */
2485
2486 int parse_case_statement (result, cfile, lose, case_context)
2487         struct executable_statement **result;
2488         struct parse *cfile;
2489         int *lose;
2490         enum expression_context case_context;
2491 {
2492         enum dhcp_token token;
2493         const char *val;
2494
2495         if (!executable_statement_allocate (result, MDL))
2496                 log_fatal ("no memory for new statement.");
2497         (*result) -> op = case_statement;
2498
2499         if (!parse_expression (&(*result) -> data.c_case,
2500                                cfile, lose, case_context,
2501                                (struct expression **)0, expr_none))
2502         {
2503                 if (!*lose) {
2504                         parse_warn (cfile, "expecting %s expression.",
2505                                     (case_context == context_data
2506                                      ? "data" : "numeric"));
2507                 }
2508               pfui:
2509                 *lose = 1;
2510                 skip_to_semi (cfile);
2511                 executable_statement_dereference (result, MDL);
2512                 return 0;
2513         }
2514
2515         token = next_token (&val, (unsigned *)0, cfile);
2516         if (token != COLON) {
2517                 parse_warn (cfile, "colon expected.");
2518                 goto pfui;
2519         }
2520         return 1;
2521 }
2522
2523 /*
2524  * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2525  *                                              else-statement
2526  *
2527  * else-statement :== <null> |
2528  *                    ELSE LBRACE executable-statements RBRACE |
2529  *                    ELSE IF if-statement |
2530  *                    ELSIF if-statement
2531  */
2532
2533 int parse_if_statement (result, cfile, lose)
2534         struct executable_statement **result;
2535         struct parse *cfile;
2536         int *lose;
2537 {
2538         enum dhcp_token token;
2539         const char *val;
2540         int parenp;
2541
2542         if (!executable_statement_allocate (result, MDL))
2543                 log_fatal ("no memory for if statement.");
2544
2545         (*result) -> op = if_statement;
2546
2547         token = peek_token (&val, (unsigned *)0, cfile);
2548         if (token == LPAREN) {
2549                 parenp = 1;
2550                 next_token (&val, (unsigned *)0, cfile);
2551         } else
2552                 parenp = 0;
2553
2554
2555         if (!parse_boolean_expression (&(*result) -> data.ie.expr,
2556                                        cfile, lose)) {
2557                 if (!*lose)
2558                         parse_warn (cfile, "boolean expression expected.");
2559                 executable_statement_dereference (result, MDL);
2560                 *lose = 1;
2561                 return 0;
2562         }
2563 #if defined (DEBUG_EXPRESSION_PARSE)
2564         print_expression ("if condition", (*result) -> data.ie.expr);
2565 #endif
2566         if (parenp) {
2567                 token = next_token (&val, (unsigned *)0, cfile);
2568                 if (token != RPAREN) {
2569                         parse_warn (cfile, "expecting right paren.");
2570                         *lose = 1;
2571                         executable_statement_dereference (result, MDL);
2572                         return 0;
2573                 }
2574         }
2575         token = next_token (&val, (unsigned *)0, cfile);
2576         if (token != LBRACE) {
2577                 parse_warn (cfile, "left brace expected.");
2578                 skip_to_semi (cfile);
2579                 *lose = 1;
2580                 executable_statement_dereference (result, MDL);
2581                 return 0;
2582         }
2583         if (!parse_executable_statements (&(*result) -> data.ie.tc,
2584                                           cfile, lose, context_any)) {
2585                 if (*lose) {
2586                         /* Try to even things up. */
2587                         do {
2588                                 token = next_token (&val,
2589                                                     (unsigned *)0, cfile);
2590                         } while (token != END_OF_FILE && token != RBRACE);
2591                         executable_statement_dereference (result, MDL);
2592                         return 0;
2593                 }
2594         }
2595         token = next_token (&val, (unsigned *)0, cfile);
2596         if (token != RBRACE) {
2597                 parse_warn (cfile, "right brace expected.");
2598                 skip_to_semi (cfile);
2599                 *lose = 1;
2600                 executable_statement_dereference (result, MDL);
2601                 return 0;
2602         }
2603         token = peek_token (&val, (unsigned *)0, cfile);
2604         if (token == ELSE) {
2605                 token = next_token (&val, (unsigned *)0, cfile);
2606                 token = peek_token (&val, (unsigned *)0, cfile);
2607                 if (token == IF) {
2608                         token = next_token (&val, (unsigned *)0, cfile);
2609                         if (!parse_if_statement (&(*result) -> data.ie.fc,
2610                                                  cfile, lose)) {
2611                                 if (!*lose)
2612                                         parse_warn (cfile,
2613                                                     "expecting if statement");
2614                                 executable_statement_dereference (result, MDL);
2615                                 *lose = 1;
2616                                 return 0;
2617                         }
2618                 } else if (token != LBRACE) {
2619                         parse_warn (cfile, "left brace or if expected.");
2620                         skip_to_semi (cfile);
2621                         *lose = 1;
2622                         executable_statement_dereference (result, MDL);
2623                         return 0;
2624                 } else {
2625                         token = next_token (&val, (unsigned *)0, cfile);
2626                         if (!(parse_executable_statements
2627                               (&(*result) -> data.ie.fc,
2628                                cfile, lose, context_any))) {
2629                                 executable_statement_dereference (result, MDL);
2630                                 return 0;
2631                         }
2632                         token = next_token (&val, (unsigned *)0, cfile);
2633                         if (token != RBRACE) {
2634                                 parse_warn (cfile, "right brace expected.");
2635                                 skip_to_semi (cfile);
2636                                 *lose = 1;
2637                                 executable_statement_dereference (result, MDL);
2638                                 return 0;
2639                         }
2640                 }
2641         } else if (token == ELSIF) {
2642                 token = next_token (&val, (unsigned *)0, cfile);
2643                 if (!parse_if_statement (&(*result) -> data.ie.fc,
2644                                          cfile, lose)) {
2645                         if (!*lose)
2646                                 parse_warn (cfile,
2647                                             "expecting conditional.");
2648                         executable_statement_dereference (result, MDL);
2649                         *lose = 1;
2650                         return 0;
2651                 }
2652         } else
2653                 (*result) -> data.ie.fc = (struct executable_statement *)0;
2654         
2655         return 1;
2656 }
2657
2658 /*
2659  * boolean_expression :== CHECK STRING |
2660  *                        NOT boolean-expression |
2661  *                        data-expression EQUAL data-expression |
2662  *                        data-expression BANG EQUAL data-expression |
2663  *                        boolean-expression AND boolean-expression |
2664  *                        boolean-expression OR boolean-expression
2665  *                        EXISTS OPTION-NAME
2666  */
2667                           
2668 int parse_boolean_expression (expr, cfile, lose)
2669         struct expression **expr;
2670         struct parse *cfile;
2671         int *lose;
2672 {
2673         /* Parse an expression... */
2674         if (!parse_expression (expr, cfile, lose, context_boolean,
2675                                (struct expression **)0, expr_none))
2676                 return 0;
2677
2678         if (!is_boolean_expression (*expr) &&
2679             (*expr) -> op != expr_variable_reference &&
2680             (*expr) -> op != expr_funcall) {
2681                 parse_warn (cfile, "Expecting a boolean expression.");
2682                 *lose = 1;
2683                 expression_dereference (expr, MDL);
2684                 return 0;
2685         }
2686         return 1;
2687 }
2688
2689 /*
2690  * data_expression :== SUBSTRING LPAREN data-expression COMMA
2691  *                                      numeric-expression COMMA
2692  *                                      numeric-expression RPAREN |
2693  *                     CONCAT LPAREN data-expression COMMA 
2694                                         data-expression RPAREN
2695  *                     SUFFIX LPAREN data_expression COMMA
2696  *                                   numeric-expression RPAREN |
2697  *                     OPTION option_name |
2698  *                     HARDWARE |
2699  *                     PACKET LPAREN numeric-expression COMMA
2700  *                                   numeric-expression RPAREN |
2701  *                     STRING |
2702  *                     colon_seperated_hex_list
2703  */
2704
2705 int parse_data_expression (expr, cfile, lose)
2706         struct expression **expr;
2707         struct parse *cfile;
2708         int *lose;
2709 {
2710         /* Parse an expression... */
2711         if (!parse_expression (expr, cfile, lose, context_data,
2712                                (struct expression **)0, expr_none))
2713                 return 0;
2714
2715         if (!is_data_expression (*expr) &&
2716             (*expr) -> op != expr_variable_reference &&
2717             (*expr) -> op != expr_funcall) {
2718                 parse_warn (cfile, "Expecting a data expression.");
2719                 *lose = 1;
2720                 return 0;
2721         }
2722         return 1;
2723 }
2724
2725 /*
2726  * numeric-expression :== EXTRACT_INT LPAREN data-expression
2727  *                                           COMMA number RPAREN |
2728  *                        NUMBER
2729  */
2730
2731 int parse_numeric_expression (expr, cfile, lose)
2732         struct expression **expr;
2733         struct parse *cfile;
2734         int *lose;
2735 {
2736         /* Parse an expression... */
2737         if (!parse_expression (expr, cfile, lose, context_numeric,
2738                                (struct expression **)0, expr_none))
2739                 return 0;
2740
2741         if (!is_numeric_expression (*expr) &&
2742             (*expr) -> op != expr_variable_reference &&
2743             (*expr) -> op != expr_funcall) {
2744                 parse_warn (cfile, "Expecting a numeric expression.");
2745                 *lose = 1;
2746                 return 0;
2747         }
2748         return 1;
2749 }
2750
2751 /*
2752  * dns-expression :==
2753  *      UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2754  *                              data-expression COMMA numeric-expression RPAREN
2755  *      DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2756  *                              data-expression RPAREN
2757  *      EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2758  *                              data-expression RPAREN
2759  *      NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2760  *                              data-expression RPAREN
2761  * ns-class :== IN | CHAOS | HS | NUMBER
2762  * ns-type :== A | PTR | MX | TXT | NUMBER
2763  */
2764
2765 int parse_dns_expression (expr, cfile, lose)
2766         struct expression **expr;
2767         struct parse *cfile;
2768         int *lose;
2769 {
2770         /* Parse an expression... */
2771         if (!parse_expression (expr, cfile, lose, context_dns,
2772                                (struct expression **)0, expr_none))
2773                 return 0;
2774
2775         if (!is_dns_expression (*expr) &&
2776             (*expr) -> op != expr_variable_reference &&
2777             (*expr) -> op != expr_funcall) {
2778                 parse_warn (cfile, "Expecting a dns update subexpression.");
2779                 *lose = 1;
2780                 return 0;
2781         }
2782         return 1;
2783 }
2784
2785 /* Parse a subexpression that does not contain a binary operator. */
2786
2787 int parse_non_binary (expr, cfile, lose, context)
2788         struct expression **expr;
2789         struct parse *cfile;
2790         int *lose;
2791         enum expression_context context;
2792 {
2793         enum dhcp_token token;
2794         const char *val;
2795         struct collection *col;
2796         struct option *option;
2797         struct expression *nexp, **ep;
2798         int known;
2799         enum expr_op opcode;
2800         const char *s;
2801         char *cptr;
2802         struct executable_statement *stmt;
2803         int i;
2804         unsigned long u;
2805         isc_result_t status, code;
2806         unsigned len;
2807
2808         token = peek_token (&val, (unsigned *)0, cfile);
2809
2810         /* Check for unary operators... */
2811         switch (token) {
2812               case CHECK:
2813                 token = next_token (&val, (unsigned *)0, cfile);
2814                 token = next_token (&val, (unsigned *)0, cfile);
2815                 if (token != STRING) {
2816                         parse_warn (cfile, "string expected.");
2817                         skip_to_semi (cfile);
2818                         *lose = 1;
2819                         return 0;
2820                 }
2821                 for (col = collections; col; col = col -> next)
2822                         if (!strcmp (col -> name, val))
2823                                 break;
2824                 if (!col) {
2825                         parse_warn (cfile, "unknown collection.");
2826                         *lose = 1;
2827                         return 0;
2828                 }
2829                 if (!expression_allocate (expr, MDL))
2830                         log_fatal ("can't allocate expression");
2831                 (*expr) -> op = expr_check;
2832                 (*expr) -> data.check = col;
2833                 break;
2834
2835               case TOKEN_NOT:
2836                 token = next_token (&val, (unsigned *)0, cfile);
2837                 if (context == context_dns) {
2838                         token = peek_token (&val, (unsigned *)0, cfile);
2839                         goto not_exists;
2840                 }
2841                 if (!expression_allocate (expr, MDL))
2842                         log_fatal ("can't allocate expression");
2843                 (*expr) -> op = expr_not;
2844                 if (!parse_non_binary (&(*expr) -> data.not,
2845                                        cfile, lose, context_boolean)) {
2846                         if (!*lose) {
2847                                 parse_warn (cfile, "expression expected");
2848                                 skip_to_semi (cfile);
2849                         }
2850                         *lose = 1;
2851                         expression_dereference (expr, MDL);
2852                         return 0;
2853                 }
2854                 if (!is_boolean_expression ((*expr) -> data.not)) {
2855                         *lose = 1;
2856                         parse_warn (cfile, "boolean expression expected");
2857                         skip_to_semi (cfile);
2858                         expression_dereference (expr, MDL);
2859                         return 0;
2860                 }
2861                 break;
2862
2863               case LPAREN:
2864                 token = next_token (&val, (unsigned *)0, cfile);
2865                 if (!parse_expression (expr, cfile, lose, context,
2866                                        (struct expression **)0, expr_none)) {
2867                         if (!*lose) {
2868                                 parse_warn (cfile, "expression expected");
2869                                 skip_to_semi (cfile);
2870                         }
2871                         *lose = 1;
2872                         return 0;
2873                 }
2874                 token = next_token (&val, (unsigned *)0, cfile);
2875                 if (token != RPAREN) {
2876                         *lose = 1;
2877                         parse_warn (cfile, "right paren expected");
2878                         skip_to_semi (cfile);
2879                         return 0;
2880                 }
2881                 break;
2882
2883               case EXISTS:
2884                 if (context == context_dns)
2885                         goto ns_exists;
2886                 token = next_token (&val, (unsigned *)0, cfile);
2887                 if (!expression_allocate (expr, MDL))
2888                         log_fatal ("can't allocate expression");
2889                 (*expr) -> op = expr_exists;
2890                 known = 0;
2891                 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
2892                 if (!(*expr) -> data.option) {
2893                         *lose = 1;
2894                         expression_dereference (expr, MDL);
2895                         return 0;
2896                 }
2897                 break;
2898
2899               case STATIC:
2900                 token = next_token (&val, (unsigned *)0, cfile);
2901                 if (!expression_allocate (expr, MDL))
2902                         log_fatal ("can't allocate expression");
2903                 (*expr) -> op = expr_static;
2904                 break;
2905
2906               case KNOWN:
2907                 token = next_token (&val, (unsigned *)0, cfile);
2908                 if (!expression_allocate (expr, MDL))
2909                         log_fatal ("can't allocate expression");
2910                 (*expr) -> op = expr_known;
2911                 break;
2912
2913               case SUBSTRING:
2914                 token = next_token (&val, (unsigned *)0, cfile);
2915                 if (!expression_allocate (expr, MDL))
2916                         log_fatal ("can't allocate expression");
2917                 (*expr) -> op = expr_substring;
2918
2919                 token = next_token (&val, (unsigned *)0, cfile);
2920                 if (token != LPAREN) {
2921                       nolparen:
2922                         expression_dereference (expr, MDL);
2923                         parse_warn (cfile, "left parenthesis expected.");
2924                         *lose = 1;
2925                         return 0;
2926                 }
2927
2928                 if (!parse_data_expression (&(*expr) -> data.substring.expr,
2929                                             cfile, lose)) {
2930                       nodata:
2931                         expression_dereference (expr, MDL);
2932                         if (!*lose) {
2933                                 parse_warn (cfile,
2934                                             "expecting data expression.");
2935                                 skip_to_semi (cfile);
2936                                 *lose = 1;
2937                         }
2938                         return 0;
2939                 }
2940
2941                 token = next_token (&val, (unsigned *)0, cfile);
2942                 if (token != COMMA) {
2943                       nocomma:
2944                         expression_dereference (expr, MDL);
2945                         parse_warn (cfile, "comma expected.");
2946                         *lose = 1;
2947
2948                         return 0;
2949                 }
2950
2951                 if (!parse_numeric_expression
2952                     (&(*expr) -> data.substring.offset,cfile, lose)) {
2953                       nonum:
2954                         if (!*lose) {
2955                                 parse_warn (cfile,
2956                                             "expecting numeric expression.");
2957                                 skip_to_semi (cfile);
2958                                 *lose = 1;
2959                         }
2960                         expression_dereference (expr, MDL);
2961                         return 0;
2962                 }
2963
2964                 token = next_token (&val, (unsigned *)0, cfile);
2965                 if (token != COMMA)
2966                         goto nocomma;
2967
2968                 if (!parse_numeric_expression
2969                     (&(*expr) -> data.substring.len, cfile, lose))
2970                         goto nonum;
2971
2972                 token = next_token (&val, (unsigned *)0, cfile);
2973                 if (token != RPAREN) {
2974                       norparen:
2975                         parse_warn (cfile, "right parenthesis expected.");
2976                         *lose = 1;
2977                         expression_dereference (expr, MDL);
2978                         return 0;
2979                 }
2980                 break;
2981
2982               case SUFFIX:
2983                 token = next_token (&val, (unsigned *)0, cfile);
2984                 if (!expression_allocate (expr, MDL))
2985                         log_fatal ("can't allocate expression");
2986                 (*expr) -> op = expr_suffix;
2987
2988                 token = next_token (&val, (unsigned *)0, cfile);
2989                 if (token != LPAREN)
2990                         goto nolparen;
2991
2992                 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
2993                                             cfile, lose))
2994                         goto nodata;
2995
2996                 token = next_token (&val, (unsigned *)0, cfile);
2997                 if (token != COMMA)
2998                         goto nocomma;
2999
3000                 if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
3001                                                cfile, lose))
3002                         goto nonum;
3003
3004                 token = next_token (&val, (unsigned *)0, cfile);
3005                 if (token != RPAREN)
3006                         goto norparen;
3007                 break;
3008
3009               case CONCAT:
3010                 token = next_token (&val, (unsigned *)0, cfile);
3011                 if (!expression_allocate (expr, MDL))
3012                         log_fatal ("can't allocate expression");
3013                 (*expr) -> op = expr_concat;
3014
3015                 token = next_token (&val, (unsigned *)0, cfile);
3016                 if (token != LPAREN)
3017                         goto nolparen;
3018
3019                 if (!parse_data_expression (&(*expr) -> data.concat [0],
3020                                             cfile, lose))
3021                         goto nodata;
3022
3023                 token = next_token (&val, (unsigned *)0, cfile);
3024                 if (token != COMMA)
3025                         goto nocomma;
3026
3027               concat_another:
3028                 if (!parse_data_expression (&(*expr) -> data.concat [1],
3029                                             cfile, lose))
3030                         goto nodata;
3031
3032                 token = next_token (&val, (unsigned *)0, cfile);
3033
3034                 if (token == COMMA) {
3035                         nexp = (struct expression *)0;
3036                         if (!expression_allocate (&nexp, MDL))
3037                                 log_fatal ("can't allocate at CONCAT2");
3038                         nexp -> op = expr_concat;
3039                         expression_reference (&nexp -> data.concat [0],
3040                                               *expr, MDL);
3041                         expression_dereference (expr, MDL);
3042                         expression_reference (expr, nexp, MDL);
3043                         expression_dereference (&nexp, MDL);
3044                         goto concat_another;
3045                 }
3046
3047                 if (token != RPAREN)
3048                         goto norparen;
3049                 break;
3050
3051               case BINARY_TO_ASCII:
3052                 token = next_token (&val, (unsigned *)0, cfile);
3053                 if (!expression_allocate (expr, MDL))
3054                         log_fatal ("can't allocate expression");
3055                 (*expr) -> op = expr_binary_to_ascii;
3056
3057                 token = next_token (&val, (unsigned *)0, cfile);
3058                 if (token != LPAREN)
3059                         goto nolparen;
3060
3061                 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3062                                                cfile, lose))
3063                         goto nodata;
3064
3065                 token = next_token (&val, (unsigned *)0, cfile);
3066                 if (token != COMMA)
3067                         goto nocomma;
3068
3069                 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3070                                                cfile, lose))
3071                         goto nodata;
3072
3073                 token = next_token (&val, (unsigned *)0, cfile);
3074                 if (token != COMMA)
3075                         goto nocomma;
3076
3077                 if (!parse_data_expression (&(*expr) -> data.b2a.seperator,
3078                                             cfile, lose))
3079                         goto nodata;
3080
3081                 token = next_token (&val, (unsigned *)0, cfile);
3082                 if (token != COMMA)
3083                         goto nocomma;
3084
3085                 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3086                                             cfile, lose))
3087                         goto nodata;
3088
3089                 token = next_token (&val, (unsigned *)0, cfile);
3090                 if (token != RPAREN)
3091                         goto norparen;
3092                 break;
3093
3094               case REVERSE:
3095                 token = next_token (&val, (unsigned *)0, cfile);
3096                 if (!expression_allocate (expr, MDL))
3097                         log_fatal ("can't allocate expression");
3098                 (*expr) -> op = expr_reverse;
3099
3100                 token = next_token (&val, (unsigned *)0, cfile);
3101                 if (token != LPAREN)
3102                         goto nolparen;
3103
3104                 if (!(parse_numeric_expression
3105                       (&(*expr) -> data.reverse.width, cfile, lose)))
3106                         goto nodata;
3107
3108                 token = next_token (&val, (unsigned *)0, cfile);
3109                 if (token != COMMA)
3110                         goto nocomma;
3111
3112                 if (!(parse_data_expression
3113                       (&(*expr) -> data.reverse.buffer, cfile, lose)))
3114                         goto nodata;
3115
3116                 token = next_token (&val, (unsigned *)0, cfile);
3117                 if (token != RPAREN)
3118                         goto norparen;
3119                 break;
3120
3121               case PICK:
3122                 /* pick (a, b, c) actually produces an internal representation
3123                    that looks like pick (a, pick (b, pick (c, nil))). */
3124                 token = next_token (&val, (unsigned *)0, cfile);
3125                 if (!(expression_allocate (expr, MDL)))
3126                         log_fatal ("can't allocate expression");
3127
3128                 token = next_token (&val, (unsigned *)0, cfile);
3129                 if (token != LPAREN)
3130                         goto nolparen;
3131
3132                 nexp = (struct expression *)0;
3133                 expression_reference (&nexp, *expr, MDL);
3134                 do {
3135                     nexp -> op = expr_pick_first_value;
3136                     if (!(parse_data_expression
3137                           (&nexp -> data.pick_first_value.car,
3138                            cfile, lose)))
3139                         goto nodata;
3140
3141                     token = next_token (&val, (unsigned *)0, cfile);
3142                     if (token == COMMA) {
3143                         struct expression *foo = (struct expression *)0;
3144                         if (!expression_allocate (&foo, MDL))
3145                             log_fatal ("can't allocate expr");
3146                         expression_reference
3147                                 (&nexp -> data.pick_first_value.cdr, foo, MDL);
3148                         expression_dereference (&nexp, MDL);
3149                         expression_reference (&nexp, foo, MDL);
3150                         expression_dereference (&foo, MDL);
3151                     }
3152                 } while (token == COMMA);
3153                 expression_dereference (&nexp, MDL);
3154
3155                 if (token != RPAREN)
3156                         goto norparen;
3157                 break;
3158
3159                 /* dns-update and dns-delete are present for historical
3160                    purposes, but are deprecated in favor of ns-update
3161                    in combination with update, delete, exists and not
3162                    exists. */
3163               case DNS_UPDATE:
3164               case DNS_DELETE:
3165 #if !defined (NSUPDATE)
3166                 parse_warn (cfile,
3167                             "Please rebuild dhcpd with --with-nsupdate.");
3168 #endif
3169                 token = next_token (&val, (unsigned *)0, cfile);
3170                 if (token == DNS_UPDATE)
3171                         opcode = expr_ns_add;
3172                 else
3173                         opcode = expr_ns_delete;
3174
3175                 token = next_token (&val, (unsigned *)0, cfile);
3176                 if (token != LPAREN)
3177                         goto nolparen;
3178
3179                 token = next_token (&val, (unsigned *)0, cfile);
3180                 if (token != STRING) {
3181                         parse_warn (cfile,
3182                                     "parse_expression: expecting string.");
3183                       badnsupdate:
3184                         skip_to_semi (cfile);
3185                         *lose = 1;
3186                         return 0;
3187                 }
3188                         
3189                 if (!strcasecmp (val, "a"))
3190                         u = T_A;
3191                 else if (!strcasecmp (val, "ptr"))
3192                         u = T_PTR;
3193                 else if (!strcasecmp (val, "mx"))
3194                         u = T_MX;
3195                 else if (!strcasecmp (val, "cname"))
3196                         u = T_CNAME;
3197                 else if (!strcasecmp (val, "TXT"))
3198                         u = T_TXT;
3199                 else {
3200                         parse_warn (cfile, "unexpected rrtype: %s", val);
3201                         goto badnsupdate;
3202                 }
3203
3204                 s = (opcode == expr_ns_add
3205                      ? "old-dns-update"
3206                      : "old-dns-delete");
3207                 cptr = dmalloc (strlen (s) + 1, MDL);
3208                 if (!cptr)
3209                         log_fatal ("can't allocate name for %s", s);
3210                 strcpy (cptr, s);
3211                 if (!expression_allocate (expr, MDL))
3212                         log_fatal ("can't allocate expression");
3213                 (*expr) -> op = expr_funcall;
3214                 (*expr) -> data.funcall.name = cptr;
3215
3216                 /* Fake up a function call. */
3217                 ep = &(*expr) -> data.funcall.arglist;
3218                 if (!expression_allocate (ep, MDL))
3219                         log_fatal ("can't allocate expression");
3220                 (*ep) -> op = expr_arg;
3221                 if (!make_const_int (&(*ep) -> data.arg.val, u))
3222                         log_fatal ("can't allocate rrtype value.");
3223
3224                 token = next_token (&val, (unsigned *)0, cfile);
3225                 if (token != COMMA)
3226                         goto nocomma;
3227                 ep = &((*ep) -> data.arg.next);
3228                 if (!expression_allocate (ep, MDL))
3229                         log_fatal ("can't allocate expression");
3230                 (*ep) -> op = expr_arg;
3231                 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3232                                              cfile, lose)))
3233                         goto nodata;
3234
3235                 token = next_token (&val, (unsigned *)0, cfile);
3236                 if (token != COMMA)
3237                         goto nocomma;
3238
3239                 ep = &((*ep) -> data.arg.next);
3240                 if (!expression_allocate (ep, MDL))
3241                         log_fatal ("can't allocate expression");
3242                 (*ep) -> op = expr_arg;
3243                 if (!(parse_data_expression (&(*ep) -> data.arg.val,
3244                                              cfile, lose)))
3245                         goto nodata;
3246
3247                 if (opcode == expr_ns_add) {
3248                         token = next_token (&val, (unsigned *)0, cfile);
3249                         if (token != COMMA)
3250                                 goto nocomma;
3251                         
3252                         ep = &((*ep) -> data.arg.next);
3253                         if (!expression_allocate (ep, MDL))
3254                                 log_fatal ("can't allocate expression");
3255                         (*ep) -> op = expr_arg;
3256                         if (!(parse_numeric_expression (&(*ep) -> data.arg.val,
3257                                                         cfile, lose))) {
3258                                 parse_warn (cfile,
3259                                             "expecting numeric expression.");
3260                                 goto badnsupdate;
3261                         }
3262                 }
3263
3264                 token = next_token (&val, (unsigned *)0, cfile);
3265                 if (token != RPAREN)
3266                         goto norparen;
3267                 break;
3268
3269               case NS_UPDATE:
3270 #if !defined (NSUPDATE)
3271                 parse_warn (cfile,
3272                             "Please rebuild dhcpd with --with-nsupdate.");
3273 #endif
3274                 token = next_token (&val, (unsigned *)0, cfile);
3275                 if (!expression_allocate (expr, MDL))
3276                         log_fatal ("can't allocate expression");
3277
3278                 token = next_token (&val, (unsigned *)0, cfile);
3279                 if (token != LPAREN)
3280                         goto nolparen;
3281
3282                 nexp = *expr;
3283                 do {
3284                         nexp -> op = expr_dns_transaction;
3285                         if (!(parse_dns_expression
3286                               (&nexp -> data.dns_transaction.car,
3287                                cfile, lose)))
3288                         {
3289                                 if (!*lose)
3290                                         parse_warn
3291                                                 (cfile,
3292                                                  "expecting dns expression.");
3293                               badnstrans:
3294                                 expression_dereference (expr, MDL);
3295                                 *lose = 1;
3296                                 return 0;
3297                         }
3298
3299                         token = next_token (&val, (unsigned *)0, cfile);
3300                         
3301                         if (token == COMMA) {
3302                                 if (!(expression_allocate
3303                                       (&nexp -> data.dns_transaction.cdr,
3304                                        MDL)))
3305                                         log_fatal
3306                                                 ("can't allocate expression");
3307                                 nexp = nexp -> data.dns_transaction.cdr;
3308                         }
3309                 } while (token == COMMA);
3310
3311                 if (token != RPAREN)
3312                         goto norparen;
3313                 break;
3314
3315                 /* NOT EXISTS is special cased above... */
3316               not_exists:
3317                 token = peek_token (&val, (unsigned *)0, cfile);
3318                 if (token != EXISTS) {
3319                         parse_warn (cfile, "expecting DNS prerequisite.");
3320                         *lose = 1;
3321                         return 0;
3322                 }
3323                 opcode = expr_ns_not_exists;
3324                 goto nsupdatecode;
3325               case TOKEN_ADD:
3326                 opcode = expr_ns_add;
3327                 goto nsupdatecode;
3328               case TOKEN_DELETE:
3329                 opcode = expr_ns_delete;
3330                 goto nsupdatecode;
3331               ns_exists:
3332                 opcode = expr_ns_exists;
3333               nsupdatecode:
3334                 token = next_token (&val, (unsigned *)0, cfile);
3335
3336 #if !defined (NSUPDATE)
3337                 parse_warn (cfile,
3338                             "Please rebuild dhcpd with --with-nsupdate.");
3339 #endif
3340                 if (!expression_allocate (expr, MDL))
3341                         log_fatal ("can't allocate expression");
3342                 (*expr) -> op = opcode;
3343
3344                 token = next_token (&val, (unsigned *)0, cfile);
3345                 if (token != LPAREN)
3346                         goto nolparen;
3347
3348                 token = next_token (&val, (unsigned *)0, cfile);
3349                 if (!is_identifier (token) && token != NUMBER) {
3350                         parse_warn (cfile, "expecting identifier or number.");
3351                       badnsop:
3352                         expression_dereference (expr, MDL);
3353                         skip_to_semi (cfile);
3354                         *lose = 1;
3355                         return 0;
3356                 }
3357                         
3358                 if (token == NUMBER)
3359                         (*expr) -> data.ns_add.rrclass = atoi (val);
3360                 else if (!strcasecmp (val, "in"))
3361                         (*expr) -> data.ns_add.rrclass = C_IN;
3362                 else if (!strcasecmp (val, "chaos"))
3363                         (*expr) -> data.ns_add.rrclass = C_CHAOS;
3364                 else if (!strcasecmp (val, "hs"))
3365                         (*expr) -> data.ns_add.rrclass = C_HS;
3366                 else {
3367                         parse_warn (cfile, "unexpected rrclass: %s", val);
3368                         goto badnsop;
3369                 }
3370                 
3371                 token = next_token (&val, (unsigned *)0, cfile);
3372                 if (token != COMMA)
3373                         goto nocomma;
3374
3375                 token = next_token (&val, (unsigned *)0, cfile);
3376                 if (!is_identifier (token) && token != NUMBER) {
3377                         parse_warn (cfile, "expecting identifier or number.");
3378                         goto badnsop;
3379                 }
3380                         
3381                 if (token == NUMBER)
3382                         (*expr) -> data.ns_add.rrtype = atoi (val);
3383                 else if (!strcasecmp (val, "a"))
3384                         (*expr) -> data.ns_add.rrtype = T_A;
3385                 else if (!strcasecmp (val, "ptr"))
3386                         (*expr) -> data.ns_add.rrtype = T_PTR;
3387                 else if (!strcasecmp (val, "mx"))
3388                         (*expr) -> data.ns_add.rrtype = T_MX;
3389                 else if (!strcasecmp (val, "cname"))
3390                         (*expr) -> data.ns_add.rrtype = T_CNAME;
3391                 else if (!strcasecmp (val, "TXT"))
3392                         (*expr) -> data.ns_add.rrtype = T_TXT;
3393                 else {
3394                         parse_warn (cfile, "unexpected rrtype: %s", val);
3395                         goto badnsop;
3396                 }
3397
3398                 token = next_token (&val, (unsigned *)0, cfile);
3399                 if (token != COMMA)
3400                         goto nocomma;
3401
3402                 if (!(parse_data_expression
3403                       (&(*expr) -> data.ns_add.rrname, cfile, lose)))
3404                         goto nodata;
3405
3406                 token = next_token (&val, (unsigned *)0, cfile);
3407                 if (token != COMMA)
3408                         goto nocomma;
3409
3410                 if (!(parse_data_expression
3411                       (&(*expr) -> data.ns_add.rrdata, cfile, lose)))
3412                         goto nodata;
3413
3414                 if (opcode == expr_ns_add) {
3415                         token = next_token (&val, (unsigned *)0, cfile);
3416                         if (token != COMMA)
3417                                 goto nocomma;
3418                         
3419                         if (!(parse_numeric_expression
3420                               (&(*expr) -> data.ns_add.ttl, cfile,
3421                                lose))) {
3422                             if (!*lose)
3423                                 parse_warn (cfile,
3424                                             "expecting numeric expression.");
3425                             goto badnsupdate;
3426                         }
3427                 }
3428
3429                 token = next_token (&val, (unsigned *)0, cfile);
3430                 if (token != RPAREN)
3431                         goto norparen;
3432                 break;
3433
3434               case OPTION:
3435               case CONFIG_OPTION:
3436                 if (!expression_allocate (expr, MDL))
3437                         log_fatal ("can't allocate expression");
3438                 (*expr) -> op = (token == OPTION
3439                                  ? expr_option
3440                                  : expr_config_option);
3441                 token = next_token (&val, (unsigned *)0, cfile);
3442                 known = 0;
3443                 (*expr) -> data.option = parse_option_name (cfile, 0, &known);
3444                 if (!(*expr) -> data.option) {
3445                         *lose = 1;
3446                         expression_dereference (expr, MDL);
3447                         return 0;
3448                 }
3449                 break;
3450
3451               case HARDWARE:
3452                 token = next_token (&val, (unsigned *)0, cfile);
3453                 if (!expression_allocate (expr, MDL))
3454                         log_fatal ("can't allocate expression");
3455                 (*expr) -> op = expr_hardware;
3456                 break;
3457
3458               case LEASED_ADDRESS:
3459                 token = next_token (&val, (unsigned *)0, cfile);
3460                 if (!expression_allocate (expr, MDL))
3461                         log_fatal ("can't allocate expression");
3462                 (*expr) -> op = expr_leased_address;
3463                 break;
3464
3465               case CLIENT_STATE:
3466                 token = next_token (&val, (unsigned *)0, cfile);
3467                 if (!expression_allocate (expr, MDL))
3468                         log_fatal ("can't allocate expression");