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