1 /* $NetBSD: parse.c,v 1.1.1.3 2014/07/12 11:57:41 spz Exp $ */
4 Common parser code for dhcpd and dhclient. */
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.
24 * Redwood City, CA 94063
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 $");
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
))
55 return (struct enumeration
*)0;
58 struct enumeration_value
*find_enumeration_value (const char *name
,
63 struct enumeration
*e
;
66 e
= find_enumeration (name
, length
);
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
87 statement foo bar { statement { } }
92 void skip_to_semi (cfile
)
95 skip_to_rbrace (cfile
, 0);
98 void skip_to_rbrace (cfile
, brace_count
)
102 enum dhcp_token token
;
105 #if defined (DEBUG_TOKEN)
106 log_error ("skip_to_rbrace: %d\n", brace_count
);
109 token
= peek_token (&val
, (unsigned *)0, cfile
);
110 if (token
== RBRACE
) {
111 skip_token(&val
, (unsigned *)0, cfile
);
117 } else if (token
== LBRACE
) {
119 } else if (token
== SEMI
&& !brace_count
) {
120 skip_token(&val
, (unsigned *)0, cfile
);
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
);
129 token
= next_token (&val
, (unsigned *)0, cfile
);
130 } while (token
!= END_OF_FILE
);
133 int parse_semi (cfile
)
136 enum dhcp_token token
;
139 token
= next_token (&val
, (unsigned *)0, cfile
);
141 parse_warn (cfile
, "semicolon expected.");
142 skip_to_semi (cfile
);
148 /* string-parameter :== STRING SEMI */
150 int parse_string (cfile
, sptr
, lptr
)
156 enum dhcp_token token
;
160 token
= next_token (&val
, &len
, cfile
);
161 if (token
!= STRING
) {
162 parse_warn (cfile
, "expecting a string");
163 skip_to_semi (cfile
);
166 s
= (char *)dmalloc (len
+ 1, MDL
);
168 log_fatal ("no memory for string %s.", val
);
169 memcpy (s
, val
, len
+ 1);
171 if (!parse_semi (cfile
)) {
185 * hostname :== IDENTIFIER
187 * | hostname DOT IDENTIFIER
190 char *parse_host_name (cfile
)
194 enum dhcp_token token
;
201 /* Read a dotted hostname... */
203 /* Read a token, which should be an identifier. */
204 token
= peek_token (&val
, (unsigned *)0, cfile
);
205 if (!is_identifier (token
) && token
!= NUMBER
)
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.");
213 c
= cons ((caddr_t
)s
, c
);
214 len
+= strlen (s
) + 1;
215 /* Look for a dot; if it's there, keep going, otherwise
217 token
= peek_token (&val
, (unsigned *)0, cfile
);
219 token
= next_token (&val
, (unsigned *)0, cfile
);
223 } while (token
== DOT
);
225 /* Should be at least one token. */
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.");
238 unsigned l
= strlen ((char *)(c
-> car
));
240 memcpy (t
, (char *)(c
-> car
), l
);
241 /* Free up temp space. */
242 dfree (c
-> car
, MDL
);
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
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
;
268 enum dhcp_token token
;
269 unsigned char addr
[4];
270 unsigned len
= sizeof addr
;
272 struct expression
*x
= (struct expression
*)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
)
290 restore_parse_state(cfile
);
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
);
302 if (!make_host_lookup (expr
, name
)) {
308 if (!make_limit (&x
, *expr
, 4))
310 expression_dereference (expr
, MDL
);
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",
319 skip_to_semi (cfile
);
327 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
330 int parse_ip_addr (cfile
, addr
)
335 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
336 &addr
-> len
, DOT
, 10, 8))
342 * Return true if every character in the string is hexadecimal.
345 is_hex_string(const char *s
) {
347 if (!isxdigit((int)*s
)) {
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()
366 parse_ip6_addr(struct parse
*cfile
, struct iaddr
*addr
) {
367 enum dhcp_token token
;
371 char v6
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
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
);
385 if ((((token
== NAME
) || (token
== NUMBER_OR_NAME
)) &&
386 is_hex_string(val
)) ||
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.");
398 memcpy(v6
+v6_len
, val
, val_len
);
404 token
= peek_raw_token(&val
, NULL
, cfile
);
409 * Use inet_pton() for actual work.
411 if (inet_pton(AF_INET6
, v6
, addr
->iabuf
) <= 0) {
412 parse_warn(cfile
, "Invalid IPv6 address.");
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
) {
429 if (!parse_ip6_addr(cfile
, &addr
)) {
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
;
444 if (!parse_ip6_addr(cfile
, addr
)) {
447 token
= next_token(&val
, NULL
, cfile
);
448 if (token
!= SLASH
) {
449 parse_warn(cfile
, "Slash expected.");
454 token
= next_token(&val
, NULL
, cfile
);
455 if (token
!= NUMBER
) {
456 parse_warn(cfile
, "Number expected.");
462 if ((n
< 0) || (n
> 128)) {
463 parse_warn(cfile
, "Invalid IPv6 prefix length.");
467 if (!is_cidr_mask_valid(addr
, n
)) {
468 parse_warn(cfile
, "network mask too short.");
477 * ip-address-with-subnet :== ip-address |
478 * ip-address "/" NUMBER
482 parse_ip_addr_with_subnet(cfile
, match
)
484 struct iaddrmatch
*match
;
486 const char *val
, *orig
;
487 enum dhcp_token token
;
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.");
508 prefixlen
= atoi(val
);
511 prefixlen
> (match
->addr
.len
* 8)) {
512 parse_warn(cfile
, "subnet prefix is out of "
514 match
->addr
.len
* 8);
519 /* construct a suitable mask field */
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
);
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
);
541 newval
= match
->addr
.iabuf
[fflen
] &
542 match
->mask
.iabuf
[fflen
];
544 if (newval
!= match
->addr
.iabuf
[fflen
]) {
546 match
->addr
.iabuf
[fflen
] = newval
;
548 } while (++fflen
< match
->mask
.len
);
551 log_error("Warning: Extraneous bits removed "
552 "in address component of %s/%d.",
554 log_error("New value: %s/%d.",
555 piaddr(match
->addr
), prefixlen
);
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
)
577 struct hardware
*hardware
;
580 enum dhcp_token token
;
584 token
= next_token(&val
, NULL
, cfile
);
587 hardware
->hbuf
[0] = HTYPE_ETHER
;
590 hardware
->hbuf
[0] = HTYPE_IEEE802
;
593 hardware
->hbuf
[0] = HTYPE_FDDI
;
595 case TOKEN_INFINIBAND
:
596 hardware
->hbuf
[0] = HTYPE_INFINIBAND
;
599 if (!strncmp(val
, "unknown-", 8)) {
600 hardware
->hbuf
[0] = atoi(&val
[8]);
603 "expecting a network hardware type");
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
618 token
= peek_token(&val
, NULL
, cfile
);
623 t
= parse_numeric_aggregate(cfile
, NULL
, &hlen
, COLON
, 16, 8);
628 if (hlen
+ 1 > sizeof(hardware
->hbuf
)) {
630 parse_warn(cfile
, "hardware address too long");
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);
641 token
= next_token(&val
, NULL
, cfile
);
643 parse_warn(cfile
, "expecting semicolon.");
648 /* lease-time :== NUMBER SEMI */
650 void parse_lease_time (cfile
, timep
)
655 enum dhcp_token token
;
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
);
664 convert_num(cfile
, (unsigned char *)&num
, val
, 10, 32);
665 /* Unswap the number - convert_num returns stuff in NBO. */
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
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
)
704 enum dhcp_token token
;
705 unsigned char *bufp
= buf
, *s
, *t
;
710 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
712 log_fatal ("no space for numeric aggregate");
718 token
= peek_token (&val
, (unsigned *)0, cfile
);
719 if (token
!= separator
) {
722 if (token
!= RBRACE
&& token
!= LBRACE
)
723 token
= next_token (&val
,
726 parse_warn (cfile
, "too few numbers.");
728 skip_to_semi (cfile
);
729 /* free bufp if it was allocated */
730 if ((bufp
!= NULL
) && (bufp
!= buf
))
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");
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
))
751 /* free any linked numbers we may have allocated */
760 /* If we can, convert the number now; otherwise, build
761 a linked list of all the numbers. */
763 convert_num (cfile
, s
, val
, base
, size
);
766 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
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. */
777 * No need to cleanup bufp, to get here we didn't allocate
780 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
782 log_fatal ("no space for numeric aggregate.");
783 s
= bufp
+ count
- size
/ 8;
788 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
790 /* Free up temp space. */
791 dfree (c
-> car
, MDL
);
798 void convert_num (cfile
, buf
, str
, base
, size
)
805 const unsigned char *ptr
= (const unsigned char *)str
;
816 /* If base wasn't specified, figure it out from the data. */
818 if (ptr
[0] == '0') {
819 if (ptr
[1] == 'x') {
822 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
835 /* XXX assumes ASCII... */
837 tval
= tval
- 'a' + 10;
838 else if (tval
>= 'A')
839 tval
= tval
- 'A' + 10;
840 else if (tval
>= '0')
843 parse_warn (cfile
, "Bogus number: %s.", str
);
848 "Bogus number %s: digit %d not in base %d",
852 val
= val
* base
+ tval
;
856 max
= (1 << (size
- 1));
858 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
863 "%s%lo exceeds max (%d) for precision.",
865 (unsigned long)val
, max
);
869 "%s%lx exceeds max (%d) for precision.",
871 (unsigned long)val
, max
);
875 "%s%lu exceeds max (%d) for precision.",
877 (unsigned long)val
, max
);
885 *buf
= -(unsigned long)val
;
888 putShort (buf
, -(long)val
);
891 putLong (buf
, -(long)val
);
895 "Unexpected integer size: %d\n", size
);
901 *buf
= (u_int8_t
)val
;
904 putUShort (buf
, (u_int16_t
)val
);
911 "Unexpected integer size: %d\n", size
);
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 |
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
932 * just parse the date
933 * any trailing semi must be consumed by the caller of this routine
936 parse_date_core(cfile
)
940 int tzoff
, year
, mon
, mday
, hour
, min
, sec
;
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 */
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
) {
960 skip_token(&val
, NULL
, cfile
);
961 parse_warn(cfile
, "Seconds since epoch expected.");
965 skip_token(&val
, NULL
, cfile
); /* consume number */
971 if (token
!= NUMBER
) {
973 skip_token(&val
, NULL
, cfile
);
974 parse_warn(cfile
, "numeric day of week expected.");
977 skip_token(&val
, NULL
, cfile
); /* consume day of week */
978 /* we are not using this for anything */
981 token
= peek_token(&val
, NULL
, cfile
);
982 if (token
!= NUMBER
) {
984 skip_token(&val
, NULL
, cfile
);
985 parse_warn(cfile
, "numeric year expected.");
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. */
998 /* Slash separating year from month... */
999 token
= peek_token(&val
, NULL
, cfile
);
1000 if (token
!= SLASH
) {
1002 skip_token(&val
, NULL
, cfile
);
1004 "expected slash separating year from month.");
1007 skip_token(&val
, NULL
, cfile
); /* consume SLASH */
1010 token
= peek_token(&val
, NULL
, cfile
);
1011 if (token
!= NUMBER
) {
1013 skip_token(&val
, NULL
, cfile
);
1014 parse_warn(cfile
, "numeric month expected.");
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
) {
1024 skip_token(&val
, NULL
, cfile
);
1026 "expected slash separating month from day.");
1029 skip_token(&val
, NULL
, cfile
); /* consume SLASH */
1031 /* Day of month... */
1032 token
= peek_token(&val
, NULL
, cfile
);
1033 if (token
!= NUMBER
) {
1035 skip_token(&val
, NULL
, cfile
);
1036 parse_warn(cfile
, "numeric day of month expected.");
1039 skip_token(&val
, NULL
, cfile
); /* consume day of month */
1043 token
= peek_token(&val
, NULL
, cfile
);
1044 if (token
!= NUMBER
) {
1046 skip_token(&val
, NULL
, cfile
);
1047 parse_warn(cfile
, "numeric hour expected.");
1050 skip_token(&val
, NULL
, cfile
); /* consume hour */
1053 /* Colon separating hour from minute... */
1054 token
= peek_token(&val
, NULL
, cfile
);
1055 if (token
!= COLON
) {
1057 skip_token(&val
, NULL
, cfile
);
1059 "expected colon separating hour from minute.");
1062 skip_token(&val
, NULL
, cfile
); /* consume colon */
1065 token
= peek_token(&val
, NULL
, cfile
);
1066 if (token
!= NUMBER
) {
1068 skip_token(&val
, NULL
, cfile
);
1069 parse_warn(cfile
, "numeric minute expected.");
1072 skip_token(&val
, NULL
, cfile
); /* consume minute */
1075 /* Colon separating minute from second... */
1076 token
= peek_token(&val
, NULL
, cfile
);
1077 if (token
!= COLON
) {
1079 skip_token(&val
, NULL
, cfile
);
1081 "expected colon separating minute from second.");
1084 skip_token(&val
, NULL
, cfile
); /* consume colon */
1087 token
= peek_token(&val
, NULL
, cfile
);
1088 if (token
!= NUMBER
) {
1090 skip_token(&val
, NULL
, cfile
);
1091 parse_warn(cfile
, "numeric second expected.");
1094 skip_token(&val
, NULL
, cfile
); /* consume second */
1098 token
= peek_token(&val
, NULL
, cfile
);
1099 if (token
== NUMBER
) {
1100 skip_token(&val
, NULL
, cfile
); /* consume tzoff */
1102 } else if (token
!= SEMI
) {
1103 skip_token(&val
, NULL
, cfile
);
1105 "Time zone offset or semicolon expected.");
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 */
1115 (mon
> 1 && /* Leap day this year */
1116 !((year
- 72) & 3)) +
1117 mday
- 1) * 24) + /* Day of month */
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
1130 return((TIME
)guess
);
1134 * Wrapper to consume the semicolon after the date
1140 struct parse
*cfile
;
1143 guess
= parse_date_core(cfile
);
1145 /* Make sure the date ends in a semicolon... */
1146 if (!parse_semi(cfile
))
1154 * option-name :== IDENTIFIER |
1155 IDENTIFIER . IDENTIFIER
1159 parse_option_name (cfile
, allocate
, known
, opt
)
1160 struct parse
*cfile
;
1163 struct option
**opt
;
1166 enum dhcp_token token
;
1168 struct universe
*universe
;
1169 struct option
*option
;
1173 return DHCP_R_INVALIDARG
;
1175 token
= next_token (&val
, (unsigned *)0, cfile
);
1176 if (!is_identifier (token
)) {
1178 "expecting identifier after option keyword.");
1180 skip_to_semi (cfile
);
1181 return DHCP_R_BADPARSE
;
1183 uname
= dmalloc (strlen (val
) + 1, MDL
);
1185 log_fatal ("no memory for uname information.");
1186 strcpy (uname
, val
);
1187 token
= peek_token (&val
, (unsigned *)0, cfile
);
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 '.'");
1197 skip_to_semi (cfile
);
1198 return DHCP_R_BADPARSE
;
1201 /* Look up the option name hash table for the specified
1203 universe
= (struct universe
*)0;
1204 if (!universe_hash_lookup (&universe
, universe_hash
,
1206 parse_warn (cfile
, "no option space named %s.", uname
);
1207 skip_to_semi (cfile
);
1208 return ISC_R_NOTFOUND
;
1211 /* Use the default hash table, which contains all the
1212 standard dhcp option names. */
1214 universe
= &dhcp_universe
;
1217 /* Look up the actual option info... */
1218 option_name_hash_lookup(opt
, universe
->name_hash
, val
, 0, MDL
);
1221 /* If we didn't get an option structure, it's an undefined option. */
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
1231 } else if (strncasecmp(val
, "unknown-", 8) == 0) {
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
,
1241 skip_to_semi(cfile
);
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.
1253 option_code_hash_lookup(opt
, universe
->code_hash
,
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
);
1270 log_info("option %s has been redefined as option %s. "
1271 "Please update your configs if neccessary.",
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
1278 } else if (allocate
) {
1279 option
= new_option(val
, MDL
);
1280 option
-> universe
= universe
;
1281 option_reference(opt
, option
, MDL
);
1283 parse_warn(cfile
, "no option named %s in space %s",
1284 val
, universe
->name
);
1285 skip_to_semi (cfile
);
1287 return ISC_R_NOTFOUND
;
1290 /* Free the initial identifier token. */
1292 return ISC_R_SUCCESS
;
1295 /* IDENTIFIER [WIDTHS] SEMI
1296 * WIDTHS ~= LENGTH WIDTH NUMBER
1300 void parse_option_space_decl (cfile
)
1301 struct parse
*cfile
;
1305 struct universe
**ua
, *nu
;
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
1312 token
= next_token (&val
, (unsigned *)0, cfile
);
1313 if (!is_identifier (token
)) {
1314 parse_warn (cfile
, "expecting identifier.");
1315 skip_to_semi (cfile
);
1318 nu
= new_universe (MDL
);
1320 log_fatal ("No memory for new option space.");
1322 /* Set up the server option universe... */
1323 nu_name
= dmalloc (strlen (val
) + 1, MDL
);
1325 log_fatal ("No memory for new option space name.");
1326 strcpy (nu_name
, val
);
1327 nu
-> name
= nu_name
;
1330 token
= next_token(&val
, NULL
, cfile
);
1336 token
= next_token(&val
, NULL
, cfile
);
1337 if (token
!= WIDTH
) {
1338 parse_warn(cfile
, "expecting width token.");
1342 token
= next_token(&val
, NULL
, cfile
);
1343 if (token
!= NUMBER
) {
1344 parse_warn(cfile
, "expecting number 1, 2, 4.");
1354 hsize
= BYTE_NAME_HASH_SIZE
;
1358 hsize
= WORD_NAME_HASH_SIZE
;
1362 hsize
= QUAD_NAME_HASH_SIZE
;
1365 parse_warn(cfile
, "invalid code width (%d), "
1366 "expecting a 1, 2 or 4.",
1373 token
= next_token(&val
, NULL
, cfile
);
1374 if (token
!= WIDTH
) {
1375 parse_warn(cfile
, "expecting width token.");
1379 token
= next_token(&val
, NULL
, cfile
);
1380 if (token
!= NUMBER
) {
1381 parse_warn(cfile
, "expecting number 1 or 2.");
1386 if (lsize
!= 1 && lsize
!= 2) {
1387 parse_warn(cfile
, "invalid length width (%d) "
1388 "expecting 1 or 2.", lsize
);
1395 token
= next_token(&val
, NULL
, cfile
);
1396 if (token
!= SIZE
) {
1397 parse_warn(cfile
, "expecting size token.");
1401 token
= next_token(&val
, NULL
, cfile
);
1402 if (token
!= NUMBER
) {
1403 parse_warn(cfile
, "expecting a 10base number");
1407 /* (2^31)-1 is the highest Mersenne prime we should
1411 if (hsize
< 0 || hsize
> 0x7FFFFFFF) {
1412 parse_warn(cfile
, "invalid hash length: %d",
1420 parse_warn(cfile
, "Unexpected token.");
1422 } while (token
!= SEMI
);
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
;
1438 nu
->get_tag
= getUChar
;
1439 nu
->store_tag
= putUChar
;
1442 nu
->get_tag
= getUShort
;
1443 nu
->store_tag
= putUShort
;
1446 nu
->get_tag
= getULong
;
1447 nu
->store_tag
= putULong
;
1450 log_fatal("Impossible condition at %s:%d.", MDL
);
1454 nu
->get_length
= NULL
;
1455 nu
->store_length
= NULL
;
1458 nu
->get_length
= getUChar
;
1459 nu
->store_length
= putUChar
;
1462 nu
->get_length
= getUShort
;
1463 nu
->store_length
= putUShort
;
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
);
1472 log_fatal ("No memory to expand option space array.");
1473 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
1475 dfree (universes
, MDL
);
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
);
1486 dfree(nu_name
, 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 |
1516 SIGNED INTEGER NUMBER |
1517 UNSIGNED INTEGER NUMBER |
1521 ENCAPSULATE identifier */
1523 int parse_option_code_definition (cfile
, option
)
1524 struct parse
*cfile
;
1525 struct option
*option
;
1528 enum dhcp_token token
;
1529 struct option
*oldopt
;
1530 unsigned arrayp
= 0;
1532 int no_more_in_record
= 0;
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
);
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
);
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
);
1562 parse_warn (cfile
, "expecting \"of\".");
1563 skip_to_semi (cfile
);
1567 token
= next_token (&val
, (unsigned *)0, cfile
);
1570 if (token
== LBRACE
) {
1572 token
= next_token (&val
, (unsigned *)0, cfile
);
1575 /* At this point we're expecting a data type. */
1577 if (has_encapsulation
) {
1579 "encapsulate must always be the last item.");
1580 skip_to_semi (cfile
);
1587 parse_warn (cfile
, "no nested arrays.");
1588 skip_to_rbrace (cfile
, recordp
);
1590 skip_to_semi (cfile
);
1593 token
= next_token (&val
, (unsigned *)0, cfile
);
1595 parse_warn (cfile
, "expecting \"of\".");
1596 skip_to_semi (cfile
);
1599 arrayp
= recordp
+ 1;
1600 token
= next_token (&val
, (unsigned *)0, cfile
);
1601 if ((recordp
) && (token
== LBRACE
)) {
1603 "only uniform array inside record.");
1604 skip_to_rbrace (cfile
, recordp
+ 1);
1605 skip_to_semi (cfile
);
1615 token
= next_token (&val
, (unsigned *)0, cfile
);
1616 if (token
!= NUMBER
) {
1617 parse_warn (cfile
, "expecting number.");
1618 skip_to_rbrace (cfile
, recordp
);
1620 skip_to_semi (cfile
);
1623 switch (atoi (val
)) {
1625 type
= is_signed
? 'b' : 'B';
1628 type
= is_signed
? 's' : 'S';
1631 type
= is_signed
? 'l' : 'L';
1635 "%s bit precision is not supported.", val
);
1636 skip_to_rbrace (cfile
, recordp
);
1638 skip_to_semi (cfile
);
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
);
1650 skip_to_semi (cfile
);
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';
1681 parse_warn (cfile
, "arrays of text strings not %s",
1683 skip_to_rbrace (cfile
, recordp
);
1685 skip_to_semi (cfile
);
1688 no_more_in_record
= 1;
1695 token
= next_token (&val
, (unsigned *)0, cfile
);
1696 if (!is_identifier (token
)) {
1698 "expecting option space identifier");
1699 skip_to_semi (cfile
);
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
);
1709 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1711 tokbuf
[tokix
++] = 'E';
1712 strcpy (&tokbuf
[tokix
], val
);
1713 tokix
+= strlen (val
);
1715 has_encapsulation
= 1;
1721 parse_warn (cfile
, "array incompatible with zerolen.");
1722 skip_to_rbrace (cfile
, recordp
);
1724 skip_to_semi (cfile
);
1727 no_more_in_record
= 1;
1731 parse_warn (cfile
, "unknown data type %s", val
);
1732 skip_to_rbrace (cfile
, recordp
);
1734 skip_to_semi (cfile
);
1738 if (tokix
== sizeof tokbuf
) {
1740 parse_warn (cfile
, "too many types in record.");
1741 skip_to_rbrace (cfile
, recordp
);
1743 skip_to_semi (cfile
);
1746 tokbuf
[tokix
++] = type
;
1749 token
= next_token (&val
, (unsigned *)0, cfile
);
1750 if (arrayp
> recordp
) {
1751 if (tokix
== sizeof tokbuf
) {
1753 "too many types in record.");
1754 skip_to_rbrace (cfile
, 1);
1755 skip_to_semi (cfile
);
1759 tokbuf
[tokix
++] = 'a';
1761 if (token
== COMMA
) {
1762 if (no_more_in_record
) {
1764 "%s must be at end of record.",
1765 type
== 't' ? "text" : "string");
1766 skip_to_rbrace (cfile
, 1);
1768 skip_to_semi (cfile
);
1771 token
= next_token (&val
, (unsigned *)0, cfile
);
1774 if (token
!= RBRACE
) {
1775 parse_warn (cfile
, "expecting right brace.");
1776 skip_to_rbrace (cfile
, 1);
1778 skip_to_semi (cfile
);
1782 if (!parse_semi (cfile
)) {
1783 parse_warn (cfile
, "semicolon expected.");
1784 skip_to_semi (cfile
);
1786 skip_to_semi (cfile
);
1789 if (has_encapsulation
&& arrayp
) {
1791 "Arrays of encapsulations don't make sense.");
1794 s
= dmalloc(tokix
+ (arrayp
? 1 : 0) + 1, MDL
);
1796 log_fatal("no memory for option format.");
1798 memcpy(s
, tokbuf
, tokix
);
1800 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1804 option
-> format
= s
;
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
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,
1828 option_name_hash_add(option
->universe
->name_hash
, option
->name
, 0,
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)",
1844 * base64 :== NUMBER_OR_STRING
1847 int parse_base64 (data
, cfile
)
1848 struct data_string
*data
;
1849 struct parse
*cfile
;
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
,
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. */
1880 (void)next_token(&val
, &l
, cfile
);
1881 t
= dmalloc(l
+ sizeof(*t
), MDL
);
1883 log_fatal("no memory for base64 buffer.");
1884 memset(t
, 0, (sizeof(*t
)) - 1);
1885 memcpy(t
->string
, val
, l
+ 1);
1892 (void)peek_token(&val
, NULL
, cfile
);
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
] != '='))) {
1901 break; /* no need to continue for loop */
1904 } while (valid_base64
);
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.");
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
!= '=') {
1921 "stuff after base64 '=' terminator: %s.",
1925 if ((foo
< ' ') || (foo
> 'z')) {
1928 "invalid base64 character %d.",
1931 data_string_forget(data
, MDL
);
1937 foo
= from64
[foo
- ' '];
1940 acc
= (acc
<< 6) + foo
;
1945 data
->buffer
->data
[j
++] = (acc
>> 4);
1950 data
->buffer
->data
[j
++] = (acc
>> 2);
1954 data
->buffer
->data
[j
++] = acc
;
1965 "partial base64 value left over: %d.",
1970 data
->data
= data
->buffer
->data
;
1972 for (t
= bufs
; t
; t
= last
) {
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];
1995 struct option_tag
*sl
= (struct option_tag
*)0;
1996 struct option_tag
*next
, **last
= &sl
;
1997 enum dhcp_token token
;
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
) {
2012 if (ilen
== sizeof ibuf
) {
2013 next
= (struct option_tag
*)
2015 sizeof (struct option_tag
), MDL
);
2017 log_fatal ("no memory for string list.");
2018 memcpy (next
-> data
, ibuf
, ilen
);
2020 last
= &next
-> next
;
2024 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
2026 token
= peek_token (&val
, (unsigned *)0, cfile
);
2029 skip_token(&val
, (unsigned *)0, cfile
);
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];
2041 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
2047 memcpy (rvp
, ibuf
, ilen
);
2052 * executable-statements :== executable-statement executable-statements |
2053 * executable-statement
2055 * executable-statement :==
2057 * ADD class-name 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
;
2069 enum expression_context case_context
;
2071 struct executable_statement
**next
;
2074 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
2075 next
= &((*next
) -> next
);
2081 int parse_executable_statement (result
, cfile
, lose
, case_context
)
2082 struct executable_statement
**result
;
2083 struct parse
*cfile
;
2085 enum expression_context case_context
;
2087 #if defined(ENABLE_EXECUTE)
2089 struct expression
**ep
;
2091 enum dhcp_token token
;
2094 struct option
*option
=NULL
;
2095 struct option_cache
*cache
;
2099 struct dns_zone
*zone
;
2100 isc_result_t status
;
2103 token
= peek_token (&val
, (unsigned *)0, cfile
);
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
;
2113 parse_warn(cfile
, "Expecting 'local' or 'default'.");
2115 skip_to_semi(cfile
);
2120 token
= next_token(&val
, NULL
, cfile
);
2121 if (token
!= SEMI
) {
2122 parse_warn(cfile
, "Expecting a semicolon.");
2127 /* We're done here. */
2131 skip_token(&val
, (unsigned *)0, cfile
);
2132 return parse_if_statement (result
, cfile
, lose
);
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
);
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
);
2152 if (!parse_semi (cfile
)) {
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
;
2163 skip_token(&val
, (unsigned *)0, cfile
);
2164 if (!parse_semi (cfile
)) {
2168 if (!executable_statement_allocate (result
, MDL
))
2169 log_fatal ("no memory for new statement.");
2170 (*result
) -> op
= break_statement
;
2174 skip_token(&val
, (unsigned *)0, cfile
);
2176 status
= parse_option_name (cfile
, 0, &known
, &option
);
2177 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2181 status
= parse_option_statement(result
, cfile
, 1, option
,
2182 send_option_statement
);
2183 option_dereference(&option
, MDL
);
2188 skip_token(&val
, (unsigned *)0, cfile
);
2190 status
= parse_option_name (cfile
, 0, &known
, &option
);
2191 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2195 status
= parse_option_statement(result
, cfile
, 1, option
,
2196 supersede_option_statement
);
2197 option_dereference(&option
, MDL
);
2209 skip_token(&val
, (unsigned *)0, cfile
);
2210 cache
= (struct option_cache
*)0;
2211 if (!parse_allow_deny (&cache
, cfile
, flag
))
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
;
2220 skip_token(&val
, (unsigned *)0, cfile
);
2221 token
= peek_token (&val
, (unsigned *)0, cfile
);
2223 goto switch_default
;
2225 status
= parse_option_name (cfile
, 0, &known
, &option
);
2226 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2230 status
= parse_option_statement(result
, cfile
, 1, option
,
2231 default_option_statement
);
2232 option_dereference(&option
, MDL
);
2236 skip_token(&val
, (unsigned *)0, cfile
);
2238 status
= parse_option_name (cfile
, 0, &known
, &option
);
2239 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2243 status
= parse_option_statement(result
, cfile
, 1, option
,
2244 prepend_option_statement
);
2245 option_dereference(&option
, MDL
);
2249 skip_token(&val
, (unsigned *)0, cfile
);
2251 status
= parse_option_name (cfile
, 0, &known
, &option
);
2252 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2256 status
= parse_option_statement(result
, cfile
, 1, option
,
2257 append_option_statement
);
2258 option_dereference(&option
, MDL
);
2262 skip_token(&val
, (unsigned *)0, cfile
);
2263 return parse_on_statement (result
, cfile
, lose
);
2266 skip_token(&val
, (unsigned *)0, cfile
);
2267 return parse_switch_statement (result
, cfile
, lose
);
2270 skip_token(&val
, (unsigned *)0, cfile
);
2271 if (case_context
== context_any
) {
2273 "case statement in inappropriate scope.");
2275 skip_to_semi (cfile
);
2278 return parse_case_statement (result
,
2279 cfile
, lose
, case_context
);
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.");
2290 if (!executable_statement_allocate (result
, MDL
))
2291 log_fatal ("no memory for default statement.");
2292 (*result
) -> op
= default_statement
;
2298 skip_token(&val
, (unsigned *)0, cfile
);
2299 if (token
== DEFINE
)
2304 token
= next_token (&val
, (unsigned *)0, cfile
);
2305 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2307 "%s can't be a variable name", val
);
2309 skip_to_semi (cfile
);
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;
2328 token
= next_token (&val
,
2329 (unsigned *)0, cfile
);
2330 if (token
== RPAREN
)
2332 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2334 "expecting argument name");
2335 skip_to_rbrace (cfile
, 0);
2337 executable_statement_dereference
2341 new = ((struct string_list
*)
2342 dmalloc (sizeof (struct string_list
) +
2343 strlen (val
), MDL
));
2345 log_fatal ("can't allocate string.");
2346 memset (new, 0, sizeof *new);
2347 strcpy (new -> string
, val
);
2354 token
= next_token (&val
,
2355 (unsigned *)0, cfile
);
2356 } while (token
== COMMA
);
2358 if (token
!= RPAREN
) {
2359 parse_warn (cfile
, "expecting right paren.");
2361 skip_to_semi (cfile
);
2363 executable_statement_dereference (result
, MDL
);
2367 token
= next_token (&val
, (unsigned *)0, cfile
);
2368 if (token
!= LBRACE
) {
2369 parse_warn (cfile
, "expecting left brace.");
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
,
2389 token
= next_token (&val
, (unsigned *)0, cfile
);
2390 if (token
!= RBRACE
) {
2391 parse_warn (cfile
, "expecting rigt brace.");
2395 if (token
!= EQUAL
) {
2397 "expecting '=' in %s statement.",
2398 flag
? "define" : "set");
2402 if (!parse_expression (&(*result
) -> data
.set
.expr
,
2403 cfile
, lose
, context_any
,
2404 (struct expression
**)0,
2408 "expecting expression.");
2411 skip_to_semi (cfile
);
2412 executable_statement_dereference (result
, MDL
);
2415 if (!parse_semi (cfile
)) {
2417 executable_statement_dereference (result
, MDL
);
2424 skip_token(&val
, (unsigned *)0, cfile
);
2425 token
= next_token (&val
, (unsigned *)0, cfile
);
2426 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2428 "%s can't be a variable name", val
);
2429 skip_to_semi (cfile
);
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
)) {
2443 executable_statement_dereference (result
, MDL
);
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
)) {
2459 "expecting data expression.");
2462 skip_to_semi (cfile
);
2463 executable_statement_dereference (result
, MDL
);
2466 if (!parse_semi (cfile
)) {
2468 executable_statement_dereference (result
, MDL
);
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
);
2488 token
= next_token(&val
, &len
, cfile
);
2489 if (token
!= STRING
) {
2490 parse_warn(cfile
, "Expecting a quoted string.");
2491 skip_to_semi(cfile
);
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
,
2512 "expecting expression.");
2515 skip_to_semi(cfile
);
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
);
2530 if (!parse_semi (cfile
)) {
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
);
2540 #endif /* ENABLE_EXECUTE */
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
)) {
2555 "expecting data expression.");
2558 skip_to_semi (cfile
);
2559 executable_statement_dereference (result
, MDL
);
2562 if (!parse_semi (cfile
)) {
2564 executable_statement_dereference (result
, MDL
);
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
);
2584 token
= peek_token (&val
, (unsigned *)0, cfile
);
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
;
2595 (*result
) -> data
.log
.priority
= log_priority_debug
;
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
);
2609 if (!(parse_data_expression
2610 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
2611 skip_to_semi (cfile
);
2616 token
= next_token (&val
, (unsigned *)0, cfile
);
2617 if (token
!= RPAREN
) {
2618 parse_warn (cfile
, "right parenthesis expected.");
2619 skip_to_semi (cfile
);
2624 token
= next_token (&val
, (unsigned *)0, cfile
);
2625 if (token
!= SEMI
) {
2626 parse_warn (cfile
, "semicolon expected.");
2627 skip_to_semi (cfile
);
2633 /* Not really a statement, but we parse it here anyway
2634 because it's appropriate for all DHCP agents with
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.");
2646 skip_to_semi (cfile
);
2647 dns_zone_dereference (&zone
, MDL
);
2650 i
= strlen (zone
-> name
);
2651 if (zone
-> name
[i
- 1] != '.') {
2652 s
= dmalloc ((unsigned)i
+ 2, MDL
);
2654 parse_warn (cfile
, "no trailing '.' on zone");
2657 strcpy (s
, zone
-> name
);
2660 dfree (zone
-> name
, MDL
);
2663 if (!parse_zone (zone
, cfile
))
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
);
2672 dns_zone_dereference (&zone
, MDL
);
2675 /* Also not really a statement, but same idea as above. */
2677 skip_token(&val
, (unsigned *)0, cfile
);
2678 if (!parse_key (cfile
)) {
2685 if (config_universe
&& is_identifier (token
)) {
2686 option
= (struct option
*)0;
2687 option_name_hash_lookup(&option
,
2688 config_universe
->name_hash
,
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
);
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,
2712 parse_warn (cfile
, "expecting "
2716 skip_to_semi (cfile
);
2717 executable_statement_dereference (result
, MDL
);
2720 if (!parse_semi (cfile
)) {
2722 executable_statement_dereference (result
, MDL
);
2735 /* zone-statements :== zone-statement |
2736 zone-statement zone-statements
2738 PRIMARY ip-addresses SEMI |
2739 SECONDARY ip-addresses SEMI |
2740 PRIMARY6 ip-address6 SEMI |
2741 SECONDARY6 ip-address6 SEMI |
2743 ip-addresses :== ip-addr-or-hostname |
2744 ip-addr-or-hostname COMMA ip-addresses
2745 key-reference :== KEY STRING |
2748 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2753 struct option_cache
*oc
;
2756 token
= next_token (&val
, (unsigned *)0, cfile
);
2757 if (token
!= LBRACE
) {
2758 parse_warn (cfile
, "expecting left brace");
2763 token
= peek_token (&val
, (unsigned *)0, cfile
);
2766 if (zone
-> primary
) {
2768 "more than one primary.");
2769 skip_to_semi (cfile
);
2772 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2773 log_fatal ("can't allocate primary option cache.");
2774 oc
= zone
-> primary
;
2778 if (zone
-> secondary
) {
2779 parse_warn (cfile
, "more than one secondary.");
2780 skip_to_semi (cfile
);
2783 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2784 log_fatal ("can't allocate secondary.");
2785 oc
= zone
-> secondary
;
2787 skip_token(&val
, (unsigned *)0, cfile
);
2789 struct expression
*expr
= (struct expression
*)0;
2790 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2792 "expecting IP addr or hostname.");
2793 skip_to_semi (cfile
);
2796 if (oc
-> expression
) {
2797 struct expression
*old
=
2798 (struct expression
*)0;
2799 expression_reference (&old
,
2802 expression_dereference (&oc
-> expression
,
2804 if (!make_concat (&oc
-> expression
,
2806 log_fatal ("no memory for concat.");
2807 expression_dereference (&expr
, MDL
);
2808 expression_dereference (&old
, MDL
);
2810 expression_reference (&oc
-> expression
,
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
);
2824 if (zone
->primary6
) {
2825 parse_warn(cfile
, "more than one primary6.");
2826 skip_to_semi(cfile
);
2829 if (!option_cache_allocate (&zone
->primary6
, MDL
))
2830 log_fatal("can't allocate primary6 option cache.");
2831 oc
= zone
->primary6
;
2835 if (zone
->secondary6
) {
2836 parse_warn(cfile
, "more than one secondary6.");
2837 skip_to_semi(cfile
);
2840 if (!option_cache_allocate (&zone
->secondary6
, MDL
))
2841 log_fatal("can't allocate secondary6 "
2843 oc
= zone
->secondary6
;
2845 skip_token(&val
, NULL
, cfile
);
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
);
2853 if (oc
->expression
) {
2854 struct expression
*old
= NULL
;
2855 expression_reference(&old
, oc
->expression
,
2857 expression_dereference(&oc
->expression
,
2859 if (!make_concat(&oc
->expression
,
2861 log_fatal("no memory for concat.");
2862 expression_dereference(&expr
, MDL
);
2863 expression_dereference(&old
, MDL
);
2865 expression_reference(&oc
->expression
,
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
);
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;
2885 key_name
= parse_host_name (cfile
);
2887 parse_warn (cfile
, "expecting key name.");
2888 skip_to_semi (cfile
);
2893 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2895 parse_warn (cfile
, "unknown key %s", val
);
2897 dfree (key_name
, MDL
);
2898 if (!parse_semi (cfile
))
2908 token
= next_token (&val
, (unsigned *)0, cfile
);
2909 if (token
!= RBRACE
) {
2910 parse_warn (cfile
, "expecting right brace.");
2916 /* key-statements :== key-statement |
2917 key-statement key-statements
2919 ALGORITHM host-name SEMI |
2920 secret-definition SEMI
2921 secret-definition :== SECRET base64val |
2924 int parse_key (struct parse
*cfile
)
2929 struct auth_key
*key
;
2930 struct data_string ds
;
2931 isc_result_t status
;
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
);
2943 log_fatal ("no memory for key name.");
2944 strcpy (key
-> name
, val
);
2947 key
-> name
= parse_host_name (cfile
);
2949 parse_warn (cfile
, "expecting key name.");
2950 skip_to_semi (cfile
);
2955 token
= next_token (&val
, (unsigned *)0, cfile
);
2956 if (token
!= LBRACE
) {
2957 parse_warn (cfile
, "expecting left brace");
2962 token
= next_token (&val
, (unsigned *)0, cfile
);
2965 if (key
-> algorithm
) {
2967 "key %s: too many algorithms",
2971 key
-> algorithm
= parse_host_name (cfile
);
2972 if (!key
-> algorithm
) {
2974 "expecting key algorithm name.");
2977 if (!parse_semi (cfile
))
2979 /* If the algorithm name isn't an FQDN, tack on
2980 the .SIG-ALG.REG.NET. domain. */
2981 s
= strrchr (key
-> algorithm
, '.');
2983 static char add
[] = ".SIG-ALG.REG.INT.";
2984 s
= dmalloc (strlen (key
-> algorithm
) +
2987 log_error ("no memory for key %s.",
2991 strcpy (s
, key
-> algorithm
);
2993 dfree (key
-> algorithm
, MDL
);
2994 key
-> algorithm
= s
;
2996 /* If there is no trailing '.', hack one in. */
2997 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2999 log_error ("no memory for key %s.",
3003 strcpy (s
, key
-> algorithm
);
3005 dfree (key
-> algorithm
, MDL
);
3006 key
-> algorithm
= s
;
3012 parse_warn (cfile
, "key %s: too many secrets",
3017 memset (&ds
, 0, sizeof(ds
));
3018 if (!parse_base64 (&ds
, cfile
))
3020 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
3022 if (status
!= ISC_R_SUCCESS
)
3024 memcpy (key
-> key
-> value
,
3025 ds
.buffer
-> data
, ds
.len
);
3026 data_string_forget (&ds
, MDL
);
3028 if (!parse_semi (cfile
))
3037 if (token
!= RBRACE
) {
3038 parse_warn (cfile
, "expecting right brace.");
3041 /* Allow the BIND 8 syntax, which has a semicolon after each
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
));
3055 omapi_auth_key_dereference (&key
, MDL
);
3059 skip_to_rbrace (cfile
, 1);
3061 omapi_auth_key_dereference (&key
, MDL
);
3066 * on-statement :== event-types LBRACE executable-statements RBRACE
3067 * event-types :== event-type OR event-types |
3069 * event-type :== EXPIRY | COMMIT | RELEASE
3072 int parse_on_statement (result
, cfile
, lose
)
3073 struct executable_statement
**result
;
3074 struct parse
*cfile
;
3077 enum dhcp_token token
;
3080 if (!executable_statement_allocate (result
, MDL
))
3081 log_fatal ("no memory for new statement.");
3082 (*result
) -> op
= on_statement
;
3085 token
= next_token (&val
, (unsigned *)0, cfile
);
3088 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
3092 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
3096 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
3100 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
3104 parse_warn (cfile
, "expecting a lease event type");
3105 skip_to_semi (cfile
);
3107 executable_statement_dereference (result
, MDL
);
3110 token
= next_token (&val
, (unsigned *)0, cfile
);
3111 } while (token
== OR
);
3113 /* Semicolon means no statements. */
3117 if (token
!= LBRACE
) {
3118 parse_warn (cfile
, "left brace expected.");
3119 skip_to_semi (cfile
);
3121 executable_statement_dereference (result
, MDL
);
3124 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
3125 cfile
, lose
, context_any
)) {
3127 /* Try to even things up. */
3129 token
= next_token (&val
,
3130 (unsigned *)0, cfile
);
3131 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3132 executable_statement_dereference (result
, MDL
);
3136 token
= next_token (&val
, (unsigned *)0, cfile
);
3137 if (token
!= RBRACE
) {
3138 parse_warn (cfile
, "right brace expected.");
3139 skip_to_semi (cfile
);
3141 executable_statement_dereference (result
, MDL
);
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
;
3157 enum dhcp_token token
;
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.");
3169 skip_to_semi (cfile
);
3171 executable_statement_dereference (result
, MDL
);
3175 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
3176 cfile
, lose
, context_data_or_numeric
,
3177 (struct expression
**)0, expr_none
)) {
3180 "expecting data or numeric expression.");
3186 token
= next_token (&val
, (unsigned *)0, cfile
);
3187 if (token
!= RPAREN
) {
3188 parse_warn (cfile
, "right paren expected.");
3192 token
= next_token (&val
, (unsigned *)0, cfile
);
3193 if (token
!= LBRACE
) {
3194 parse_warn (cfile
, "left brace expected.");
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
)))) {
3202 skip_to_rbrace (cfile
, 1);
3203 executable_statement_dereference (result
, MDL
);
3207 token
= next_token (&val
, (unsigned *)0, cfile
);
3208 if (token
!= RBRACE
) {
3209 parse_warn (cfile
, "right brace expected.");
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
;
3224 enum expression_context case_context
;
3226 enum dhcp_token token
;
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
))
3238 parse_warn (cfile
, "expecting %s expression.",
3239 (case_context
== context_data
3240 ? "data" : "numeric"));
3244 skip_to_semi (cfile
);
3245 executable_statement_dereference (result
, MDL
);
3249 token
= next_token (&val
, (unsigned *)0, cfile
);
3250 if (token
!= COLON
) {
3251 parse_warn (cfile
, "colon expected.");
3258 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
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
;
3272 enum dhcp_token token
;
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
) {
3284 skip_token(&val
, (unsigned *)0, cfile
);
3289 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
3292 parse_warn (cfile
, "boolean expression expected.");
3293 executable_statement_dereference (result
, MDL
);
3297 #if defined (DEBUG_EXPRESSION_PARSE)
3298 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
3301 token
= next_token (&val
, (unsigned *)0, cfile
);
3302 if (token
!= RPAREN
) {
3303 parse_warn (cfile
, "expecting right paren.");
3305 executable_statement_dereference (result
, MDL
);
3309 token
= next_token (&val
, (unsigned *)0, cfile
);
3310 if (token
!= LBRACE
) {
3311 parse_warn (cfile
, "left brace expected.");
3312 skip_to_semi (cfile
);
3314 executable_statement_dereference (result
, MDL
);
3317 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
3318 cfile
, lose
, context_any
)) {
3320 /* Try to even things up. */
3322 token
= next_token (&val
,
3323 (unsigned *)0, cfile
);
3324 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3325 executable_statement_dereference (result
, MDL
);
3329 token
= next_token (&val
, (unsigned *)0, cfile
);
3330 if (token
!= RBRACE
) {
3331 parse_warn (cfile
, "right brace expected.");
3332 skip_to_semi (cfile
);
3334 executable_statement_dereference (result
, MDL
);
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
);
3342 skip_token(&val
, (unsigned *)0, cfile
);
3343 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3347 "expecting if statement");
3348 executable_statement_dereference (result
, MDL
);
3352 } else if (token
!= LBRACE
) {
3353 parse_warn (cfile
, "left brace or if expected.");
3354 skip_to_semi (cfile
);
3356 executable_statement_dereference (result
, MDL
);
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
);
3366 token
= next_token (&val
, (unsigned *)0, cfile
);
3367 if (token
!= RBRACE
) {
3368 parse_warn (cfile
, "right brace expected.");
3369 skip_to_semi (cfile
);
3371 executable_statement_dereference (result
, MDL
);
3375 } else if (token
== ELSIF
) {
3376 skip_token(&val
, (unsigned *)0, cfile
);
3377 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3381 "expecting conditional.");
3382 executable_statement_dereference (result
, MDL
);
3387 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
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
;
3408 /* Parse an expression... */
3409 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
3410 (struct expression
**)0, expr_none
))
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.");
3418 expression_dereference (expr
, MDL
);
3424 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3426 int parse_boolean (cfile
)
3427 struct parse
*cfile
;
3432 (void)next_token(&val
, NULL
, cfile
);
3433 if (!strcasecmp (val
, "true")
3434 || !strcasecmp (val
, "on"))
3436 else if (!strcasecmp (val
, "false")
3437 || !strcasecmp (val
, "off"))
3441 "boolean value (true/false/on/off) expected");
3442 skip_to_semi (cfile
);
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 |
3462 * PACKET LPAREN numeric-expression COMMA
3463 * numeric-expression RPAREN |
3464 * V6RELAY LPAREN numeric-expression COMMA
3465 * data-expression RPAREN |
3467 * colon_separated_hex_list
3470 int parse_data_expression (expr
, cfile
, lose
)
3471 struct expression
**expr
;
3472 struct parse
*cfile
;
3475 /* Parse an expression... */
3476 if (!parse_expression (expr
, cfile
, lose
, context_data
,
3477 (struct expression
**)0, expr_none
))
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.");
3492 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3493 * COMMA number RPAREN |
3497 int parse_numeric_expression (expr
, cfile
, lose
)
3498 struct expression
**expr
;
3499 struct parse
*cfile
;
3502 /* Parse an expression... */
3503 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
3504 (struct expression
**)0, expr_none
))
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.");
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
;
3524 enum expression_context context
;
3526 enum dhcp_token token
;
3528 struct collection
*col
;
3529 struct expression
*nexp
, **ep
;
3532 isc_result_t status
;
3535 token
= peek_token (&val
, (unsigned *)0, cfile
);
3537 /* Check for unary operators... */
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
);
3548 for (col
= collections
; col
; col
= col
-> next
)
3549 if (!strcmp (col
-> name
, val
))
3552 parse_warn (cfile
, "unknown collection.");
3556 if (!expression_allocate (expr
, MDL
))
3557 log_fatal ("can't allocate expression");
3558 (*expr
) -> op
= expr_check
;
3559 (*expr
) -> data
.check
= col
;
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
)) {
3570 parse_warn (cfile
, "expression expected");
3571 skip_to_semi (cfile
);
3574 expression_dereference (expr
, MDL
);
3577 if (!is_boolean_expression ((*expr
) -> data
.not)) {
3579 parse_warn (cfile
, "boolean expression expected");
3580 skip_to_semi (cfile
);
3581 expression_dereference (expr
, MDL
);
3587 skip_token(&val
, (unsigned *)0, cfile
);
3588 if (!parse_expression (expr
, cfile
, lose
, context
,
3589 (struct expression
**)0, expr_none
)) {
3591 parse_warn (cfile
, "expression expected");
3592 skip_to_semi (cfile
);
3597 token
= next_token (&val
, (unsigned *)0, cfile
);
3598 if (token
!= RPAREN
) {
3600 parse_warn (cfile
, "right paren expected");
3601 skip_to_semi (cfile
);
3607 skip_token(&val
, NULL
, cfile
);
3608 if (!expression_allocate (expr
, MDL
))
3609 log_fatal ("can't allocate expression");
3610 (*expr
)->op
= expr_exists
;
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
) {
3618 expression_dereference (expr
, MDL
);
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
;
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
;
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
) {
3646 expression_dereference (expr
, MDL
);
3647 parse_warn (cfile
, "left parenthesis expected.");
3652 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
3655 expression_dereference (expr
, MDL
);
3658 "expecting data expression.");
3659 skip_to_semi (cfile
);
3665 token
= next_token (&val
, (unsigned *)0, cfile
);
3666 if (token
!= COMMA
) {
3668 expression_dereference (expr
, MDL
);
3669 parse_warn (cfile
, "comma expected.");
3675 if (!parse_numeric_expression
3676 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
3680 "expecting numeric expression.");
3681 skip_to_semi (cfile
);
3684 expression_dereference (expr
, MDL
);
3688 token
= next_token (&val
, (unsigned *)0, cfile
);
3692 if (!parse_numeric_expression
3693 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
3696 token
= next_token (&val
, (unsigned *)0, cfile
);
3697 if (token
!= RPAREN
) {
3699 parse_warn (cfile
, "right parenthesis expected.");
3701 expression_dereference (expr
, MDL
);
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
)
3716 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
3720 token
= next_token (&val
, (unsigned *)0, cfile
);
3724 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
3728 token
= next_token (&val
, (unsigned *)0, cfile
);
3729 if (token
!= RPAREN
)
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
)
3743 if (!parse_data_expression(&(*expr
)->data
.lcase
, cfile
, lose
))
3746 token
= next_token(&val
, (unsigned *)0, cfile
);
3747 if (token
!= RPAREN
)
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
)
3761 if (!parse_data_expression(&(*expr
)->data
.ucase
,
3765 token
= next_token(&val
, (unsigned *)0, cfile
);
3766 if (token
!= RPAREN
)
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
)
3780 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3784 token
= next_token (&val
, (unsigned *)0, cfile
);
3789 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
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],
3802 expression_dereference (expr
, MDL
);
3803 expression_reference (expr
, nexp
, MDL
);
3804 expression_dereference (&nexp
, MDL
);
3805 goto concat_another
;
3808 if (token
!= RPAREN
)
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
)
3822 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3826 token
= next_token (&val
, (unsigned *)0, cfile
);
3830 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3834 token
= next_token (&val
, (unsigned *)0, cfile
);
3838 if (!parse_data_expression (&(*expr
) -> data
.b2a
.separator
,
3842 token
= next_token (&val
, (unsigned *)0, cfile
);
3846 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3850 token
= next_token (&val
, (unsigned *)0, cfile
);
3851 if (token
!= RPAREN
)
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
)
3865 if (!(parse_numeric_expression
3866 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3869 token
= next_token (&val
, (unsigned *)0, cfile
);
3873 if (!(parse_data_expression
3874 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3877 token
= next_token (&val
, (unsigned *)0, cfile
);
3878 if (token
!= RPAREN
)
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
)
3893 nexp
= (struct expression
*)0;
3894 expression_reference (&nexp
, *expr
, MDL
);
3896 nexp
-> op
= expr_pick_first_value
;
3897 if (!(parse_data_expression
3898 (&nexp
-> data
.pick_first_value
.car
,
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
)
3922 if (!expression_allocate (expr
, MDL
))
3923 log_fatal ("can't allocate expression");
3924 (*expr
) -> op
= (token
== OPTION
3926 : expr_config_option
);
3927 skip_token(&val
, (unsigned *)0, cfile
);
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
) {
3935 expression_dereference (expr
, MDL
);
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
)
4006 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
4010 token
= next_token (&val
, (unsigned *)0, cfile
);
4014 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
4018 token
= next_token (&val
, (unsigned *)0, cfile
);
4019 if (token
!= RPAREN
)
4024 skip_token(&val
, &len
, cfile
);
4025 if (!make_const_data (expr
, (const unsigned char *)val
,
4027 log_fatal ("can't make constant string expression.");
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.");
4039 if (!expression_allocate (expr
, MDL
))
4040 log_fatal ("can't allocate expression");
4042 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
4046 "expecting data expression.");
4047 skip_to_semi (cfile
);
4050 expression_dereference (expr
, MDL
);
4054 token
= next_token (&val
, (unsigned *)0, cfile
);
4055 if (token
!= COMMA
) {
4056 parse_warn (cfile
, "comma expected.");
4058 expression_dereference (expr
, MDL
);
4062 token
= next_token (&val
, (unsigned *)0, cfile
);
4063 if (token
!= NUMBER
) {
4064 parse_warn (cfile
, "number expected.");
4066 expression_dereference (expr
, MDL
);
4069 switch (atoi (val
)) {
4071 (*expr
) -> op
= expr_extract_int8
;
4075 (*expr
) -> op
= expr_extract_int16
;
4079 (*expr
) -> op
= expr_extract_int32
;
4084 "unsupported integer size %d", atoi (val
));
4086 skip_to_semi (cfile
);
4087 expression_dereference (expr
, MDL
);
4091 token
= next_token (&val
, (unsigned *)0, cfile
);
4092 if (token
!= RPAREN
) {
4093 parse_warn (cfile
, "right parenthesis expected.");
4095 expression_dereference (expr
, MDL
);
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.");
4109 if (!expression_allocate (expr
, MDL
))
4110 log_fatal ("can't allocate expression");
4112 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
4114 parse_warn (cfile
, "expecting numeric expression.");
4115 skip_to_semi (cfile
);
4117 expression_dereference (expr
, MDL
);
4121 token
= next_token (&val
, (unsigned *)0, cfile
);
4122 if (token
!= COMMA
) {
4123 parse_warn (cfile
, "comma expected.");
4125 expression_dereference (expr
, MDL
);
4129 token
= next_token (&val
, (unsigned *)0, cfile
);
4130 if (token
!= NUMBER
) {
4131 parse_warn (cfile
, "number expected.");
4133 expression_dereference (expr
, MDL
);
4136 switch (atoi (val
)) {
4138 (*expr
) -> op
= expr_encode_int8
;
4142 (*expr
) -> op
= expr_encode_int16
;
4146 (*expr
) -> op
= expr_encode_int32
;
4151 "unsupported integer size %d", atoi (val
));
4153 skip_to_semi (cfile
);
4154 expression_dereference (expr
, MDL
);
4158 token
= next_token (&val
, (unsigned *)0, cfile
);
4159 if (token
!= RPAREN
) {
4160 parse_warn (cfile
, "right parenthesis expected.");
4162 expression_dereference (expr
, MDL
);
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
);
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
);
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
;
4203 known
= ISC_R_SUCCESS
;
4207 known
= DHCP_R_NOTAUTH
;
4211 known
= ISC_R_NOTIMPLEMENTED
;
4215 known
= DHCP_R_NOTZONE
;
4219 known
= DHCP_R_NXDOMAIN
;
4223 known
= DHCP_R_NXRRSET
;
4227 known
= DHCP_R_REFUSED
;
4231 known
= DHCP_R_SERVFAIL
;
4235 known
= DHCP_R_YXDOMAIN
;
4239 known
= DHCP_R_YXRRSET
;
4247 known
= S_REBOOTING
;
4251 known
= S_SELECTING
;
4255 known
= S_REQUESTING
;
4267 known
= S_REBINDING
;
4271 skip_token(&val
, (unsigned *)0, cfile
);
4272 token
= next_token (&val
, (unsigned *)0, cfile
);
4273 if (token
!= LPAREN
)
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
);
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
)
4296 /* This parses '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
)
4307 token
= next_token(NULL
, NULL
, cfile
);
4308 if (token
!= RPAREN
)
4313 skip_token(&val
, NULL
, cfile
);
4314 token
= next_token(NULL
, NULL
, cfile
);
4315 if (token
!= LPAREN
)
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
);
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
)
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
)
4346 if (!parse_numeric_expression (&(*expr
)->data
.v6relay
.relay
,
4350 token
= next_token (&val
, NULL
, cfile
);
4354 if (!parse_data_expression (&(*expr
)->data
.v6relay
.roption
,
4358 token
= next_token (&val
, NULL
, cfile
);
4360 if (token
!= RPAREN
)
4364 /* Not a valid start to an expression... */
4366 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
4369 skip_token(&val
, (unsigned *)0, cfile
);
4371 /* Save the name of the variable being referenced. */
4372 cptr
= dmalloc (strlen (val
) + 1, MDL
);
4374 log_fatal ("can't allocate variable name");
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
;
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
;
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,
4405 "expecting expression.");
4408 skip_to_semi (cfile
);
4409 expression_dereference (expr
, MDL
);
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
);
4419 expression_dereference (expr
, MDL
);
4427 /* Parse an expression. */
4429 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
4430 struct expression
**expr
;
4431 struct parse
*cfile
;
4433 enum expression_context context
;
4434 struct expression
**plhs
;
4437 enum dhcp_token token
;
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. */
4448 expression_reference (&lhs
, *plhs
, MDL
);
4449 expression_dereference (plhs
, MDL
);
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. */
4460 "expecting right-hand side.");
4462 skip_to_semi (cfile
);
4464 expression_dereference (&lhs
, MDL
);
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
);
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 =");
4481 skip_to_semi (cfile
);
4483 expression_dereference (&lhs
, MDL
);
4486 next_op
= expr_not_equal
;
4487 context
= expression_context (rhs
);
4491 next_op
= expr_equal
;
4492 context
= expression_context (rhs
);
4497 skip_token(&val
, NULL
, cfile
);
4498 token
= peek_token(&val
, NULL
, cfile
);
4501 next_op
= expr_iregex_match
;
4502 else if (token
== EQUAL
)
4503 next_op
= expr_regex_match
;
4505 parse_warn(cfile
, "expecting ~= or ~~ operator");
4507 skip_to_semi(cfile
);
4509 expression_dereference(&lhs
, MDL
);
4513 context
= expression_context(rhs
);
4515 parse_warn(cfile
, "No support for regex operator.");
4517 skip_to_semi(cfile
);
4519 expression_dereference(&lhs
, MDL
);
4526 context
= expression_context (rhs
);
4531 context
= expression_context (rhs
);
4536 context
= expression_context (rhs
);
4540 next_op
= expr_subtract
;
4541 context
= expression_context (rhs
);
4545 next_op
= expr_divide
;
4546 context
= expression_context (rhs
);
4550 next_op
= expr_multiply
;
4551 context
= expression_context (rhs
);
4555 next_op
= expr_remainder
;
4556 context
= expression_context (rhs
);
4560 next_op
= expr_binary_and
;
4561 context
= expression_context (rhs
);
4565 next_op
= expr_binary_or
;
4566 context
= expression_context (rhs
);
4570 next_op
= expr_binary_xor
;
4571 context
= expression_context (rhs
);
4575 next_op
= expr_none
;
4578 /* If we have no lhs yet, we just parsed it. */
4580 /* If there was no operator following what we just parsed,
4581 then we're done - return it. */
4582 if (next_op
== expr_none
) {
4587 rhs
= (struct expression
*)0;
4589 skip_token(&val
, (unsigned *)0, cfile
);
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
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. */
4608 rhs
= (struct expression
*)0;
4609 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4613 "expecting a subexpression");
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
);
4636 case expr_not_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
);
4650 case expr_regex_match
:
4652 if (expression_context(rhs
) != context_data
) {
4653 parse_warn(cfile
, "expecting data expression");
4654 skip_to_semi(cfile
);
4655 expression_dereference(&rhs
, MDL
);
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
);
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
);
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
);
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
;
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
;
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
4738 if (next_op
== expr_none
) {
4748 int parse_option_data (expr
, cfile
, lookups
, option
)
4749 struct expression
**expr
;
4750 struct parse
*cfile
;
4752 struct option
*option
;
4755 const char *fmt
= NULL
;
4756 struct expression
*tmp
;
4757 enum dhcp_token token
;
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
4768 /* Set fmt to start of format for 'A' and one char back
4771 if ((fmt
!= NULL
) && (fmt
!= option
->format
) && (*fmt
== 'a'))
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'))
4781 if ((*fmt
== 'A') || (*fmt
== 'a'))
4784 /* consume the optional flag */
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,
4800 if (token
== SEMI
) {
4809 if (!parse_option_token(expr
, cfile
, &fmt
, tmp
,
4810 uniform
, lookups
)) {
4811 if (fmt
[1] != 'o') {
4813 expression_dereference (&tmp
,
4821 expression_dereference (&tmp
, MDL
);
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
);
4833 /* no comma: end of array.
4834 'A' or end of string means: leave the loop */
4835 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4837 /* 'a' means: go on with next char */
4843 } while ((*fmt
== 'A') || (*fmt
== 'a'));
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
;
4859 struct option
*option
;
4860 enum statement_op op
;
4863 enum dhcp_token token
;
4864 struct expression
*expr
= (struct expression
*)0;
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
4888 "expecting a data expression.");
4889 skip_to_semi (cfile
);
4894 if (! parse_option_data(&expr
, cfile
, lookups
, option
))
4898 if (!parse_semi (cfile
))
4900 if (!executable_statement_allocate (result
, MDL
))
4901 log_fatal ("no memory for option statement.");
4904 if (expr
&& !option_cache (&(*result
)->data
.option
,
4905 NULL
, expr
, option
, MDL
))
4906 log_fatal ("no memory for option cache");
4909 expression_dereference (&expr
, MDL
);
4914 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4915 struct expression
**rv
;
4916 struct parse
*cfile
;
4918 struct expression
*expr
;
4923 enum dhcp_token token
;
4924 struct expression
*t
= (struct expression
*)0;
4925 unsigned char buf
[4];
4929 isc_boolean_t freeval
= ISC_FALSE
;
4931 struct enumeration_value
*e
;
4935 token
= next_token (&val
, &len
, cfile
);
4936 if (!is_identifier (token
)) {
4937 if ((*fmt
) [1] != 'o') {
4938 parse_warn (cfile
, "expecting identifier.");
4940 skip_to_semi (cfile
);
4944 if (!make_const_data (&t
, (const unsigned char *)val
,
4946 log_fatal ("No memory for %s", val
);
4950 g
= strchr (*fmt
, '.');
4953 "malformed encapsulation format (bug!)");
4954 skip_to_semi (cfile
);
4959 /* to get string value for the option */
4961 token
= peek_token (&val
, (unsigned *)0, cfile
);
4962 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4963 if (!expression_allocate (&t
, MDL
))
4965 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4966 expression_dereference (&t
, MDL
);
4969 t
-> op
= expr_const_data
;
4971 token
= next_token (&val
, &len
, cfile
);
4973 if(token
== STRING
) {
4974 if (!make_const_data (&t
,
4975 (const unsigned char *)val
,
4977 log_fatal ("No memory for \"%s\"", val
);
4979 if ((*fmt
) [1] != 'o') {
4980 parse_warn (cfile
, "expecting string "
4981 "or hexadecimal data.");
4982 skip_to_semi (cfile
);
4989 case 'D': /* Domain list... */
4990 if ((*fmt
)[1] == 'c') {
4992 /* Skip the compress-flag atom. */
4997 t
= parse_domain_list(cfile
, compress
);
5000 if ((*fmt
)[1] != 'o')
5001 skip_to_semi(cfile
);
5007 case 'd': /* Domain name... */
5008 val
= parse_host_name (cfile
);
5010 parse_warn (cfile
, "not a valid domain name.");
5011 skip_to_semi (cfile
);
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.");
5024 skip_to_semi (cfile
);
5029 if (!make_const_data (&t
, (const unsigned char *)val
,
5031 log_fatal ("No memory for concatenation");
5032 if (freeval
== ISC_TRUE
) {
5033 dfree((char *)val
, MDL
);
5034 freeval
= ISC_FALSE
;
5041 g
= strchr (*fmt
, '.');
5043 parse_warn (cfile
, "malformed %s (bug!)",
5044 "enumeration format");
5046 skip_to_semi (cfile
);
5050 token
= next_token (&val
, (unsigned *)0, cfile
);
5051 if (!is_identifier (token
)) {
5053 "identifier expected");
5056 e
= find_enumeration_value (f
, (*fmt
) - f
, &len
, val
);
5058 parse_warn (cfile
, "unknown value");
5061 if (!make_const_data (&t
, &e
-> value
, len
, 0, 1, MDL
))
5065 case 'I': /* IP address or hostname. */
5067 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
5070 if (!parse_ip_addr (cfile
, &addr
))
5072 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
5078 case '6': /* IPv6 address. */
5079 if (!parse_ip6_addr(cfile
, &addr
)) {
5082 if (!make_const_data(&t
, addr
.iabuf
, addr
.len
, 0, 1, MDL
)) {
5087 case 'T': /* Lease interval. */
5088 token
= next_token (&val
, (unsigned *)0, cfile
);
5089 if (token
!= INFINITE
)
5092 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5096 case 'L': /* Unsigned 32-bit integer... */
5097 case 'l': /* Signed 32-bit integer... */
5098 token
= next_token (&val
, (unsigned *)0, cfile
);
5100 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
5102 if ((*fmt
) [1] != 'o') {
5103 parse_warn (cfile
, "expecting number.");
5105 skip_to_semi (cfile
);
5109 convert_num (cfile
, buf
, val
, 0, 32);
5110 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
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
))
5119 convert_num (cfile
, buf
, val
, 0, 16);
5120 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
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
))
5129 convert_num (cfile
, buf
, val
, 0, 8);
5130 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
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.");
5140 if ((*fmt
) [1] != 'o') {
5142 skip_to_semi (cfile
);
5146 if (!strcasecmp (val
, "true")
5147 || !strcasecmp (val
, "on"))
5149 else if (!strcasecmp (val
, "false")
5150 || !strcasecmp (val
, "off"))
5152 else if (!strcasecmp (val
, "ignore"))
5155 if ((*fmt
) [1] != 'o')
5156 parse_warn (cfile
, "expecting boolean.");
5159 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
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
);
5170 if (!make_const_data(&t
, /* expression */
5180 parse_warn (cfile
, "Bad format '%c' in parse_option_token.",
5182 skip_to_semi (cfile
);
5186 if (!make_concat (rv
, expr
, t
))
5189 expression_reference (rv
, t
, MDL
);
5190 expression_dereference (&t
, MDL
);
5194 int parse_option_decl (oc
, cfile
)
5195 struct option_cache
**oc
;
5196 struct parse
*cfile
;
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
;
5207 const u_int8_t
*cdp
;
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
)
5221 fmt
= option
->format
;
5223 /* Parse the option data... */
5225 for (; *fmt
; fmt
++) {
5227 /* 'A' is an array of records, start at
5230 fmt
= option
->format
;
5235 /* 'a' is an array of the last field,
5236 * back up one format character
5241 if (*fmt
== 'o' && fmt
!= option
-> format
)
5245 fmt
= strchr (fmt
, '.');
5248 "malformed %s (bug!)",
5249 "encapsulation format");
5253 /* to get string value for the option */
5255 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
5256 sizeof hunkbuf
- hunkix
);
5260 case 't': /* Text string... */
5261 token
= peek_token (&val
,
5263 if (token
== SEMI
&& fmt
[1] == 'o') {
5267 token
= next_token (&val
,
5269 if (token
!= STRING
) {
5271 "expecting string.");
5274 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
5276 "option data buffer %s",
5280 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
5286 if (fmt
[1] == 'c') {
5292 express
= parse_domain_list(cfile
, compress
);
5294 if (express
== NULL
)
5297 if (express
->op
!= expr_const_data
) {
5298 parse_warn(cfile
, "unexpected "
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 "
5311 memcpy(&hunkbuf
[hunkix
], cdp
, len
);
5314 expression_dereference(&express
, MDL
);
5319 fmt
= strchr (fmt
, '.');
5322 "malformed %s (bug!)",
5323 "enumeration format");
5326 token
= next_token (&val
,
5327 (unsigned *)0, cfile
);
5328 if (!is_identifier (token
)) {
5330 "identifier expected");
5333 e
= find_enumeration_value (f
, fmt
- f
,
5344 if (!parse_ip6_addr(cfile
, &ip_addr
))
5350 case 'I': /* IP address. */
5351 if (!parse_ip_addr (cfile
, &ip_addr
))
5357 if (hunkix
+ len
> sizeof hunkbuf
) {
5359 "option data buffer %s",
5363 memcpy (&hunkbuf
[hunkix
], dp
, len
);
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
)) {
5375 "expecting number.");
5381 convert_num (cfile
, buf
, val
, 0, 32);
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
))
5393 convert_num (cfile
, buf
, val
, 0, 16);
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
))
5405 convert_num (cfile
, buf
, val
, 0, 8);
5410 case 'f': /* Boolean flag. */
5411 token
= next_token (&val
,
5412 (unsigned *)0, cfile
);
5413 if (!is_identifier (token
)) {
5415 "expecting identifier.");
5422 if (!strcasecmp (val
, "true")
5423 || !strcasecmp (val
, "on"))
5425 else if (!strcasecmp (val
, "false")
5426 || !strcasecmp (val
, "off"))
5430 "expecting boolean.");
5437 case 'Z': /* Zero-length option */
5438 token
= peek_token(&val
, (unsigned *)0, cfile
);
5439 if (token
!= SEMI
) {
5441 "semicolon expected.");
5449 log_error ("parse_option_param: Bad format %c",
5454 token
= next_token (&val
, (unsigned *)0, cfile
);
5455 } while (*fmt
&& token
== COMMA
);
5457 if (token
!= SEMI
) {
5458 parse_warn (cfile
, "semicolon expected.");
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
);
5479 if (express
!= NULL
)
5480 expression_dereference(&express
, MDL
);
5481 skip_to_semi (cfile
);
5483 option_dereference(&option
, MDL
);
5488 /* Consider merging parse_cshl into this. */
5490 int parse_X (cfile
, buf
, max
)
5491 struct parse
*cfile
;
5499 token
= peek_token (&val
, (unsigned *)0, cfile
);
5500 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5503 token
= next_token (&val
, (unsigned *)0, cfile
);
5504 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
5506 "expecting hexadecimal constant.");
5507 skip_to_semi (cfile
);
5510 convert_num (cfile
, &buf
[len
], val
, 16, 8);
5513 "hexadecimal constant too long.");
5514 skip_to_semi (cfile
);
5517 token
= peek_token (&val
, (unsigned *)0, cfile
);
5519 token
= next_token (&val
,
5520 (unsigned *)0, cfile
);
5521 } while (token
== COLON
);
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
);
5530 memcpy (buf
, val
, len
+ 1);
5532 parse_warn (cfile
, "expecting string or hexadecimal data");
5533 skip_to_semi (cfile
);
5539 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
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
);
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
++)
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
);
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;
5594 parse_domain_list(struct parse
*cfile
, int compress
)
5597 enum dhcp_token token
= SEMI
;
5598 struct expression
*t
= NULL
;
5599 unsigned len
, clen
= 0;
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];
5610 /* Consume the COMMA token if peeked. */
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.");
5622 /* If compression pointers are enabled, compress. If not,
5623 * just pack the names in series into the buffer.
5626 result
= MRns_name_compress(val
, compbuf
+ clen
,
5627 sizeof(compbuf
) - clen
,
5631 parse_warn(cfile
, "Error compressing domain "
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.
5646 parse_warn(cfile
, "Error assembling domain "
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). */
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.");