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