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