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