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