3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2012 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
25 * https://www.isc.org/
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 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
38 /* Enumerations can be specified in option formats, and are used for
39 parsing, so we define the routines that manage them here. */
41 struct enumeration
*enumerations
;
43 void add_enumeration (struct enumeration
*enumeration
)
45 enumeration
-> next
= enumerations
;
46 enumerations
= enumeration
;
49 struct enumeration
*find_enumeration (const char *name
, int length
)
51 struct enumeration
*e
;
53 for (e
= enumerations
; e
; e
= e
-> next
)
54 if (strlen (e
-> name
) == length
&&
55 !memcmp (e
-> name
, name
, (unsigned)length
))
57 return (struct enumeration
*)0;
60 struct enumeration_value
*find_enumeration_value (const char *name
,
65 struct enumeration
*e
;
68 e
= find_enumeration (name
, length
);
72 for (i
= 0; e
-> values
[i
].name
; i
++) {
73 if (!strcmp (value
, e
-> values
[i
].name
))
74 return &e
-> values
[i
];
77 return (struct enumeration_value
*)0;
80 /* Skip to the semicolon ending the current statement. If we encounter
81 braces, the matching closing brace terminates the statement. If we
82 encounter a right brace but haven't encountered a left brace, return
83 leaving the brace in the token buffer for the caller. If we see a
84 semicolon and haven't seen a left brace, return. This lets us skip
89 statement foo bar { statement { } }
94 void skip_to_semi (cfile
)
97 skip_to_rbrace (cfile
, 0);
100 void skip_to_rbrace (cfile
, brace_count
)
104 enum dhcp_token token
;
107 #if defined (DEBUG_TOKEN)
108 log_error ("skip_to_rbrace: %d\n", brace_count
);
111 token
= peek_token (&val
, (unsigned *)0, cfile
);
112 if (token
== RBRACE
) {
113 token
= next_token (&val
, (unsigned *)0, cfile
);
119 } else if (token
== LBRACE
) {
121 } else if (token
== SEMI
&& !brace_count
) {
122 token
= next_token (&val
, (unsigned *)0, cfile
);
124 } else if (token
== EOL
) {
125 /* EOL only happens when parsing /etc/resolv.conf,
126 and we treat it like a semicolon because the
127 resolv.conf file is line-oriented. */
128 token
= next_token (&val
, (unsigned *)0, cfile
);
131 token
= next_token (&val
, (unsigned *)0, cfile
);
132 } while (token
!= END_OF_FILE
);
135 int parse_semi (cfile
)
138 enum dhcp_token token
;
141 token
= next_token (&val
, (unsigned *)0, cfile
);
143 parse_warn (cfile
, "semicolon expected.");
144 skip_to_semi (cfile
);
150 /* string-parameter :== STRING SEMI */
152 int parse_string (cfile
, sptr
, lptr
)
158 enum dhcp_token token
;
162 token
= next_token (&val
, &len
, cfile
);
163 if (token
!= STRING
) {
164 parse_warn (cfile
, "expecting a string");
165 skip_to_semi (cfile
);
168 s
= (char *)dmalloc (len
+ 1, MDL
);
170 log_fatal ("no memory for string %s.", val
);
171 memcpy (s
, val
, len
+ 1);
173 if (!parse_semi (cfile
)) {
187 * hostname :== IDENTIFIER
189 * | hostname DOT IDENTIFIER
192 char *parse_host_name (cfile
)
196 enum dhcp_token token
;
203 /* Read a dotted hostname... */
205 /* Read a token, which should be an identifier. */
206 token
= peek_token (&val
, (unsigned *)0, cfile
);
207 if (!is_identifier (token
) && token
!= NUMBER
)
209 token
= next_token (&val
, (unsigned *)0, cfile
);
211 /* Store this identifier... */
212 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
213 log_fatal ("can't allocate temp space for hostname.");
215 c
= cons ((caddr_t
)s
, c
);
216 len
+= strlen (s
) + 1;
217 /* Look for a dot; if it's there, keep going, otherwise
219 token
= peek_token (&val
, (unsigned *)0, cfile
);
221 token
= next_token (&val
, (unsigned *)0, cfile
);
225 } while (token
== DOT
);
227 /* Should be at least one token. */
231 /* Assemble the hostname together into a string. */
232 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
233 log_fatal ("can't allocate space for hostname.");
240 unsigned l
= strlen ((char *)(c
-> car
));
242 memcpy (t
, (char *)(c
-> car
), l
);
243 /* Free up temp space. */
244 dfree (c
-> car
, MDL
);
253 /* ip-addr-or-hostname :== ip-address | hostname
254 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
256 Parse an ip address or a hostname. If uniform is zero, put in
257 an expr_substring node to limit hostnames that evaluate to more
260 Note that RFC1123 permits hostnames to consist of all digits,
261 making it difficult to quickly disambiguate them from ip addresses.
264 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
265 struct expression
**expr
;
270 enum dhcp_token token
;
271 unsigned char addr
[4];
272 unsigned len
= sizeof addr
;
274 struct expression
*x
= (struct expression
*)0;
277 token
= peek_token (&val
, (unsigned *)0, cfile
);
279 if (token
== NUMBER
) {
281 * a hostname may be numeric, but domain names must
282 * start with a letter, so we can disambiguate by
283 * looking ahead a few tokens. we save the parse
284 * context first, and restore it after we know what
285 * we're dealing with.
287 save_parse_state(cfile
);
288 (void) next_token(NULL
, NULL
, cfile
);
289 if (next_token(NULL
, NULL
, cfile
) == DOT
&&
290 next_token(NULL
, NULL
, cfile
) == NUMBER
)
292 restore_parse_state(cfile
);
295 parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
296 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
300 if (is_identifier (token
) || token
== NUMBER
) {
301 name
= parse_host_name (cfile
);
304 if (!make_host_lookup (expr
, name
)) {
310 if (!make_limit (&x
, *expr
, 4))
312 expression_dereference (expr
, MDL
);
316 if (token
!= RBRACE
&& token
!= LBRACE
)
317 token
= next_token (&val
, (unsigned *)0, cfile
);
318 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
321 skip_to_semi (cfile
);
329 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
332 int parse_ip_addr (cfile
, addr
)
337 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
338 &addr
-> len
, DOT
, 10, 8))
344 * Return true if every character in the string is hexadecimal.
347 is_hex_string(const char *s
) {
349 if (!isxdigit((int)*s
)) {
358 * ip-address6 :== (complicated set of rules)
360 * See section 2.2 of RFC 1884 for details.
362 * We are lazy for this. We pull numbers, names, colons, and dots
363 * together and then throw the resulting string at the inet_pton()
368 parse_ip6_addr(struct parse
*cfile
, struct iaddr
*addr
) {
369 enum dhcp_token token
;
373 char v6
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
377 * First token is non-raw. This way we eat any whitespace before
378 * our IPv6 address begins, like one would expect.
380 token
= peek_token(&val
, NULL
, cfile
);
387 if ((((token
== NAME
) || (token
== NUMBER_OR_NAME
)) &&
388 is_hex_string(val
)) ||
393 next_raw_token(&val
, NULL
, cfile
);
394 val_len
= strlen(val
);
395 if ((v6_len
+ val_len
) >= sizeof(v6
)) {
396 parse_warn(cfile
, "Invalid IPv6 address.");
400 memcpy(v6
+v6_len
, val
, val_len
);
406 token
= peek_raw_token(&val
, NULL
, cfile
);
411 * Use inet_pton() for actual work.
413 if (inet_pton(AF_INET6
, v6
, addr
->iabuf
) <= 0) {
414 parse_warn(cfile
, "Invalid IPv6 address.");
423 * Same as parse_ip6_addr() above, but returns the value in the
424 * expression rather than in an address structure.
427 parse_ip6_addr_expr(struct expression
**expr
,
428 struct parse
*cfile
) {
431 if (!parse_ip6_addr(cfile
, &addr
)) {
434 return make_const_data(expr
, addr
.iabuf
, addr
.len
, 0, 1, MDL
);
438 * ip6-prefix :== ip6-address "/" NUMBER
441 parse_ip6_prefix(struct parse
*cfile
, struct iaddr
*addr
, u_int8_t
*plen
) {
442 enum dhcp_token token
;
446 if (!parse_ip6_addr(cfile
, addr
)) {
449 token
= next_token(&val
, NULL
, cfile
);
450 if (token
!= SLASH
) {
451 parse_warn(cfile
, "Slash expected.");
456 token
= next_token(&val
, NULL
, cfile
);
457 if (token
!= NUMBER
) {
458 parse_warn(cfile
, "Number expected.");
464 if ((n
< 0) || (n
> 128)) {
465 parse_warn(cfile
, "Invalid IPv6 prefix length.");
469 if (!is_cidr_mask_valid(addr
, n
)) {
470 parse_warn(cfile
, "network mask too short.");
479 * ip-address-with-subnet :== ip-address |
480 * ip-address "/" NUMBER
484 parse_ip_addr_with_subnet(cfile
, match
)
486 struct iaddrmatch
*match
;
488 const char *val
, *orig
;
489 enum dhcp_token token
;
492 unsigned char newval
, warnmask
=0;
494 if (parse_ip_addr(cfile
, &match
->addr
)) {
495 /* default to host mask */
496 prefixlen
= match
->addr
.len
* 8;
498 token
= peek_token(&val
, NULL
, cfile
);
500 if (token
== SLASH
) {
501 next_token(&val
, NULL
, cfile
);
502 token
= next_token(&val
, NULL
, cfile
);
504 if (token
!= NUMBER
) {
505 parse_warn(cfile
, "Invalid CIDR prefix length:"
506 " expecting a number.");
510 prefixlen
= atoi(val
);
513 prefixlen
> (match
->addr
.len
* 8)) {
514 parse_warn(cfile
, "subnet prefix is out of "
516 match
->addr
.len
* 8);
521 /* construct a suitable mask field */
524 match
->mask
.len
= match
->addr
.len
;
526 /* count of 0xff bytes in mask */
527 fflen
= prefixlen
/ 8;
529 /* set leading mask */
530 memset(match
->mask
.iabuf
, 0xff, fflen
);
533 if (fflen
< match
->mask
.len
) {
534 match
->mask
.iabuf
[fflen
] =
535 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen
% 8];
537 memset(match
->mask
.iabuf
+fflen
+1, 0x00,
538 match
->mask
.len
- fflen
- 1);
540 /* AND-out insignificant bits from supplied netmask. */
541 orig
= piaddr(match
->addr
);
543 newval
= match
->addr
.iabuf
[fflen
] &
544 match
->mask
.iabuf
[fflen
];
546 if (newval
!= match
->addr
.iabuf
[fflen
]) {
548 match
->addr
.iabuf
[fflen
] = newval
;
550 } while (++fflen
< match
->mask
.len
);
553 log_error("Warning: Extraneous bits removed "
554 "in address component of %s/%d.",
556 log_error("New value: %s/%d.",
557 piaddr(match
->addr
), prefixlen
);
565 "expecting ip-address or ip-address/prefixlen");
567 return 0; /* let caller pick up pieces */
571 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
572 * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND
573 * Note that INFINIBAND may not be useful for some items, such as classification
574 * as the hardware address won't always be available.
577 void parse_hardware_param (cfile
, hardware
)
579 struct hardware
*hardware
;
582 enum dhcp_token token
;
586 token
= next_token(&val
, NULL
, cfile
);
589 hardware
->hbuf
[0] = HTYPE_ETHER
;
592 hardware
->hbuf
[0] = HTYPE_IEEE802
;
595 hardware
->hbuf
[0] = HTYPE_FDDI
;
597 case TOKEN_INFINIBAND
:
598 hardware
->hbuf
[0] = HTYPE_INFINIBAND
;
601 if (!strncmp(val
, "unknown-", 8)) {
602 hardware
->hbuf
[0] = atoi(&val
[8]);
605 "expecting a network hardware type");
612 /* Parse the hardware address information. Technically,
613 it would make a lot of sense to restrict the length of the
614 data we'll accept here to the length of a particular hardware
615 address type. Unfortunately, there are some broken clients
616 out there that put bogus data in the chaddr buffer, and we accept
617 that data in the lease file rather than simply failing on such
620 token
= peek_token(&val
, NULL
, cfile
);
625 t
= parse_numeric_aggregate(cfile
, NULL
, &hlen
, COLON
, 16, 8);
630 if (hlen
+ 1 > sizeof(hardware
->hbuf
)) {
632 parse_warn(cfile
, "hardware address too long");
634 hardware
->hlen
= hlen
+ 1;
635 memcpy((unsigned char *)&hardware
->hbuf
[1], t
, hlen
);
636 if (hlen
+ 1 < sizeof(hardware
->hbuf
))
637 memset(&hardware
->hbuf
[hlen
+ 1], 0,
638 (sizeof(hardware
->hbuf
)) - hlen
- 1);
643 token
= next_token(&val
, NULL
, cfile
);
645 parse_warn(cfile
, "expecting semicolon.");
650 /* lease-time :== NUMBER SEMI */
652 void parse_lease_time (cfile
, timep
)
657 enum dhcp_token token
;
660 token
= next_token (&val
, (unsigned *)0, cfile
);
661 if (token
!= NUMBER
) {
662 parse_warn (cfile
, "Expecting numeric lease time");
663 skip_to_semi (cfile
);
666 convert_num(cfile
, (unsigned char *)&num
, val
, 10, 32);
667 /* Unswap the number - convert_num returns stuff in NBO. */
673 /* No BNF for numeric aggregates - that's defined by the caller. What
674 this function does is to parse a sequence of numbers separated by
675 the token specified in separator. If max is zero, any number of
676 numbers will be parsed; otherwise, exactly max numbers are
677 expected. Base and size tell us how to internalize the numbers
678 once they've been tokenized. */
680 unsigned char *parse_numeric_aggregate (cfile
, buf
,
681 max
, separator
, base
, size
)
690 enum dhcp_token token
;
691 unsigned char *bufp
= buf
, *s
, *t
;
696 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
698 log_fatal ("no space for numeric aggregate");
705 token
= peek_token (&val
, (unsigned *)0, cfile
);
706 if (token
!= separator
) {
709 if (token
!= RBRACE
&& token
!= LBRACE
)
710 token
= next_token (&val
,
713 parse_warn (cfile
, "too few numbers.");
715 skip_to_semi (cfile
);
716 return (unsigned char *)0;
718 token
= next_token (&val
, (unsigned *)0, cfile
);
720 token
= next_token (&val
, (unsigned *)0, cfile
);
722 if (token
== END_OF_FILE
) {
723 parse_warn (cfile
, "unexpected end of file");
727 /* Allow NUMBER_OR_NAME if base is 16. */
728 if (token
!= NUMBER
&&
729 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
730 parse_warn (cfile
, "expecting numeric value.");
731 skip_to_semi (cfile
);
732 return (unsigned char *)0;
734 /* If we can, convert the number now; otherwise, build
735 a linked list of all the numbers. */
737 convert_num (cfile
, s
, val
, base
, size
);
740 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
742 log_fatal ("no temp space for number.");
743 strcpy ((char *)t
, val
);
744 c
= cons ((caddr_t
)t
, c
);
746 } while (++count
!= *max
);
748 /* If we had to cons up a list, convert it now. */
750 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
752 log_fatal ("no space for numeric aggregate.");
753 s
= bufp
+ count
- size
/ 8;
758 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
760 /* Free up temp space. */
761 dfree (c
-> car
, MDL
);
768 void convert_num (cfile
, buf
, str
, base
, size
)
775 const unsigned char *ptr
= (const unsigned char *)str
;
786 /* If base wasn't specified, figure it out from the data. */
788 if (ptr
[0] == '0') {
789 if (ptr
[1] == 'x') {
792 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
805 /* XXX assumes ASCII... */
807 tval
= tval
- 'a' + 10;
808 else if (tval
>= 'A')
809 tval
= tval
- 'A' + 10;
810 else if (tval
>= '0')
813 parse_warn (cfile
, "Bogus number: %s.", str
);
818 "Bogus number %s: digit %d not in base %d",
822 val
= val
* base
+ tval
;
826 max
= (1 << (size
- 1));
828 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
833 "%s%lo exceeds max (%d) for precision.",
835 (unsigned long)val
, max
);
839 "%s%lx exceeds max (%d) for precision.",
841 (unsigned long)val
, max
);
845 "%s%lu exceeds max (%d) for precision.",
847 (unsigned long)val
, max
);
855 *buf
= -(unsigned long)val
;
858 putShort (buf
, -(long)val
);
861 putLong (buf
, -(long)val
);
865 "Unexpected integer size: %d\n", size
);
871 *buf
= (u_int8_t
)val
;
874 putUShort (buf
, (u_int16_t
)val
);
881 "Unexpected integer size: %d\n", size
);
888 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
889 * NUMBER COLON NUMBER COLON NUMBER |
890 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
891 * NUMBER COLON NUMBER COLON NUMBER NUMBER |
895 * Dates are stored in UTC or with a timezone offset; first number is day
896 * of week; next is year/month/day; next is hours:minutes:seconds on a
897 * 24-hour clock, followed by the timezone offset in seconds, which is
902 * just parse the date
903 * any trailing semi must be consumed by the caller of this routine
906 parse_date_core(cfile
)
910 int tzoff
, wday
, year
, mon
, mday
, hour
, min
, sec
;
912 enum dhcp_token token
;
913 static int months
[11] = { 31, 59, 90, 120, 151, 181,
914 212, 243, 273, 304, 334 };
916 /* "never", "epoch" or day of week */
917 token
= peek_token(&val
, NULL
, cfile
);
918 if (token
== NEVER
) {
919 token
= next_token(&val
, NULL
, cfile
); /* consume NEVER */
923 /* This indicates 'local' time format. */
924 if (token
== EPOCH
) {
925 token
= next_token(&val
, NULL
, cfile
); /* consume EPOCH */
926 token
= peek_token(&val
, NULL
, cfile
);
928 if (token
!= NUMBER
) {
930 token
= next_token(&val
, NULL
, cfile
);
931 parse_warn(cfile
, "Seconds since epoch expected.");
935 token
= next_token(&val
, NULL
, cfile
); /* consume number */
941 if (token
!= NUMBER
) {
943 token
= next_token(&val
, NULL
, cfile
);
944 parse_warn(cfile
, "numeric day of week expected.");
947 token
= next_token(&val
, NULL
, cfile
); /* consume day of week */
951 token
= peek_token(&val
, NULL
, cfile
);
952 if (token
!= NUMBER
) {
954 token
= next_token(&val
, NULL
, cfile
);
955 parse_warn(cfile
, "numeric year expected.");
958 token
= next_token(&val
, NULL
, cfile
); /* consume year */
960 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
961 somebody invents a time machine, I think we can safely disregard
962 it. This actually works around a stupid Y2K bug that was present
963 in a very early beta release of dhcpd. */
968 /* Slash separating year from month... */
969 token
= peek_token(&val
, NULL
, cfile
);
970 if (token
!= SLASH
) {
972 token
= next_token(&val
, NULL
, cfile
);
974 "expected slash separating year from month.");
977 token
= next_token(&val
, NULL
, cfile
); /* consume SLASH */
980 token
= peek_token(&val
, NULL
, cfile
);
981 if (token
!= NUMBER
) {
983 token
= next_token(&val
, NULL
, cfile
);
984 parse_warn(cfile
, "numeric month expected.");
987 token
= next_token(&val
, NULL
, cfile
); /* consume month */
990 /* Slash separating month from day... */
991 token
= peek_token(&val
, NULL
, cfile
);
992 if (token
!= SLASH
) {
994 token
= next_token(&val
, NULL
, cfile
);
996 "expected slash separating month from day.");
999 token
= next_token(&val
, NULL
, cfile
); /* consume SLASH */
1001 /* Day of month... */
1002 token
= peek_token(&val
, NULL
, cfile
);
1003 if (token
!= NUMBER
) {
1005 token
= next_token(&val
, NULL
, cfile
);
1006 parse_warn(cfile
, "numeric day of month expected.");
1009 token
= next_token(&val
, NULL
, cfile
); /* consume day of month */
1013 token
= peek_token(&val
, NULL
, cfile
);
1014 if (token
!= NUMBER
) {
1016 token
= next_token(&val
, NULL
, cfile
);
1017 parse_warn(cfile
, "numeric hour expected.");
1020 token
= next_token(&val
, NULL
, cfile
); /* consume hour */
1023 /* Colon separating hour from minute... */
1024 token
= peek_token(&val
, NULL
, cfile
);
1025 if (token
!= COLON
) {
1027 token
= next_token(&val
, NULL
, cfile
);
1029 "expected colon separating hour from minute.");
1032 token
= next_token(&val
, NULL
, cfile
); /* consume colon */
1035 token
= peek_token(&val
, NULL
, cfile
);
1036 if (token
!= NUMBER
) {
1038 token
= next_token(&val
, NULL
, cfile
);
1039 parse_warn(cfile
, "numeric minute expected.");
1042 token
= next_token(&val
, NULL
, cfile
); /* consume minute */
1045 /* Colon separating minute from second... */
1046 token
= peek_token(&val
, NULL
, cfile
);
1047 if (token
!= COLON
) {
1049 token
= next_token(&val
, NULL
, cfile
);
1051 "expected colon separating minute from second.");
1054 token
= next_token(&val
, NULL
, cfile
); /* consume colon */
1057 token
= peek_token(&val
, NULL
, cfile
);
1058 if (token
!= NUMBER
) {
1060 token
= next_token(&val
, NULL
, cfile
);
1061 parse_warn(cfile
, "numeric second expected.");
1064 token
= next_token(&val
, NULL
, cfile
); /* consume second */
1068 token
= peek_token(&val
, NULL
, cfile
);
1069 if (token
== NUMBER
) {
1070 token
= next_token(&val
, NULL
, cfile
); /* consume tzoff */
1072 } else if (token
!= SEMI
) {
1073 token
= next_token(&val
, NULL
, cfile
);
1075 "Time zone offset or semicolon expected.");
1079 /* Guess the time value... */
1080 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
1081 (year
- 69) / 4 + /* Leap days since '70 */
1082 (mon
/* Days in months this year */
1085 (mon
> 1 && /* Leap day this year */
1086 !((year
- 72) & 3)) +
1087 mday
- 1) * 24) + /* Day of month */
1089 min
) * 60) + sec
+ tzoff
;
1091 /* This guess could be wrong because of leap seconds or other
1092 weirdness we don't know about that the system does. For
1093 now, we're just going to accept the guess, but at some point
1094 it might be nice to do a successive approximation here to
1095 get an exact value. Even if the error is small, if the
1096 server is restarted frequently (and thus the lease database
1097 is reread), the error could accumulate into something
1100 return((TIME
)guess
);
1104 * Wrapper to consume the semicolon after the date
1110 struct parse
*cfile
;
1113 guess
= parse_date_core(cfile
);
1115 /* Make sure the date ends in a semicolon... */
1116 if (!parse_semi(cfile
))
1124 * option-name :== IDENTIFIER |
1125 IDENTIFIER . IDENTIFIER
1129 parse_option_name (cfile
, allocate
, known
, opt
)
1130 struct parse
*cfile
;
1133 struct option
**opt
;
1136 enum dhcp_token token
;
1138 struct universe
*universe
;
1139 struct option
*option
;
1143 return DHCP_R_INVALIDARG
;
1145 token
= next_token (&val
, (unsigned *)0, cfile
);
1146 if (!is_identifier (token
)) {
1148 "expecting identifier after option keyword.");
1150 skip_to_semi (cfile
);
1151 return DHCP_R_BADPARSE
;
1153 uname
= dmalloc (strlen (val
) + 1, MDL
);
1155 log_fatal ("no memory for uname information.");
1156 strcpy (uname
, val
);
1157 token
= peek_token (&val
, (unsigned *)0, cfile
);
1159 /* Go ahead and take the DOT token... */
1160 token
= next_token (&val
, (unsigned *)0, cfile
);
1162 /* The next token should be an identifier... */
1163 token
= next_token (&val
, (unsigned *)0, cfile
);
1164 if (!is_identifier (token
)) {
1165 parse_warn (cfile
, "expecting identifier after '.'");
1167 skip_to_semi (cfile
);
1168 return DHCP_R_BADPARSE
;
1171 /* Look up the option name hash table for the specified
1173 universe
= (struct universe
*)0;
1174 if (!universe_hash_lookup (&universe
, universe_hash
,
1176 parse_warn (cfile
, "no option space named %s.", uname
);
1177 skip_to_semi (cfile
);
1178 return ISC_R_NOTFOUND
;
1181 /* Use the default hash table, which contains all the
1182 standard dhcp option names. */
1184 universe
= &dhcp_universe
;
1187 /* Look up the actual option info... */
1188 option_name_hash_lookup(opt
, universe
->name_hash
, val
, 0, MDL
);
1191 /* If we didn't get an option structure, it's an undefined option. */
1195 /* If the option name is of the form unknown-[decimal], use
1196 * the trailing decimal value to find the option definition.
1197 * If there is no definition, construct one. This is to
1198 * support legacy use of unknown options in config files or
1201 } else if (strncasecmp(val
, "unknown-", 8) == 0) {
1204 /* Option code 0 is always illegal for us, thanks
1205 * to the option decoder.
1207 if (code
== 0 || code
== universe
->end
) {
1208 parse_warn(cfile
, "Option codes 0 and %u are illegal "
1209 "in the %s space.", universe
->end
,
1211 skip_to_semi(cfile
);
1213 return ISC_R_FAILURE
;
1216 /* It's odd to think of unknown option codes as
1217 * being known, but this means we know what the
1218 * parsed name is talking about.
1223 option_code_hash_lookup(opt
, universe
->code_hash
,
1227 /* If we did not find an option of that code,
1228 * manufacture an unknown-xxx option definition.
1229 * Its single reference will ensure that it is
1230 * deleted once the option is recycled out of
1231 * existence (by the parent).
1233 if (option
== NULL
) {
1234 option
= new_option(val
, MDL
);
1235 option
->universe
= universe
;
1236 option
->code
= code
;
1237 option
->format
= default_option_format
;
1238 option_reference(opt
, option
, MDL
);
1240 log_info("option %s has been redefined as option %s. "
1241 "Please update your configs if neccessary.",
1243 /* If we've been told to allocate, that means that this
1244 * (might) be an option code definition, so we'll create
1245 * an option structure and return it for the parent to
1248 } else if (allocate
) {
1249 option
= new_option(val
, MDL
);
1250 option
-> universe
= universe
;
1251 option_reference(opt
, option
, MDL
);
1253 parse_warn(cfile
, "no option named %s in space %s",
1254 val
, universe
->name
);
1255 skip_to_semi (cfile
);
1257 return ISC_R_NOTFOUND
;
1260 /* Free the initial identifier token. */
1262 return ISC_R_SUCCESS
;
1265 /* IDENTIFIER [WIDTHS] SEMI
1266 * WIDTHS ~= LENGTH WIDTH NUMBER
1270 void parse_option_space_decl (cfile
)
1271 struct parse
*cfile
;
1275 struct universe
**ua
, *nu
;
1277 int tsize
=1, lsize
=1, hsize
= 0;
1279 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
1280 which was checked by the
1282 token
= next_token (&val
, (unsigned *)0, cfile
);
1283 if (!is_identifier (token
)) {
1284 parse_warn (cfile
, "expecting identifier.");
1285 skip_to_semi (cfile
);
1288 nu
= new_universe (MDL
);
1290 log_fatal ("No memory for new option space.");
1292 /* Set up the server option universe... */
1293 nu_name
= dmalloc (strlen (val
) + 1, MDL
);
1295 log_fatal ("No memory for new option space name.");
1296 strcpy (nu_name
, val
);
1297 nu
-> name
= nu_name
;
1300 token
= next_token(&val
, NULL
, cfile
);
1306 token
= next_token(&val
, NULL
, cfile
);
1307 if (token
!= WIDTH
) {
1308 parse_warn(cfile
, "expecting width token.");
1312 token
= next_token(&val
, NULL
, cfile
);
1313 if (token
!= NUMBER
) {
1314 parse_warn(cfile
, "expecting number 1, 2, 4.");
1324 hsize
= BYTE_NAME_HASH_SIZE
;
1328 hsize
= WORD_NAME_HASH_SIZE
;
1332 hsize
= QUAD_NAME_HASH_SIZE
;
1335 parse_warn(cfile
, "invalid code width (%d), "
1336 "expecting a 1, 2 or 4.",
1343 token
= next_token(&val
, NULL
, cfile
);
1344 if (token
!= WIDTH
) {
1345 parse_warn(cfile
, "expecting width token.");
1349 token
= next_token(&val
, NULL
, cfile
);
1350 if (token
!= NUMBER
) {
1351 parse_warn(cfile
, "expecting number 1 or 2.");
1356 if (lsize
!= 1 && lsize
!= 2) {
1357 parse_warn(cfile
, "invalid length width (%d) "
1358 "expecting 1 or 2.", lsize
);
1365 token
= next_token(&val
, NULL
, cfile
);
1366 if (token
!= SIZE
) {
1367 parse_warn(cfile
, "expecting size token.");
1371 token
= next_token(&val
, NULL
, cfile
);
1372 if (token
!= NUMBER
) {
1373 parse_warn(cfile
, "expecting a 10base number");
1377 /* (2^31)-1 is the highest Mersenne prime we should
1381 if (hsize
< 0 || hsize
> 0x7FFFFFFF) {
1382 parse_warn(cfile
, "invalid hash length: %d",
1390 parse_warn(cfile
, "Unexpected token.");
1392 } while (token
!= SEMI
);
1395 hsize
= DEFAULT_SPACE_HASH_SIZE
;
1397 nu
-> lookup_func
= lookup_hashed_option
;
1398 nu
-> option_state_dereference
= hashed_option_state_dereference
;
1399 nu
-> foreach
= hashed_option_space_foreach
;
1400 nu
-> save_func
= save_hashed_option
;
1401 nu
-> delete_func
= delete_hashed_option
;
1402 nu
-> encapsulate
= hashed_option_space_encapsulate
;
1403 nu
-> decode
= parse_option_buffer
;
1404 nu
-> length_size
= lsize
;
1405 nu
-> tag_size
= tsize
;
1408 nu
->get_tag
= getUChar
;
1409 nu
->store_tag
= putUChar
;
1412 nu
->get_tag
= getUShort
;
1413 nu
->store_tag
= putUShort
;
1416 nu
->get_tag
= getULong
;
1417 nu
->store_tag
= putULong
;
1420 log_fatal("Impossible condition at %s:%d.", MDL
);
1424 nu
->get_length
= NULL
;
1425 nu
->store_length
= NULL
;
1428 nu
->get_length
= getUChar
;
1429 nu
->store_length
= putUChar
;
1432 nu
->get_length
= getUShort
;
1433 nu
->store_length
= putUShort
;
1436 log_fatal("Impossible condition at %s:%d.", MDL
);
1438 nu
-> index
= universe_count
++;
1439 if (nu
-> index
>= universe_max
) {
1440 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
1442 log_fatal ("No memory to expand option space array.");
1443 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
1445 dfree (universes
, MDL
);
1448 universes
[nu
-> index
] = nu
;
1449 if (!option_name_new_hash(&nu
->name_hash
, hsize
, MDL
) ||
1450 !option_code_new_hash(&nu
->code_hash
, hsize
, MDL
))
1451 log_fatal("Can't allocate %s option hash table.", nu
->name
);
1452 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
1456 dfree(nu_name
, MDL
);
1460 /* This is faked up to look good right now. Ideally, this should do a
1461 recursive parse and allow arbitrary data structure definitions, but for
1462 now it just allows you to specify a single type, an array of single types,
1463 a sequence of types, or an array of sequences of types.
1465 ocd :== NUMBER EQUALS ocsd SEMI
1467 ocsd :== ocsd_type |
1468 ocsd_type_sequence |
1469 ARRAY OF ocsd_simple_type_sequence
1471 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1473 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1475 ocsd_types :== ocsd_type |
1476 ocsd_types ocsd_type
1478 ocsd_type :== ocsd_simple_type |
1479 ARRAY OF ocsd_simple_type
1481 ocsd_simple_types :== ocsd_simple_type |
1482 ocsd_simple_types ocsd_simple_type
1484 ocsd_simple_type :== BOOLEAN |
1486 SIGNED INTEGER NUMBER |
1487 UNSIGNED INTEGER NUMBER |
1491 ENCAPSULATE identifier */
1493 int parse_option_code_definition (cfile
, option
)
1494 struct parse
*cfile
;
1495 struct option
*option
;
1498 enum dhcp_token token
;
1499 struct option
*oldopt
;
1500 unsigned arrayp
= 0;
1502 int no_more_in_record
= 0;
1508 int has_encapsulation
= 0;
1509 struct universe
*encapsulated
;
1511 /* Parse the option code. */
1512 token
= next_token (&val
, (unsigned *)0, cfile
);
1513 if (token
!= NUMBER
) {
1514 parse_warn (cfile
, "expecting option code number.");
1515 skip_to_semi (cfile
);
1518 option
-> code
= atoi (val
);
1520 token
= next_token (&val
, (unsigned *)0, cfile
);
1521 if (token
!= EQUAL
) {
1522 parse_warn (cfile
, "expecting \"=\"");
1523 skip_to_semi (cfile
);
1527 /* See if this is an array. */
1528 token
= next_token (&val
, (unsigned *)0, cfile
);
1529 if (token
== ARRAY
) {
1530 token
= next_token (&val
, (unsigned *)0, cfile
);
1532 parse_warn (cfile
, "expecting \"of\".");
1533 skip_to_semi (cfile
);
1537 token
= next_token (&val
, (unsigned *)0, cfile
);
1540 if (token
== LBRACE
) {
1542 token
= next_token (&val
, (unsigned *)0, cfile
);
1545 /* At this point we're expecting a data type. */
1547 if (has_encapsulation
) {
1549 "encapsulate must always be the last item.");
1550 skip_to_semi (cfile
);
1557 parse_warn (cfile
, "no nested arrays.");
1558 skip_to_rbrace (cfile
, recordp
);
1560 skip_to_semi (cfile
);
1563 token
= next_token (&val
, (unsigned *)0, cfile
);
1565 parse_warn (cfile
, "expecting \"of\".");
1566 skip_to_semi (cfile
);
1569 arrayp
= recordp
+ 1;
1570 token
= next_token (&val
, (unsigned *)0, cfile
);
1571 if ((recordp
) && (token
== LBRACE
)) {
1573 "only uniform array inside record.");
1574 skip_to_rbrace (cfile
, recordp
+ 1);
1575 skip_to_semi (cfile
);
1585 token
= next_token (&val
, (unsigned *)0, cfile
);
1586 if (token
!= NUMBER
) {
1587 parse_warn (cfile
, "expecting number.");
1588 skip_to_rbrace (cfile
, recordp
);
1590 skip_to_semi (cfile
);
1593 switch (atoi (val
)) {
1595 type
= is_signed
? 'b' : 'B';
1598 type
= is_signed
? 's' : 'S';
1601 type
= is_signed
? 'l' : 'L';
1605 "%s bit precision is not supported.", val
);
1606 skip_to_rbrace (cfile
, recordp
);
1608 skip_to_semi (cfile
);
1615 token
= next_token (&val
, (unsigned *)0, cfile
);
1616 if (token
!= INTEGER
) {
1617 parse_warn (cfile
, "expecting \"integer\" keyword.");
1618 skip_to_rbrace (cfile
, recordp
);
1620 skip_to_semi (cfile
);
1638 /* Consume optional compression indicator. */
1639 token
= peek_token(&val
, NULL
, cfile
);
1640 if (token
== COMPRESSED
) {
1641 token
= next_token(&val
, NULL
, cfile
);
1642 tokbuf
[tokix
++] = 'D';
1651 parse_warn (cfile
, "arrays of text strings not %s",
1653 skip_to_rbrace (cfile
, recordp
);
1655 skip_to_semi (cfile
);
1658 no_more_in_record
= 1;
1665 token
= next_token (&val
, (unsigned *)0, cfile
);
1666 if (!is_identifier (token
)) {
1668 "expecting option space identifier");
1669 skip_to_semi (cfile
);
1672 encapsulated
= NULL
;
1673 if (!universe_hash_lookup(&encapsulated
, universe_hash
,
1674 val
, strlen(val
), MDL
)) {
1675 parse_warn(cfile
, "unknown option space %s", val
);
1676 skip_to_semi (cfile
);
1679 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1681 tokbuf
[tokix
++] = 'E';
1682 strcpy (&tokbuf
[tokix
], val
);
1683 tokix
+= strlen (val
);
1685 has_encapsulation
= 1;
1691 parse_warn (cfile
, "array incompatible with zerolen.");
1692 skip_to_rbrace (cfile
, recordp
);
1694 skip_to_semi (cfile
);
1697 no_more_in_record
= 1;
1701 parse_warn (cfile
, "unknown data type %s", val
);
1702 skip_to_rbrace (cfile
, recordp
);
1704 skip_to_semi (cfile
);
1708 if (tokix
== sizeof tokbuf
) {
1710 parse_warn (cfile
, "too many types in record.");
1711 skip_to_rbrace (cfile
, recordp
);
1713 skip_to_semi (cfile
);
1716 tokbuf
[tokix
++] = type
;
1719 token
= next_token (&val
, (unsigned *)0, cfile
);
1720 if (arrayp
> recordp
) {
1721 if (tokix
== sizeof tokbuf
) {
1723 "too many types in record.");
1724 skip_to_rbrace (cfile
, 1);
1725 skip_to_semi (cfile
);
1729 tokbuf
[tokix
++] = 'a';
1731 if (token
== COMMA
) {
1732 if (no_more_in_record
) {
1734 "%s must be at end of record.",
1735 type
== 't' ? "text" : "string");
1736 skip_to_rbrace (cfile
, 1);
1738 skip_to_semi (cfile
);
1741 token
= next_token (&val
, (unsigned *)0, cfile
);
1744 if (token
!= RBRACE
) {
1745 parse_warn (cfile
, "expecting right brace.");
1746 skip_to_rbrace (cfile
, 1);
1748 skip_to_semi (cfile
);
1752 if (!parse_semi (cfile
)) {
1753 parse_warn (cfile
, "semicolon expected.");
1754 skip_to_semi (cfile
);
1756 skip_to_semi (cfile
);
1759 if (has_encapsulation
&& arrayp
) {
1761 "Arrays of encapsulations don't make sense.");
1764 s
= dmalloc(tokix
+ (arrayp
? 1 : 0) + 1, MDL
);
1766 log_fatal("no memory for option format.");
1768 memcpy(s
, tokbuf
, tokix
);
1770 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1774 option
-> format
= s
;
1777 option_code_hash_lookup(&oldopt
, option
->universe
->code_hash
,
1778 &option
->code
, 0, MDL
);
1779 if (oldopt
!= NULL
) {
1781 * XXX: This illegalizes a configuration syntax that was
1782 * valid in 3.0.x, where multiple name->code mappings are
1783 * given, but only one code->name mapping survives. It is
1784 * unclear what can or should be done at this point, but it
1785 * seems best to retain 3.0.x behaviour for upgrades to go
1788 option_name_hash_delete(option->universe->name_hash,
1789 oldopt->name, 0, MDL);
1791 option_code_hash_delete(option
->universe
->code_hash
,
1792 &oldopt
->code
, 0, MDL
);
1794 option_dereference(&oldopt
, MDL
);
1796 option_code_hash_add(option
->universe
->code_hash
, &option
->code
, 0,
1798 option_name_hash_add(option
->universe
->name_hash
, option
->name
, 0,
1800 if (has_encapsulation
) {
1801 /* INSIST(tokbuf[0] == 'E'); */
1802 /* INSIST(encapsulated != NULL); */
1803 if (!option_code_hash_lookup(&encapsulated
->enc_opt
,
1804 option
->universe
->code_hash
,
1805 &option
->code
, 0, MDL
)) {
1806 log_fatal("error finding encapsulated option (%s:%d)",
1814 * base64 :== NUMBER_OR_STRING
1817 int parse_base64 (data
, cfile
)
1818 struct data_string
*data
;
1819 struct parse
*cfile
;
1821 enum dhcp_token token
;
1825 static unsigned char
1826 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1827 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1828 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1829 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1830 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1831 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1832 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1833 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1834 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1835 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1836 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1837 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1838 struct string_list
*bufs
= (struct string_list
*)0,
1839 *last
= (struct string_list
*)0,
1844 /* It's possible for a + or a / to cause a base64 quantity to be
1845 tokenized into more than one token, so we have to parse them all
1846 in before decoding. */
1850 token
= next_token (&val
, &l
, cfile
);
1851 t
= dmalloc (l
+ sizeof *t
, MDL
);
1853 log_fatal ("no memory for base64 buffer.");
1854 memset (t
, 0, (sizeof *t
) - 1);
1855 memcpy (t
-> string
, val
, l
+ 1);
1862 token
= peek_token (&val
, (unsigned *)0, cfile
);
1863 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1864 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1868 data
-> len
= (data
-> len
* 3) / 4;
1869 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1870 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1872 data
-> data
= (unsigned char *)0;
1877 for (t
= bufs
; t
; t
= t
-> next
) {
1878 for (i
= 0; t
-> string
[i
]; i
++) {
1879 unsigned foo
= t
-> string
[i
];
1880 if (terminated
&& foo
!= '=') {
1882 "stuff after base64 '=' terminator: %s.",
1886 if (foo
< ' ' || foo
> 'z') {
1889 "invalid base64 character %d.",
1892 data_string_forget (data
, MDL
);
1898 foo
= from64
[foo
- ' '];
1901 acc
= (acc
<< 6) + foo
;
1906 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1911 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1915 data
-> buffer
-> data
[j
++] = acc
;
1926 "partial base64 value left over: %d.",
1931 data
-> data
= data
-> buffer
-> data
;
1933 for (t
= bufs
; t
; t
= last
) {
1945 * colon-separated-hex-list :== NUMBER |
1946 * NUMBER COLON colon-separated-hex-list
1949 int parse_cshl (data
, cfile
)
1950 struct data_string
*data
;
1951 struct parse
*cfile
;
1953 u_int8_t ibuf
[128];
1956 struct option_tag
*sl
= (struct option_tag
*)0;
1957 struct option_tag
*next
, **last
= &sl
;
1958 enum dhcp_token token
;
1963 token
= next_token (&val
, (unsigned *)0, cfile
);
1964 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1965 parse_warn (cfile
, "expecting hexadecimal number.");
1966 skip_to_semi (cfile
);
1967 for (; sl
; sl
= next
) {
1973 if (ilen
== sizeof ibuf
) {
1974 next
= (struct option_tag
*)
1976 sizeof (struct option_tag
), MDL
);
1978 log_fatal ("no memory for string list.");
1979 memcpy (next
-> data
, ibuf
, ilen
);
1981 last
= &next
-> next
;
1985 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1987 token
= peek_token (&val
, (unsigned *)0, cfile
);
1990 token
= next_token (&val
, (unsigned *)0, cfile
);
1993 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1994 log_fatal ("no memory to store octet data.");
1995 data
-> data
= &data
-> buffer
-> data
[0];
1996 data
-> len
= tlen
+ ilen
;
1997 data
-> terminated
= 0;
1999 rvp
= &data
-> buffer
-> data
[0];
2002 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
2008 memcpy (rvp
, ibuf
, ilen
);
2013 * executable-statements :== executable-statement executable-statements |
2014 * executable-statement
2016 * executable-statement :==
2018 * ADD class-name SEMI |
2020 * OPTION option-parameter SEMI |
2021 * SUPERSEDE option-parameter SEMI |
2022 * PREPEND option-parameter SEMI |
2023 * APPEND option-parameter SEMI
2026 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
2027 struct executable_statement
**statements
;
2028 struct parse
*cfile
;
2030 enum expression_context case_context
;
2032 struct executable_statement
**next
;
2035 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
2036 next
= &((*next
) -> next
);
2042 int parse_executable_statement (result
, cfile
, lose
, case_context
)
2043 struct executable_statement
**result
;
2044 struct parse
*cfile
;
2046 enum expression_context case_context
;
2048 #if defined(ENABLE_EXECUTE)
2050 struct expression
**ep
;
2052 enum dhcp_token token
;
2055 struct option
*option
=NULL
;
2056 struct option_cache
*cache
;
2060 struct dns_zone
*zone
;
2061 isc_result_t status
;
2064 token
= peek_token (&val
, (unsigned *)0, cfile
);
2066 case DB_TIME_FORMAT
:
2067 next_token(&val
, NULL
, cfile
);
2069 token
= next_token(&val
, NULL
, cfile
);
2070 if (token
== DEFAULT
) {
2071 db_time_format
= DEFAULT_TIME_FORMAT
;
2072 } else if (token
== LOCAL
) {
2073 db_time_format
= LOCAL_TIME_FORMAT
;
2075 parse_warn(cfile
, "Expecting 'local' or 'default'.");
2077 skip_to_semi(cfile
);
2082 token
= next_token(&val
, NULL
, cfile
);
2083 if (token
!= SEMI
) {
2084 parse_warn(cfile
, "Expecting a semicolon.");
2089 /* We're done here. */
2093 next_token (&val
, (unsigned *)0, cfile
);
2094 return parse_if_statement (result
, cfile
, lose
);
2097 token
= next_token (&val
, (unsigned *)0, cfile
);
2098 token
= next_token (&val
, (unsigned *)0, cfile
);
2099 if (token
!= STRING
) {
2100 parse_warn (cfile
, "expecting class name.");
2101 skip_to_semi (cfile
);
2105 cta
= (struct class *)0;
2106 status
= find_class (&cta
, val
, MDL
);
2107 if (status
!= ISC_R_SUCCESS
) {
2108 parse_warn (cfile
, "class %s: %s",
2109 val
, isc_result_totext (status
));
2110 skip_to_semi (cfile
);
2114 if (!parse_semi (cfile
)) {
2118 if (!executable_statement_allocate (result
, MDL
))
2119 log_fatal ("no memory for new statement.");
2120 (*result
) -> op
= add_statement
;
2121 (*result
) -> data
.add
= cta
;
2125 token
= next_token (&val
, (unsigned *)0, cfile
);
2126 if (!parse_semi (cfile
)) {
2130 if (!executable_statement_allocate (result
, MDL
))
2131 log_fatal ("no memory for new statement.");
2132 (*result
) -> op
= break_statement
;
2136 token
= next_token (&val
, (unsigned *)0, cfile
);
2138 status
= parse_option_name (cfile
, 0, &known
, &option
);
2139 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2143 status
= parse_option_statement(result
, cfile
, 1, option
,
2144 send_option_statement
);
2145 option_dereference(&option
, MDL
);
2150 token
= next_token (&val
, (unsigned *)0, cfile
);
2152 status
= parse_option_name (cfile
, 0, &known
, &option
);
2153 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2157 status
= parse_option_statement(result
, cfile
, 1, option
,
2158 supersede_option_statement
);
2159 option_dereference(&option
, MDL
);
2171 token
= next_token (&val
, (unsigned *)0, cfile
);
2172 cache
= (struct option_cache
*)0;
2173 if (!parse_allow_deny (&cache
, cfile
, flag
))
2175 if (!executable_statement_allocate (result
, MDL
))
2176 log_fatal ("no memory for new statement.");
2177 (*result
) -> op
= supersede_option_statement
;
2178 (*result
) -> data
.option
= cache
;
2182 token
= next_token (&val
, (unsigned *)0, cfile
);
2183 token
= peek_token (&val
, (unsigned *)0, cfile
);
2185 goto switch_default
;
2187 status
= parse_option_name (cfile
, 0, &known
, &option
);
2188 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2192 status
= parse_option_statement(result
, cfile
, 1, option
,
2193 default_option_statement
);
2194 option_dereference(&option
, MDL
);
2198 token
= next_token (&val
, (unsigned *)0, cfile
);
2200 status
= parse_option_name (cfile
, 0, &known
, &option
);
2201 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2205 status
= parse_option_statement(result
, cfile
, 1, option
,
2206 prepend_option_statement
);
2207 option_dereference(&option
, MDL
);
2211 token
= next_token (&val
, (unsigned *)0, cfile
);
2213 status
= parse_option_name (cfile
, 0, &known
, &option
);
2214 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2218 status
= parse_option_statement(result
, cfile
, 1, option
,
2219 append_option_statement
);
2220 option_dereference(&option
, MDL
);
2224 token
= next_token (&val
, (unsigned *)0, cfile
);
2225 return parse_on_statement (result
, cfile
, lose
);
2228 token
= next_token (&val
, (unsigned *)0, cfile
);
2229 return parse_switch_statement (result
, cfile
, lose
);
2232 token
= next_token (&val
, (unsigned *)0, cfile
);
2233 if (case_context
== context_any
) {
2235 "case statement in inappropriate scope.");
2237 skip_to_semi (cfile
);
2240 return parse_case_statement (result
,
2241 cfile
, lose
, case_context
);
2244 token
= next_token (&val
, (unsigned *)0, cfile
);
2245 if (case_context
== context_any
) {
2246 parse_warn (cfile
, "switch default statement in %s",
2247 "inappropriate scope.");
2252 if (!executable_statement_allocate (result
, MDL
))
2253 log_fatal ("no memory for default statement.");
2254 (*result
) -> op
= default_statement
;
2260 token
= next_token (&val
, (unsigned *)0, cfile
);
2261 if (token
== DEFINE
)
2266 token
= next_token (&val
, (unsigned *)0, cfile
);
2267 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2269 "%s can't be a variable name", val
);
2271 skip_to_semi (cfile
);
2276 if (!executable_statement_allocate (result
, MDL
))
2277 log_fatal ("no memory for set statement.");
2278 (*result
) -> op
= flag
? define_statement
: set_statement
;
2279 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
2280 if (!(*result
)->data
.set
.name
)
2281 log_fatal ("can't allocate variable name");
2282 strcpy ((*result
) -> data
.set
.name
, val
);
2283 token
= next_token (&val
, (unsigned *)0, cfile
);
2285 if (token
== LPAREN
) {
2286 struct string_list
*head
, *cur
, *new;
2287 struct expression
*expr
;
2288 head
= cur
= (struct string_list
*)0;
2290 token
= next_token (&val
,
2291 (unsigned *)0, cfile
);
2292 if (token
== RPAREN
)
2294 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2296 "expecting argument name");
2297 skip_to_rbrace (cfile
, 0);
2299 executable_statement_dereference
2303 new = ((struct string_list
*)
2304 dmalloc (sizeof (struct string_list
) +
2305 strlen (val
), MDL
));
2307 log_fatal ("can't allocate string.");
2308 memset (new, 0, sizeof *new);
2309 strcpy (new -> string
, val
);
2316 token
= next_token (&val
,
2317 (unsigned *)0, cfile
);
2318 } while (token
== COMMA
);
2320 if (token
!= RPAREN
) {
2321 parse_warn (cfile
, "expecting right paren.");
2323 skip_to_semi (cfile
);
2325 executable_statement_dereference (result
, MDL
);
2329 token
= next_token (&val
, (unsigned *)0, cfile
);
2330 if (token
!= LBRACE
) {
2331 parse_warn (cfile
, "expecting left brace.");
2335 expr
= (struct expression
*)0;
2336 if (!(expression_allocate (&expr
, MDL
)))
2337 log_fatal ("can't allocate expression.");
2338 expr
-> op
= expr_function
;
2339 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
2340 log_fatal ("can't allocate fundef.");
2341 expr
-> data
.func
-> args
= head
;
2342 (*result
) -> data
.set
.expr
= expr
;
2344 if (!(parse_executable_statements
2345 (&expr
-> data
.func
-> statements
, cfile
, lose
,
2351 token
= next_token (&val
, (unsigned *)0, cfile
);
2352 if (token
!= RBRACE
) {
2353 parse_warn (cfile
, "expecting rigt brace.");
2357 if (token
!= EQUAL
) {
2359 "expecting '=' in %s statement.",
2360 flag
? "define" : "set");
2364 if (!parse_expression (&(*result
) -> data
.set
.expr
,
2365 cfile
, lose
, context_any
,
2366 (struct expression
**)0,
2370 "expecting expression.");
2373 skip_to_semi (cfile
);
2374 executable_statement_dereference (result
, MDL
);
2377 if (!parse_semi (cfile
)) {
2379 executable_statement_dereference (result
, MDL
);
2386 token
= next_token (&val
, (unsigned *)0, cfile
);
2388 token
= next_token (&val
, (unsigned *)0, cfile
);
2389 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2391 "%s can't be a variable name", val
);
2392 skip_to_semi (cfile
);
2397 if (!executable_statement_allocate (result
, MDL
))
2398 log_fatal ("no memory for set statement.");
2399 (*result
) -> op
= unset_statement
;
2400 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
2401 if (!(*result
)->data
.unset
)
2402 log_fatal ("can't allocate variable name");
2403 strcpy ((*result
) -> data
.unset
, val
);
2404 if (!parse_semi (cfile
)) {
2406 executable_statement_dereference (result
, MDL
);
2412 token
= next_token (&val
, (unsigned *)0, cfile
);
2414 if (!executable_statement_allocate (result
, MDL
))
2415 log_fatal ("no memory for eval statement.");
2416 (*result
) -> op
= eval_statement
;
2418 if (!parse_expression (&(*result
) -> data
.eval
,
2419 cfile
, lose
, context_data
, /* XXX */
2420 (struct expression
**)0, expr_none
)) {
2423 "expecting data expression.");
2426 skip_to_semi (cfile
);
2427 executable_statement_dereference (result
, MDL
);
2430 if (!parse_semi (cfile
)) {
2432 executable_statement_dereference (result
, MDL
);
2437 #ifdef ENABLE_EXECUTE
2438 token
= next_token(&val
, NULL
, cfile
);
2440 if (!executable_statement_allocate (result
, MDL
))
2441 log_fatal ("no memory for execute statement.");
2442 (*result
)->op
= execute_statement
;
2444 token
= next_token(&val
, NULL
, cfile
);
2445 if (token
!= LPAREN
) {
2446 parse_warn(cfile
, "left parenthesis expected.");
2447 skip_to_semi(cfile
);
2452 token
= next_token(&val
, &len
, cfile
);
2453 if (token
!= STRING
) {
2454 parse_warn(cfile
, "Expecting a quoted string.");
2455 skip_to_semi(cfile
);
2460 (*result
)->data
.execute
.command
= dmalloc(len
+ 1, MDL
);
2461 if ((*result
)->data
.execute
.command
== NULL
)
2462 log_fatal("can't allocate command name");
2463 strcpy((*result
)->data
.execute
.command
, val
);
2465 ep
= &(*result
)->data
.execute
.arglist
;
2466 (*result
)->data
.execute
.argc
= 0;
2468 while((token
= next_token(&val
, NULL
, cfile
)) == COMMA
) {
2469 if (!expression_allocate(ep
, MDL
))
2470 log_fatal ("can't allocate expression");
2472 if (!parse_data_expression (&(*ep
) -> data
.arg
.val
,
2476 "expecting expression.");
2479 skip_to_semi(cfile
);
2483 ep
= &(*ep
)->data
.arg
.next
;
2484 (*result
)->data
.execute
.argc
++;
2487 if (token
!= RPAREN
) {
2488 parse_warn(cfile
, "right parenthesis expected.");
2489 skip_to_semi(cfile
);
2494 if (!parse_semi (cfile
)) {
2496 executable_statement_dereference (result
, MDL
);
2498 #else /* ! ENABLE_EXECUTE */
2499 parse_warn(cfile
, "define ENABLE_EXECUTE in site.h to "
2500 "enable execute(); expressions.");
2501 skip_to_semi(cfile
);
2504 #endif /* ENABLE_EXECUTE */
2508 token
= next_token (&val
, (unsigned *)0, cfile
);
2510 if (!executable_statement_allocate (result
, MDL
))
2511 log_fatal ("no memory for return statement.");
2512 (*result
) -> op
= return_statement
;
2514 if (!parse_expression (&(*result
) -> data
.retval
,
2515 cfile
, lose
, context_data
,
2516 (struct expression
**)0, expr_none
)) {
2519 "expecting data expression.");
2522 skip_to_semi (cfile
);
2523 executable_statement_dereference (result
, MDL
);
2526 if (!parse_semi (cfile
)) {
2528 executable_statement_dereference (result
, MDL
);
2534 token
= next_token (&val
, (unsigned *)0, cfile
);
2536 if (!executable_statement_allocate (result
, MDL
))
2537 log_fatal ("no memory for log statement.");
2538 (*result
) -> op
= log_statement
;
2540 token
= next_token (&val
, (unsigned *)0, cfile
);
2541 if (token
!= LPAREN
) {
2542 parse_warn (cfile
, "left parenthesis expected.");
2543 skip_to_semi (cfile
);
2548 token
= peek_token (&val
, (unsigned *)0, cfile
);
2550 if (token
== FATAL
) {
2551 (*result
) -> data
.log
.priority
= log_priority_fatal
;
2552 } else if (token
== ERROR
) {
2553 (*result
) -> data
.log
.priority
= log_priority_error
;
2554 } else if (token
== TOKEN_DEBUG
) {
2555 (*result
) -> data
.log
.priority
= log_priority_debug
;
2556 } else if (token
== INFO
) {
2557 (*result
) -> data
.log
.priority
= log_priority_info
;
2559 (*result
) -> data
.log
.priority
= log_priority_debug
;
2563 token
= next_token (&val
, (unsigned *)0, cfile
);
2564 token
= next_token (&val
, (unsigned *)0, cfile
);
2565 if (token
!= COMMA
) {
2566 parse_warn (cfile
, "comma expected.");
2567 skip_to_semi (cfile
);
2573 if (!(parse_data_expression
2574 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
2575 skip_to_semi (cfile
);
2580 token
= next_token (&val
, (unsigned *)0, cfile
);
2581 if (token
!= RPAREN
) {
2582 parse_warn (cfile
, "right parenthesis expected.");
2583 skip_to_semi (cfile
);
2588 token
= next_token (&val
, (unsigned *)0, cfile
);
2589 if (token
!= SEMI
) {
2590 parse_warn (cfile
, "semicolon expected.");
2591 skip_to_semi (cfile
);
2597 /* Not really a statement, but we parse it here anyway
2598 because it's appropriate for all DHCP agents with
2601 token
= next_token (&val
, (unsigned *)0, cfile
);
2602 zone
= (struct dns_zone
*)0;
2603 if (!dns_zone_allocate (&zone
, MDL
))
2604 log_fatal ("no memory for new zone.");
2605 zone
-> name
= parse_host_name (cfile
);
2606 if (!zone
-> name
) {
2607 parse_warn (cfile
, "expecting hostname.");
2610 skip_to_semi (cfile
);
2611 dns_zone_dereference (&zone
, MDL
);
2614 i
= strlen (zone
-> name
);
2615 if (zone
-> name
[i
- 1] != '.') {
2616 s
= dmalloc ((unsigned)i
+ 2, MDL
);
2618 parse_warn (cfile
, "no trailing '.' on zone");
2621 strcpy (s
, zone
-> name
);
2624 dfree (zone
-> name
, MDL
);
2627 if (!parse_zone (zone
, cfile
))
2629 status
= enter_dns_zone (zone
);
2630 if (status
!= ISC_R_SUCCESS
) {
2631 parse_warn (cfile
, "dns zone key %s: %s",
2632 zone
-> name
, isc_result_totext (status
));
2633 dns_zone_dereference (&zone
, MDL
);
2636 dns_zone_dereference (&zone
, MDL
);
2639 /* Also not really a statement, but same idea as above. */
2641 token
= next_token (&val
, (unsigned *)0, cfile
);
2642 if (!parse_key (cfile
)) {
2649 if (config_universe
&& is_identifier (token
)) {
2650 option
= (struct option
*)0;
2651 option_name_hash_lookup(&option
,
2652 config_universe
->name_hash
,
2655 token
= next_token (&val
,
2656 (unsigned *)0, cfile
);
2657 status
= parse_option_statement
2658 (result
, cfile
, 1, option
,
2659 supersede_option_statement
);
2660 option_dereference(&option
, MDL
);
2665 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2666 /* This is rather ugly. Since function calls are
2667 data expressions, fake up an eval statement. */
2668 if (!executable_statement_allocate (result
, MDL
))
2669 log_fatal ("no memory for eval statement.");
2670 (*result
) -> op
= eval_statement
;
2672 if (!parse_expression (&(*result
) -> data
.eval
,
2673 cfile
, lose
, context_data
,
2674 (struct expression
**)0,
2677 parse_warn (cfile
, "expecting "
2681 skip_to_semi (cfile
);
2682 executable_statement_dereference (result
, MDL
);
2685 if (!parse_semi (cfile
)) {
2687 executable_statement_dereference (result
, MDL
);
2700 /* zone-statements :== zone-statement |
2701 zone-statement zone-statements
2703 PRIMARY ip-addresses SEMI |
2704 SECONDARY ip-addresses SEMI |
2705 PRIMARY6 ip-address6 SEMI |
2706 SECONDARY6 ip-address6 SEMI |
2708 ip-addresses :== ip-addr-or-hostname |
2709 ip-addr-or-hostname COMMA ip-addresses
2710 key-reference :== KEY STRING |
2713 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2718 struct option_cache
*oc
;
2721 token
= next_token (&val
, (unsigned *)0, cfile
);
2722 if (token
!= LBRACE
) {
2723 parse_warn (cfile
, "expecting left brace");
2728 token
= peek_token (&val
, (unsigned *)0, cfile
);
2731 if (zone
-> primary
) {
2733 "more than one primary.");
2734 skip_to_semi (cfile
);
2737 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2738 log_fatal ("can't allocate primary option cache.");
2739 oc
= zone
-> primary
;
2743 if (zone
-> secondary
) {
2744 parse_warn (cfile
, "more than one secondary.");
2745 skip_to_semi (cfile
);
2748 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2749 log_fatal ("can't allocate secondary.");
2750 oc
= zone
-> secondary
;
2752 token
= next_token (&val
, (unsigned *)0, cfile
);
2754 struct expression
*expr
= (struct expression
*)0;
2755 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2757 "expecting IP addr or hostname.");
2758 skip_to_semi (cfile
);
2761 if (oc
-> expression
) {
2762 struct expression
*old
=
2763 (struct expression
*)0;
2764 expression_reference (&old
,
2767 expression_dereference (&oc
-> expression
,
2769 if (!make_concat (&oc
-> expression
,
2771 log_fatal ("no memory for concat.");
2772 expression_dereference (&expr
, MDL
);
2773 expression_dereference (&old
, MDL
);
2775 expression_reference (&oc
-> expression
,
2777 expression_dereference (&expr
, MDL
);
2779 token
= next_token (&val
, (unsigned *)0, cfile
);
2780 } while (token
== COMMA
);
2781 if (token
!= SEMI
) {
2782 parse_warn (cfile
, "expecting semicolon.");
2783 skip_to_semi (cfile
);
2789 if (zone
->primary6
) {
2790 parse_warn(cfile
, "more than one primary6.");
2791 skip_to_semi(cfile
);
2794 if (!option_cache_allocate (&zone
->primary6
, MDL
))
2795 log_fatal("can't allocate primary6 option cache.");
2796 oc
= zone
->primary6
;
2800 if (zone
->secondary6
) {
2801 parse_warn(cfile
, "more than one secondary6.");
2802 skip_to_semi(cfile
);
2805 if (!option_cache_allocate (&zone
->secondary6
, MDL
))
2806 log_fatal("can't allocate secondary6 "
2808 oc
= zone
->secondary6
;
2810 token
= next_token(&val
, NULL
, cfile
);
2812 struct expression
*expr
= NULL
;
2813 if (parse_ip6_addr_expr(&expr
, cfile
) == 0) {
2814 parse_warn(cfile
, "expecting IPv6 addr.");
2815 skip_to_semi(cfile
);
2818 if (oc
->expression
) {
2819 struct expression
*old
= NULL
;
2820 expression_reference(&old
, oc
->expression
,
2822 expression_dereference(&oc
->expression
,
2824 if (!make_concat(&oc
->expression
,
2826 log_fatal("no memory for concat.");
2827 expression_dereference(&expr
, MDL
);
2828 expression_dereference(&old
, MDL
);
2830 expression_reference(&oc
->expression
,
2832 expression_dereference(&expr
, MDL
);
2834 token
= next_token(&val
, NULL
, cfile
);
2835 } while (token
== COMMA
);
2836 if (token
!= SEMI
) {
2837 parse_warn(cfile
, "expecting semicolon.");
2838 skip_to_semi(cfile
);
2844 token
= next_token (&val
, (unsigned *)0, cfile
);
2845 token
= peek_token (&val
, (unsigned *)0, cfile
);
2846 if (token
== STRING
) {
2847 token
= next_token (&val
, (unsigned *)0, cfile
);
2848 key_name
= (char *)0;
2850 key_name
= parse_host_name (cfile
);
2852 parse_warn (cfile
, "expecting key name.");
2853 skip_to_semi (cfile
);
2858 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2860 parse_warn (cfile
, "unknown key %s", val
);
2862 dfree (key_name
, MDL
);
2863 if (!parse_semi (cfile
))
2873 token
= next_token (&val
, (unsigned *)0, cfile
);
2874 if (token
!= RBRACE
) {
2875 parse_warn (cfile
, "expecting right brace.");
2881 /* key-statements :== key-statement |
2882 key-statement key-statements
2884 ALGORITHM host-name SEMI |
2885 secret-definition SEMI
2886 secret-definition :== SECRET base64val |
2889 int parse_key (struct parse
*cfile
)
2894 struct auth_key
*key
;
2895 struct data_string ds
;
2896 isc_result_t status
;
2899 key
= (struct auth_key
*)0;
2900 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2901 log_fatal ("no memory for key");
2903 token
= peek_token (&val
, (unsigned *)0, cfile
);
2904 if (token
== STRING
) {
2905 token
= next_token (&val
, (unsigned *)0, cfile
);
2906 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2908 log_fatal ("no memory for key name.");
2909 strcpy (key
-> name
, val
);
2912 key
-> name
= parse_host_name (cfile
);
2914 parse_warn (cfile
, "expecting key name.");
2915 skip_to_semi (cfile
);
2920 token
= next_token (&val
, (unsigned *)0, cfile
);
2921 if (token
!= LBRACE
) {
2922 parse_warn (cfile
, "expecting left brace");
2927 token
= next_token (&val
, (unsigned *)0, cfile
);
2930 if (key
-> algorithm
) {
2932 "key %s: too many algorithms",
2936 key
-> algorithm
= parse_host_name (cfile
);
2937 if (!key
-> algorithm
) {
2939 "expecting key algorithm name.");
2942 if (!parse_semi (cfile
))
2944 /* If the algorithm name isn't an FQDN, tack on
2945 the .SIG-ALG.REG.NET. domain. */
2946 s
= strrchr (key
-> algorithm
, '.');
2948 static char add
[] = ".SIG-ALG.REG.INT.";
2949 s
= dmalloc (strlen (key
-> algorithm
) +
2952 log_error ("no memory for key %s.",
2956 strcpy (s
, key
-> algorithm
);
2958 dfree (key
-> algorithm
, MDL
);
2959 key
-> algorithm
= s
;
2961 /* If there is no trailing '.', hack one in. */
2962 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2964 log_error ("no memory for key %s.",
2968 strcpy (s
, key
-> algorithm
);
2970 dfree (key
-> algorithm
, MDL
);
2971 key
-> algorithm
= s
;
2977 parse_warn (cfile
, "key %s: too many secrets",
2982 memset (&ds
, 0, sizeof(ds
));
2983 if (!parse_base64 (&ds
, cfile
))
2985 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2987 if (status
!= ISC_R_SUCCESS
)
2989 memcpy (key
-> key
-> value
,
2990 ds
.buffer
-> data
, ds
.len
);
2991 data_string_forget (&ds
, MDL
);
2993 if (!parse_semi (cfile
))
3002 if (token
!= RBRACE
) {
3003 parse_warn (cfile
, "expecting right brace.");
3006 /* Allow the BIND 8 syntax, which has a semicolon after each
3008 token
= peek_token (&val
, (unsigned *)0, cfile
);
3010 token
= next_token (&val
, (unsigned *)0, cfile
);
3012 /* Remember the key. */
3013 status
= omapi_auth_key_enter (key
);
3014 if (status
!= ISC_R_SUCCESS
) {
3015 parse_warn (cfile
, "tsig key %s: %s",
3016 key
-> name
, isc_result_totext (status
));
3019 omapi_auth_key_dereference (&key
, MDL
);
3023 skip_to_rbrace (cfile
, 1);
3025 omapi_auth_key_dereference (&key
, MDL
);
3030 * on-statement :== event-types LBRACE executable-statements RBRACE
3031 * event-types :== event-type OR event-types |
3033 * event-type :== EXPIRY | COMMIT | RELEASE
3036 int parse_on_statement (result
, cfile
, lose
)
3037 struct executable_statement
**result
;
3038 struct parse
*cfile
;
3041 enum dhcp_token token
;
3044 if (!executable_statement_allocate (result
, MDL
))
3045 log_fatal ("no memory for new statement.");
3046 (*result
) -> op
= on_statement
;
3049 token
= next_token (&val
, (unsigned *)0, cfile
);
3052 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
3056 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
3060 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
3064 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
3068 parse_warn (cfile
, "expecting a lease event type");
3069 skip_to_semi (cfile
);
3071 executable_statement_dereference (result
, MDL
);
3074 token
= next_token (&val
, (unsigned *)0, cfile
);
3075 } while (token
== OR
);
3077 /* Semicolon means no statements. */
3081 if (token
!= LBRACE
) {
3082 parse_warn (cfile
, "left brace expected.");
3083 skip_to_semi (cfile
);
3085 executable_statement_dereference (result
, MDL
);
3088 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
3089 cfile
, lose
, context_any
)) {
3091 /* Try to even things up. */
3093 token
= next_token (&val
,
3094 (unsigned *)0, cfile
);
3095 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3096 executable_statement_dereference (result
, MDL
);
3100 token
= next_token (&val
, (unsigned *)0, cfile
);
3101 if (token
!= RBRACE
) {
3102 parse_warn (cfile
, "right brace expected.");
3103 skip_to_semi (cfile
);
3105 executable_statement_dereference (result
, MDL
);
3112 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3116 int parse_switch_statement (result
, cfile
, lose
)
3117 struct executable_statement
**result
;
3118 struct parse
*cfile
;
3121 enum dhcp_token token
;
3124 if (!executable_statement_allocate (result
, MDL
))
3125 log_fatal ("no memory for new statement.");
3126 (*result
) -> op
= switch_statement
;
3128 token
= next_token (&val
, (unsigned *)0, cfile
);
3129 if (token
!= LPAREN
) {
3130 parse_warn (cfile
, "expecting left brace.");
3133 skip_to_semi (cfile
);
3135 executable_statement_dereference (result
, MDL
);
3139 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
3140 cfile
, lose
, context_data_or_numeric
,
3141 (struct expression
**)0, expr_none
)) {
3144 "expecting data or numeric expression.");
3150 token
= next_token (&val
, (unsigned *)0, cfile
);
3151 if (token
!= RPAREN
) {
3152 parse_warn (cfile
, "right paren expected.");
3156 token
= next_token (&val
, (unsigned *)0, cfile
);
3157 if (token
!= LBRACE
) {
3158 parse_warn (cfile
, "left brace expected.");
3161 if (!(parse_executable_statements
3162 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
3163 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
3164 ? context_data
: context_numeric
)))) {
3166 skip_to_rbrace (cfile
, 1);
3167 executable_statement_dereference (result
, MDL
);
3171 token
= next_token (&val
, (unsigned *)0, cfile
);
3172 if (token
!= RBRACE
) {
3173 parse_warn (cfile
, "right brace expected.");
3180 * case-statement :== CASE expr COLON
3184 int parse_case_statement (result
, cfile
, lose
, case_context
)
3185 struct executable_statement
**result
;
3186 struct parse
*cfile
;
3188 enum expression_context case_context
;
3190 enum dhcp_token token
;
3193 if (!executable_statement_allocate (result
, MDL
))
3194 log_fatal ("no memory for new statement.");
3195 (*result
) -> op
= case_statement
;
3197 if (!parse_expression (&(*result
) -> data
.c_case
,
3198 cfile
, lose
, case_context
,
3199 (struct expression
**)0, expr_none
))
3202 parse_warn (cfile
, "expecting %s expression.",
3203 (case_context
== context_data
3204 ? "data" : "numeric"));
3208 skip_to_semi (cfile
);
3209 executable_statement_dereference (result
, MDL
);
3213 token
= next_token (&val
, (unsigned *)0, cfile
);
3214 if (token
!= COLON
) {
3215 parse_warn (cfile
, "colon expected.");
3222 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3225 * else-statement :== <null> |
3226 * ELSE LBRACE executable-statements RBRACE |
3227 * ELSE IF if-statement |
3228 * ELSIF if-statement
3231 int parse_if_statement (result
, cfile
, lose
)
3232 struct executable_statement
**result
;
3233 struct parse
*cfile
;
3236 enum dhcp_token token
;
3240 if (!executable_statement_allocate (result
, MDL
))
3241 log_fatal ("no memory for if statement.");
3243 (*result
) -> op
= if_statement
;
3245 token
= peek_token (&val
, (unsigned *)0, cfile
);
3246 if (token
== LPAREN
) {
3248 next_token (&val
, (unsigned *)0, cfile
);
3253 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
3256 parse_warn (cfile
, "boolean expression expected.");
3257 executable_statement_dereference (result
, MDL
);
3261 #if defined (DEBUG_EXPRESSION_PARSE)
3262 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
3265 token
= next_token (&val
, (unsigned *)0, cfile
);
3266 if (token
!= RPAREN
) {
3267 parse_warn (cfile
, "expecting right paren.");
3269 executable_statement_dereference (result
, MDL
);
3273 token
= next_token (&val
, (unsigned *)0, cfile
);
3274 if (token
!= LBRACE
) {
3275 parse_warn (cfile
, "left brace expected.");
3276 skip_to_semi (cfile
);
3278 executable_statement_dereference (result
, MDL
);
3281 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
3282 cfile
, lose
, context_any
)) {
3284 /* Try to even things up. */
3286 token
= next_token (&val
,
3287 (unsigned *)0, cfile
);
3288 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3289 executable_statement_dereference (result
, MDL
);
3293 token
= next_token (&val
, (unsigned *)0, cfile
);
3294 if (token
!= RBRACE
) {
3295 parse_warn (cfile
, "right brace expected.");
3296 skip_to_semi (cfile
);
3298 executable_statement_dereference (result
, MDL
);
3301 token
= peek_token (&val
, (unsigned *)0, cfile
);
3302 if (token
== ELSE
) {
3303 token
= next_token (&val
, (unsigned *)0, cfile
);
3304 token
= peek_token (&val
, (unsigned *)0, cfile
);
3306 token
= next_token (&val
, (unsigned *)0, cfile
);
3307 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3311 "expecting if statement");
3312 executable_statement_dereference (result
, MDL
);
3316 } else if (token
!= LBRACE
) {
3317 parse_warn (cfile
, "left brace or if expected.");
3318 skip_to_semi (cfile
);
3320 executable_statement_dereference (result
, MDL
);
3323 token
= next_token (&val
, (unsigned *)0, cfile
);
3324 if (!(parse_executable_statements
3325 (&(*result
) -> data
.ie
.fc
,
3326 cfile
, lose
, context_any
))) {
3327 executable_statement_dereference (result
, MDL
);
3330 token
= next_token (&val
, (unsigned *)0, cfile
);
3331 if (token
!= RBRACE
) {
3332 parse_warn (cfile
, "right brace expected.");
3333 skip_to_semi (cfile
);
3335 executable_statement_dereference (result
, MDL
);
3339 } else if (token
== ELSIF
) {
3340 token
= next_token (&val
, (unsigned *)0, cfile
);
3341 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3345 "expecting conditional.");
3346 executable_statement_dereference (result
, MDL
);
3351 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
3357 * boolean_expression :== CHECK STRING |
3358 * NOT boolean-expression |
3359 * data-expression EQUAL data-expression |
3360 * data-expression BANG EQUAL data-expression |
3361 * data-expression REGEX_MATCH data-expression |
3362 * boolean-expression AND boolean-expression |
3363 * boolean-expression OR boolean-expression
3364 * EXISTS OPTION-NAME
3367 int parse_boolean_expression (expr
, cfile
, lose
)
3368 struct expression
**expr
;
3369 struct parse
*cfile
;
3372 /* Parse an expression... */
3373 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
3374 (struct expression
**)0, expr_none
))
3377 if (!is_boolean_expression (*expr
) &&
3378 (*expr
) -> op
!= expr_variable_reference
&&
3379 (*expr
) -> op
!= expr_funcall
) {
3380 parse_warn (cfile
, "Expecting a boolean expression.");
3382 expression_dereference (expr
, MDL
);
3388 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3390 int parse_boolean (cfile
)
3391 struct parse
*cfile
;
3393 enum dhcp_token token
;
3397 token
= next_token (&val
, (unsigned *)0, cfile
);
3398 if (!strcasecmp (val
, "true")
3399 || !strcasecmp (val
, "on"))
3401 else if (!strcasecmp (val
, "false")
3402 || !strcasecmp (val
, "off"))
3406 "boolean value (true/false/on/off) expected");
3407 skip_to_semi (cfile
);
3416 * data_expression :== SUBSTRING LPAREN data-expression COMMA
3417 * numeric-expression COMMA
3418 * numeric-expression RPAREN |
3419 * CONCAT LPAREN data-expression COMMA
3420 * data-expression RPAREN
3421 * SUFFIX LPAREN data_expression COMMA
3422 * numeric-expression RPAREN |
3423 * LCASE LPAREN data_expression RPAREN |
3424 * UCASE LPAREN data_expression RPAREN |
3425 * OPTION option_name |
3427 * PACKET LPAREN numeric-expression COMMA
3428 * numeric-expression RPAREN |
3430 * colon_separated_hex_list
3433 int parse_data_expression (expr
, cfile
, lose
)
3434 struct expression
**expr
;
3435 struct parse
*cfile
;
3438 /* Parse an expression... */
3439 if (!parse_expression (expr
, cfile
, lose
, context_data
,
3440 (struct expression
**)0, expr_none
))
3443 if (!is_data_expression (*expr
) &&
3444 (*expr
) -> op
!= expr_variable_reference
&&
3445 (*expr
) -> op
!= expr_funcall
) {
3446 expression_dereference (expr
, MDL
);
3447 parse_warn (cfile
, "Expecting a data expression.");
3455 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3456 * COMMA number RPAREN |
3460 int parse_numeric_expression (expr
, cfile
, lose
)
3461 struct expression
**expr
;
3462 struct parse
*cfile
;
3465 /* Parse an expression... */
3466 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
3467 (struct expression
**)0, expr_none
))
3470 if (!is_numeric_expression (*expr
) &&
3471 (*expr
) -> op
!= expr_variable_reference
&&
3472 (*expr
) -> op
!= expr_funcall
) {
3473 expression_dereference (expr
, MDL
);
3474 parse_warn (cfile
, "Expecting a numeric expression.");
3480 #if defined (NSUPDATE_OLD)
3482 * dns-expression :==
3483 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3484 * data-expression COMMA numeric-expression RPAREN
3485 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3486 * data-expression RPAREN
3487 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3488 * data-expression RPAREN
3489 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
3490 * data-expression RPAREN
3491 * ns-class :== IN | CHAOS | HS | NUMBER
3492 * ns-type :== A | PTR | MX | TXT | NUMBER
3495 int parse_dns_expression (expr
, cfile
, lose
)
3496 struct expression
**expr
;
3497 struct parse
*cfile
;
3500 /* Parse an expression... */
3501 if (!parse_expression (expr
, cfile
, lose
, context_dns
,
3502 (struct expression
**)0, expr_none
))
3505 if (!is_dns_expression (*expr
) &&
3506 (*expr
) -> op
!= expr_variable_reference
&&
3507 (*expr
) -> op
!= expr_funcall
) {
3508 expression_dereference (expr
, MDL
);
3509 parse_warn (cfile
, "Expecting a dns update subexpression.");
3515 #endif /* NSUPDATE_OLD */
3516 /* Parse a subexpression that does not contain a binary operator. */
3518 int parse_non_binary (expr
, cfile
, lose
, context
)
3519 struct expression
**expr
;
3520 struct parse
*cfile
;
3522 enum expression_context context
;
3524 enum dhcp_token token
;
3526 struct collection
*col
;
3527 struct expression
*nexp
, **ep
;
3530 #if defined (NSUPDATE_OLD)
3531 enum expr_op opcode
;
3535 isc_result_t status
;
3538 token
= peek_token (&val
, (unsigned *)0, cfile
);
3540 /* Check for unary operators... */
3543 token
= next_token (&val
, (unsigned *)0, cfile
);
3544 token
= next_token (&val
, (unsigned *)0, cfile
);
3545 if (token
!= STRING
) {
3546 parse_warn (cfile
, "string expected.");
3547 skip_to_semi (cfile
);
3551 for (col
= collections
; col
; col
= col
-> next
)
3552 if (!strcmp (col
-> name
, val
))
3555 parse_warn (cfile
, "unknown collection.");
3559 if (!expression_allocate (expr
, MDL
))
3560 log_fatal ("can't allocate expression");
3561 (*expr
) -> op
= expr_check
;
3562 (*expr
) -> data
.check
= col
;
3566 token
= next_token (&val
, (unsigned *)0, cfile
);
3567 #if defined(NSUPDATE_OLD)
3568 if (context
== context_dns
) {
3569 token
= peek_token (&val
, (unsigned *)0, cfile
);
3573 if (!expression_allocate (expr
, MDL
))
3574 log_fatal ("can't allocate expression");
3575 (*expr
) -> op
= expr_not
;
3576 if (!parse_non_binary (&(*expr
) -> data
.not,
3577 cfile
, lose
, context_boolean
)) {
3579 parse_warn (cfile
, "expression expected");
3580 skip_to_semi (cfile
);
3583 expression_dereference (expr
, MDL
);
3586 if (!is_boolean_expression ((*expr
) -> data
.not)) {
3588 parse_warn (cfile
, "boolean expression expected");
3589 skip_to_semi (cfile
);
3590 expression_dereference (expr
, MDL
);
3596 token
= next_token (&val
, (unsigned *)0, cfile
);
3597 if (!parse_expression (expr
, cfile
, lose
, context
,
3598 (struct expression
**)0, expr_none
)) {
3600 parse_warn (cfile
, "expression expected");
3601 skip_to_semi (cfile
);
3606 token
= next_token (&val
, (unsigned *)0, cfile
);
3607 if (token
!= RPAREN
) {
3609 parse_warn (cfile
, "right paren expected");
3610 skip_to_semi (cfile
);
3616 #if defined(NSUPDATE_OLD)
3617 if (context
== context_dns
)
3620 token
= next_token (&val
, (unsigned *)0, cfile
);
3621 if (!expression_allocate (expr
, MDL
))
3622 log_fatal ("can't allocate expression");
3623 (*expr
) -> op
= expr_exists
;
3625 /* Pass reference directly to expression structure. */
3626 status
= parse_option_name(cfile
, 0, &known
,
3627 &(*expr
)->data
.option
);
3628 if (status
!= ISC_R_SUCCESS
||
3629 (*expr
)->data
.option
== NULL
) {
3631 expression_dereference (expr
, MDL
);
3637 token
= next_token (&val
, (unsigned *)0, cfile
);
3638 if (!expression_allocate (expr
, MDL
))
3639 log_fatal ("can't allocate expression");
3640 (*expr
) -> op
= expr_static
;
3644 token
= next_token (&val
, (unsigned *)0, cfile
);
3645 if (!expression_allocate (expr
, MDL
))
3646 log_fatal ("can't allocate expression");
3647 (*expr
) -> op
= expr_known
;
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_substring
;
3656 token
= next_token (&val
, (unsigned *)0, cfile
);
3657 if (token
!= LPAREN
) {
3659 expression_dereference (expr
, MDL
);
3660 parse_warn (cfile
, "left parenthesis expected.");
3665 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
3668 expression_dereference (expr
, MDL
);
3671 "expecting data expression.");
3672 skip_to_semi (cfile
);
3678 token
= next_token (&val
, (unsigned *)0, cfile
);
3679 if (token
!= COMMA
) {
3681 expression_dereference (expr
, MDL
);
3682 parse_warn (cfile
, "comma expected.");
3688 if (!parse_numeric_expression
3689 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
3693 "expecting numeric expression.");
3694 skip_to_semi (cfile
);
3697 expression_dereference (expr
, MDL
);
3701 token
= next_token (&val
, (unsigned *)0, cfile
);
3705 if (!parse_numeric_expression
3706 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
3709 token
= next_token (&val
, (unsigned *)0, cfile
);
3710 if (token
!= RPAREN
) {
3712 parse_warn (cfile
, "right parenthesis expected.");
3714 expression_dereference (expr
, MDL
);
3720 token
= next_token (&val
, (unsigned *)0, cfile
);
3721 if (!expression_allocate (expr
, MDL
))
3722 log_fatal ("can't allocate expression");
3723 (*expr
) -> op
= expr_suffix
;
3725 token
= next_token (&val
, (unsigned *)0, cfile
);
3726 if (token
!= LPAREN
)
3729 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
3733 token
= next_token (&val
, (unsigned *)0, cfile
);
3737 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
3741 token
= next_token (&val
, (unsigned *)0, cfile
);
3742 if (token
!= RPAREN
)
3747 token
= next_token(&val
, (unsigned *)0, cfile
);
3748 if (!expression_allocate(expr
, MDL
))
3749 log_fatal ("can't allocate expression");
3750 (*expr
)->op
= expr_lcase
;
3752 token
= next_token(&val
, (unsigned *)0, cfile
);
3753 if (token
!= LPAREN
)
3756 if (!parse_data_expression(&(*expr
)->data
.lcase
, cfile
, lose
))
3759 token
= next_token(&val
, (unsigned *)0, cfile
);
3760 if (token
!= RPAREN
)
3765 token
= next_token(&val
, (unsigned *)0, cfile
);
3766 if (!expression_allocate(expr
, MDL
))
3767 log_fatal ("can't allocate expression");
3768 (*expr
)->op
= expr_ucase
;
3770 token
= next_token (&val
, (unsigned *)0, cfile
);
3771 if (token
!= LPAREN
)
3774 if (!parse_data_expression(&(*expr
)->data
.ucase
,
3778 token
= next_token(&val
, (unsigned *)0, cfile
);
3779 if (token
!= RPAREN
)
3784 token
= next_token (&val
, (unsigned *)0, cfile
);
3785 if (!expression_allocate (expr
, MDL
))
3786 log_fatal ("can't allocate expression");
3787 (*expr
) -> op
= expr_concat
;
3789 token
= next_token (&val
, (unsigned *)0, cfile
);
3790 if (token
!= LPAREN
)
3793 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3797 token
= next_token (&val
, (unsigned *)0, cfile
);
3802 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3806 token
= next_token (&val
, (unsigned *)0, cfile
);
3808 if (token
== COMMA
) {
3809 nexp
= (struct expression
*)0;
3810 if (!expression_allocate (&nexp
, MDL
))
3811 log_fatal ("can't allocate at CONCAT2");
3812 nexp
-> op
= expr_concat
;
3813 expression_reference (&nexp
-> data
.concat
[0],
3815 expression_dereference (expr
, MDL
);
3816 expression_reference (expr
, nexp
, MDL
);
3817 expression_dereference (&nexp
, MDL
);
3818 goto concat_another
;
3821 if (token
!= RPAREN
)
3825 case BINARY_TO_ASCII
:
3826 token
= next_token (&val
, (unsigned *)0, cfile
);
3827 if (!expression_allocate (expr
, MDL
))
3828 log_fatal ("can't allocate expression");
3829 (*expr
) -> op
= expr_binary_to_ascii
;
3831 token
= next_token (&val
, (unsigned *)0, cfile
);
3832 if (token
!= LPAREN
)
3835 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3839 token
= next_token (&val
, (unsigned *)0, cfile
);
3843 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3847 token
= next_token (&val
, (unsigned *)0, cfile
);
3851 if (!parse_data_expression (&(*expr
) -> data
.b2a
.separator
,
3855 token
= next_token (&val
, (unsigned *)0, cfile
);
3859 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3863 token
= next_token (&val
, (unsigned *)0, cfile
);
3864 if (token
!= RPAREN
)
3869 token
= next_token (&val
, (unsigned *)0, cfile
);
3870 if (!expression_allocate (expr
, MDL
))
3871 log_fatal ("can't allocate expression");
3872 (*expr
) -> op
= expr_reverse
;
3874 token
= next_token (&val
, (unsigned *)0, cfile
);
3875 if (token
!= LPAREN
)
3878 if (!(parse_numeric_expression
3879 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3882 token
= next_token (&val
, (unsigned *)0, cfile
);
3886 if (!(parse_data_expression
3887 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3890 token
= next_token (&val
, (unsigned *)0, cfile
);
3891 if (token
!= RPAREN
)
3896 /* pick (a, b, c) actually produces an internal representation
3897 that looks like pick (a, pick (b, pick (c, nil))). */
3898 token
= next_token (&val
, (unsigned *)0, cfile
);
3899 if (!(expression_allocate (expr
, MDL
)))
3900 log_fatal ("can't allocate expression");
3902 token
= next_token (&val
, (unsigned *)0, cfile
);
3903 if (token
!= LPAREN
)
3906 nexp
= (struct expression
*)0;
3907 expression_reference (&nexp
, *expr
, MDL
);
3909 nexp
-> op
= expr_pick_first_value
;
3910 if (!(parse_data_expression
3911 (&nexp
-> data
.pick_first_value
.car
,
3915 token
= next_token (&val
, (unsigned *)0, cfile
);
3916 if (token
== COMMA
) {
3917 struct expression
*foo
= (struct expression
*)0;
3918 if (!expression_allocate (&foo
, MDL
))
3919 log_fatal ("can't allocate expr");
3920 expression_reference
3921 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3922 expression_dereference (&nexp
, MDL
);
3923 expression_reference (&nexp
, foo
, MDL
);
3924 expression_dereference (&foo
, MDL
);
3926 } while (token
== COMMA
);
3927 expression_dereference (&nexp
, MDL
);
3929 if (token
!= RPAREN
)
3933 #if defined(NSUPDATE_OLD)
3934 /* dns-update and dns-delete are present for historical
3935 purposes, but are deprecated in favor of ns-update
3936 in combination with update, delete, exists and not
3940 #if !defined (NSUPDATE)
3942 "Please rebuild dhcpd with --with-nsupdate.");
3944 token
= next_token (&val
, (unsigned *)0, cfile
);
3945 if (token
== DNS_UPDATE
)
3946 opcode
= expr_ns_add
;
3948 opcode
= expr_ns_delete
;
3950 token
= next_token (&val
, (unsigned *)0, cfile
);
3951 if (token
!= LPAREN
)
3954 token
= next_token (&val
, (unsigned *)0, cfile
);
3955 if (token
!= STRING
) {
3957 "parse_expression: expecting string.");
3959 skip_to_semi (cfile
);
3964 if (!strcasecmp (val
, "a"))
3966 else if (!strcasecmp (val
, "aaaa"))
3968 else if (!strcasecmp (val
, "ptr"))
3970 else if (!strcasecmp (val
, "mx"))
3972 else if (!strcasecmp (val
, "cname"))
3974 else if (!strcasecmp (val
, "TXT"))
3977 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3981 s
= (opcode
== expr_ns_add
3983 : "old-dns-delete");
3984 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3986 log_fatal ("can't allocate name for %s", s
);
3988 if (!expression_allocate (expr
, MDL
))
3989 log_fatal ("can't allocate expression");
3990 (*expr
) -> op
= expr_funcall
;
3991 (*expr
) -> data
.funcall
.name
= cptr
;
3993 /* Fake up a function call. */
3994 ep
= &(*expr
) -> data
.funcall
.arglist
;
3995 if (!expression_allocate (ep
, MDL
))
3996 log_fatal ("can't allocate expression");
3997 (*ep
) -> op
= expr_arg
;
3998 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3999 log_fatal ("can't allocate rrtype value.");
4001 token
= next_token (&val
, (unsigned *)0, cfile
);
4004 ep
= &((*ep
) -> data
.arg
.next
);
4005 if (!expression_allocate (ep
, MDL
))
4006 log_fatal ("can't allocate expression");
4007 (*ep
) -> op
= expr_arg
;
4008 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
4012 token
= next_token (&val
, (unsigned *)0, cfile
);
4016 ep
= &((*ep
) -> data
.arg
.next
);
4017 if (!expression_allocate (ep
, MDL
))
4018 log_fatal ("can't allocate expression");
4019 (*ep
) -> op
= expr_arg
;
4020 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
4024 if (opcode
== expr_ns_add
) {
4025 token
= next_token (&val
, (unsigned *)0, cfile
);
4029 ep
= &((*ep
) -> data
.arg
.next
);
4030 if (!expression_allocate (ep
, MDL
))
4031 log_fatal ("can't allocate expression");
4032 (*ep
) -> op
= expr_arg
;
4033 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
4036 "expecting numeric expression.");
4041 token
= next_token (&val
, (unsigned *)0, cfile
);
4042 if (token
!= RPAREN
)
4047 #if !defined (NSUPDATE)
4049 "Please rebuild dhcpd with --with-nsupdate.");
4051 token
= next_token (&val
, (unsigned *)0, cfile
);
4052 if (!expression_allocate (expr
, MDL
))
4053 log_fatal ("can't allocate expression");
4055 token
= next_token (&val
, (unsigned *)0, cfile
);
4056 if (token
!= LPAREN
)
4061 nexp
-> op
= expr_dns_transaction
;
4062 if (!(parse_dns_expression
4063 (&nexp
-> data
.dns_transaction
.car
,
4069 "expecting dns expression.");
4070 expression_dereference (expr
, MDL
);
4075 token
= next_token (&val
, (unsigned *)0, cfile
);
4077 if (token
== COMMA
) {
4078 if (!(expression_allocate
4079 (&nexp
-> data
.dns_transaction
.cdr
,
4082 ("can't allocate expression");
4083 nexp
= nexp
-> data
.dns_transaction
.cdr
;
4085 } while (token
== COMMA
);
4087 if (token
!= RPAREN
)
4091 /* NOT EXISTS is special cased above... */
4093 token
= peek_token (&val
, (unsigned *)0, cfile
);
4094 if (token
!= EXISTS
) {
4095 parse_warn (cfile
, "expecting DNS prerequisite.");
4099 opcode
= expr_ns_not_exists
;
4102 opcode
= expr_ns_add
;
4105 opcode
= expr_ns_delete
;
4108 opcode
= expr_ns_exists
;
4110 token
= next_token (&val
, (unsigned *)0, cfile
);
4112 #if !defined (NSUPDATE)
4114 "Please rebuild dhcpd with --with-nsupdate.");
4116 if (!expression_allocate (expr
, MDL
))
4117 log_fatal ("can't allocate expression");
4118 (*expr
) -> op
= opcode
;
4120 token
= next_token (&val
, (unsigned *)0, cfile
);
4121 if (token
!= LPAREN
)
4124 token
= next_token (&val
, (unsigned *)0, cfile
);
4125 if (!is_identifier (token
) && token
!= NUMBER
) {
4126 parse_warn (cfile
, "expecting identifier or number.");
4128 expression_dereference (expr
, MDL
);
4129 skip_to_semi (cfile
);
4134 if (token
== NUMBER
)
4135 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
4136 else if (!strcasecmp (val
, "in"))
4137 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
4138 else if (!strcasecmp (val
, "chaos"))
4139 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
4140 else if (!strcasecmp (val
, "hs"))
4141 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
4143 parse_warn (cfile
, "unexpected rrclass: %s", val
);
4147 token
= next_token (&val
, (unsigned *)0, cfile
);
4151 token
= next_token (&val
, (unsigned *)0, cfile
);
4152 if (!is_identifier (token
) && token
!= NUMBER
) {
4153 parse_warn (cfile
, "expecting identifier or number.");
4157 if (token
== NUMBER
)
4158 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
4159 else if (!strcasecmp (val
, "a"))
4160 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
4161 else if (!strcasecmp (val
, "aaaa"))
4162 (*expr
) -> data
.ns_add
.rrtype
= T_AAAA
;
4163 else if (!strcasecmp (val
, "ptr"))
4164 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
4165 else if (!strcasecmp (val
, "mx"))
4166 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
4167 else if (!strcasecmp (val
, "cname"))
4168 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
4169 else if (!strcasecmp (val
, "TXT"))
4170 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
4172 parse_warn (cfile
, "unexpected rrtype: %s", val
);
4176 token
= next_token (&val
, (unsigned *)0, cfile
);
4180 if (!(parse_data_expression
4181 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
4184 token
= next_token (&val
, (unsigned *)0, cfile
);
4188 if (!(parse_data_expression
4189 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
4192 if (opcode
== expr_ns_add
) {
4193 token
= next_token (&val
, (unsigned *)0, cfile
);
4197 if (!(parse_numeric_expression
4198 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
4202 "expecting numeric expression.");
4207 token
= next_token (&val
, (unsigned *)0, cfile
);
4208 if (token
!= RPAREN
)
4211 #endif /* NSUPDATE_OLD */
4214 if (!expression_allocate (expr
, MDL
))
4215 log_fatal ("can't allocate expression");
4216 (*expr
) -> op
= (token
== OPTION
4218 : expr_config_option
);
4219 token
= next_token (&val
, (unsigned *)0, cfile
);
4221 /* Pass reference directly to expression structure. */
4222 status
= parse_option_name(cfile
, 0, &known
,
4223 &(*expr
)->data
.option
);
4224 if (status
!= ISC_R_SUCCESS
||
4225 (*expr
)->data
.option
== NULL
) {
4227 expression_dereference (expr
, MDL
);
4233 token
= next_token (&val
, (unsigned *)0, cfile
);
4234 if (!expression_allocate (expr
, MDL
))
4235 log_fatal ("can't allocate expression");
4236 (*expr
) -> op
= expr_hardware
;
4239 case LEASED_ADDRESS
:
4240 token
= next_token (&val
, (unsigned *)0, cfile
);
4241 if (!expression_allocate (expr
, MDL
))
4242 log_fatal ("can't allocate expression");
4243 (*expr
) -> op
= expr_leased_address
;
4247 token
= next_token (&val
, (unsigned *)0, cfile
);
4248 if (!expression_allocate (expr
, MDL
))
4249 log_fatal ("can't allocate expression");
4250 (*expr
) -> op
= expr_client_state
;
4254 token
= next_token (&val
, (unsigned *)0, cfile
);
4255 if (!expression_allocate (expr
, MDL
))
4256 log_fatal ("can't allocate expression");
4257 (*expr
) -> op
= expr_filename
;
4261 token
= next_token (&val
, (unsigned *)0, cfile
);
4262 if (!expression_allocate (expr
, MDL
))
4263 log_fatal ("can't allocate expression");
4264 (*expr
) -> op
= expr_sname
;
4268 token
= next_token (&val
, (unsigned *)0, cfile
);
4269 if (!expression_allocate (expr
, MDL
))
4270 log_fatal ("can't allocate expression");
4271 (*expr
) -> op
= expr_lease_time
;
4275 token
= next_token (&val
, (unsigned *)0, cfile
);
4276 if (!expression_allocate (expr
, MDL
))
4277 log_fatal ("can't allocate expression");
4278 (*expr
) -> op
= expr_null
;
4281 case HOST_DECL_NAME
:
4282 token
= next_token (&val
, (unsigned *)0, cfile
);
4283 if (!expression_allocate (expr
, MDL
))
4284 log_fatal ("can't allocate expression");
4285 (*expr
) -> op
= expr_host_decl_name
;
4288 #if defined(NSUPDATE_OLD)
4289 case UPDATED_DNS_RR
:
4290 token
= next_token (&val
, (unsigned *)0, cfile
);
4292 token
= next_token (&val
, (unsigned *)0, cfile
);
4293 if (token
!= LPAREN
)
4296 token
= next_token (&val
, (unsigned *)0, cfile
);
4297 if (token
!= STRING
) {
4298 parse_warn (cfile
, "expecting string.");
4303 if (!strcasecmp (val
, "a"))
4304 s
= "ddns-fwd-name";
4305 else if (!strcasecmp (val
, "ptr"))
4306 s
= "ddns-rev-name";
4308 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
4312 token
= next_token (&val
, (unsigned *)0, cfile
);
4313 if (token
!= RPAREN
)
4316 if (!expression_allocate (expr
, MDL
))
4317 log_fatal ("can't allocate expression");
4318 (*expr
) -> op
= expr_variable_reference
;
4319 (*expr
) -> data
.variable
=
4320 dmalloc (strlen (s
) + 1, MDL
);
4321 if (!(*expr
) -> data
.variable
)
4322 log_fatal ("can't allocate variable name.");
4323 strcpy ((*expr
) -> data
.variable
, s
);
4325 #endif /* NSUPDATE_OLD */
4327 token
= next_token (&val
, (unsigned *)0, cfile
);
4328 if (!expression_allocate (expr
, MDL
))
4329 log_fatal ("can't allocate expression");
4330 (*expr
) -> op
= expr_packet
;
4332 token
= next_token (&val
, (unsigned *)0, cfile
);
4333 if (token
!= LPAREN
)
4336 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
4340 token
= next_token (&val
, (unsigned *)0, cfile
);
4344 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
4348 token
= next_token (&val
, (unsigned *)0, cfile
);
4349 if (token
!= RPAREN
)
4354 token
= next_token (&val
, &len
, cfile
);
4355 if (!make_const_data (expr
, (const unsigned char *)val
,
4357 log_fatal ("can't make constant string expression.");
4361 token
= next_token (&val
, (unsigned *)0, cfile
);
4362 token
= next_token (&val
, (unsigned *)0, cfile
);
4363 if (token
!= LPAREN
) {
4364 parse_warn (cfile
, "left parenthesis expected.");
4369 if (!expression_allocate (expr
, MDL
))
4370 log_fatal ("can't allocate expression");
4372 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
4376 "expecting data expression.");
4377 skip_to_semi (cfile
);
4380 expression_dereference (expr
, MDL
);
4384 token
= next_token (&val
, (unsigned *)0, cfile
);
4385 if (token
!= COMMA
) {
4386 parse_warn (cfile
, "comma expected.");
4388 expression_dereference (expr
, MDL
);
4392 token
= next_token (&val
, (unsigned *)0, cfile
);
4393 if (token
!= NUMBER
) {
4394 parse_warn (cfile
, "number expected.");
4396 expression_dereference (expr
, MDL
);
4399 switch (atoi (val
)) {
4401 (*expr
) -> op
= expr_extract_int8
;
4405 (*expr
) -> op
= expr_extract_int16
;
4409 (*expr
) -> op
= expr_extract_int32
;
4414 "unsupported integer size %d", atoi (val
));
4416 skip_to_semi (cfile
);
4417 expression_dereference (expr
, MDL
);
4421 token
= next_token (&val
, (unsigned *)0, cfile
);
4422 if (token
!= RPAREN
) {
4423 parse_warn (cfile
, "right parenthesis expected.");
4425 expression_dereference (expr
, MDL
);
4431 token
= next_token (&val
, (unsigned *)0, cfile
);
4432 token
= next_token (&val
, (unsigned *)0, cfile
);
4433 if (token
!= LPAREN
) {
4434 parse_warn (cfile
, "left parenthesis expected.");
4439 if (!expression_allocate (expr
, MDL
))
4440 log_fatal ("can't allocate expression");
4442 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
4444 parse_warn (cfile
, "expecting numeric expression.");
4445 skip_to_semi (cfile
);
4447 expression_dereference (expr
, MDL
);
4451 token
= next_token (&val
, (unsigned *)0, cfile
);
4452 if (token
!= COMMA
) {
4453 parse_warn (cfile
, "comma expected.");
4455 expression_dereference (expr
, MDL
);
4459 token
= next_token (&val
, (unsigned *)0, cfile
);
4460 if (token
!= NUMBER
) {
4461 parse_warn (cfile
, "number expected.");
4463 expression_dereference (expr
, MDL
);
4466 switch (atoi (val
)) {
4468 (*expr
) -> op
= expr_encode_int8
;
4472 (*expr
) -> op
= expr_encode_int16
;
4476 (*expr
) -> op
= expr_encode_int32
;
4481 "unsupported integer size %d", atoi (val
));
4483 skip_to_semi (cfile
);
4484 expression_dereference (expr
, MDL
);
4488 token
= next_token (&val
, (unsigned *)0, cfile
);
4489 if (token
!= RPAREN
) {
4490 parse_warn (cfile
, "right parenthesis expected.");
4492 expression_dereference (expr
, MDL
);
4498 /* If we're in a numeric context, this should just be a
4499 number, by itself. */
4500 if (context
== context_numeric
||
4501 context
== context_data_or_numeric
) {
4502 next_token (&val
, (unsigned *)0, cfile
);
4503 if (!expression_allocate (expr
, MDL
))
4504 log_fatal ("can't allocate expression");
4505 (*expr
) -> op
= expr_const_int
;
4506 (*expr
) -> data
.const_int
= atoi (val
);
4510 case NUMBER_OR_NAME
:
4511 if (!expression_allocate (expr
, MDL
))
4512 log_fatal ("can't allocate expression");
4514 (*expr
) -> op
= expr_const_data
;
4515 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
4516 expression_dereference (expr
, MDL
);
4525 token
= next_token (&val
, (unsigned *)0, cfile
);
4526 if (!expression_allocate (expr
, MDL
))
4527 log_fatal ("can't allocate expression");
4528 (*expr
) -> op
= expr_const_int
;
4529 (*expr
) -> data
.const_int
= known
;
4533 known
= ISC_R_SUCCESS
;
4537 known
= DHCP_R_NOTAUTH
;
4541 known
= ISC_R_NOTIMPLEMENTED
;
4545 known
= DHCP_R_NOTZONE
;
4549 known
= DHCP_R_NXDOMAIN
;
4553 known
= DHCP_R_NXRRSET
;
4557 known
= DHCP_R_REFUSED
;
4561 known
= DHCP_R_SERVFAIL
;
4565 known
= DHCP_R_YXDOMAIN
;
4569 known
= DHCP_R_YXRRSET
;
4577 known
= S_REBOOTING
;
4581 known
= S_SELECTING
;
4585 known
= S_REQUESTING
;
4597 known
= S_REBINDING
;
4601 token
= next_token (&val
, (unsigned *)0, cfile
);
4602 token
= next_token (&val
, (unsigned *)0, cfile
);
4603 if (token
!= LPAREN
)
4606 token
= next_token (&val
, (unsigned *)0, cfile
);
4607 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
4608 parse_warn (cfile
, "%s can't be a variable name", val
);
4609 skip_to_semi (cfile
);
4614 if (!expression_allocate (expr
, MDL
))
4615 log_fatal ("can't allocate expression");
4616 (*expr
) -> op
= expr_variable_exists
;
4617 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
4618 if (!(*expr
)->data
.variable
)
4619 log_fatal ("can't allocate variable name");
4620 strcpy ((*expr
) -> data
.variable
, val
);
4621 token
= next_token (&val
, (unsigned *)0, cfile
);
4622 if (token
!= RPAREN
)
4626 /* This parses 'gethostname()'. */
4628 token
= next_token(&val
, NULL
, cfile
);
4629 if (!expression_allocate(expr
, MDL
))
4630 log_fatal("can't allocate expression");
4631 (*expr
)->op
= expr_gethostname
;
4633 token
= next_token(NULL
, NULL
, cfile
);
4634 if (token
!= LPAREN
)
4637 token
= next_token(NULL
, NULL
, cfile
);
4638 if (token
!= RPAREN
)
4643 token
= next_token(&val
, NULL
, cfile
);
4645 token
= next_token(NULL
, NULL
, cfile
);
4646 if (token
!= LPAREN
)
4649 /* The argument is a quoted string. */
4650 token
= next_token(&val
, NULL
, cfile
);
4651 if (token
!= STRING
) {
4652 parse_warn(cfile
, "Expecting quoted literal: "
4653 "\"foo.example.com\"");
4654 skip_to_semi(cfile
);
4658 if (!make_host_lookup(expr
, val
))
4659 log_fatal("Error creating gethostbyname() internal "
4660 "record. (%s:%d)", MDL
);
4662 token
= next_token(NULL
, NULL
, cfile
);
4663 if (token
!= RPAREN
)
4667 /* Not a valid start to an expression... */
4669 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
4672 token
= next_token (&val
, (unsigned *)0, cfile
);
4674 /* Save the name of the variable being referenced. */
4675 cptr
= dmalloc (strlen (val
) + 1, MDL
);
4677 log_fatal ("can't allocate variable name");
4680 /* Simple variable reference, as far as we can tell. */
4681 token
= peek_token (&val
, (unsigned *)0, cfile
);
4682 if (token
!= LPAREN
) {
4683 if (!expression_allocate (expr
, MDL
))
4684 log_fatal ("can't allocate expression");
4685 (*expr
) -> op
= expr_variable_reference
;
4686 (*expr
) -> data
.variable
= cptr
;
4690 token
= next_token (&val
, (unsigned *)0, cfile
);
4691 if (!expression_allocate (expr
, MDL
))
4692 log_fatal ("can't allocate expression");
4693 (*expr
) -> op
= expr_funcall
;
4694 (*expr
) -> data
.funcall
.name
= cptr
;
4696 /* Now parse the argument list. */
4697 ep
= &(*expr
) -> data
.funcall
.arglist
;
4699 if (!expression_allocate (ep
, MDL
))
4700 log_fatal ("can't allocate expression");
4701 (*ep
) -> op
= expr_arg
;
4702 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
4703 cfile
, lose
, context_any
,
4704 (struct expression
**)0,
4708 "expecting expression.");
4711 skip_to_semi (cfile
);
4712 expression_dereference (expr
, MDL
);
4715 ep
= &((*ep
) -> data
.arg
.next
);
4716 token
= next_token (&val
, (unsigned *)0, cfile
);
4717 } while (token
== COMMA
);
4718 if (token
!= RPAREN
) {
4719 parse_warn (cfile
, "Right parenthesis expected.");
4720 skip_to_semi (cfile
);
4722 expression_dereference (expr
, MDL
);
4730 /* Parse an expression. */
4732 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
4733 struct expression
**expr
;
4734 struct parse
*cfile
;
4736 enum expression_context context
;
4737 struct expression
**plhs
;
4740 enum dhcp_token token
;
4742 struct expression
*rhs
= (struct expression
*)0, *tmp
;
4743 struct expression
*lhs
= (struct expression
*)0;
4744 enum expr_op next_op
;
4745 enum expression_context
4746 lhs_context
= context_any
,
4747 rhs_context
= context_any
;
4749 /* Consume the left hand side we were passed. */
4751 expression_reference (&lhs
, *plhs
, MDL
);
4752 expression_dereference (plhs
, MDL
);
4756 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
4757 /* If we already have a left-hand side, then it's not
4758 okay for there not to be a right-hand side here, so
4759 we need to flag it as an error. */
4763 "expecting right-hand side.");
4765 skip_to_semi (cfile
);
4767 expression_dereference (&lhs
, MDL
);
4772 /* At this point, rhs contains either an entire subexpression,
4773 or at least a left-hand-side. If we do not see a binary token
4774 as the next token, we're done with the expression. */
4776 token
= peek_token (&val
, (unsigned *)0, cfile
);
4779 token
= next_token (&val
, (unsigned *)0, cfile
);
4780 token
= peek_token (&val
, (unsigned *)0, cfile
);
4781 if (token
!= EQUAL
) {
4782 parse_warn (cfile
, "! in boolean context without =");
4784 skip_to_semi (cfile
);
4786 expression_dereference (&lhs
, MDL
);
4789 next_op
= expr_not_equal
;
4790 context
= expression_context (rhs
);
4794 next_op
= expr_equal
;
4795 context
= expression_context (rhs
);
4800 token
= next_token(&val
, NULL
, cfile
);
4801 token
= peek_token(&val
, NULL
, cfile
);
4804 next_op
= expr_iregex_match
;
4805 else if (token
== EQUAL
)
4806 next_op
= expr_regex_match
;
4808 parse_warn(cfile
, "expecting ~= or ~~ operator");
4810 skip_to_semi(cfile
);
4812 expression_dereference(&lhs
, MDL
);
4816 context
= expression_context(rhs
);
4818 parse_warn(cfile
, "No support for regex operator.");
4820 skip_to_semi(cfile
);
4822 expression_dereference(&lhs
, MDL
);
4829 context
= expression_context (rhs
);
4834 context
= expression_context (rhs
);
4839 context
= expression_context (rhs
);
4843 next_op
= expr_subtract
;
4844 context
= expression_context (rhs
);
4848 next_op
= expr_divide
;
4849 context
= expression_context (rhs
);
4853 next_op
= expr_multiply
;
4854 context
= expression_context (rhs
);
4858 next_op
= expr_remainder
;
4859 context
= expression_context (rhs
);
4863 next_op
= expr_binary_and
;
4864 context
= expression_context (rhs
);
4868 next_op
= expr_binary_or
;
4869 context
= expression_context (rhs
);
4873 next_op
= expr_binary_xor
;
4874 context
= expression_context (rhs
);
4878 next_op
= expr_none
;
4881 /* If we have no lhs yet, we just parsed it. */
4883 /* If there was no operator following what we just parsed,
4884 then we're done - return it. */
4885 if (next_op
== expr_none
) {
4890 rhs
= (struct expression
*)0;
4892 next_token (&val
, (unsigned *)0, cfile
);
4896 /* If the next binary operator is of greater precedence than the
4897 * current operator, then rhs we have parsed so far is actually
4898 * the lhs of the next operator. To get this value, we have to
4901 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4902 op_precedence (binop
, next_op
) < 0) {
4904 /* Eat the subexpression operator token, which we pass to
4905 * parse_expression...we only peek()'d earlier.
4907 token
= next_token (&val
, (unsigned *)0, cfile
);
4909 /* Continue parsing of the right hand side with that token. */
4911 rhs
= (struct expression
*)0;
4912 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4916 "expecting a subexpression");
4921 next_op
= expr_none
;
4924 if (binop
!= expr_none
) {
4925 rhs_context
= expression_context(rhs
);
4926 lhs_context
= expression_context(lhs
);
4928 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4929 (rhs_context
!= lhs_context
)) {
4930 parse_warn (cfile
, "illegal expression relating different types");
4931 skip_to_semi (cfile
);
4932 expression_dereference (&rhs
, MDL
);
4933 expression_dereference (&lhs
, MDL
);
4939 case expr_not_equal
:
4941 if ((rhs_context
!= context_data_or_numeric
) &&
4942 (rhs_context
!= context_data
) &&
4943 (rhs_context
!= context_numeric
) &&
4944 (rhs_context
!= context_any
)) {
4945 parse_warn (cfile
, "expecting data/numeric expression");
4946 skip_to_semi (cfile
);
4947 expression_dereference (&rhs
, MDL
);
4953 case expr_regex_match
:
4955 if (expression_context(rhs
) != context_data
) {
4956 parse_warn(cfile
, "expecting data expression");
4957 skip_to_semi(cfile
);
4958 expression_dereference(&rhs
, MDL
);
4963 /* It should not be possible to attempt to parse the right
4964 * hand side of an operator there is no support for.
4966 log_fatal("Impossible condition at %s:%d.", MDL
);
4972 if ((rhs_context
!= context_boolean
) &&
4973 (rhs_context
!= context_any
)) {
4974 parse_warn (cfile
, "expecting boolean expressions");
4975 skip_to_semi (cfile
);
4976 expression_dereference (&rhs
, MDL
);
4986 case expr_remainder
:
4987 case expr_binary_and
:
4988 case expr_binary_or
:
4989 case expr_binary_xor
:
4990 if ((rhs_context
!= context_numeric
) &&
4991 (rhs_context
!= context_any
)) {
4992 parse_warn (cfile
, "expecting numeric expressions");
4993 skip_to_semi (cfile
);
4994 expression_dereference (&rhs
, MDL
);
5005 /* Now, if we didn't find a binary operator, we're done parsing
5006 this subexpression, so combine it with the preceding binary
5007 operator and return the result. */
5008 if (next_op
== expr_none
) {
5009 if (!expression_allocate (expr
, MDL
))
5010 log_fatal ("Can't allocate expression!");
5012 (*expr
) -> op
= binop
;
5013 /* All the binary operators' data union members
5014 are the same, so we'll cheat and use the member
5015 for the equals operator. */
5016 (*expr
) -> data
.equal
[0] = lhs
;
5017 (*expr
) -> data
.equal
[1] = rhs
;
5021 /* Eat the operator token - we now know it was a binary operator... */
5022 token
= next_token (&val
, (unsigned *)0, cfile
);
5024 /* Now combine the LHS and the RHS using binop. */
5025 tmp
= (struct expression
*)0;
5026 if (!expression_allocate (&tmp
, MDL
))
5027 log_fatal ("No memory for equal precedence combination.");
5029 /* Store the LHS and RHS. */
5030 tmp
-> data
.equal
[0] = lhs
;
5031 tmp
-> data
.equal
[1] = rhs
;
5035 tmp
= (struct expression
*)0;
5036 rhs
= (struct expression
*)0;
5038 /* Recursions don't return until we have parsed the end of the
5039 expression, so if we recursed earlier, we can now return what
5041 if (next_op
== expr_none
) {
5051 int parse_option_data (expr
, cfile
, lookups
, option
)
5052 struct expression
**expr
;
5053 struct parse
*cfile
;
5055 struct option
*option
;
5058 const char *fmt
= NULL
;
5059 struct expression
*tmp
;
5060 enum dhcp_token token
;
5064 * Set a flag if this is an array of a simple type (i.e.,
5065 * not an array of pairs of IP addresses, or something like
5071 /* Set fmt to start of format for 'A' and one char back
5074 if ((fmt
!= NULL
) && (fmt
!= option
->format
) && (*fmt
== 'a'))
5076 else if ((fmt
== NULL
) || (*fmt
== 'A'))
5077 fmt
= option
->format
;
5079 /* 'a' means always uniform */
5080 if ((fmt
[0] != 'Z') && (tolower((unsigned char)fmt
[1]) == 'a'))
5084 if ((*fmt
== 'A') || (*fmt
== 'a'))
5087 /* consume the optional flag */
5092 if (fmt
[1] == 'o') {
5094 * A value for the current format is
5095 * optional - check to see if the next
5096 * token is a semi-colon if so we don't
5097 * need to parse it and doing so would
5098 * consume the semi-colon which our
5099 * caller is expecting to parse
5101 token
= peek_token(&val
, (unsigned *)0,
5103 if (token
== SEMI
) {
5112 if (!parse_option_token(expr
, cfile
, &fmt
, tmp
,
5113 uniform
, lookups
)) {
5114 if (fmt
[1] != 'o') {
5116 expression_dereference (&tmp
,
5124 expression_dereference (&tmp
, MDL
);
5127 } while (*fmt
!= '\0');
5129 if ((*fmt
== 'A') || (*fmt
== 'a')) {
5130 token
= peek_token (&val
, (unsigned *)0, cfile
);
5131 /* Comma means: continue with next element in array */
5132 if (token
== COMMA
) {
5133 token
= next_token (&val
,
5134 (unsigned *)0, cfile
);
5137 /* no comma: end of array.
5138 'A' or end of string means: leave the loop */
5139 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
5141 /* 'a' means: go on with next char */
5147 } while ((*fmt
== 'A') || (*fmt
== 'a'));
5152 /* option-statement :== identifier DOT identifier <syntax> SEMI
5153 | identifier <syntax> SEMI
5155 Option syntax is handled specially through format strings, so it
5156 would be painful to come up with BNF for it. However, it always
5157 starts as above and ends in a SEMI. */
5159 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
5160 struct executable_statement
**result
;
5161 struct parse
*cfile
;
5163 struct option
*option
;
5164 enum statement_op op
;
5167 enum dhcp_token token
;
5168 struct expression
*expr
= (struct expression
*)0;
5171 token
= peek_token (&val
, (unsigned *)0, cfile
);
5172 if ((token
== SEMI
) && (option
->format
[0] != 'Z')) {
5173 /* Eat the semicolon... */
5175 * XXXSK: I'm not sure why we should ever get here, but we
5176 * do during our startup. This confuses things if
5177 * we are parsing a zero-length option, so don't
5178 * eat the semicolon token in that case.
5180 token
= next_token (&val
, (unsigned *)0, cfile
);
5181 } else if (token
== EQUAL
) {
5182 /* Eat the equals sign. */
5183 token
= next_token (&val
, (unsigned *)0, cfile
);
5185 /* Parse a data expression and use its value for the data. */
5186 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
5187 /* In this context, we must have an executable
5188 statement, so if we found something else, it's
5192 "expecting a data expression.");
5193 skip_to_semi (cfile
);
5198 if (! parse_option_data(&expr
, cfile
, lookups
, option
))
5202 if (!parse_semi (cfile
))
5204 if (!executable_statement_allocate (result
, MDL
))
5205 log_fatal ("no memory for option statement.");
5208 if (expr
&& !option_cache (&(*result
)->data
.option
,
5209 NULL
, expr
, option
, MDL
))
5210 log_fatal ("no memory for option cache");
5213 expression_dereference (&expr
, MDL
);
5218 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
5219 struct expression
**rv
;
5220 struct parse
*cfile
;
5222 struct expression
*expr
;
5227 enum dhcp_token token
;
5228 struct expression
*t
= (struct expression
*)0;
5229 unsigned char buf
[4];
5233 isc_boolean_t freeval
= ISC_FALSE
;
5235 struct enumeration_value
*e
;
5239 token
= next_token (&val
, &len
, cfile
);
5240 if (!is_identifier (token
)) {
5241 if ((*fmt
) [1] != 'o') {
5242 parse_warn (cfile
, "expecting identifier.");
5244 skip_to_semi (cfile
);
5248 if (!make_const_data (&t
, (const unsigned char *)val
,
5250 log_fatal ("No memory for %s", val
);
5254 g
= strchr (*fmt
, '.');
5257 "malformed encapsulation format (bug!)");
5258 skip_to_semi (cfile
);
5263 token
= peek_token (&val
, (unsigned *)0, cfile
);
5264 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5265 if (!expression_allocate (&t
, MDL
))
5267 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
5268 expression_dereference (&t
, MDL
);
5271 t
-> op
= expr_const_data
;
5273 token
= next_token (&val
, &len
, cfile
);
5275 if(token
== STRING
) {
5276 if (!make_const_data (&t
,
5277 (const unsigned char *)val
,
5279 log_fatal ("No memory for \"%s\"", val
);
5281 if ((*fmt
) [1] != 'o') {
5282 parse_warn (cfile
, "expecting string "
5283 "or hexadecimal data.");
5284 skip_to_semi (cfile
);
5291 case 'D': /* Domain list... */
5292 if ((*fmt
)[1] == 'c') {
5294 /* Skip the compress-flag atom. */
5299 t
= parse_domain_list(cfile
, compress
);
5302 if ((*fmt
)[1] != 'o')
5303 skip_to_semi(cfile
);
5309 case 'd': /* Domain name... */
5310 val
= parse_host_name (cfile
);
5312 parse_warn (cfile
, "not a valid domain name.");
5313 skip_to_semi (cfile
);
5320 case 't': /* Text string... */
5321 token
= next_token (&val
, &len
, cfile
);
5322 if (token
!= STRING
&& !is_identifier (token
)) {
5323 if ((*fmt
) [1] != 'o') {
5324 parse_warn (cfile
, "expecting string.");
5326 skip_to_semi (cfile
);
5331 if (!make_const_data (&t
, (const unsigned char *)val
,
5333 log_fatal ("No memory for concatenation");
5334 if (freeval
== ISC_TRUE
) {
5335 dfree((char *)val
, MDL
);
5336 freeval
= ISC_FALSE
;
5342 g
= strchr (*fmt
, '.');
5344 parse_warn (cfile
, "malformed %s (bug!)",
5345 "enumeration format");
5347 skip_to_semi (cfile
);
5351 token
= next_token (&val
, (unsigned *)0, cfile
);
5352 if (!is_identifier (token
)) {
5354 "identifier expected");
5357 e
= find_enumeration_value (f
, (*fmt
) - f
, &len
, val
);
5359 parse_warn (cfile
, "unknown value");
5362 if (!make_const_data (&t
, &e
-> value
, len
, 0, 1, MDL
))
5366 case 'I': /* IP address or hostname. */
5368 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
5371 if (!parse_ip_addr (cfile
, &addr
))
5373 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
5379 case '6': /* IPv6 address. */
5380 if (!parse_ip6_addr(cfile
, &addr
)) {
5383 if (!make_const_data(&t
, addr
.iabuf
, addr
.len
, 0, 1, MDL
)) {
5388 case 'T': /* Lease interval. */
5389 token
= next_token (&val
, (unsigned *)0, cfile
);
5390 if (token
!= INFINITE
)
5393 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5397 case 'L': /* Unsigned 32-bit integer... */
5398 case 'l': /* Signed 32-bit integer... */
5399 token
= next_token (&val
, (unsigned *)0, cfile
);
5401 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
5403 if ((*fmt
) [1] != 'o') {
5404 parse_warn (cfile
, "expecting number.");
5406 skip_to_semi (cfile
);
5410 convert_num (cfile
, buf
, val
, 0, 32);
5411 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5415 case 's': /* Signed 16-bit integer. */
5416 case 'S': /* Unsigned 16-bit integer. */
5417 token
= next_token (&val
, (unsigned *)0, cfile
);
5418 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5420 convert_num (cfile
, buf
, val
, 0, 16);
5421 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
5425 case 'b': /* Signed 8-bit integer. */
5426 case 'B': /* Unsigned 8-bit integer. */
5427 token
= next_token (&val
, (unsigned *)0, cfile
);
5428 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5430 convert_num (cfile
, buf
, val
, 0, 8);
5431 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5435 case 'f': /* Boolean flag. */
5436 token
= next_token (&val
, (unsigned *)0, cfile
);
5437 if (!is_identifier (token
)) {
5438 if ((*fmt
) [1] != 'o')
5439 parse_warn (cfile
, "expecting identifier.");
5441 if ((*fmt
) [1] != 'o') {
5443 skip_to_semi (cfile
);
5447 if (!strcasecmp (val
, "true")
5448 || !strcasecmp (val
, "on"))
5450 else if (!strcasecmp (val
, "false")
5451 || !strcasecmp (val
, "off"))
5453 else if (!strcasecmp (val
, "ignore"))
5456 if ((*fmt
) [1] != 'o')
5457 parse_warn (cfile
, "expecting boolean.");
5460 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5464 case 'Z': /* Zero-length option. */
5465 token
= peek_token (&val
, (unsigned *)0, cfile
);
5466 if (token
!= SEMI
) {
5467 parse_warn(cfile
, "semicolon expected.");
5468 skip_to_semi(cfile
);
5471 if (!make_const_data(&t
, /* expression */
5481 parse_warn (cfile
, "Bad format '%c' in parse_option_token.",
5483 skip_to_semi (cfile
);
5487 if (!make_concat (rv
, expr
, t
))
5490 expression_reference (rv
, t
, MDL
);
5491 expression_dereference (&t
, MDL
);
5495 int parse_option_decl (oc
, cfile
)
5496 struct option_cache
**oc
;
5497 struct parse
*cfile
;
5502 u_int8_t hunkbuf
[1024];
5503 unsigned hunkix
= 0;
5504 const char *fmt
, *f
;
5505 struct option
*option
=NULL
;
5506 struct iaddr ip_addr
;
5508 const u_int8_t
*cdp
;
5514 struct expression
*express
= NULL
;
5515 struct enumeration_value
*e
;
5516 isc_result_t status
;
5518 status
= parse_option_name (cfile
, 0, &known
, &option
);
5519 if (status
!= ISC_R_SUCCESS
|| option
== NULL
)
5522 /* Parse the option data... */
5524 for (fmt
= option
-> format
; *fmt
; fmt
++) {
5527 if (*fmt
== 'o' && fmt
!= option
-> format
)
5531 fmt
= strchr (fmt
, '.');
5534 "malformed %s (bug!)",
5535 "encapsulation format");
5539 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
5540 sizeof hunkbuf
- hunkix
);
5544 case 't': /* Text string... */
5545 token
= peek_token (&val
,
5547 if (token
== SEMI
&& fmt
[1] == 'o') {
5551 token
= next_token (&val
,
5553 if (token
!= STRING
) {
5555 "expecting string.");
5558 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
5560 "option data buffer %s",
5564 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
5570 if (fmt
[1] == 'c') {
5576 express
= parse_domain_list(cfile
, compress
);
5578 if (express
== NULL
)
5581 if (express
->op
!= expr_const_data
) {
5582 parse_warn(cfile
, "unexpected "
5587 len
= express
->data
.const_data
.len
;
5588 cdp
= express
->data
.const_data
.data
;
5590 if ((hunkix
+ len
) > sizeof(hunkbuf
)) {
5591 parse_warn(cfile
, "option data buffer "
5595 memcpy(&hunkbuf
[hunkix
], cdp
, len
);
5598 expression_dereference(&express
, MDL
);
5603 fmt
= strchr (fmt
, '.');
5606 "malformed %s (bug!)",
5607 "enumeration format");
5610 token
= next_token (&val
,
5611 (unsigned *)0, cfile
);
5612 if (!is_identifier (token
)) {
5614 "identifier expected");
5617 e
= find_enumeration_value (f
, fmt
- f
,
5628 if (!parse_ip6_addr(cfile
, &ip_addr
))
5634 case 'I': /* IP address. */
5635 if (!parse_ip_addr (cfile
, &ip_addr
))
5641 if (hunkix
+ len
> sizeof hunkbuf
) {
5643 "option data buffer %s",
5647 memcpy (&hunkbuf
[hunkix
], dp
, len
);
5651 case 'L': /* Unsigned 32-bit integer... */
5652 case 'l': /* Signed 32-bit integer... */
5653 token
= next_token (&val
,
5654 (unsigned *)0, cfile
);
5655 if ((token
!= NUMBER
) &&
5656 (token
!= NUMBER_OR_NAME
)) {
5659 "expecting number.");
5665 convert_num (cfile
, buf
, val
, 0, 32);
5670 case 's': /* Signed 16-bit integer. */
5671 case 'S': /* Unsigned 16-bit integer. */
5672 token
= next_token (&val
,
5673 (unsigned *)0, cfile
);
5674 if ((token
!= NUMBER
) &&
5675 (token
!= NUMBER_OR_NAME
))
5677 convert_num (cfile
, buf
, val
, 0, 16);
5682 case 'b': /* Signed 8-bit integer. */
5683 case 'B': /* Unsigned 8-bit integer. */
5684 token
= next_token (&val
,
5685 (unsigned *)0, cfile
);
5686 if ((token
!= NUMBER
) &&
5687 (token
!= NUMBER_OR_NAME
))
5689 convert_num (cfile
, buf
, val
, 0, 8);
5694 case 'f': /* Boolean flag. */
5695 token
= next_token (&val
,
5696 (unsigned *)0, cfile
);
5697 if (!is_identifier (token
)) {
5699 "expecting identifier.");
5706 if (!strcasecmp (val
, "true")
5707 || !strcasecmp (val
, "on"))
5709 else if (!strcasecmp (val
, "false")
5710 || !strcasecmp (val
, "off"))
5714 "expecting boolean.");
5721 case 'Z': /* Zero-length option */
5722 token
= next_token(&val
, (unsigned *)0, cfile
);
5723 if (token
!= SEMI
) {
5725 "semicolon expected.");
5733 log_error ("parse_option_param: Bad format %c",
5738 token
= next_token (&val
, (unsigned *)0, cfile
);
5739 } while (*fmt
== 'A' && token
== COMMA
);
5741 if (token
!= SEMI
) {
5742 parse_warn (cfile
, "semicolon expected.");
5746 bp
= (struct buffer
*)0;
5747 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
5748 log_fatal ("no memory to store option declaration.");
5750 log_fatal ("out of memory allocating option data.");
5751 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
5753 if (!option_cache_allocate (oc
, MDL
))
5754 log_fatal ("out of memory allocating option cache.");
5756 (*oc
) -> data
.buffer
= bp
;
5757 (*oc
) -> data
.data
= &bp
-> data
[0];
5758 (*oc
) -> data
.terminated
= nul_term
;
5759 (*oc
) -> data
.len
= hunkix
;
5760 option_reference(&(*oc
)->option
, option
, MDL
);
5761 option_dereference(&option
, MDL
);
5765 if (express
!= NULL
)
5766 expression_dereference(&express
, MDL
);
5767 skip_to_semi (cfile
);
5769 option_dereference(&option
, MDL
);
5774 /* Consider merging parse_cshl into this. */
5776 int parse_X (cfile
, buf
, max
)
5777 struct parse
*cfile
;
5785 token
= peek_token (&val
, (unsigned *)0, cfile
);
5786 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5789 token
= next_token (&val
, (unsigned *)0, cfile
);
5790 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
5792 "expecting hexadecimal constant.");
5793 skip_to_semi (cfile
);
5796 convert_num (cfile
, &buf
[len
], val
, 16, 8);
5799 "hexadecimal constant too long.");
5800 skip_to_semi (cfile
);
5803 token
= peek_token (&val
, (unsigned *)0, cfile
);
5805 token
= next_token (&val
,
5806 (unsigned *)0, cfile
);
5807 } while (token
== COLON
);
5809 } else if (token
== STRING
) {
5810 token
= next_token (&val
, &len
, cfile
);
5811 if (len
+ 1 > max
) {
5812 parse_warn (cfile
, "string constant too long.");
5813 skip_to_semi (cfile
);
5816 memcpy (buf
, val
, len
+ 1);
5818 parse_warn (cfile
, "expecting string or hexadecimal data");
5819 skip_to_semi (cfile
);
5825 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
5833 do_percentm (mbuf
, fmt
);
5834 /* %Audit% This is log output. %2004.06.17,Safe%
5835 * If we truncate we hope the user can get a hint from the log.
5837 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
5838 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
5840 va_start (list
, fmt
);
5841 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
5846 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
5847 if (lix
< (sizeof lexbuf
) - 1)
5848 lexbuf
[lix
++] = ' ';
5849 if (cfile
-> token_line
[i
] == '\t') {
5850 for (; lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
5857 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
5858 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
5859 if (cfile
-> lexchar
< 81)
5860 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
5864 IGNORE_RET (write (STDERR_FILENO
, mbuf
, strlen (mbuf
)));
5865 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5866 IGNORE_RET (write (STDERR_FILENO
, cfile
-> token_line
,
5867 strlen (cfile
-> token_line
)));
5868 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5869 if (cfile
-> lexchar
< 81)
5870 IGNORE_RET (write (STDERR_FILENO
, lexbuf
, lix
));
5871 IGNORE_RET (write (STDERR_FILENO
, "^\n", 2));
5874 cfile
-> warnings_occurred
= 1;
5880 parse_domain_list(struct parse
*cfile
, int compress
)
5883 enum dhcp_token token
= SEMI
;
5884 struct expression
*t
= NULL
;
5885 unsigned len
, clen
= 0;
5887 unsigned char compbuf
[256 * NS_MAXCDNAME
];
5888 const unsigned char *dnptrs
[256], **lastdnptr
;
5890 memset(compbuf
, 0, sizeof(compbuf
));
5891 memset(dnptrs
, 0, sizeof(dnptrs
));
5892 dnptrs
[0] = compbuf
;
5893 lastdnptr
= &dnptrs
[255];
5896 /* Consume the COMMA token if peeked. */
5898 next_token(&val
, NULL
, cfile
);
5900 /* Get next (or first) value. */
5901 token
= next_token(&val
, &len
, cfile
);
5903 if (token
!= STRING
) {
5904 parse_warn(cfile
, "Expecting a domain string.");
5908 /* If compression pointers are enabled, compress. If not,
5909 * just pack the names in series into the buffer.
5912 result
= MRns_name_compress(val
, compbuf
+ clen
,
5913 sizeof(compbuf
) - clen
,
5917 parse_warn(cfile
, "Error compressing domain "
5924 result
= MRns_name_pton(val
, compbuf
+ clen
,
5925 sizeof(compbuf
) - clen
);
5927 /* result == 1 means the input was fully qualified.
5928 * result == 0 means the input wasn't.
5929 * result == -1 means bad things.
5932 parse_warn(cfile
, "Error assembling domain "
5938 * We need to figure out how many bytes to increment
5939 * our buffer pointer since pton doesn't tell us.
5941 while (compbuf
[clen
] != 0)
5942 clen
+= compbuf
[clen
] + 1;
5944 /* Count the last label (0). */
5948 if (clen
> sizeof(compbuf
))
5949 log_fatal("Impossible error at %s:%d", MDL
);
5951 token
= peek_token(&val
, NULL
, cfile
);
5952 } while (token
== COMMA
);
5954 if (!make_const_data(&t
, compbuf
, clen
, 1, 1, MDL
))
5955 log_fatal("No memory for domain list object.");