Merge from vendor branch LIBARCHIVE:
[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");
3469                 (*expr) -> op = expr_client_state;
3470                 break;
3471
3472               case FILENAME:
3473                 token = next_token (&val, (unsigned *)0, cfile);
3474                 if (!expression_allocate (expr, MDL))
3475                         log_fatal ("can't allocate expression");
3476                 (*expr) -> op = expr_filename;
3477                 break;
3478
3479               case SERVER_NAME:
3480                 token = next_token (&val, (unsigned *)0, cfile);
3481                 if (!expression_allocate (expr, MDL))
3482                         log_fatal ("can't allocate expression");
3483                 (*expr) -> op = expr_sname;
3484                 break;
3485
3486               case LEASE_TIME:
3487                 token = next_token (&val, (unsigned *)0, cfile);
3488                 if (!expression_allocate (expr, MDL))
3489                         log_fatal ("can't allocate expression");
3490                 (*expr) -> op = expr_lease_time;
3491                 break;
3492
3493               case TOKEN_NULL:
3494                 token = next_token (&val, (unsigned *)0, cfile);
3495                 if (!expression_allocate (expr, MDL))
3496                         log_fatal ("can't allocate expression");
3497                 (*expr) -> op = expr_null;
3498                 break;
3499
3500               case HOST_DECL_NAME:
3501                 token = next_token (&val, (unsigned *)0, cfile);
3502                 if (!expression_allocate (expr, MDL))
3503                         log_fatal ("can't allocate expression");
3504                 (*expr) -> op = expr_host_decl_name;
3505                 break;
3506
3507               case UPDATED_DNS_RR:
3508                 token = next_token (&val, (unsigned *)0, cfile);
3509
3510                 token = next_token (&val, (unsigned *)0, cfile);
3511                 if (token != LPAREN)
3512                         goto nolparen;
3513
3514                 token = next_token (&val, (unsigned *)0, cfile);
3515                 if (token != STRING) {
3516                         parse_warn (cfile, "expecting string.");
3517                       bad_rrtype:
3518                         *lose = 1;
3519                         return 0;
3520                 }
3521                 if (!strcasecmp (val, "a"))
3522                         s = "ddns-fwd-name";
3523                 else if (!strcasecmp (val, "ptr"))
3524                         s = "ddns-rev-name";
3525                 else {
3526                         parse_warn (cfile, "invalid DNS rrtype: %s", val);
3527                         goto bad_rrtype;
3528                 }
3529
3530                 token = next_token (&val, (unsigned *)0, cfile);
3531                 if (token != RPAREN)
3532                         goto norparen;
3533
3534                 if (!expression_allocate (expr, MDL))
3535                         log_fatal ("can't allocate expression");
3536                 (*expr) -> op = expr_variable_reference;
3537                 (*expr) -> data.variable =
3538                         dmalloc (strlen (s) + 1, MDL);
3539                 if (!(*expr) -> data.variable)
3540                         log_fatal ("can't allocate variable name.");
3541                 strcpy ((*expr) -> data.variable, s);
3542                 break;
3543
3544               case PACKET:
3545                 token = next_token (&val, (unsigned *)0, cfile);
3546                 if (!expression_allocate (expr, MDL))
3547                         log_fatal ("can't allocate expression");
3548                 (*expr) -> op = expr_packet;
3549
3550                 token = next_token (&val, (unsigned *)0, cfile);
3551                 if (token != LPAREN)
3552                         goto nolparen;
3553
3554                 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
3555                                                cfile, lose))
3556                         goto nonum;
3557
3558                 token = next_token (&val, (unsigned *)0, cfile);
3559                 if (token != COMMA)
3560                         goto nocomma;
3561
3562                 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
3563                                                cfile, lose))
3564                         goto nonum;
3565
3566                 token = next_token (&val, (unsigned *)0, cfile);
3567                 if (token != RPAREN)
3568                         goto norparen;
3569                 break;
3570                 
3571               case STRING:
3572                 token = next_token (&val, &len, cfile);
3573                 if (!make_const_data (expr, (const unsigned char *)val,
3574                                       len, 1, 1, MDL))
3575                         log_fatal ("can't make constant string expression.");
3576                 break;
3577
3578               case EXTRACT_INT:
3579                 token = next_token (&val, (unsigned *)0, cfile);        
3580                 token = next_token (&val, (unsigned *)0, cfile);
3581                 if (token != LPAREN) {
3582                         parse_warn (cfile, "left parenthesis expected.");
3583                         *lose = 1;
3584                         return 0;
3585                 }
3586
3587                 if (!expression_allocate (expr, MDL))
3588                         log_fatal ("can't allocate expression");
3589
3590                 if (!parse_data_expression (&(*expr) -> data.extract_int,
3591                                             cfile, lose)) {
3592                         if (!*lose) {
3593                                 parse_warn (cfile,
3594                                             "expecting data expression.");
3595                                 skip_to_semi (cfile);
3596                                 *lose = 1;
3597                         }
3598                         expression_dereference (expr, MDL);
3599                         return 0;
3600                 }
3601
3602                 token = next_token (&val, (unsigned *)0, cfile);
3603                 if (token != COMMA) {
3604                         parse_warn (cfile, "comma expected.");
3605                         *lose = 1;
3606                         expression_dereference (expr, MDL);
3607                         return 0;
3608                 }
3609
3610                 token = next_token (&val, (unsigned *)0, cfile);
3611                 if (token != NUMBER) {
3612                         parse_warn (cfile, "number expected.");
3613                         *lose = 1;
3614                         expression_dereference (expr, MDL);
3615                         return 0;
3616                 }
3617                 switch (atoi (val)) {
3618                       case 8:
3619                         (*expr) -> op = expr_extract_int8;
3620                         break;
3621
3622                       case 16:
3623                         (*expr) -> op = expr_extract_int16;
3624                         break;
3625
3626                       case 32:
3627                         (*expr) -> op = expr_extract_int32;
3628                         break;
3629
3630                       default:
3631                         parse_warn (cfile,
3632                                     "unsupported integer size %d", atoi (val));
3633                         *lose = 1;
3634                         skip_to_semi (cfile);
3635                         expression_dereference (expr, MDL);
3636                         return 0;
3637                 }
3638
3639                 token = next_token (&val, (unsigned *)0, cfile);
3640                 if (token != RPAREN) {
3641                         parse_warn (cfile, "right parenthesis expected.");
3642                         *lose = 1;
3643                         expression_dereference (expr, MDL);
3644                         return 0;
3645                 }
3646                 break;
3647         
3648               case ENCODE_INT:
3649                 token = next_token (&val, (unsigned *)0, cfile);        
3650                 token = next_token (&val, (unsigned *)0, cfile);
3651                 if (token != LPAREN) {
3652                         parse_warn (cfile, "left parenthesis expected.");
3653                         *lose = 1;
3654                         return 0;
3655                 }
3656
3657                 if (!expression_allocate (expr, MDL))
3658                         log_fatal ("can't allocate expression");
3659
3660                 if (!parse_numeric_expression (&(*expr) -> data.encode_int,
3661                                                cfile, lose)) {
3662                         parse_warn (cfile, "expecting numeric expression.");
3663                         skip_to_semi (cfile);
3664                         *lose = 1;
3665                         expression_dereference (expr, MDL);
3666                         return 0;
3667                 }
3668
3669                 token = next_token (&val, (unsigned *)0, cfile);
3670                 if (token != COMMA) {
3671                         parse_warn (cfile, "comma expected.");
3672                         *lose = 1;
3673                         expression_dereference (expr, MDL);
3674                         return 0;
3675                 }
3676
3677                 token = next_token (&val, (unsigned *)0, cfile);
3678                 if (token != NUMBER) {
3679                         parse_warn (cfile, "number expected.");
3680                         *lose = 1;
3681                         expression_dereference (expr, MDL);
3682                         return 0;
3683                 }
3684                 switch (atoi (val)) {
3685                       case 8:
3686                         (*expr) -> op = expr_encode_int8;
3687                         break;
3688
3689                       case 16:
3690                         (*expr) -> op = expr_encode_int16;
3691                         break;
3692
3693                       case 32:
3694                         (*expr) -> op = expr_encode_int32;
3695                         break;
3696
3697                       default:
3698                         parse_warn (cfile,
3699                                     "unsupported integer size %d", atoi (val));
3700                         *lose = 1;
3701                         skip_to_semi (cfile);
3702                         expression_dereference (expr, MDL);
3703                         return 0;
3704                 }
3705
3706                 token = next_token (&val, (unsigned *)0, cfile);
3707                 if (token != RPAREN) {
3708                         parse_warn (cfile, "right parenthesis expected.");
3709                         *lose = 1;
3710                         expression_dereference (expr, MDL);
3711                         return 0;
3712                 }
3713                 break;
3714         
3715               case NUMBER:
3716                 /* If we're in a numeric context, this should just be a
3717                    number, by itself. */
3718                 if (context == context_numeric ||
3719                     context == context_data_or_numeric) {
3720                         next_token (&val, (unsigned *)0, cfile);
3721                         if (!expression_allocate (expr, MDL))
3722                                 log_fatal ("can't allocate expression");
3723                         (*expr) -> op = expr_const_int;
3724                         (*expr) -> data.const_int = atoi (val);
3725                         break;
3726                 }
3727
3728               case NUMBER_OR_NAME:
3729                 if (!expression_allocate (expr, MDL))
3730                         log_fatal ("can't allocate expression");
3731
3732                 (*expr) -> op = expr_const_data;
3733                 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
3734                         expression_dereference (expr, MDL);
3735                         return 0;
3736                 }
3737                 break;
3738
3739               case NS_FORMERR:
3740                 known = FORMERR;
3741                 goto ns_const;
3742               ns_const:
3743                 token = next_token (&val, (unsigned *)0, cfile);
3744                 if (!expression_allocate (expr, MDL))
3745                         log_fatal ("can't allocate expression");
3746                 (*expr) -> op = expr_const_int;
3747                 (*expr) -> data.const_int = known;
3748                 break;
3749                 
3750               case NS_NOERROR:
3751                 known = ISC_R_SUCCESS;
3752                 goto ns_const;
3753
3754               case NS_NOTAUTH:
3755                 known = ISC_R_NOTAUTH;
3756                 goto ns_const;
3757
3758               case NS_NOTIMP:
3759                 known = ISC_R_NOTIMPLEMENTED;
3760                 goto ns_const;
3761
3762               case NS_NOTZONE:
3763                 known = ISC_R_NOTZONE;
3764                 goto ns_const;
3765
3766               case NS_NXDOMAIN:
3767                 known = ISC_R_NXDOMAIN;
3768                 goto ns_const;
3769
3770               case NS_NXRRSET:
3771                 known = ISC_R_NXRRSET;
3772                 goto ns_const;
3773
3774               case NS_REFUSED:
3775                 known = ISC_R_REFUSED;
3776                 goto ns_const;
3777
3778               case NS_SERVFAIL:
3779                 known = ISC_R_SERVFAIL;
3780                 goto ns_const;
3781
3782               case NS_YXDOMAIN:
3783                 known = ISC_R_YXDOMAIN;
3784                 goto ns_const;
3785
3786               case NS_YXRRSET:
3787                 known = ISC_R_YXRRSET;
3788                 goto ns_const;
3789
3790               case BOOTING:
3791                 known = S_INIT;
3792                 goto ns_const;
3793
3794               case REBOOT:
3795                 known = S_REBOOTING;
3796                 goto ns_const;
3797
3798               case SELECT:
3799                 known = S_SELECTING;
3800                 goto ns_const;
3801
3802               case REQUEST:
3803                 known = S_REQUESTING;
3804                 goto ns_const;
3805
3806               case BOUND:
3807                 known = S_BOUND;
3808                 goto ns_const;
3809
3810               case RENEW:
3811                 known = S_RENEWING;
3812                 goto ns_const;
3813
3814               case REBIND:
3815                 known = S_REBINDING;
3816                 goto ns_const;
3817
3818               case DEFINED:
3819                 token = next_token (&val, (unsigned *)0, cfile);
3820                 token = next_token (&val, (unsigned *)0, cfile);
3821                 if (token != LPAREN)
3822                         goto nolparen;
3823
3824                 token = next_token (&val, (unsigned *)0, cfile);
3825                 if (token != NAME && token != NUMBER_OR_NAME) {
3826                         parse_warn (cfile, "%s can't be a variable name", val);
3827                         skip_to_semi (cfile);
3828                         *lose = 1;
3829                         return 0;
3830                 }
3831
3832                 if (!expression_allocate (expr, MDL))
3833                         log_fatal ("can't allocate expression");
3834                 (*expr) -> op = expr_variable_exists;
3835                 (*expr) -> data.variable = dmalloc (strlen (val) + 1, MDL);
3836                 if (!(*expr)->data.variable)
3837                         log_fatal ("can't allocate variable name");
3838                 strcpy ((*expr) -> data.variable, val);
3839                 token = next_token (&val, (unsigned *)0, cfile);
3840                 if (token != RPAREN)
3841                         goto norparen;
3842                 break;
3843
3844                 /* Not a valid start to an expression... */
3845               default:
3846                 if (token != NAME && token != NUMBER_OR_NAME)
3847                         return 0;
3848
3849                 token = next_token (&val, (unsigned *)0, cfile);
3850
3851                 /* Save the name of the variable being referenced. */
3852                 cptr = dmalloc (strlen (val) + 1, MDL);
3853                 if (!cptr)
3854                         log_fatal ("can't allocate variable name");
3855                 strcpy (cptr, val);
3856
3857                 /* Simple variable reference, as far as we can tell. */
3858                 token = peek_token (&val, (unsigned *)0, cfile);
3859                 if (token != LPAREN) {
3860                         if (!expression_allocate (expr, MDL))
3861                                 log_fatal ("can't allocate expression");
3862                         (*expr) -> op = expr_variable_reference;
3863                         (*expr) -> data.variable = cptr;
3864                         break;
3865                 }
3866
3867                 token = next_token (&val, (unsigned *)0, cfile);
3868                 if (!expression_allocate (expr, MDL))
3869                         log_fatal ("can't allocate expression");
3870                 (*expr) -> op = expr_funcall;
3871                 (*expr) -> data.funcall.name = cptr;
3872
3873                 /* Now parse the argument list. */
3874                 ep = &(*expr) -> data.funcall.arglist;
3875                 do {
3876                         if (!expression_allocate (ep, MDL))
3877                                 log_fatal ("can't allocate expression");
3878                         (*ep) -> op = expr_arg;
3879                         if (!parse_expression (&(*ep) -> data.arg.val,
3880                                                cfile, lose, context_any,
3881                                                (struct expression **)0,
3882                                                expr_none)) {
3883                                 if (!*lose) {
3884                                         parse_warn (cfile,
3885                                                     "expecting expression.");
3886                                         *lose = 1;
3887                                 }
3888                                 skip_to_semi (cfile);
3889                                 expression_dereference (expr, MDL);
3890                                 return 0;
3891                         }
3892                         ep = &((*ep) -> data.arg.next);
3893                         token = next_token (&val, (unsigned *)0, cfile);
3894                 } while (token == COMMA);
3895                 if (token != RPAREN) {
3896                         parse_warn (cfile, "Right parenthesis expected.");
3897                         skip_to_semi (cfile);
3898                         *lose = 1;
3899                         expression_dereference (expr, MDL);
3900                         return 0;
3901                 }
3902                 break;
3903         }
3904         return 1;
3905 }
3906
3907 /* Parse an expression. */
3908
3909 int parse_expression (expr, cfile, lose, context, plhs, binop)
3910         struct expression **expr;
3911         struct parse *cfile;
3912         int *lose;
3913         enum expression_context context;
3914         struct expression **plhs;
3915         enum expr_op binop;
3916 {
3917         enum dhcp_token token;
3918         const char *val;
3919         struct expression *rhs = (struct expression *)0, *tmp;
3920         struct expression *lhs = (struct expression *)0;
3921         enum expr_op next_op;
3922         enum expression_context
3923                 lhs_context = context_any,
3924                 rhs_context = context_any;
3925
3926         /* Consume the left hand side we were passed. */
3927         if (plhs) {
3928                 expression_reference (&lhs, *plhs, MDL);
3929                 expression_dereference (plhs, MDL);
3930         }
3931
3932       new_rhs:
3933         if (!parse_non_binary (&rhs, cfile, lose, context)) {
3934                 /* If we already have a left-hand side, then it's not
3935                    okay for there not to be a right-hand side here, so
3936                    we need to flag it as an error. */
3937                 if (lhs) {
3938                         if (!*lose) {
3939                                 parse_warn (cfile,
3940                                             "expecting right-hand side.");
3941                                 *lose = 1;
3942                                 skip_to_semi (cfile);
3943                         }
3944                         expression_dereference (&lhs, MDL);
3945                 }
3946                 return 0;
3947         }
3948
3949         /* At this point, rhs contains either an entire subexpression,
3950            or at least a left-hand-side.   If we do not see a binary token
3951            as the next token, we're done with the expression. */
3952
3953         token = peek_token (&val, (unsigned *)0, cfile);
3954         switch (token) {
3955               case BANG:
3956                 token = next_token (&val, (unsigned *)0, cfile);
3957                 token = peek_token (&val, (unsigned *)0, cfile);
3958                 if (token != EQUAL) {
3959                         parse_warn (cfile, "! in boolean context without =");
3960                         *lose = 1;
3961                         skip_to_semi (cfile);
3962                         if (lhs)
3963                                 expression_dereference (&lhs, MDL);
3964                         return 0;
3965                 }
3966                 next_op = expr_not_equal;
3967                 context = expression_context (rhs);
3968                 break;
3969
3970               case EQUAL:
3971                 next_op = expr_equal;
3972                 context = expression_context (rhs);
3973                 break;
3974
3975               case AND:
3976                 next_op = expr_and;
3977                 context = expression_context (rhs);
3978                 break;
3979
3980               case OR:
3981                 next_op = expr_or;
3982                 context = expression_context (rhs);
3983                 break;
3984
3985               case PLUS:
3986                 next_op = expr_add;
3987                 context = expression_context (rhs);
3988                 break;
3989
3990               case MINUS:
3991                 next_op = expr_subtract;
3992                 context = expression_context (rhs);
3993                 break;
3994
3995               case SLASH:
3996                 next_op = expr_divide;
3997                 context = expression_context (rhs);
3998                 break;
3999
4000               case ASTERISK:
4001                 next_op = expr_multiply;
4002                 context = expression_context (rhs);
4003                 break;
4004
4005               case PERCENT:
4006                 next_op = expr_remainder;
4007                 context = expression_context (rhs);
4008                 break;
4009
4010               case AMPERSAND:
4011                 next_op = expr_binary_and;
4012                 context = expression_context (rhs);
4013                 break;
4014
4015               case PIPE:
4016                 next_op = expr_binary_or;
4017                 context = expression_context (rhs);
4018                 break;
4019
4020               case CARET:
4021                 next_op = expr_binary_xor;
4022                 context = expression_context (rhs);
4023                 break;
4024
4025               default:
4026                 next_op = expr_none;
4027         }
4028
4029         /* If we have no lhs yet, we just parsed it. */
4030         if (!lhs) {
4031                 /* If there was no operator following what we just parsed,
4032                    then we're done - return it. */
4033                 if (next_op == expr_none) {
4034                         *expr = rhs;
4035                         return 1;
4036                 }
4037                 lhs = rhs;
4038                 rhs = (struct expression *)0;
4039                 binop = next_op;
4040                 next_token (&val, (unsigned *)0, cfile);
4041                 goto new_rhs;
4042         }
4043
4044         if (binop != expr_none) {
4045           rhs_context = expression_context(rhs);
4046           lhs_context = expression_context(lhs);
4047
4048           if ((rhs_context != context_any) && (lhs_context != context_any) &&
4049                         (rhs_context != lhs_context)) {
4050             parse_warn (cfile, "illegal expression relating different types");
4051             skip_to_semi (cfile);
4052             expression_dereference (&rhs, MDL);
4053             expression_dereference (&lhs, MDL);
4054             *lose = 1;
4055             return 0;
4056           }
4057
4058           switch(binop) {
4059             case expr_not_equal:
4060             case expr_equal:
4061                 if ((rhs_context != context_data_or_numeric) &&
4062                     (rhs_context != context_data) &&
4063                     (rhs_context != context_numeric) &&
4064                     (rhs_context != context_any)) {
4065                         parse_warn (cfile, "expecting data/numeric expression");
4066                         skip_to_semi (cfile);
4067                         expression_dereference (&rhs, MDL);
4068                         *lose = 1;
4069                         return 0;
4070                 }
4071                 break;
4072
4073             case expr_and:
4074             case expr_or:
4075                 if ((rhs_context != context_boolean) &&
4076                     (rhs_context != context_any)) {
4077                         parse_warn (cfile, "expecting boolean expressions");
4078                         skip_to_semi (cfile);
4079                         expression_dereference (&rhs, MDL);
4080                         *lose = 1;
4081                         return 0;
4082                 }
4083                 break;
4084
4085             case expr_add:
4086             case expr_subtract:
4087             case expr_divide:
4088             case expr_multiply:
4089             case expr_remainder:
4090             case expr_binary_and:
4091             case expr_binary_or:
4092             case expr_binary_xor:
4093                 if ((rhs_context != context_numeric) &&
4094                     (rhs_context != context_any)) {
4095                         parse_warn (cfile, "expecting numeric expressions");
4096                         skip_to_semi (cfile);
4097                         expression_dereference (&rhs, MDL);
4098                         *lose = 1;
4099                         return 0;
4100                 }
4101                 break;
4102
4103             default:
4104                 break;
4105           }
4106         }
4107
4108         /* Now, if we didn't find a binary operator, we're done parsing
4109            this subexpression, so combine it with the preceding binary
4110            operator and return the result. */
4111         if (next_op == expr_none) {
4112                 if (!expression_allocate (expr, MDL))
4113                         log_fatal ("Can't allocate expression!");
4114
4115                 (*expr) -> op = binop;
4116                 /* All the binary operators' data union members
4117                    are the same, so we'll cheat and use the member
4118                    for the equals operator. */
4119                 (*expr) -> data.equal [0] = lhs;
4120                 (*expr) -> data.equal [1] = rhs;
4121                 return 1;
4122         }
4123
4124         /* Eat the operator token - we now know it was a binary operator... */
4125         token = next_token (&val, (unsigned *)0, cfile);
4126
4127         /* If the binary operator we saw previously has a lower precedence
4128            than the next operator, then the rhs we just parsed for that
4129            operator is actually the lhs of the operator with the higher
4130            precedence - to get the real rhs, we need to recurse on the
4131            new operator. */
4132         if (binop != expr_none &&
4133             op_precedence (binop, next_op) < 0) {
4134                 tmp = rhs;
4135                 rhs = (struct expression *)0;
4136                 if (!parse_expression (&rhs, cfile, lose, op_context (next_op),
4137                                        &tmp, next_op)) {
4138                         if (!*lose) {
4139                                 parse_warn (cfile,
4140                                             "expecting a subexpression");
4141                                 *lose = 1;
4142                         }
4143                         return 0;
4144                 }
4145                 next_op = expr_none;
4146         }
4147
4148         /* Now combine the LHS and the RHS using binop. */
4149         tmp = (struct expression *)0;
4150         if (!expression_allocate (&tmp, MDL))
4151                 log_fatal ("No memory for equal precedence combination.");
4152         
4153         /* Store the LHS and RHS. */
4154         tmp -> data.equal [0] = lhs;
4155         tmp -> data.equal [1] = rhs;
4156         tmp -> op = binop;
4157         
4158         lhs = tmp;
4159         tmp = (struct expression *)0;
4160         rhs = (struct expression *)0;
4161
4162         /* Recursions don't return until we have parsed the end of the
4163            expression, so if we recursed earlier, we can now return what
4164            we got. */
4165         if (next_op == expr_none) {
4166                 *expr = lhs;
4167                 return 1;
4168         }
4169
4170         binop = next_op;
4171         goto new_rhs;
4172 }       
4173
4174 /* option-statement :== identifier DOT identifier <syntax> SEMI
4175                       | identifier <syntax> SEMI
4176
4177    Option syntax is handled specially through format strings, so it
4178    would be painful to come up with BNF for it.   However, it always
4179    starts as above and ends in a SEMI. */
4180
4181 int parse_option_statement (result, cfile, lookups, option, op)
4182         struct executable_statement **result;
4183         struct parse *cfile;
4184         int lookups;
4185         struct option *option;
4186         enum statement_op op;
4187 {
4188         const char *val;
4189         enum dhcp_token token;
4190         const char *fmt = NULL;
4191         struct expression *expr = (struct expression *)0;
4192         struct expression *tmp;
4193         int lose;
4194         struct executable_statement *stmt;
4195         int ftt = 1;
4196
4197         token = peek_token (&val, (unsigned *)0, cfile);
4198         if (token == SEMI) {
4199                 /* Eat the semicolon... */
4200                 token = next_token (&val, (unsigned *)0, cfile);
4201                 goto done;
4202         }
4203
4204         if (token == EQUAL) {
4205                 /* Eat the equals sign. */
4206                 token = next_token (&val, (unsigned *)0, cfile);
4207
4208                 /* Parse a data expression and use its value for the data. */
4209                 if (!parse_data_expression (&expr, cfile, &lose)) {
4210                         /* In this context, we must have an executable
4211                            statement, so if we found something else, it's
4212                            still an error. */
4213                         if (!lose) {
4214                                 parse_warn (cfile,
4215                                             "expecting a data expression.");
4216                                 skip_to_semi (cfile);
4217                         }
4218                         return 0;
4219                 }
4220
4221                 /* We got a valid expression, so use it. */
4222                 goto done;
4223         }
4224
4225         /* Parse the option data... */
4226         do {
4227                 /* Set a flag if this is an array of a simple type (i.e.,
4228                    not an array of pairs of IP addresses, or something
4229                    like that. */
4230                 int uniform = option -> format [1] == 'A';
4231
4232               and_again:
4233                 /* Set fmt to start of format for 'A' and one char back
4234                    for 'a' */
4235                 if ((fmt != NULL) &&
4236                     (fmt != option -> format) && (*fmt == 'a'))
4237                         fmt -= 1;
4238                 else
4239                         fmt = ((fmt == NULL) ||
4240                                (*fmt == 'A')) ? option -> format : fmt;
4241
4242                 /* 'a' means always uniform */
4243                 uniform |= (fmt [1] == 'a');
4244
4245                 for ( ; *fmt; fmt++) {
4246                         if ((*fmt == 'A') || (*fmt == 'a'))
4247                                 break;
4248                         if (*fmt == 'o')
4249                                 continue;
4250                         tmp = expr;
4251                         expr = (struct expression *)0;
4252                         if (!parse_option_token (&expr, cfile, &fmt,
4253                                                  tmp, uniform, lookups)) {
4254                                 if (fmt [1] != 'o') {
4255                                         if (tmp)
4256                                                 expression_dereference (&tmp,
4257                                                                         MDL);
4258                                         return 0;
4259                                 }
4260                                 expr = tmp;
4261                                 tmp = (struct expression *)0;
4262                         }
4263                         if (tmp)
4264                                 expression_dereference (&tmp, MDL);
4265                 }
4266                 if ((*fmt == 'A') || (*fmt == 'a')) {
4267                         token = peek_token (&val, (unsigned *)0, cfile);
4268                         /* Comma means: continue with next element in array */
4269                         if (token == COMMA) {
4270                                 token = next_token (&val,
4271                                                     (unsigned *)0, cfile);
4272                                 continue;
4273                         }
4274                         /* no comma: end of array.
4275                            'A' or end of string means: leave the loop */
4276                         if ((*fmt == 'A') || (fmt[1] == '\0'))
4277                                 break;
4278                         /* 'a' means: go on with next char */
4279                         if (*fmt == 'a') {
4280                                 fmt++;
4281                                 goto and_again;
4282                         }
4283                 }
4284         } while ((*fmt == 'A') || (*fmt == 'a'));
4285
4286       done:
4287         if (!parse_semi (cfile))
4288                 return 0;
4289         if (!executable_statement_allocate (result, MDL))
4290                 log_fatal ("no memory for option statement.");
4291         (*result) -> op = op;
4292         if (expr && !option_cache (&(*result) -> data.option,
4293                                    (struct data_string *)0, expr, option, MDL))
4294                 log_fatal ("no memory for option cache");
4295         if (expr)
4296                 expression_dereference (&expr, MDL);
4297         return 1;
4298 }
4299
4300 int parse_option_token (rv, cfile, fmt, expr, uniform, lookups)
4301         struct expression **rv;
4302         struct parse *cfile;
4303         const char **fmt;
4304         struct expression *expr;
4305         int uniform;
4306         int lookups;
4307 {
4308         const char *val;
4309         enum dhcp_token token;
4310         struct expression *t = (struct expression *)0;
4311         unsigned char buf [4];
4312         unsigned len;
4313         unsigned char *ob;
4314         struct iaddr addr;
4315         int num;
4316         const char *f, *g;
4317         struct enumeration_value *e;
4318
4319         switch (**fmt) {
4320               case 'U':
4321                 token = peek_token (&val, (unsigned *)0, cfile);
4322                 if (!is_identifier (token)) {
4323                         if ((*fmt) [1] != 'o') {
4324                                 parse_warn (cfile, "expecting identifier.");
4325                                 skip_to_semi (cfile);
4326                         }
4327                         return 0;
4328                 }
4329                 token = next_token (&val, &len, cfile);
4330                 if (!make_const_data (&t, (const unsigned char *)val,
4331                                       len, 1, 1, MDL))
4332                         log_fatal ("No memory for %s", val);
4333                 break;
4334
4335               case 'E':
4336                 g = strchr (*fmt, '.');
4337                 if (!g) {
4338                         parse_warn (cfile,
4339                                     "malformed encapsulation format (bug!)");
4340                         skip_to_semi (cfile);
4341                         return 0;
4342                 }
4343                 *fmt = g;
4344               case 'X':
4345                 token = peek_token (&val, (unsigned *)0, cfile);
4346                 if (token == NUMBER_OR_NAME || token == NUMBER) {
4347                         if (!expression_allocate (&t, MDL))
4348                                 return 0;
4349                         if (!parse_cshl (&t -> data.const_data, cfile)) {
4350                                 expression_dereference (&t, MDL);
4351                                 return 0;
4352                         }
4353                         t -> op = expr_const_data;
4354                 } else if (token == STRING) {
4355                         token = next_token (&val, &len, cfile);
4356                         if (!make_const_data (&t, (const unsigned char *)val,
4357                                               len, 1, 1, MDL))
4358                                 log_fatal ("No memory for \"%s\"", val);
4359                 } else {
4360                         if ((*fmt) [1] != 'o') {
4361                                 parse_warn (cfile, "expecting string %s.",
4362                                             "or hexadecimal data");
4363                                 skip_to_semi (cfile);
4364                         }
4365                         return 0;
4366                 }
4367                 break;
4368                 
4369               case 'd': /* Domain name... */
4370                 val = parse_host_name (cfile);
4371                 if (!val) {
4372                         parse_warn (cfile, "not a valid domain name.");
4373                         skip_to_semi (cfile);
4374                         return 0;
4375                 }
4376                 len = strlen (val);
4377                 goto make_string;
4378
4379               case 't': /* Text string... */
4380                 token = peek_token (&val, (unsigned *)0, cfile);
4381                 if (token != STRING && !is_identifier (token)) {
4382                         if ((*fmt) [1] != 'o') {
4383                                 parse_warn (cfile, "expecting string.");
4384                                 if (token != SEMI)
4385                                         skip_to_semi (cfile);
4386                         }
4387                         return 0;
4388                 }
4389                 token = next_token (&val, &len, cfile);
4390               make_string:
4391                 if (!make_const_data (&t, (const unsigned char *)val,
4392                                       len, 1, 1, MDL))
4393                         log_fatal ("No memory for concatenation");
4394                 break;
4395                 
4396               case 'N':
4397                 f = (*fmt) + 1;
4398                 g = strchr (*fmt, '.');
4399                 if (!g) {
4400                         parse_warn (cfile, "malformed %s (bug!)",
4401                                     "enumeration format");
4402                       foo:
4403                         skip_to_semi (cfile);
4404                         return 0;
4405                 }
4406                 *fmt = g;
4407                 token = next_token (&val, (unsigned *)0, cfile);
4408                 if (!is_identifier (token)) {
4409                         parse_warn (cfile,
4410                                     "identifier expected");
4411                         goto foo;
4412                 }
4413                 e = find_enumeration_value (f, (*fmt) - f, val);
4414                 if (!e) {
4415                         parse_warn (cfile, "unknown value");
4416                         goto foo;
4417                 }
4418                 if (!make_const_data (&t, &e -> value, 1, 0, 1, MDL))
4419                         return 0;
4420                 break;
4421
4422               case 'I': /* IP address or hostname. */
4423                 if (lookups) {
4424                         if (!parse_ip_addr_or_hostname (&t, cfile, uniform))
4425                                 return 0;
4426                 } else {
4427                         if (!parse_ip_addr (cfile, &addr))
4428                                 return 0;
4429                         if (!make_const_data (&t, addr.iabuf, addr.len,
4430                                               0, 1, MDL))
4431                                 return 0;
4432                 }
4433                 break;
4434                 
4435               case 'T': /* Lease interval. */
4436                 token = peek_token (&val, (unsigned *)0, cfile);
4437                 if (token != INFINITE)
4438                         goto check_number;
4439                 token = next_token (&val, (unsigned *)0, cfile);
4440                 putLong (buf, -1);
4441                 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4442                         return 0;
4443                 break;
4444
4445               case 'L': /* Unsigned 32-bit integer... */
4446               case 'l': /* Signed 32-bit integer... */
4447                 token = peek_token (&val, (unsigned *)0, cfile);
4448               check_number:
4449                 if (token != NUMBER) {
4450                       need_number:
4451                         if ((*fmt) [1] != 'o') {
4452                                 parse_warn (cfile, "expecting number.");
4453                                 if (token != SEMI)
4454                                         skip_to_semi (cfile);
4455                         }
4456                         return 0;
4457                 }
4458                 token = next_token (&val, (unsigned *)0, cfile);
4459                 convert_num (cfile, buf, val, 0, 32);
4460                 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
4461                         return 0;
4462                 break;
4463
4464               case 's': /* Signed 16-bit integer. */
4465               case 'S': /* Unsigned 16-bit integer. */
4466                 token = peek_token (&val, (unsigned *)0, cfile);
4467                 if (token != NUMBER)
4468                         goto need_number;
4469                 token = next_token (&val, (unsigned *)0, cfile);
4470                 convert_num (cfile, buf, val, 0, 16);
4471                 if (!make_const_data (&t, buf, 2, 0, 1, MDL))
4472                         return 0;
4473                 break;
4474
4475               case 'b': /* Signed 8-bit integer. */
4476               case 'B': /* Unsigned 8-bit integer. */
4477                 token = peek_token (&val, (unsigned *)0, cfile);
4478                 if (token != NUMBER)
4479                         goto need_number;
4480                 token = next_token (&val, (unsigned *)0, cfile);
4481                 convert_num (cfile, buf, val, 0, 8);
4482                 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4483                         return 0;
4484                 break;
4485
4486               case 'f': /* Boolean flag. */
4487                 token = peek_token (&val, (unsigned *)0, cfile);
4488                 if (!is_identifier (token)) {
4489                         if ((*fmt) [1] != 'o')
4490                                 parse_warn (cfile, "expecting identifier.");
4491                       bad_flag:
4492                         if ((*fmt) [1] != 'o') {
4493                                 if (token != SEMI)
4494                                         skip_to_semi (cfile);
4495                         }
4496                         return 0;
4497                 }
4498                 if (!strcasecmp (val, "true")
4499                     || !strcasecmp (val, "on"))
4500                         buf [0] = 1;
4501                 else if (!strcasecmp (val, "false")
4502                          || !strcasecmp (val, "off"))
4503                         buf [0] = 0;
4504                 else if (!strcasecmp (val, "ignore"))
4505                         buf [0] = 2;
4506                 else {
4507                         if ((*fmt) [1] != 'o')
4508                                 parse_warn (cfile, "expecting boolean.");
4509                         goto bad_flag;
4510                 }
4511                 token = next_token (&val, (unsigned *)0, cfile);
4512                 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
4513                         return 0;
4514                 break;
4515
4516               default:
4517                 parse_warn (cfile, "Bad format %c in parse_option_token.",
4518                             **fmt);
4519                 skip_to_semi (cfile);
4520                 return 0;
4521         }
4522         if (expr) {
4523                 if (!make_concat (rv, expr, t))
4524                         return 0;
4525         } else
4526                 expression_reference (rv, t, MDL);
4527         expression_dereference (&t, MDL);
4528         return 1;
4529 }
4530
4531 int parse_option_decl (oc, cfile)
4532         struct option_cache **oc;
4533         struct parse *cfile;
4534 {
4535         const char *val;
4536         int token;
4537         u_int8_t buf [4];
4538         u_int8_t hunkbuf [1024];
4539         unsigned hunkix = 0;
4540         const char *fmt, *f;
4541         struct option *option;
4542         struct iaddr ip_addr;
4543         u_int8_t *dp;
4544         unsigned len;
4545         int nul_term = 0;
4546         struct buffer *bp;
4547         int known = 0;
4548         struct enumeration_value *e;
4549
4550         option = parse_option_name (cfile, 0, &known);
4551         if (!option)
4552                 return 0;
4553
4554         /* Parse the option data... */
4555         do {
4556                 /* Set a flag if this is an array of a simple type (i.e.,
4557                    not an array of pairs of IP addresses, or something
4558                    like that. */
4559                 int uniform = option -> format [1] == 'A';
4560
4561                 for (fmt = option -> format; *fmt; fmt++) {
4562                         if (*fmt == 'A')
4563                                 break;
4564                         switch (*fmt) {
4565                               case 'E':
4566                                 fmt = strchr (fmt, '.');
4567                                 if (!fmt) {
4568                                         parse_warn (cfile,
4569                                                     "malformed %s (bug!)",
4570                                                     "encapsulation format");
4571                                         skip_to_semi (cfile);
4572                                         return 0;
4573                                 }
4574                               case 'X':
4575                                 len = parse_X (cfile, &hunkbuf [hunkix],
4576                                                sizeof hunkbuf - hunkix);
4577                                 hunkix += len;
4578                                 break;
4579                                         
4580                               case 't': /* Text string... */
4581                                 token = next_token (&val,
4582                                                     &len, cfile);
4583                                 if (token != STRING) {
4584                                         parse_warn (cfile,
4585                                                     "expecting string.");
4586                                         skip_to_semi (cfile);
4587                                         return 0;
4588                                 }
4589                                 if (hunkix + len + 1 > sizeof hunkbuf) {
4590                                         parse_warn (cfile,
4591                                                     "option data buffer %s",
4592                                                     "overflow");
4593                                         skip_to_semi (cfile);
4594                                         return 0;
4595                                 }
4596                                 memcpy (&hunkbuf [hunkix], val, len + 1);
4597                                 nul_term = 1;
4598                                 hunkix += len;
4599                                 break;
4600
4601                               case 'N':
4602                                 f = fmt;
4603                                 fmt = strchr (fmt, '.');
4604                                 if (!fmt) {
4605                                         parse_warn (cfile,
4606                                                     "malformed %s (bug!)",
4607                                                     "enumeration format");
4608                                       foo:
4609                                         skip_to_semi (cfile);
4610                                         return 0;
4611                                 }
4612                                 token = next_token (&val,
4613                                                     (unsigned *)0, cfile);
4614                                 if (!is_identifier (token)) {
4615                                         parse_warn (cfile,
4616                                                     "identifier expected");
4617                                         goto foo;
4618                                 }
4619                                 e = find_enumeration_value (f, fmt - f, val);
4620                                 if (!e) {
4621                                         parse_warn (cfile,
4622                                                     "unknown value");
4623                                         goto foo;
4624                                 }
4625                                 len = 1;
4626                                 dp = &e -> value;
4627                                 goto alloc;
4628
4629                               case 'I': /* IP address. */
4630                                 if (!parse_ip_addr (cfile, &ip_addr))
4631                                         return 0;
4632                                 len = ip_addr.len;
4633                                 dp = ip_addr.iabuf;
4634
4635                               alloc:
4636                                 if (hunkix + len > sizeof hunkbuf) {
4637                                         parse_warn (cfile,
4638                                                     "option data buffer %s",
4639                                                     "overflow");
4640                                         skip_to_semi (cfile);
4641                                         return 0;
4642                                 }
4643                                 memcpy (&hunkbuf [hunkix], dp, len);
4644                                 hunkix += len;
4645                                 break;
4646
4647                               case 'L': /* Unsigned 32-bit integer... */
4648                               case 'l': /* Signed 32-bit integer... */
4649                                 token = next_token (&val,
4650                                                     (unsigned *)0, cfile);
4651                                 if (token != NUMBER) {
4652                                       need_number:
4653                                         parse_warn (cfile,
4654                                                     "expecting number.");
4655                                         if (token != SEMI)
4656                                                 skip_to_semi (cfile);
4657                                         return 0;
4658                                 }
4659                                 convert_num (cfile, buf, val, 0, 32);
4660                                 len = 4;
4661                                 dp = buf;
4662                                 goto alloc;
4663
4664                               case 's': /* Signed 16-bit integer. */
4665                               case 'S': /* Unsigned 16-bit integer. */
4666                                 token = next_token (&val,
4667                                                     (unsigned *)0, cfile);
4668                                 if (token != NUMBER)
4669                                         goto need_number;
4670                                 convert_num (cfile, buf, val, 0, 16);
4671                                 len = 2;
4672                                 dp = buf;
4673                                 goto alloc;
4674
4675                               case 'b': /* Signed 8-bit integer. */
4676                               case 'B': /* Unsigned 8-bit integer. */
4677                                 token = next_token (&val,
4678                                                     (unsigned *)0, cfile);
4679                                 if (token != NUMBER)
4680                                         goto need_number;
4681                                 convert_num (cfile, buf, val, 0, 8);
4682                                 len = 1;
4683                                 dp = buf;
4684                                 goto alloc;
4685
4686                               case 'f': /* Boolean flag. */
4687                                 token = next_token (&val,
4688                                                     (unsigned *)0, cfile);
4689                                 if (!is_identifier (token)) {
4690                                         parse_warn (cfile,
4691                                                     "expecting identifier.");
4692                                       bad_flag:
4693                                         if (token != SEMI)
4694                                                 skip_to_semi (cfile);
4695                                         return 0;
4696                                 }
4697                                 if (!strcasecmp (val, "true")
4698                                     || !strcasecmp (val, "on"))
4699                                         buf [0] = 1;
4700                                 else if (!strcasecmp (val, "false")
4701                                          || !strcasecmp (val, "off"))
4702                                         buf [0] = 0;
4703                                 else {
4704                                         parse_warn (cfile,
4705                                                     "expecting boolean.");
4706                                         goto bad_flag;
4707                                 }
4708                                 len = 1;
4709                                 dp = buf;
4710                                 goto alloc;
4711
4712                               default:
4713                                 log_error ("parse_option_param: Bad format %c",
4714                                       *fmt);
4715                                 skip_to_semi (cfile);
4716                                 return 0;
4717                         }
4718                 }
4719                 token = next_token (&val, (unsigned *)0, cfile);
4720         } while (*fmt == 'A' && token == COMMA);
4721
4722         if (token != SEMI) {
4723                 parse_warn (cfile, "semicolon expected.");
4724                 skip_to_semi (cfile);
4725                 return 0;
4726         }
4727
4728         bp = (struct buffer *)0;
4729         if (!buffer_allocate (&bp, hunkix + nul_term, MDL))
4730                 log_fatal ("no memory to store option declaration.");
4731         if (!bp -> data)
4732                 log_fatal ("out of memory allocating option data.");
4733         memcpy (bp -> data, hunkbuf, hunkix + nul_term);
4734         
4735         if (!option_cache_allocate (oc, MDL))
4736                 log_fatal ("out of memory allocating option cache.");
4737
4738         (*oc) -> data.buffer = bp;
4739         (*oc) -> data.data = &bp -> data [0];
4740         (*oc) -> data.terminated = nul_term;
4741         (*oc) -> data.len = hunkix;
4742         (*oc) -> option = option;
4743         return 1;
4744 }
4745
4746 /* Consider merging parse_cshl into this. */
4747
4748 int parse_X (cfile, buf, max)
4749         struct parse *cfile;
4750         u_int8_t *buf;
4751         unsigned max;
4752 {
4753         int token;
4754         const char *val;
4755         unsigned len;
4756         u_int8_t *s;
4757
4758         token = peek_token (&val, (unsigned *)0, cfile);
4759         if (token == NUMBER_OR_NAME || token == NUMBER) {
4760                 len = 0;
4761                 do {
4762                         token = next_token (&val, (unsigned *)0, cfile);
4763                         if (token != NUMBER && token != NUMBER_OR_NAME) {
4764                                 parse_warn (cfile,
4765                                             "expecting hexadecimal constant.");
4766                                 skip_to_semi (cfile);
4767                                 return 0;
4768                         }
4769                         convert_num (cfile, &buf [len], val, 16, 8);
4770                         if (len++ > max) {
4771                                 parse_warn (cfile,
4772                                             "hexadecimal constant too long.");
4773                                 skip_to_semi (cfile);
4774                                 return 0;
4775                         }
4776                         token = peek_token (&val, (unsigned *)0, cfile);
4777                         if (token == COLON)
4778                                 token = next_token (&val,
4779                                                     (unsigned *)0, cfile);
4780                 } while (token == COLON);
4781                 val = (char *)buf;
4782         } else if (token == STRING) {
4783                 token = next_token (&val, &len, cfile);
4784                 if (len + 1 > max) {
4785                         parse_warn (cfile, "string constant too long.");
4786                         skip_to_semi (cfile);
4787                         return 0;
4788                 }
4789                 memcpy (buf, val, len + 1);
4790         } else {
4791                 parse_warn (cfile, "expecting string or hexadecimal data");
4792                 skip_to_semi (cfile);
4793                 return 0;
4794         }
4795         return len;
4796 }
4797
4798 int parse_warn (struct parse *cfile, const char *fmt, ...)
4799 {
4800         va_list list;
4801         char lexbuf [256];
4802         char mbuf [1024];
4803         char fbuf [1024];
4804         unsigned i, lix;
4805         
4806         do_percentm (mbuf, fmt);
4807 #ifndef NO_SNPRINTF
4808         snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
4809                   cfile -> tlname, cfile -> lexline, mbuf);
4810 #else
4811         sprintf (fbuf, "%s line %d: %s",
4812                  cfile -> tlname, cfile -> lexline, mbuf);
4813 #endif
4814         
4815         va_start (list, fmt);
4816         vsnprintf (mbuf, sizeof mbuf, fbuf, list);
4817         va_end (list);
4818
4819         lix = 0;
4820         for (i = 0;
4821              cfile -> token_line [i] && i < (cfile -> lexchar - 1); i++) {
4822                 if (lix < (sizeof lexbuf) - 1)
4823                         lexbuf [lix++] = ' ';
4824                 if (cfile -> token_line [i] == '\t') {
4825                         for (lix;
4826                              lix < (sizeof lexbuf) - 1 && (lix & 7); lix++)
4827                                 lexbuf [lix] = ' ';
4828                 }
4829         }
4830         lexbuf [lix] = 0;
4831
4832 #ifndef DEBUG
4833         syslog (log_priority | LOG_ERR, "%s", mbuf);
4834         syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
4835         if (cfile -> lexchar < 81)
4836                 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
4837 #endif
4838
4839         if (log_perror) {
4840                 write (2, mbuf, strlen (mbuf));
4841                 write (2, "\n", 1);
4842                 write (2, cfile -> token_line, strlen (cfile -> token_line));
4843                 write (2, "\n", 1);
4844                 if (cfile -> lexchar < 81)
4845                         write (2, lexbuf, lix);
4846                 write (2, "^\n", 2);
4847         }
4848
4849         cfile -> warnings_occurred = 1;
4850
4851         return 0;
4852 }