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