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