3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
38 /* Enumerations can be specified in option formats, and are used for
39 parsing, so we define the routines that manage them here. */
41 struct enumeration
*enumerations
;
43 void add_enumeration (struct enumeration
*enumeration
)
45 enumeration
-> next
= enumerations
;
46 enumerations
= enumeration
;
49 struct enumeration
*find_enumeration (const char *name
, int length
)
51 struct enumeration
*e
;
53 for (e
= enumerations
; e
; e
= e
-> next
)
54 if (strlen (e
-> name
) == length
&&
55 !memcmp (e
-> name
, name
, (unsigned)length
))
57 return (struct enumeration
*)0;
60 struct enumeration_value
*find_enumeration_value (const char *name
,
65 struct enumeration
*e
;
68 e
= find_enumeration (name
, length
);
72 for (i
= 0; e
-> values
[i
].name
; i
++) {
73 if (!strcmp (value
, e
-> values
[i
].name
))
74 return &e
-> values
[i
];
77 return (struct enumeration_value
*)0;
80 /* Skip to the semicolon ending the current statement. If we encounter
81 braces, the matching closing brace terminates the statement. If we
82 encounter a right brace but haven't encountered a left brace, return
83 leaving the brace in the token buffer for the caller. If we see a
84 semicolon and haven't seen a left brace, return. This lets us skip
89 statement foo bar { statement { } }
94 void skip_to_semi (cfile
)
97 skip_to_rbrace (cfile
, 0);
100 void skip_to_rbrace (cfile
, brace_count
)
104 enum dhcp_token token
;
107 #if defined (DEBUG_TOKEN)
108 log_error ("skip_to_rbrace: %d\n", brace_count
);
111 token
= peek_token (&val
, (unsigned *)0, cfile
);
112 if (token
== RBRACE
) {
113 token
= next_token (&val
, (unsigned *)0, cfile
);
119 } else if (token
== LBRACE
) {
121 } else if (token
== SEMI
&& !brace_count
) {
122 token
= next_token (&val
, (unsigned *)0, cfile
);
124 } else if (token
== EOL
) {
125 /* EOL only happens when parsing /etc/resolv.conf,
126 and we treat it like a semicolon because the
127 resolv.conf file is line-oriented. */
128 token
= next_token (&val
, (unsigned *)0, cfile
);
131 token
= next_token (&val
, (unsigned *)0, cfile
);
132 } while (token
!= END_OF_FILE
);
135 int parse_semi (cfile
)
138 enum dhcp_token token
;
141 token
= next_token (&val
, (unsigned *)0, cfile
);
143 parse_warn (cfile
, "semicolon expected.");
144 skip_to_semi (cfile
);
150 /* string-parameter :== STRING SEMI */
152 int parse_string (cfile
, sptr
, lptr
)
158 enum dhcp_token token
;
162 token
= next_token (&val
, &len
, cfile
);
163 if (token
!= STRING
) {
164 parse_warn (cfile
, "expecting a string");
165 skip_to_semi (cfile
);
168 s
= (char *)dmalloc (len
+ 1, MDL
);
170 log_fatal ("no memory for string %s.", val
);
171 memcpy (s
, val
, len
+ 1);
173 if (!parse_semi (cfile
)) {
187 * hostname :== IDENTIFIER
189 * | hostname DOT IDENTIFIER
192 char *parse_host_name (cfile
)
196 enum dhcp_token token
;
203 /* Read a dotted hostname... */
205 /* Read a token, which should be an identifier. */
206 token
= peek_token (&val
, (unsigned *)0, cfile
);
207 if (!is_identifier (token
) && token
!= NUMBER
)
209 token
= next_token (&val
, (unsigned *)0, cfile
);
211 /* Store this identifier... */
212 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
213 log_fatal ("can't allocate temp space for hostname.");
215 c
= cons ((caddr_t
)s
, c
);
216 len
+= strlen (s
) + 1;
217 /* Look for a dot; if it's there, keep going, otherwise
219 token
= peek_token (&val
, (unsigned *)0, cfile
);
221 token
= next_token (&val
, (unsigned *)0, cfile
);
225 } while (token
== DOT
);
227 /* Should be at least one token. */
231 /* Assemble the hostname together into a string. */
232 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
233 log_fatal ("can't allocate space for hostname.");
240 unsigned l
= strlen ((char *)(c
-> car
));
242 memcpy (t
, (char *)(c
-> car
), l
);
243 /* Free up temp space. */
244 dfree (c
-> car
, MDL
);
253 /* ip-addr-or-hostname :== ip-address | hostname
254 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
256 Parse an ip address or a hostname. If uniform is zero, put in
257 an expr_substring node to limit hostnames that evaluate to more
260 Note that RFC1123 permits hostnames to consist of all digits,
261 making it difficult to quickly disambiguate them from ip addresses.
264 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
265 struct expression
**expr
;
270 enum dhcp_token token
;
271 unsigned char addr
[4];
272 unsigned len
= sizeof addr
;
274 struct expression
*x
= (struct expression
*)0;
277 token
= peek_token (&val
, (unsigned *)0, cfile
);
279 if (token
== NUMBER
) {
281 * a hostname may be numeric, but domain names must
282 * start with a letter, so we can disambiguate by
283 * looking ahead a few tokens. we save the parse
284 * context first, and restore it after we know what
285 * we're dealing with.
287 save_parse_state(cfile
);
288 (void) next_token(NULL
, NULL
, cfile
);
289 if (next_token(NULL
, NULL
, cfile
) == DOT
&&
290 next_token(NULL
, NULL
, cfile
) == NUMBER
)
292 restore_parse_state(cfile
);
295 parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
296 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
300 if (is_identifier (token
) || token
== NUMBER
) {
301 name
= parse_host_name (cfile
);
304 if (!make_host_lookup (expr
, name
)) {
310 if (!make_limit (&x
, *expr
, 4))
312 expression_dereference (expr
, MDL
);
316 if (token
!= RBRACE
&& token
!= LBRACE
)
317 token
= next_token (&val
, (unsigned *)0, cfile
);
318 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
321 skip_to_semi (cfile
);
329 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
332 int parse_ip_addr (cfile
, addr
)
337 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
338 &addr
-> len
, DOT
, 10, 8))
344 * Return true if every character in the string is hexadecimal.
347 is_hex_string(const char *s
) {
349 if (!isxdigit((int)*s
)) {
358 * ip-address6 :== (complicated set of rules)
360 * See section 2.2 of RFC 1884 for details.
362 * We are lazy for this. We pull numbers, names, colons, and dots
363 * together and then throw the resulting string at the inet_pton()
368 parse_ip6_addr(struct parse
*cfile
, struct iaddr
*addr
) {
369 enum dhcp_token token
;
373 char v6
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
376 if (local_family
!= AF_INET6
) {
377 parse_warn(cfile
, "IPv6 addresses are only available "
384 * First token is non-raw. This way we eat any whitespace before
385 * our IPv6 address begins, like one would expect.
387 token
= peek_token(&val
, NULL
, cfile
);
394 if ((((token
== NAME
) || (token
== NUMBER_OR_NAME
)) &&
395 is_hex_string(val
)) ||
400 next_raw_token(&val
, NULL
, cfile
);
401 val_len
= strlen(val
);
402 if ((v6_len
+ val_len
) >= sizeof(v6
)) {
403 parse_warn(cfile
, "Invalid IPv6 address.");
407 memcpy(v6
+v6_len
, val
, val_len
);
413 token
= peek_raw_token(&val
, NULL
, cfile
);
418 * Use inet_pton() for actual work.
420 if (inet_pton(AF_INET6
, v6
, addr
->iabuf
) <= 0) {
421 parse_warn(cfile
, "Invalid IPv6 address.");
430 * Same as parse_ip6_addr() above, but returns the value in the
431 * expression rather than in an address structure.
434 parse_ip6_addr_expr(struct expression
**expr
,
435 struct parse
*cfile
) {
438 if (!parse_ip6_addr(cfile
, &addr
)) {
441 return make_const_data(expr
, addr
.iabuf
, addr
.len
, 0, 1, MDL
);
445 * ip6-prefix :== ip6-address "/" NUMBER
448 parse_ip6_prefix(struct parse
*cfile
, struct iaddr
*addr
, u_int8_t
*plen
) {
449 enum dhcp_token token
;
453 if (!parse_ip6_addr(cfile
, addr
)) {
456 token
= next_token(&val
, NULL
, cfile
);
457 if (token
!= SLASH
) {
458 parse_warn(cfile
, "Slash expected.");
463 token
= next_token(&val
, NULL
, cfile
);
464 if (token
!= NUMBER
) {
465 parse_warn(cfile
, "Number expected.");
471 if ((n
< 0) || (n
> 128)) {
472 parse_warn(cfile
, "Invalid IPv6 prefix length.");
476 if (!is_cidr_mask_valid(addr
, n
)) {
477 parse_warn(cfile
, "network mask too short.");
486 * ip-address-with-subnet :== ip-address |
487 * ip-address "/" NUMBER
491 parse_ip_addr_with_subnet(cfile
, match
)
493 struct iaddrmatch
*match
;
495 const char *val
, *orig
;
496 enum dhcp_token token
;
499 unsigned char newval
, warnmask
=0;
501 if (parse_ip_addr(cfile
, &match
->addr
)) {
502 /* default to host mask */
503 prefixlen
= match
->addr
.len
* 8;
505 token
= peek_token(&val
, NULL
, cfile
);
507 if (token
== SLASH
) {
508 next_token(&val
, NULL
, cfile
);
509 token
= next_token(&val
, NULL
, cfile
);
511 if (token
!= NUMBER
) {
512 parse_warn(cfile
, "Invalid CIDR prefix length:"
513 " expecting a number.");
517 prefixlen
= atoi(val
);
520 prefixlen
> (match
->addr
.len
* 8)) {
521 parse_warn(cfile
, "subnet prefix is out of "
523 match
->addr
.len
* 8);
528 /* construct a suitable mask field */
531 match
->mask
.len
= match
->addr
.len
;
533 /* count of 0xff bytes in mask */
534 fflen
= prefixlen
/ 8;
536 /* set leading mask */
537 memset(match
->mask
.iabuf
, 0xff, fflen
);
540 if (fflen
< match
->mask
.len
) {
541 match
->mask
.iabuf
[fflen
] =
542 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen
% 8];
544 memset(match
->mask
.iabuf
+fflen
+1, 0x00,
545 match
->mask
.len
- fflen
- 1);
547 /* AND-out insignificant bits from supplied netmask. */
548 orig
= piaddr(match
->addr
);
550 newval
= match
->addr
.iabuf
[fflen
] &
551 match
->mask
.iabuf
[fflen
];
553 if (newval
!= match
->addr
.iabuf
[fflen
]) {
555 match
->addr
.iabuf
[fflen
] = newval
;
557 } while (++fflen
< match
->mask
.len
);
560 log_error("Warning: Extraneous bits removed "
561 "in address component of %s/%d.",
563 log_error("New value: %s/%d.",
564 piaddr(match
->addr
), prefixlen
);
572 "expecting ip-address or ip-address/prefixlen");
574 return 0; /* let caller pick up pieces */
578 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
579 * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI
582 void parse_hardware_param (cfile
, hardware
)
584 struct hardware
*hardware
;
587 enum dhcp_token token
;
591 token
= next_token (&val
, (unsigned *)0, cfile
);
594 hardware
-> hbuf
[0] = HTYPE_ETHER
;
597 hardware
-> hbuf
[0] = HTYPE_IEEE802
;
600 hardware
-> hbuf
[0] = HTYPE_FDDI
;
603 if (!strncmp (val
, "unknown-", 8)) {
604 hardware
-> hbuf
[0] = atoi (&val
[8]);
607 "expecting a network hardware type");
608 skip_to_semi (cfile
);
614 /* Parse the hardware address information. Technically,
615 it would make a lot of sense to restrict the length of the
616 data we'll accept here to the length of a particular hardware
617 address type. Unfortunately, there are some broken clients
618 out there that put bogus data in the chaddr buffer, and we accept
619 that data in the lease file rather than simply failing on such
622 token
= peek_token (&val
, (unsigned *)0, cfile
);
624 hardware
-> hlen
= 1;
627 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
630 hardware
-> hlen
= 1;
633 if (hlen
+ 1 > sizeof hardware
-> hbuf
) {
635 parse_warn (cfile
, "hardware address too long");
637 hardware
-> hlen
= hlen
+ 1;
638 memcpy ((unsigned char *)&hardware
-> hbuf
[1], t
, hlen
);
639 if (hlen
+ 1 < sizeof hardware
-> hbuf
)
640 memset (&hardware
-> hbuf
[hlen
+ 1], 0,
641 (sizeof hardware
-> hbuf
) - hlen
- 1);
646 token
= next_token (&val
, (unsigned *)0, cfile
);
648 parse_warn (cfile
, "expecting semicolon.");
649 skip_to_semi (cfile
);
653 /* lease-time :== NUMBER SEMI */
655 void parse_lease_time (cfile
, timep
)
660 enum dhcp_token token
;
663 token
= next_token (&val
, (unsigned *)0, cfile
);
664 if (token
!= NUMBER
) {
665 parse_warn (cfile
, "Expecting numeric lease time");
666 skip_to_semi (cfile
);
669 convert_num(cfile
, (unsigned char *)&num
, val
, 10, 32);
670 /* Unswap the number - convert_num returns stuff in NBO. */
676 /* No BNF for numeric aggregates - that's defined by the caller. What
677 this function does is to parse a sequence of numbers separated by
678 the token specified in separator. If max is zero, any number of
679 numbers will be parsed; otherwise, exactly max numbers are
680 expected. Base and size tell us how to internalize the numbers
681 once they've been tokenized. */
683 unsigned char *parse_numeric_aggregate (cfile
, buf
,
684 max
, separator
, base
, size
)
693 enum dhcp_token token
;
694 unsigned char *bufp
= buf
, *s
, *t
;
699 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
701 log_fatal ("no space for numeric aggregate");
708 token
= peek_token (&val
, (unsigned *)0, cfile
);
709 if (token
!= separator
) {
712 if (token
!= RBRACE
&& token
!= LBRACE
)
713 token
= next_token (&val
,
716 parse_warn (cfile
, "too few numbers.");
718 skip_to_semi (cfile
);
719 return (unsigned char *)0;
721 token
= next_token (&val
, (unsigned *)0, cfile
);
723 token
= next_token (&val
, (unsigned *)0, cfile
);
725 if (token
== END_OF_FILE
) {
726 parse_warn (cfile
, "unexpected end of file");
730 /* Allow NUMBER_OR_NAME if base is 16. */
731 if (token
!= NUMBER
&&
732 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
733 parse_warn (cfile
, "expecting numeric value.");
734 skip_to_semi (cfile
);
735 return (unsigned char *)0;
737 /* If we can, convert the number now; otherwise, build
738 a linked list of all the numbers. */
740 convert_num (cfile
, s
, val
, base
, size
);
743 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
745 log_fatal ("no temp space for number.");
746 strcpy ((char *)t
, val
);
747 c
= cons ((caddr_t
)t
, c
);
749 } while (++count
!= *max
);
751 /* If we had to cons up a list, convert it now. */
753 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
755 log_fatal ("no space for numeric aggregate.");
756 s
= bufp
+ count
- size
/ 8;
761 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
763 /* Free up temp space. */
764 dfree (c
-> car
, MDL
);
771 void convert_num (cfile
, buf
, str
, base
, size
)
778 const unsigned char *ptr
= (const unsigned char *)str
;
789 /* If base wasn't specified, figure it out from the data. */
791 if (ptr
[0] == '0') {
792 if (ptr
[1] == 'x') {
795 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
808 /* XXX assumes ASCII... */
810 tval
= tval
- 'a' + 10;
811 else if (tval
>= 'A')
812 tval
= tval
- 'A' + 10;
813 else if (tval
>= '0')
816 parse_warn (cfile
, "Bogus number: %s.", str
);
821 "Bogus number %s: digit %d not in base %d",
825 val
= val
* base
+ tval
;
829 max
= (1 << (size
- 1));
831 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
836 "%s%lo exceeds max (%d) for precision.",
838 (unsigned long)val
, max
);
842 "%s%lx exceeds max (%d) for precision.",
844 (unsigned long)val
, max
);
848 "%s%lu exceeds max (%d) for precision.",
850 (unsigned long)val
, max
);
858 *buf
= -(unsigned long)val
;
861 putShort (buf
, -(long)val
);
864 putLong (buf
, -(long)val
);
868 "Unexpected integer size: %d\n", size
);
874 *buf
= (u_int8_t
)val
;
877 putUShort (buf
, (u_int16_t
)val
);
884 "Unexpected integer size: %d\n", size
);
891 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
892 * NUMBER COLON NUMBER COLON NUMBER SEMI |
893 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
894 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
897 * Dates are stored in UTC or with a timezone offset; first number is day
898 * of week; next is year/month/day; next is hours:minutes:seconds on a
899 * 24-hour clock, followed by the timezone offset in seconds, which is
903 /* just parse the date */
905 parse_date_core(cfile
)
909 int tzoff
, wday
, year
, mon
, mday
, hour
, min
, sec
;
911 enum dhcp_token token
;
912 static int months
[11] = { 31, 59, 90, 120, 151, 181,
913 212, 243, 273, 304, 334 };
915 /* Day of week, or "never"... */
916 token
= next_token (&val
, (unsigned *)0, cfile
);
917 if (token
== NEVER
) {
918 if (!parse_semi (cfile
))
923 /* This indicates 'local' time format. */
924 if (token
== EPOCH
) {
925 token
= next_token(&val
, NULL
, cfile
);
927 if (token
!= NUMBER
) {
928 parse_warn(cfile
, "Seconds since epoch expected.");
936 if (!parse_semi(cfile
))
942 if (token
!= NUMBER
) {
943 parse_warn (cfile
, "numeric day of week expected.");
945 skip_to_semi (cfile
);
951 token
= next_token (&val
, (unsigned *)0, cfile
);
952 if (token
!= NUMBER
) {
953 parse_warn (cfile
, "numeric year expected.");
955 skip_to_semi (cfile
);
959 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
960 somebody invents a time machine, I think we can safely disregard
961 it. This actually works around a stupid Y2K bug that was present
962 in a very early beta release of dhcpd. */
967 /* Slash separating year from month... */
968 token
= next_token (&val
, (unsigned *)0, cfile
);
969 if (token
!= SLASH
) {
971 "expected slash separating year from month.");
973 skip_to_semi (cfile
);
978 token
= next_token (&val
, (unsigned *)0, cfile
);
979 if (token
!= NUMBER
) {
980 parse_warn (cfile
, "numeric month expected.");
982 skip_to_semi (cfile
);
985 mon
= atoi (val
) - 1;
987 /* Slash separating month from day... */
988 token
= next_token (&val
, (unsigned *)0, cfile
);
989 if (token
!= SLASH
) {
991 "expected slash separating month from day.");
993 skip_to_semi (cfile
);
997 /* Day of month... */
998 token
= next_token (&val
, (unsigned *)0, cfile
);
999 if (token
!= NUMBER
) {
1000 parse_warn (cfile
, "numeric day of month expected.");
1002 skip_to_semi (cfile
);
1008 token
= next_token (&val
, (unsigned *)0, cfile
);
1009 if (token
!= NUMBER
) {
1010 parse_warn (cfile
, "numeric hour expected.");
1012 skip_to_semi (cfile
);
1017 /* Colon separating hour from minute... */
1018 token
= next_token (&val
, (unsigned *)0, cfile
);
1019 if (token
!= COLON
) {
1021 "expected colon separating hour from minute.");
1023 skip_to_semi (cfile
);
1028 token
= next_token (&val
, (unsigned *)0, cfile
);
1029 if (token
!= NUMBER
) {
1030 parse_warn (cfile
, "numeric minute expected.");
1032 skip_to_semi (cfile
);
1037 /* Colon separating minute from second... */
1038 token
= next_token (&val
, (unsigned *)0, cfile
);
1039 if (token
!= COLON
) {
1041 "expected colon separating minute from second.");
1043 skip_to_semi (cfile
);
1048 token
= next_token (&val
, (unsigned *)0, cfile
);
1049 if (token
!= NUMBER
) {
1050 parse_warn (cfile
, "numeric second expected.");
1052 skip_to_semi (cfile
);
1057 token
= peek_token (&val
, (unsigned *)0, cfile
);
1058 if (token
== NUMBER
) {
1059 token
= next_token (&val
, (unsigned *)0, cfile
);
1064 /* Guess the time value... */
1065 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
1066 (year
- 69) / 4 + /* Leap days since '70 */
1067 (mon
/* Days in months this year */
1070 (mon
> 1 && /* Leap day this year */
1071 !((year
- 72) & 3)) +
1072 mday
- 1) * 24) + /* Day of month */
1074 min
) * 60) + sec
+ tzoff
;
1076 /* This guess could be wrong because of leap seconds or other
1077 weirdness we don't know about that the system does. For
1078 now, we're just going to accept the guess, but at some point
1079 it might be nice to do a successive approximation here to
1080 get an exact value. Even if the error is small, if the
1081 server is restarted frequently (and thus the lease database
1082 is reread), the error could accumulate into something
1088 /* Wrapper to consume the semicolon after the date */
1091 struct parse
*cfile
;
1094 guess
= parse_date_core(cfile
);
1096 /* Make sure the date ends in a semicolon... */
1097 if (!parse_semi(cfile
))
1105 * option-name :== IDENTIFIER |
1106 IDENTIFIER . IDENTIFIER
1110 parse_option_name (cfile
, allocate
, known
, opt
)
1111 struct parse
*cfile
;
1114 struct option
**opt
;
1117 enum dhcp_token token
;
1119 struct universe
*universe
;
1120 struct option
*option
;
1124 return ISC_R_INVALIDARG
;
1126 token
= next_token (&val
, (unsigned *)0, cfile
);
1127 if (!is_identifier (token
)) {
1129 "expecting identifier after option keyword.");
1131 skip_to_semi (cfile
);
1132 return ISC_R_BADPARSE
;
1134 uname
= dmalloc (strlen (val
) + 1, MDL
);
1136 log_fatal ("no memory for uname information.");
1137 strcpy (uname
, val
);
1138 token
= peek_token (&val
, (unsigned *)0, cfile
);
1140 /* Go ahead and take the DOT token... */
1141 token
= next_token (&val
, (unsigned *)0, cfile
);
1143 /* The next token should be an identifier... */
1144 token
= next_token (&val
, (unsigned *)0, cfile
);
1145 if (!is_identifier (token
)) {
1146 parse_warn (cfile
, "expecting identifier after '.'");
1148 skip_to_semi (cfile
);
1149 return ISC_R_BADPARSE
;
1152 /* Look up the option name hash table for the specified
1154 universe
= (struct universe
*)0;
1155 if (!universe_hash_lookup (&universe
, universe_hash
,
1157 parse_warn (cfile
, "no option space named %s.", uname
);
1158 skip_to_semi (cfile
);
1159 return ISC_R_NOTFOUND
;
1162 /* Use the default hash table, which contains all the
1163 standard dhcp option names. */
1165 universe
= &dhcp_universe
;
1168 /* Look up the actual option info... */
1169 option_name_hash_lookup(opt
, universe
->name_hash
, val
, 0, MDL
);
1172 /* If we didn't get an option structure, it's an undefined option. */
1176 /* If the option name is of the form unknown-[decimal], use
1177 * the trailing decimal value to find the option definition.
1178 * If there is no definition, construct one. This is to
1179 * support legacy use of unknown options in config files or
1182 } else if (strncasecmp(val
, "unknown-", 8) == 0) {
1185 /* Option code 0 is always illegal for us, thanks
1186 * to the option decoder.
1188 if (code
== 0 || code
== universe
->end
) {
1189 parse_warn(cfile
, "Option codes 0 and %u are illegal "
1190 "in the %s space.", universe
->end
,
1192 skip_to_semi(cfile
);
1194 return ISC_R_FAILURE
;
1197 /* It's odd to think of unknown option codes as
1198 * being known, but this means we know what the
1199 * parsed name is talking about.
1204 option_code_hash_lookup(opt
, universe
->code_hash
,
1208 /* If we did not find an option of that code,
1209 * manufacture an unknown-xxx option definition.
1210 * Its single reference will ensure that it is
1211 * deleted once the option is recycled out of
1212 * existence (by the parent).
1214 if (option
== NULL
) {
1215 option
= new_option(val
, MDL
);
1216 option
->universe
= universe
;
1217 option
->code
= code
;
1218 option
->format
= default_option_format
;
1219 option_reference(opt
, option
, MDL
);
1221 log_info("option %s has been redefined as option %s. "
1222 "Please update your configs if neccessary.",
1224 /* If we've been told to allocate, that means that this
1225 * (might) be an option code definition, so we'll create
1226 * an option structure and return it for the parent to
1229 } else if (allocate
) {
1230 option
= new_option(val
, MDL
);
1231 option
-> universe
= universe
;
1232 option_reference(opt
, option
, MDL
);
1234 parse_warn(cfile
, "no option named %s in space %s",
1235 val
, universe
->name
);
1236 skip_to_semi (cfile
);
1238 return ISC_R_NOTFOUND
;
1241 /* Free the initial identifier token. */
1243 return ISC_R_SUCCESS
;
1246 /* IDENTIFIER [WIDTHS] SEMI
1247 * WIDTHS ~= LENGTH WIDTH NUMBER
1251 void parse_option_space_decl (cfile
)
1252 struct parse
*cfile
;
1256 struct universe
**ua
, *nu
;
1258 int tsize
=1, lsize
=1, hsize
= 0;
1260 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
1261 which was checked by the
1263 token
= next_token (&val
, (unsigned *)0, cfile
);
1264 if (!is_identifier (token
)) {
1265 parse_warn (cfile
, "expecting identifier.");
1266 skip_to_semi (cfile
);
1269 nu
= new_universe (MDL
);
1271 log_fatal ("No memory for new option space.");
1273 /* Set up the server option universe... */
1274 nu_name
= dmalloc (strlen (val
) + 1, MDL
);
1276 log_fatal ("No memory for new option space name.");
1277 strcpy (nu_name
, val
);
1278 nu
-> name
= nu_name
;
1281 token
= next_token(&val
, NULL
, cfile
);
1287 token
= next_token(&val
, NULL
, cfile
);
1288 if (token
!= WIDTH
) {
1289 parse_warn(cfile
, "expecting width token.");
1293 token
= next_token(&val
, NULL
, cfile
);
1294 if (token
!= NUMBER
) {
1295 parse_warn(cfile
, "expecting number 1, 2, 4.");
1305 hsize
= BYTE_NAME_HASH_SIZE
;
1309 hsize
= WORD_NAME_HASH_SIZE
;
1313 hsize
= QUAD_NAME_HASH_SIZE
;
1316 parse_warn(cfile
, "invalid code width (%d), "
1317 "expecting a 1, 2 or 4.",
1324 token
= next_token(&val
, NULL
, cfile
);
1325 if (token
!= WIDTH
) {
1326 parse_warn(cfile
, "expecting width token.");
1330 token
= next_token(&val
, NULL
, cfile
);
1331 if (token
!= NUMBER
) {
1332 parse_warn(cfile
, "expecting number 1 or 2.");
1337 if (lsize
!= 1 && lsize
!= 2) {
1338 parse_warn(cfile
, "invalid length width (%d) "
1339 "expecting 1 or 2.", lsize
);
1346 token
= next_token(&val
, NULL
, cfile
);
1347 if (token
!= SIZE
) {
1348 parse_warn(cfile
, "expecting size token.");
1352 token
= next_token(&val
, NULL
, cfile
);
1353 if (token
!= NUMBER
) {
1354 parse_warn(cfile
, "expecting a 10base number");
1358 /* (2^31)-1 is the highest Mersenne prime we should
1362 if (hsize
< 0 || hsize
> 0x7FFFFFFF) {
1363 parse_warn(cfile
, "invalid hash length: %d",
1371 parse_warn(cfile
, "Unexpected token.");
1373 } while (token
!= SEMI
);
1376 hsize
= DEFAULT_SPACE_HASH_SIZE
;
1378 nu
-> lookup_func
= lookup_hashed_option
;
1379 nu
-> option_state_dereference
= hashed_option_state_dereference
;
1380 nu
-> foreach
= hashed_option_space_foreach
;
1381 nu
-> save_func
= save_hashed_option
;
1382 nu
-> delete_func
= delete_hashed_option
;
1383 nu
-> encapsulate
= hashed_option_space_encapsulate
;
1384 nu
-> decode
= parse_option_buffer
;
1385 nu
-> length_size
= lsize
;
1386 nu
-> tag_size
= tsize
;
1389 nu
->get_tag
= getUChar
;
1390 nu
->store_tag
= putUChar
;
1393 nu
->get_tag
= getUShort
;
1394 nu
->store_tag
= putUShort
;
1397 nu
->get_tag
= getULong
;
1398 nu
->store_tag
= putULong
;
1401 log_fatal("Impossible condition at %s:%d.", MDL
);
1405 nu
->get_length
= NULL
;
1406 nu
->store_length
= NULL
;
1409 nu
->get_length
= getUChar
;
1410 nu
->store_length
= putUChar
;
1413 nu
->get_length
= getUShort
;
1414 nu
->store_length
= putUShort
;
1417 log_fatal("Impossible condition at %s:%d.", MDL
);
1419 nu
-> index
= universe_count
++;
1420 if (nu
-> index
>= universe_max
) {
1421 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
1423 log_fatal ("No memory to expand option space array.");
1424 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
1426 dfree (universes
, MDL
);
1429 universes
[nu
-> index
] = nu
;
1430 if (!option_name_new_hash(&nu
->name_hash
, hsize
, MDL
) ||
1431 !option_code_new_hash(&nu
->code_hash
, hsize
, MDL
))
1432 log_fatal("Can't allocate %s option hash table.", nu
->name
);
1433 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
1437 dfree(nu_name
, MDL
);
1441 /* This is faked up to look good right now. Ideally, this should do a
1442 recursive parse and allow arbitrary data structure definitions, but for
1443 now it just allows you to specify a single type, an array of single types,
1444 a sequence of types, or an array of sequences of types.
1446 ocd :== NUMBER EQUALS ocsd SEMI
1448 ocsd :== ocsd_type |
1449 ocsd_type_sequence |
1450 ARRAY OF ocsd_simple_type_sequence
1452 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1454 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1456 ocsd_types :== ocsd_type |
1457 ocsd_types ocsd_type
1459 ocsd_type :== ocsd_simple_type |
1460 ARRAY OF ocsd_simple_type
1462 ocsd_simple_types :== ocsd_simple_type |
1463 ocsd_simple_types ocsd_simple_type
1465 ocsd_simple_type :== BOOLEAN |
1467 SIGNED INTEGER NUMBER |
1468 UNSIGNED INTEGER NUMBER |
1472 ENCAPSULATE identifier */
1474 int parse_option_code_definition (cfile
, option
)
1475 struct parse
*cfile
;
1476 struct option
*option
;
1479 enum dhcp_token token
;
1480 struct option
*oldopt
;
1481 unsigned arrayp
= 0;
1483 int no_more_in_record
= 0;
1489 int has_encapsulation
= 0;
1490 struct universe
*encapsulated
;
1492 /* Parse the option code. */
1493 token
= next_token (&val
, (unsigned *)0, cfile
);
1494 if (token
!= NUMBER
) {
1495 parse_warn (cfile
, "expecting option code number.");
1496 skip_to_semi (cfile
);
1499 option
-> code
= atoi (val
);
1501 token
= next_token (&val
, (unsigned *)0, cfile
);
1502 if (token
!= EQUAL
) {
1503 parse_warn (cfile
, "expecting \"=\"");
1504 skip_to_semi (cfile
);
1508 /* See if this is an array. */
1509 token
= next_token (&val
, (unsigned *)0, cfile
);
1510 if (token
== ARRAY
) {
1511 token
= next_token (&val
, (unsigned *)0, cfile
);
1513 parse_warn (cfile
, "expecting \"of\".");
1514 skip_to_semi (cfile
);
1518 token
= next_token (&val
, (unsigned *)0, cfile
);
1521 if (token
== LBRACE
) {
1523 token
= next_token (&val
, (unsigned *)0, cfile
);
1526 /* At this point we're expecting a data type. */
1528 if (has_encapsulation
) {
1530 "encapsulate must always be the last item.");
1531 skip_to_semi (cfile
);
1538 parse_warn (cfile
, "no nested arrays.");
1539 skip_to_rbrace (cfile
, recordp
);
1541 skip_to_semi (cfile
);
1544 token
= next_token (&val
, (unsigned *)0, cfile
);
1546 parse_warn (cfile
, "expecting \"of\".");
1547 skip_to_semi (cfile
);
1550 arrayp
= recordp
+ 1;
1551 token
= next_token (&val
, (unsigned *)0, cfile
);
1552 if ((recordp
) && (token
== LBRACE
)) {
1554 "only uniform array inside record.");
1555 skip_to_rbrace (cfile
, recordp
+ 1);
1556 skip_to_semi (cfile
);
1566 token
= next_token (&val
, (unsigned *)0, cfile
);
1567 if (token
!= NUMBER
) {
1568 parse_warn (cfile
, "expecting number.");
1569 skip_to_rbrace (cfile
, recordp
);
1571 skip_to_semi (cfile
);
1574 switch (atoi (val
)) {
1576 type
= is_signed
? 'b' : 'B';
1579 type
= is_signed
? 's' : 'S';
1582 type
= is_signed
? 'l' : 'L';
1586 "%s bit precision is not supported.", val
);
1587 skip_to_rbrace (cfile
, recordp
);
1589 skip_to_semi (cfile
);
1596 token
= next_token (&val
, (unsigned *)0, cfile
);
1597 if (token
!= INTEGER
) {
1598 parse_warn (cfile
, "expecting \"integer\" keyword.");
1599 skip_to_rbrace (cfile
, recordp
);
1601 skip_to_semi (cfile
);
1619 /* Consume optional compression indicator. */
1620 token
= peek_token(&val
, NULL
, cfile
);
1621 if (token
== COMPRESSED
) {
1622 token
= next_token(&val
, NULL
, cfile
);
1623 tokbuf
[tokix
++] = 'D';
1632 parse_warn (cfile
, "arrays of text strings not %s",
1634 skip_to_rbrace (cfile
, recordp
);
1636 skip_to_semi (cfile
);
1639 no_more_in_record
= 1;
1646 token
= next_token (&val
, (unsigned *)0, cfile
);
1647 if (!is_identifier (token
)) {
1649 "expecting option space identifier");
1650 skip_to_semi (cfile
);
1653 encapsulated
= NULL
;
1654 if (!universe_hash_lookup(&encapsulated
, universe_hash
,
1655 val
, strlen(val
), MDL
)) {
1656 parse_warn(cfile
, "unknown option space %s", val
);
1657 skip_to_semi (cfile
);
1660 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1662 tokbuf
[tokix
++] = 'E';
1663 strcpy (&tokbuf
[tokix
], val
);
1664 tokix
+= strlen (val
);
1666 has_encapsulation
= 1;
1672 parse_warn (cfile
, "array incompatible with zerolen.");
1673 skip_to_rbrace (cfile
, recordp
);
1675 skip_to_semi (cfile
);
1678 no_more_in_record
= 1;
1682 parse_warn (cfile
, "unknown data type %s", val
);
1683 skip_to_rbrace (cfile
, recordp
);
1685 skip_to_semi (cfile
);
1689 if (tokix
== sizeof tokbuf
) {
1691 parse_warn (cfile
, "too many types in record.");
1692 skip_to_rbrace (cfile
, recordp
);
1694 skip_to_semi (cfile
);
1697 tokbuf
[tokix
++] = type
;
1700 token
= next_token (&val
, (unsigned *)0, cfile
);
1701 if (arrayp
> recordp
) {
1702 if (tokix
== sizeof tokbuf
) {
1704 "too many types in record.");
1705 skip_to_rbrace (cfile
, 1);
1706 skip_to_semi (cfile
);
1710 tokbuf
[tokix
++] = 'a';
1712 if (token
== COMMA
) {
1713 if (no_more_in_record
) {
1715 "%s must be at end of record.",
1716 type
== 't' ? "text" : "string");
1717 skip_to_rbrace (cfile
, 1);
1719 skip_to_semi (cfile
);
1722 token
= next_token (&val
, (unsigned *)0, cfile
);
1725 if (token
!= RBRACE
) {
1726 parse_warn (cfile
, "expecting right brace.");
1727 skip_to_rbrace (cfile
, 1);
1729 skip_to_semi (cfile
);
1733 if (!parse_semi (cfile
)) {
1734 parse_warn (cfile
, "semicolon expected.");
1735 skip_to_semi (cfile
);
1737 skip_to_semi (cfile
);
1740 if (has_encapsulation
&& arrayp
) {
1742 "Arrays of encapsulations don't make sense.");
1745 s
= dmalloc(tokix
+ (arrayp
? 1 : 0) + 1, MDL
);
1747 log_fatal("no memory for option format.");
1749 memcpy(s
, tokbuf
, tokix
);
1751 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1755 option
-> format
= s
;
1758 option_code_hash_lookup(&oldopt
, option
->universe
->code_hash
,
1759 &option
->code
, 0, MDL
);
1761 option_name_hash_delete(option
->universe
->name_hash
,
1762 oldopt
->name
, 0, MDL
);
1763 option_code_hash_delete(option
->universe
->code_hash
,
1764 &oldopt
->code
, 0, MDL
);
1766 option_dereference(&oldopt
, MDL
);
1768 option_code_hash_add(option
->universe
->code_hash
, &option
->code
, 0,
1770 option_name_hash_add(option
->universe
->name_hash
, option
->name
, 0,
1772 if (has_encapsulation
) {
1773 /* INSIST(tokbuf[0] == 'E'); */
1774 /* INSIST(encapsulated != NULL); */
1775 if (!option_code_hash_lookup(&encapsulated
->enc_opt
,
1776 option
->universe
->code_hash
,
1777 &option
->code
, 0, MDL
)) {
1778 log_fatal("error finding encapsulated option (%s:%d)",
1786 * base64 :== NUMBER_OR_STRING
1789 int parse_base64 (data
, cfile
)
1790 struct data_string
*data
;
1791 struct parse
*cfile
;
1793 enum dhcp_token token
;
1797 static unsigned char
1798 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1799 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1800 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1801 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1802 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1803 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1804 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1805 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1806 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1807 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1808 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1809 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1810 struct string_list
*bufs
= (struct string_list
*)0,
1811 *last
= (struct string_list
*)0,
1816 /* It's possible for a + or a / to cause a base64 quantity to be
1817 tokenized into more than one token, so we have to parse them all
1818 in before decoding. */
1822 token
= next_token (&val
, &l
, cfile
);
1823 t
= dmalloc (l
+ sizeof *t
, MDL
);
1825 log_fatal ("no memory for base64 buffer.");
1826 memset (t
, 0, (sizeof *t
) - 1);
1827 memcpy (t
-> string
, val
, l
+ 1);
1834 token
= peek_token (&val
, (unsigned *)0, cfile
);
1835 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1836 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1840 data
-> len
= (data
-> len
* 3) / 4;
1841 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1842 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1844 data
-> data
= (unsigned char *)0;
1849 for (t
= bufs
; t
; t
= t
-> next
) {
1850 for (i
= 0; t
-> string
[i
]; i
++) {
1851 unsigned foo
= t
-> string
[i
];
1852 if (terminated
&& foo
!= '=') {
1854 "stuff after base64 '=' terminator: %s.",
1858 if (foo
< ' ' || foo
> 'z') {
1861 "invalid base64 character %d.",
1864 data_string_forget (data
, MDL
);
1870 foo
= from64
[foo
- ' '];
1873 acc
= (acc
<< 6) + foo
;
1878 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1883 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1887 data
-> buffer
-> data
[j
++] = acc
;
1898 "partial base64 value left over: %d.",
1903 data
-> data
= data
-> buffer
-> data
;
1905 for (t
= bufs
; t
; t
= last
) {
1917 * colon-separated-hex-list :== NUMBER |
1918 * NUMBER COLON colon-separated-hex-list
1921 int parse_cshl (data
, cfile
)
1922 struct data_string
*data
;
1923 struct parse
*cfile
;
1925 u_int8_t ibuf
[128];
1928 struct option_tag
*sl
= (struct option_tag
*)0;
1929 struct option_tag
*next
, **last
= &sl
;
1930 enum dhcp_token token
;
1935 token
= next_token (&val
, (unsigned *)0, cfile
);
1936 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1937 parse_warn (cfile
, "expecting hexadecimal number.");
1938 skip_to_semi (cfile
);
1939 for (; sl
; sl
= next
) {
1945 if (ilen
== sizeof ibuf
) {
1946 next
= (struct option_tag
*)
1948 sizeof (struct option_tag
), MDL
);
1950 log_fatal ("no memory for string list.");
1951 memcpy (next
-> data
, ibuf
, ilen
);
1953 last
= &next
-> next
;
1957 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1959 token
= peek_token (&val
, (unsigned *)0, cfile
);
1962 token
= next_token (&val
, (unsigned *)0, cfile
);
1965 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1966 log_fatal ("no memory to store octet data.");
1967 data
-> data
= &data
-> buffer
-> data
[0];
1968 data
-> len
= tlen
+ ilen
;
1969 data
-> terminated
= 0;
1971 rvp
= &data
-> buffer
-> data
[0];
1974 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
1980 memcpy (rvp
, ibuf
, ilen
);
1985 * executable-statements :== executable-statement executable-statements |
1986 * executable-statement
1988 * executable-statement :==
1990 * ADD class-name SEMI |
1992 * OPTION option-parameter SEMI |
1993 * SUPERSEDE option-parameter SEMI |
1994 * PREPEND option-parameter SEMI |
1995 * APPEND option-parameter SEMI
1998 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
1999 struct executable_statement
**statements
;
2000 struct parse
*cfile
;
2002 enum expression_context case_context
;
2004 struct executable_statement
**next
;
2007 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
2008 next
= &((*next
) -> next
);
2014 int parse_executable_statement (result
, cfile
, lose
, case_context
)
2015 struct executable_statement
**result
;
2016 struct parse
*cfile
;
2018 enum expression_context case_context
;
2020 #if defined(ENABLE_EXECUTE)
2022 struct expression
**ep
;
2024 enum dhcp_token token
;
2027 struct option
*option
=NULL
;
2028 struct option_cache
*cache
;
2032 struct dns_zone
*zone
;
2033 isc_result_t status
;
2036 token
= peek_token (&val
, (unsigned *)0, cfile
);
2038 case DB_TIME_FORMAT
:
2039 next_token(&val
, NULL
, cfile
);
2041 token
= next_token(&val
, NULL
, cfile
);
2042 if (token
== DEFAULT
) {
2043 db_time_format
= DEFAULT_TIME_FORMAT
;
2044 } else if (token
== LOCAL
) {
2045 db_time_format
= LOCAL_TIME_FORMAT
;
2047 parse_warn(cfile
, "Expecting 'local' or 'default'.");
2049 skip_to_semi(cfile
);
2054 token
= next_token(&val
, NULL
, cfile
);
2055 if (token
!= SEMI
) {
2056 parse_warn(cfile
, "Expecting a semicolon.");
2061 /* We're done here. */
2065 next_token (&val
, (unsigned *)0, cfile
);
2066 return parse_if_statement (result
, cfile
, lose
);
2069 token
= next_token (&val
, (unsigned *)0, cfile
);
2070 token
= next_token (&val
, (unsigned *)0, cfile
);
2071 if (token
!= STRING
) {
2072 parse_warn (cfile
, "expecting class name.");
2073 skip_to_semi (cfile
);
2077 cta
= (struct class *)0;
2078 status
= find_class (&cta
, val
, MDL
);
2079 if (status
!= ISC_R_SUCCESS
) {
2080 parse_warn (cfile
, "class %s: %s",
2081 val
, isc_result_totext (status
));
2082 skip_to_semi (cfile
);
2086 if (!parse_semi (cfile
)) {
2090 if (!executable_statement_allocate (result
, MDL
))
2091 log_fatal ("no memory for new statement.");
2092 (*result
) -> op
= add_statement
;
2093 (*result
) -> data
.add
= cta
;
2097 token
= next_token (&val
, (unsigned *)0, cfile
);
2098 if (!parse_semi (cfile
)) {
2102 if (!executable_statement_allocate (result
, MDL
))
2103 log_fatal ("no memory for new statement.");
2104 (*result
) -> op
= break_statement
;
2108 token
= next_token (&val
, (unsigned *)0, cfile
);
2110 status
= parse_option_name (cfile
, 0, &known
, &option
);
2111 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2115 status
= parse_option_statement(result
, cfile
, 1, option
,
2116 send_option_statement
);
2117 option_dereference(&option
, MDL
);
2122 token
= next_token (&val
, (unsigned *)0, cfile
);
2124 status
= parse_option_name (cfile
, 0, &known
, &option
);
2125 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2129 status
= parse_option_statement(result
, cfile
, 1, option
,
2130 supersede_option_statement
);
2131 option_dereference(&option
, MDL
);
2143 token
= next_token (&val
, (unsigned *)0, cfile
);
2144 cache
= (struct option_cache
*)0;
2145 if (!parse_allow_deny (&cache
, cfile
, flag
))
2147 if (!executable_statement_allocate (result
, MDL
))
2148 log_fatal ("no memory for new statement.");
2149 (*result
) -> op
= supersede_option_statement
;
2150 (*result
) -> data
.option
= cache
;
2154 token
= next_token (&val
, (unsigned *)0, cfile
);
2155 token
= peek_token (&val
, (unsigned *)0, cfile
);
2157 goto switch_default
;
2159 status
= parse_option_name (cfile
, 0, &known
, &option
);
2160 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2164 status
= parse_option_statement(result
, cfile
, 1, option
,
2165 default_option_statement
);
2166 option_dereference(&option
, MDL
);
2170 token
= next_token (&val
, (unsigned *)0, cfile
);
2172 status
= parse_option_name (cfile
, 0, &known
, &option
);
2173 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2177 status
= parse_option_statement(result
, cfile
, 1, option
,
2178 prepend_option_statement
);
2179 option_dereference(&option
, MDL
);
2183 token
= next_token (&val
, (unsigned *)0, cfile
);
2185 status
= parse_option_name (cfile
, 0, &known
, &option
);
2186 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2190 status
= parse_option_statement(result
, cfile
, 1, option
,
2191 append_option_statement
);
2192 option_dereference(&option
, MDL
);
2196 token
= next_token (&val
, (unsigned *)0, cfile
);
2197 return parse_on_statement (result
, cfile
, lose
);
2200 token
= next_token (&val
, (unsigned *)0, cfile
);
2201 return parse_switch_statement (result
, cfile
, lose
);
2204 token
= next_token (&val
, (unsigned *)0, cfile
);
2205 if (case_context
== context_any
) {
2207 "case statement in inappropriate scope.");
2209 skip_to_semi (cfile
);
2212 return parse_case_statement (result
,
2213 cfile
, lose
, case_context
);
2216 token
= next_token (&val
, (unsigned *)0, cfile
);
2217 if (case_context
== context_any
) {
2218 parse_warn (cfile
, "switch default statement in %s",
2219 "inappropriate scope.");
2224 if (!executable_statement_allocate (result
, MDL
))
2225 log_fatal ("no memory for default statement.");
2226 (*result
) -> op
= default_statement
;
2232 token
= next_token (&val
, (unsigned *)0, cfile
);
2233 if (token
== DEFINE
)
2238 token
= next_token (&val
, (unsigned *)0, cfile
);
2239 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2241 "%s can't be a variable name", val
);
2243 skip_to_semi (cfile
);
2248 if (!executable_statement_allocate (result
, MDL
))
2249 log_fatal ("no memory for set statement.");
2250 (*result
) -> op
= flag
? define_statement
: set_statement
;
2251 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
2252 if (!(*result
)->data
.set
.name
)
2253 log_fatal ("can't allocate variable name");
2254 strcpy ((*result
) -> data
.set
.name
, val
);
2255 token
= next_token (&val
, (unsigned *)0, cfile
);
2257 if (token
== LPAREN
) {
2258 struct string_list
*head
, *cur
, *new;
2259 struct expression
*expr
;
2260 head
= cur
= (struct string_list
*)0;
2262 token
= next_token (&val
,
2263 (unsigned *)0, cfile
);
2264 if (token
== RPAREN
)
2266 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2268 "expecting argument name");
2269 skip_to_rbrace (cfile
, 0);
2271 executable_statement_dereference
2275 new = ((struct string_list
*)
2276 dmalloc (sizeof (struct string_list
) +
2277 strlen (val
), MDL
));
2279 log_fatal ("can't allocate string.");
2280 memset (new, 0, sizeof *new);
2281 strcpy (new -> string
, val
);
2288 token
= next_token (&val
,
2289 (unsigned *)0, cfile
);
2290 } while (token
== COMMA
);
2292 if (token
!= RPAREN
) {
2293 parse_warn (cfile
, "expecting right paren.");
2295 skip_to_semi (cfile
);
2297 executable_statement_dereference (result
, MDL
);
2301 token
= next_token (&val
, (unsigned *)0, cfile
);
2302 if (token
!= LBRACE
) {
2303 parse_warn (cfile
, "expecting left brace.");
2307 expr
= (struct expression
*)0;
2308 if (!(expression_allocate (&expr
, MDL
)))
2309 log_fatal ("can't allocate expression.");
2310 expr
-> op
= expr_function
;
2311 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
2312 log_fatal ("can't allocate fundef.");
2313 expr
-> data
.func
-> args
= head
;
2314 (*result
) -> data
.set
.expr
= expr
;
2316 if (!(parse_executable_statements
2317 (&expr
-> data
.func
-> statements
, cfile
, lose
,
2323 token
= next_token (&val
, (unsigned *)0, cfile
);
2324 if (token
!= RBRACE
) {
2325 parse_warn (cfile
, "expecting rigt brace.");
2329 if (token
!= EQUAL
) {
2331 "expecting '=' in %s statement.",
2332 flag
? "define" : "set");
2336 if (!parse_expression (&(*result
) -> data
.set
.expr
,
2337 cfile
, lose
, context_any
,
2338 (struct expression
**)0,
2342 "expecting expression.");
2345 skip_to_semi (cfile
);
2346 executable_statement_dereference (result
, MDL
);
2349 if (!parse_semi (cfile
)) {
2351 executable_statement_dereference (result
, MDL
);
2358 token
= next_token (&val
, (unsigned *)0, cfile
);
2360 token
= next_token (&val
, (unsigned *)0, cfile
);
2361 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2363 "%s can't be a variable name", val
);
2364 skip_to_semi (cfile
);
2369 if (!executable_statement_allocate (result
, MDL
))
2370 log_fatal ("no memory for set statement.");
2371 (*result
) -> op
= unset_statement
;
2372 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
2373 if (!(*result
)->data
.unset
)
2374 log_fatal ("can't allocate variable name");
2375 strcpy ((*result
) -> data
.unset
, val
);
2376 if (!parse_semi (cfile
)) {
2378 executable_statement_dereference (result
, MDL
);
2384 token
= next_token (&val
, (unsigned *)0, cfile
);
2386 if (!executable_statement_allocate (result
, MDL
))
2387 log_fatal ("no memory for eval statement.");
2388 (*result
) -> op
= eval_statement
;
2390 if (!parse_expression (&(*result
) -> data
.eval
,
2391 cfile
, lose
, context_data
, /* XXX */
2392 (struct expression
**)0, expr_none
)) {
2395 "expecting data expression.");
2398 skip_to_semi (cfile
);
2399 executable_statement_dereference (result
, MDL
);
2402 if (!parse_semi (cfile
)) {
2404 executable_statement_dereference (result
, MDL
);
2409 #ifdef ENABLE_EXECUTE
2410 token
= next_token(&val
, NULL
, cfile
);
2412 if (!executable_statement_allocate (result
, MDL
))
2413 log_fatal ("no memory for execute statement.");
2414 (*result
)->op
= execute_statement
;
2416 token
= next_token(&val
, NULL
, cfile
);
2417 if (token
!= LPAREN
) {
2418 parse_warn(cfile
, "left parenthesis expected.");
2419 skip_to_semi(cfile
);
2424 token
= next_token(&val
, &len
, cfile
);
2425 if (token
!= STRING
) {
2426 parse_warn(cfile
, "Expecting a quoted string.");
2427 skip_to_semi(cfile
);
2432 (*result
)->data
.execute
.command
= dmalloc(len
+ 1, MDL
);
2433 if ((*result
)->data
.execute
.command
== NULL
)
2434 log_fatal("can't allocate command name");
2435 strcpy((*result
)->data
.execute
.command
, val
);
2437 ep
= &(*result
)->data
.execute
.arglist
;
2438 (*result
)->data
.execute
.argc
= 0;
2440 while((token
= next_token(&val
, NULL
, cfile
)) == COMMA
) {
2441 if (!expression_allocate(ep
, MDL
))
2442 log_fatal ("can't allocate expression");
2444 if (!parse_data_expression (&(*ep
) -> data
.arg
.val
,
2448 "expecting expression.");
2451 skip_to_semi(cfile
);
2455 ep
= &(*ep
)->data
.arg
.next
;
2456 (*result
)->data
.execute
.argc
++;
2459 if (token
!= RPAREN
) {
2460 parse_warn(cfile
, "right parenthesis expected.");
2461 skip_to_semi(cfile
);
2466 if (!parse_semi (cfile
)) {
2468 executable_statement_dereference (result
, MDL
);
2470 #else /* ! ENABLE_EXECUTE */
2471 parse_warn(cfile
, "define ENABLE_EXECUTE in site.h to "
2472 "enable execute(); expressions.");
2473 skip_to_semi(cfile
);
2476 #endif /* ENABLE_EXECUTE */
2480 token
= next_token (&val
, (unsigned *)0, cfile
);
2482 if (!executable_statement_allocate (result
, MDL
))
2483 log_fatal ("no memory for return statement.");
2484 (*result
) -> op
= return_statement
;
2486 if (!parse_expression (&(*result
) -> data
.retval
,
2487 cfile
, lose
, context_data
,
2488 (struct expression
**)0, expr_none
)) {
2491 "expecting data expression.");
2494 skip_to_semi (cfile
);
2495 executable_statement_dereference (result
, MDL
);
2498 if (!parse_semi (cfile
)) {
2500 executable_statement_dereference (result
, MDL
);
2506 token
= next_token (&val
, (unsigned *)0, cfile
);
2508 if (!executable_statement_allocate (result
, MDL
))
2509 log_fatal ("no memory for log statement.");
2510 (*result
) -> op
= log_statement
;
2512 token
= next_token (&val
, (unsigned *)0, cfile
);
2513 if (token
!= LPAREN
) {
2514 parse_warn (cfile
, "left parenthesis expected.");
2515 skip_to_semi (cfile
);
2520 token
= peek_token (&val
, (unsigned *)0, cfile
);
2522 if (token
== FATAL
) {
2523 (*result
) -> data
.log
.priority
= log_priority_fatal
;
2524 } else if (token
== ERROR
) {
2525 (*result
) -> data
.log
.priority
= log_priority_error
;
2526 } else if (token
== TOKEN_DEBUG
) {
2527 (*result
) -> data
.log
.priority
= log_priority_debug
;
2528 } else if (token
== INFO
) {
2529 (*result
) -> data
.log
.priority
= log_priority_info
;
2531 (*result
) -> data
.log
.priority
= log_priority_debug
;
2535 token
= next_token (&val
, (unsigned *)0, cfile
);
2536 token
= next_token (&val
, (unsigned *)0, cfile
);
2537 if (token
!= COMMA
) {
2538 parse_warn (cfile
, "comma expected.");
2539 skip_to_semi (cfile
);
2545 if (!(parse_data_expression
2546 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
2547 skip_to_semi (cfile
);
2552 token
= next_token (&val
, (unsigned *)0, cfile
);
2553 if (token
!= RPAREN
) {
2554 parse_warn (cfile
, "right parenthesis expected.");
2555 skip_to_semi (cfile
);
2560 token
= next_token (&val
, (unsigned *)0, cfile
);
2561 if (token
!= SEMI
) {
2562 parse_warn (cfile
, "semicolon expected.");
2563 skip_to_semi (cfile
);
2569 /* Not really a statement, but we parse it here anyway
2570 because it's appropriate for all DHCP agents with
2573 token
= next_token (&val
, (unsigned *)0, cfile
);
2574 zone
= (struct dns_zone
*)0;
2575 if (!dns_zone_allocate (&zone
, MDL
))
2576 log_fatal ("no memory for new zone.");
2577 zone
-> name
= parse_host_name (cfile
);
2578 if (!zone
-> name
) {
2579 parse_warn (cfile
, "expecting hostname.");
2582 skip_to_semi (cfile
);
2583 dns_zone_dereference (&zone
, MDL
);
2586 i
= strlen (zone
-> name
);
2587 if (zone
-> name
[i
- 1] != '.') {
2588 s
= dmalloc ((unsigned)i
+ 2, MDL
);
2590 parse_warn (cfile
, "no trailing '.' on zone");
2593 strcpy (s
, zone
-> name
);
2596 dfree (zone
-> name
, MDL
);
2599 if (!parse_zone (zone
, cfile
))
2601 status
= enter_dns_zone (zone
);
2602 if (status
!= ISC_R_SUCCESS
) {
2603 parse_warn (cfile
, "dns zone key %s: %s",
2604 zone
-> name
, isc_result_totext (status
));
2605 dns_zone_dereference (&zone
, MDL
);
2608 dns_zone_dereference (&zone
, MDL
);
2611 /* Also not really a statement, but same idea as above. */
2613 token
= next_token (&val
, (unsigned *)0, cfile
);
2614 if (!parse_key (cfile
)) {
2621 if (config_universe
&& is_identifier (token
)) {
2622 option
= (struct option
*)0;
2623 option_name_hash_lookup(&option
,
2624 config_universe
->name_hash
,
2627 token
= next_token (&val
,
2628 (unsigned *)0, cfile
);
2629 status
= parse_option_statement
2630 (result
, cfile
, 1, option
,
2631 supersede_option_statement
);
2632 option_dereference(&option
, MDL
);
2637 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2638 /* This is rather ugly. Since function calls are
2639 data expressions, fake up an eval statement. */
2640 if (!executable_statement_allocate (result
, MDL
))
2641 log_fatal ("no memory for eval statement.");
2642 (*result
) -> op
= eval_statement
;
2644 if (!parse_expression (&(*result
) -> data
.eval
,
2645 cfile
, lose
, context_data
,
2646 (struct expression
**)0,
2649 parse_warn (cfile
, "expecting "
2653 skip_to_semi (cfile
);
2654 executable_statement_dereference (result
, MDL
);
2657 if (!parse_semi (cfile
)) {
2659 executable_statement_dereference (result
, MDL
);
2672 /* zone-statements :== zone-statement |
2673 zone-statement zone-statements
2675 PRIMARY ip-addresses SEMI |
2676 SECONDARY ip-addresses SEMI |
2678 ip-addresses :== ip-addr-or-hostname |
2679 ip-addr-or-hostname COMMA ip-addresses
2680 key-reference :== KEY STRING |
2683 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2688 struct option_cache
*oc
;
2691 token
= next_token (&val
, (unsigned *)0, cfile
);
2692 if (token
!= LBRACE
) {
2693 parse_warn (cfile
, "expecting left brace");
2698 token
= peek_token (&val
, (unsigned *)0, cfile
);
2701 if (zone
-> primary
) {
2703 "more than one primary.");
2704 skip_to_semi (cfile
);
2707 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2708 log_fatal ("can't allocate primary option cache.");
2709 oc
= zone
-> primary
;
2713 if (zone
-> secondary
) {
2714 parse_warn (cfile
, "more than one secondary.");
2715 skip_to_semi (cfile
);
2718 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2719 log_fatal ("can't allocate secondary.");
2720 oc
= zone
-> secondary
;
2722 token
= next_token (&val
, (unsigned *)0, cfile
);
2724 struct expression
*expr
= (struct expression
*)0;
2725 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2727 "expecting IP addr or hostname.");
2728 skip_to_semi (cfile
);
2731 if (oc
-> expression
) {
2732 struct expression
*old
=
2733 (struct expression
*)0;
2734 expression_reference (&old
,
2737 expression_dereference (&oc
-> expression
,
2739 if (!make_concat (&oc
-> expression
,
2741 log_fatal ("no memory for concat.");
2742 expression_dereference (&expr
, MDL
);
2743 expression_dereference (&old
, MDL
);
2745 expression_reference (&oc
-> expression
,
2747 expression_dereference (&expr
, MDL
);
2749 token
= next_token (&val
, (unsigned *)0, cfile
);
2750 } while (token
== COMMA
);
2751 if (token
!= SEMI
) {
2752 parse_warn (cfile
, "expecting semicolon.");
2753 skip_to_semi (cfile
);
2759 token
= next_token (&val
, (unsigned *)0, cfile
);
2760 token
= peek_token (&val
, (unsigned *)0, cfile
);
2761 if (token
== STRING
) {
2762 token
= next_token (&val
, (unsigned *)0, cfile
);
2763 key_name
= (char *)0;
2765 key_name
= parse_host_name (cfile
);
2767 parse_warn (cfile
, "expecting key name.");
2768 skip_to_semi (cfile
);
2773 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2775 parse_warn (cfile
, "unknown key %s", val
);
2777 dfree (key_name
, MDL
);
2778 if (!parse_semi (cfile
))
2788 token
= next_token (&val
, (unsigned *)0, cfile
);
2789 if (token
!= RBRACE
) {
2790 parse_warn (cfile
, "expecting right brace.");
2796 /* key-statements :== key-statement |
2797 key-statement key-statements
2799 ALGORITHM host-name SEMI |
2800 secret-definition SEMI
2801 secret-definition :== SECRET base64val |
2804 int parse_key (struct parse
*cfile
)
2809 struct auth_key
*key
;
2810 struct data_string ds
;
2811 isc_result_t status
;
2814 key
= (struct auth_key
*)0;
2815 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2816 log_fatal ("no memory for key");
2818 token
= peek_token (&val
, (unsigned *)0, cfile
);
2819 if (token
== STRING
) {
2820 token
= next_token (&val
, (unsigned *)0, cfile
);
2821 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2823 log_fatal ("no memory for key name.");
2824 strcpy (key
-> name
, val
);
2827 key
-> name
= parse_host_name (cfile
);
2829 parse_warn (cfile
, "expecting key name.");
2830 skip_to_semi (cfile
);
2835 token
= next_token (&val
, (unsigned *)0, cfile
);
2836 if (token
!= LBRACE
) {
2837 parse_warn (cfile
, "expecting left brace");
2842 token
= next_token (&val
, (unsigned *)0, cfile
);
2845 if (key
-> algorithm
) {
2847 "key %s: too many algorithms",
2851 key
-> algorithm
= parse_host_name (cfile
);
2852 if (!key
-> algorithm
) {
2854 "expecting key algorithm name.");
2857 if (!parse_semi (cfile
))
2859 /* If the algorithm name isn't an FQDN, tack on
2860 the .SIG-ALG.REG.NET. domain. */
2861 s
= strrchr (key
-> algorithm
, '.');
2863 static char add
[] = ".SIG-ALG.REG.INT.";
2864 s
= dmalloc (strlen (key
-> algorithm
) +
2867 log_error ("no memory for key %s.",
2871 strcpy (s
, key
-> algorithm
);
2873 dfree (key
-> algorithm
, MDL
);
2874 key
-> algorithm
= s
;
2876 /* If there is no trailing '.', hack one in. */
2877 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2879 log_error ("no memory for key %s.",
2883 strcpy (s
, key
-> algorithm
);
2885 dfree (key
-> algorithm
, MDL
);
2886 key
-> algorithm
= s
;
2892 parse_warn (cfile
, "key %s: too many secrets",
2897 memset (&ds
, 0, sizeof(ds
));
2898 if (!parse_base64 (&ds
, cfile
))
2900 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2902 if (status
!= ISC_R_SUCCESS
)
2904 memcpy (key
-> key
-> value
,
2905 ds
.buffer
-> data
, ds
.len
);
2906 data_string_forget (&ds
, MDL
);
2908 if (!parse_semi (cfile
))
2917 if (token
!= RBRACE
) {
2918 parse_warn (cfile
, "expecting right brace.");
2921 /* Allow the BIND 8 syntax, which has a semicolon after each
2923 token
= peek_token (&val
, (unsigned *)0, cfile
);
2925 token
= next_token (&val
, (unsigned *)0, cfile
);
2927 /* Remember the key. */
2928 status
= omapi_auth_key_enter (key
);
2929 if (status
!= ISC_R_SUCCESS
) {
2930 parse_warn (cfile
, "tsig key %s: %s",
2931 key
-> name
, isc_result_totext (status
));
2934 omapi_auth_key_dereference (&key
, MDL
);
2938 skip_to_rbrace (cfile
, 1);
2940 omapi_auth_key_dereference (&key
, MDL
);
2945 * on-statement :== event-types LBRACE executable-statements RBRACE
2946 * event-types :== event-type OR event-types |
2948 * event-type :== EXPIRY | COMMIT | RELEASE
2951 int parse_on_statement (result
, cfile
, lose
)
2952 struct executable_statement
**result
;
2953 struct parse
*cfile
;
2956 enum dhcp_token token
;
2959 if (!executable_statement_allocate (result
, MDL
))
2960 log_fatal ("no memory for new statement.");
2961 (*result
) -> op
= on_statement
;
2964 token
= next_token (&val
, (unsigned *)0, cfile
);
2967 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
2971 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
2975 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
2979 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
2983 parse_warn (cfile
, "expecting a lease event type");
2984 skip_to_semi (cfile
);
2986 executable_statement_dereference (result
, MDL
);
2989 token
= next_token (&val
, (unsigned *)0, cfile
);
2990 } while (token
== OR
);
2992 /* Semicolon means no statements. */
2996 if (token
!= LBRACE
) {
2997 parse_warn (cfile
, "left brace expected.");
2998 skip_to_semi (cfile
);
3000 executable_statement_dereference (result
, MDL
);
3003 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
3004 cfile
, lose
, context_any
)) {
3006 /* Try to even things up. */
3008 token
= next_token (&val
,
3009 (unsigned *)0, cfile
);
3010 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3011 executable_statement_dereference (result
, MDL
);
3015 token
= next_token (&val
, (unsigned *)0, cfile
);
3016 if (token
!= RBRACE
) {
3017 parse_warn (cfile
, "right brace expected.");
3018 skip_to_semi (cfile
);
3020 executable_statement_dereference (result
, MDL
);
3027 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3031 int parse_switch_statement (result
, cfile
, lose
)
3032 struct executable_statement
**result
;
3033 struct parse
*cfile
;
3036 enum dhcp_token token
;
3039 if (!executable_statement_allocate (result
, MDL
))
3040 log_fatal ("no memory for new statement.");
3041 (*result
) -> op
= switch_statement
;
3043 token
= next_token (&val
, (unsigned *)0, cfile
);
3044 if (token
!= LPAREN
) {
3045 parse_warn (cfile
, "expecting left brace.");
3048 skip_to_semi (cfile
);
3050 executable_statement_dereference (result
, MDL
);
3054 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
3055 cfile
, lose
, context_data_or_numeric
,
3056 (struct expression
**)0, expr_none
)) {
3059 "expecting data or numeric expression.");
3065 token
= next_token (&val
, (unsigned *)0, cfile
);
3066 if (token
!= RPAREN
) {
3067 parse_warn (cfile
, "right paren expected.");
3071 token
= next_token (&val
, (unsigned *)0, cfile
);
3072 if (token
!= LBRACE
) {
3073 parse_warn (cfile
, "left brace expected.");
3076 if (!(parse_executable_statements
3077 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
3078 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
3079 ? context_data
: context_numeric
)))) {
3081 skip_to_rbrace (cfile
, 1);
3082 executable_statement_dereference (result
, MDL
);
3086 token
= next_token (&val
, (unsigned *)0, cfile
);
3087 if (token
!= RBRACE
) {
3088 parse_warn (cfile
, "right brace expected.");
3095 * case-statement :== CASE expr COLON
3099 int parse_case_statement (result
, cfile
, lose
, case_context
)
3100 struct executable_statement
**result
;
3101 struct parse
*cfile
;
3103 enum expression_context case_context
;
3105 enum dhcp_token token
;
3108 if (!executable_statement_allocate (result
, MDL
))
3109 log_fatal ("no memory for new statement.");
3110 (*result
) -> op
= case_statement
;
3112 if (!parse_expression (&(*result
) -> data
.c_case
,
3113 cfile
, lose
, case_context
,
3114 (struct expression
**)0, expr_none
))
3117 parse_warn (cfile
, "expecting %s expression.",
3118 (case_context
== context_data
3119 ? "data" : "numeric"));
3123 skip_to_semi (cfile
);
3124 executable_statement_dereference (result
, MDL
);
3128 token
= next_token (&val
, (unsigned *)0, cfile
);
3129 if (token
!= COLON
) {
3130 parse_warn (cfile
, "colon expected.");
3137 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3140 * else-statement :== <null> |
3141 * ELSE LBRACE executable-statements RBRACE |
3142 * ELSE IF if-statement |
3143 * ELSIF if-statement
3146 int parse_if_statement (result
, cfile
, lose
)
3147 struct executable_statement
**result
;
3148 struct parse
*cfile
;
3151 enum dhcp_token token
;
3155 if (!executable_statement_allocate (result
, MDL
))
3156 log_fatal ("no memory for if statement.");
3158 (*result
) -> op
= if_statement
;
3160 token
= peek_token (&val
, (unsigned *)0, cfile
);
3161 if (token
== LPAREN
) {
3163 next_token (&val
, (unsigned *)0, cfile
);
3168 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
3171 parse_warn (cfile
, "boolean expression expected.");
3172 executable_statement_dereference (result
, MDL
);
3176 #if defined (DEBUG_EXPRESSION_PARSE)
3177 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
3180 token
= next_token (&val
, (unsigned *)0, cfile
);
3181 if (token
!= RPAREN
) {
3182 parse_warn (cfile
, "expecting right paren.");
3184 executable_statement_dereference (result
, MDL
);
3188 token
= next_token (&val
, (unsigned *)0, cfile
);
3189 if (token
!= LBRACE
) {
3190 parse_warn (cfile
, "left brace expected.");
3191 skip_to_semi (cfile
);
3193 executable_statement_dereference (result
, MDL
);
3196 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
3197 cfile
, lose
, context_any
)) {
3199 /* Try to even things up. */
3201 token
= next_token (&val
,
3202 (unsigned *)0, cfile
);
3203 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3204 executable_statement_dereference (result
, MDL
);
3208 token
= next_token (&val
, (unsigned *)0, cfile
);
3209 if (token
!= RBRACE
) {
3210 parse_warn (cfile
, "right brace expected.");
3211 skip_to_semi (cfile
);
3213 executable_statement_dereference (result
, MDL
);
3216 token
= peek_token (&val
, (unsigned *)0, cfile
);
3217 if (token
== ELSE
) {
3218 token
= next_token (&val
, (unsigned *)0, cfile
);
3219 token
= peek_token (&val
, (unsigned *)0, cfile
);
3221 token
= next_token (&val
, (unsigned *)0, cfile
);
3222 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3226 "expecting if statement");
3227 executable_statement_dereference (result
, MDL
);
3231 } else if (token
!= LBRACE
) {
3232 parse_warn (cfile
, "left brace or if expected.");
3233 skip_to_semi (cfile
);
3235 executable_statement_dereference (result
, MDL
);
3238 token
= next_token (&val
, (unsigned *)0, cfile
);
3239 if (!(parse_executable_statements
3240 (&(*result
) -> data
.ie
.fc
,
3241 cfile
, lose
, context_any
))) {
3242 executable_statement_dereference (result
, MDL
);
3245 token
= next_token (&val
, (unsigned *)0, cfile
);
3246 if (token
!= RBRACE
) {
3247 parse_warn (cfile
, "right brace expected.");
3248 skip_to_semi (cfile
);
3250 executable_statement_dereference (result
, MDL
);
3254 } else if (token
== ELSIF
) {
3255 token
= next_token (&val
, (unsigned *)0, cfile
);
3256 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3260 "expecting conditional.");
3261 executable_statement_dereference (result
, MDL
);
3266 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
3272 * boolean_expression :== CHECK STRING |
3273 * NOT boolean-expression |
3274 * data-expression EQUAL data-expression |
3275 * data-expression BANG EQUAL data-expression |
3276 * data-expression REGEX_MATCH data-expression |
3277 * boolean-expression AND boolean-expression |
3278 * boolean-expression OR boolean-expression
3279 * EXISTS OPTION-NAME
3282 int parse_boolean_expression (expr
, cfile
, lose
)
3283 struct expression
**expr
;
3284 struct parse
*cfile
;
3287 /* Parse an expression... */
3288 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
3289 (struct expression
**)0, expr_none
))
3292 if (!is_boolean_expression (*expr
) &&
3293 (*expr
) -> op
!= expr_variable_reference
&&
3294 (*expr
) -> op
!= expr_funcall
) {
3295 parse_warn (cfile
, "Expecting a boolean expression.");
3297 expression_dereference (expr
, MDL
);
3304 * data_expression :== SUBSTRING LPAREN data-expression COMMA
3305 * numeric-expression COMMA
3306 * numeric-expression RPAREN |
3307 * CONCAT LPAREN data-expression COMMA
3308 * data-expression RPAREN
3309 * SUFFIX LPAREN data_expression COMMA
3310 * numeric-expression RPAREN |
3311 * LCASE LPAREN data_expression RPAREN |
3312 * UCASE LPAREN data_expression RPAREN |
3313 * OPTION option_name |
3315 * PACKET LPAREN numeric-expression COMMA
3316 * numeric-expression RPAREN |
3318 * colon_separated_hex_list
3321 int parse_data_expression (expr
, cfile
, lose
)
3322 struct expression
**expr
;
3323 struct parse
*cfile
;
3326 /* Parse an expression... */
3327 if (!parse_expression (expr
, cfile
, lose
, context_data
,
3328 (struct expression
**)0, expr_none
))
3331 if (!is_data_expression (*expr
) &&
3332 (*expr
) -> op
!= expr_variable_reference
&&
3333 (*expr
) -> op
!= expr_funcall
) {
3334 expression_dereference (expr
, MDL
);
3335 parse_warn (cfile
, "Expecting a data expression.");
3343 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3344 * COMMA number RPAREN |
3348 int parse_numeric_expression (expr
, cfile
, lose
)
3349 struct expression
**expr
;
3350 struct parse
*cfile
;
3353 /* Parse an expression... */
3354 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
3355 (struct expression
**)0, expr_none
))
3358 if (!is_numeric_expression (*expr
) &&
3359 (*expr
) -> op
!= expr_variable_reference
&&
3360 (*expr
) -> op
!= expr_funcall
) {
3361 expression_dereference (expr
, MDL
);
3362 parse_warn (cfile
, "Expecting a numeric expression.");
3370 * dns-expression :==
3371 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3372 * data-expression COMMA numeric-expression RPAREN
3373 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3374 * data-expression RPAREN
3375 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3376 * data-expression RPAREN
3377 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3378 * data-expression RPAREN
3379 * ns-class :== IN | CHAOS | HS | NUMBER
3380 * ns-type :== A | PTR | MX | TXT | NUMBER
3383 int parse_dns_expression (expr
, cfile
, lose
)
3384 struct expression
**expr
;
3385 struct parse
*cfile
;
3388 /* Parse an expression... */
3389 if (!parse_expression (expr
, cfile
, lose
, context_dns
,
3390 (struct expression
**)0, expr_none
))
3393 if (!is_dns_expression (*expr
) &&
3394 (*expr
) -> op
!= expr_variable_reference
&&
3395 (*expr
) -> op
!= expr_funcall
) {
3396 expression_dereference (expr
, MDL
);
3397 parse_warn (cfile
, "Expecting a dns update subexpression.");
3404 /* Parse a subexpression that does not contain a binary operator. */
3406 int parse_non_binary (expr
, cfile
, lose
, context
)
3407 struct expression
**expr
;
3408 struct parse
*cfile
;
3410 enum expression_context context
;
3412 enum dhcp_token token
;
3414 struct collection
*col
;
3415 struct expression
*nexp
, **ep
;
3417 enum expr_op opcode
;
3421 isc_result_t status
;
3424 token
= peek_token (&val
, (unsigned *)0, cfile
);
3426 /* Check for unary operators... */
3429 token
= next_token (&val
, (unsigned *)0, cfile
);
3430 token
= next_token (&val
, (unsigned *)0, cfile
);
3431 if (token
!= STRING
) {
3432 parse_warn (cfile
, "string expected.");
3433 skip_to_semi (cfile
);
3437 for (col
= collections
; col
; col
= col
-> next
)
3438 if (!strcmp (col
-> name
, val
))
3441 parse_warn (cfile
, "unknown collection.");
3445 if (!expression_allocate (expr
, MDL
))
3446 log_fatal ("can't allocate expression");
3447 (*expr
) -> op
= expr_check
;
3448 (*expr
) -> data
.check
= col
;
3452 token
= next_token (&val
, (unsigned *)0, cfile
);
3453 if (context
== context_dns
) {
3454 token
= peek_token (&val
, (unsigned *)0, cfile
);
3457 if (!expression_allocate (expr
, MDL
))
3458 log_fatal ("can't allocate expression");
3459 (*expr
) -> op
= expr_not
;
3460 if (!parse_non_binary (&(*expr
) -> data
.not,
3461 cfile
, lose
, context_boolean
)) {
3463 parse_warn (cfile
, "expression expected");
3464 skip_to_semi (cfile
);
3467 expression_dereference (expr
, MDL
);
3470 if (!is_boolean_expression ((*expr
) -> data
.not)) {
3472 parse_warn (cfile
, "boolean expression expected");
3473 skip_to_semi (cfile
);
3474 expression_dereference (expr
, MDL
);
3480 token
= next_token (&val
, (unsigned *)0, cfile
);
3481 if (!parse_expression (expr
, cfile
, lose
, context
,
3482 (struct expression
**)0, expr_none
)) {
3484 parse_warn (cfile
, "expression expected");
3485 skip_to_semi (cfile
);
3490 token
= next_token (&val
, (unsigned *)0, cfile
);
3491 if (token
!= RPAREN
) {
3493 parse_warn (cfile
, "right paren expected");
3494 skip_to_semi (cfile
);
3500 if (context
== context_dns
)
3502 token
= next_token (&val
, (unsigned *)0, cfile
);
3503 if (!expression_allocate (expr
, MDL
))
3504 log_fatal ("can't allocate expression");
3505 (*expr
) -> op
= expr_exists
;
3507 /* Pass reference directly to expression structure. */
3508 status
= parse_option_name(cfile
, 0, &known
,
3509 &(*expr
)->data
.option
);
3510 if (status
!= ISC_R_SUCCESS
||
3511 (*expr
)->data
.option
== NULL
) {
3513 expression_dereference (expr
, MDL
);
3519 token
= next_token (&val
, (unsigned *)0, cfile
);
3520 if (!expression_allocate (expr
, MDL
))
3521 log_fatal ("can't allocate expression");
3522 (*expr
) -> op
= expr_static
;
3526 token
= next_token (&val
, (unsigned *)0, cfile
);
3527 if (!expression_allocate (expr
, MDL
))
3528 log_fatal ("can't allocate expression");
3529 (*expr
) -> op
= expr_known
;
3533 token
= next_token (&val
, (unsigned *)0, cfile
);
3534 if (!expression_allocate (expr
, MDL
))
3535 log_fatal ("can't allocate expression");
3536 (*expr
) -> op
= expr_substring
;
3538 token
= next_token (&val
, (unsigned *)0, cfile
);
3539 if (token
!= LPAREN
) {
3541 expression_dereference (expr
, MDL
);
3542 parse_warn (cfile
, "left parenthesis expected.");
3547 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
3550 expression_dereference (expr
, MDL
);
3553 "expecting data expression.");
3554 skip_to_semi (cfile
);
3560 token
= next_token (&val
, (unsigned *)0, cfile
);
3561 if (token
!= COMMA
) {
3563 expression_dereference (expr
, MDL
);
3564 parse_warn (cfile
, "comma expected.");
3570 if (!parse_numeric_expression
3571 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
3575 "expecting numeric expression.");
3576 skip_to_semi (cfile
);
3579 expression_dereference (expr
, MDL
);
3583 token
= next_token (&val
, (unsigned *)0, cfile
);
3587 if (!parse_numeric_expression
3588 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
3591 token
= next_token (&val
, (unsigned *)0, cfile
);
3592 if (token
!= RPAREN
) {
3594 parse_warn (cfile
, "right parenthesis expected.");
3596 expression_dereference (expr
, MDL
);
3602 token
= next_token (&val
, (unsigned *)0, cfile
);
3603 if (!expression_allocate (expr
, MDL
))
3604 log_fatal ("can't allocate expression");
3605 (*expr
) -> op
= expr_suffix
;
3607 token
= next_token (&val
, (unsigned *)0, cfile
);
3608 if (token
!= LPAREN
)
3611 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
3615 token
= next_token (&val
, (unsigned *)0, cfile
);
3619 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
3623 token
= next_token (&val
, (unsigned *)0, cfile
);
3624 if (token
!= RPAREN
)
3629 token
= next_token(&val
, (unsigned *)0, cfile
);
3630 if (!expression_allocate(expr
, MDL
))
3631 log_fatal ("can't allocate expression");
3632 (*expr
)->op
= expr_lcase
;
3634 token
= next_token(&val
, (unsigned *)0, cfile
);
3635 if (token
!= LPAREN
)
3638 if (!parse_data_expression(&(*expr
)->data
.lcase
, cfile
, lose
))
3641 token
= next_token(&val
, (unsigned *)0, cfile
);
3642 if (token
!= RPAREN
)
3647 token
= next_token(&val
, (unsigned *)0, cfile
);
3648 if (!expression_allocate(expr
, MDL
))
3649 log_fatal ("can't allocate expression");
3650 (*expr
)->op
= expr_ucase
;
3652 token
= next_token (&val
, (unsigned *)0, cfile
);
3653 if (token
!= LPAREN
)
3656 if (!parse_data_expression(&(*expr
)->data
.ucase
,
3660 token
= next_token(&val
, (unsigned *)0, cfile
);
3661 if (token
!= RPAREN
)
3666 token
= next_token (&val
, (unsigned *)0, cfile
);
3667 if (!expression_allocate (expr
, MDL
))
3668 log_fatal ("can't allocate expression");
3669 (*expr
) -> op
= expr_concat
;
3671 token
= next_token (&val
, (unsigned *)0, cfile
);
3672 if (token
!= LPAREN
)
3675 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3679 token
= next_token (&val
, (unsigned *)0, cfile
);
3684 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3688 token
= next_token (&val
, (unsigned *)0, cfile
);
3690 if (token
== COMMA
) {
3691 nexp
= (struct expression
*)0;
3692 if (!expression_allocate (&nexp
, MDL
))
3693 log_fatal ("can't allocate at CONCAT2");
3694 nexp
-> op
= expr_concat
;
3695 expression_reference (&nexp
-> data
.concat
[0],
3697 expression_dereference (expr
, MDL
);
3698 expression_reference (expr
, nexp
, MDL
);
3699 expression_dereference (&nexp
, MDL
);
3700 goto concat_another
;
3703 if (token
!= RPAREN
)
3707 case BINARY_TO_ASCII
:
3708 token
= next_token (&val
, (unsigned *)0, cfile
);
3709 if (!expression_allocate (expr
, MDL
))
3710 log_fatal ("can't allocate expression");
3711 (*expr
) -> op
= expr_binary_to_ascii
;
3713 token
= next_token (&val
, (unsigned *)0, cfile
);
3714 if (token
!= LPAREN
)
3717 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3721 token
= next_token (&val
, (unsigned *)0, cfile
);
3725 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3729 token
= next_token (&val
, (unsigned *)0, cfile
);
3733 if (!parse_data_expression (&(*expr
) -> data
.b2a
.separator
,
3737 token
= next_token (&val
, (unsigned *)0, cfile
);
3741 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3745 token
= next_token (&val
, (unsigned *)0, cfile
);
3746 if (token
!= RPAREN
)
3751 token
= next_token (&val
, (unsigned *)0, cfile
);
3752 if (!expression_allocate (expr
, MDL
))
3753 log_fatal ("can't allocate expression");
3754 (*expr
) -> op
= expr_reverse
;
3756 token
= next_token (&val
, (unsigned *)0, cfile
);
3757 if (token
!= LPAREN
)
3760 if (!(parse_numeric_expression
3761 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3764 token
= next_token (&val
, (unsigned *)0, cfile
);
3768 if (!(parse_data_expression
3769 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3772 token
= next_token (&val
, (unsigned *)0, cfile
);
3773 if (token
!= RPAREN
)
3778 /* pick (a, b, c) actually produces an internal representation
3779 that looks like pick (a, pick (b, pick (c, nil))). */
3780 token
= next_token (&val
, (unsigned *)0, cfile
);
3781 if (!(expression_allocate (expr
, MDL
)))
3782 log_fatal ("can't allocate expression");
3784 token
= next_token (&val
, (unsigned *)0, cfile
);
3785 if (token
!= LPAREN
)
3788 nexp
= (struct expression
*)0;
3789 expression_reference (&nexp
, *expr
, MDL
);
3791 nexp
-> op
= expr_pick_first_value
;
3792 if (!(parse_data_expression
3793 (&nexp
-> data
.pick_first_value
.car
,
3797 token
= next_token (&val
, (unsigned *)0, cfile
);
3798 if (token
== COMMA
) {
3799 struct expression
*foo
= (struct expression
*)0;
3800 if (!expression_allocate (&foo
, MDL
))
3801 log_fatal ("can't allocate expr");
3802 expression_reference
3803 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3804 expression_dereference (&nexp
, MDL
);
3805 expression_reference (&nexp
, foo
, MDL
);
3806 expression_dereference (&foo
, MDL
);
3808 } while (token
== COMMA
);
3809 expression_dereference (&nexp
, MDL
);
3811 if (token
!= RPAREN
)
3815 /* dns-update and dns-delete are present for historical
3816 purposes, but are deprecated in favor of ns-update
3817 in combination with update, delete, exists and not
3821 #if !defined (NSUPDATE)
3823 "Please rebuild dhcpd with --with-nsupdate.");
3825 token
= next_token (&val
, (unsigned *)0, cfile
);
3826 if (token
== DNS_UPDATE
)
3827 opcode
= expr_ns_add
;
3829 opcode
= expr_ns_delete
;
3831 token
= next_token (&val
, (unsigned *)0, cfile
);
3832 if (token
!= LPAREN
)
3835 token
= next_token (&val
, (unsigned *)0, cfile
);
3836 if (token
!= STRING
) {
3838 "parse_expression: expecting string.");
3840 skip_to_semi (cfile
);
3845 if (!strcasecmp (val
, "a"))
3847 else if (!strcasecmp (val
, "aaaa"))
3849 else if (!strcasecmp (val
, "ptr"))
3851 else if (!strcasecmp (val
, "mx"))
3853 else if (!strcasecmp (val
, "cname"))
3855 else if (!strcasecmp (val
, "TXT"))
3858 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3862 s
= (opcode
== expr_ns_add
3864 : "old-dns-delete");
3865 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3867 log_fatal ("can't allocate name for %s", s
);
3869 if (!expression_allocate (expr
, MDL
))
3870 log_fatal ("can't allocate expression");
3871 (*expr
) -> op
= expr_funcall
;
3872 (*expr
) -> data
.funcall
.name
= cptr
;
3874 /* Fake up a function call. */
3875 ep
= &(*expr
) -> data
.funcall
.arglist
;
3876 if (!expression_allocate (ep
, MDL
))
3877 log_fatal ("can't allocate expression");
3878 (*ep
) -> op
= expr_arg
;
3879 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3880 log_fatal ("can't allocate rrtype value.");
3882 token
= next_token (&val
, (unsigned *)0, cfile
);
3885 ep
= &((*ep
) -> data
.arg
.next
);
3886 if (!expression_allocate (ep
, MDL
))
3887 log_fatal ("can't allocate expression");
3888 (*ep
) -> op
= expr_arg
;
3889 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3893 token
= next_token (&val
, (unsigned *)0, cfile
);
3897 ep
= &((*ep
) -> data
.arg
.next
);
3898 if (!expression_allocate (ep
, MDL
))
3899 log_fatal ("can't allocate expression");
3900 (*ep
) -> op
= expr_arg
;
3901 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3905 if (opcode
== expr_ns_add
) {
3906 token
= next_token (&val
, (unsigned *)0, cfile
);
3910 ep
= &((*ep
) -> data
.arg
.next
);
3911 if (!expression_allocate (ep
, MDL
))
3912 log_fatal ("can't allocate expression");
3913 (*ep
) -> op
= expr_arg
;
3914 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
3917 "expecting numeric expression.");
3922 token
= next_token (&val
, (unsigned *)0, cfile
);
3923 if (token
!= RPAREN
)
3928 #if !defined (NSUPDATE)
3930 "Please rebuild dhcpd with --with-nsupdate.");
3932 token
= next_token (&val
, (unsigned *)0, cfile
);
3933 if (!expression_allocate (expr
, MDL
))
3934 log_fatal ("can't allocate expression");
3936 token
= next_token (&val
, (unsigned *)0, cfile
);
3937 if (token
!= LPAREN
)
3942 nexp
-> op
= expr_dns_transaction
;
3943 if (!(parse_dns_expression
3944 (&nexp
-> data
.dns_transaction
.car
,
3950 "expecting dns expression.");
3951 expression_dereference (expr
, MDL
);
3956 token
= next_token (&val
, (unsigned *)0, cfile
);
3958 if (token
== COMMA
) {
3959 if (!(expression_allocate
3960 (&nexp
-> data
.dns_transaction
.cdr
,
3963 ("can't allocate expression");
3964 nexp
= nexp
-> data
.dns_transaction
.cdr
;
3966 } while (token
== COMMA
);
3968 if (token
!= RPAREN
)
3972 /* NOT EXISTS is special cased above... */
3974 token
= peek_token (&val
, (unsigned *)0, cfile
);
3975 if (token
!= EXISTS
) {
3976 parse_warn (cfile
, "expecting DNS prerequisite.");
3980 opcode
= expr_ns_not_exists
;
3983 opcode
= expr_ns_add
;
3986 opcode
= expr_ns_delete
;
3989 opcode
= expr_ns_exists
;
3991 token
= next_token (&val
, (unsigned *)0, cfile
);
3993 #if !defined (NSUPDATE)
3995 "Please rebuild dhcpd with --with-nsupdate.");
3997 if (!expression_allocate (expr
, MDL
))
3998 log_fatal ("can't allocate expression");
3999 (*expr
) -> op
= opcode
;
4001 token
= next_token (&val
, (unsigned *)0, cfile
);
4002 if (token
!= LPAREN
)
4005 token
= next_token (&val
, (unsigned *)0, cfile
);
4006 if (!is_identifier (token
) && token
!= NUMBER
) {
4007 parse_warn (cfile
, "expecting identifier or number.");
4009 expression_dereference (expr
, MDL
);
4010 skip_to_semi (cfile
);
4015 if (token
== NUMBER
)
4016 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
4017 else if (!strcasecmp (val
, "in"))
4018 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
4019 else if (!strcasecmp (val
, "chaos"))
4020 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
4021 else if (!strcasecmp (val
, "hs"))
4022 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
4024 parse_warn (cfile
, "unexpected rrclass: %s", val
);
4028 token
= next_token (&val
, (unsigned *)0, cfile
);
4032 token
= next_token (&val
, (unsigned *)0, cfile
);
4033 if (!is_identifier (token
) && token
!= NUMBER
) {
4034 parse_warn (cfile
, "expecting identifier or number.");
4038 if (token
== NUMBER
)
4039 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
4040 else if (!strcasecmp (val
, "a"))
4041 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
4042 else if (!strcasecmp (val
, "aaaa"))
4043 (*expr
) -> data
.ns_add
.rrtype
= T_AAAA
;
4044 else if (!strcasecmp (val
, "ptr"))
4045 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
4046 else if (!strcasecmp (val
, "mx"))
4047 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
4048 else if (!strcasecmp (val
, "cname"))
4049 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
4050 else if (!strcasecmp (val
, "TXT"))
4051 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
4053 parse_warn (cfile
, "unexpected rrtype: %s", val
);
4057 token
= next_token (&val
, (unsigned *)0, cfile
);
4061 if (!(parse_data_expression
4062 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
4065 token
= next_token (&val
, (unsigned *)0, cfile
);
4069 if (!(parse_data_expression
4070 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
4073 if (opcode
== expr_ns_add
) {
4074 token
= next_token (&val
, (unsigned *)0, cfile
);
4078 if (!(parse_numeric_expression
4079 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
4083 "expecting numeric expression.");
4088 token
= next_token (&val
, (unsigned *)0, cfile
);
4089 if (token
!= RPAREN
)
4095 if (!expression_allocate (expr
, MDL
))
4096 log_fatal ("can't allocate expression");
4097 (*expr
) -> op
= (token
== OPTION
4099 : expr_config_option
);
4100 token
= next_token (&val
, (unsigned *)0, cfile
);
4102 /* Pass reference directly to expression structure. */
4103 status
= parse_option_name(cfile
, 0, &known
,
4104 &(*expr
)->data
.option
);
4105 if (status
!= ISC_R_SUCCESS
||
4106 (*expr
)->data
.option
== NULL
) {
4108 expression_dereference (expr
, MDL
);
4114 token
= next_token (&val
, (unsigned *)0, cfile
);
4115 if (!expression_allocate (expr
, MDL
))
4116 log_fatal ("can't allocate expression");
4117 (*expr
) -> op
= expr_hardware
;
4120 case LEASED_ADDRESS
:
4121 token
= next_token (&val
, (unsigned *)0, cfile
);
4122 if (!expression_allocate (expr
, MDL
))
4123 log_fatal ("can't allocate expression");
4124 (*expr
) -> op
= expr_leased_address
;
4128 token
= next_token (&val
, (unsigned *)0, cfile
);
4129 if (!expression_allocate (expr
, MDL
))
4130 log_fatal ("can't allocate expression");
4131 (*expr
) -> op
= expr_client_state
;
4135 token
= next_token (&val
, (unsigned *)0, cfile
);
4136 if (!expression_allocate (expr
, MDL
))
4137 log_fatal ("can't allocate expression");
4138 (*expr
) -> op
= expr_filename
;
4142 token
= next_token (&val
, (unsigned *)0, cfile
);
4143 if (!expression_allocate (expr
, MDL
))
4144 log_fatal ("can't allocate expression");
4145 (*expr
) -> op
= expr_sname
;
4149 token
= next_token (&val
, (unsigned *)0, cfile
);
4150 if (!expression_allocate (expr
, MDL
))
4151 log_fatal ("can't allocate expression");
4152 (*expr
) -> op
= expr_lease_time
;
4156 token
= next_token (&val
, (unsigned *)0, cfile
);
4157 if (!expression_allocate (expr
, MDL
))
4158 log_fatal ("can't allocate expression");
4159 (*expr
) -> op
= expr_null
;
4162 case HOST_DECL_NAME
:
4163 token
= next_token (&val
, (unsigned *)0, cfile
);
4164 if (!expression_allocate (expr
, MDL
))
4165 log_fatal ("can't allocate expression");
4166 (*expr
) -> op
= expr_host_decl_name
;
4169 case UPDATED_DNS_RR
:
4170 token
= next_token (&val
, (unsigned *)0, cfile
);
4172 token
= next_token (&val
, (unsigned *)0, cfile
);
4173 if (token
!= LPAREN
)
4176 token
= next_token (&val
, (unsigned *)0, cfile
);
4177 if (token
!= STRING
) {
4178 parse_warn (cfile
, "expecting string.");
4183 if (!strcasecmp (val
, "a"))
4184 s
= "ddns-fwd-name";
4185 else if (!strcasecmp (val
, "ptr"))
4186 s
= "ddns-rev-name";
4188 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
4192 token
= next_token (&val
, (unsigned *)0, cfile
);
4193 if (token
!= RPAREN
)
4196 if (!expression_allocate (expr
, MDL
))
4197 log_fatal ("can't allocate expression");
4198 (*expr
) -> op
= expr_variable_reference
;
4199 (*expr
) -> data
.variable
=
4200 dmalloc (strlen (s
) + 1, MDL
);
4201 if (!(*expr
) -> data
.variable
)
4202 log_fatal ("can't allocate variable name.");
4203 strcpy ((*expr
) -> data
.variable
, s
);
4207 token
= next_token (&val
, (unsigned *)0, cfile
);
4208 if (!expression_allocate (expr
, MDL
))
4209 log_fatal ("can't allocate expression");
4210 (*expr
) -> op
= expr_packet
;
4212 token
= next_token (&val
, (unsigned *)0, cfile
);
4213 if (token
!= LPAREN
)
4216 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
4220 token
= next_token (&val
, (unsigned *)0, cfile
);
4224 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
4228 token
= next_token (&val
, (unsigned *)0, cfile
);
4229 if (token
!= RPAREN
)
4234 token
= next_token (&val
, &len
, cfile
);
4235 if (!make_const_data (expr
, (const unsigned char *)val
,
4237 log_fatal ("can't make constant string expression.");
4241 token
= next_token (&val
, (unsigned *)0, cfile
);
4242 token
= next_token (&val
, (unsigned *)0, cfile
);
4243 if (token
!= LPAREN
) {
4244 parse_warn (cfile
, "left parenthesis expected.");
4249 if (!expression_allocate (expr
, MDL
))
4250 log_fatal ("can't allocate expression");
4252 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
4256 "expecting data expression.");
4257 skip_to_semi (cfile
);
4260 expression_dereference (expr
, MDL
);
4264 token
= next_token (&val
, (unsigned *)0, cfile
);
4265 if (token
!= COMMA
) {
4266 parse_warn (cfile
, "comma expected.");
4268 expression_dereference (expr
, MDL
);
4272 token
= next_token (&val
, (unsigned *)0, cfile
);
4273 if (token
!= NUMBER
) {
4274 parse_warn (cfile
, "number expected.");
4276 expression_dereference (expr
, MDL
);
4279 switch (atoi (val
)) {
4281 (*expr
) -> op
= expr_extract_int8
;
4285 (*expr
) -> op
= expr_extract_int16
;
4289 (*expr
) -> op
= expr_extract_int32
;
4294 "unsupported integer size %d", atoi (val
));
4296 skip_to_semi (cfile
);
4297 expression_dereference (expr
, MDL
);
4301 token
= next_token (&val
, (unsigned *)0, cfile
);
4302 if (token
!= RPAREN
) {
4303 parse_warn (cfile
, "right parenthesis expected.");
4305 expression_dereference (expr
, MDL
);
4311 token
= next_token (&val
, (unsigned *)0, cfile
);
4312 token
= next_token (&val
, (unsigned *)0, cfile
);
4313 if (token
!= LPAREN
) {
4314 parse_warn (cfile
, "left parenthesis expected.");
4319 if (!expression_allocate (expr
, MDL
))
4320 log_fatal ("can't allocate expression");
4322 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
4324 parse_warn (cfile
, "expecting numeric expression.");
4325 skip_to_semi (cfile
);
4327 expression_dereference (expr
, MDL
);
4331 token
= next_token (&val
, (unsigned *)0, cfile
);
4332 if (token
!= COMMA
) {
4333 parse_warn (cfile
, "comma expected.");
4335 expression_dereference (expr
, MDL
);
4339 token
= next_token (&val
, (unsigned *)0, cfile
);
4340 if (token
!= NUMBER
) {
4341 parse_warn (cfile
, "number expected.");
4343 expression_dereference (expr
, MDL
);
4346 switch (atoi (val
)) {
4348 (*expr
) -> op
= expr_encode_int8
;
4352 (*expr
) -> op
= expr_encode_int16
;
4356 (*expr
) -> op
= expr_encode_int32
;
4361 "unsupported integer size %d", atoi (val
));
4363 skip_to_semi (cfile
);
4364 expression_dereference (expr
, MDL
);
4368 token
= next_token (&val
, (unsigned *)0, cfile
);
4369 if (token
!= RPAREN
) {
4370 parse_warn (cfile
, "right parenthesis expected.");
4372 expression_dereference (expr
, MDL
);
4378 /* If we're in a numeric context, this should just be a
4379 number, by itself. */
4380 if (context
== context_numeric
||
4381 context
== context_data_or_numeric
) {
4382 next_token (&val
, (unsigned *)0, cfile
);
4383 if (!expression_allocate (expr
, MDL
))
4384 log_fatal ("can't allocate expression");
4385 (*expr
) -> op
= expr_const_int
;
4386 (*expr
) -> data
.const_int
= atoi (val
);
4390 case NUMBER_OR_NAME
:
4391 if (!expression_allocate (expr
, MDL
))
4392 log_fatal ("can't allocate expression");
4394 (*expr
) -> op
= expr_const_data
;
4395 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
4396 expression_dereference (expr
, MDL
);
4405 token
= next_token (&val
, (unsigned *)0, cfile
);
4406 if (!expression_allocate (expr
, MDL
))
4407 log_fatal ("can't allocate expression");
4408 (*expr
) -> op
= expr_const_int
;
4409 (*expr
) -> data
.const_int
= known
;
4413 known
= ISC_R_SUCCESS
;
4417 known
= ISC_R_NOTAUTH
;
4421 known
= ISC_R_NOTIMPLEMENTED
;
4425 known
= ISC_R_NOTZONE
;
4429 known
= ISC_R_NXDOMAIN
;
4433 known
= ISC_R_NXRRSET
;
4437 known
= ISC_R_REFUSED
;
4441 known
= ISC_R_SERVFAIL
;
4445 known
= ISC_R_YXDOMAIN
;
4449 known
= ISC_R_YXRRSET
;
4457 known
= S_REBOOTING
;
4461 known
= S_SELECTING
;
4465 known
= S_REQUESTING
;
4477 known
= S_REBINDING
;
4481 token
= next_token (&val
, (unsigned *)0, cfile
);
4482 token
= next_token (&val
, (unsigned *)0, cfile
);
4483 if (token
!= LPAREN
)
4486 token
= next_token (&val
, (unsigned *)0, cfile
);
4487 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
4488 parse_warn (cfile
, "%s can't be a variable name", val
);
4489 skip_to_semi (cfile
);
4494 if (!expression_allocate (expr
, MDL
))
4495 log_fatal ("can't allocate expression");
4496 (*expr
) -> op
= expr_variable_exists
;
4497 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
4498 if (!(*expr
)->data
.variable
)
4499 log_fatal ("can't allocate variable name");
4500 strcpy ((*expr
) -> data
.variable
, val
);
4501 token
= next_token (&val
, (unsigned *)0, cfile
);
4502 if (token
!= RPAREN
)
4506 /* This parses 'gethostname()'. */
4508 token
= next_token(&val
, NULL
, cfile
);
4509 if (!expression_allocate(expr
, MDL
))
4510 log_fatal("can't allocate expression");
4511 (*expr
)->op
= expr_gethostname
;
4513 token
= next_token(NULL
, NULL
, cfile
);
4514 if (token
!= LPAREN
)
4517 token
= next_token(NULL
, NULL
, cfile
);
4518 if (token
!= RPAREN
)
4522 /* Not a valid start to an expression... */
4524 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
4527 token
= next_token (&val
, (unsigned *)0, cfile
);
4529 /* Save the name of the variable being referenced. */
4530 cptr
= dmalloc (strlen (val
) + 1, MDL
);
4532 log_fatal ("can't allocate variable name");
4535 /* Simple variable reference, as far as we can tell. */
4536 token
= peek_token (&val
, (unsigned *)0, cfile
);
4537 if (token
!= LPAREN
) {
4538 if (!expression_allocate (expr
, MDL
))
4539 log_fatal ("can't allocate expression");
4540 (*expr
) -> op
= expr_variable_reference
;
4541 (*expr
) -> data
.variable
= cptr
;
4545 token
= next_token (&val
, (unsigned *)0, cfile
);
4546 if (!expression_allocate (expr
, MDL
))
4547 log_fatal ("can't allocate expression");
4548 (*expr
) -> op
= expr_funcall
;
4549 (*expr
) -> data
.funcall
.name
= cptr
;
4551 /* Now parse the argument list. */
4552 ep
= &(*expr
) -> data
.funcall
.arglist
;
4554 if (!expression_allocate (ep
, MDL
))
4555 log_fatal ("can't allocate expression");
4556 (*ep
) -> op
= expr_arg
;
4557 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
4558 cfile
, lose
, context_any
,
4559 (struct expression
**)0,
4563 "expecting expression.");
4566 skip_to_semi (cfile
);
4567 expression_dereference (expr
, MDL
);
4570 ep
= &((*ep
) -> data
.arg
.next
);
4571 token
= next_token (&val
, (unsigned *)0, cfile
);
4572 } while (token
== COMMA
);
4573 if (token
!= RPAREN
) {
4574 parse_warn (cfile
, "Right parenthesis expected.");
4575 skip_to_semi (cfile
);
4577 expression_dereference (expr
, MDL
);
4585 /* Parse an expression. */
4587 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
4588 struct expression
**expr
;
4589 struct parse
*cfile
;
4591 enum expression_context context
;
4592 struct expression
**plhs
;
4595 enum dhcp_token token
;
4597 struct expression
*rhs
= (struct expression
*)0, *tmp
;
4598 struct expression
*lhs
= (struct expression
*)0;
4599 enum expr_op next_op
;
4600 enum expression_context
4601 lhs_context
= context_any
,
4602 rhs_context
= context_any
;
4604 /* Consume the left hand side we were passed. */
4606 expression_reference (&lhs
, *plhs
, MDL
);
4607 expression_dereference (plhs
, MDL
);
4611 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
4612 /* If we already have a left-hand side, then it's not
4613 okay for there not to be a right-hand side here, so
4614 we need to flag it as an error. */
4618 "expecting right-hand side.");
4620 skip_to_semi (cfile
);
4622 expression_dereference (&lhs
, MDL
);
4627 /* At this point, rhs contains either an entire subexpression,
4628 or at least a left-hand-side. If we do not see a binary token
4629 as the next token, we're done with the expression. */
4631 token
= peek_token (&val
, (unsigned *)0, cfile
);
4634 token
= next_token (&val
, (unsigned *)0, cfile
);
4635 token
= peek_token (&val
, (unsigned *)0, cfile
);
4636 if (token
!= EQUAL
) {
4637 parse_warn (cfile
, "! in boolean context without =");
4639 skip_to_semi (cfile
);
4641 expression_dereference (&lhs
, MDL
);
4644 next_op
= expr_not_equal
;
4645 context
= expression_context (rhs
);
4649 next_op
= expr_equal
;
4650 context
= expression_context (rhs
);
4655 token
= next_token(&val
, NULL
, cfile
);
4656 token
= peek_token(&val
, NULL
, cfile
);
4659 next_op
= expr_iregex_match
;
4660 else if (token
== EQUAL
)
4661 next_op
= expr_regex_match
;
4663 parse_warn(cfile
, "expecting ~= or ~~ operator");
4665 skip_to_semi(cfile
);
4667 expression_dereference(&lhs
, MDL
);
4671 context
= expression_context(rhs
);
4673 parse_warn(cfile
, "No support for regex operator.");
4675 skip_to_semi(cfile
);
4677 expression_dereference(&lhs
, MDL
);
4684 context
= expression_context (rhs
);
4689 context
= expression_context (rhs
);
4694 context
= expression_context (rhs
);
4698 next_op
= expr_subtract
;
4699 context
= expression_context (rhs
);
4703 next_op
= expr_divide
;
4704 context
= expression_context (rhs
);
4708 next_op
= expr_multiply
;
4709 context
= expression_context (rhs
);
4713 next_op
= expr_remainder
;
4714 context
= expression_context (rhs
);
4718 next_op
= expr_binary_and
;
4719 context
= expression_context (rhs
);
4723 next_op
= expr_binary_or
;
4724 context
= expression_context (rhs
);
4728 next_op
= expr_binary_xor
;
4729 context
= expression_context (rhs
);
4733 next_op
= expr_none
;
4736 /* If we have no lhs yet, we just parsed it. */
4738 /* If there was no operator following what we just parsed,
4739 then we're done - return it. */
4740 if (next_op
== expr_none
) {
4745 rhs
= (struct expression
*)0;
4747 next_token (&val
, (unsigned *)0, cfile
);
4751 /* If the next binary operator is of greater precedence than the
4752 * current operator, then rhs we have parsed so far is actually
4753 * the lhs of the next operator. To get this value, we have to
4756 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4757 op_precedence (binop
, next_op
) < 0) {
4759 /* Eat the subexpression operator token, which we pass to
4760 * parse_expression...we only peek()'d earlier.
4762 token
= next_token (&val
, (unsigned *)0, cfile
);
4764 /* Continue parsing of the right hand side with that token. */
4766 rhs
= (struct expression
*)0;
4767 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4771 "expecting a subexpression");
4776 next_op
= expr_none
;
4779 if (binop
!= expr_none
) {
4780 rhs_context
= expression_context(rhs
);
4781 lhs_context
= expression_context(lhs
);
4783 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4784 (rhs_context
!= lhs_context
)) {
4785 parse_warn (cfile
, "illegal expression relating different types");
4786 skip_to_semi (cfile
);
4787 expression_dereference (&rhs
, MDL
);
4788 expression_dereference (&lhs
, MDL
);
4794 case expr_not_equal
:
4796 if ((rhs_context
!= context_data_or_numeric
) &&
4797 (rhs_context
!= context_data
) &&
4798 (rhs_context
!= context_numeric
) &&
4799 (rhs_context
!= context_any
)) {
4800 parse_warn (cfile
, "expecting data/numeric expression");
4801 skip_to_semi (cfile
);
4802 expression_dereference (&rhs
, MDL
);
4808 case expr_regex_match
:
4810 if (expression_context(rhs
) != context_data
) {
4811 parse_warn(cfile
, "expecting data expression");
4812 skip_to_semi(cfile
);
4813 expression_dereference(&rhs
, MDL
);
4818 /* It should not be possible to attempt to parse the right
4819 * hand side of an operator there is no support for.
4821 log_fatal("Impossible condition at %s:%d.", MDL
);
4827 if ((rhs_context
!= context_boolean
) &&
4828 (rhs_context
!= context_any
)) {
4829 parse_warn (cfile
, "expecting boolean expressions");
4830 skip_to_semi (cfile
);
4831 expression_dereference (&rhs
, MDL
);
4841 case expr_remainder
:
4842 case expr_binary_and
:
4843 case expr_binary_or
:
4844 case expr_binary_xor
:
4845 if ((rhs_context
!= context_numeric
) &&
4846 (rhs_context
!= context_any
)) {
4847 parse_warn (cfile
, "expecting numeric expressions");
4848 skip_to_semi (cfile
);
4849 expression_dereference (&rhs
, MDL
);
4860 /* Now, if we didn't find a binary operator, we're done parsing
4861 this subexpression, so combine it with the preceding binary
4862 operator and return the result. */
4863 if (next_op
== expr_none
) {
4864 if (!expression_allocate (expr
, MDL
))
4865 log_fatal ("Can't allocate expression!");
4867 (*expr
) -> op
= binop
;
4868 /* All the binary operators' data union members
4869 are the same, so we'll cheat and use the member
4870 for the equals operator. */
4871 (*expr
) -> data
.equal
[0] = lhs
;
4872 (*expr
) -> data
.equal
[1] = rhs
;
4876 /* Eat the operator token - we now know it was a binary operator... */
4877 token
= next_token (&val
, (unsigned *)0, cfile
);
4879 /* Now combine the LHS and the RHS using binop. */
4880 tmp
= (struct expression
*)0;
4881 if (!expression_allocate (&tmp
, MDL
))
4882 log_fatal ("No memory for equal precedence combination.");
4884 /* Store the LHS and RHS. */
4885 tmp
-> data
.equal
[0] = lhs
;
4886 tmp
-> data
.equal
[1] = rhs
;
4890 tmp
= (struct expression
*)0;
4891 rhs
= (struct expression
*)0;
4893 /* Recursions don't return until we have parsed the end of the
4894 expression, so if we recursed earlier, we can now return what
4896 if (next_op
== expr_none
) {
4906 int parse_option_data (expr
, cfile
, lookups
, option
)
4907 struct expression
**expr
;
4908 struct parse
*cfile
;
4910 struct option
*option
;
4913 const char *fmt
= NULL
;
4914 struct expression
*tmp
;
4915 enum dhcp_token token
;
4919 * Set a flag if this is an array of a simple type (i.e.,
4920 * not an array of pairs of IP addresses, or something like
4926 /* Set fmt to start of format for 'A' and one char back
4929 if ((fmt
!= NULL
) && (fmt
!= option
->format
) && (*fmt
== 'a'))
4931 else if ((fmt
== NULL
) || (*fmt
== 'A'))
4932 fmt
= option
->format
;
4934 /* 'a' means always uniform */
4935 if ((fmt
[0] != 'Z') && (tolower((int)fmt
[1]) == 'a'))
4939 if ((*fmt
== 'A') || (*fmt
== 'a'))
4947 if (!parse_option_token(expr
, cfile
, &fmt
, tmp
,
4948 uniform
, lookups
)) {
4949 if (fmt
[1] != 'o') {
4951 expression_dereference (&tmp
,
4959 expression_dereference (&tmp
, MDL
);
4962 } while (*fmt
!= '\0');
4964 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4965 token
= peek_token (&val
, (unsigned *)0, cfile
);
4966 /* Comma means: continue with next element in array */
4967 if (token
== COMMA
) {
4968 token
= next_token (&val
,
4969 (unsigned *)0, cfile
);
4972 /* no comma: end of array.
4973 'A' or end of string means: leave the loop */
4974 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4976 /* 'a' means: go on with next char */
4982 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4987 /* option-statement :== identifier DOT identifier <syntax> SEMI
4988 | identifier <syntax> SEMI
4990 Option syntax is handled specially through format strings, so it
4991 would be painful to come up with BNF for it. However, it always
4992 starts as above and ends in a SEMI. */
4994 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4995 struct executable_statement
**result
;
4996 struct parse
*cfile
;
4998 struct option
*option
;
4999 enum statement_op op
;
5002 enum dhcp_token token
;
5003 struct expression
*expr
= (struct expression
*)0;
5006 token
= peek_token (&val
, (unsigned *)0, cfile
);
5007 if ((token
== SEMI
) && (option
->format
[0] != 'Z')) {
5008 /* Eat the semicolon... */
5010 * XXXSK: I'm not sure why we should ever get here, but we
5011 * do during our startup. This confuses things if
5012 * we are parsing a zero-length option, so don't
5013 * eat the semicolon token in that case.
5015 token
= next_token (&val
, (unsigned *)0, cfile
);
5016 } else if (token
== EQUAL
) {
5017 /* Eat the equals sign. */
5018 token
= next_token (&val
, (unsigned *)0, cfile
);
5020 /* Parse a data expression and use its value for the data. */
5021 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
5022 /* In this context, we must have an executable
5023 statement, so if we found something else, it's
5027 "expecting a data expression.");
5028 skip_to_semi (cfile
);
5033 if (! parse_option_data(&expr
, cfile
, lookups
, option
))
5037 if (!parse_semi (cfile
))
5039 if (!executable_statement_allocate (result
, MDL
))
5040 log_fatal ("no memory for option statement.");
5043 if (expr
&& !option_cache (&(*result
)->data
.option
,
5044 NULL
, expr
, option
, MDL
))
5045 log_fatal ("no memory for option cache");
5048 expression_dereference (&expr
, MDL
);
5053 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
5054 struct expression
**rv
;
5055 struct parse
*cfile
;
5057 struct expression
*expr
;
5062 enum dhcp_token token
;
5063 struct expression
*t
= (struct expression
*)0;
5064 unsigned char buf
[4];
5069 struct enumeration_value
*e
;
5073 token
= next_token (&val
, &len
, cfile
);
5074 if (!is_identifier (token
)) {
5075 if ((*fmt
) [1] != 'o') {
5076 parse_warn (cfile
, "expecting identifier.");
5078 skip_to_semi (cfile
);
5082 if (!make_const_data (&t
, (const unsigned char *)val
,
5084 log_fatal ("No memory for %s", val
);
5088 g
= strchr (*fmt
, '.');
5091 "malformed encapsulation format (bug!)");
5092 skip_to_semi (cfile
);
5097 token
= peek_token (&val
, (unsigned *)0, cfile
);
5098 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5099 if (!expression_allocate (&t
, MDL
))
5101 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
5102 expression_dereference (&t
, MDL
);
5105 t
-> op
= expr_const_data
;
5107 token
= next_token (&val
, &len
, cfile
);
5109 if(token
== STRING
) {
5110 if (!make_const_data (&t
,
5111 (const unsigned char *)val
,
5113 log_fatal ("No memory for \"%s\"", val
);
5115 if ((*fmt
) [1] != 'o') {
5116 parse_warn (cfile
, "expecting string "
5117 "or hexadecimal data.");
5118 skip_to_semi (cfile
);
5125 case 'D': /* Domain list... */
5126 if ((*fmt
)[1] == 'c') {
5128 /* Skip the compress-flag atom. */
5133 t
= parse_domain_list(cfile
, compress
);
5136 if ((*fmt
)[1] != 'o')
5137 skip_to_semi(cfile
);
5143 case 'd': /* Domain name... */
5144 val
= parse_host_name (cfile
);
5146 parse_warn (cfile
, "not a valid domain name.");
5147 skip_to_semi (cfile
);
5153 case 't': /* Text string... */
5154 token
= next_token (&val
, &len
, cfile
);
5155 if (token
!= STRING
&& !is_identifier (token
)) {
5156 if ((*fmt
) [1] != 'o') {
5157 parse_warn (cfile
, "expecting string.");
5159 skip_to_semi (cfile
);
5164 if (!make_const_data (&t
, (const unsigned char *)val
,
5166 log_fatal ("No memory for concatenation");
5171 g
= strchr (*fmt
, '.');
5173 parse_warn (cfile
, "malformed %s (bug!)",
5174 "enumeration format");
5176 skip_to_semi (cfile
);
5180 token
= next_token (&val
, (unsigned *)0, cfile
);
5181 if (!is_identifier (token
)) {
5183 "identifier expected");
5186 e
= find_enumeration_value (f
, (*fmt
) - f
, &len
, val
);
5188 parse_warn (cfile
, "unknown value");
5191 if (!make_const_data (&t
, &e
-> value
, len
, 0, 1, MDL
))
5195 case 'I': /* IP address or hostname. */
5197 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
5200 if (!parse_ip_addr (cfile
, &addr
))
5202 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
5208 case '6': /* IPv6 address. */
5209 if (!parse_ip6_addr(cfile
, &addr
)) {
5212 if (!make_const_data(&t
, addr
.iabuf
, addr
.len
, 0, 1, MDL
)) {
5217 case 'T': /* Lease interval. */
5218 token
= next_token (&val
, (unsigned *)0, cfile
);
5219 if (token
!= INFINITE
)
5222 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5226 case 'L': /* Unsigned 32-bit integer... */
5227 case 'l': /* Signed 32-bit integer... */
5228 token
= next_token (&val
, (unsigned *)0, cfile
);
5230 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
5232 if ((*fmt
) [1] != 'o') {
5233 parse_warn (cfile
, "expecting number.");
5235 skip_to_semi (cfile
);
5239 convert_num (cfile
, buf
, val
, 0, 32);
5240 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5244 case 's': /* Signed 16-bit integer. */
5245 case 'S': /* Unsigned 16-bit integer. */
5246 token
= next_token (&val
, (unsigned *)0, cfile
);
5247 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5249 convert_num (cfile
, buf
, val
, 0, 16);
5250 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
5254 case 'b': /* Signed 8-bit integer. */
5255 case 'B': /* Unsigned 8-bit integer. */
5256 token
= next_token (&val
, (unsigned *)0, cfile
);
5257 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5259 convert_num (cfile
, buf
, val
, 0, 8);
5260 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5264 case 'f': /* Boolean flag. */
5265 token
= next_token (&val
, (unsigned *)0, cfile
);
5266 if (!is_identifier (token
)) {
5267 if ((*fmt
) [1] != 'o')
5268 parse_warn (cfile
, "expecting identifier.");
5270 if ((*fmt
) [1] != 'o') {
5272 skip_to_semi (cfile
);
5276 if (!strcasecmp (val
, "true")
5277 || !strcasecmp (val
, "on"))
5279 else if (!strcasecmp (val
, "false")
5280 || !strcasecmp (val
, "off"))
5282 else if (!strcasecmp (val
, "ignore"))
5285 if ((*fmt
) [1] != 'o')
5286 parse_warn (cfile
, "expecting boolean.");
5289 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5293 case 'Z': /* Zero-length option. */
5294 token
= peek_token (&val
, (unsigned *)0, cfile
);
5295 if (token
!= SEMI
) {
5296 parse_warn(cfile
, "semicolon expected.");
5297 skip_to_semi(cfile
);
5300 if (!make_const_data(&t
, /* expression */
5310 parse_warn (cfile
, "Bad format '%c' in parse_option_token.",
5312 skip_to_semi (cfile
);
5316 if (!make_concat (rv
, expr
, t
))
5319 expression_reference (rv
, t
, MDL
);
5320 expression_dereference (&t
, MDL
);
5324 int parse_option_decl (oc
, cfile
)
5325 struct option_cache
**oc
;
5326 struct parse
*cfile
;
5331 u_int8_t hunkbuf
[1024];
5332 unsigned hunkix
= 0;
5333 const char *fmt
, *f
;
5334 struct option
*option
=NULL
;
5335 struct iaddr ip_addr
;
5337 const u_int8_t
*cdp
;
5343 struct expression
*express
= NULL
;
5344 struct enumeration_value
*e
;
5345 isc_result_t status
;
5347 status
= parse_option_name (cfile
, 0, &known
, &option
);
5348 if (status
!= ISC_R_SUCCESS
|| option
== NULL
)
5351 /* Parse the option data... */
5353 for (fmt
= option
-> format
; *fmt
; fmt
++) {
5356 if (*fmt
== 'o' && fmt
!= option
-> format
)
5360 fmt
= strchr (fmt
, '.');
5363 "malformed %s (bug!)",
5364 "encapsulation format");
5368 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
5369 sizeof hunkbuf
- hunkix
);
5373 case 't': /* Text string... */
5374 token
= peek_token (&val
,
5376 if (token
== SEMI
&& fmt
[1] == 'o') {
5380 token
= next_token (&val
,
5382 if (token
!= STRING
) {
5384 "expecting string.");
5387 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
5389 "option data buffer %s",
5393 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
5399 if (fmt
[1] == 'c') {
5405 express
= parse_domain_list(cfile
, compress
);
5407 if (express
== NULL
)
5410 if (express
->op
!= expr_const_data
) {
5411 parse_warn(cfile
, "unexpected "
5416 len
= express
->data
.const_data
.len
;
5417 cdp
= express
->data
.const_data
.data
;
5419 if ((hunkix
+ len
) > sizeof(hunkbuf
)) {
5420 parse_warn(cfile
, "option data buffer "
5424 memcpy(&hunkbuf
[hunkix
], cdp
, len
);
5427 expression_dereference(&express
, MDL
);
5432 fmt
= strchr (fmt
, '.');
5435 "malformed %s (bug!)",
5436 "enumeration format");
5439 token
= next_token (&val
,
5440 (unsigned *)0, cfile
);
5441 if (!is_identifier (token
)) {
5443 "identifier expected");
5446 e
= find_enumeration_value (f
, fmt
- f
,
5457 if (!parse_ip6_addr(cfile
, &ip_addr
))
5463 case 'I': /* IP address. */
5464 if (!parse_ip_addr (cfile
, &ip_addr
))
5470 if (hunkix
+ len
> sizeof hunkbuf
) {
5472 "option data buffer %s",
5476 memcpy (&hunkbuf
[hunkix
], dp
, len
);
5480 case 'L': /* Unsigned 32-bit integer... */
5481 case 'l': /* Signed 32-bit integer... */
5482 token
= next_token (&val
,
5483 (unsigned *)0, cfile
);
5484 if ((token
!= NUMBER
) &&
5485 (token
!= NUMBER_OR_NAME
)) {
5488 "expecting number.");
5494 convert_num (cfile
, buf
, val
, 0, 32);
5499 case 's': /* Signed 16-bit integer. */
5500 case 'S': /* Unsigned 16-bit integer. */
5501 token
= next_token (&val
,
5502 (unsigned *)0, cfile
);
5503 if ((token
!= NUMBER
) &&
5504 (token
!= NUMBER_OR_NAME
))
5506 convert_num (cfile
, buf
, val
, 0, 16);
5511 case 'b': /* Signed 8-bit integer. */
5512 case 'B': /* Unsigned 8-bit integer. */
5513 token
= next_token (&val
,
5514 (unsigned *)0, cfile
);
5515 if ((token
!= NUMBER
) &&
5516 (token
!= NUMBER_OR_NAME
))
5518 convert_num (cfile
, buf
, val
, 0, 8);
5523 case 'f': /* Boolean flag. */
5524 token
= next_token (&val
,
5525 (unsigned *)0, cfile
);
5526 if (!is_identifier (token
)) {
5528 "expecting identifier.");
5535 if (!strcasecmp (val
, "true")
5536 || !strcasecmp (val
, "on"))
5538 else if (!strcasecmp (val
, "false")
5539 || !strcasecmp (val
, "off"))
5543 "expecting boolean.");
5550 case 'Z': /* Zero-length option */
5551 token
= next_token(&val
, (unsigned *)0, cfile
);
5552 if (token
!= SEMI
) {
5554 "semicolon expected.");
5562 log_error ("parse_option_param: Bad format %c",
5567 token
= next_token (&val
, (unsigned *)0, cfile
);
5568 } while (*fmt
== 'A' && token
== COMMA
);
5570 if (token
!= SEMI
) {
5571 parse_warn (cfile
, "semicolon expected.");
5575 bp
= (struct buffer
*)0;
5576 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
5577 log_fatal ("no memory to store option declaration.");
5579 log_fatal ("out of memory allocating option data.");
5580 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
5582 if (!option_cache_allocate (oc
, MDL
))
5583 log_fatal ("out of memory allocating option cache.");
5585 (*oc
) -> data
.buffer
= bp
;
5586 (*oc
) -> data
.data
= &bp
-> data
[0];
5587 (*oc
) -> data
.terminated
= nul_term
;
5588 (*oc
) -> data
.len
= hunkix
;
5589 option_reference(&(*oc
)->option
, option
, MDL
);
5590 option_dereference(&option
, MDL
);
5594 if (express
!= NULL
)
5595 expression_dereference(&express
, MDL
);
5596 skip_to_semi (cfile
);
5598 option_dereference(&option
, MDL
);
5603 /* Consider merging parse_cshl into this. */
5605 int parse_X (cfile
, buf
, max
)
5606 struct parse
*cfile
;
5614 token
= peek_token (&val
, (unsigned *)0, cfile
);
5615 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5618 token
= next_token (&val
, (unsigned *)0, cfile
);
5619 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
5621 "expecting hexadecimal constant.");
5622 skip_to_semi (cfile
);
5625 convert_num (cfile
, &buf
[len
], val
, 16, 8);
5628 "hexadecimal constant too long.");
5629 skip_to_semi (cfile
);
5632 token
= peek_token (&val
, (unsigned *)0, cfile
);
5634 token
= next_token (&val
,
5635 (unsigned *)0, cfile
);
5636 } while (token
== COLON
);
5638 } else if (token
== STRING
) {
5639 token
= next_token (&val
, &len
, cfile
);
5640 if (len
+ 1 > max
) {
5641 parse_warn (cfile
, "string constant too long.");
5642 skip_to_semi (cfile
);
5645 memcpy (buf
, val
, len
+ 1);
5647 parse_warn (cfile
, "expecting string or hexadecimal data");
5648 skip_to_semi (cfile
);
5654 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
5662 do_percentm (mbuf
, fmt
);
5663 /* %Audit% This is log output. %2004.06.17,Safe%
5664 * If we truncate we hope the user can get a hint from the log.
5666 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
5667 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
5669 va_start (list
, fmt
);
5670 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
5675 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
5676 if (lix
< (sizeof lexbuf
) - 1)
5677 lexbuf
[lix
++] = ' ';
5678 if (cfile
-> token_line
[i
] == '\t') {
5679 for (; lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
5686 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
5687 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
5688 if (cfile
-> lexchar
< 81)
5689 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
5693 IGNORE_RET (write (STDERR_FILENO
, mbuf
, strlen (mbuf
)));
5694 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5695 IGNORE_RET (write (STDERR_FILENO
, cfile
-> token_line
,
5696 strlen (cfile
-> token_line
)));
5697 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5698 if (cfile
-> lexchar
< 81)
5699 IGNORE_RET (write (STDERR_FILENO
, lexbuf
, lix
));
5700 IGNORE_RET (write (STDERR_FILENO
, "^\n", 2));
5703 cfile
-> warnings_occurred
= 1;
5709 parse_domain_list(struct parse
*cfile
, int compress
)
5712 enum dhcp_token token
= SEMI
;
5713 struct expression
*t
= NULL
;
5714 unsigned len
, clen
= 0;
5716 unsigned char compbuf
[256 * NS_MAXCDNAME
];
5717 const unsigned char *dnptrs
[256], **lastdnptr
;
5719 memset(compbuf
, 0, sizeof(compbuf
));
5720 memset(dnptrs
, 0, sizeof(dnptrs
));
5721 dnptrs
[0] = compbuf
;
5722 lastdnptr
= &dnptrs
[255];
5725 /* Consume the COMMA token if peeked. */
5727 next_token(&val
, NULL
, cfile
);
5729 /* Get next (or first) value. */
5730 token
= next_token(&val
, &len
, cfile
);
5732 if (token
!= STRING
) {
5733 parse_warn(cfile
, "Expecting a domain string.");
5737 /* If compression pointers are enabled, compress. If not,
5738 * just pack the names in series into the buffer.
5741 result
= MRns_name_compress(val
, compbuf
+ clen
,
5742 sizeof(compbuf
) - clen
,
5746 parse_warn(cfile
, "Error compressing domain "
5753 result
= MRns_name_pton(val
, compbuf
+ clen
,
5754 sizeof(compbuf
) - clen
);
5756 /* result == 1 means the input was fully qualified.
5757 * result == 0 means the input wasn't.
5758 * result == -1 means bad things.
5761 parse_warn(cfile
, "Error assembling domain "
5767 * We need to figure out how many bytes to increment
5768 * our buffer pointer since pton doesn't tell us.
5770 while (compbuf
[clen
] != 0)
5771 clen
+= compbuf
[clen
] + 1;
5773 /* Count the last label (0). */
5777 if (clen
> sizeof(compbuf
))
5778 log_fatal("Impossible error at %s:%d", MDL
);
5780 token
= peek_token(&val
, NULL
, cfile
);
5781 } while (token
== COMMA
);
5783 if (!make_const_data(&t
, compbuf
, clen
, 1, 1, MDL
))
5784 log_fatal("No memory for domain list object.");