3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2006 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''.
36 static char copyright
[] =
37 "$Id: parse.c,v 1.123 2007/05/19 18:47:14 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
43 /* Enumerations can be specified in option formats, and are used for
44 parsing, so we define the routines that manage them here. */
46 struct enumeration
*enumerations
;
48 void add_enumeration (struct enumeration
*enumeration
)
50 enumeration
-> next
= enumerations
;
51 enumerations
= enumeration
;
54 struct enumeration
*find_enumeration (const char *name
, int length
)
56 struct enumeration
*e
;
58 for (e
= enumerations
; e
; e
= e
-> next
)
59 if (strlen (e
-> name
) == length
&&
60 !memcmp (e
-> name
, name
, (unsigned)length
))
62 return (struct enumeration
*)0;
65 struct enumeration_value
*find_enumeration_value (const char *name
,
69 struct enumeration
*e
;
72 e
= find_enumeration (name
, length
);
74 for (i
= 0; e
-> values
[i
].name
; i
++) {
75 if (!strcmp (value
, e
-> values
[i
].name
))
76 return &e
-> values
[i
];
79 return (struct enumeration_value
*)0;
82 /* Skip to the semicolon ending the current statement. If we encounter
83 braces, the matching closing brace terminates the statement. If we
84 encounter a right brace but haven't encountered a left brace, return
85 leaving the brace in the token buffer for the caller. If we see a
86 semicolon and haven't seen a left brace, return. This lets us skip
91 statement foo bar { statement { } }
96 void skip_to_semi (cfile
)
99 skip_to_rbrace (cfile
, 0);
102 void skip_to_rbrace (cfile
, brace_count
)
106 enum dhcp_token token
;
109 #if defined (DEBUG_TOKEN)
110 log_error ("skip_to_rbrace: %d\n", brace_count
);
113 token
= peek_token (&val
, (unsigned *)0, cfile
);
114 if (token
== RBRACE
) {
115 token
= next_token (&val
, (unsigned *)0, cfile
);
121 } else if (token
== LBRACE
) {
123 } else if (token
== SEMI
&& !brace_count
) {
124 token
= next_token (&val
, (unsigned *)0, cfile
);
126 } else if (token
== EOL
) {
127 /* EOL only happens when parsing /etc/resolv.conf,
128 and we treat it like a semicolon because the
129 resolv.conf file is line-oriented. */
130 token
= next_token (&val
, (unsigned *)0, cfile
);
133 token
= next_token (&val
, (unsigned *)0, cfile
);
134 } while (token
!= END_OF_FILE
);
137 int parse_semi (cfile
)
140 enum dhcp_token token
;
143 token
= next_token (&val
, (unsigned *)0, cfile
);
145 parse_warn (cfile
, "semicolon expected.");
146 skip_to_semi (cfile
);
152 /* string-parameter :== STRING SEMI */
154 int parse_string (cfile
, sptr
, lptr
)
160 enum dhcp_token token
;
164 token
= next_token (&val
, &len
, cfile
);
165 if (token
!= STRING
) {
166 parse_warn (cfile
, "expecting a string");
167 skip_to_semi (cfile
);
170 s
= (char *)dmalloc (len
+ 1, MDL
);
172 log_fatal ("no memory for string %s.", val
);
173 memcpy (s
, val
, len
+ 1);
175 if (!parse_semi (cfile
)) {
189 * hostname :== IDENTIFIER
191 * | hostname DOT IDENTIFIER
194 char *parse_host_name (cfile
)
198 enum dhcp_token token
;
205 /* Read a dotted hostname... */
207 /* Read a token, which should be an identifier. */
208 token
= peek_token (&val
, (unsigned *)0, cfile
);
209 if (!is_identifier (token
) && token
!= NUMBER
)
211 token
= next_token (&val
, (unsigned *)0, cfile
);
213 /* Store this identifier... */
214 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
215 log_fatal ("can't allocate temp space for hostname.");
217 c
= cons ((caddr_t
)s
, c
);
218 len
+= strlen (s
) + 1;
219 /* Look for a dot; if it's there, keep going, otherwise
221 token
= peek_token (&val
, (unsigned *)0, cfile
);
223 token
= next_token (&val
, (unsigned *)0, cfile
);
227 } while (token
== DOT
);
229 /* Should be at least one token. */
233 /* Assemble the hostname together into a string. */
234 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
235 log_fatal ("can't allocate space for hostname.");
242 unsigned l
= strlen ((char *)(c
-> car
));
244 memcpy (t
, (char *)(c
-> car
), l
);
245 /* Free up temp space. */
246 dfree (c
-> car
, MDL
);
255 /* ip-addr-or-hostname :== ip-address | hostname
256 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
258 Parse an ip address or a hostname. If uniform is zero, put in
259 an expr_substring node to limit hostnames that evaluate to more
260 than one IP address. */
262 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
263 struct expression
**expr
;
268 enum dhcp_token token
;
269 unsigned char addr
[4];
270 unsigned len
= sizeof addr
;
272 struct expression
*x
= (struct expression
*)0;
274 token
= peek_token (&val
, (unsigned *)0, cfile
);
275 if (is_identifier (token
)) {
276 name
= parse_host_name (cfile
);
279 if (!make_host_lookup (expr
, name
)) {
285 if (!make_limit (&x
, *expr
, 4))
287 expression_dereference (expr
, MDL
);
290 } else if (token
== NUMBER
) {
291 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
293 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
295 if (token
!= RBRACE
&& token
!= LBRACE
)
296 token
= next_token (&val
, (unsigned *)0, cfile
);
297 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
300 skip_to_semi (cfile
);
308 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
311 int parse_ip_addr (cfile
, addr
)
316 enum dhcp_token token
;
319 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
320 &addr
-> len
, DOT
, 10, 8))
326 * Return true if every character in the string is hexidecimal.
329 is_hex_string(const char *s
) {
340 * ip-address6 :== (complicated set of rules)
342 * See section 2.2 of RFC 1884 for details.
344 * We are lazy for this. We pull numbers, names, colons, and dots
345 * together and then throw the resulting string at the inet_pton()
350 parse_ip6_addr(struct parse
*cfile
, struct iaddr
*addr
) {
351 enum dhcp_token token
;
355 char v6
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
360 token
= peek_token(&val
, NULL
, cfile
);
361 if ((((token
== NAME
) || (token
== NUMBER_OR_NAME
)) &&
362 is_hex_string(val
)) ||
367 next_token(&val
, NULL
, cfile
);
368 val_len
= strlen(val
);
369 if ((v6_len
+ val_len
) >= sizeof(v6
)) {
370 parse_warn(cfile
, "Invalid IPv6 address.");
374 memcpy(v6
+v6_len
, val
, val_len
);
383 if (inet_pton(AF_INET6
, v6
, addr
->iabuf
) <= 0) {
384 parse_warn(cfile
, "Invalid IPv6 address.");
393 * Same as parse_ip6_addr() above, but returns the value in the
394 * expression rather than in an address structure.
397 parse_ip6_addr_expr(struct expression
**expr
,
398 struct parse
*cfile
) {
401 if (!parse_ip6_addr(cfile
, &addr
)) {
404 return make_const_data(expr
, addr
.iabuf
, addr
.len
, 0, 1, MDL
);
408 * ip-address-with-subnet :== ip-address |
409 * ip-address "/" NUMBER
413 parse_ip_addr_with_subnet(cfile
, match
)
415 struct iaddrmatch
*match
;
417 const char *val
, *orig
;
418 enum dhcp_token token
;
421 unsigned char newval
, warnmask
=0;
423 if (parse_ip_addr(cfile
, &match
->addr
)) {
424 /* default to host mask */
425 prefixlen
= match
->addr
.len
* 8;
427 token
= peek_token(&val
, NULL
, cfile
);
429 if (token
== SLASH
) {
430 next_token(&val
, NULL
, cfile
);
431 token
= next_token(&val
, NULL
, cfile
);
433 if (token
!= NUMBER
) {
434 parse_warn(cfile
, "Invalid CIDR prefix length:"
435 " expecting a number.");
439 prefixlen
= atoi(val
);
442 prefixlen
> (match
->addr
.len
* 8)) {
443 parse_warn(cfile
, "subnet prefix is out of "
445 match
->addr
.len
* 8);
450 /* construct a suitable mask field */
453 match
->mask
.len
= match
->addr
.len
;
455 /* count of 0xff bytes in mask */
456 fflen
= prefixlen
/ 8;
458 /* set leading mask */
459 memset(match
->mask
.iabuf
, 0xff, fflen
);
462 if (fflen
< match
->mask
.len
) {
463 match
->mask
.iabuf
[fflen
] =
464 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen
% 8];
466 memset(match
->mask
.iabuf
+fflen
+1, 0x00,
467 match
->mask
.len
- fflen
- 1);
469 /* AND-out insignificant bits from supplied netmask. */
470 orig
= piaddr(match
->addr
);
472 newval
= match
->addr
.iabuf
[fflen
] &
473 match
->mask
.iabuf
[fflen
];
475 if (newval
!= match
->addr
.iabuf
[fflen
]) {
477 match
->addr
.iabuf
[fflen
] = newval
;
479 } while (++fflen
< match
->mask
.len
);
482 log_error("Warning: Extraneous bits removed "
483 "in address component of %s/%d.",
485 log_error("New value: %s/%d.",
486 piaddr(match
->addr
), prefixlen
);
494 "expecting ip-address or ip-address/prefixlen");
496 return 0; /* let caller pick up pieces */
500 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
501 * hardware-type :== ETHERNET | TOKEN_RING | FDDI
504 void parse_hardware_param (cfile
, hardware
)
506 struct hardware
*hardware
;
509 enum dhcp_token token
;
513 token
= next_token (&val
, (unsigned *)0, cfile
);
516 hardware
-> hbuf
[0] = HTYPE_ETHER
;
519 hardware
-> hbuf
[0] = HTYPE_IEEE802
;
522 hardware
-> hbuf
[0] = HTYPE_FDDI
;
525 if (!strncmp (val
, "unknown-", 8)) {
526 hardware
-> hbuf
[0] = atoi (&val
[8]);
529 "expecting a network hardware type");
530 skip_to_semi (cfile
);
536 /* Parse the hardware address information. Technically,
537 it would make a lot of sense to restrict the length of the
538 data we'll accept here to the length of a particular hardware
539 address type. Unfortunately, there are some broken clients
540 out there that put bogus data in the chaddr buffer, and we accept
541 that data in the lease file rather than simply failing on such
544 token
= peek_token (&val
, (unsigned *)0, cfile
);
546 hardware
-> hlen
= 1;
549 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
552 hardware
-> hlen
= 1;
555 if (hlen
+ 1 > sizeof hardware
-> hbuf
) {
557 parse_warn (cfile
, "hardware address too long");
559 hardware
-> hlen
= hlen
+ 1;
560 memcpy ((unsigned char *)&hardware
-> hbuf
[1], t
, hlen
);
561 if (hlen
+ 1 < sizeof hardware
-> hbuf
)
562 memset (&hardware
-> hbuf
[hlen
+ 1], 0,
563 (sizeof hardware
-> hbuf
) - hlen
- 1);
568 token
= next_token (&val
, (unsigned *)0, cfile
);
570 parse_warn (cfile
, "expecting semicolon.");
571 skip_to_semi (cfile
);
575 /* lease-time :== NUMBER SEMI */
577 void parse_lease_time (cfile
, timep
)
582 enum dhcp_token token
;
585 token
= next_token (&val
, (unsigned *)0, cfile
);
586 if (token
!= NUMBER
) {
587 parse_warn (cfile
, "Expecting numeric lease time");
588 skip_to_semi (cfile
);
591 convert_num(cfile
, (unsigned char *)&num
, val
, 10, 32);
592 /* Unswap the number - convert_num returns stuff in NBO. */
598 /* No BNF for numeric aggregates - that's defined by the caller. What
599 this function does is to parse a sequence of numbers separated by
600 the token specified in separator. If max is zero, any number of
601 numbers will be parsed; otherwise, exactly max numbers are
602 expected. Base and size tell us how to internalize the numbers
603 once they've been tokenized. */
605 unsigned char *parse_numeric_aggregate (cfile
, buf
,
606 max
, separator
, base
, size
)
615 enum dhcp_token token
;
616 unsigned char *bufp
= buf
, *s
, *t
;
621 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
623 log_fatal ("no space for numeric aggregate");
630 token
= peek_token (&val
, (unsigned *)0, cfile
);
631 if (token
!= separator
) {
634 if (token
!= RBRACE
&& token
!= LBRACE
)
635 token
= next_token (&val
,
638 parse_warn (cfile
, "too few numbers.");
640 skip_to_semi (cfile
);
641 return (unsigned char *)0;
643 token
= next_token (&val
, (unsigned *)0, cfile
);
645 token
= next_token (&val
, (unsigned *)0, cfile
);
647 if (token
== END_OF_FILE
) {
648 parse_warn (cfile
, "unexpected end of file");
652 /* Allow NUMBER_OR_NAME if base is 16. */
653 if (token
!= NUMBER
&&
654 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
655 parse_warn (cfile
, "expecting numeric value.");
656 skip_to_semi (cfile
);
657 return (unsigned char *)0;
659 /* If we can, convert the number now; otherwise, build
660 a linked list of all the numbers. */
662 convert_num (cfile
, s
, val
, base
, size
);
665 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
667 log_fatal ("no temp space for number.");
668 strcpy ((char *)t
, val
);
669 c
= cons ((caddr_t
)t
, c
);
671 } while (++count
!= *max
);
673 /* If we had to cons up a list, convert it now. */
675 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
677 log_fatal ("no space for numeric aggregate.");
678 s
= bufp
+ count
- size
/ 8;
683 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
685 /* Free up temp space. */
686 dfree (c
-> car
, MDL
);
693 void convert_num (cfile
, buf
, str
, base
, size
)
700 const char *ptr
= str
;
711 /* If base wasn't specified, figure it out from the data. */
713 if (ptr
[0] == '0') {
714 if (ptr
[1] == 'x') {
717 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
730 /* XXX assumes ASCII... */
732 tval
= tval
- 'a' + 10;
733 else if (tval
>= 'A')
734 tval
= tval
- 'A' + 10;
735 else if (tval
>= '0')
738 parse_warn (cfile
, "Bogus number: %s.", str
);
743 "Bogus number %s: digit %d not in base %d",
747 val
= val
* base
+ tval
;
751 max
= (1 << (size
- 1));
753 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
758 "%s%lo exceeds max (%d) for precision.",
760 (unsigned long)val
, max
);
764 "%s%lx exceeds max (%d) for precision.",
766 (unsigned long)val
, max
);
770 "%s%lu exceeds max (%d) for precision.",
772 (unsigned long)val
, max
);
780 *buf
= -(unsigned long)val
;
783 putShort (buf
, -(long)val
);
786 putLong (buf
, -(long)val
);
790 "Unexpected integer size: %d\n", size
);
796 *buf
= (u_int8_t
)val
;
799 putUShort (buf
, (u_int16_t
)val
);
806 "Unexpected integer size: %d\n", size
);
813 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
814 * NUMBER COLON NUMBER COLON NUMBER SEMI |
815 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
816 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
819 * Dates are stored in GMT or with a timezone offset; first number is day
820 * of week; next is year/month/day; next is hours:minutes:seconds on a
821 * 24-hour clock, followed by the timezone offset in seconds, which is
825 TIME
parse_date (cfile
)
830 int tzoff
, wday
, year
, mon
, mday
, hour
, min
, sec
;
832 enum dhcp_token token
;
833 static int months
[11] = { 31, 59, 90, 120, 151, 181,
834 212, 243, 273, 304, 334 };
836 /* Day of week, or "never"... */
837 token
= next_token (&val
, (unsigned *)0, cfile
);
838 if (token
== NEVER
) {
839 if (!parse_semi (cfile
))
844 /* This indicates 'local' time format. */
845 if (token
== EPOCH
) {
846 token
= next_token(&val
, NULL
, cfile
);
848 if (token
!= NUMBER
) {
849 parse_warn(cfile
, "Seconds since epoch expected.");
857 if (!parse_semi(cfile
))
863 if (token
!= NUMBER
) {
864 parse_warn (cfile
, "numeric day of week expected.");
866 skip_to_semi (cfile
);
872 token
= next_token (&val
, (unsigned *)0, cfile
);
873 if (token
!= NUMBER
) {
874 parse_warn (cfile
, "numeric year expected.");
876 skip_to_semi (cfile
);
880 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
881 somebody invents a time machine, I think we can safely disregard
882 it. This actually works around a stupid Y2K bug that was present
883 in a very early beta release of dhcpd. */
888 /* Slash separating year from month... */
889 token
= next_token (&val
, (unsigned *)0, cfile
);
890 if (token
!= SLASH
) {
892 "expected slash separating year from month.");
894 skip_to_semi (cfile
);
899 token
= next_token (&val
, (unsigned *)0, cfile
);
900 if (token
!= NUMBER
) {
901 parse_warn (cfile
, "numeric month expected.");
903 skip_to_semi (cfile
);
906 mon
= atoi (val
) - 1;
908 /* Slash separating month from day... */
909 token
= next_token (&val
, (unsigned *)0, cfile
);
910 if (token
!= SLASH
) {
912 "expected slash separating month from day.");
914 skip_to_semi (cfile
);
918 /* Day of month... */
919 token
= next_token (&val
, (unsigned *)0, cfile
);
920 if (token
!= NUMBER
) {
921 parse_warn (cfile
, "numeric day of month expected.");
923 skip_to_semi (cfile
);
929 token
= next_token (&val
, (unsigned *)0, cfile
);
930 if (token
!= NUMBER
) {
931 parse_warn (cfile
, "numeric hour expected.");
933 skip_to_semi (cfile
);
938 /* Colon separating hour from minute... */
939 token
= next_token (&val
, (unsigned *)0, cfile
);
940 if (token
!= COLON
) {
942 "expected colon separating hour from minute.");
944 skip_to_semi (cfile
);
949 token
= next_token (&val
, (unsigned *)0, cfile
);
950 if (token
!= NUMBER
) {
951 parse_warn (cfile
, "numeric minute expected.");
953 skip_to_semi (cfile
);
958 /* Colon separating minute from second... */
959 token
= next_token (&val
, (unsigned *)0, cfile
);
960 if (token
!= COLON
) {
962 "expected colon separating minute from second.");
964 skip_to_semi (cfile
);
969 token
= next_token (&val
, (unsigned *)0, cfile
);
970 if (token
!= NUMBER
) {
971 parse_warn (cfile
, "numeric second expected.");
973 skip_to_semi (cfile
);
978 token
= peek_token (&val
, (unsigned *)0, cfile
);
979 if (token
== NUMBER
) {
980 token
= next_token (&val
, (unsigned *)0, cfile
);
985 /* Make sure the date ends in a semicolon... */
986 if (!parse_semi (cfile
))
989 /* Guess the time value... */
990 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
991 (year
- 69) / 4 + /* Leap days since '70 */
992 (mon
/* Days in months this year */
995 (mon
> 1 && /* Leap day this year */
996 !((year
- 72) & 3)) +
997 mday
- 1) * 24) + /* Day of month */
999 min
) * 60) + sec
+ tzoff
;
1001 /* This guess could be wrong because of leap seconds or other
1002 weirdness we don't know about that the system does. For
1003 now, we're just going to accept the guess, but at some point
1004 it might be nice to do a successive approximation here to
1005 get an exact value. Even if the error is small, if the
1006 server is restarted frequently (and thus the lease database
1007 is reread), the error could accumulate into something
1014 * option-name :== IDENTIFIER |
1015 IDENTIFIER . IDENTIFIER
1019 parse_option_name (cfile
, allocate
, known
, opt
)
1020 struct parse
*cfile
;
1023 struct option
**opt
;
1026 enum dhcp_token token
;
1028 struct universe
*universe
;
1029 struct option
*option
;
1033 return ISC_R_INVALIDARG
;
1035 token
= next_token (&val
, (unsigned *)0, cfile
);
1036 if (!is_identifier (token
)) {
1038 "expecting identifier after option keyword.");
1040 skip_to_semi (cfile
);
1041 return ISC_R_BADPARSE
;
1043 uname
= dmalloc (strlen (val
) + 1, MDL
);
1045 log_fatal ("no memory for uname information.");
1046 strcpy (uname
, val
);
1047 token
= peek_token (&val
, (unsigned *)0, cfile
);
1049 /* Go ahead and take the DOT token... */
1050 token
= next_token (&val
, (unsigned *)0, cfile
);
1052 /* The next token should be an identifier... */
1053 token
= next_token (&val
, (unsigned *)0, cfile
);
1054 if (!is_identifier (token
)) {
1055 parse_warn (cfile
, "expecting identifier after '.'");
1057 skip_to_semi (cfile
);
1058 return ISC_R_BADPARSE
;
1061 /* Look up the option name hash table for the specified
1063 universe
= (struct universe
*)0;
1064 if (!universe_hash_lookup (&universe
, universe_hash
,
1066 parse_warn (cfile
, "no option space named %s.", uname
);
1067 skip_to_semi (cfile
);
1068 return ISC_R_NOTFOUND
;
1071 /* Use the default hash table, which contains all the
1072 standard dhcp option names. */
1074 universe
= &dhcp_universe
;
1077 /* Look up the actual option info... */
1078 option_name_hash_lookup(opt
, universe
->name_hash
, val
, 0, MDL
);
1081 /* If we didn't get an option structure, it's an undefined option. */
1085 /* If the option name is of the form unknown-[decimal], use
1086 * the trailing decimal value to find the option definition.
1087 * If there is no definition, construct one. This is to
1088 * support legacy use of unknown options in config files or
1091 } else if (strncasecmp(val
, "unknown-", 8) == 0) {
1094 /* Option code 0 is always illegal for us, thanks
1095 * to the option decoder.
1097 if (code
== 0 || code
== universe
->end
) {
1098 parse_warn(cfile
, "Option codes 0 and %u are illegal "
1099 "in the %s space.", universe
->end
,
1101 skip_to_semi(cfile
);
1103 return ISC_R_FAILURE
;
1106 /* It's odd to think of unknown option codes as
1107 * being known, but this means we know what the
1108 * parsed name is talking about.
1113 option_code_hash_lookup(opt
, universe
->code_hash
,
1117 /* If we did not find an option of that code,
1118 * manufacture an unknown-xxx option definition.
1119 * Its single reference will ensure that it is
1120 * deleted once the option is recycled out of
1121 * existence (by the parent).
1123 if (option
== NULL
) {
1124 option
= new_option(val
, MDL
);
1125 option
->universe
= universe
;
1126 option
->code
= code
;
1127 option
->format
= "X";
1128 option_reference(opt
, option
, MDL
);
1130 log_info("option %s has been redefined as option %s. "
1131 "Please update your configs if neccessary.",
1133 /* If we've been told to allocate, that means that this
1134 * (might) be an option code definition, so we'll create
1135 * an option structure and return it for the parent to
1138 } else if (allocate
) {
1139 option
= new_option(val
, MDL
);
1140 option
-> universe
= universe
;
1141 option_reference(opt
, option
, MDL
);
1143 parse_warn(cfile
, "no option named %s in space %s",
1144 val
, universe
->name
);
1145 skip_to_semi (cfile
);
1147 return ISC_R_NOTFOUND
;
1150 /* Free the initial identifier token. */
1152 return ISC_R_SUCCESS
;
1155 /* IDENTIFIER [WIDTHS] SEMI
1156 * WIDTHS ~= LENGTH WIDTH NUMBER
1160 void parse_option_space_decl (cfile
)
1161 struct parse
*cfile
;
1165 struct universe
**ua
, *nu
;
1167 int tsize
=1, lsize
=1, hsize
= 0;
1169 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
1170 which was checked by the
1172 token
= next_token (&val
, (unsigned *)0, cfile
);
1173 if (!is_identifier (token
)) {
1174 parse_warn (cfile
, "expecting identifier.");
1175 skip_to_semi (cfile
);
1178 nu
= new_universe (MDL
);
1180 log_fatal ("No memory for new option space.");
1182 /* Set up the server option universe... */
1183 nu_name
= dmalloc (strlen (val
) + 1, MDL
);
1185 log_fatal ("No memory for new option space name.");
1186 strcpy (nu_name
, val
);
1187 nu
-> name
= nu_name
;
1190 token
= next_token(&val
, NULL
, cfile
);
1196 token
= next_token(&val
, NULL
, cfile
);
1197 if (token
!= WIDTH
) {
1198 parse_warn(cfile
, "expecting width token.");
1202 token
= next_token(&val
, NULL
, cfile
);
1203 if (token
!= NUMBER
) {
1204 parse_warn(cfile
, "expecting number 1, 2, 4.");
1214 hsize
= BYTE_NAME_HASH_SIZE
;
1218 hsize
= WORD_NAME_HASH_SIZE
;
1222 hsize
= QUAD_NAME_HASH_SIZE
;
1225 parse_warn(cfile
, "invalid code width (%d), "
1226 "expecting a 1, 2 or 4.",
1233 token
= next_token(&val
, NULL
, cfile
);
1234 if (token
!= WIDTH
) {
1235 parse_warn(cfile
, "expecting width token.");
1239 token
= next_token(&val
, NULL
, cfile
);
1240 if (token
!= NUMBER
) {
1241 parse_warn(cfile
, "expecting number 1 or 2.");
1246 if (lsize
!= 1 && lsize
!= 2) {
1247 parse_warn(cfile
, "invalid length width (%d) "
1248 "expecting 1 or 2.", lsize
);
1255 token
= next_token(&val
, NULL
, cfile
);
1256 if (token
!= SIZE
) {
1257 parse_warn(cfile
, "expecting size token.");
1261 token
= next_token(&val
, NULL
, cfile
);
1262 if (token
!= NUMBER
) {
1263 parse_warn(cfile
, "expecting a 10base number");
1267 /* (2^31)-1 is the highest Mersenne prime we should
1271 if (hsize
< 0 || hsize
> 0x7FFFFFFF) {
1272 parse_warn(cfile
, "invalid hash length: %d",
1280 parse_warn(cfile
, "Unexpected token.");
1282 } while (token
!= SEMI
);
1285 hsize
= DEFAULT_SPACE_HASH_SIZE
;
1287 nu
-> lookup_func
= lookup_hashed_option
;
1288 nu
-> option_state_dereference
= hashed_option_state_dereference
;
1289 nu
-> foreach
= hashed_option_space_foreach
;
1290 nu
-> save_func
= save_hashed_option
;
1291 nu
-> delete_func
= delete_hashed_option
;
1292 nu
-> encapsulate
= hashed_option_space_encapsulate
;
1293 nu
-> decode
= parse_option_buffer
;
1294 nu
-> length_size
= lsize
;
1295 nu
-> tag_size
= tsize
;
1298 nu
->get_tag
= getUChar
;
1299 nu
->store_tag
= putUChar
;
1302 nu
->get_tag
= getUShort
;
1303 nu
->store_tag
= putUShort
;
1306 nu
->get_tag
= getULong
;
1307 nu
->store_tag
= putULong
;
1310 log_fatal("Impossible condition at %s:%d.", MDL
);
1314 nu
->get_length
= NULL
;
1315 nu
->store_length
= NULL
;
1318 nu
->get_length
= getUChar
;
1319 nu
->store_length
= putUChar
;
1322 nu
->get_length
= getUShort
;
1323 nu
->store_length
= putUShort
;
1326 log_fatal("Impossible condition at %s:%d.", MDL
);
1328 nu
-> index
= universe_count
++;
1329 if (nu
-> index
>= universe_max
) {
1330 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
1332 log_fatal ("No memory to expand option space array.");
1333 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
1335 dfree (universes
, MDL
);
1338 universes
[nu
-> index
] = nu
;
1339 if (!option_name_new_hash(&nu
->name_hash
, hsize
, MDL
) ||
1340 !option_code_new_hash(&nu
->code_hash
, hsize
, MDL
))
1341 log_fatal("Can't allocate %s option hash table.", nu
->name
);
1342 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
1346 dfree(nu_name
, MDL
);
1350 /* This is faked up to look good right now. Ideally, this should do a
1351 recursive parse and allow arbitrary data structure definitions, but for
1352 now it just allows you to specify a single type, an array of single types,
1353 a sequence of types, or an array of sequences of types.
1355 ocd :== NUMBER EQUALS ocsd SEMI
1357 ocsd :== ocsd_type |
1358 ocsd_type_sequence |
1359 ARRAY OF ocsd_simple_type_sequence
1361 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1363 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1365 ocsd_types :== ocsd_type |
1366 ocsd_types ocsd_type
1368 ocsd_type :== ocsd_simple_type |
1369 ARRAY OF ocsd_simple_type
1371 ocsd_simple_types :== ocsd_simple_type |
1372 ocsd_simple_types ocsd_simple_type
1374 ocsd_simple_type :== BOOLEAN |
1376 SIGNED INTEGER NUMBER |
1377 UNSIGNED INTEGER NUMBER |
1381 ENCAPSULATE identifier */
1383 int parse_option_code_definition (cfile
, option
)
1384 struct parse
*cfile
;
1385 struct option
*option
;
1388 enum dhcp_token token
;
1389 struct option
*oldopt
;
1390 unsigned arrayp
= 0;
1392 int no_more_in_record
= 0;
1399 int has_encapsulation
= 0;
1400 struct universe
*encapsulated
;
1402 /* Parse the option code. */
1403 token
= next_token (&val
, (unsigned *)0, cfile
);
1404 if (token
!= NUMBER
) {
1405 parse_warn (cfile
, "expecting option code number.");
1406 skip_to_semi (cfile
);
1409 option
-> code
= atoi (val
);
1411 token
= next_token (&val
, (unsigned *)0, cfile
);
1412 if (token
!= EQUAL
) {
1413 parse_warn (cfile
, "expecting \"=\"");
1414 skip_to_semi (cfile
);
1418 /* See if this is an array. */
1419 token
= next_token (&val
, (unsigned *)0, cfile
);
1420 if (token
== ARRAY
) {
1421 token
= next_token (&val
, (unsigned *)0, cfile
);
1423 parse_warn (cfile
, "expecting \"of\".");
1424 skip_to_semi (cfile
);
1428 token
= next_token (&val
, (unsigned *)0, cfile
);
1431 if (token
== LBRACE
) {
1433 token
= next_token (&val
, (unsigned *)0, cfile
);
1436 /* At this point we're expecting a data type. */
1438 if (has_encapsulation
) {
1440 "encapsulate must always be the last item.");
1441 skip_to_semi (cfile
);
1448 parse_warn (cfile
, "no nested arrays.");
1449 skip_to_rbrace (cfile
, recordp
);
1451 skip_to_semi (cfile
);
1454 token
= next_token (&val
, (unsigned *)0, cfile
);
1456 parse_warn (cfile
, "expecting \"of\".");
1457 skip_to_semi (cfile
);
1460 arrayp
= recordp
+ 1;
1461 token
= next_token (&val
, (unsigned *)0, cfile
);
1462 if ((recordp
) && (token
== LBRACE
)) {
1464 "only uniform array inside record.");
1465 skip_to_rbrace (cfile
, recordp
+ 1);
1466 skip_to_semi (cfile
);
1476 token
= next_token (&val
, (unsigned *)0, cfile
);
1477 if (token
!= NUMBER
) {
1478 parse_warn (cfile
, "expecting number.");
1479 skip_to_rbrace (cfile
, recordp
);
1481 skip_to_semi (cfile
);
1484 switch (atoi (val
)) {
1486 type
= is_signed
? 'b' : 'B';
1489 type
= is_signed
? 's' : 'S';
1492 type
= is_signed
? 'l' : 'L';
1496 "%s bit precision is not supported.", val
);
1497 skip_to_rbrace (cfile
, recordp
);
1499 skip_to_semi (cfile
);
1506 token
= next_token (&val
, (unsigned *)0, cfile
);
1507 if (token
!= INTEGER
) {
1508 parse_warn (cfile
, "expecting \"integer\" keyword.");
1509 skip_to_rbrace (cfile
, recordp
);
1511 skip_to_semi (cfile
);
1529 /* Consume optional compression indicator. */
1530 token
= peek_token(&val
, NULL
, cfile
);
1531 if (token
== COMPRESSED
) {
1532 token
= next_token(&val
, NULL
, cfile
);
1533 tokbuf
[tokix
++] = 'D';
1542 parse_warn (cfile
, "arrays of text strings not %s",
1544 skip_to_rbrace (cfile
, recordp
);
1546 skip_to_semi (cfile
);
1549 no_more_in_record
= 1;
1556 token
= next_token (&val
, (unsigned *)0, cfile
);
1557 if (!is_identifier (token
)) {
1559 "expecting option space identifier");
1560 skip_to_semi (cfile
);
1563 encapsulated
= NULL
;
1564 if (!universe_hash_lookup(&encapsulated
, universe_hash
,
1565 val
, strlen(val
), MDL
)) {
1566 parse_warn(cfile
, "unknown option space %s", val
);
1567 skip_to_semi (cfile
);
1570 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1572 tokbuf
[tokix
++] = 'E';
1573 strcpy (&tokbuf
[tokix
], val
);
1574 tokix
+= strlen (val
);
1576 has_encapsulation
= 1;
1580 parse_warn (cfile
, "unknown data type %s", val
);
1581 skip_to_rbrace (cfile
, recordp
);
1583 skip_to_semi (cfile
);
1587 if (tokix
== sizeof tokbuf
) {
1589 parse_warn (cfile
, "too many types in record.");
1590 skip_to_rbrace (cfile
, recordp
);
1592 skip_to_semi (cfile
);
1595 tokbuf
[tokix
++] = type
;
1598 token
= next_token (&val
, (unsigned *)0, cfile
);
1599 if (arrayp
> recordp
) {
1600 if (tokix
== sizeof tokbuf
) {
1602 "too many types in record.");
1603 skip_to_rbrace (cfile
, 1);
1604 skip_to_semi (cfile
);
1608 tokbuf
[tokix
++] = 'a';
1610 if (token
== COMMA
) {
1611 if (no_more_in_record
) {
1613 "%s must be at end of record.",
1614 type
== 't' ? "text" : "string");
1615 skip_to_rbrace (cfile
, 1);
1617 skip_to_semi (cfile
);
1620 token
= next_token (&val
, (unsigned *)0, cfile
);
1623 if (token
!= RBRACE
) {
1624 parse_warn (cfile
, "expecting right brace.");
1625 skip_to_rbrace (cfile
, 1);
1627 skip_to_semi (cfile
);
1631 if (!parse_semi (cfile
)) {
1632 parse_warn (cfile
, "semicolon expected.");
1633 skip_to_semi (cfile
);
1635 skip_to_semi (cfile
);
1638 if (has_encapsulation
&& arrayp
) {
1640 "Arrays of encapsulations don't make sense.");
1643 s
= dmalloc(tokix
+ (arrayp
? 1 : 0) + 1, MDL
);
1645 log_fatal("no memory for option format.");
1647 memcpy(s
, tokbuf
, tokix
);
1649 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1653 option
-> format
= s
;
1656 option_code_hash_lookup(&oldopt
, option
->universe
->code_hash
,
1657 &option
->code
, 0, MDL
);
1659 option_name_hash_delete(option
->universe
->name_hash
,
1660 oldopt
->name
, 0, MDL
);
1661 option_code_hash_delete(option
->universe
->code_hash
,
1662 &oldopt
->code
, 0, MDL
);
1664 option_dereference(&oldopt
, MDL
);
1666 option_code_hash_add(option
->universe
->code_hash
, &option
->code
, 0,
1668 option_name_hash_add(option
->universe
->name_hash
, option
->name
, 0,
1670 if (has_encapsulation
) {
1671 /* INSIST(tokbuf[0] == 'E'); */
1672 /* INSIST(encapsulated != NULL); */
1673 if (!option_code_hash_lookup(&encapsulated
->enc_opt
,
1674 option
->universe
->code_hash
,
1675 &option
->code
, 0, MDL
)) {
1676 log_fatal("error finding encapsulated option (%s:%d)",
1684 * base64 :== NUMBER_OR_STRING
1687 int parse_base64 (data
, cfile
)
1688 struct data_string
*data
;
1689 struct parse
*cfile
;
1691 enum dhcp_token token
;
1695 static unsigned char
1696 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1697 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1698 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1699 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1700 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1701 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1702 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1703 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1704 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1705 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1706 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1707 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1708 struct string_list
*bufs
= (struct string_list
*)0,
1709 *last
= (struct string_list
*)0,
1714 /* It's possible for a + or a / to cause a base64 quantity to be
1715 tokenized into more than one token, so we have to parse them all
1716 in before decoding. */
1720 token
= next_token (&val
, &l
, cfile
);
1721 t
= dmalloc (l
+ sizeof *t
, MDL
);
1723 log_fatal ("no memory for base64 buffer.");
1724 memset (t
, 0, (sizeof *t
) - 1);
1725 memcpy (t
-> string
, val
, l
+ 1);
1732 token
= peek_token (&val
, (unsigned *)0, cfile
);
1733 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1734 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1738 data
-> len
= (data
-> len
* 3) / 4;
1739 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1740 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1742 data
-> data
= (unsigned char *)0;
1747 for (t
= bufs
; t
; t
= t
-> next
) {
1748 for (i
= 0; t
-> string
[i
]; i
++) {
1749 unsigned foo
= t
-> string
[i
];
1750 if (terminated
&& foo
!= '=') {
1752 "stuff after base64 '=' terminator: %s.",
1756 if (foo
< ' ' || foo
> 'z') {
1759 "invalid base64 character %d.",
1762 data_string_forget (data
, MDL
);
1768 foo
= from64
[foo
- ' '];
1771 acc
= (acc
<< 6) + foo
;
1776 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1781 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1785 data
-> buffer
-> data
[j
++] = acc
;
1796 "partial base64 value left over: %d.",
1801 data
-> data
= data
-> buffer
-> data
;
1803 for (t
= bufs
; t
; t
= last
) {
1815 * colon-separated-hex-list :== NUMBER |
1816 * NUMBER COLON colon-separated-hex-list
1819 int parse_cshl (data
, cfile
)
1820 struct data_string
*data
;
1821 struct parse
*cfile
;
1823 u_int8_t ibuf
[128];
1826 struct option_tag
*sl
= (struct option_tag
*)0;
1827 struct option_tag
*next
, **last
= &sl
;
1828 enum dhcp_token token
;
1833 token
= next_token (&val
, (unsigned *)0, cfile
);
1834 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1835 parse_warn (cfile
, "expecting hexadecimal number.");
1836 skip_to_semi (cfile
);
1837 for (; sl
; sl
= next
) {
1843 if (ilen
== sizeof ibuf
) {
1844 next
= (struct option_tag
*)
1846 sizeof (struct option_tag
), MDL
);
1848 log_fatal ("no memory for string list.");
1849 memcpy (next
-> data
, ibuf
, ilen
);
1851 last
= &next
-> next
;
1855 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1857 token
= peek_token (&val
, (unsigned *)0, cfile
);
1860 token
= next_token (&val
, (unsigned *)0, cfile
);
1863 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1864 log_fatal ("no memory to store octet data.");
1865 data
-> data
= &data
-> buffer
-> data
[0];
1866 data
-> len
= tlen
+ ilen
;
1867 data
-> terminated
= 0;
1869 rvp
= &data
-> buffer
-> data
[0];
1872 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
1878 memcpy (rvp
, ibuf
, ilen
);
1883 * executable-statements :== executable-statement executable-statements |
1884 * executable-statement
1886 * executable-statement :==
1888 * ADD class-name SEMI |
1890 * OPTION option-parameter SEMI |
1891 * SUPERSEDE option-parameter SEMI |
1892 * PREPEND option-parameter SEMI |
1893 * APPEND option-parameter SEMI
1896 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
1897 struct executable_statement
**statements
;
1898 struct parse
*cfile
;
1900 enum expression_context case_context
;
1902 struct executable_statement
**next
;
1905 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
1906 next
= &((*next
) -> next
);
1912 int parse_executable_statement (result
, cfile
, lose
, case_context
)
1913 struct executable_statement
**result
;
1914 struct parse
*cfile
;
1916 enum expression_context case_context
;
1918 enum dhcp_token token
;
1921 struct executable_statement base
;
1923 struct option
*option
=NULL
;
1924 struct option_cache
*cache
;
1925 struct expression
**ep
;
1929 struct dns_zone
*zone
;
1930 isc_result_t status
;
1933 token
= peek_token (&val
, (unsigned *)0, cfile
);
1935 case DB_TIME_FORMAT
:
1936 next_token(&val
, NULL
, cfile
);
1938 token
= next_token(&val
, NULL
, cfile
);
1939 if (token
== DEFAULT
) {
1940 db_time_format
= DEFAULT_TIME_FORMAT
;
1941 } else if (token
== LOCAL
) {
1942 db_time_format
= LOCAL_TIME_FORMAT
;
1944 parse_warn(cfile
, "Expecting 'local' or 'default'.");
1946 skip_to_semi(cfile
);
1951 token
= next_token(&val
, NULL
, cfile
);
1952 if (token
!= SEMI
) {
1953 parse_warn(cfile
, "Expecting a semicolon.");
1958 /* We're done here. */
1962 next_token (&val
, (unsigned *)0, cfile
);
1963 return parse_if_statement (result
, cfile
, lose
);
1966 token
= next_token (&val
, (unsigned *)0, cfile
);
1967 token
= next_token (&val
, (unsigned *)0, cfile
);
1968 if (token
!= STRING
) {
1969 parse_warn (cfile
, "expecting class name.");
1970 skip_to_semi (cfile
);
1974 cta
= (struct class *)0;
1975 status
= find_class (&cta
, val
, MDL
);
1976 if (status
!= ISC_R_SUCCESS
) {
1977 parse_warn (cfile
, "class %s: %s",
1978 val
, isc_result_totext (status
));
1979 skip_to_semi (cfile
);
1983 if (!parse_semi (cfile
)) {
1987 if (!executable_statement_allocate (result
, MDL
))
1988 log_fatal ("no memory for new statement.");
1989 (*result
) -> op
= add_statement
;
1990 (*result
) -> data
.add
= cta
;
1994 token
= next_token (&val
, (unsigned *)0, cfile
);
1995 if (!parse_semi (cfile
)) {
1999 if (!executable_statement_allocate (result
, MDL
))
2000 log_fatal ("no memory for new statement.");
2001 (*result
) -> op
= break_statement
;
2005 token
= next_token (&val
, (unsigned *)0, cfile
);
2007 status
= parse_option_name (cfile
, 0, &known
, &option
);
2008 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2012 status
= parse_option_statement(result
, cfile
, 1, option
,
2013 send_option_statement
);
2014 option_dereference(&option
, MDL
);
2019 token
= next_token (&val
, (unsigned *)0, cfile
);
2021 status
= parse_option_name (cfile
, 0, &known
, &option
);
2022 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2026 status
= parse_option_statement(result
, cfile
, 1, option
,
2027 supersede_option_statement
);
2028 option_dereference(&option
, MDL
);
2040 token
= next_token (&val
, (unsigned *)0, cfile
);
2041 cache
= (struct option_cache
*)0;
2042 if (!parse_allow_deny (&cache
, cfile
, flag
))
2044 if (!executable_statement_allocate (result
, MDL
))
2045 log_fatal ("no memory for new statement.");
2046 (*result
) -> op
= supersede_option_statement
;
2047 (*result
) -> data
.option
= cache
;
2051 token
= next_token (&val
, (unsigned *)0, cfile
);
2052 token
= peek_token (&val
, (unsigned *)0, cfile
);
2054 goto switch_default
;
2056 status
= parse_option_name (cfile
, 0, &known
, &option
);
2057 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2061 status
= parse_option_statement(result
, cfile
, 1, option
,
2062 default_option_statement
);
2063 option_dereference(&option
, MDL
);
2067 token
= next_token (&val
, (unsigned *)0, cfile
);
2069 status
= parse_option_name (cfile
, 0, &known
, &option
);
2070 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2074 status
= parse_option_statement(result
, cfile
, 1, option
,
2075 prepend_option_statement
);
2076 option_dereference(&option
, MDL
);
2080 token
= next_token (&val
, (unsigned *)0, cfile
);
2082 status
= parse_option_name (cfile
, 0, &known
, &option
);
2083 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2087 status
= parse_option_statement(result
, cfile
, 1, option
,
2088 append_option_statement
);
2089 option_dereference(&option
, MDL
);
2093 token
= next_token (&val
, (unsigned *)0, cfile
);
2094 return parse_on_statement (result
, cfile
, lose
);
2097 token
= next_token (&val
, (unsigned *)0, cfile
);
2098 return parse_switch_statement (result
, cfile
, lose
);
2101 token
= next_token (&val
, (unsigned *)0, cfile
);
2102 if (case_context
== context_any
) {
2104 "case statement in inappropriate scope.");
2106 skip_to_semi (cfile
);
2109 return parse_case_statement (result
,
2110 cfile
, lose
, case_context
);
2113 token
= next_token (&val
, (unsigned *)0, cfile
);
2114 if (case_context
== context_any
) {
2115 parse_warn (cfile
, "switch default statement in %s",
2116 "inappropriate scope.");
2121 if (!executable_statement_allocate (result
, MDL
))
2122 log_fatal ("no memory for default statement.");
2123 (*result
) -> op
= default_statement
;
2129 token
= next_token (&val
, (unsigned *)0, cfile
);
2130 if (token
== DEFINE
)
2135 token
= next_token (&val
, (unsigned *)0, cfile
);
2136 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2138 "%s can't be a variable name", val
);
2140 skip_to_semi (cfile
);
2145 if (!executable_statement_allocate (result
, MDL
))
2146 log_fatal ("no memory for set statement.");
2147 (*result
) -> op
= flag
? define_statement
: set_statement
;
2148 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
2149 if (!(*result
)->data
.set
.name
)
2150 log_fatal ("can't allocate variable name");
2151 strcpy ((*result
) -> data
.set
.name
, val
);
2152 token
= next_token (&val
, (unsigned *)0, cfile
);
2154 if (token
== LPAREN
) {
2155 struct string_list
*head
, *cur
, *new;
2156 struct expression
*expr
;
2157 head
= cur
= (struct string_list
*)0;
2159 token
= next_token (&val
,
2160 (unsigned *)0, cfile
);
2161 if (token
== RPAREN
)
2163 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2165 "expecting argument name");
2166 skip_to_rbrace (cfile
, 0);
2168 executable_statement_dereference
2172 new = ((struct string_list
*)
2173 dmalloc (sizeof (struct string_list
) +
2174 strlen (val
), MDL
));
2176 log_fatal ("can't allocate string.");
2177 memset (new, 0, sizeof *new);
2178 strcpy (new -> string
, val
);
2185 token
= next_token (&val
,
2186 (unsigned *)0, cfile
);
2187 } while (token
== COMMA
);
2189 if (token
!= RPAREN
) {
2190 parse_warn (cfile
, "expecting right paren.");
2192 skip_to_semi (cfile
);
2194 executable_statement_dereference (result
, MDL
);
2198 token
= next_token (&val
, (unsigned *)0, cfile
);
2199 if (token
!= LBRACE
) {
2200 parse_warn (cfile
, "expecting left brace.");
2204 expr
= (struct expression
*)0;
2205 if (!(expression_allocate (&expr
, MDL
)))
2206 log_fatal ("can't allocate expression.");
2207 expr
-> op
= expr_function
;
2208 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
2209 log_fatal ("can't allocate fundef.");
2210 expr
-> data
.func
-> args
= head
;
2211 (*result
) -> data
.set
.expr
= expr
;
2213 if (!(parse_executable_statements
2214 (&expr
-> data
.func
-> statements
, cfile
, lose
,
2220 token
= next_token (&val
, (unsigned *)0, cfile
);
2221 if (token
!= RBRACE
) {
2222 parse_warn (cfile
, "expecting rigt brace.");
2226 if (token
!= EQUAL
) {
2228 "expecting '=' in %s statement.",
2229 flag
? "define" : "set");
2233 if (!parse_expression (&(*result
) -> data
.set
.expr
,
2234 cfile
, lose
, context_any
,
2235 (struct expression
**)0,
2239 "expecting expression.");
2242 skip_to_semi (cfile
);
2243 executable_statement_dereference (result
, MDL
);
2246 if (!parse_semi (cfile
)) {
2248 executable_statement_dereference (result
, MDL
);
2255 token
= next_token (&val
, (unsigned *)0, cfile
);
2257 token
= next_token (&val
, (unsigned *)0, cfile
);
2258 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2260 "%s can't be a variable name", val
);
2262 skip_to_semi (cfile
);
2267 if (!executable_statement_allocate (result
, MDL
))
2268 log_fatal ("no memory for set statement.");
2269 (*result
) -> op
= unset_statement
;
2270 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
2271 if (!(*result
)->data
.unset
)
2272 log_fatal ("can't allocate variable name");
2273 strcpy ((*result
) -> data
.unset
, val
);
2274 if (!parse_semi (cfile
)) {
2276 executable_statement_dereference (result
, MDL
);
2282 token
= next_token (&val
, (unsigned *)0, cfile
);
2284 if (!executable_statement_allocate (result
, MDL
))
2285 log_fatal ("no memory for eval statement.");
2286 (*result
) -> op
= eval_statement
;
2288 if (!parse_expression (&(*result
) -> data
.eval
,
2289 cfile
, lose
, context_data
, /* XXX */
2290 (struct expression
**)0, expr_none
)) {
2293 "expecting data expression.");
2296 skip_to_semi (cfile
);
2297 executable_statement_dereference (result
, MDL
);
2300 if (!parse_semi (cfile
)) {
2302 executable_statement_dereference (result
, MDL
);
2307 #ifdef ENABLE_EXECUTE
2308 token
= next_token(&val
, NULL
, cfile
);
2310 if (!executable_statement_allocate (result
, MDL
))
2311 log_fatal ("no memory for execute statement.");
2312 (*result
)->op
= execute_statement
;
2314 token
= next_token(&val
, NULL
, cfile
);
2315 if (token
!= LPAREN
) {
2316 parse_warn(cfile
, "left parenthesis expected.");
2317 skip_to_semi(cfile
);
2322 token
= next_token(&val
, &len
, cfile
);
2323 if (token
!= STRING
) {
2324 parse_warn(cfile
, "Expecting a quoted string.");
2325 skip_to_semi(cfile
);
2330 (*result
)->data
.execute
.command
= dmalloc(len
+ 1, MDL
);
2331 if ((*result
)->data
.execute
.command
== NULL
)
2332 log_fatal("can't allocate command name");
2333 strcpy((*result
)->data
.execute
.command
, val
);
2335 ep
= &(*result
)->data
.execute
.arglist
;
2336 (*result
)->data
.execute
.argc
= 0;
2338 while((token
= next_token(&val
, NULL
, cfile
)) == COMMA
) {
2339 if (!expression_allocate(ep
, MDL
))
2340 log_fatal ("can't allocate expression");
2342 if (!parse_data_expression (&(*ep
) -> data
.arg
.val
,
2346 "expecting expression.");
2349 skip_to_semi(cfile
);
2353 ep
= &(*ep
)->data
.arg
.next
;
2354 (*result
)->data
.execute
.argc
++;
2357 if (token
!= RPAREN
) {
2358 parse_warn(cfile
, "right parenthesis expected.");
2359 skip_to_semi(cfile
);
2364 if (!parse_semi (cfile
)) {
2366 executable_statement_dereference (result
, MDL
);
2368 #else /* ! ENABLE_EXECUTE */
2369 parse_warn(cfile
, "define ENABLE_EXECUTE in site.h to "
2370 "enable execute(); expressions.");
2371 skip_to_semi(cfile
);
2374 #endif /* ENABLE_EXECUTE */
2378 token
= next_token (&val
, (unsigned *)0, cfile
);
2380 if (!executable_statement_allocate (result
, MDL
))
2381 log_fatal ("no memory for return statement.");
2382 (*result
) -> op
= return_statement
;
2384 if (!parse_expression (&(*result
) -> data
.retval
,
2385 cfile
, lose
, context_data
,
2386 (struct expression
**)0, expr_none
)) {
2389 "expecting data expression.");
2392 skip_to_semi (cfile
);
2393 executable_statement_dereference (result
, MDL
);
2396 if (!parse_semi (cfile
)) {
2398 executable_statement_dereference (result
, MDL
);
2404 token
= next_token (&val
, (unsigned *)0, cfile
);
2406 if (!executable_statement_allocate (result
, MDL
))
2407 log_fatal ("no memory for log statement.");
2408 (*result
) -> op
= log_statement
;
2410 token
= next_token (&val
, (unsigned *)0, cfile
);
2411 if (token
!= LPAREN
) {
2412 parse_warn (cfile
, "left parenthesis expected.");
2413 skip_to_semi (cfile
);
2418 token
= peek_token (&val
, (unsigned *)0, cfile
);
2420 if (token
== FATAL
) {
2421 (*result
) -> data
.log
.priority
= log_priority_fatal
;
2422 } else if (token
== ERROR
) {
2423 (*result
) -> data
.log
.priority
= log_priority_error
;
2424 } else if (token
== TOKEN_DEBUG
) {
2425 (*result
) -> data
.log
.priority
= log_priority_debug
;
2426 } else if (token
== INFO
) {
2427 (*result
) -> data
.log
.priority
= log_priority_info
;
2429 (*result
) -> data
.log
.priority
= log_priority_debug
;
2433 token
= next_token (&val
, (unsigned *)0, cfile
);
2434 token
= next_token (&val
, (unsigned *)0, cfile
);
2435 if (token
!= COMMA
) {
2436 parse_warn (cfile
, "comma expected.");
2437 skip_to_semi (cfile
);
2443 if (!(parse_data_expression
2444 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
2445 skip_to_semi (cfile
);
2450 token
= next_token (&val
, (unsigned *)0, cfile
);
2451 if (token
!= RPAREN
) {
2452 parse_warn (cfile
, "right parenthesis expected.");
2453 skip_to_semi (cfile
);
2458 token
= next_token (&val
, (unsigned *)0, cfile
);
2459 if (token
!= SEMI
) {
2460 parse_warn (cfile
, "semicolon expected.");
2461 skip_to_semi (cfile
);
2467 /* Not really a statement, but we parse it here anyway
2468 because it's appropriate for all DHCP agents with
2471 token
= next_token (&val
, (unsigned *)0, cfile
);
2472 zone
= (struct dns_zone
*)0;
2473 if (!dns_zone_allocate (&zone
, MDL
))
2474 log_fatal ("no memory for new zone.");
2475 zone
-> name
= parse_host_name (cfile
);
2476 if (!zone
-> name
) {
2477 parse_warn (cfile
, "expecting hostname.");
2480 skip_to_semi (cfile
);
2481 dns_zone_dereference (&zone
, MDL
);
2484 i
= strlen (zone
-> name
);
2485 if (zone
-> name
[i
- 1] != '.') {
2486 s
= dmalloc ((unsigned)i
+ 2, MDL
);
2488 parse_warn (cfile
, "no trailing '.' on zone");
2491 strcpy (s
, zone
-> name
);
2494 dfree (zone
-> name
, MDL
);
2497 if (!parse_zone (zone
, cfile
))
2499 status
= enter_dns_zone (zone
);
2500 if (status
!= ISC_R_SUCCESS
) {
2501 parse_warn (cfile
, "dns zone key %s: %s",
2502 zone
-> name
, isc_result_totext (status
));
2503 dns_zone_dereference (&zone
, MDL
);
2506 dns_zone_dereference (&zone
, MDL
);
2509 /* Also not really a statement, but same idea as above. */
2511 token
= next_token (&val
, (unsigned *)0, cfile
);
2512 if (!parse_key (cfile
)) {
2519 if (config_universe
&& is_identifier (token
)) {
2520 option
= (struct option
*)0;
2521 option_name_hash_lookup(&option
,
2522 config_universe
->name_hash
,
2525 token
= next_token (&val
,
2526 (unsigned *)0, cfile
);
2527 status
= parse_option_statement
2528 (result
, cfile
, 1, option
,
2529 supersede_option_statement
);
2530 option_dereference(&option
, MDL
);
2535 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2536 /* This is rather ugly. Since function calls are
2537 data expressions, fake up an eval statement. */
2538 if (!executable_statement_allocate (result
, MDL
))
2539 log_fatal ("no memory for eval statement.");
2540 (*result
) -> op
= eval_statement
;
2542 if (!parse_expression (&(*result
) -> data
.eval
,
2543 cfile
, lose
, context_data
,
2544 (struct expression
**)0,
2547 parse_warn (cfile
, "expecting "
2551 skip_to_semi (cfile
);
2552 executable_statement_dereference (result
, MDL
);
2555 if (!parse_semi (cfile
)) {
2557 executable_statement_dereference (result
, MDL
);
2570 /* zone-statements :== zone-statement |
2571 zone-statement zone-statements
2573 PRIMARY ip-addresses SEMI |
2574 SECONDARY ip-addresses SEMI |
2576 ip-addresses :== ip-addr-or-hostname |
2577 ip-addr-or-hostname COMMA ip-addresses
2578 key-reference :== KEY STRING |
2581 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2586 struct option_cache
*oc
;
2589 token
= next_token (&val
, (unsigned *)0, cfile
);
2590 if (token
!= LBRACE
) {
2591 parse_warn (cfile
, "expecting left brace");
2596 token
= peek_token (&val
, (unsigned *)0, cfile
);
2599 if (zone
-> primary
) {
2601 "more than one primary.");
2602 skip_to_semi (cfile
);
2605 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2606 log_fatal ("can't allocate primary option cache.");
2607 oc
= zone
-> primary
;
2611 if (zone
-> secondary
) {
2612 parse_warn (cfile
, "more than one secondary.");
2613 skip_to_semi (cfile
);
2616 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2617 log_fatal ("can't allocate secondary.");
2618 oc
= zone
-> secondary
;
2620 token
= next_token (&val
, (unsigned *)0, cfile
);
2622 struct expression
*expr
= (struct expression
*)0;
2623 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2625 "expecting IP addr or hostname.");
2626 skip_to_semi (cfile
);
2629 if (oc
-> expression
) {
2630 struct expression
*old
=
2631 (struct expression
*)0;
2632 expression_reference (&old
,
2635 expression_dereference (&oc
-> expression
,
2637 if (!make_concat (&oc
-> expression
,
2639 log_fatal ("no memory for concat.");
2640 expression_dereference (&expr
, MDL
);
2641 expression_dereference (&old
, MDL
);
2643 expression_reference (&oc
-> expression
,
2645 expression_dereference (&expr
, MDL
);
2647 token
= next_token (&val
, (unsigned *)0, cfile
);
2648 } while (token
== COMMA
);
2649 if (token
!= SEMI
) {
2650 parse_warn (cfile
, "expecting semicolon.");
2651 skip_to_semi (cfile
);
2657 token
= next_token (&val
, (unsigned *)0, cfile
);
2658 token
= peek_token (&val
, (unsigned *)0, cfile
);
2659 if (token
== STRING
) {
2660 token
= next_token (&val
, (unsigned *)0, cfile
);
2661 key_name
= (char *)0;
2663 key_name
= parse_host_name (cfile
);
2665 parse_warn (cfile
, "expecting key name.");
2666 skip_to_semi (cfile
);
2671 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2673 parse_warn (cfile
, "unknown key %s", val
);
2675 dfree (key_name
, MDL
);
2676 if (!parse_semi (cfile
))
2686 token
= next_token (&val
, (unsigned *)0, cfile
);
2687 if (token
!= RBRACE
) {
2688 parse_warn (cfile
, "expecting right brace.");
2694 /* key-statements :== key-statement |
2695 key-statement key-statements
2697 ALGORITHM host-name SEMI |
2698 secret-definition SEMI
2699 secret-definition :== SECRET base64val |
2702 int parse_key (struct parse
*cfile
)
2707 struct auth_key
*key
;
2708 struct data_string ds
;
2709 isc_result_t status
;
2712 key
= (struct auth_key
*)0;
2713 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2714 log_fatal ("no memory for key");
2716 token
= peek_token (&val
, (unsigned *)0, cfile
);
2717 if (token
== STRING
) {
2718 token
= next_token (&val
, (unsigned *)0, cfile
);
2719 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2721 log_fatal ("no memory for key name.");
2722 strcpy (key
-> name
, val
);
2725 key
-> name
= parse_host_name (cfile
);
2727 parse_warn (cfile
, "expecting key name.");
2728 skip_to_semi (cfile
);
2733 token
= next_token (&val
, (unsigned *)0, cfile
);
2734 if (token
!= LBRACE
) {
2735 parse_warn (cfile
, "expecting left brace");
2740 token
= next_token (&val
, (unsigned *)0, cfile
);
2743 if (key
-> algorithm
) {
2745 "key %s: too many algorithms",
2749 key
-> algorithm
= parse_host_name (cfile
);
2750 if (!key
-> algorithm
) {
2752 "expecting key algorithm name.");
2755 if (!parse_semi (cfile
))
2757 /* If the algorithm name isn't an FQDN, tack on
2758 the .SIG-ALG.REG.NET. domain. */
2759 s
= strrchr (key
-> algorithm
, '.');
2761 static char add
[] = ".SIG-ALG.REG.INT.";
2762 s
= dmalloc (strlen (key
-> algorithm
) +
2765 log_error ("no memory for key %s.",
2769 strcpy (s
, key
-> algorithm
);
2771 dfree (key
-> algorithm
, MDL
);
2772 key
-> algorithm
= s
;
2774 /* If there is no trailing '.', hack one in. */
2775 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2777 log_error ("no memory for key %s.",
2781 strcpy (s
, key
-> algorithm
);
2783 dfree (key
-> algorithm
, MDL
);
2784 key
-> algorithm
= s
;
2790 parse_warn (cfile
, "key %s: too many secrets",
2795 memset (&ds
, 0, sizeof(ds
));
2796 if (!parse_base64 (&ds
, cfile
))
2798 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2800 if (status
!= ISC_R_SUCCESS
)
2802 memcpy (key
-> key
-> value
,
2803 ds
.buffer
-> data
, ds
.len
);
2804 data_string_forget (&ds
, MDL
);
2806 if (!parse_semi (cfile
))
2815 if (token
!= RBRACE
) {
2816 parse_warn (cfile
, "expecting right brace.");
2819 /* Allow the BIND 8 syntax, which has a semicolon after each
2821 token
= peek_token (&val
, (unsigned *)0, cfile
);
2823 token
= next_token (&val
, (unsigned *)0, cfile
);
2825 /* Remember the key. */
2826 status
= omapi_auth_key_enter (key
);
2827 if (status
!= ISC_R_SUCCESS
) {
2828 parse_warn (cfile
, "tsig key %s: %s",
2829 key
-> name
, isc_result_totext (status
));
2832 omapi_auth_key_dereference (&key
, MDL
);
2836 skip_to_rbrace (cfile
, 1);
2838 omapi_auth_key_dereference (&key
, MDL
);
2843 * on-statement :== event-types LBRACE executable-statements RBRACE
2844 * event-types :== event-type OR event-types |
2846 * event-type :== EXPIRY | COMMIT | RELEASE
2849 int parse_on_statement (result
, cfile
, lose
)
2850 struct executable_statement
**result
;
2851 struct parse
*cfile
;
2854 enum dhcp_token token
;
2857 if (!executable_statement_allocate (result
, MDL
))
2858 log_fatal ("no memory for new statement.");
2859 (*result
) -> op
= on_statement
;
2862 token
= next_token (&val
, (unsigned *)0, cfile
);
2865 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
2869 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
2873 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
2877 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
2881 parse_warn (cfile
, "expecting a lease event type");
2882 skip_to_semi (cfile
);
2884 executable_statement_dereference (result
, MDL
);
2887 token
= next_token (&val
, (unsigned *)0, cfile
);
2888 } while (token
== OR
);
2890 /* Semicolon means no statements. */
2894 if (token
!= LBRACE
) {
2895 parse_warn (cfile
, "left brace expected.");
2896 skip_to_semi (cfile
);
2898 executable_statement_dereference (result
, MDL
);
2901 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
2902 cfile
, lose
, context_any
)) {
2904 /* Try to even things up. */
2906 token
= next_token (&val
,
2907 (unsigned *)0, cfile
);
2908 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
2909 executable_statement_dereference (result
, MDL
);
2913 token
= next_token (&val
, (unsigned *)0, cfile
);
2914 if (token
!= RBRACE
) {
2915 parse_warn (cfile
, "right brace expected.");
2916 skip_to_semi (cfile
);
2918 executable_statement_dereference (result
, MDL
);
2925 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2929 int parse_switch_statement (result
, cfile
, lose
)
2930 struct executable_statement
**result
;
2931 struct parse
*cfile
;
2934 enum dhcp_token token
;
2937 if (!executable_statement_allocate (result
, MDL
))
2938 log_fatal ("no memory for new statement.");
2939 (*result
) -> op
= switch_statement
;
2941 token
= next_token (&val
, (unsigned *)0, cfile
);
2942 if (token
!= LPAREN
) {
2943 parse_warn (cfile
, "expecting left brace.");
2946 skip_to_semi (cfile
);
2948 executable_statement_dereference (result
, MDL
);
2952 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
2953 cfile
, lose
, context_data_or_numeric
,
2954 (struct expression
**)0, expr_none
)) {
2957 "expecting data or numeric expression.");
2963 token
= next_token (&val
, (unsigned *)0, cfile
);
2964 if (token
!= RPAREN
) {
2965 parse_warn (cfile
, "right paren expected.");
2969 token
= next_token (&val
, (unsigned *)0, cfile
);
2970 if (token
!= LBRACE
) {
2971 parse_warn (cfile
, "left brace expected.");
2974 if (!(parse_executable_statements
2975 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
2976 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
2977 ? context_data
: context_numeric
)))) {
2979 skip_to_rbrace (cfile
, 1);
2980 executable_statement_dereference (result
, MDL
);
2984 token
= next_token (&val
, (unsigned *)0, cfile
);
2985 if (token
!= RBRACE
) {
2986 parse_warn (cfile
, "right brace expected.");
2993 * case-statement :== CASE expr COLON
2997 int parse_case_statement (result
, cfile
, lose
, case_context
)
2998 struct executable_statement
**result
;
2999 struct parse
*cfile
;
3001 enum expression_context case_context
;
3003 enum dhcp_token token
;
3006 if (!executable_statement_allocate (result
, MDL
))
3007 log_fatal ("no memory for new statement.");
3008 (*result
) -> op
= case_statement
;
3010 if (!parse_expression (&(*result
) -> data
.c_case
,
3011 cfile
, lose
, case_context
,
3012 (struct expression
**)0, expr_none
))
3015 parse_warn (cfile
, "expecting %s expression.",
3016 (case_context
== context_data
3017 ? "data" : "numeric"));
3021 skip_to_semi (cfile
);
3022 executable_statement_dereference (result
, MDL
);
3026 token
= next_token (&val
, (unsigned *)0, cfile
);
3027 if (token
!= COLON
) {
3028 parse_warn (cfile
, "colon expected.");
3035 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3038 * else-statement :== <null> |
3039 * ELSE LBRACE executable-statements RBRACE |
3040 * ELSE IF if-statement |
3041 * ELSIF if-statement
3044 int parse_if_statement (result
, cfile
, lose
)
3045 struct executable_statement
**result
;
3046 struct parse
*cfile
;
3049 enum dhcp_token token
;
3053 if (!executable_statement_allocate (result
, MDL
))
3054 log_fatal ("no memory for if statement.");
3056 (*result
) -> op
= if_statement
;
3058 token
= peek_token (&val
, (unsigned *)0, cfile
);
3059 if (token
== LPAREN
) {
3061 next_token (&val
, (unsigned *)0, cfile
);
3066 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
3069 parse_warn (cfile
, "boolean expression expected.");
3070 executable_statement_dereference (result
, MDL
);
3074 #if defined (DEBUG_EXPRESSION_PARSE)
3075 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
3078 token
= next_token (&val
, (unsigned *)0, cfile
);
3079 if (token
!= RPAREN
) {
3080 parse_warn (cfile
, "expecting right paren.");
3082 executable_statement_dereference (result
, MDL
);
3086 token
= next_token (&val
, (unsigned *)0, cfile
);
3087 if (token
!= LBRACE
) {
3088 parse_warn (cfile
, "left brace expected.");
3089 skip_to_semi (cfile
);
3091 executable_statement_dereference (result
, MDL
);
3094 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
3095 cfile
, lose
, context_any
)) {
3097 /* Try to even things up. */
3099 token
= next_token (&val
,
3100 (unsigned *)0, cfile
);
3101 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3102 executable_statement_dereference (result
, MDL
);
3106 token
= next_token (&val
, (unsigned *)0, cfile
);
3107 if (token
!= RBRACE
) {
3108 parse_warn (cfile
, "right brace expected.");
3109 skip_to_semi (cfile
);
3111 executable_statement_dereference (result
, MDL
);
3114 token
= peek_token (&val
, (unsigned *)0, cfile
);
3115 if (token
== ELSE
) {
3116 token
= next_token (&val
, (unsigned *)0, cfile
);
3117 token
= peek_token (&val
, (unsigned *)0, cfile
);
3119 token
= next_token (&val
, (unsigned *)0, cfile
);
3120 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3124 "expecting if statement");
3125 executable_statement_dereference (result
, MDL
);
3129 } else if (token
!= LBRACE
) {
3130 parse_warn (cfile
, "left brace or if expected.");
3131 skip_to_semi (cfile
);
3133 executable_statement_dereference (result
, MDL
);
3136 token
= next_token (&val
, (unsigned *)0, cfile
);
3137 if (!(parse_executable_statements
3138 (&(*result
) -> data
.ie
.fc
,
3139 cfile
, lose
, context_any
))) {
3140 executable_statement_dereference (result
, MDL
);
3143 token
= next_token (&val
, (unsigned *)0, cfile
);
3144 if (token
!= RBRACE
) {
3145 parse_warn (cfile
, "right brace expected.");
3146 skip_to_semi (cfile
);
3148 executable_statement_dereference (result
, MDL
);
3152 } else if (token
== ELSIF
) {
3153 token
= next_token (&val
, (unsigned *)0, cfile
);
3154 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3158 "expecting conditional.");
3159 executable_statement_dereference (result
, MDL
);
3164 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
3170 * boolean_expression :== CHECK STRING |
3171 * NOT boolean-expression |
3172 * data-expression EQUAL data-expression |
3173 * data-expression BANG EQUAL data-expression |
3174 * boolean-expression AND boolean-expression |
3175 * boolean-expression OR boolean-expression
3176 * EXISTS OPTION-NAME
3179 int parse_boolean_expression (expr
, cfile
, lose
)
3180 struct expression
**expr
;
3181 struct parse
*cfile
;
3184 /* Parse an expression... */
3185 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
3186 (struct expression
**)0, expr_none
))
3189 if (!is_boolean_expression (*expr
) &&
3190 (*expr
) -> op
!= expr_variable_reference
&&
3191 (*expr
) -> op
!= expr_funcall
) {
3192 parse_warn (cfile
, "Expecting a boolean expression.");
3194 expression_dereference (expr
, MDL
);
3201 * data_expression :== SUBSTRING LPAREN data-expression COMMA
3202 * numeric-expression COMMA
3203 * numeric-expression RPAREN |
3204 * CONCAT LPAREN data-expression COMMA
3205 * data-expression RPAREN
3206 * SUFFIX LPAREN data_expression COMMA
3207 * numeric-expression RPAREN |
3208 * LCASE LPAREN data_expression RPAREN |
3209 * UCASE LPAREN data_expression RPAREN |
3210 * OPTION option_name |
3212 * PACKET LPAREN numeric-expression COMMA
3213 * numeric-expression RPAREN |
3215 * colon_separated_hex_list
3218 int parse_data_expression (expr
, cfile
, lose
)
3219 struct expression
**expr
;
3220 struct parse
*cfile
;
3223 /* Parse an expression... */
3224 if (!parse_expression (expr
, cfile
, lose
, context_data
,
3225 (struct expression
**)0, expr_none
))
3228 if (!is_data_expression (*expr
) &&
3229 (*expr
) -> op
!= expr_variable_reference
&&
3230 (*expr
) -> op
!= expr_funcall
) {
3231 expression_dereference (expr
, MDL
);
3232 parse_warn (cfile
, "Expecting a data expression.");
3240 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3241 * COMMA number RPAREN |
3245 int parse_numeric_expression (expr
, cfile
, lose
)
3246 struct expression
**expr
;
3247 struct parse
*cfile
;
3250 /* Parse an expression... */
3251 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
3252 (struct expression
**)0, expr_none
))
3255 if (!is_numeric_expression (*expr
) &&
3256 (*expr
) -> op
!= expr_variable_reference
&&
3257 (*expr
) -> op
!= expr_funcall
) {
3258 expression_dereference (expr
, MDL
);
3259 parse_warn (cfile
, "Expecting a numeric expression.");
3267 * dns-expression :==
3268 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3269 * data-expression COMMA numeric-expression RPAREN
3270 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3271 * data-expression RPAREN
3272 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3273 * data-expression RPAREN
3274 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3275 * data-expression RPAREN
3276 * ns-class :== IN | CHAOS | HS | NUMBER
3277 * ns-type :== A | PTR | MX | TXT | NUMBER
3280 int parse_dns_expression (expr
, cfile
, lose
)
3281 struct expression
**expr
;
3282 struct parse
*cfile
;
3285 /* Parse an expression... */
3286 if (!parse_expression (expr
, cfile
, lose
, context_dns
,
3287 (struct expression
**)0, expr_none
))
3290 if (!is_dns_expression (*expr
) &&
3291 (*expr
) -> op
!= expr_variable_reference
&&
3292 (*expr
) -> op
!= expr_funcall
) {
3293 expression_dereference (expr
, MDL
);
3294 parse_warn (cfile
, "Expecting a dns update subexpression.");
3301 /* Parse a subexpression that does not contain a binary operator. */
3303 int parse_non_binary (expr
, cfile
, lose
, context
)
3304 struct expression
**expr
;
3305 struct parse
*cfile
;
3307 enum expression_context context
;
3309 enum dhcp_token token
;
3311 struct collection
*col
;
3312 struct option
*option
;
3313 struct expression
*nexp
, **ep
;
3315 enum expr_op opcode
;
3318 struct executable_statement
*stmt
;
3321 isc_result_t status
, code
;
3324 token
= peek_token (&val
, (unsigned *)0, cfile
);
3326 /* Check for unary operators... */
3329 token
= next_token (&val
, (unsigned *)0, cfile
);
3330 token
= next_token (&val
, (unsigned *)0, cfile
);
3331 if (token
!= STRING
) {
3332 parse_warn (cfile
, "string expected.");
3333 skip_to_semi (cfile
);
3337 for (col
= collections
; col
; col
= col
-> next
)
3338 if (!strcmp (col
-> name
, val
))
3341 parse_warn (cfile
, "unknown collection.");
3345 if (!expression_allocate (expr
, MDL
))
3346 log_fatal ("can't allocate expression");
3347 (*expr
) -> op
= expr_check
;
3348 (*expr
) -> data
.check
= col
;
3352 token
= next_token (&val
, (unsigned *)0, cfile
);
3353 if (context
== context_dns
) {
3354 token
= peek_token (&val
, (unsigned *)0, cfile
);
3357 if (!expression_allocate (expr
, MDL
))
3358 log_fatal ("can't allocate expression");
3359 (*expr
) -> op
= expr_not
;
3360 if (!parse_non_binary (&(*expr
) -> data
.not,
3361 cfile
, lose
, context_boolean
)) {
3363 parse_warn (cfile
, "expression expected");
3364 skip_to_semi (cfile
);
3367 expression_dereference (expr
, MDL
);
3370 if (!is_boolean_expression ((*expr
) -> data
.not)) {
3372 parse_warn (cfile
, "boolean expression expected");
3373 skip_to_semi (cfile
);
3374 expression_dereference (expr
, MDL
);
3380 token
= next_token (&val
, (unsigned *)0, cfile
);
3381 if (!parse_expression (expr
, cfile
, lose
, context
,
3382 (struct expression
**)0, expr_none
)) {
3384 parse_warn (cfile
, "expression expected");
3385 skip_to_semi (cfile
);
3390 token
= next_token (&val
, (unsigned *)0, cfile
);
3391 if (token
!= RPAREN
) {
3393 parse_warn (cfile
, "right paren expected");
3394 skip_to_semi (cfile
);
3400 if (context
== context_dns
)
3402 token
= next_token (&val
, (unsigned *)0, cfile
);
3403 if (!expression_allocate (expr
, MDL
))
3404 log_fatal ("can't allocate expression");
3405 (*expr
) -> op
= expr_exists
;
3407 /* Pass reference directly to expression structure. */
3408 status
= parse_option_name(cfile
, 0, &known
,
3409 &(*expr
)->data
.option
);
3410 if (status
!= ISC_R_SUCCESS
||
3411 (*expr
)->data
.option
== NULL
) {
3413 expression_dereference (expr
, MDL
);
3419 token
= next_token (&val
, (unsigned *)0, cfile
);
3420 if (!expression_allocate (expr
, MDL
))
3421 log_fatal ("can't allocate expression");
3422 (*expr
) -> op
= expr_static
;
3426 token
= next_token (&val
, (unsigned *)0, cfile
);
3427 if (!expression_allocate (expr
, MDL
))
3428 log_fatal ("can't allocate expression");
3429 (*expr
) -> op
= expr_known
;
3433 token
= next_token (&val
, (unsigned *)0, cfile
);
3434 if (!expression_allocate (expr
, MDL
))
3435 log_fatal ("can't allocate expression");
3436 (*expr
) -> op
= expr_substring
;
3438 token
= next_token (&val
, (unsigned *)0, cfile
);
3439 if (token
!= LPAREN
) {
3441 expression_dereference (expr
, MDL
);
3442 parse_warn (cfile
, "left parenthesis expected.");
3447 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
3450 expression_dereference (expr
, MDL
);
3453 "expecting data expression.");
3454 skip_to_semi (cfile
);
3460 token
= next_token (&val
, (unsigned *)0, cfile
);
3461 if (token
!= COMMA
) {
3463 expression_dereference (expr
, MDL
);
3464 parse_warn (cfile
, "comma expected.");
3470 if (!parse_numeric_expression
3471 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
3475 "expecting numeric expression.");
3476 skip_to_semi (cfile
);
3479 expression_dereference (expr
, MDL
);
3483 token
= next_token (&val
, (unsigned *)0, cfile
);
3487 if (!parse_numeric_expression
3488 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
3491 token
= next_token (&val
, (unsigned *)0, cfile
);
3492 if (token
!= RPAREN
) {
3494 parse_warn (cfile
, "right parenthesis expected.");
3496 expression_dereference (expr
, MDL
);
3502 token
= next_token (&val
, (unsigned *)0, cfile
);
3503 if (!expression_allocate (expr
, MDL
))
3504 log_fatal ("can't allocate expression");
3505 (*expr
) -> op
= expr_suffix
;
3507 token
= next_token (&val
, (unsigned *)0, cfile
);
3508 if (token
!= LPAREN
)
3511 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
3515 token
= next_token (&val
, (unsigned *)0, cfile
);
3519 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
3523 token
= next_token (&val
, (unsigned *)0, cfile
);
3524 if (token
!= RPAREN
)
3529 token
= next_token(&val
, (unsigned *)0, cfile
);
3530 if (!expression_allocate(expr
, MDL
))
3531 log_fatal ("can't allocate expression");
3532 (*expr
)->op
= expr_lcase
;
3534 token
= next_token(&val
, (unsigned *)0, cfile
);
3535 if (token
!= LPAREN
)
3538 if (!parse_data_expression(&(*expr
)->data
.lcase
, cfile
, lose
))
3541 token
= next_token(&val
, (unsigned *)0, cfile
);
3542 if (token
!= RPAREN
)
3547 token
= next_token(&val
, (unsigned *)0, cfile
);
3548 if (!expression_allocate(expr
, MDL
))
3549 log_fatal ("can't allocate expression");
3550 (*expr
)->op
= expr_ucase
;
3552 token
= next_token (&val
, (unsigned *)0, cfile
);
3553 if (token
!= LPAREN
)
3556 if (!parse_data_expression(&(*expr
)->data
.ucase
,
3560 token
= next_token(&val
, (unsigned *)0, cfile
);
3561 if (token
!= RPAREN
)
3566 token
= next_token (&val
, (unsigned *)0, cfile
);
3567 if (!expression_allocate (expr
, MDL
))
3568 log_fatal ("can't allocate expression");
3569 (*expr
) -> op
= expr_concat
;
3571 token
= next_token (&val
, (unsigned *)0, cfile
);
3572 if (token
!= LPAREN
)
3575 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3579 token
= next_token (&val
, (unsigned *)0, cfile
);
3584 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3588 token
= next_token (&val
, (unsigned *)0, cfile
);
3590 if (token
== COMMA
) {
3591 nexp
= (struct expression
*)0;
3592 if (!expression_allocate (&nexp
, MDL
))
3593 log_fatal ("can't allocate at CONCAT2");
3594 nexp
-> op
= expr_concat
;
3595 expression_reference (&nexp
-> data
.concat
[0],
3597 expression_dereference (expr
, MDL
);
3598 expression_reference (expr
, nexp
, MDL
);
3599 expression_dereference (&nexp
, MDL
);
3600 goto concat_another
;
3603 if (token
!= RPAREN
)
3607 case BINARY_TO_ASCII
:
3608 token
= next_token (&val
, (unsigned *)0, cfile
);
3609 if (!expression_allocate (expr
, MDL
))
3610 log_fatal ("can't allocate expression");
3611 (*expr
) -> op
= expr_binary_to_ascii
;
3613 token
= next_token (&val
, (unsigned *)0, cfile
);
3614 if (token
!= LPAREN
)
3617 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3621 token
= next_token (&val
, (unsigned *)0, cfile
);
3625 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3629 token
= next_token (&val
, (unsigned *)0, cfile
);
3633 if (!parse_data_expression (&(*expr
) -> data
.b2a
.separator
,
3637 token
= next_token (&val
, (unsigned *)0, cfile
);
3641 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3645 token
= next_token (&val
, (unsigned *)0, cfile
);
3646 if (token
!= RPAREN
)
3651 token
= next_token (&val
, (unsigned *)0, cfile
);
3652 if (!expression_allocate (expr
, MDL
))
3653 log_fatal ("can't allocate expression");
3654 (*expr
) -> op
= expr_reverse
;
3656 token
= next_token (&val
, (unsigned *)0, cfile
);
3657 if (token
!= LPAREN
)
3660 if (!(parse_numeric_expression
3661 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3664 token
= next_token (&val
, (unsigned *)0, cfile
);
3668 if (!(parse_data_expression
3669 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3672 token
= next_token (&val
, (unsigned *)0, cfile
);
3673 if (token
!= RPAREN
)
3678 /* pick (a, b, c) actually produces an internal representation
3679 that looks like pick (a, pick (b, pick (c, nil))). */
3680 token
= next_token (&val
, (unsigned *)0, cfile
);
3681 if (!(expression_allocate (expr
, MDL
)))
3682 log_fatal ("can't allocate expression");
3684 token
= next_token (&val
, (unsigned *)0, cfile
);
3685 if (token
!= LPAREN
)
3688 nexp
= (struct expression
*)0;
3689 expression_reference (&nexp
, *expr
, MDL
);
3691 nexp
-> op
= expr_pick_first_value
;
3692 if (!(parse_data_expression
3693 (&nexp
-> data
.pick_first_value
.car
,
3697 token
= next_token (&val
, (unsigned *)0, cfile
);
3698 if (token
== COMMA
) {
3699 struct expression
*foo
= (struct expression
*)0;
3700 if (!expression_allocate (&foo
, MDL
))
3701 log_fatal ("can't allocate expr");
3702 expression_reference
3703 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3704 expression_dereference (&nexp
, MDL
);
3705 expression_reference (&nexp
, foo
, MDL
);
3706 expression_dereference (&foo
, MDL
);
3708 } while (token
== COMMA
);
3709 expression_dereference (&nexp
, MDL
);
3711 if (token
!= RPAREN
)
3715 /* dns-update and dns-delete are present for historical
3716 purposes, but are deprecated in favor of ns-update
3717 in combination with update, delete, exists and not
3721 #if !defined (NSUPDATE)
3723 "Please rebuild dhcpd with --with-nsupdate.");
3725 token
= next_token (&val
, (unsigned *)0, cfile
);
3726 if (token
== DNS_UPDATE
)
3727 opcode
= expr_ns_add
;
3729 opcode
= expr_ns_delete
;
3731 token
= next_token (&val
, (unsigned *)0, cfile
);
3732 if (token
!= LPAREN
)
3735 token
= next_token (&val
, (unsigned *)0, cfile
);
3736 if (token
!= STRING
) {
3738 "parse_expression: expecting string.");
3740 skip_to_semi (cfile
);
3745 if (!strcasecmp (val
, "a"))
3747 else if (!strcasecmp (val
, "aaaa"))
3749 else if (!strcasecmp (val
, "ptr"))
3751 else if (!strcasecmp (val
, "mx"))
3753 else if (!strcasecmp (val
, "cname"))
3755 else if (!strcasecmp (val
, "TXT"))
3758 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3762 s
= (opcode
== expr_ns_add
3764 : "old-dns-delete");
3765 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3767 log_fatal ("can't allocate name for %s", s
);
3769 if (!expression_allocate (expr
, MDL
))
3770 log_fatal ("can't allocate expression");
3771 (*expr
) -> op
= expr_funcall
;
3772 (*expr
) -> data
.funcall
.name
= cptr
;
3774 /* Fake up a function call. */
3775 ep
= &(*expr
) -> data
.funcall
.arglist
;
3776 if (!expression_allocate (ep
, MDL
))
3777 log_fatal ("can't allocate expression");
3778 (*ep
) -> op
= expr_arg
;
3779 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3780 log_fatal ("can't allocate rrtype value.");
3782 token
= next_token (&val
, (unsigned *)0, cfile
);
3785 ep
= &((*ep
) -> data
.arg
.next
);
3786 if (!expression_allocate (ep
, MDL
))
3787 log_fatal ("can't allocate expression");
3788 (*ep
) -> op
= expr_arg
;
3789 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3793 token
= next_token (&val
, (unsigned *)0, cfile
);
3797 ep
= &((*ep
) -> data
.arg
.next
);
3798 if (!expression_allocate (ep
, MDL
))
3799 log_fatal ("can't allocate expression");
3800 (*ep
) -> op
= expr_arg
;
3801 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3805 if (opcode
== expr_ns_add
) {
3806 token
= next_token (&val
, (unsigned *)0, cfile
);
3810 ep
= &((*ep
) -> data
.arg
.next
);
3811 if (!expression_allocate (ep
, MDL
))
3812 log_fatal ("can't allocate expression");
3813 (*ep
) -> op
= expr_arg
;
3814 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
3817 "expecting numeric expression.");
3822 token
= next_token (&val
, (unsigned *)0, cfile
);
3823 if (token
!= RPAREN
)
3828 #if !defined (NSUPDATE)
3830 "Please rebuild dhcpd with --with-nsupdate.");
3832 token
= next_token (&val
, (unsigned *)0, cfile
);
3833 if (!expression_allocate (expr
, MDL
))
3834 log_fatal ("can't allocate expression");
3836 token
= next_token (&val
, (unsigned *)0, cfile
);
3837 if (token
!= LPAREN
)
3842 nexp
-> op
= expr_dns_transaction
;
3843 if (!(parse_dns_expression
3844 (&nexp
-> data
.dns_transaction
.car
,
3850 "expecting dns expression.");
3852 expression_dereference (expr
, MDL
);
3857 token
= next_token (&val
, (unsigned *)0, cfile
);
3859 if (token
== COMMA
) {
3860 if (!(expression_allocate
3861 (&nexp
-> data
.dns_transaction
.cdr
,
3864 ("can't allocate expression");
3865 nexp
= nexp
-> data
.dns_transaction
.cdr
;
3867 } while (token
== COMMA
);
3869 if (token
!= RPAREN
)
3873 /* NOT EXISTS is special cased above... */
3875 token
= peek_token (&val
, (unsigned *)0, cfile
);
3876 if (token
!= EXISTS
) {
3877 parse_warn (cfile
, "expecting DNS prerequisite.");
3881 opcode
= expr_ns_not_exists
;
3884 opcode
= expr_ns_add
;
3887 opcode
= expr_ns_delete
;
3890 opcode
= expr_ns_exists
;
3892 token
= next_token (&val
, (unsigned *)0, cfile
);
3894 #if !defined (NSUPDATE)
3896 "Please rebuild dhcpd with --with-nsupdate.");
3898 if (!expression_allocate (expr
, MDL
))
3899 log_fatal ("can't allocate expression");
3900 (*expr
) -> op
= opcode
;
3902 token
= next_token (&val
, (unsigned *)0, cfile
);
3903 if (token
!= LPAREN
)
3906 token
= next_token (&val
, (unsigned *)0, cfile
);
3907 if (!is_identifier (token
) && token
!= NUMBER
) {
3908 parse_warn (cfile
, "expecting identifier or number.");
3910 expression_dereference (expr
, MDL
);
3911 skip_to_semi (cfile
);
3916 if (token
== NUMBER
)
3917 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
3918 else if (!strcasecmp (val
, "in"))
3919 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
3920 else if (!strcasecmp (val
, "chaos"))
3921 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
3922 else if (!strcasecmp (val
, "hs"))
3923 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
3925 parse_warn (cfile
, "unexpected rrclass: %s", val
);
3929 token
= next_token (&val
, (unsigned *)0, cfile
);
3933 token
= next_token (&val
, (unsigned *)0, cfile
);
3934 if (!is_identifier (token
) && token
!= NUMBER
) {
3935 parse_warn (cfile
, "expecting identifier or number.");
3939 if (token
== NUMBER
)
3940 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
3941 else if (!strcasecmp (val
, "a"))
3942 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
3943 else if (!strcasecmp (val
, "aaaa"))
3944 (*expr
) -> data
.ns_add
.rrtype
= T_AAAA
;
3945 else if (!strcasecmp (val
, "ptr"))
3946 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
3947 else if (!strcasecmp (val
, "mx"))
3948 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
3949 else if (!strcasecmp (val
, "cname"))
3950 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
3951 else if (!strcasecmp (val
, "TXT"))
3952 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
3954 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3958 token
= next_token (&val
, (unsigned *)0, cfile
);
3962 if (!(parse_data_expression
3963 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
3966 token
= next_token (&val
, (unsigned *)0, cfile
);
3970 if (!(parse_data_expression
3971 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
3974 if (opcode
== expr_ns_add
) {
3975 token
= next_token (&val
, (unsigned *)0, cfile
);
3979 if (!(parse_numeric_expression
3980 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
3984 "expecting numeric expression.");
3989 token
= next_token (&val
, (unsigned *)0, cfile
);
3990 if (token
!= RPAREN
)
3996 if (!expression_allocate (expr
, MDL
))
3997 log_fatal ("can't allocate expression");
3998 (*expr
) -> op
= (token
== OPTION
4000 : expr_config_option
);
4001 token
= next_token (&val
, (unsigned *)0, cfile
);
4003 /* Pass reference directly to expression structure. */
4004 status
= parse_option_name(cfile
, 0, &known
,
4005 &(*expr
)->data
.option
);
4006 if (status
!= ISC_R_SUCCESS
||
4007 (*expr
)->data
.option
== NULL
) {
4009 expression_dereference (expr
, MDL
);
4015 token
= next_token (&val
, (unsigned *)0, cfile
);
4016 if (!expression_allocate (expr
, MDL
))
4017 log_fatal ("can't allocate expression");
4018 (*expr
) -> op
= expr_hardware
;
4021 case LEASED_ADDRESS
:
4022 token
= next_token (&val
, (unsigned *)0, cfile
);
4023 if (!expression_allocate (expr
, MDL
))
4024 log_fatal ("can't allocate expression");
4025 (*expr
) -> op
= expr_leased_address
;
4029 token
= next_token (&val
, (unsigned *)0, cfile
);
4030 if (!expression_allocate (expr
, MDL
))
4031 log_fatal ("can't allocate expression");
4032 (*expr
) -> op
= expr_client_state
;
4036 token
= next_token (&val
, (unsigned *)0, cfile
);
4037 if (!expression_allocate (expr
, MDL
))
4038 log_fatal ("can't allocate expression");
4039 (*expr
) -> op
= expr_filename
;
4043 token
= next_token (&val
, (unsigned *)0, cfile
);
4044 if (!expression_allocate (expr
, MDL
))
4045 log_fatal ("can't allocate expression");
4046 (*expr
) -> op
= expr_sname
;
4050 token
= next_token (&val
, (unsigned *)0, cfile
);
4051 if (!expression_allocate (expr
, MDL
))
4052 log_fatal ("can't allocate expression");
4053 (*expr
) -> op
= expr_lease_time
;
4057 token
= next_token (&val
, (unsigned *)0, cfile
);
4058 if (!expression_allocate (expr
, MDL
))
4059 log_fatal ("can't allocate expression");
4060 (*expr
) -> op
= expr_null
;
4063 case HOST_DECL_NAME
:
4064 token
= next_token (&val
, (unsigned *)0, cfile
);
4065 if (!expression_allocate (expr
, MDL
))
4066 log_fatal ("can't allocate expression");
4067 (*expr
) -> op
= expr_host_decl_name
;
4070 case UPDATED_DNS_RR
:
4071 token
= next_token (&val
, (unsigned *)0, cfile
);
4073 token
= next_token (&val
, (unsigned *)0, cfile
);
4074 if (token
!= LPAREN
)
4077 token
= next_token (&val
, (unsigned *)0, cfile
);
4078 if (token
!= STRING
) {
4079 parse_warn (cfile
, "expecting string.");
4084 if (!strcasecmp (val
, "a"))
4085 s
= "ddns-fwd-name";
4086 else if (!strcasecmp (val
, "ptr"))
4087 s
= "ddns-rev-name";
4089 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
4093 token
= next_token (&val
, (unsigned *)0, cfile
);
4094 if (token
!= RPAREN
)
4097 if (!expression_allocate (expr
, MDL
))
4098 log_fatal ("can't allocate expression");
4099 (*expr
) -> op
= expr_variable_reference
;
4100 (*expr
) -> data
.variable
=
4101 dmalloc (strlen (s
) + 1, MDL
);
4102 if (!(*expr
) -> data
.variable
)
4103 log_fatal ("can't allocate variable name.");
4104 strcpy ((*expr
) -> data
.variable
, s
);
4108 token
= next_token (&val
, (unsigned *)0, cfile
);
4109 if (!expression_allocate (expr
, MDL
))
4110 log_fatal ("can't allocate expression");
4111 (*expr
) -> op
= expr_packet
;
4113 token
= next_token (&val
, (unsigned *)0, cfile
);
4114 if (token
!= LPAREN
)
4117 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
4121 token
= next_token (&val
, (unsigned *)0, cfile
);
4125 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
4129 token
= next_token (&val
, (unsigned *)0, cfile
);
4130 if (token
!= RPAREN
)
4135 token
= next_token (&val
, &len
, cfile
);
4136 if (!make_const_data (expr
, (const unsigned char *)val
,
4138 log_fatal ("can't make constant string expression.");
4142 token
= next_token (&val
, (unsigned *)0, cfile
);
4143 token
= next_token (&val
, (unsigned *)0, cfile
);
4144 if (token
!= LPAREN
) {
4145 parse_warn (cfile
, "left parenthesis expected.");
4150 if (!expression_allocate (expr
, MDL
))
4151 log_fatal ("can't allocate expression");
4153 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
4157 "expecting data expression.");
4158 skip_to_semi (cfile
);
4161 expression_dereference (expr
, MDL
);
4165 token
= next_token (&val
, (unsigned *)0, cfile
);
4166 if (token
!= COMMA
) {
4167 parse_warn (cfile
, "comma expected.");
4169 expression_dereference (expr
, MDL
);
4173 token
= next_token (&val
, (unsigned *)0, cfile
);
4174 if (token
!= NUMBER
) {
4175 parse_warn (cfile
, "number expected.");
4177 expression_dereference (expr
, MDL
);
4180 switch (atoi (val
)) {
4182 (*expr
) -> op
= expr_extract_int8
;
4186 (*expr
) -> op
= expr_extract_int16
;
4190 (*expr
) -> op
= expr_extract_int32
;
4195 "unsupported integer size %d", atoi (val
));
4197 skip_to_semi (cfile
);
4198 expression_dereference (expr
, MDL
);
4202 token
= next_token (&val
, (unsigned *)0, cfile
);
4203 if (token
!= RPAREN
) {
4204 parse_warn (cfile
, "right parenthesis expected.");
4206 expression_dereference (expr
, MDL
);
4212 token
= next_token (&val
, (unsigned *)0, cfile
);
4213 token
= next_token (&val
, (unsigned *)0, cfile
);
4214 if (token
!= LPAREN
) {
4215 parse_warn (cfile
, "left parenthesis expected.");
4220 if (!expression_allocate (expr
, MDL
))
4221 log_fatal ("can't allocate expression");
4223 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
4225 parse_warn (cfile
, "expecting numeric expression.");
4226 skip_to_semi (cfile
);
4228 expression_dereference (expr
, MDL
);
4232 token
= next_token (&val
, (unsigned *)0, cfile
);
4233 if (token
!= COMMA
) {
4234 parse_warn (cfile
, "comma expected.");
4236 expression_dereference (expr
, MDL
);
4240 token
= next_token (&val
, (unsigned *)0, cfile
);
4241 if (token
!= NUMBER
) {
4242 parse_warn (cfile
, "number expected.");
4244 expression_dereference (expr
, MDL
);
4247 switch (atoi (val
)) {
4249 (*expr
) -> op
= expr_encode_int8
;
4253 (*expr
) -> op
= expr_encode_int16
;
4257 (*expr
) -> op
= expr_encode_int32
;
4262 "unsupported integer size %d", atoi (val
));
4264 skip_to_semi (cfile
);
4265 expression_dereference (expr
, MDL
);
4269 token
= next_token (&val
, (unsigned *)0, cfile
);
4270 if (token
!= RPAREN
) {
4271 parse_warn (cfile
, "right parenthesis expected.");
4273 expression_dereference (expr
, MDL
);
4279 /* If we're in a numeric context, this should just be a
4280 number, by itself. */
4281 if (context
== context_numeric
||
4282 context
== context_data_or_numeric
) {
4283 next_token (&val
, (unsigned *)0, cfile
);
4284 if (!expression_allocate (expr
, MDL
))
4285 log_fatal ("can't allocate expression");
4286 (*expr
) -> op
= expr_const_int
;
4287 (*expr
) -> data
.const_int
= atoi (val
);
4291 case NUMBER_OR_NAME
:
4292 if (!expression_allocate (expr
, MDL
))
4293 log_fatal ("can't allocate expression");
4295 (*expr
) -> op
= expr_const_data
;
4296 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
4297 expression_dereference (expr
, MDL
);
4306 token
= next_token (&val
, (unsigned *)0, cfile
);
4307 if (!expression_allocate (expr
, MDL
))
4308 log_fatal ("can't allocate expression");
4309 (*expr
) -> op
= expr_const_int
;
4310 (*expr
) -> data
.const_int
= known
;
4314 known
= ISC_R_SUCCESS
;
4318 known
= ISC_R_NOTAUTH
;
4322 known
= ISC_R_NOTIMPLEMENTED
;
4326 known
= ISC_R_NOTZONE
;
4330 known
= ISC_R_NXDOMAIN
;
4334 known
= ISC_R_NXRRSET
;
4338 known
= ISC_R_REFUSED
;
4342 known
= ISC_R_SERVFAIL
;
4346 known
= ISC_R_YXDOMAIN
;
4350 known
= ISC_R_YXRRSET
;
4358 known
= S_REBOOTING
;
4362 known
= S_SELECTING
;
4366 known
= S_REQUESTING
;
4378 known
= S_REBINDING
;
4382 token
= next_token (&val
, (unsigned *)0, cfile
);
4383 token
= next_token (&val
, (unsigned *)0, cfile
);
4384 if (token
!= LPAREN
)
4387 token
= next_token (&val
, (unsigned *)0, cfile
);
4388 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
4389 parse_warn (cfile
, "%s can't be a variable name", val
);
4390 skip_to_semi (cfile
);
4395 if (!expression_allocate (expr
, MDL
))
4396 log_fatal ("can't allocate expression");
4397 (*expr
) -> op
= expr_variable_exists
;
4398 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
4399 if (!(*expr
)->data
.variable
)
4400 log_fatal ("can't allocate variable name");
4401 strcpy ((*expr
) -> data
.variable
, val
);
4402 token
= next_token (&val
, (unsigned *)0, cfile
);
4403 if (token
!= RPAREN
)
4407 /* Not a valid start to an expression... */
4409 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
4412 token
= next_token (&val
, (unsigned *)0, cfile
);
4414 /* Save the name of the variable being referenced. */
4415 cptr
= dmalloc (strlen (val
) + 1, MDL
);
4417 log_fatal ("can't allocate variable name");
4420 /* Simple variable reference, as far as we can tell. */
4421 token
= peek_token (&val
, (unsigned *)0, cfile
);
4422 if (token
!= LPAREN
) {
4423 if (!expression_allocate (expr
, MDL
))
4424 log_fatal ("can't allocate expression");
4425 (*expr
) -> op
= expr_variable_reference
;
4426 (*expr
) -> data
.variable
= cptr
;
4430 token
= next_token (&val
, (unsigned *)0, cfile
);
4431 if (!expression_allocate (expr
, MDL
))
4432 log_fatal ("can't allocate expression");
4433 (*expr
) -> op
= expr_funcall
;
4434 (*expr
) -> data
.funcall
.name
= cptr
;
4436 /* Now parse the argument list. */
4437 ep
= &(*expr
) -> data
.funcall
.arglist
;
4439 if (!expression_allocate (ep
, MDL
))
4440 log_fatal ("can't allocate expression");
4441 (*ep
) -> op
= expr_arg
;
4442 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
4443 cfile
, lose
, context_any
,
4444 (struct expression
**)0,
4448 "expecting expression.");
4451 skip_to_semi (cfile
);
4452 expression_dereference (expr
, MDL
);
4455 ep
= &((*ep
) -> data
.arg
.next
);
4456 token
= next_token (&val
, (unsigned *)0, cfile
);
4457 } while (token
== COMMA
);
4458 if (token
!= RPAREN
) {
4459 parse_warn (cfile
, "Right parenthesis expected.");
4460 skip_to_semi (cfile
);
4462 expression_dereference (expr
, MDL
);
4470 /* Parse an expression. */
4472 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
4473 struct expression
**expr
;
4474 struct parse
*cfile
;
4476 enum expression_context context
;
4477 struct expression
**plhs
;
4480 enum dhcp_token token
;
4482 struct expression
*rhs
= (struct expression
*)0, *tmp
;
4483 struct expression
*lhs
= (struct expression
*)0;
4484 enum expr_op next_op
;
4485 enum expression_context
4486 lhs_context
= context_any
,
4487 rhs_context
= context_any
;
4489 /* Consume the left hand side we were passed. */
4491 expression_reference (&lhs
, *plhs
, MDL
);
4492 expression_dereference (plhs
, MDL
);
4496 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
4497 /* If we already have a left-hand side, then it's not
4498 okay for there not to be a right-hand side here, so
4499 we need to flag it as an error. */
4503 "expecting right-hand side.");
4505 skip_to_semi (cfile
);
4507 expression_dereference (&lhs
, MDL
);
4512 /* At this point, rhs contains either an entire subexpression,
4513 or at least a left-hand-side. If we do not see a binary token
4514 as the next token, we're done with the expression. */
4516 token
= peek_token (&val
, (unsigned *)0, cfile
);
4519 token
= next_token (&val
, (unsigned *)0, cfile
);
4520 token
= peek_token (&val
, (unsigned *)0, cfile
);
4521 if (token
!= EQUAL
) {
4522 parse_warn (cfile
, "! in boolean context without =");
4524 skip_to_semi (cfile
);
4526 expression_dereference (&lhs
, MDL
);
4529 next_op
= expr_not_equal
;
4530 context
= expression_context (rhs
);
4534 next_op
= expr_equal
;
4535 context
= expression_context (rhs
);
4540 context
= expression_context (rhs
);
4545 context
= expression_context (rhs
);
4550 context
= expression_context (rhs
);
4554 next_op
= expr_subtract
;
4555 context
= expression_context (rhs
);
4559 next_op
= expr_divide
;
4560 context
= expression_context (rhs
);
4564 next_op
= expr_multiply
;
4565 context
= expression_context (rhs
);
4569 next_op
= expr_remainder
;
4570 context
= expression_context (rhs
);
4574 next_op
= expr_binary_and
;
4575 context
= expression_context (rhs
);
4579 next_op
= expr_binary_or
;
4580 context
= expression_context (rhs
);
4584 next_op
= expr_binary_xor
;
4585 context
= expression_context (rhs
);
4589 next_op
= expr_none
;
4592 /* If we have no lhs yet, we just parsed it. */
4594 /* If there was no operator following what we just parsed,
4595 then we're done - return it. */
4596 if (next_op
== expr_none
) {
4601 rhs
= (struct expression
*)0;
4603 next_token (&val
, (unsigned *)0, cfile
);
4607 /* If the next binary operator is of greater precedence than the
4608 * current operator, then rhs we have parsed so far is actually
4609 * the lhs of the next operator. To get this value, we have to
4612 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4613 op_precedence (binop
, next_op
) < 0) {
4615 /* Eat the subexpression operator token, which we pass to
4616 * parse_expression...we only peek()'d earlier.
4618 token
= next_token (&val
, (unsigned *)0, cfile
);
4620 /* Continue parsing of the right hand side with that token. */
4622 rhs
= (struct expression
*)0;
4623 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4627 "expecting a subexpression");
4632 next_op
= expr_none
;
4635 if (binop
!= expr_none
) {
4636 rhs_context
= expression_context(rhs
);
4637 lhs_context
= expression_context(lhs
);
4639 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4640 (rhs_context
!= lhs_context
)) {
4641 parse_warn (cfile
, "illegal expression relating different types");
4642 skip_to_semi (cfile
);
4643 expression_dereference (&rhs
, MDL
);
4644 expression_dereference (&lhs
, MDL
);
4650 case expr_not_equal
:
4652 if ((rhs_context
!= context_data_or_numeric
) &&
4653 (rhs_context
!= context_data
) &&
4654 (rhs_context
!= context_numeric
) &&
4655 (rhs_context
!= context_any
)) {
4656 parse_warn (cfile
, "expecting data/numeric expression");
4657 skip_to_semi (cfile
);
4658 expression_dereference (&rhs
, MDL
);
4666 if ((rhs_context
!= context_boolean
) &&
4667 (rhs_context
!= context_any
)) {
4668 parse_warn (cfile
, "expecting boolean expressions");
4669 skip_to_semi (cfile
);
4670 expression_dereference (&rhs
, MDL
);
4680 case expr_remainder
:
4681 case expr_binary_and
:
4682 case expr_binary_or
:
4683 case expr_binary_xor
:
4684 if ((rhs_context
!= context_numeric
) &&
4685 (rhs_context
!= context_any
)) {
4686 parse_warn (cfile
, "expecting numeric expressions");
4687 skip_to_semi (cfile
);
4688 expression_dereference (&rhs
, MDL
);
4699 /* Now, if we didn't find a binary operator, we're done parsing
4700 this subexpression, so combine it with the preceding binary
4701 operator and return the result. */
4702 if (next_op
== expr_none
) {
4703 if (!expression_allocate (expr
, MDL
))
4704 log_fatal ("Can't allocate expression!");
4706 (*expr
) -> op
= binop
;
4707 /* All the binary operators' data union members
4708 are the same, so we'll cheat and use the member
4709 for the equals operator. */
4710 (*expr
) -> data
.equal
[0] = lhs
;
4711 (*expr
) -> data
.equal
[1] = rhs
;
4715 /* Eat the operator token - we now know it was a binary operator... */
4716 token
= next_token (&val
, (unsigned *)0, cfile
);
4718 /* Now combine the LHS and the RHS using binop. */
4719 tmp
= (struct expression
*)0;
4720 if (!expression_allocate (&tmp
, MDL
))
4721 log_fatal ("No memory for equal precedence combination.");
4723 /* Store the LHS and RHS. */
4724 tmp
-> data
.equal
[0] = lhs
;
4725 tmp
-> data
.equal
[1] = rhs
;
4729 tmp
= (struct expression
*)0;
4730 rhs
= (struct expression
*)0;
4732 /* Recursions don't return until we have parsed the end of the
4733 expression, so if we recursed earlier, we can now return what
4735 if (next_op
== expr_none
) {
4744 /* option-statement :== identifier DOT identifier <syntax> SEMI
4745 | identifier <syntax> SEMI
4747 Option syntax is handled specially through format strings, so it
4748 would be painful to come up with BNF for it. However, it always
4749 starts as above and ends in a SEMI. */
4751 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4752 struct executable_statement
**result
;
4753 struct parse
*cfile
;
4755 struct option
*option
;
4756 enum statement_op op
;
4759 enum dhcp_token token
;
4760 const char *fmt
= NULL
;
4761 struct expression
*expr
= (struct expression
*)0;
4762 struct expression
*tmp
;
4764 struct executable_statement
*stmt
;
4767 token
= peek_token (&val
, (unsigned *)0, cfile
);
4768 if (token
== SEMI
) {
4769 /* Eat the semicolon... */
4770 token
= next_token (&val
, (unsigned *)0, cfile
);
4774 if (token
== EQUAL
) {
4775 /* Eat the equals sign. */
4776 token
= next_token (&val
, (unsigned *)0, cfile
);
4778 /* Parse a data expression and use its value for the data. */
4779 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
4780 /* In this context, we must have an executable
4781 statement, so if we found something else, it's
4785 "expecting a data expression.");
4786 skip_to_semi (cfile
);
4791 /* We got a valid expression, so use it. */
4795 /* Parse the option data... */
4797 /* Set a flag if this is an array of a simple type (i.e.,
4798 not an array of pairs of IP addresses, or something
4800 int uniform
= option
-> format
[1] == 'A';
4803 /* Set fmt to start of format for 'A' and one char back
4806 if ((fmt
!= NULL
) && (fmt
!= option
->format
) && (*fmt
== 'a'))
4808 else if ((fmt
== NULL
) || (*fmt
== 'A'))
4809 fmt
= option
->format
;
4811 /* 'a' means always uniform */
4812 uniform
|= (fmt
[1] == 'a');
4814 for ( ; *fmt
; fmt
++) {
4815 if ((*fmt
== 'A') || (*fmt
== 'a'))
4820 expr
= (struct expression
*)0;
4821 if (!parse_option_token (&expr
, cfile
, &fmt
,
4822 tmp
, uniform
, lookups
)) {
4823 if (fmt
[1] != 'o') {
4825 expression_dereference (&tmp
,
4830 tmp
= (struct expression
*)0;
4833 expression_dereference (&tmp
, MDL
);
4835 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4836 token
= peek_token (&val
, (unsigned *)0, cfile
);
4837 /* Comma means: continue with next element in array */
4838 if (token
== COMMA
) {
4839 token
= next_token (&val
,
4840 (unsigned *)0, cfile
);
4843 /* no comma: end of array.
4844 'A' or end of string means: leave the loop */
4845 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4847 /* 'a' means: go on with next char */
4853 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4856 if (!parse_semi (cfile
))
4858 if (!executable_statement_allocate (result
, MDL
))
4859 log_fatal ("no memory for option statement.");
4860 (*result
) -> op
= op
;
4861 if (expr
&& !option_cache (&(*result
) -> data
.option
,
4862 (struct data_string
*)0, expr
, option
, MDL
))
4863 log_fatal ("no memory for option cache");
4865 expression_dereference (&expr
, MDL
);
4869 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4870 struct expression
**rv
;
4871 struct parse
*cfile
;
4873 struct expression
*expr
;
4878 enum dhcp_token token
;
4879 struct expression
*t
= (struct expression
*)0;
4880 unsigned char buf
[4];
4886 struct enumeration_value
*e
;
4890 token
= next_token (&val
, &len
, cfile
);
4891 if (!is_identifier (token
)) {
4892 if ((*fmt
) [1] != 'o') {
4893 parse_warn (cfile
, "expecting identifier.");
4895 skip_to_semi (cfile
);
4899 if (!make_const_data (&t
, (const unsigned char *)val
,
4901 log_fatal ("No memory for %s", val
);
4905 g
= strchr (*fmt
, '.');
4908 "malformed encapsulation format (bug!)");
4909 skip_to_semi (cfile
);
4914 token
= peek_token (&val
, (unsigned *)0, cfile
);
4915 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4916 if (!expression_allocate (&t
, MDL
))
4918 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4919 expression_dereference (&t
, MDL
);
4922 t
-> op
= expr_const_data
;
4924 token
= next_token (&val
, &len
, cfile
);
4926 if(token
== STRING
) {
4927 if (!make_const_data (&t
,
4928 (const unsigned char *)val
,
4930 log_fatal ("No memory for \"%s\"", val
);
4931 } else if ((*fmt
) [1] != 'o') {
4932 parse_warn (cfile
, "expecting string %s.",
4933 "or hexadecimal data");
4934 skip_to_semi (cfile
);
4941 case 'D': /* Domain list... */
4942 if ((*fmt
)[1] == 'c') {
4944 /* Skip the compress-flag atom. */
4949 t
= parse_domain_list(cfile
, compress
);
4952 if ((*fmt
)[1] != 'o')
4953 skip_to_semi(cfile
);
4959 case 'd': /* Domain name... */
4960 val
= parse_host_name (cfile
);
4962 parse_warn (cfile
, "not a valid domain name.");
4963 skip_to_semi (cfile
);
4969 case 't': /* Text string... */
4970 token
= next_token (&val
, &len
, cfile
);
4971 if (token
!= STRING
&& !is_identifier (token
)) {
4972 if ((*fmt
) [1] != 'o') {
4973 parse_warn (cfile
, "expecting string.");
4975 skip_to_semi (cfile
);
4980 if (!make_const_data (&t
, (const unsigned char *)val
,
4982 log_fatal ("No memory for concatenation");
4987 g
= strchr (*fmt
, '.');
4989 parse_warn (cfile
, "malformed %s (bug!)",
4990 "enumeration format");
4992 skip_to_semi (cfile
);
4996 token
= next_token (&val
, (unsigned *)0, cfile
);
4997 if (!is_identifier (token
)) {
4999 "identifier expected");
5002 e
= find_enumeration_value (f
, (*fmt
) - f
, val
);
5004 parse_warn (cfile
, "unknown value");
5007 if (!make_const_data (&t
, &e
-> value
, 1, 0, 1, MDL
))
5011 case 'I': /* IP address or hostname. */
5013 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
5016 if (!parse_ip_addr (cfile
, &addr
))
5018 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
5024 case '6': /* IPv6 address. */
5025 if (!parse_ip6_addr(cfile
, &addr
)) {
5028 if (!make_const_data(&t
, addr
.iabuf
, addr
.len
, 0, 1, MDL
)) {
5033 case 'T': /* Lease interval. */
5034 token
= next_token (&val
, (unsigned *)0, cfile
);
5035 if (token
!= INFINITE
)
5038 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5042 case 'L': /* Unsigned 32-bit integer... */
5043 case 'l': /* Signed 32-bit integer... */
5044 token
= next_token (&val
, (unsigned *)0, cfile
);
5046 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
5048 if ((*fmt
) [1] != 'o') {
5049 parse_warn (cfile
, "expecting number.");
5051 skip_to_semi (cfile
);
5055 convert_num (cfile
, buf
, val
, 0, 32);
5056 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5060 case 's': /* Signed 16-bit integer. */
5061 case 'S': /* Unsigned 16-bit integer. */
5062 token
= next_token (&val
, (unsigned *)0, cfile
);
5063 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5065 convert_num (cfile
, buf
, val
, 0, 16);
5066 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
5070 case 'b': /* Signed 8-bit integer. */
5071 case 'B': /* Unsigned 8-bit integer. */
5072 token
= next_token (&val
, (unsigned *)0, cfile
);
5073 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5075 convert_num (cfile
, buf
, val
, 0, 8);
5076 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5080 case 'f': /* Boolean flag. */
5081 token
= next_token (&val
, (unsigned *)0, cfile
);
5082 if (!is_identifier (token
)) {
5083 if ((*fmt
) [1] != 'o')
5084 parse_warn (cfile
, "expecting identifier.");
5086 if ((*fmt
) [1] != 'o') {
5088 skip_to_semi (cfile
);
5092 if (!strcasecmp (val
, "true")
5093 || !strcasecmp (val
, "on"))
5095 else if (!strcasecmp (val
, "false")
5096 || !strcasecmp (val
, "off"))
5098 else if (!strcasecmp (val
, "ignore"))
5101 if ((*fmt
) [1] != 'o')
5102 parse_warn (cfile
, "expecting boolean.");
5105 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5110 parse_warn (cfile
, "Bad format %c in parse_option_token.",
5112 skip_to_semi (cfile
);
5116 if (!make_concat (rv
, expr
, t
))
5119 expression_reference (rv
, t
, MDL
);
5120 expression_dereference (&t
, MDL
);
5124 int parse_option_decl (oc
, cfile
)
5125 struct option_cache
**oc
;
5126 struct parse
*cfile
;
5131 u_int8_t hunkbuf
[1024];
5132 unsigned hunkix
= 0;
5133 const char *fmt
, *f
;
5134 struct option
*option
=NULL
;
5135 struct iaddr ip_addr
;
5137 const u_int8_t
*cdp
;
5143 struct expression
*express
= NULL
;
5144 struct enumeration_value
*e
;
5145 isc_result_t status
;
5147 status
= parse_option_name (cfile
, 0, &known
, &option
);
5148 if (status
!= ISC_R_SUCCESS
|| option
== NULL
)
5151 /* Parse the option data... */
5153 /* Set a flag if this is an array of a simple type (i.e.,
5154 not an array of pairs of IP addresses, or something
5156 int uniform
= option
-> format
[1] == 'A';
5158 for (fmt
= option
-> format
; *fmt
; fmt
++) {
5163 fmt
= strchr (fmt
, '.');
5166 "malformed %s (bug!)",
5167 "encapsulation format");
5171 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
5172 sizeof hunkbuf
- hunkix
);
5176 case 't': /* Text string... */
5177 token
= next_token (&val
,
5179 if (token
!= STRING
) {
5181 "expecting string.");
5184 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
5186 "option data buffer %s",
5190 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
5196 if (fmt
[1] == 'c') {
5202 express
= parse_domain_list(cfile
, compress
);
5204 if (express
== NULL
)
5207 if (express
->op
!= expr_const_data
) {
5208 parse_warn(cfile
, "unexpected "
5213 len
= express
->data
.const_data
.len
;
5214 cdp
= express
->data
.const_data
.data
;
5216 if ((hunkix
+ len
) > sizeof(hunkbuf
)) {
5217 parse_warn(cfile
, "option data buffer "
5221 memcpy(&hunkbuf
[hunkix
], cdp
, len
);
5224 expression_dereference(&express
, MDL
);
5229 fmt
= strchr (fmt
, '.');
5232 "malformed %s (bug!)",
5233 "enumeration format");
5236 token
= next_token (&val
,
5237 (unsigned *)0, cfile
);
5238 if (!is_identifier (token
)) {
5240 "identifier expected");
5243 e
= find_enumeration_value (f
, fmt
- f
, val
);
5254 if (!parse_ip6_addr(cfile
, &ip_addr
))
5260 case 'I': /* IP address. */
5261 if (!parse_ip_addr (cfile
, &ip_addr
))
5267 if (hunkix
+ len
> sizeof hunkbuf
) {
5269 "option data buffer %s",
5273 memcpy (&hunkbuf
[hunkix
], dp
, len
);
5277 case 'L': /* Unsigned 32-bit integer... */
5278 case 'l': /* Signed 32-bit integer... */
5279 token
= next_token (&val
,
5280 (unsigned *)0, cfile
);
5281 if ((token
!= NUMBER
) &&
5282 (token
!= NUMBER_OR_NAME
)) {
5285 "expecting number.");
5291 convert_num (cfile
, buf
, val
, 0, 32);
5296 case 's': /* Signed 16-bit integer. */
5297 case 'S': /* Unsigned 16-bit integer. */
5298 token
= next_token (&val
,
5299 (unsigned *)0, cfile
);
5300 if ((token
!= NUMBER
) &&
5301 (token
!= NUMBER_OR_NAME
))
5303 convert_num (cfile
, buf
, val
, 0, 16);
5308 case 'b': /* Signed 8-bit integer. */
5309 case 'B': /* Unsigned 8-bit integer. */
5310 token
= next_token (&val
,
5311 (unsigned *)0, cfile
);
5312 if ((token
!= NUMBER
) &&
5313 (token
!= NUMBER_OR_NAME
))
5315 convert_num (cfile
, buf
, val
, 0, 8);
5320 case 'f': /* Boolean flag. */
5321 token
= next_token (&val
,
5322 (unsigned *)0, cfile
);
5323 if (!is_identifier (token
)) {
5325 "expecting identifier.");
5332 if (!strcasecmp (val
, "true")
5333 || !strcasecmp (val
, "on"))
5335 else if (!strcasecmp (val
, "false")
5336 || !strcasecmp (val
, "off"))
5340 "expecting boolean.");
5348 log_error ("parse_option_param: Bad format %c",
5353 token
= next_token (&val
, (unsigned *)0, cfile
);
5354 } while (*fmt
== 'A' && token
== COMMA
);
5356 if (token
!= SEMI
) {
5357 parse_warn (cfile
, "semicolon expected.");
5361 bp
= (struct buffer
*)0;
5362 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
5363 log_fatal ("no memory to store option declaration.");
5365 log_fatal ("out of memory allocating option data.");
5366 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
5368 if (!option_cache_allocate (oc
, MDL
))
5369 log_fatal ("out of memory allocating option cache.");
5371 (*oc
) -> data
.buffer
= bp
;
5372 (*oc
) -> data
.data
= &bp
-> data
[0];
5373 (*oc
) -> data
.terminated
= nul_term
;
5374 (*oc
) -> data
.len
= hunkix
;
5375 option_reference(&(*oc
)->option
, option
, MDL
);
5376 option_dereference(&option
, MDL
);
5380 if (express
!= NULL
)
5381 expression_dereference(&express
, MDL
);
5382 skip_to_semi (cfile
);
5384 option_dereference(&option
, MDL
);
5389 /* Consider merging parse_cshl into this. */
5391 int parse_X (cfile
, buf
, max
)
5392 struct parse
*cfile
;
5401 token
= peek_token (&val
, (unsigned *)0, cfile
);
5402 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5405 token
= next_token (&val
, (unsigned *)0, cfile
);
5406 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
5408 "expecting hexadecimal constant.");
5409 skip_to_semi (cfile
);
5412 convert_num (cfile
, &buf
[len
], val
, 16, 8);
5415 "hexadecimal constant too long.");
5416 skip_to_semi (cfile
);
5419 token
= peek_token (&val
, (unsigned *)0, cfile
);
5421 token
= next_token (&val
,
5422 (unsigned *)0, cfile
);
5423 } while (token
== COLON
);
5425 } else if (token
== STRING
) {
5426 token
= next_token (&val
, &len
, cfile
);
5427 if (len
+ 1 > max
) {
5428 parse_warn (cfile
, "string constant too long.");
5429 skip_to_semi (cfile
);
5432 memcpy (buf
, val
, len
+ 1);
5434 parse_warn (cfile
, "expecting string or hexadecimal data");
5435 skip_to_semi (cfile
);
5441 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
5449 do_percentm (mbuf
, fmt
);
5450 /* %Audit% This is log output. %2004.06.17,Safe%
5451 * If we truncate we hope the user can get a hint from the log.
5453 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
5454 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
5456 va_start (list
, fmt
);
5457 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
5462 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
5463 if (lix
< (sizeof lexbuf
) - 1)
5464 lexbuf
[lix
++] = ' ';
5465 if (cfile
-> token_line
[i
] == '\t') {
5467 lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
5474 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
5475 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
5476 if (cfile
-> lexchar
< 81)
5477 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
5481 write (STDERR_FILENO
, mbuf
, strlen (mbuf
));
5482 write (STDERR_FILENO
, "\n", 1);
5483 write (STDERR_FILENO
, cfile
-> token_line
,
5484 strlen (cfile
-> token_line
));
5485 write (STDERR_FILENO
, "\n", 1);
5486 if (cfile
-> lexchar
< 81)
5487 write (STDERR_FILENO
, lexbuf
, lix
);
5488 write (STDERR_FILENO
, "^\n", 2);
5491 cfile
-> warnings_occurred
= 1;
5497 parse_domain_list(struct parse
*cfile
, int compress
)
5500 enum dhcp_token token
= SEMI
;
5501 struct expression
*t
= NULL
;
5502 unsigned len
, clen
= 0;
5504 unsigned char compbuf
[256 * NS_MAXCDNAME
];
5505 const unsigned char *dnptrs
[256], **lastdnptr
;
5507 memset(compbuf
, 0, sizeof(compbuf
));
5508 memset(dnptrs
, 0, sizeof(dnptrs
));
5509 dnptrs
[0] = compbuf
;
5510 lastdnptr
= &dnptrs
[255];
5513 /* Consume the COMMA token if peeked. */
5515 next_token(&val
, NULL
, cfile
);
5517 /* Get next (or first) value. */
5518 token
= next_token(&val
, &len
, cfile
);
5520 if (token
!= STRING
) {
5521 parse_warn(cfile
, "Expecting a domain string.");
5525 /* If compression pointers are enabled, compress. If not,
5526 * just pack the names in series into the buffer.
5529 result
= MRns_name_compress(val
, compbuf
+ clen
,
5530 sizeof(compbuf
) - clen
,
5534 parse_warn(cfile
, "Error compressing domain "
5541 result
= MRns_name_pton(val
, compbuf
+ clen
,
5542 sizeof(compbuf
) - clen
);
5544 /* result == 1 means the input was fully qualified.
5545 * result == 0 means the input wasn't.
5546 * result == -1 means bad things.
5549 parse_warn(cfile
, "Error assembling domain "
5555 * We need to figure out how many bytes to increment
5556 * our buffer pointer since pton doesn't tell us.
5558 while (compbuf
[clen
] != 0)
5559 clen
+= compbuf
[clen
] + 1;
5561 /* Count the last label (0). */
5565 if (clen
> sizeof(compbuf
))
5566 log_fatal("Impossible error at %s:%d", MDL
);
5568 token
= peek_token(&val
, NULL
, cfile
);
5569 } while (token
== COMMA
);
5571 if (!make_const_data(&t
, compbuf
, clen
, 1, 1, MDL
))
5572 log_fatal("No memory for domain list object.");