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