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