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