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