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