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