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