etc/protocols - sync with NetBSD-8
[minix.git] / external / bsd / dhcp / dist / common / parse.c
blobe0fab5b643cc28e7663c625d005b5c39d927d619
1 /* $NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $ */
2 /* parse.c
4 Common parser code for dhcpd and dhclient. */
6 /*
7 * Copyright (c) 2004-2014 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1995-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
23 * 950 Charter Street
24 * Redwood City, CA 94063
25 * <info@isc.org>
26 * https://www.isc.org/
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $");
33 #include "dhcpd.h"
34 #include <syslog.h>
36 /* Enumerations can be specified in option formats, and are used for
37 parsing, so we define the routines that manage them here. */
39 struct enumeration *enumerations;
41 void add_enumeration (struct enumeration *enumeration)
43 enumeration -> next = enumerations;
44 enumerations = enumeration;
47 struct enumeration *find_enumeration (const char *name, int length)
49 struct enumeration *e;
51 for (e = enumerations; e; e = e -> next)
52 if (strlen (e -> name) == length &&
53 !memcmp (e -> name, name, (unsigned)length))
54 return e;
55 return (struct enumeration *)0;
58 struct enumeration_value *find_enumeration_value (const char *name,
59 int length,
60 unsigned *widthp,
61 const char *value)
63 struct enumeration *e;
64 int i;
66 e = find_enumeration (name, length);
67 if (e) {
68 if (widthp != NULL)
69 *widthp = e->width;
70 for (i = 0; e -> values [i].name; i++) {
71 if (!strcmp (value, e -> values [i].name))
72 return &e -> values [i];
75 return (struct enumeration_value *)0;
78 /* Skip to the semicolon ending the current statement. If we encounter
79 braces, the matching closing brace terminates the statement. If we
80 encounter a right brace but haven't encountered a left brace, return
81 leaving the brace in the token buffer for the caller. If we see a
82 semicolon and haven't seen a left brace, return. This lets us skip
83 over:
85 statement;
86 statement foo bar { }
87 statement foo bar { statement { } }
88 statement}
90 ...et cetera. */
92 void skip_to_semi (cfile)
93 struct parse *cfile;
95 skip_to_rbrace (cfile, 0);
98 void skip_to_rbrace (cfile, brace_count)
99 struct parse *cfile;
100 int brace_count;
102 enum dhcp_token token;
103 const char *val;
105 #if defined (DEBUG_TOKEN)
106 log_error ("skip_to_rbrace: %d\n", brace_count);
107 #endif
108 do {
109 token = peek_token (&val, (unsigned *)0, cfile);
110 if (token == RBRACE) {
111 skip_token(&val, (unsigned *)0, cfile);
112 if (brace_count) {
113 if (!--brace_count)
114 return;
115 } else
116 return;
117 } else if (token == LBRACE) {
118 brace_count++;
119 } else if (token == SEMI && !brace_count) {
120 skip_token(&val, (unsigned *)0, cfile);
121 return;
122 } else if (token == EOL) {
123 /* EOL only happens when parsing /etc/resolv.conf,
124 and we treat it like a semicolon because the
125 resolv.conf file is line-oriented. */
126 skip_token(&val, (unsigned *)0, cfile);
127 return;
129 token = next_token (&val, (unsigned *)0, cfile);
130 } while (token != END_OF_FILE);
133 int parse_semi (cfile)
134 struct parse *cfile;
136 enum dhcp_token token;
137 const char *val;
139 token = next_token (&val, (unsigned *)0, cfile);
140 if (token != SEMI) {
141 parse_warn (cfile, "semicolon expected.");
142 skip_to_semi (cfile);
143 return 0;
145 return 1;
148 /* string-parameter :== STRING SEMI */
150 int parse_string (cfile, sptr, lptr)
151 struct parse *cfile;
152 char **sptr;
153 unsigned *lptr;
155 const char *val;
156 enum dhcp_token token;
157 char *s;
158 unsigned len;
160 token = next_token (&val, &len, cfile);
161 if (token != STRING) {
162 parse_warn (cfile, "expecting a string");
163 skip_to_semi (cfile);
164 return 0;
166 s = (char *)dmalloc (len + 1, MDL);
167 if (!s)
168 log_fatal ("no memory for string %s.", val);
169 memcpy (s, val, len + 1);
171 if (!parse_semi (cfile)) {
172 dfree (s, MDL);
173 return 0;
175 if (sptr)
176 *sptr = s;
177 else
178 dfree (s, MDL);
179 if (lptr)
180 *lptr = len;
181 return 1;
185 * hostname :== IDENTIFIER
186 * | IDENTIFIER DOT
187 * | hostname DOT IDENTIFIER
190 char *parse_host_name (cfile)
191 struct parse *cfile;
193 const char *val;
194 enum dhcp_token token;
195 unsigned len = 0;
196 char *s;
197 char *t;
198 pair c = (pair)0;
199 int ltid = 0;
201 /* Read a dotted hostname... */
202 do {
203 /* Read a token, which should be an identifier. */
204 token = peek_token (&val, (unsigned *)0, cfile);
205 if (!is_identifier (token) && token != NUMBER)
206 break;
207 skip_token(&val, (unsigned *)0, cfile);
209 /* Store this identifier... */
210 if (!(s = (char *)dmalloc (strlen (val) + 1, MDL)))
211 log_fatal ("can't allocate temp space for hostname.");
212 strcpy (s, val);
213 c = cons ((caddr_t)s, c);
214 len += strlen (s) + 1;
215 /* Look for a dot; if it's there, keep going, otherwise
216 we're done. */
217 token = peek_token (&val, (unsigned *)0, cfile);
218 if (token == DOT) {
219 token = next_token (&val, (unsigned *)0, cfile);
220 ltid = 1;
221 } else
222 ltid = 0;
223 } while (token == DOT);
225 /* Should be at least one token. */
226 if (!len)
227 return (char *)0;
229 /* Assemble the hostname together into a string. */
230 if (!(s = (char *)dmalloc (len + ltid, MDL)))
231 log_fatal ("can't allocate space for hostname.");
232 t = s + len + ltid;
233 *--t = 0;
234 if (ltid)
235 *--t = '.';
236 while (c) {
237 pair cdr = c -> cdr;
238 unsigned l = strlen ((char *)(c -> car));
239 t -= l;
240 memcpy (t, (char *)(c -> car), l);
241 /* Free up temp space. */
242 dfree (c -> car, MDL);
243 dfree (c, MDL);
244 c = cdr;
245 if (t != s)
246 *--t = '.';
248 return s;
251 /* ip-addr-or-hostname :== ip-address | hostname
252 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
254 Parse an ip address or a hostname. If uniform is zero, put in
255 an expr_substring node to limit hostnames that evaluate to more
256 than one IP address.
258 Note that RFC1123 permits hostnames to consist of all digits,
259 making it difficult to quickly disambiguate them from ip addresses.
262 int parse_ip_addr_or_hostname (expr, cfile, uniform)
263 struct expression **expr;
264 struct parse *cfile;
265 int uniform;
267 const char *val;
268 enum dhcp_token token;
269 unsigned char addr [4];
270 unsigned len = sizeof addr;
271 char *name;
272 struct expression *x = (struct expression *)0;
273 int ipaddr = 0;
275 token = peek_token (&val, (unsigned *)0, cfile);
277 if (token == NUMBER) {
279 * a hostname may be numeric, but domain names must
280 * start with a letter, so we can disambiguate by
281 * looking ahead a few tokens. we save the parse
282 * context first, and restore it after we know what
283 * we're dealing with.
285 save_parse_state(cfile);
286 skip_token(NULL, NULL, cfile);
287 if (next_token(NULL, NULL, cfile) == DOT &&
288 next_token(NULL, NULL, cfile) == NUMBER)
289 ipaddr = 1;
290 restore_parse_state(cfile);
292 if (ipaddr &&
293 parse_numeric_aggregate (cfile, addr, &len, DOT, 10, 8))
294 return make_const_data (expr, addr, len, 0, 1, MDL);
298 if (is_identifier (token) || token == NUMBER) {
299 name = parse_host_name (cfile);
300 if (!name)
301 return 0;
302 if (!make_host_lookup (expr, name)) {
303 dfree(name, MDL);
304 return 0;
306 dfree(name, MDL);
307 if (!uniform) {
308 if (!make_limit (&x, *expr, 4))
309 return 0;
310 expression_dereference (expr, MDL);
311 *expr = x;
313 } else {
314 if (token != RBRACE && token != LBRACE)
315 token = next_token (&val, (unsigned *)0, cfile);
316 parse_warn (cfile, "%s (%d): expecting IP address or hostname",
317 val, token);
318 if (token != SEMI)
319 skip_to_semi (cfile);
320 return 0;
323 return 1;
327 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
330 int parse_ip_addr (cfile, addr)
331 struct parse *cfile;
332 struct iaddr *addr;
334 addr -> len = 4;
335 if (parse_numeric_aggregate (cfile, addr -> iabuf,
336 &addr -> len, DOT, 10, 8))
337 return 1;
338 return 0;
342 * Return true if every character in the string is hexadecimal.
344 static int
345 is_hex_string(const char *s) {
346 while (*s != '\0') {
347 if (!isxdigit((int)*s)) {
348 return 0;
350 s++;
352 return 1;
356 * ip-address6 :== (complicated set of rules)
358 * See section 2.2 of RFC 1884 for details.
360 * We are lazy for this. We pull numbers, names, colons, and dots
361 * together and then throw the resulting string at the inet_pton()
362 * function.
366 parse_ip6_addr(struct parse *cfile, struct iaddr *addr) {
367 enum dhcp_token token;
368 const char *val;
369 int val_len;
371 char v6[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
372 int v6_len;
375 * First token is non-raw. This way we eat any whitespace before
376 * our IPv6 address begins, like one would expect.
378 token = peek_token(&val, NULL, cfile);
381 * Gather symbols.
383 v6_len = 0;
384 for (;;) {
385 if ((((token == NAME) || (token == NUMBER_OR_NAME)) &&
386 is_hex_string(val)) ||
387 (token == NUMBER) ||
388 (token == DOT) ||
389 (token == COLON)) {
391 next_raw_token(&val, NULL, cfile);
392 val_len = strlen(val);
393 if ((v6_len + val_len) >= sizeof(v6)) {
394 parse_warn(cfile, "Invalid IPv6 address.");
395 skip_to_semi(cfile);
396 return 0;
398 memcpy(v6+v6_len, val, val_len);
399 v6_len += val_len;
401 } else {
402 break;
404 token = peek_raw_token(&val, NULL, cfile);
406 v6[v6_len] = '\0';
409 * Use inet_pton() for actual work.
411 if (inet_pton(AF_INET6, v6, addr->iabuf) <= 0) {
412 parse_warn(cfile, "Invalid IPv6 address.");
413 skip_to_semi(cfile);
414 return 0;
416 addr->len = 16;
417 return 1;
421 * Same as parse_ip6_addr() above, but returns the value in the
422 * expression rather than in an address structure.
425 parse_ip6_addr_expr(struct expression **expr,
426 struct parse *cfile) {
427 struct iaddr addr;
429 if (!parse_ip6_addr(cfile, &addr)) {
430 return 0;
432 return make_const_data(expr, addr.iabuf, addr.len, 0, 1, MDL);
436 * ip6-prefix :== ip6-address "/" NUMBER
439 parse_ip6_prefix(struct parse *cfile, struct iaddr *addr, u_int8_t *plen) {
440 enum dhcp_token token;
441 const char *val;
442 int n;
444 if (!parse_ip6_addr(cfile, addr)) {
445 return 0;
447 token = next_token(&val, NULL, cfile);
448 if (token != SLASH) {
449 parse_warn(cfile, "Slash expected.");
450 if (token != SEMI)
451 skip_to_semi(cfile);
452 return 0;
454 token = next_token(&val, NULL, cfile);
455 if (token != NUMBER) {
456 parse_warn(cfile, "Number expected.");
457 if (token != SEMI)
458 skip_to_semi(cfile);
459 return 0;
461 n = atoi(val);
462 if ((n < 0) || (n > 128)) {
463 parse_warn(cfile, "Invalid IPv6 prefix length.");
464 skip_to_semi(cfile);
465 return 0;
467 if (!is_cidr_mask_valid(addr, n)) {
468 parse_warn(cfile, "network mask too short.");
469 skip_to_semi(cfile);
470 return 0;
472 *plen = n;
473 return 1;
477 * ip-address-with-subnet :== ip-address |
478 * ip-address "/" NUMBER
482 parse_ip_addr_with_subnet(cfile, match)
483 struct parse *cfile;
484 struct iaddrmatch *match;
486 const char *val, *orig;
487 enum dhcp_token token;
488 int prefixlen;
489 int fflen;
490 unsigned char newval, warnmask=0;
492 if (parse_ip_addr(cfile, &match->addr)) {
493 /* default to host mask */
494 prefixlen = match->addr.len * 8;
496 token = peek_token(&val, NULL, cfile);
498 if (token == SLASH) {
499 skip_token(&val, NULL, cfile);
500 token = next_token(&val, NULL, cfile);
502 if (token != NUMBER) {
503 parse_warn(cfile, "Invalid CIDR prefix length:"
504 " expecting a number.");
505 return 0;
508 prefixlen = atoi(val);
510 if (prefixlen < 0 ||
511 prefixlen > (match->addr.len * 8)) {
512 parse_warn(cfile, "subnet prefix is out of "
513 "range [0..%d].",
514 match->addr.len * 8);
515 return 0;
519 /* construct a suitable mask field */
521 /* copy length */
522 match->mask.len = match->addr.len;
524 /* count of 0xff bytes in mask */
525 fflen = prefixlen / 8;
527 /* set leading mask */
528 memset(match->mask.iabuf, 0xff, fflen);
530 /* set zeroes */
531 if (fflen < match->mask.len) {
532 match->mask.iabuf[fflen] =
533 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen % 8];
535 memset(match->mask.iabuf+fflen+1, 0x00,
536 match->mask.len - fflen - 1);
538 /* AND-out insignificant bits from supplied netmask. */
539 orig = piaddr(match->addr);
540 do {
541 newval = match->addr.iabuf[fflen] &
542 match->mask.iabuf[fflen];
544 if (newval != match->addr.iabuf[fflen]) {
545 warnmask = 1;
546 match->addr.iabuf[fflen] = newval;
548 } while (++fflen < match->mask.len);
550 if (warnmask) {
551 log_error("Warning: Extraneous bits removed "
552 "in address component of %s/%d.",
553 orig, prefixlen);
554 log_error("New value: %s/%d.",
555 piaddr(match->addr), prefixlen);
559 return 1;
562 parse_warn(cfile,
563 "expecting ip-address or ip-address/prefixlen");
565 return 0; /* let caller pick up pieces */
569 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
570 * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND
571 * Note that INFINIBAND may not be useful for some items, such as classification
572 * as the hardware address won't always be available.
575 void parse_hardware_param (cfile, hardware)
576 struct parse *cfile;
577 struct hardware *hardware;
579 const char *val;
580 enum dhcp_token token;
581 unsigned hlen;
582 unsigned char *t;
584 token = next_token(&val, NULL, cfile);
585 switch (token) {
586 case ETHERNET:
587 hardware->hbuf[0] = HTYPE_ETHER;
588 break;
589 case TOKEN_RING:
590 hardware->hbuf[0] = HTYPE_IEEE802;
591 break;
592 case TOKEN_FDDI:
593 hardware->hbuf[0] = HTYPE_FDDI;
594 break;
595 case TOKEN_INFINIBAND:
596 hardware->hbuf[0] = HTYPE_INFINIBAND;
597 break;
598 default:
599 if (!strncmp(val, "unknown-", 8)) {
600 hardware->hbuf[0] = atoi(&val[8]);
601 } else {
602 parse_warn(cfile,
603 "expecting a network hardware type");
604 skip_to_semi(cfile);
606 return;
610 /* Parse the hardware address information. Technically,
611 it would make a lot of sense to restrict the length of the
612 data we'll accept here to the length of a particular hardware
613 address type. Unfortunately, there are some broken clients
614 out there that put bogus data in the chaddr buffer, and we accept
615 that data in the lease file rather than simply failing on such
616 clients. Yuck. */
617 hlen = 0;
618 token = peek_token(&val, NULL, cfile);
619 if (token == SEMI) {
620 hardware->hlen = 1;
621 goto out;
623 t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
624 if (t == NULL) {
625 hardware->hlen = 1;
626 return;
628 if (hlen + 1 > sizeof(hardware->hbuf)) {
629 dfree(t, MDL);
630 parse_warn(cfile, "hardware address too long");
631 } else {
632 hardware->hlen = hlen + 1;
633 memcpy((unsigned char *)&hardware->hbuf[1], t, hlen);
634 if (hlen + 1 < sizeof(hardware->hbuf))
635 memset(&hardware->hbuf[hlen + 1], 0,
636 (sizeof(hardware->hbuf)) - hlen - 1);
637 dfree(t, MDL);
640 out:
641 token = next_token(&val, NULL, cfile);
642 if (token != SEMI) {
643 parse_warn(cfile, "expecting semicolon.");
644 skip_to_semi(cfile);
648 /* lease-time :== NUMBER SEMI */
650 void parse_lease_time (cfile, timep)
651 struct parse *cfile;
652 TIME *timep;
654 const char *val;
655 enum dhcp_token token;
656 u_int32_t num;
658 token = next_token (&val, (unsigned *)0, cfile);
659 if (token != NUMBER) {
660 parse_warn (cfile, "Expecting numeric lease time");
661 skip_to_semi (cfile);
662 return;
664 convert_num(cfile, (unsigned char *)&num, val, 10, 32);
665 /* Unswap the number - convert_num returns stuff in NBO. */
666 *timep = ntohl(num);
668 parse_semi (cfile);
671 /* No BNF for numeric aggregates - that's defined by the caller. What
672 this function does is to parse a sequence of numbers separated by
673 the token specified in separator. If max is zero, any number of
674 numbers will be parsed; otherwise, exactly max numbers are
675 expected. Base and size tell us how to internalize the numbers
676 once they've been tokenized.
678 buf - A pointer to space to return the parsed value, if it is null
679 then the function will allocate space for the return.
681 max - The maximum number of items to store. If zero there is no
682 maximum. When buf is null and the function needs to allocate space
683 it will do an allocation of max size at the beginning if max is non
684 zero. If max is zero then the allocation will be done later, after
685 the function has determined the size necessary for the incoming
686 string.
688 returns NULL on errors or a pointer to the value string on success.
689 The pointer will either be buf if it was non-NULL or newly allocated
690 space if buf was NULL
694 unsigned char *parse_numeric_aggregate (cfile, buf,
695 max, separator, base, size)
696 struct parse *cfile;
697 unsigned char *buf;
698 unsigned *max;
699 int separator;
700 int base;
701 unsigned size;
703 const char *val;
704 enum dhcp_token token;
705 unsigned char *bufp = buf, *s, *t;
706 unsigned count = 0;
707 pair c = (pair)0;
709 if (!bufp && *max) {
710 bufp = (unsigned char *)dmalloc (*max * size / 8, MDL);
711 if (!bufp)
712 log_fatal ("no space for numeric aggregate");
714 s = bufp;
716 do {
717 if (count) {
718 token = peek_token (&val, (unsigned *)0, cfile);
719 if (token != separator) {
720 if (!*max)
721 break;
722 if (token != RBRACE && token != LBRACE)
723 token = next_token (&val,
724 (unsigned *)0,
725 cfile);
726 parse_warn (cfile, "too few numbers.");
727 if (token != SEMI)
728 skip_to_semi (cfile);
729 /* free bufp if it was allocated */
730 if ((bufp != NULL) && (bufp != buf))
731 dfree(bufp, MDL);
732 return (unsigned char *)0;
734 skip_token(&val, (unsigned *)0, cfile);
736 token = next_token (&val, (unsigned *)0, cfile);
738 if (token == END_OF_FILE) {
739 parse_warn (cfile, "unexpected end of file");
740 break;
743 /* Allow NUMBER_OR_NAME if base is 16. */
744 if (token != NUMBER &&
745 (base != 16 || token != NUMBER_OR_NAME)) {
746 parse_warn (cfile, "expecting numeric value.");
747 skip_to_semi (cfile);
748 /* free bufp if it was allocated */
749 if ((bufp != NULL) && (bufp != buf))
750 dfree(bufp, MDL);
751 /* free any linked numbers we may have allocated */
752 while (c) {
753 pair cdr = c->cdr;
754 dfree(c->car, MDL);
755 dfree(c, MDL);
756 c = cdr;
758 return (NULL);
760 /* If we can, convert the number now; otherwise, build
761 a linked list of all the numbers. */
762 if (s) {
763 convert_num (cfile, s, val, base, size);
764 s += size / 8;
765 } else {
766 t = (unsigned char *)dmalloc (strlen (val) + 1, MDL);
767 if (!t)
768 log_fatal ("no temp space for number.");
769 strcpy ((char *)t, val);
770 c = cons ((caddr_t)t, c);
772 } while (++count != *max);
774 /* If we had to cons up a list, convert it now. */
775 if (c) {
777 * No need to cleanup bufp, to get here we didn't allocate
778 * bufp above
780 bufp = (unsigned char *)dmalloc (count * size / 8, MDL);
781 if (!bufp)
782 log_fatal ("no space for numeric aggregate.");
783 s = bufp + count - size / 8;
784 *max = count;
786 while (c) {
787 pair cdr = c -> cdr;
788 convert_num (cfile, s, (char *)(c -> car), base, size);
789 s -= size / 8;
790 /* Free up temp space. */
791 dfree (c -> car, MDL);
792 dfree (c, MDL);
793 c = cdr;
795 return bufp;
798 void convert_num (cfile, buf, str, base, size)
799 struct parse *cfile;
800 unsigned char *buf;
801 const char *str;
802 int base;
803 unsigned size;
805 const unsigned char *ptr = (const unsigned char *)str;
806 int negative = 0;
807 u_int32_t val = 0;
808 int tval;
809 int max;
811 if (*ptr == '-') {
812 negative = 1;
813 ++ptr;
816 /* If base wasn't specified, figure it out from the data. */
817 if (!base) {
818 if (ptr [0] == '0') {
819 if (ptr [1] == 'x') {
820 base = 16;
821 ptr += 2;
822 } else if (isascii (ptr [1]) && isdigit (ptr [1])) {
823 base = 8;
824 ptr += 1;
825 } else {
826 base = 10;
828 } else {
829 base = 10;
833 do {
834 tval = *ptr++;
835 /* XXX assumes ASCII... */
836 if (tval >= 'a')
837 tval = tval - 'a' + 10;
838 else if (tval >= 'A')
839 tval = tval - 'A' + 10;
840 else if (tval >= '0')
841 tval -= '0';
842 else {
843 parse_warn (cfile, "Bogus number: %s.", str);
844 break;
846 if (tval >= base) {
847 parse_warn (cfile,
848 "Bogus number %s: digit %d not in base %d",
849 str, tval, base);
850 break;
852 val = val * base + tval;
853 } while (*ptr);
855 if (negative)
856 max = (1 << (size - 1));
857 else
858 max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
859 if (val > max) {
860 switch (base) {
861 case 8:
862 parse_warn (cfile,
863 "%s%lo exceeds max (%d) for precision.",
864 negative ? "-" : "",
865 (unsigned long)val, max);
866 break;
867 case 16:
868 parse_warn (cfile,
869 "%s%lx exceeds max (%d) for precision.",
870 negative ? "-" : "",
871 (unsigned long)val, max);
872 break;
873 default:
874 parse_warn (cfile,
875 "%s%lu exceeds max (%d) for precision.",
876 negative ? "-" : "",
877 (unsigned long)val, max);
878 break;
882 if (negative) {
883 switch (size) {
884 case 8:
885 *buf = -(unsigned long)val;
886 break;
887 case 16:
888 putShort (buf, -(long)val);
889 break;
890 case 32:
891 putLong (buf, -(long)val);
892 break;
893 default:
894 parse_warn (cfile,
895 "Unexpected integer size: %d\n", size);
896 break;
898 } else {
899 switch (size) {
900 case 8:
901 *buf = (u_int8_t)val;
902 break;
903 case 16:
904 putUShort (buf, (u_int16_t)val);
905 break;
906 case 32:
907 putULong (buf, val);
908 break;
909 default:
910 parse_warn (cfile,
911 "Unexpected integer size: %d\n", size);
912 break;
918 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
919 * NUMBER COLON NUMBER COLON NUMBER |
920 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
921 * NUMBER COLON NUMBER COLON NUMBER NUMBER |
922 * EPOCH NUMBER |
923 * NEVER
925 * Dates are stored in UTC or with a timezone offset; first number is day
926 * of week; next is year/month/day; next is hours:minutes:seconds on a
927 * 24-hour clock, followed by the timezone offset in seconds, which is
928 * optional.
932 * just parse the date
933 * any trailing semi must be consumed by the caller of this routine
935 TIME
936 parse_date_core(cfile)
937 struct parse *cfile;
939 int guess;
940 int tzoff, year, mon, mday, hour, min, sec;
941 const char *val;
942 enum dhcp_token token;
943 static int months[11] = { 31, 59, 90, 120, 151, 181,
944 212, 243, 273, 304, 334 };
946 /* "never", "epoch" or day of week */
947 token = peek_token(&val, NULL, cfile);
948 if (token == NEVER) {
949 skip_token(&val, NULL, cfile); /* consume NEVER */
950 return(MAX_TIME);
953 /* This indicates 'local' time format. */
954 if (token == EPOCH) {
955 skip_token(&val, NULL, cfile); /* consume EPOCH */
956 token = peek_token(&val, NULL, cfile);
958 if (token != NUMBER) {
959 if (token != SEMI)
960 skip_token(&val, NULL, cfile);
961 parse_warn(cfile, "Seconds since epoch expected.");
962 return((TIME)0);
965 skip_token(&val, NULL, cfile); /* consume number */
966 guess = atoi(val);
968 return((TIME)guess);
971 if (token != NUMBER) {
972 if (token != SEMI)
973 skip_token(&val, NULL, cfile);
974 parse_warn(cfile, "numeric day of week expected.");
975 return((TIME)0);
977 skip_token(&val, NULL, cfile); /* consume day of week */
978 /* we are not using this for anything */
980 /* Year... */
981 token = peek_token(&val, NULL, cfile);
982 if (token != NUMBER) {
983 if (token != SEMI)
984 skip_token(&val, NULL, cfile);
985 parse_warn(cfile, "numeric year expected.");
986 return((TIME)0);
988 skip_token(&val, NULL, cfile); /* consume year */
990 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
991 somebody invents a time machine, I think we can safely disregard
992 it. This actually works around a stupid Y2K bug that was present
993 in a very early beta release of dhcpd. */
994 year = atoi(val);
995 if (year > 1900)
996 year -= 1900;
998 /* Slash separating year from month... */
999 token = peek_token(&val, NULL, cfile);
1000 if (token != SLASH) {
1001 if (token != SEMI)
1002 skip_token(&val, NULL, cfile);
1003 parse_warn(cfile,
1004 "expected slash separating year from month.");
1005 return((TIME)0);
1007 skip_token(&val, NULL, cfile); /* consume SLASH */
1009 /* Month... */
1010 token = peek_token(&val, NULL, cfile);
1011 if (token != NUMBER) {
1012 if (token != SEMI)
1013 skip_token(&val, NULL, cfile);
1014 parse_warn(cfile, "numeric month expected.");
1015 return((TIME)0);
1017 skip_token(&val, NULL, cfile); /* consume month */
1018 mon = atoi(val) - 1;
1020 /* Slash separating month from day... */
1021 token = peek_token(&val, NULL, cfile);
1022 if (token != SLASH) {
1023 if (token != SEMI)
1024 skip_token(&val, NULL, cfile);
1025 parse_warn(cfile,
1026 "expected slash separating month from day.");
1027 return((TIME)0);
1029 skip_token(&val, NULL, cfile); /* consume SLASH */
1031 /* Day of month... */
1032 token = peek_token(&val, NULL, cfile);
1033 if (token != NUMBER) {
1034 if (token != SEMI)
1035 skip_token(&val, NULL, cfile);
1036 parse_warn(cfile, "numeric day of month expected.");
1037 return((TIME)0);
1039 skip_token(&val, NULL, cfile); /* consume day of month */
1040 mday = atoi(val);
1042 /* Hour... */
1043 token = peek_token(&val, NULL, cfile);
1044 if (token != NUMBER) {
1045 if (token != SEMI)
1046 skip_token(&val, NULL, cfile);
1047 parse_warn(cfile, "numeric hour expected.");
1048 return((TIME)0);
1050 skip_token(&val, NULL, cfile); /* consume hour */
1051 hour = atoi(val);
1053 /* Colon separating hour from minute... */
1054 token = peek_token(&val, NULL, cfile);
1055 if (token != COLON) {
1056 if (token != SEMI)
1057 skip_token(&val, NULL, cfile);
1058 parse_warn(cfile,
1059 "expected colon separating hour from minute.");
1060 return((TIME)0);
1062 skip_token(&val, NULL, cfile); /* consume colon */
1064 /* Minute... */
1065 token = peek_token(&val, NULL, cfile);
1066 if (token != NUMBER) {
1067 if (token != SEMI)
1068 skip_token(&val, NULL, cfile);
1069 parse_warn(cfile, "numeric minute expected.");
1070 return((TIME)0);
1072 skip_token(&val, NULL, cfile); /* consume minute */
1073 min = atoi(val);
1075 /* Colon separating minute from second... */
1076 token = peek_token(&val, NULL, cfile);
1077 if (token != COLON) {
1078 if (token != SEMI)
1079 skip_token(&val, NULL, cfile);
1080 parse_warn(cfile,
1081 "expected colon separating minute from second.");
1082 return((TIME)0);
1084 skip_token(&val, NULL, cfile); /* consume colon */
1086 /* Second... */
1087 token = peek_token(&val, NULL, cfile);
1088 if (token != NUMBER) {
1089 if (token != SEMI)
1090 skip_token(&val, NULL, cfile);
1091 parse_warn(cfile, "numeric second expected.");
1092 return((TIME)0);
1094 skip_token(&val, NULL, cfile); /* consume second */
1095 sec = atoi(val);
1097 tzoff = 0;
1098 token = peek_token(&val, NULL, cfile);
1099 if (token == NUMBER) {
1100 skip_token(&val, NULL, cfile); /* consume tzoff */
1101 tzoff = atoi(val);
1102 } else if (token != SEMI) {
1103 skip_token(&val, NULL, cfile);
1104 parse_warn(cfile,
1105 "Time zone offset or semicolon expected.");
1106 return((TIME)0);
1109 /* Guess the time value... */
1110 guess = ((((((365 * (year - 70) + /* Days in years since '70 */
1111 (year - 69) / 4 + /* Leap days since '70 */
1112 (mon /* Days in months this year */
1113 ? months [mon - 1]
1114 : 0) +
1115 (mon > 1 && /* Leap day this year */
1116 !((year - 72) & 3)) +
1117 mday - 1) * 24) + /* Day of month */
1118 hour) * 60) +
1119 min) * 60) + sec + tzoff;
1121 /* This guess could be wrong because of leap seconds or other
1122 weirdness we don't know about that the system does. For
1123 now, we're just going to accept the guess, but at some point
1124 it might be nice to do a successive approximation here to
1125 get an exact value. Even if the error is small, if the
1126 server is restarted frequently (and thus the lease database
1127 is reread), the error could accumulate into something
1128 significant. */
1130 return((TIME)guess);
1134 * Wrapper to consume the semicolon after the date
1135 * :== date semi
1138 TIME
1139 parse_date(cfile)
1140 struct parse *cfile;
1142 TIME guess;
1143 guess = parse_date_core(cfile);
1145 /* Make sure the date ends in a semicolon... */
1146 if (!parse_semi(cfile))
1147 return((TIME)0);
1148 return(guess);
1154 * option-name :== IDENTIFIER |
1155 IDENTIFIER . IDENTIFIER
1158 isc_result_t
1159 parse_option_name (cfile, allocate, known, opt)
1160 struct parse *cfile;
1161 int allocate;
1162 int *known;
1163 struct option **opt;
1165 const char *val;
1166 enum dhcp_token token;
1167 char *uname;
1168 struct universe *universe;
1169 struct option *option;
1170 unsigned code;
1172 if (opt == NULL)
1173 return DHCP_R_INVALIDARG;
1175 token = next_token (&val, (unsigned *)0, cfile);
1176 if (!is_identifier (token)) {
1177 parse_warn (cfile,
1178 "expecting identifier after option keyword.");
1179 if (token != SEMI)
1180 skip_to_semi (cfile);
1181 return DHCP_R_BADPARSE;
1183 uname = dmalloc (strlen (val) + 1, MDL);
1184 if (!uname)
1185 log_fatal ("no memory for uname information.");
1186 strcpy (uname, val);
1187 token = peek_token (&val, (unsigned *)0, cfile);
1188 if (token == DOT) {
1189 /* Go ahead and take the DOT token... */
1190 skip_token(&val, (unsigned *)0, cfile);
1192 /* The next token should be an identifier... */
1193 token = next_token (&val, (unsigned *)0, cfile);
1194 if (!is_identifier (token)) {
1195 parse_warn (cfile, "expecting identifier after '.'");
1196 if (token != SEMI)
1197 skip_to_semi (cfile);
1198 return DHCP_R_BADPARSE;
1201 /* Look up the option name hash table for the specified
1202 uname. */
1203 universe = (struct universe *)0;
1204 if (!universe_hash_lookup (&universe, universe_hash,
1205 uname, 0, MDL)) {
1206 parse_warn (cfile, "no option space named %s.", uname);
1207 skip_to_semi (cfile);
1208 return ISC_R_NOTFOUND;
1210 } else {
1211 /* Use the default hash table, which contains all the
1212 standard dhcp option names. */
1213 val = uname;
1214 universe = &dhcp_universe;
1217 /* Look up the actual option info... */
1218 option_name_hash_lookup(opt, universe->name_hash, val, 0, MDL);
1219 option = *opt;
1221 /* If we didn't get an option structure, it's an undefined option. */
1222 if (option) {
1223 if (known)
1224 *known = 1;
1225 /* If the option name is of the form unknown-[decimal], use
1226 * the trailing decimal value to find the option definition.
1227 * If there is no definition, construct one. This is to
1228 * support legacy use of unknown options in config files or
1229 * lease databases.
1231 } else if (strncasecmp(val, "unknown-", 8) == 0) {
1232 code = atoi(val+8);
1234 /* Option code 0 is always illegal for us, thanks
1235 * to the option decoder.
1237 if (code == 0 || code == universe->end) {
1238 parse_warn(cfile, "Option codes 0 and %u are illegal "
1239 "in the %s space.", universe->end,
1240 universe->name);
1241 skip_to_semi(cfile);
1242 dfree(uname, MDL);
1243 return ISC_R_FAILURE;
1246 /* It's odd to think of unknown option codes as
1247 * being known, but this means we know what the
1248 * parsed name is talking about.
1250 if (known)
1251 *known = 1;
1253 option_code_hash_lookup(opt, universe->code_hash,
1254 &code, 0, MDL);
1255 option = *opt;
1257 /* If we did not find an option of that code,
1258 * manufacture an unknown-xxx option definition.
1259 * Its single reference will ensure that it is
1260 * deleted once the option is recycled out of
1261 * existence (by the parent).
1263 if (option == NULL) {
1264 option = new_option(val, MDL);
1265 option->universe = universe;
1266 option->code = code;
1267 option->format = default_option_format;
1268 option_reference(opt, option, MDL);
1269 } else
1270 log_info("option %s has been redefined as option %s. "
1271 "Please update your configs if neccessary.",
1272 val, option->name);
1273 /* If we've been told to allocate, that means that this
1274 * (might) be an option code definition, so we'll create
1275 * an option structure and return it for the parent to
1276 * decide.
1278 } else if (allocate) {
1279 option = new_option(val, MDL);
1280 option -> universe = universe;
1281 option_reference(opt, option, MDL);
1282 } else {
1283 parse_warn(cfile, "no option named %s in space %s",
1284 val, universe->name);
1285 skip_to_semi (cfile);
1286 dfree(uname, MDL);
1287 return ISC_R_NOTFOUND;
1290 /* Free the initial identifier token. */
1291 dfree (uname, MDL);
1292 return ISC_R_SUCCESS;
1295 /* IDENTIFIER [WIDTHS] SEMI
1296 * WIDTHS ~= LENGTH WIDTH NUMBER
1297 * CODE WIDTH NUMBER
1300 void parse_option_space_decl (cfile)
1301 struct parse *cfile;
1303 int token;
1304 const char *val;
1305 struct universe **ua, *nu;
1306 char *nu_name;
1307 int tsize=1, lsize=1, hsize = 0;
1309 skip_token(&val, (unsigned *)0, cfile); /* Discard the SPACE token,
1310 which was checked by the
1311 caller. */
1312 token = next_token (&val, (unsigned *)0, cfile);
1313 if (!is_identifier (token)) {
1314 parse_warn (cfile, "expecting identifier.");
1315 skip_to_semi (cfile);
1316 return;
1318 nu = new_universe (MDL);
1319 if (!nu)
1320 log_fatal ("No memory for new option space.");
1322 /* Set up the server option universe... */
1323 nu_name = dmalloc (strlen (val) + 1, MDL);
1324 if (!nu_name)
1325 log_fatal ("No memory for new option space name.");
1326 strcpy (nu_name, val);
1327 nu -> name = nu_name;
1329 do {
1330 token = next_token(&val, NULL, cfile);
1331 switch(token) {
1332 case SEMI:
1333 break;
1335 case CODE:
1336 token = next_token(&val, NULL, cfile);
1337 if (token != WIDTH) {
1338 parse_warn(cfile, "expecting width token.");
1339 goto bad;
1342 token = next_token(&val, NULL, cfile);
1343 if (token != NUMBER) {
1344 parse_warn(cfile, "expecting number 1, 2, 4.");
1345 goto bad;
1348 tsize = atoi(val);
1351 switch (tsize) {
1352 case 1:
1353 if (!hsize)
1354 hsize = BYTE_NAME_HASH_SIZE;
1355 break;
1356 case 2:
1357 if (!hsize)
1358 hsize = WORD_NAME_HASH_SIZE;
1359 break;
1360 case 4:
1361 if (!hsize)
1362 hsize = QUAD_NAME_HASH_SIZE;
1363 break;
1364 default:
1365 parse_warn(cfile, "invalid code width (%d), "
1366 "expecting a 1, 2 or 4.",
1367 tsize);
1368 goto bad;
1370 break;
1372 case LENGTH:
1373 token = next_token(&val, NULL, cfile);
1374 if (token != WIDTH) {
1375 parse_warn(cfile, "expecting width token.");
1376 goto bad;
1379 token = next_token(&val, NULL, cfile);
1380 if (token != NUMBER) {
1381 parse_warn(cfile, "expecting number 1 or 2.");
1382 goto bad;
1385 lsize = atoi(val);
1386 if (lsize != 1 && lsize != 2) {
1387 parse_warn(cfile, "invalid length width (%d) "
1388 "expecting 1 or 2.", lsize);
1389 goto bad;
1392 break;
1394 case HASH:
1395 token = next_token(&val, NULL, cfile);
1396 if (token != SIZE) {
1397 parse_warn(cfile, "expecting size token.");
1398 goto bad;
1401 token = next_token(&val, NULL, cfile);
1402 if (token != NUMBER) {
1403 parse_warn(cfile, "expecting a 10base number");
1404 goto bad;
1407 /* (2^31)-1 is the highest Mersenne prime we should
1408 * probably allow...
1410 hsize = atoi(val);
1411 if (hsize < 0 || hsize > 0x7FFFFFFF) {
1412 parse_warn(cfile, "invalid hash length: %d",
1413 hsize);
1414 goto bad;
1417 break;
1419 default:
1420 parse_warn(cfile, "Unexpected token.");
1422 } while (token != SEMI);
1424 if (!hsize)
1425 hsize = DEFAULT_SPACE_HASH_SIZE;
1427 nu -> lookup_func = lookup_hashed_option;
1428 nu -> option_state_dereference = hashed_option_state_dereference;
1429 nu -> foreach = hashed_option_space_foreach;
1430 nu -> save_func = save_hashed_option;
1431 nu -> delete_func = delete_hashed_option;
1432 nu -> encapsulate = hashed_option_space_encapsulate;
1433 nu -> decode = parse_option_buffer;
1434 nu -> length_size = lsize;
1435 nu -> tag_size = tsize;
1436 switch(tsize) {
1437 case 1:
1438 nu->get_tag = getUChar;
1439 nu->store_tag = putUChar;
1440 break;
1441 case 2:
1442 nu->get_tag = getUShort;
1443 nu->store_tag = putUShort;
1444 break;
1445 case 4:
1446 nu->get_tag = getULong;
1447 nu->store_tag = putULong;
1448 break;
1449 default:
1450 log_fatal("Impossible condition at %s:%d.", MDL);
1452 switch(lsize) {
1453 case 0:
1454 nu->get_length = NULL;
1455 nu->store_length = NULL;
1456 break;
1457 case 1:
1458 nu->get_length = getUChar;
1459 nu->store_length = putUChar;
1460 break;
1461 case 2:
1462 nu->get_length = getUShort;
1463 nu->store_length = putUShort;
1464 break;
1465 default:
1466 log_fatal("Impossible condition at %s:%d.", MDL);
1468 nu -> index = universe_count++;
1469 if (nu -> index >= universe_max) {
1470 ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);
1471 if (!ua)
1472 log_fatal ("No memory to expand option space array.");
1473 memcpy (ua, universes, universe_max * sizeof *ua);
1474 universe_max *= 2;
1475 dfree (universes, MDL);
1476 universes = ua;
1478 universes [nu -> index] = nu;
1479 if (!option_name_new_hash(&nu->name_hash, hsize, MDL) ||
1480 !option_code_new_hash(&nu->code_hash, hsize, MDL))
1481 log_fatal("Can't allocate %s option hash table.", nu->name);
1482 universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);
1483 return;
1485 bad:
1486 dfree(nu_name, MDL);
1487 dfree(nu, MDL);
1490 /* This is faked up to look good right now. Ideally, this should do a
1491 recursive parse and allow arbitrary data structure definitions, but for
1492 now it just allows you to specify a single type, an array of single types,
1493 a sequence of types, or an array of sequences of types.
1495 ocd :== NUMBER EQUALS ocsd SEMI
1497 ocsd :== ocsd_type |
1498 ocsd_type_sequence |
1499 ARRAY OF ocsd_simple_type_sequence
1501 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1503 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1505 ocsd_types :== ocsd_type |
1506 ocsd_types ocsd_type
1508 ocsd_type :== ocsd_simple_type |
1509 ARRAY OF ocsd_simple_type
1511 ocsd_simple_types :== ocsd_simple_type |
1512 ocsd_simple_types ocsd_simple_type
1514 ocsd_simple_type :== BOOLEAN |
1515 INTEGER NUMBER |
1516 SIGNED INTEGER NUMBER |
1517 UNSIGNED INTEGER NUMBER |
1518 IP-ADDRESS |
1519 TEXT |
1520 STRING |
1521 ENCAPSULATE identifier */
1523 int parse_option_code_definition (cfile, option)
1524 struct parse *cfile;
1525 struct option *option;
1527 const char *val;
1528 enum dhcp_token token;
1529 struct option *oldopt;
1530 unsigned arrayp = 0;
1531 int recordp = 0;
1532 int no_more_in_record = 0;
1533 char tokbuf [128];
1534 unsigned tokix = 0;
1535 char type;
1536 int is_signed;
1537 char *s;
1538 int has_encapsulation = 0;
1539 struct universe *encapsulated;
1541 /* Parse the option code. */
1542 token = next_token (&val, (unsigned *)0, cfile);
1543 if (token != NUMBER) {
1544 parse_warn (cfile, "expecting option code number.");
1545 skip_to_semi (cfile);
1546 return 0;
1548 option -> code = atoi (val);
1550 token = next_token (&val, (unsigned *)0, cfile);
1551 if (token != EQUAL) {
1552 parse_warn (cfile, "expecting \"=\"");
1553 skip_to_semi (cfile);
1554 return 0;
1557 /* See if this is an array. */
1558 token = next_token (&val, (unsigned *)0, cfile);
1559 if (token == ARRAY) {
1560 token = next_token (&val, (unsigned *)0, cfile);
1561 if (token != OF) {
1562 parse_warn (cfile, "expecting \"of\".");
1563 skip_to_semi (cfile);
1564 return 0;
1566 arrayp = 1;
1567 token = next_token (&val, (unsigned *)0, cfile);
1570 if (token == LBRACE) {
1571 recordp = 1;
1572 token = next_token (&val, (unsigned *)0, cfile);
1575 /* At this point we're expecting a data type. */
1576 next_type:
1577 if (has_encapsulation) {
1578 parse_warn (cfile,
1579 "encapsulate must always be the last item.");
1580 skip_to_semi (cfile);
1581 return 0;
1584 switch (token) {
1585 case ARRAY:
1586 if (arrayp) {
1587 parse_warn (cfile, "no nested arrays.");
1588 skip_to_rbrace (cfile, recordp);
1589 if (recordp)
1590 skip_to_semi (cfile);
1591 return 0;
1593 token = next_token (&val, (unsigned *)0, cfile);
1594 if (token != OF) {
1595 parse_warn (cfile, "expecting \"of\".");
1596 skip_to_semi (cfile);
1597 return 0;
1599 arrayp = recordp + 1;
1600 token = next_token (&val, (unsigned *)0, cfile);
1601 if ((recordp) && (token == LBRACE)) {
1602 parse_warn (cfile,
1603 "only uniform array inside record.");
1604 skip_to_rbrace (cfile, recordp + 1);
1605 skip_to_semi (cfile);
1606 return 0;
1608 goto next_type;
1609 case BOOLEAN:
1610 type = 'f';
1611 break;
1612 case INTEGER:
1613 is_signed = 1;
1614 parse_integer:
1615 token = next_token (&val, (unsigned *)0, cfile);
1616 if (token != NUMBER) {
1617 parse_warn (cfile, "expecting number.");
1618 skip_to_rbrace (cfile, recordp);
1619 if (recordp)
1620 skip_to_semi (cfile);
1621 return 0;
1623 switch (atoi (val)) {
1624 case 8:
1625 type = is_signed ? 'b' : 'B';
1626 break;
1627 case 16:
1628 type = is_signed ? 's' : 'S';
1629 break;
1630 case 32:
1631 type = is_signed ? 'l' : 'L';
1632 break;
1633 default:
1634 parse_warn (cfile,
1635 "%s bit precision is not supported.", val);
1636 skip_to_rbrace (cfile, recordp);
1637 if (recordp)
1638 skip_to_semi (cfile);
1639 return 0;
1641 break;
1642 case SIGNED:
1643 is_signed = 1;
1644 parse_signed:
1645 token = next_token (&val, (unsigned *)0, cfile);
1646 if (token != INTEGER) {
1647 parse_warn (cfile, "expecting \"integer\" keyword.");
1648 skip_to_rbrace (cfile, recordp);
1649 if (recordp)
1650 skip_to_semi (cfile);
1651 return 0;
1653 goto parse_integer;
1654 case UNSIGNED:
1655 is_signed = 0;
1656 goto parse_signed;
1658 case IP_ADDRESS:
1659 type = 'I';
1660 break;
1661 case IP6_ADDRESS:
1662 type = '6';
1663 break;
1664 case DOMAIN_NAME:
1665 type = 'd';
1666 goto no_arrays;
1667 case DOMAIN_LIST:
1668 /* Consume optional compression indicator. */
1669 token = peek_token(&val, NULL, cfile);
1670 if (token == COMPRESSED) {
1671 skip_token(&val, NULL, cfile);
1672 tokbuf[tokix++] = 'D';
1673 type = 'c';
1674 } else
1675 type = 'D';
1676 goto no_arrays;
1677 case TEXT:
1678 type = 't';
1679 no_arrays:
1680 if (arrayp) {
1681 parse_warn (cfile, "arrays of text strings not %s",
1682 "yet supported.");
1683 skip_to_rbrace (cfile, recordp);
1684 if (recordp)
1685 skip_to_semi (cfile);
1686 return 0;
1688 no_more_in_record = 1;
1689 break;
1690 case STRING_TOKEN:
1691 type = 'X';
1692 goto no_arrays;
1694 case ENCAPSULATE:
1695 token = next_token (&val, (unsigned *)0, cfile);
1696 if (!is_identifier (token)) {
1697 parse_warn (cfile,
1698 "expecting option space identifier");
1699 skip_to_semi (cfile);
1700 return 0;
1702 encapsulated = NULL;
1703 if (!universe_hash_lookup(&encapsulated, universe_hash,
1704 val, strlen(val), MDL)) {
1705 parse_warn(cfile, "unknown option space %s", val);
1706 skip_to_semi (cfile);
1707 return 0;
1709 if (strlen (val) + tokix + 2 > sizeof (tokbuf))
1710 goto toobig;
1711 tokbuf [tokix++] = 'E';
1712 strcpy (&tokbuf [tokix], val);
1713 tokix += strlen (val);
1714 type = '.';
1715 has_encapsulation = 1;
1716 break;
1718 case ZEROLEN:
1719 type = 'Z';
1720 if (arrayp) {
1721 parse_warn (cfile, "array incompatible with zerolen.");
1722 skip_to_rbrace (cfile, recordp);
1723 if (recordp)
1724 skip_to_semi (cfile);
1725 return 0;
1727 no_more_in_record = 1;
1728 break;
1730 default:
1731 parse_warn (cfile, "unknown data type %s", val);
1732 skip_to_rbrace (cfile, recordp);
1733 if (recordp)
1734 skip_to_semi (cfile);
1735 return 0;
1738 if (tokix == sizeof tokbuf) {
1739 toobig:
1740 parse_warn (cfile, "too many types in record.");
1741 skip_to_rbrace (cfile, recordp);
1742 if (recordp)
1743 skip_to_semi (cfile);
1744 return 0;
1746 tokbuf [tokix++] = type;
1748 if (recordp) {
1749 token = next_token (&val, (unsigned *)0, cfile);
1750 if (arrayp > recordp) {
1751 if (tokix == sizeof tokbuf) {
1752 parse_warn (cfile,
1753 "too many types in record.");
1754 skip_to_rbrace (cfile, 1);
1755 skip_to_semi (cfile);
1756 return 0;
1758 arrayp = 0;
1759 tokbuf[tokix++] = 'a';
1761 if (token == COMMA) {
1762 if (no_more_in_record) {
1763 parse_warn (cfile,
1764 "%s must be at end of record.",
1765 type == 't' ? "text" : "string");
1766 skip_to_rbrace (cfile, 1);
1767 if (recordp)
1768 skip_to_semi (cfile);
1769 return 0;
1771 token = next_token (&val, (unsigned *)0, cfile);
1772 goto next_type;
1774 if (token != RBRACE) {
1775 parse_warn (cfile, "expecting right brace.");
1776 skip_to_rbrace (cfile, 1);
1777 if (recordp)
1778 skip_to_semi (cfile);
1779 return 0;
1782 if (!parse_semi (cfile)) {
1783 parse_warn (cfile, "semicolon expected.");
1784 skip_to_semi (cfile);
1785 if (recordp)
1786 skip_to_semi (cfile);
1787 return 0;
1789 if (has_encapsulation && arrayp) {
1790 parse_warn (cfile,
1791 "Arrays of encapsulations don't make sense.");
1792 return 0;
1794 s = dmalloc(tokix + (arrayp ? 1 : 0) + 1, MDL);
1795 if (s == NULL) {
1796 log_fatal("no memory for option format.");
1798 memcpy(s, tokbuf, tokix);
1799 if (arrayp) {
1800 s[tokix++] = (arrayp > recordp) ? 'a' : 'A';
1802 s[tokix] = '\0';
1804 option -> format = s;
1806 oldopt = NULL;
1807 option_code_hash_lookup(&oldopt, option->universe->code_hash,
1808 &option->code, 0, MDL);
1809 if (oldopt != NULL) {
1811 * XXX: This illegalizes a configuration syntax that was
1812 * valid in 3.0.x, where multiple name->code mappings are
1813 * given, but only one code->name mapping survives. It is
1814 * unclear what can or should be done at this point, but it
1815 * seems best to retain 3.0.x behaviour for upgrades to go
1816 * smoothly.
1818 option_name_hash_delete(option->universe->name_hash,
1819 oldopt->name, 0, MDL);
1821 option_code_hash_delete(option->universe->code_hash,
1822 &oldopt->code, 0, MDL);
1824 option_dereference(&oldopt, MDL);
1826 option_code_hash_add(option->universe->code_hash, &option->code, 0,
1827 option, MDL);
1828 option_name_hash_add(option->universe->name_hash, option->name, 0,
1829 option, MDL);
1830 if (has_encapsulation) {
1831 /* INSIST(tokbuf[0] == 'E'); */
1832 /* INSIST(encapsulated != NULL); */
1833 if (!option_code_hash_lookup(&encapsulated->enc_opt,
1834 option->universe->code_hash,
1835 &option->code, 0, MDL)) {
1836 log_fatal("error finding encapsulated option (%s:%d)",
1837 MDL);
1840 return 1;
1844 * base64 :== NUMBER_OR_STRING
1847 int parse_base64 (data, cfile)
1848 struct data_string *data;
1849 struct parse *cfile;
1851 const char *val;
1852 int i, j, k;
1853 unsigned acc = 0;
1854 static unsigned char
1855 from64 [] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1856 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1857 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1858 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1859 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1860 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1861 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1862 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1863 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1864 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1865 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1866 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1867 struct string_list *bufs = NULL,
1868 *last = NULL,
1870 int cc = 0;
1871 int terminated = 0;
1872 int valid_base64;
1874 /* It's possible for a + or a / to cause a base64 quantity to be
1875 tokenized into more than one token, so we have to parse them all
1876 in before decoding. */
1877 do {
1878 unsigned l;
1880 (void)next_token(&val, &l, cfile);
1881 t = dmalloc(l + sizeof(*t), MDL);
1882 if (t == NULL)
1883 log_fatal("no memory for base64 buffer.");
1884 memset(t, 0, (sizeof(*t)) - 1);
1885 memcpy(t->string, val, l + 1);
1886 cc += l;
1887 if (last)
1888 last->next = t;
1889 else
1890 bufs = t;
1891 last = t;
1892 (void)peek_token(&val, NULL, cfile);
1893 valid_base64 = 1;
1894 for (i = 0; val[i]; i++) {
1895 /* Check to see if the character is valid. It
1896 may be out of range or within the right range
1897 but not used in the mapping */
1898 if (((val[i] < ' ') || (val[i] > 'z')) ||
1899 ((from64[val[i] - ' '] > 63) && (val[i] != '='))) {
1900 valid_base64 = 0;
1901 break; /* no need to continue for loop */
1904 } while (valid_base64);
1906 data->len = cc;
1907 data->len = (data->len * 3) / 4;
1908 if (!buffer_allocate(&data->buffer, data->len, MDL)) {
1909 parse_warn (cfile, "can't allocate buffer for base64 data.");
1910 data->len = 0;
1911 data->data = NULL;
1912 goto out;
1915 j = k = 0;
1916 for (t = bufs; t; t = t->next) {
1917 for (i = 0; t->string[i]; i++) {
1918 unsigned foo = t->string[i];
1919 if (terminated && foo != '=') {
1920 parse_warn(cfile,
1921 "stuff after base64 '=' terminator: %s.",
1922 &t->string[i]);
1923 goto bad;
1925 if ((foo < ' ') || (foo > 'z')) {
1926 bad64:
1927 parse_warn(cfile,
1928 "invalid base64 character %d.",
1929 t->string[i]);
1930 bad:
1931 data_string_forget(data, MDL);
1932 goto out;
1934 if (foo == '=')
1935 terminated = 1;
1936 else {
1937 foo = from64[foo - ' '];
1938 if (foo == 64)
1939 goto bad64;
1940 acc = (acc << 6) + foo;
1941 switch (k % 4) {
1942 case 0:
1943 break;
1944 case 1:
1945 data->buffer->data[j++] = (acc >> 4);
1946 acc = acc & 0x0f;
1947 break;
1949 case 2:
1950 data->buffer->data[j++] = (acc >> 2);
1951 acc = acc & 0x03;
1952 break;
1953 case 3:
1954 data->buffer->data[j++] = acc;
1955 acc = 0;
1956 break;
1959 k++;
1962 if (k % 4) {
1963 if (acc) {
1964 parse_warn(cfile,
1965 "partial base64 value left over: %d.",
1966 acc);
1969 data->len = j;
1970 data->data = data->buffer->data;
1971 out:
1972 for (t = bufs; t; t = last) {
1973 last = t->next;
1974 dfree(t, MDL);
1976 if (data->len)
1977 return 1;
1978 else
1979 return 0;
1984 * colon-separated-hex-list :== NUMBER |
1985 * NUMBER COLON colon-separated-hex-list
1988 int parse_cshl (data, cfile)
1989 struct data_string *data;
1990 struct parse *cfile;
1992 u_int8_t ibuf [128];
1993 unsigned ilen = 0;
1994 unsigned tlen = 0;
1995 struct option_tag *sl = (struct option_tag *)0;
1996 struct option_tag *next, **last = &sl;
1997 enum dhcp_token token;
1998 const char *val;
1999 unsigned char *rvp;
2001 do {
2002 token = next_token (&val, (unsigned *)0, cfile);
2003 if (token != NUMBER && token != NUMBER_OR_NAME) {
2004 parse_warn (cfile, "expecting hexadecimal number.");
2005 skip_to_semi (cfile);
2006 for (; sl; sl = next) {
2007 next = sl -> next;
2008 dfree (sl, MDL);
2010 return 0;
2012 if (ilen == sizeof ibuf) {
2013 next = (struct option_tag *)
2014 dmalloc (ilen - 1 +
2015 sizeof (struct option_tag), MDL);
2016 if (!next)
2017 log_fatal ("no memory for string list.");
2018 memcpy (next -> data, ibuf, ilen);
2019 *last = next;
2020 last = &next -> next;
2021 tlen += ilen;
2022 ilen = 0;
2024 convert_num (cfile, &ibuf [ilen++], val, 16, 8);
2026 token = peek_token (&val, (unsigned *)0, cfile);
2027 if (token != COLON)
2028 break;
2029 skip_token(&val, (unsigned *)0, cfile);
2030 } while (1);
2032 if (!buffer_allocate (&data -> buffer, tlen + ilen, MDL))
2033 log_fatal ("no memory to store octet data.");
2034 data -> data = &data -> buffer -> data [0];
2035 data -> len = tlen + ilen;
2036 data -> terminated = 0;
2038 rvp = &data -> buffer -> data [0];
2039 while (sl) {
2040 next = sl -> next;
2041 memcpy (rvp, sl -> data, sizeof ibuf);
2042 rvp += sizeof ibuf;
2043 dfree (sl, MDL);
2044 sl = next;
2047 memcpy (rvp, ibuf, ilen);
2048 return 1;
2052 * executable-statements :== executable-statement executable-statements |
2053 * executable-statement
2055 * executable-statement :==
2056 * IF if-statement |
2057 * ADD class-name SEMI |
2058 * BREAK SEMI |
2059 * OPTION option-parameter SEMI |
2060 * SUPERSEDE option-parameter SEMI |
2061 * PREPEND option-parameter SEMI |
2062 * APPEND option-parameter SEMI
2065 int parse_executable_statements (statements, cfile, lose, case_context)
2066 struct executable_statement **statements;
2067 struct parse *cfile;
2068 int *lose;
2069 enum expression_context case_context;
2071 struct executable_statement **next;
2073 next = statements;
2074 while (parse_executable_statement (next, cfile, lose, case_context))
2075 next = &((*next) -> next);
2076 if (!*lose)
2077 return 1;
2078 return 0;
2081 int parse_executable_statement (result, cfile, lose, case_context)
2082 struct executable_statement **result;
2083 struct parse *cfile;
2084 int *lose;
2085 enum expression_context case_context;
2087 #if defined(ENABLE_EXECUTE)
2088 unsigned len;
2089 struct expression **ep;
2090 #endif
2091 enum dhcp_token token;
2092 const char *val;
2093 struct class *cta;
2094 struct option *option=NULL;
2095 struct option_cache *cache;
2096 int known;
2097 int flag;
2098 int i;
2099 struct dns_zone *zone;
2100 isc_result_t status;
2101 char *s;
2103 token = peek_token (&val, (unsigned *)0, cfile);
2104 switch (token) {
2105 case DB_TIME_FORMAT:
2106 skip_token(&val, NULL, cfile);
2107 token = next_token(&val, NULL, cfile);
2108 if (token == DEFAULT) {
2109 db_time_format = DEFAULT_TIME_FORMAT;
2110 } else if (token == LOCAL) {
2111 db_time_format = LOCAL_TIME_FORMAT;
2112 } else {
2113 parse_warn(cfile, "Expecting 'local' or 'default'.");
2114 if (token != SEMI)
2115 skip_to_semi(cfile);
2116 *lose = 1;
2117 return 0;
2120 token = next_token(&val, NULL, cfile);
2121 if (token != SEMI) {
2122 parse_warn(cfile, "Expecting a semicolon.");
2123 *lose = 1;
2124 return 0;
2127 /* We're done here. */
2128 return 1;
2130 case IF:
2131 skip_token(&val, (unsigned *)0, cfile);
2132 return parse_if_statement (result, cfile, lose);
2134 case TOKEN_ADD:
2135 skip_token(&val, (unsigned *)0, cfile);
2136 token = next_token (&val, (unsigned *)0, cfile);
2137 if (token != STRING) {
2138 parse_warn (cfile, "expecting class name.");
2139 skip_to_semi (cfile);
2140 *lose = 1;
2141 return 0;
2143 cta = (struct class *)0;
2144 status = find_class (&cta, val, MDL);
2145 if (status != ISC_R_SUCCESS) {
2146 parse_warn (cfile, "class %s: %s",
2147 val, isc_result_totext (status));
2148 skip_to_semi (cfile);
2149 *lose = 1;
2150 return 0;
2152 if (!parse_semi (cfile)) {
2153 *lose = 1;
2154 return 0;
2156 if (!executable_statement_allocate (result, MDL))
2157 log_fatal ("no memory for new statement.");
2158 (*result) -> op = add_statement;
2159 (*result) -> data.add = cta;
2160 break;
2162 case BREAK:
2163 skip_token(&val, (unsigned *)0, cfile);
2164 if (!parse_semi (cfile)) {
2165 *lose = 1;
2166 return 0;
2168 if (!executable_statement_allocate (result, MDL))
2169 log_fatal ("no memory for new statement.");
2170 (*result) -> op = break_statement;
2171 break;
2173 case SEND:
2174 skip_token(&val, (unsigned *)0, cfile);
2175 known = 0;
2176 status = parse_option_name (cfile, 0, &known, &option);
2177 if (status != ISC_R_SUCCESS || option == NULL) {
2178 *lose = 1;
2179 return 0;
2181 status = parse_option_statement(result, cfile, 1, option,
2182 send_option_statement);
2183 option_dereference(&option, MDL);
2184 return status;
2186 case SUPERSEDE:
2187 case OPTION:
2188 skip_token(&val, (unsigned *)0, cfile);
2189 known = 0;
2190 status = parse_option_name (cfile, 0, &known, &option);
2191 if (status != ISC_R_SUCCESS || option == NULL) {
2192 *lose = 1;
2193 return 0;
2195 status = parse_option_statement(result, cfile, 1, option,
2196 supersede_option_statement);
2197 option_dereference(&option, MDL);
2198 return status;
2200 case ALLOW:
2201 flag = 1;
2202 goto pad;
2203 case DENY:
2204 flag = 0;
2205 goto pad;
2206 case IGNORE:
2207 flag = 2;
2208 pad:
2209 skip_token(&val, (unsigned *)0, cfile);
2210 cache = (struct option_cache *)0;
2211 if (!parse_allow_deny (&cache, cfile, flag))
2212 return 0;
2213 if (!executable_statement_allocate (result, MDL))
2214 log_fatal ("no memory for new statement.");
2215 (*result) -> op = supersede_option_statement;
2216 (*result) -> data.option = cache;
2217 break;
2219 case DEFAULT:
2220 skip_token(&val, (unsigned *)0, cfile);
2221 token = peek_token (&val, (unsigned *)0, cfile);
2222 if (token == COLON)
2223 goto switch_default;
2224 known = 0;
2225 status = parse_option_name (cfile, 0, &known, &option);
2226 if (status != ISC_R_SUCCESS || option == NULL) {
2227 *lose = 1;
2228 return 0;
2230 status = parse_option_statement(result, cfile, 1, option,
2231 default_option_statement);
2232 option_dereference(&option, MDL);
2233 return status;
2235 case PREPEND:
2236 skip_token(&val, (unsigned *)0, cfile);
2237 known = 0;
2238 status = parse_option_name (cfile, 0, &known, &option);
2239 if (status != ISC_R_SUCCESS || option == NULL) {
2240 *lose = 1;
2241 return 0;
2243 status = parse_option_statement(result, cfile, 1, option,
2244 prepend_option_statement);
2245 option_dereference(&option, MDL);
2246 return status;
2248 case APPEND:
2249 skip_token(&val, (unsigned *)0, cfile);
2250 known = 0;
2251 status = parse_option_name (cfile, 0, &known, &option);
2252 if (status != ISC_R_SUCCESS || option == NULL) {
2253 *lose = 1;
2254 return 0;
2256 status = parse_option_statement(result, cfile, 1, option,
2257 append_option_statement);
2258 option_dereference(&option, MDL);
2259 return status;
2261 case ON:
2262 skip_token(&val, (unsigned *)0, cfile);
2263 return parse_on_statement (result, cfile, lose);
2265 case SWITCH:
2266 skip_token(&val, (unsigned *)0, cfile);
2267 return parse_switch_statement (result, cfile, lose);
2269 case CASE:
2270 skip_token(&val, (unsigned *)0, cfile);
2271 if (case_context == context_any) {
2272 parse_warn (cfile,
2273 "case statement in inappropriate scope.");
2274 *lose = 1;
2275 skip_to_semi (cfile);
2276 return 0;
2278 return parse_case_statement (result,
2279 cfile, lose, case_context);
2281 switch_default:
2282 skip_token(&val, (unsigned *)0, cfile);
2283 if (case_context == context_any) {
2284 parse_warn (cfile, "switch default statement in %s",
2285 "inappropriate scope.");
2287 *lose = 1;
2288 return 0;
2289 } else {
2290 if (!executable_statement_allocate (result, MDL))
2291 log_fatal ("no memory for default statement.");
2292 (*result) -> op = default_statement;
2293 return 1;
2296 case DEFINE:
2297 case TOKEN_SET:
2298 skip_token(&val, (unsigned *)0, cfile);
2299 if (token == DEFINE)
2300 flag = 1;
2301 else
2302 flag = 0;
2304 token = next_token (&val, (unsigned *)0, cfile);
2305 if (token != NAME && token != NUMBER_OR_NAME) {
2306 parse_warn (cfile,
2307 "%s can't be a variable name", val);
2308 badset:
2309 skip_to_semi (cfile);
2310 *lose = 1;
2311 return 0;
2314 if (!executable_statement_allocate (result, MDL))
2315 log_fatal ("no memory for set statement.");
2316 (*result) -> op = flag ? define_statement : set_statement;
2317 (*result) -> data.set.name = dmalloc (strlen (val) + 1, MDL);
2318 if (!(*result)->data.set.name)
2319 log_fatal ("can't allocate variable name");
2320 strcpy ((*result) -> data.set.name, val);
2321 token = next_token (&val, (unsigned *)0, cfile);
2323 if (token == LPAREN) {
2324 struct string_list *head, *cur, *new;
2325 struct expression *expr;
2326 head = cur = (struct string_list *)0;
2327 do {
2328 token = next_token (&val,
2329 (unsigned *)0, cfile);
2330 if (token == RPAREN)
2331 break;
2332 if (token != NAME && token != NUMBER_OR_NAME) {
2333 parse_warn (cfile,
2334 "expecting argument name");
2335 skip_to_rbrace (cfile, 0);
2336 *lose = 1;
2337 executable_statement_dereference
2338 (result, MDL);
2339 return 0;
2341 new = ((struct string_list *)
2342 dmalloc (sizeof (struct string_list) +
2343 strlen (val), MDL));
2344 if (!new)
2345 log_fatal ("can't allocate string.");
2346 memset (new, 0, sizeof *new);
2347 strcpy (new -> string, val);
2348 if (cur) {
2349 cur -> next = new;
2350 cur = new;
2351 } else {
2352 head = cur = new;
2354 token = next_token (&val,
2355 (unsigned *)0, cfile);
2356 } while (token == COMMA);
2358 if (token != RPAREN) {
2359 parse_warn (cfile, "expecting right paren.");
2360 badx:
2361 skip_to_semi (cfile);
2362 *lose = 1;
2363 executable_statement_dereference (result, MDL);
2364 return 0;
2367 token = next_token (&val, (unsigned *)0, cfile);
2368 if (token != LBRACE) {
2369 parse_warn (cfile, "expecting left brace.");
2370 goto badx;
2373 expr = (struct expression *)0;
2374 if (!(expression_allocate (&expr, MDL)))
2375 log_fatal ("can't allocate expression.");
2376 expr -> op = expr_function;
2377 if (!fundef_allocate (&expr -> data.func, MDL))
2378 log_fatal ("can't allocate fundef.");
2379 expr -> data.func -> args = head;
2380 (*result) -> data.set.expr = expr;
2382 if (!(parse_executable_statements
2383 (&expr -> data.func -> statements, cfile, lose,
2384 case_context))) {
2385 if (*lose)
2386 goto badx;
2389 token = next_token (&val, (unsigned *)0, cfile);
2390 if (token != RBRACE) {
2391 parse_warn (cfile, "expecting rigt brace.");
2392 goto badx;
2394 } else {
2395 if (token != EQUAL) {
2396 parse_warn (cfile,
2397 "expecting '=' in %s statement.",
2398 flag ? "define" : "set");
2399 goto badset;
2402 if (!parse_expression (&(*result) -> data.set.expr,
2403 cfile, lose, context_any,
2404 (struct expression **)0,
2405 expr_none)) {
2406 if (!*lose)
2407 parse_warn (cfile,
2408 "expecting expression.");
2409 else
2410 *lose = 1;
2411 skip_to_semi (cfile);
2412 executable_statement_dereference (result, MDL);
2413 return 0;
2415 if (!parse_semi (cfile)) {
2416 *lose = 1;
2417 executable_statement_dereference (result, MDL);
2418 return 0;
2421 break;
2423 case UNSET:
2424 skip_token(&val, (unsigned *)0, cfile);
2425 token = next_token (&val, (unsigned *)0, cfile);
2426 if (token != NAME && token != NUMBER_OR_NAME) {
2427 parse_warn (cfile,
2428 "%s can't be a variable name", val);
2429 skip_to_semi (cfile);
2430 *lose = 1;
2431 return 0;
2434 if (!executable_statement_allocate (result, MDL))
2435 log_fatal ("no memory for set statement.");
2436 (*result) -> op = unset_statement;
2437 (*result) -> data.unset = dmalloc (strlen (val) + 1, MDL);
2438 if (!(*result)->data.unset)
2439 log_fatal ("can't allocate variable name");
2440 strcpy ((*result) -> data.unset, val);
2441 if (!parse_semi (cfile)) {
2442 *lose = 1;
2443 executable_statement_dereference (result, MDL);
2444 return 0;
2446 break;
2448 case EVAL:
2449 skip_token(&val, (unsigned *)0, cfile);
2450 if (!executable_statement_allocate (result, MDL))
2451 log_fatal ("no memory for eval statement.");
2452 (*result) -> op = eval_statement;
2454 if (!parse_expression (&(*result) -> data.eval,
2455 cfile, lose, context_data, /* XXX */
2456 (struct expression **)0, expr_none)) {
2457 if (!*lose)
2458 parse_warn (cfile,
2459 "expecting data expression.");
2460 else
2461 *lose = 1;
2462 skip_to_semi (cfile);
2463 executable_statement_dereference (result, MDL);
2464 return 0;
2466 if (!parse_semi (cfile)) {
2467 *lose = 1;
2468 executable_statement_dereference (result, MDL);
2470 break;
2472 case EXECUTE:
2473 #ifdef ENABLE_EXECUTE
2474 skip_token(&val, NULL, cfile);
2476 if (!executable_statement_allocate (result, MDL))
2477 log_fatal ("no memory for execute statement.");
2478 (*result)->op = execute_statement;
2480 token = next_token(&val, NULL, cfile);
2481 if (token != LPAREN) {
2482 parse_warn(cfile, "left parenthesis expected.");
2483 skip_to_semi(cfile);
2484 *lose = 1;
2485 return 0;
2488 token = next_token(&val, &len, cfile);
2489 if (token != STRING) {
2490 parse_warn(cfile, "Expecting a quoted string.");
2491 skip_to_semi(cfile);
2492 *lose = 1;
2493 return 0;
2496 (*result)->data.execute.command = dmalloc(len + 1, MDL);
2497 if ((*result)->data.execute.command == NULL)
2498 log_fatal("can't allocate command name");
2499 strcpy((*result)->data.execute.command, val);
2501 ep = &(*result)->data.execute.arglist;
2502 (*result)->data.execute.argc = 0;
2504 while((token = next_token(&val, NULL, cfile)) == COMMA) {
2505 if (!expression_allocate(ep, MDL))
2506 log_fatal ("can't allocate expression");
2508 if (!parse_data_expression (&(*ep) -> data.arg.val,
2509 cfile, lose)) {
2510 if (!*lose) {
2511 parse_warn (cfile,
2512 "expecting expression.");
2513 *lose = 1;
2515 skip_to_semi(cfile);
2516 *lose = 1;
2517 return 0;
2519 ep = &(*ep)->data.arg.next;
2520 (*result)->data.execute.argc++;
2523 if (token != RPAREN) {
2524 parse_warn(cfile, "right parenthesis expected.");
2525 skip_to_semi(cfile);
2526 *lose = 1;
2527 return 0;
2530 if (!parse_semi (cfile)) {
2531 *lose = 1;
2532 executable_statement_dereference (result, MDL);
2534 #else /* ! ENABLE_EXECUTE */
2535 parse_warn(cfile, "define ENABLE_EXECUTE in site.h to "
2536 "enable execute(); expressions.");
2537 skip_to_semi(cfile);
2538 *lose = 1;
2539 return 0;
2540 #endif /* ENABLE_EXECUTE */
2541 break;
2543 case RETURN:
2544 skip_token(&val, (unsigned *)0, cfile);
2546 if (!executable_statement_allocate (result, MDL))
2547 log_fatal ("no memory for return statement.");
2548 (*result) -> op = return_statement;
2550 if (!parse_expression (&(*result) -> data.retval,
2551 cfile, lose, context_data,
2552 (struct expression **)0, expr_none)) {
2553 if (!*lose)
2554 parse_warn (cfile,
2555 "expecting data expression.");
2556 else
2557 *lose = 1;
2558 skip_to_semi (cfile);
2559 executable_statement_dereference (result, MDL);
2560 return 0;
2562 if (!parse_semi (cfile)) {
2563 *lose = 1;
2564 executable_statement_dereference (result, MDL);
2565 return 0;
2567 break;
2569 case LOG:
2570 skip_token(&val, (unsigned *)0, cfile);
2572 if (!executable_statement_allocate (result, MDL))
2573 log_fatal ("no memory for log statement.");
2574 (*result) -> op = log_statement;
2576 token = next_token (&val, (unsigned *)0, cfile);
2577 if (token != LPAREN) {
2578 parse_warn (cfile, "left parenthesis expected.");
2579 skip_to_semi (cfile);
2580 *lose = 1;
2581 return 0;
2584 token = peek_token (&val, (unsigned *)0, cfile);
2585 i = 1;
2586 if (token == FATAL) {
2587 (*result) -> data.log.priority = log_priority_fatal;
2588 } else if (token == ERROR) {
2589 (*result) -> data.log.priority = log_priority_error;
2590 } else if (token == TOKEN_DEBUG) {
2591 (*result) -> data.log.priority = log_priority_debug;
2592 } else if (token == INFO) {
2593 (*result) -> data.log.priority = log_priority_info;
2594 } else {
2595 (*result) -> data.log.priority = log_priority_debug;
2596 i = 0;
2598 if (i) {
2599 skip_token(&val, (unsigned *)0, cfile);
2600 token = next_token (&val, (unsigned *)0, cfile);
2601 if (token != COMMA) {
2602 parse_warn (cfile, "comma expected.");
2603 skip_to_semi (cfile);
2604 *lose = 1;
2605 return 0;
2609 if (!(parse_data_expression
2610 (&(*result) -> data.log.expr, cfile, lose))) {
2611 skip_to_semi (cfile);
2612 *lose = 1;
2613 return 0;
2616 token = next_token (&val, (unsigned *)0, cfile);
2617 if (token != RPAREN) {
2618 parse_warn (cfile, "right parenthesis expected.");
2619 skip_to_semi (cfile);
2620 *lose = 1;
2621 return 0;
2624 token = next_token (&val, (unsigned *)0, cfile);
2625 if (token != SEMI) {
2626 parse_warn (cfile, "semicolon expected.");
2627 skip_to_semi (cfile);
2628 *lose = 1;
2629 return 0;
2631 break;
2633 /* Not really a statement, but we parse it here anyway
2634 because it's appropriate for all DHCP agents with
2635 parsers. */
2636 case ZONE:
2637 skip_token(&val, (unsigned *)0, cfile);
2638 zone = (struct dns_zone *)0;
2639 if (!dns_zone_allocate (&zone, MDL))
2640 log_fatal ("no memory for new zone.");
2641 zone -> name = parse_host_name (cfile);
2642 if (!zone -> name) {
2643 parse_warn (cfile, "expecting hostname.");
2644 badzone:
2645 *lose = 1;
2646 skip_to_semi (cfile);
2647 dns_zone_dereference (&zone, MDL);
2648 return 0;
2650 i = strlen (zone -> name);
2651 if (zone -> name [i - 1] != '.') {
2652 s = dmalloc ((unsigned)i + 2, MDL);
2653 if (!s) {
2654 parse_warn (cfile, "no trailing '.' on zone");
2655 goto badzone;
2657 strcpy (s, zone -> name);
2658 s [i] = '.';
2659 s [i + 1] = 0;
2660 dfree (zone -> name, MDL);
2661 zone -> name = s;
2663 if (!parse_zone (zone, cfile))
2664 goto badzone;
2665 status = enter_dns_zone (zone);
2666 if (status != ISC_R_SUCCESS) {
2667 parse_warn (cfile, "dns zone key %s: %s",
2668 zone -> name, isc_result_totext (status));
2669 dns_zone_dereference (&zone, MDL);
2670 return 0;
2672 dns_zone_dereference (&zone, MDL);
2673 return 1;
2675 /* Also not really a statement, but same idea as above. */
2676 case KEY:
2677 skip_token(&val, (unsigned *)0, cfile);
2678 if (!parse_key (cfile)) {
2679 *lose = 1;
2680 return 0;
2682 return 1;
2684 default:
2685 if (config_universe && is_identifier (token)) {
2686 option = (struct option *)0;
2687 option_name_hash_lookup(&option,
2688 config_universe->name_hash,
2689 val, 0, MDL);
2690 if (option) {
2691 skip_token(&val, (unsigned *)0, cfile);
2692 status = parse_option_statement
2693 (result, cfile, 1, option,
2694 supersede_option_statement);
2695 option_dereference(&option, MDL);
2696 return status;
2700 if (token == NUMBER_OR_NAME || token == NAME) {
2701 /* This is rather ugly. Since function calls are
2702 data expressions, fake up an eval statement. */
2703 if (!executable_statement_allocate (result, MDL))
2704 log_fatal ("no memory for eval statement.");
2705 (*result) -> op = eval_statement;
2707 if (!parse_expression (&(*result) -> data.eval,
2708 cfile, lose, context_data,
2709 (struct expression **)0,
2710 expr_none)) {
2711 if (!*lose)
2712 parse_warn (cfile, "expecting "
2713 "function call.");
2714 else
2715 *lose = 1;
2716 skip_to_semi (cfile);
2717 executable_statement_dereference (result, MDL);
2718 return 0;
2720 if (!parse_semi (cfile)) {
2721 *lose = 1;
2722 executable_statement_dereference (result, MDL);
2723 return 0;
2725 break;
2728 *lose = 0;
2729 return 0;
2732 return 1;
2735 /* zone-statements :== zone-statement |
2736 zone-statement zone-statements
2737 zone-statement :==
2738 PRIMARY ip-addresses SEMI |
2739 SECONDARY ip-addresses SEMI |
2740 PRIMARY6 ip-address6 SEMI |
2741 SECONDARY6 ip-address6 SEMI |
2742 key-reference SEMI
2743 ip-addresses :== ip-addr-or-hostname |
2744 ip-addr-or-hostname COMMA ip-addresses
2745 key-reference :== KEY STRING |
2746 KEY identifier */
2748 int parse_zone (struct dns_zone *zone, struct parse *cfile)
2750 int token;
2751 const char *val;
2752 char *key_name;
2753 struct option_cache *oc;
2754 int done = 0;
2756 token = next_token (&val, (unsigned *)0, cfile);
2757 if (token != LBRACE) {
2758 parse_warn (cfile, "expecting left brace");
2759 return 0;
2762 do {
2763 token = peek_token (&val, (unsigned *)0, cfile);
2764 switch (token) {
2765 case PRIMARY:
2766 if (zone -> primary) {
2767 parse_warn (cfile,
2768 "more than one primary.");
2769 skip_to_semi (cfile);
2770 return 0;
2772 if (!option_cache_allocate (&zone -> primary, MDL))
2773 log_fatal ("can't allocate primary option cache.");
2774 oc = zone -> primary;
2775 goto consemup;
2777 case SECONDARY:
2778 if (zone -> secondary) {
2779 parse_warn (cfile, "more than one secondary.");
2780 skip_to_semi (cfile);
2781 return 0;
2783 if (!option_cache_allocate (&zone -> secondary, MDL))
2784 log_fatal ("can't allocate secondary.");
2785 oc = zone -> secondary;
2786 consemup:
2787 skip_token(&val, (unsigned *)0, cfile);
2788 do {
2789 struct expression *expr = (struct expression *)0;
2790 if (!parse_ip_addr_or_hostname (&expr, cfile, 0)) {
2791 parse_warn (cfile,
2792 "expecting IP addr or hostname.");
2793 skip_to_semi (cfile);
2794 return 0;
2796 if (oc -> expression) {
2797 struct expression *old =
2798 (struct expression *)0;
2799 expression_reference (&old,
2800 oc -> expression,
2801 MDL);
2802 expression_dereference (&oc -> expression,
2803 MDL);
2804 if (!make_concat (&oc -> expression,
2805 old, expr))
2806 log_fatal ("no memory for concat.");
2807 expression_dereference (&expr, MDL);
2808 expression_dereference (&old, MDL);
2809 } else {
2810 expression_reference (&oc -> expression,
2811 expr, MDL);
2812 expression_dereference (&expr, MDL);
2814 token = next_token (&val, (unsigned *)0, cfile);
2815 } while (token == COMMA);
2816 if (token != SEMI) {
2817 parse_warn (cfile, "expecting semicolon.");
2818 skip_to_semi (cfile);
2819 return 0;
2821 break;
2823 case PRIMARY6:
2824 if (zone->primary6) {
2825 parse_warn(cfile, "more than one primary6.");
2826 skip_to_semi(cfile);
2827 return (0);
2829 if (!option_cache_allocate (&zone->primary6, MDL))
2830 log_fatal("can't allocate primary6 option cache.");
2831 oc = zone->primary6;
2832 goto consemup6;
2834 case SECONDARY6:
2835 if (zone->secondary6) {
2836 parse_warn(cfile, "more than one secondary6.");
2837 skip_to_semi(cfile);
2838 return (0);
2840 if (!option_cache_allocate (&zone->secondary6, MDL))
2841 log_fatal("can't allocate secondary6 "
2842 "option cache.");
2843 oc = zone->secondary6;
2844 consemup6:
2845 skip_token(&val, NULL, cfile);
2846 do {
2847 struct expression *expr = NULL;
2848 if (parse_ip6_addr_expr(&expr, cfile) == 0) {
2849 parse_warn(cfile, "expecting IPv6 addr.");
2850 skip_to_semi(cfile);
2851 return (0);
2853 if (oc->expression) {
2854 struct expression *old = NULL;
2855 expression_reference(&old, oc->expression,
2856 MDL);
2857 expression_dereference(&oc->expression,
2858 MDL);
2859 if (!make_concat(&oc->expression,
2860 old, expr))
2861 log_fatal("no memory for concat.");
2862 expression_dereference(&expr, MDL);
2863 expression_dereference(&old, MDL);
2864 } else {
2865 expression_reference(&oc->expression,
2866 expr, MDL);
2867 expression_dereference(&expr, MDL);
2869 token = next_token(&val, NULL, cfile);
2870 } while (token == COMMA);
2871 if (token != SEMI) {
2872 parse_warn(cfile, "expecting semicolon.");
2873 skip_to_semi(cfile);
2874 return (0);
2876 break;
2878 case KEY:
2879 skip_token(&val, (unsigned *)0, cfile);
2880 token = peek_token (&val, (unsigned *)0, cfile);
2881 if (token == STRING) {
2882 skip_token(&val, (unsigned *)0, cfile);
2883 key_name = (char *)0;
2884 } else {
2885 key_name = parse_host_name (cfile);
2886 if (!key_name) {
2887 parse_warn (cfile, "expecting key name.");
2888 skip_to_semi (cfile);
2889 return 0;
2891 val = key_name;
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;
2902 default:
2903 done = 1;
2904 break;
2906 } while (!done);
2908 token = next_token (&val, (unsigned *)0, cfile);
2909 if (token != RBRACE) {
2910 parse_warn (cfile, "expecting right brace.");
2911 return 0;
2913 return 1;
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 */
2924 int parse_key (struct parse *cfile)
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;
2934 key = (struct auth_key *)0;
2935 if (omapi_auth_key_new (&key, MDL) != ISC_R_SUCCESS)
2936 log_fatal ("no memory for key");
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);
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;
2955 token = next_token (&val, (unsigned *)0, cfile);
2956 if (token != LBRACE) {
2957 parse_warn (cfile, "expecting left brace");
2958 goto bad;
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;
2971 key -> algorithm = parse_host_name (cfile);
2972 if (!key -> algorithm) {
2973 parse_warn (cfile,
2974 "expecting key algorithm name.");
2975 goto rbad;
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;
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;
3003 strcpy (s, key -> algorithm);
3004 strcat (s, ".");
3005 dfree (key -> algorithm, MDL);
3006 key -> algorithm = s;
3008 break;
3010 case SECRET:
3011 if (key -> key) {
3012 parse_warn (cfile, "key %s: too many secrets",
3013 key -> name);
3014 goto rbad;
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);
3028 if (!parse_semi (cfile))
3029 goto rbad;
3030 break;
3032 default:
3033 done = 1;
3034 break;
3036 } while (!done);
3037 if (token != RBRACE) {
3038 parse_warn (cfile, "expecting right brace.");
3039 goto rbad;
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);
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;
3055 omapi_auth_key_dereference (&key, MDL);
3056 return 1;
3058 rbad:
3059 skip_to_rbrace (cfile, 1);
3060 bad:
3061 omapi_auth_key_dereference (&key, MDL);
3062 return 0;
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
3072 int parse_on_statement (result, cfile, lose)
3073 struct executable_statement **result;
3074 struct parse *cfile;
3075 int *lose;
3077 enum dhcp_token token;
3078 const char *val;
3080 if (!executable_statement_allocate (result, MDL))
3081 log_fatal ("no memory for new statement.");
3082 (*result) -> op = on_statement;
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;
3091 case COMMIT:
3092 (*result) -> data.on.evtypes |= ON_COMMIT;
3093 break;
3095 case RELEASE:
3096 (*result) -> data.on.evtypes |= ON_RELEASE;
3097 break;
3099 case TRANSMISSION:
3100 (*result) -> data.on.evtypes |= ON_TRANSMISSION;
3101 break;
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;
3110 token = next_token (&val, (unsigned *)0, cfile);
3111 } while (token == OR);
3113 /* Semicolon means no statements. */
3114 if (token == SEMI)
3115 return 1;
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;
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;
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;
3144 return 1;
3148 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3152 int parse_switch_statement (result, cfile, lose)
3153 struct executable_statement **result;
3154 struct parse *cfile;
3155 int *lose;
3157 enum dhcp_token token;
3158 const char *val;
3160 if (!executable_statement_allocate (result, MDL))
3161 log_fatal ("no memory for new statement.");
3162 (*result) -> op = switch_statement;
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;
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;
3183 goto gnorf;
3186 token = next_token (&val, (unsigned *)0, cfile);
3187 if (token != RPAREN) {
3188 parse_warn (cfile, "right paren expected.");
3189 goto pfui;
3192 token = next_token (&val, (unsigned *)0, cfile);
3193 if (token != LBRACE) {
3194 parse_warn (cfile, "left brace expected.");
3195 goto pfui;
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;
3207 token = next_token (&val, (unsigned *)0, cfile);
3208 if (token != RBRACE) {
3209 parse_warn (cfile, "right brace expected.");
3210 goto pfui;
3212 return 1;
3216 * case-statement :== CASE expr COLON
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;
3226 enum dhcp_token token;
3227 const char *val;
3229 if (!executable_statement_allocate (result, MDL))
3230 log_fatal ("no memory for new statement.");
3231 (*result) -> op = case_statement;
3233 if (!parse_expression (&(*result) -> data.c_case,
3234 cfile, lose, case_context,
3235 (struct expression **)0, expr_none))
3237 if (!*lose) {
3238 parse_warn (cfile, "expecting %s expression.",
3239 (case_context == context_data
3240 ? "data" : "numeric"));
3242 pfui:
3243 *lose = 1;
3244 skip_to_semi (cfile);
3245 executable_statement_dereference (result, MDL);
3246 return 0;
3249 token = next_token (&val, (unsigned *)0, cfile);
3250 if (token != COLON) {
3251 parse_warn (cfile, "colon expected.");
3252 goto pfui;
3254 return 1;
3258 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3259 * else-statement
3261 * else-statement :== <null> |
3262 * ELSE LBRACE executable-statements RBRACE |
3263 * ELSE IF if-statement |
3264 * ELSIF if-statement
3267 int parse_if_statement (result, cfile, lose)
3268 struct executable_statement **result;
3269 struct parse *cfile;
3270 int *lose;
3272 enum dhcp_token token;
3273 const char *val;
3274 int parenp;
3276 if (!executable_statement_allocate (result, MDL))
3277 log_fatal ("no memory for if statement.");
3279 (*result) -> op = if_statement;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
3386 } else
3387 (*result) -> data.ie.fc = (struct executable_statement *)0;
3389 return 1;
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
3403 int parse_boolean_expression (expr, cfile, lose)
3404 struct expression **expr;
3405 struct parse *cfile;
3406 int *lose;
3408 /* Parse an expression... */
3409 if (!parse_expression (expr, cfile, lose, context_boolean,
3410 (struct expression **)0, expr_none))
3411 return 0;
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;
3421 return 1;
3424 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3426 int parse_boolean (cfile)
3427 struct parse *cfile;
3429 const char *val;
3430 int rv;
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;
3445 parse_semi (cfile);
3446 return rv;
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
3470 int parse_data_expression (expr, cfile, lose)
3471 struct expression **expr;
3472 struct parse *cfile;
3473 int *lose;
3475 /* Parse an expression... */
3476 if (!parse_expression (expr, cfile, lose, context_data,
3477 (struct expression **)0, expr_none))
3478 return 0;
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;
3488 return 1;
3492 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3493 * COMMA number RPAREN |
3494 * NUMBER
3497 int parse_numeric_expression (expr, cfile, lose)
3498 struct expression **expr;
3499 struct parse *cfile;
3500 int *lose;
3502 /* Parse an expression... */
3503 if (!parse_expression (expr, cfile, lose, context_numeric,
3504 (struct expression **)0, expr_none))
3505 return 0;
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;
3515 return 1;
3518 /* Parse a subexpression that does not contain a binary operator. */
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;
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;
3535 token = peek_token (&val, (unsigned *)0, cfile);
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;
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;
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;
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);
3573 *lose = 1;
3574 expression_dereference (expr, MDL);
3575 return (0);
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;
3584 break;
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);
3594 *lose = 1;
3595 return 0;
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;
3604 break;
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);
3621 break;
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;
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;
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;
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;
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;
3662 return 0;
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;
3672 return 0;
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;
3684 expression_dereference (expr, MDL);
3685 return 0;
3688 token = next_token (&val, (unsigned *)0, cfile);
3689 if (token != COMMA)
3690 goto nocomma;
3692 if (!parse_numeric_expression
3693 (&(*expr) -> data.substring.len, cfile, lose))
3694 goto nonum;
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;
3704 break;
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;
3712 token = next_token (&val, (unsigned *)0, cfile);
3713 if (token != LPAREN)
3714 goto nolparen;
3716 if (!parse_data_expression (&(*expr) -> data.suffix.expr,
3717 cfile, lose))
3718 goto nodata;
3720 token = next_token (&val, (unsigned *)0, cfile);
3721 if (token != COMMA)
3722 goto nocomma;
3724 if (!parse_numeric_expression (&(*expr) -> data.suffix.len,
3725 cfile, lose))
3726 goto nonum;
3728 token = next_token (&val, (unsigned *)0, cfile);
3729 if (token != RPAREN)
3730 goto norparen;
3731 break;
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;
3739 token = next_token(&val, (unsigned *)0, cfile);
3740 if (token != LPAREN)
3741 goto nolparen;
3743 if (!parse_data_expression(&(*expr)->data.lcase, cfile, lose))
3744 goto nodata;
3746 token = next_token(&val, (unsigned *)0, cfile);
3747 if (token != RPAREN)
3748 goto norparen;
3749 break;
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;
3757 token = next_token (&val, (unsigned *)0, cfile);
3758 if (token != LPAREN)
3759 goto nolparen;
3761 if (!parse_data_expression(&(*expr)->data.ucase,
3762 cfile, lose))
3763 goto nodata;
3765 token = next_token(&val, (unsigned *)0, cfile);
3766 if (token != RPAREN)
3767 goto norparen;
3768 break;
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;
3776 token = next_token (&val, (unsigned *)0, cfile);
3777 if (token != LPAREN)
3778 goto nolparen;
3780 if (!parse_data_expression (&(*expr) -> data.concat [0],
3781 cfile, lose))
3782 goto nodata;
3784 token = next_token (&val, (unsigned *)0, cfile);
3785 if (token != COMMA)
3786 goto nocomma;
3788 concat_another:
3789 if (!parse_data_expression (&(*expr) -> data.concat [1],
3790 cfile, lose))
3791 goto nodata;
3793 token = next_token (&val, (unsigned *)0, cfile);
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;
3808 if (token != RPAREN)
3809 goto norparen;
3810 break;
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;
3818 token = next_token (&val, (unsigned *)0, cfile);
3819 if (token != LPAREN)
3820 goto nolparen;
3822 if (!parse_numeric_expression (&(*expr) -> data.b2a.base,
3823 cfile, lose))
3824 goto nodata;
3826 token = next_token (&val, (unsigned *)0, cfile);
3827 if (token != COMMA)
3828 goto nocomma;
3830 if (!parse_numeric_expression (&(*expr) -> data.b2a.width,
3831 cfile, lose))
3832 goto nodata;
3834 token = next_token (&val, (unsigned *)0, cfile);
3835 if (token != COMMA)
3836 goto nocomma;
3838 if (!parse_data_expression (&(*expr) -> data.b2a.separator,
3839 cfile, lose))
3840 goto nodata;
3842 token = next_token (&val, (unsigned *)0, cfile);
3843 if (token != COMMA)
3844 goto nocomma;
3846 if (!parse_data_expression (&(*expr) -> data.b2a.buffer,
3847 cfile, lose))
3848 goto nodata;
3850 token = next_token (&val, (unsigned *)0, cfile);
3851 if (token != RPAREN)
3852 goto norparen;
3853 break;
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;
3861 token = next_token (&val, (unsigned *)0, cfile);
3862 if (token != LPAREN)
3863 goto nolparen;
3865 if (!(parse_numeric_expression
3866 (&(*expr) -> data.reverse.width, cfile, lose)))
3867 goto nodata;
3869 token = next_token (&val, (unsigned *)0, cfile);
3870 if (token != COMMA)
3871 goto nocomma;
3873 if (!(parse_data_expression
3874 (&(*expr) -> data.reverse.buffer, cfile, lose)))
3875 goto nodata;
3877 token = next_token (&val, (unsigned *)0, cfile);
3878 if (token != RPAREN)
3879 goto norparen;
3880 break;
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");
3889 token = next_token (&val, (unsigned *)0, cfile);
3890 if (token != LPAREN)
3891 goto nolparen;
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;
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);
3913 } while (token == COMMA);
3914 expression_dereference (&nexp, MDL);
3916 if (token != RPAREN)
3917 goto norparen;
3918 break;
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;
3938 break;
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;
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;
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;
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;
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;
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;
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;
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;
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;
4002 token = next_token (&val, (unsigned *)0, cfile);
4003 if (token != LPAREN)
4004 goto nolparen;
4006 if (!parse_numeric_expression (&(*expr) -> data.packet.offset,
4007 cfile, lose))
4008 goto nonum;
4010 token = next_token (&val, (unsigned *)0, cfile);
4011 if (token != COMMA)
4012 goto nocomma;
4014 if (!parse_numeric_expression (&(*expr) -> data.packet.len,
4015 cfile, lose))
4016 goto nonum;
4018 token = next_token (&val, (unsigned *)0, cfile);
4019 if (token != RPAREN)
4020 goto norparen;
4021 break;
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;
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;
4039 if (!expression_allocate (expr, MDL))
4040 log_fatal ("can't allocate expression");
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;
4050 expression_dereference (expr, MDL);
4051 return 0;
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;
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;
4069 switch (atoi (val)) {
4070 case 8:
4071 (*expr) -> op = expr_extract_int8;
4072 break;
4074 case 16:
4075 (*expr) -> op = expr_extract_int16;
4076 break;
4078 case 32:
4079 (*expr) -> op = expr_extract_int32;
4080 break;
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;
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;
4098 break;
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;
4109 if (!expression_allocate (expr, MDL))
4110 log_fatal ("can't allocate expression");
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;
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;
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;
4136 switch (atoi (val)) {
4137 case 8:
4138 (*expr) -> op = expr_encode_int8;
4139 break;
4141 case 16:
4142 (*expr) -> op = expr_encode_int16;
4143 break;
4145 case 32:
4146 (*expr) -> op = expr_encode_int32;
4147 break;
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;
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;
4165 break;
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;
4180 case NUMBER_OR_NAME:
4181 if (!expression_allocate (expr, MDL))
4182 log_fatal ("can't allocate expression");
4184 (*expr) -> op = expr_const_data;
4185 if (!parse_cshl (&(*expr) -> data.const_data, cfile)) {
4186 expression_dereference (expr, MDL);
4187 return 0;
4189 break;
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;
4202 case NS_NOERROR:
4203 known = ISC_R_SUCCESS;
4204 goto ns_const;
4206 case NS_NOTAUTH:
4207 known = DHCP_R_NOTAUTH;
4208 goto ns_const;
4210 case NS_NOTIMP:
4211 known = ISC_R_NOTIMPLEMENTED;
4212 goto ns_const;
4214 case NS_NOTZONE:
4215 known = DHCP_R_NOTZONE;
4216 goto ns_const;
4218 case NS_NXDOMAIN:
4219 known = DHCP_R_NXDOMAIN;
4220 goto ns_const;
4222 case NS_NXRRSET:
4223 known = DHCP_R_NXRRSET;
4224 goto ns_const;
4226 case NS_REFUSED:
4227 known = DHCP_R_REFUSED;
4228 goto ns_const;
4230 case NS_SERVFAIL:
4231 known = DHCP_R_SERVFAIL;
4232 goto ns_const;
4234 case NS_YXDOMAIN:
4235 known = DHCP_R_YXDOMAIN;
4236 goto ns_const;
4238 case NS_YXRRSET:
4239 known = DHCP_R_YXRRSET;
4240 goto ns_const;
4242 case BOOTING:
4243 known = S_INIT;
4244 goto ns_const;
4246 case REBOOT:
4247 known = S_REBOOTING;
4248 goto ns_const;
4250 case SELECT:
4251 known = S_SELECTING;
4252 goto ns_const;
4254 case REQUEST:
4255 known = S_REQUESTING;
4256 goto ns_const;
4258 case BOUND:
4259 known = S_BOUND;
4260 goto ns_const;
4262 case RENEW:
4263 known = S_RENEWING;
4264 goto ns_const;
4266 case REBIND:
4267 known = S_REBINDING;
4268 goto ns_const;
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;
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;
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;
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;
4303 token = next_token(NULL, NULL, cfile);
4304 if (token != LPAREN)
4305 goto nolparen;
4307 token = next_token(NULL, NULL, cfile);
4308 if (token != RPAREN)
4309 goto norparen;
4310 break;
4312 case GETHOSTBYNAME:
4313 skip_token(&val, NULL, cfile);
4314 token = next_token(NULL, NULL, cfile);
4315 if (token != LPAREN)
4316 goto nolparen;
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;
4327 if (!make_host_lookup(expr, val))
4328 log_fatal("Error creating gethostbyname() internal "
4329 "record. (%s:%d)", MDL);
4331 token = next_token(NULL, NULL, cfile);
4332 if (token != RPAREN)
4333 goto norparen;
4334 break;
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;
4342 token = next_token (&val, NULL, cfile);
4343 if (token != LPAREN)
4344 goto nolparen;
4346 if (!parse_numeric_expression (&(*expr)->data.v6relay.relay,
4347 cfile, lose))
4348 goto nodata;
4350 token = next_token (&val, NULL, cfile);
4351 if (token != COMMA)
4352 goto nocomma;
4354 if (!parse_data_expression (&(*expr)->data.v6relay.roption,
4355 cfile, lose))
4356 goto nodata;
4358 token = next_token (&val, NULL, cfile);
4360 if (token != RPAREN)
4361 goto norparen;
4362 break;
4364 /* Not a valid start to an expression... */
4365 default:
4366 if (token != NAME && token != NUMBER_OR_NAME)
4367 return 0;
4369 skip_token(&val, (unsigned *)0, cfile);
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);
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;
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;
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;
4408 skip_to_semi (cfile);
4409 expression_dereference (expr, MDL);
4410 return 0;
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;
4422 break;
4424 return 1;
4427 /* Parse an expression. */
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;
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;
4446 /* Consume the left hand side we were passed. */
4447 if (plhs) {
4448 expression_reference (&lhs, *plhs, MDL);
4449 expression_dereference (plhs, MDL);
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);
4464 expression_dereference (&lhs, MDL);
4466 return 0;
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. */
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;
4486 next_op = expr_not_equal;
4487 context = expression_context (rhs);
4488 break;
4490 case EQUAL:
4491 next_op = expr_equal;
4492 context = expression_context (rhs);
4493 break;
4495 case TILDE:
4496 #ifdef HAVE_REGEX_H
4497 skip_token(&val, NULL, cfile);
4498 token = peek_token(&val, NULL, cfile);
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;
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;
4524 case AND:
4525 next_op = expr_and;
4526 context = expression_context (rhs);
4527 break;
4529 case OR:
4530 next_op = expr_or;
4531 context = expression_context (rhs);
4532 break;
4534 case PLUS:
4535 next_op = expr_add;
4536 context = expression_context (rhs);
4537 break;
4539 case MINUS:
4540 next_op = expr_subtract;
4541 context = expression_context (rhs);
4542 break;
4544 case SLASH:
4545 next_op = expr_divide;
4546 context = expression_context (rhs);
4547 break;
4549 case ASTERISK:
4550 next_op = expr_multiply;
4551 context = expression_context (rhs);
4552 break;
4554 case PERCENT:
4555 next_op = expr_remainder;
4556 context = expression_context (rhs);
4557 break;
4559 case AMPERSAND:
4560 next_op = expr_binary_and;
4561 context = expression_context (rhs);
4562 break;
4564 case PIPE:
4565 next_op = expr_binary_or;
4566 context = expression_context (rhs);
4567 break;
4569 case CARET:
4570 next_op = expr_binary_xor;
4571 context = expression_context (rhs);
4572 break;
4574 default:
4575 next_op = expr_none;
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;
4586 lhs = rhs;
4587 rhs = (struct expression *)0;
4588 binop = next_op;
4589 skip_token(&val, (unsigned *)0, cfile);
4590 goto new_rhs;
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.
4598 if (binop != expr_none && next_op != expr_none &&
4599 op_precedence (binop, next_op) < 0) {
4601 /* Eat the subexpression operator token, which we pass to
4602 * parse_expression...we only peek()'d earlier.
4604 skip_token(&val, (unsigned *)0, cfile);
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;
4616 return 0;
4618 next_op = expr_none;
4621 if (binop != expr_none) {
4622 rhs_context = expression_context(rhs);
4623 lhs_context = expression_context(lhs);
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;
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;
4648 break;
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;
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.
4663 log_fatal("Impossible condition at %s:%d.", MDL);
4664 #endif
4665 break;
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;
4677 break;
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;
4695 break;
4697 default:
4698 break;
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!");
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;
4718 /* Eat the operator token - we now know it was a binary operator... */
4719 skip_token(&val, (unsigned *)0, cfile);
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.");
4726 /* Store the LHS and RHS. */
4727 tmp -> data.equal [0] = lhs;
4728 tmp -> data.equal [1] = rhs;
4729 tmp -> op = binop;
4731 lhs = tmp;
4732 tmp = (struct expression *)0;
4733 rhs = (struct expression *)0;
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;
4743 binop = next_op;
4744 goto new_rhs;
4748 int parse_option_data (expr, cfile, lookups, option)
4749 struct expression **expr;
4750 struct parse *cfile;
4751 int lookups;
4752 struct option *option;
4754 const char *val;
4755 const char *fmt = NULL;
4756 struct expression *tmp;
4757 enum dhcp_token token;
4759 do {
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.
4765 int uniform = 0;
4767 and_again:
4768 /* Set fmt to start of format for 'A' and one char back
4769 * for 'a'.
4771 if ((fmt != NULL) && (fmt != option->format) && (*fmt == 'a'))
4772 fmt -= 1;
4773 else if ((fmt == NULL) || (*fmt == 'A'))
4774 fmt = option->format;
4776 /* 'a' means always uniform */
4777 if ((fmt[0] != 'Z') && (tolower((unsigned char)fmt[1]) == 'a'))
4778 uniform = 1;
4780 do {
4781 if ((*fmt == 'A') || (*fmt == 'a'))
4782 break;
4783 if (*fmt == 'o') {
4784 /* consume the optional flag */
4785 fmt++;
4786 continue;
4789 if (fmt[1] == 'o') {
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
4798 token = peek_token(&val, (unsigned *)0,
4799 cfile);
4800 if (token == SEMI) {
4801 fmt++;
4802 continue;
4806 tmp = *expr;
4807 *expr = NULL;
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;
4817 *expr = tmp;
4818 tmp = NULL;
4820 if (tmp)
4821 expression_dereference (&tmp, MDL);
4823 fmt++;
4824 } while (*fmt != '\0');
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;
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;
4843 } while ((*fmt == 'A') || (*fmt == 'a'));
4845 return 1;
4848 /* option-statement :== identifier DOT identifier <syntax> SEMI
4849 | identifier <syntax> SEMI
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. */
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;
4862 const char *val;
4863 enum dhcp_token token;
4864 struct expression *expr = (struct expression *)0;
4865 int lose;
4867 token = peek_token (&val, (unsigned *)0, cfile);
4868 if ((token == SEMI) && (option->format[0] != 'Z')) {
4869 /* Eat the semicolon... */
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.
4876 skip_token(&val, (unsigned *)0, cfile);
4877 } else if (token == EQUAL) {
4878 /* Eat the equals sign. */
4879 skip_token(&val, (unsigned *)0, cfile);
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);
4891 return 0;
4893 } else {
4894 if (! parse_option_data(&expr, cfile, lookups, option))
4895 return 0;
4898 if (!parse_semi (cfile))
4899 return 0;
4900 if (!executable_statement_allocate (result, MDL))
4901 log_fatal ("no memory for option statement.");
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");
4908 if (expr)
4909 expression_dereference (&expr, MDL);
4911 return 1;
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;
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;
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);
4942 return 0;
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;
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;
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;
4969 t -> op = expr_const_data;
4970 } else {
4971 token = next_token (&val, &len, cfile);
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);
4984 return 0;
4987 break;
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;
4997 t = parse_domain_list(cfile, compress);
4999 if (!t) {
5000 if ((*fmt)[1] != 'o')
5001 skip_to_semi(cfile);
5002 return 0;
5005 break;
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;
5014 len = strlen (val);
5015 freeval = ISC_TRUE;
5016 goto make_string;
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);
5026 return 0;
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);
5037 break;
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;
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;
5056 e = find_enumeration_value (f, (*fmt) - f, &len, val);
5057 if (!e) {
5058 parse_warn (cfile, "unknown value");
5059 goto foo;
5061 if (!make_const_data (&t, &e -> value, len, 0, 1, MDL))
5062 return 0;
5063 break;
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;
5076 break;
5078 case '6': /* IPv6 address. */
5079 if (!parse_ip6_addr(cfile, &addr)) {
5080 return 0;
5082 if (!make_const_data(&t, addr.iabuf, addr.len, 0, 1, MDL)) {
5083 return 0;
5085 break;
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;
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);
5107 return 0;
5109 convert_num (cfile, buf, val, 0, 32);
5110 if (!make_const_data (&t, buf, 4, 0, 1, MDL))
5111 return 0;
5112 break;
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;
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;
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);
5144 return 0;
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;
5159 if (!make_const_data (&t, buf, 1, 0, 1, MDL))
5160 return 0;
5161 break;
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);
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;
5179 default:
5180 parse_warn (cfile, "Bad format '%c' in parse_option_token.",
5181 **fmt);
5182 skip_to_semi (cfile);
5183 return 0;
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;
5194 int parse_option_decl (oc, cfile)
5195 struct option_cache **oc;
5196 struct parse *cfile;
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;
5217 status = parse_option_name (cfile, 0, &known, &option);
5218 if (status != ISC_R_SUCCESS || option == NULL)
5219 return 0;
5221 fmt = option->format;
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
5230 fmt = option->format;
5231 break;
5234 if (*fmt == 'a') {
5235 /* 'a' is an array of the last field,
5236 * back up one format character
5238 fmt--;
5239 break;
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;
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;
5260 case 't': /* Text string... */
5261 token = peek_token (&val,
5262 &len, cfile);
5263 if (token == SEMI && fmt[1] == 'o') {
5264 fmt++;
5265 break;
5267 token = next_token (&val,
5268 &len, cfile);
5269 if (token != STRING) {
5270 parse_warn (cfile,
5271 "expecting string.");
5272 goto parse_exit;
5274 if (hunkix + len + 1 > sizeof hunkbuf) {
5275 parse_warn (cfile,
5276 "option data buffer %s",
5277 "overflow");
5278 goto parse_exit;
5280 memcpy (&hunkbuf [hunkix], val, len + 1);
5281 nul_term = 1;
5282 hunkix += len;
5283 break;
5285 case 'D':
5286 if (fmt[1] == 'c') {
5287 compress = 1;
5288 fmt++;
5289 } else
5290 compress = 0;
5292 express = parse_domain_list(cfile, compress);
5294 if (express == NULL)
5295 goto exit;
5297 if (express->op != expr_const_data) {
5298 parse_warn(cfile, "unexpected "
5299 "expression");
5300 goto parse_exit;
5303 len = express->data.const_data.len;
5304 cdp = express->data.const_data.data;
5306 if ((hunkix + len) > sizeof(hunkbuf)) {
5307 parse_warn(cfile, "option data buffer "
5308 "overflow");
5309 goto parse_exit;
5311 memcpy(&hunkbuf[hunkix], cdp, len);
5312 hunkix += len;
5314 expression_dereference(&express, MDL);
5315 break;
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;
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;
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;
5340 dp = &e -> value;
5341 goto alloc;
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;
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;
5356 alloc:
5357 if (hunkix + len > sizeof hunkbuf) {
5358 parse_warn (cfile,
5359 "option data buffer %s",
5360 "overflow");
5361 goto parse_exit;
5363 memcpy (&hunkbuf [hunkix], dp, len);
5364 hunkix += len;
5365 break;
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;
5381 convert_num (cfile, buf, val, 0, 32);
5382 len = 4;
5383 dp = buf;
5384 goto alloc;
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;
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;
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;
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;
5433 len = 1;
5434 dp = buf;
5435 goto alloc;
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;
5444 len = 0;
5445 buf[0] = '\0';
5446 break;
5448 default:
5449 log_error ("parse_option_param: Bad format %c",
5450 *fmt);
5451 goto parse_exit;
5454 token = next_token (&val, (unsigned *)0, cfile);
5455 } while (*fmt && token == COMMA);
5457 if (token != SEMI) {
5458 parse_warn (cfile, "semicolon expected.");
5459 goto parse_exit;
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);
5467 if (!option_cache_allocate (oc, MDL))
5468 log_fatal ("out of memory allocating option cache.");
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;
5478 parse_exit:
5479 if (express != NULL)
5480 expression_dereference(&express, MDL);
5481 skip_to_semi (cfile);
5482 exit:
5483 option_dereference(&option, MDL);
5485 return 0;
5488 /* Consider merging parse_cshl into this. */
5490 int parse_X (cfile, buf, max)
5491 struct parse *cfile;
5492 u_int8_t *buf;
5493 unsigned max;
5495 int token;
5496 const char *val;
5497 unsigned len;
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;
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;
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;
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;
5536 return len;
5539 int parse_warn (struct parse *cfile, const char *fmt, ...)
5541 va_list list;
5542 char lexbuf [256];
5543 char mbuf [1024];
5544 char fbuf [1024];
5545 unsigned i, lix;
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.
5551 snprintf (fbuf, sizeof fbuf, "%s line %d: %s",
5552 cfile -> tlname, cfile -> lexline, mbuf);
5554 va_start (list, fmt);
5555 vsnprintf (mbuf, sizeof mbuf, fbuf, list);
5556 va_end (list);
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] = ' ';
5568 lexbuf [lix] = 0;
5570 #ifndef DEBUG
5571 syslog (log_priority | LOG_ERR, "%s", mbuf);
5572 syslog (log_priority | LOG_ERR, "%s", cfile -> token_line);
5573 if (cfile -> lexchar < 81)
5574 syslog (log_priority | LOG_ERR, "%s^", lexbuf);
5575 #endif
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));
5588 cfile -> warnings_occurred = 1;
5590 return 0;
5593 struct expression *
5594 parse_domain_list(struct parse *cfile, int compress)
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;
5604 memset(compbuf, 0, sizeof(compbuf));
5605 memset(dnptrs, 0, sizeof(dnptrs));
5606 dnptrs[0] = compbuf;
5607 lastdnptr = &dnptrs[255];
5609 do {
5610 /* Consume the COMMA token if peeked. */
5611 if (token == COMMA)
5612 skip_token(&val, NULL, cfile);
5614 /* Get next (or first) value. */
5615 token = next_token(&val, &len, cfile);
5617 if (token != STRING) {
5618 parse_warn(cfile, "Expecting a domain string.");
5619 return NULL;
5622 /* If compression pointers are enabled, compress. If not,
5623 * just pack the names in series into the buffer.
5625 if (compress) {
5626 result = MRns_name_compress(val, compbuf + clen,
5627 sizeof(compbuf) - clen,
5628 dnptrs, lastdnptr);
5630 if (result < 0) {
5631 parse_warn(cfile, "Error compressing domain "
5632 "list: %m");
5633 return NULL;
5636 clen += result;
5637 } else {
5638 result = MRns_name_pton(val, compbuf + clen,
5639 sizeof(compbuf) - clen);
5641 /* result == 1 means the input was fully qualified.
5642 * result == 0 means the input wasn't.
5643 * result == -1 means bad things.
5645 if (result < 0) {
5646 parse_warn(cfile, "Error assembling domain "
5647 "list: %m");
5648 return NULL;
5652 * We need to figure out how many bytes to increment
5653 * our buffer pointer since pton doesn't tell us.
5655 while (compbuf[clen] != 0)
5656 clen += compbuf[clen] + 1;
5658 /* Count the last label (0). */
5659 clen++;
5662 if (clen > sizeof(compbuf))
5663 log_fatal("Impossible error at %s:%d", MDL);
5665 token = peek_token(&val, NULL, cfile);
5666 } while (token == COMMA);
5668 if (!make_const_data(&t, compbuf, clen, 1, 1, MDL))
5669 log_fatal("No memory for domain list object.");
5671 return t;