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