3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2014 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/
32 /* Enumerations can be specified in option formats, and are used for
33 parsing, so we define the routines that manage them here. */
35 struct enumeration
*enumerations
;
37 void add_enumeration (struct enumeration
*enumeration
)
39 enumeration
-> next
= enumerations
;
40 enumerations
= enumeration
;
43 struct enumeration
*find_enumeration (const char *name
, int length
)
45 struct enumeration
*e
;
47 for (e
= enumerations
; e
; e
= e
-> next
)
48 if (strlen (e
-> name
) == length
&&
49 !memcmp (e
-> name
, name
, (unsigned)length
))
51 return (struct enumeration
*)0;
54 struct enumeration_value
*find_enumeration_value (const char *name
,
59 struct enumeration
*e
;
62 e
= find_enumeration (name
, length
);
66 for (i
= 0; e
-> values
[i
].name
; i
++) {
67 if (!strcmp (value
, e
-> values
[i
].name
))
68 return &e
-> values
[i
];
71 return (struct enumeration_value
*)0;
74 /* Skip to the semicolon ending the current statement. If we encounter
75 braces, the matching closing brace terminates the statement. If we
76 encounter a right brace but haven't encountered a left brace, return
77 leaving the brace in the token buffer for the caller. If we see a
78 semicolon and haven't seen a left brace, return. This lets us skip
83 statement foo bar { statement { } }
88 void skip_to_semi (cfile
)
91 skip_to_rbrace (cfile
, 0);
94 void skip_to_rbrace (cfile
, brace_count
)
98 enum dhcp_token token
;
101 #if defined (DEBUG_TOKEN)
102 log_error ("skip_to_rbrace: %d\n", brace_count
);
105 token
= peek_token (&val
, (unsigned *)0, cfile
);
106 if (token
== RBRACE
) {
107 skip_token(&val
, (unsigned *)0, cfile
);
113 } else if (token
== LBRACE
) {
115 } else if (token
== SEMI
&& !brace_count
) {
116 skip_token(&val
, (unsigned *)0, cfile
);
118 } else if (token
== EOL
) {
119 /* EOL only happens when parsing /etc/resolv.conf,
120 and we treat it like a semicolon because the
121 resolv.conf file is line-oriented. */
122 skip_token(&val
, (unsigned *)0, cfile
);
125 token
= next_token (&val
, (unsigned *)0, cfile
);
126 } while (token
!= END_OF_FILE
);
129 int parse_semi (cfile
)
132 enum dhcp_token token
;
135 token
= next_token (&val
, (unsigned *)0, cfile
);
137 parse_warn (cfile
, "semicolon expected.");
138 skip_to_semi (cfile
);
144 /* string-parameter :== STRING SEMI */
146 int parse_string (cfile
, sptr
, lptr
)
152 enum dhcp_token token
;
156 token
= next_token (&val
, &len
, cfile
);
157 if (token
!= STRING
) {
158 parse_warn (cfile
, "expecting a string");
159 skip_to_semi (cfile
);
162 s
= (char *)dmalloc (len
+ 1, MDL
);
164 log_fatal ("no memory for string %s.", val
);
165 memcpy (s
, val
, len
+ 1);
167 if (!parse_semi (cfile
)) {
181 * hostname :== IDENTIFIER
183 * | hostname DOT IDENTIFIER
186 char *parse_host_name (cfile
)
190 enum dhcp_token token
;
197 /* Read a dotted hostname... */
199 /* Read a token, which should be an identifier. */
200 token
= peek_token (&val
, (unsigned *)0, cfile
);
201 if (!is_identifier (token
) && token
!= NUMBER
)
203 skip_token(&val
, (unsigned *)0, cfile
);
205 /* Store this identifier... */
206 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
207 log_fatal ("can't allocate temp space for hostname.");
209 c
= cons ((caddr_t
)s
, c
);
210 len
+= strlen (s
) + 1;
211 /* Look for a dot; if it's there, keep going, otherwise
213 token
= peek_token (&val
, (unsigned *)0, cfile
);
215 token
= next_token (&val
, (unsigned *)0, cfile
);
219 } while (token
== DOT
);
221 /* Should be at least one token. */
225 /* Assemble the hostname together into a string. */
226 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
227 log_fatal ("can't allocate space for hostname.");
234 unsigned l
= strlen ((char *)(c
-> car
));
236 memcpy (t
, (char *)(c
-> car
), l
);
237 /* Free up temp space. */
238 dfree (c
-> car
, MDL
);
247 /* ip-addr-or-hostname :== ip-address | hostname
248 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
250 Parse an ip address or a hostname. If uniform is zero, put in
251 an expr_substring node to limit hostnames that evaluate to more
254 Note that RFC1123 permits hostnames to consist of all digits,
255 making it difficult to quickly disambiguate them from ip addresses.
258 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
259 struct expression
**expr
;
264 enum dhcp_token token
;
265 unsigned char addr
[4];
266 unsigned len
= sizeof addr
;
268 struct expression
*x
= (struct expression
*)0;
271 token
= peek_token (&val
, (unsigned *)0, cfile
);
273 if (token
== NUMBER
) {
275 * a hostname may be numeric, but domain names must
276 * start with a letter, so we can disambiguate by
277 * looking ahead a few tokens. we save the parse
278 * context first, and restore it after we know what
279 * we're dealing with.
281 save_parse_state(cfile
);
282 skip_token(NULL
, NULL
, cfile
);
283 if (next_token(NULL
, NULL
, cfile
) == DOT
&&
284 next_token(NULL
, NULL
, cfile
) == NUMBER
)
286 restore_parse_state(cfile
);
289 parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
290 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
294 if (is_identifier (token
) || token
== NUMBER
) {
295 name
= parse_host_name (cfile
);
298 if (!make_host_lookup (expr
, name
)) {
304 if (!make_limit (&x
, *expr
, 4))
306 expression_dereference (expr
, MDL
);
310 if (token
!= RBRACE
&& token
!= LBRACE
)
311 token
= next_token (&val
, (unsigned *)0, cfile
);
312 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
315 skip_to_semi (cfile
);
323 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
326 int parse_ip_addr (cfile
, addr
)
331 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
332 &addr
-> len
, DOT
, 10, 8))
338 * Return true if every character in the string is hexadecimal.
341 is_hex_string(const char *s
) {
343 if (!isxdigit((int)*s
)) {
352 * ip-address6 :== (complicated set of rules)
354 * See section 2.2 of RFC 1884 for details.
356 * We are lazy for this. We pull numbers, names, colons, and dots
357 * together and then throw the resulting string at the inet_pton()
362 parse_ip6_addr(struct parse
*cfile
, struct iaddr
*addr
) {
363 enum dhcp_token token
;
367 char v6
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
371 * First token is non-raw. This way we eat any whitespace before
372 * our IPv6 address begins, like one would expect.
374 token
= peek_token(&val
, NULL
, cfile
);
381 if ((((token
== NAME
) || (token
== NUMBER_OR_NAME
)) &&
382 is_hex_string(val
)) ||
387 next_raw_token(&val
, NULL
, cfile
);
388 val_len
= strlen(val
);
389 if ((v6_len
+ val_len
) >= sizeof(v6
)) {
390 parse_warn(cfile
, "Invalid IPv6 address.");
394 memcpy(v6
+v6_len
, val
, val_len
);
400 token
= peek_raw_token(&val
, NULL
, cfile
);
405 * Use inet_pton() for actual work.
407 if (inet_pton(AF_INET6
, v6
, addr
->iabuf
) <= 0) {
408 parse_warn(cfile
, "Invalid IPv6 address.");
417 * Same as parse_ip6_addr() above, but returns the value in the
418 * expression rather than in an address structure.
421 parse_ip6_addr_expr(struct expression
**expr
,
422 struct parse
*cfile
) {
425 if (!parse_ip6_addr(cfile
, &addr
)) {
428 return make_const_data(expr
, addr
.iabuf
, addr
.len
, 0, 1, MDL
);
432 * ip6-prefix :== ip6-address "/" NUMBER
435 parse_ip6_prefix(struct parse
*cfile
, struct iaddr
*addr
, u_int8_t
*plen
) {
436 enum dhcp_token token
;
440 if (!parse_ip6_addr(cfile
, addr
)) {
443 token
= next_token(&val
, NULL
, cfile
);
444 if (token
!= SLASH
) {
445 parse_warn(cfile
, "Slash expected.");
450 token
= next_token(&val
, NULL
, cfile
);
451 if (token
!= NUMBER
) {
452 parse_warn(cfile
, "Number expected.");
458 if ((n
< 0) || (n
> 128)) {
459 parse_warn(cfile
, "Invalid IPv6 prefix length.");
463 if (!is_cidr_mask_valid(addr
, n
)) {
464 parse_warn(cfile
, "network mask too short.");
473 * ip-address-with-subnet :== ip-address |
474 * ip-address "/" NUMBER
478 parse_ip_addr_with_subnet(cfile
, match
)
480 struct iaddrmatch
*match
;
482 const char *val
, *orig
;
483 enum dhcp_token token
;
486 unsigned char newval
, warnmask
=0;
488 if (parse_ip_addr(cfile
, &match
->addr
)) {
489 /* default to host mask */
490 prefixlen
= match
->addr
.len
* 8;
492 token
= peek_token(&val
, NULL
, cfile
);
494 if (token
== SLASH
) {
495 skip_token(&val
, NULL
, cfile
);
496 token
= next_token(&val
, NULL
, cfile
);
498 if (token
!= NUMBER
) {
499 parse_warn(cfile
, "Invalid CIDR prefix length:"
500 " expecting a number.");
504 prefixlen
= atoi(val
);
507 prefixlen
> (match
->addr
.len
* 8)) {
508 parse_warn(cfile
, "subnet prefix is out of "
510 match
->addr
.len
* 8);
515 /* construct a suitable mask field */
518 match
->mask
.len
= match
->addr
.len
;
520 /* count of 0xff bytes in mask */
521 fflen
= prefixlen
/ 8;
523 /* set leading mask */
524 memset(match
->mask
.iabuf
, 0xff, fflen
);
527 if (fflen
< match
->mask
.len
) {
528 match
->mask
.iabuf
[fflen
] =
529 "\x00\x80\xc0\xe0\xf0\xf8\xfc\xfe"[prefixlen
% 8];
531 memset(match
->mask
.iabuf
+fflen
+1, 0x00,
532 match
->mask
.len
- fflen
- 1);
534 /* AND-out insignificant bits from supplied netmask. */
535 orig
= piaddr(match
->addr
);
537 newval
= match
->addr
.iabuf
[fflen
] &
538 match
->mask
.iabuf
[fflen
];
540 if (newval
!= match
->addr
.iabuf
[fflen
]) {
542 match
->addr
.iabuf
[fflen
] = newval
;
544 } while (++fflen
< match
->mask
.len
);
547 log_error("Warning: Extraneous bits removed "
548 "in address component of %s/%d.",
550 log_error("New value: %s/%d.",
551 piaddr(match
->addr
), prefixlen
);
559 "expecting ip-address or ip-address/prefixlen");
561 return 0; /* let caller pick up pieces */
565 * hardware-parameter :== HARDWARE hardware-type colon-separated-hex-list SEMI
566 * hardware-type :== ETHERNET | TOKEN_RING | TOKEN_FDDI | INFINIBAND
567 * Note that INFINIBAND may not be useful for some items, such as classification
568 * as the hardware address won't always be available.
571 void parse_hardware_param (cfile
, hardware
)
573 struct hardware
*hardware
;
576 enum dhcp_token token
;
580 token
= next_token(&val
, NULL
, cfile
);
583 hardware
->hbuf
[0] = HTYPE_ETHER
;
586 hardware
->hbuf
[0] = HTYPE_IEEE802
;
589 hardware
->hbuf
[0] = HTYPE_FDDI
;
591 case TOKEN_INFINIBAND
:
592 hardware
->hbuf
[0] = HTYPE_INFINIBAND
;
595 if (!strncmp(val
, "unknown-", 8)) {
596 hardware
->hbuf
[0] = atoi(&val
[8]);
599 "expecting a network hardware type");
606 /* Parse the hardware address information. Technically,
607 it would make a lot of sense to restrict the length of the
608 data we'll accept here to the length of a particular hardware
609 address type. Unfortunately, there are some broken clients
610 out there that put bogus data in the chaddr buffer, and we accept
611 that data in the lease file rather than simply failing on such
614 token
= peek_token(&val
, NULL
, cfile
);
619 t
= parse_numeric_aggregate(cfile
, NULL
, &hlen
, COLON
, 16, 8);
624 if (hlen
+ 1 > sizeof(hardware
->hbuf
)) {
626 parse_warn(cfile
, "hardware address too long");
628 hardware
->hlen
= hlen
+ 1;
629 memcpy((unsigned char *)&hardware
->hbuf
[1], t
, hlen
);
630 if (hlen
+ 1 < sizeof(hardware
->hbuf
))
631 memset(&hardware
->hbuf
[hlen
+ 1], 0,
632 (sizeof(hardware
->hbuf
)) - hlen
- 1);
637 token
= next_token(&val
, NULL
, cfile
);
639 parse_warn(cfile
, "expecting semicolon.");
644 /* lease-time :== NUMBER SEMI */
646 void parse_lease_time (cfile
, timep
)
651 enum dhcp_token token
;
654 token
= next_token (&val
, (unsigned *)0, cfile
);
655 if (token
!= NUMBER
) {
656 parse_warn (cfile
, "Expecting numeric lease time");
657 skip_to_semi (cfile
);
660 convert_num(cfile
, (unsigned char *)&num
, val
, 10, 32);
661 /* Unswap the number - convert_num returns stuff in NBO. */
667 /* No BNF for numeric aggregates - that's defined by the caller. What
668 this function does is to parse a sequence of numbers separated by
669 the token specified in separator. If max is zero, any number of
670 numbers will be parsed; otherwise, exactly max numbers are
671 expected. Base and size tell us how to internalize the numbers
672 once they've been tokenized.
674 buf - A pointer to space to return the parsed value, if it is null
675 then the function will allocate space for the return.
677 max - The maximum number of items to store. If zero there is no
678 maximum. When buf is null and the function needs to allocate space
679 it will do an allocation of max size at the beginning if max is non
680 zero. If max is zero then the allocation will be done later, after
681 the function has determined the size necessary for the incoming
684 returns NULL on errors or a pointer to the value string on success.
685 The pointer will either be buf if it was non-NULL or newly allocated
686 space if buf was NULL
690 unsigned char *parse_numeric_aggregate (cfile
, buf
,
691 max
, separator
, base
, size
)
700 enum dhcp_token token
;
701 unsigned char *bufp
= buf
, *s
, *t
;
706 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
708 log_fatal ("no space for numeric aggregate");
714 token
= peek_token (&val
, (unsigned *)0, cfile
);
715 if (token
!= separator
) {
718 if (token
!= RBRACE
&& token
!= LBRACE
)
719 token
= next_token (&val
,
722 parse_warn (cfile
, "too few numbers.");
724 skip_to_semi (cfile
);
725 /* free bufp if it was allocated */
726 if ((bufp
!= NULL
) && (bufp
!= buf
))
728 return (unsigned char *)0;
730 skip_token(&val
, (unsigned *)0, cfile
);
732 token
= next_token (&val
, (unsigned *)0, cfile
);
734 if (token
== END_OF_FILE
) {
735 parse_warn (cfile
, "unexpected end of file");
739 /* Allow NUMBER_OR_NAME if base is 16. */
740 if (token
!= NUMBER
&&
741 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
742 parse_warn (cfile
, "expecting numeric value.");
743 skip_to_semi (cfile
);
744 /* free bufp if it was allocated */
745 if ((bufp
!= NULL
) && (bufp
!= buf
))
747 /* free any linked numbers we may have allocated */
756 /* If we can, convert the number now; otherwise, build
757 a linked list of all the numbers. */
759 convert_num (cfile
, s
, val
, base
, size
);
762 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
764 log_fatal ("no temp space for number.");
765 strcpy ((char *)t
, val
);
766 c
= cons ((caddr_t
)t
, c
);
768 } while (++count
!= *max
);
770 /* If we had to cons up a list, convert it now. */
773 * No need to cleanup bufp, to get here we didn't allocate
776 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
778 log_fatal ("no space for numeric aggregate.");
779 s
= bufp
+ count
- size
/ 8;
784 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
786 /* Free up temp space. */
787 dfree (c
-> car
, MDL
);
794 void convert_num (cfile
, buf
, str
, base
, size
)
801 const unsigned char *ptr
= (const unsigned char *)str
;
812 /* If base wasn't specified, figure it out from the data. */
814 if (ptr
[0] == '0') {
815 if (ptr
[1] == 'x') {
818 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
831 /* XXX assumes ASCII... */
833 tval
= tval
- 'a' + 10;
834 else if (tval
>= 'A')
835 tval
= tval
- 'A' + 10;
836 else if (tval
>= '0')
839 parse_warn (cfile
, "Bogus number: %s.", str
);
844 "Bogus number %s: digit %d not in base %d",
848 val
= val
* base
+ tval
;
852 max
= (1 << (size
- 1));
854 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
859 "%s%lo exceeds max (%d) for precision.",
861 (unsigned long)val
, max
);
865 "%s%lx exceeds max (%d) for precision.",
867 (unsigned long)val
, max
);
871 "%s%lu exceeds max (%d) for precision.",
873 (unsigned long)val
, max
);
881 *buf
= -(unsigned long)val
;
884 putShort (buf
, -(long)val
);
887 putLong (buf
, -(long)val
);
891 "Unexpected integer size: %d\n", size
);
897 *buf
= (u_int8_t
)val
;
900 putUShort (buf
, (u_int16_t
)val
);
907 "Unexpected integer size: %d\n", size
);
914 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
915 * NUMBER COLON NUMBER COLON NUMBER |
916 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
917 * NUMBER COLON NUMBER COLON NUMBER NUMBER |
921 * Dates are stored in UTC or with a timezone offset; first number is day
922 * of week; next is year/month/day; next is hours:minutes:seconds on a
923 * 24-hour clock, followed by the timezone offset in seconds, which is
928 * just parse the date
929 * any trailing semi must be consumed by the caller of this routine
932 parse_date_core(cfile
)
936 int tzoff
, year
, mon
, mday
, hour
, min
, sec
;
938 enum dhcp_token token
;
939 static int months
[11] = { 31, 59, 90, 120, 151, 181,
940 212, 243, 273, 304, 334 };
942 /* "never", "epoch" or day of week */
943 token
= peek_token(&val
, NULL
, cfile
);
944 if (token
== NEVER
) {
945 skip_token(&val
, NULL
, cfile
); /* consume NEVER */
949 /* This indicates 'local' time format. */
950 if (token
== EPOCH
) {
951 skip_token(&val
, NULL
, cfile
); /* consume EPOCH */
952 token
= peek_token(&val
, NULL
, cfile
);
954 if (token
!= NUMBER
) {
956 skip_token(&val
, NULL
, cfile
);
957 parse_warn(cfile
, "Seconds since epoch expected.");
961 skip_token(&val
, NULL
, cfile
); /* consume number */
967 if (token
!= NUMBER
) {
969 skip_token(&val
, NULL
, cfile
);
970 parse_warn(cfile
, "numeric day of week expected.");
973 skip_token(&val
, NULL
, cfile
); /* consume day of week */
974 /* we are not using this for anything */
977 token
= peek_token(&val
, NULL
, cfile
);
978 if (token
!= NUMBER
) {
980 skip_token(&val
, NULL
, cfile
);
981 parse_warn(cfile
, "numeric year expected.");
984 skip_token(&val
, NULL
, cfile
); /* consume year */
986 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
987 somebody invents a time machine, I think we can safely disregard
988 it. This actually works around a stupid Y2K bug that was present
989 in a very early beta release of dhcpd. */
994 /* Slash separating year from month... */
995 token
= peek_token(&val
, NULL
, cfile
);
996 if (token
!= SLASH
) {
998 skip_token(&val
, NULL
, cfile
);
1000 "expected slash separating year from month.");
1003 skip_token(&val
, NULL
, cfile
); /* consume SLASH */
1006 token
= peek_token(&val
, NULL
, cfile
);
1007 if (token
!= NUMBER
) {
1009 skip_token(&val
, NULL
, cfile
);
1010 parse_warn(cfile
, "numeric month expected.");
1013 skip_token(&val
, NULL
, cfile
); /* consume month */
1014 mon
= atoi(val
) - 1;
1016 /* Slash separating month from day... */
1017 token
= peek_token(&val
, NULL
, cfile
);
1018 if (token
!= SLASH
) {
1020 skip_token(&val
, NULL
, cfile
);
1022 "expected slash separating month from day.");
1025 skip_token(&val
, NULL
, cfile
); /* consume SLASH */
1027 /* Day of month... */
1028 token
= peek_token(&val
, NULL
, cfile
);
1029 if (token
!= NUMBER
) {
1031 skip_token(&val
, NULL
, cfile
);
1032 parse_warn(cfile
, "numeric day of month expected.");
1035 skip_token(&val
, NULL
, cfile
); /* consume day of month */
1039 token
= peek_token(&val
, NULL
, cfile
);
1040 if (token
!= NUMBER
) {
1042 skip_token(&val
, NULL
, cfile
);
1043 parse_warn(cfile
, "numeric hour expected.");
1046 skip_token(&val
, NULL
, cfile
); /* consume hour */
1049 /* Colon separating hour from minute... */
1050 token
= peek_token(&val
, NULL
, cfile
);
1051 if (token
!= COLON
) {
1053 skip_token(&val
, NULL
, cfile
);
1055 "expected colon separating hour from minute.");
1058 skip_token(&val
, NULL
, cfile
); /* consume colon */
1061 token
= peek_token(&val
, NULL
, cfile
);
1062 if (token
!= NUMBER
) {
1064 skip_token(&val
, NULL
, cfile
);
1065 parse_warn(cfile
, "numeric minute expected.");
1068 skip_token(&val
, NULL
, cfile
); /* consume minute */
1071 /* Colon separating minute from second... */
1072 token
= peek_token(&val
, NULL
, cfile
);
1073 if (token
!= COLON
) {
1075 skip_token(&val
, NULL
, cfile
);
1077 "expected colon separating minute from second.");
1080 skip_token(&val
, NULL
, cfile
); /* consume colon */
1083 token
= peek_token(&val
, NULL
, cfile
);
1084 if (token
!= NUMBER
) {
1086 skip_token(&val
, NULL
, cfile
);
1087 parse_warn(cfile
, "numeric second expected.");
1090 skip_token(&val
, NULL
, cfile
); /* consume second */
1094 token
= peek_token(&val
, NULL
, cfile
);
1095 if (token
== NUMBER
) {
1096 skip_token(&val
, NULL
, cfile
); /* consume tzoff */
1098 } else if (token
!= SEMI
) {
1099 skip_token(&val
, NULL
, cfile
);
1101 "Time zone offset or semicolon expected.");
1105 /* Guess the time value... */
1106 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
1107 (year
- 69) / 4 + /* Leap days since '70 */
1108 (mon
/* Days in months this year */
1111 (mon
> 1 && /* Leap day this year */
1112 !((year
- 72) & 3)) +
1113 mday
- 1) * 24) + /* Day of month */
1115 min
) * 60) + sec
+ tzoff
;
1117 /* This guess could be wrong because of leap seconds or other
1118 weirdness we don't know about that the system does. For
1119 now, we're just going to accept the guess, but at some point
1120 it might be nice to do a successive approximation here to
1121 get an exact value. Even if the error is small, if the
1122 server is restarted frequently (and thus the lease database
1123 is reread), the error could accumulate into something
1126 return((TIME
)guess
);
1130 * Wrapper to consume the semicolon after the date
1136 struct parse
*cfile
;
1139 guess
= parse_date_core(cfile
);
1141 /* Make sure the date ends in a semicolon... */
1142 if (!parse_semi(cfile
))
1150 * option-name :== IDENTIFIER |
1151 IDENTIFIER . IDENTIFIER
1155 parse_option_name (cfile
, allocate
, known
, opt
)
1156 struct parse
*cfile
;
1159 struct option
**opt
;
1162 enum dhcp_token token
;
1164 struct universe
*universe
;
1165 struct option
*option
;
1169 return DHCP_R_INVALIDARG
;
1171 token
= next_token (&val
, (unsigned *)0, cfile
);
1172 if (!is_identifier (token
)) {
1174 "expecting identifier after option keyword.");
1176 skip_to_semi (cfile
);
1177 return DHCP_R_BADPARSE
;
1179 uname
= dmalloc (strlen (val
) + 1, MDL
);
1181 log_fatal ("no memory for uname information.");
1182 strcpy (uname
, val
);
1183 token
= peek_token (&val
, (unsigned *)0, cfile
);
1185 /* Go ahead and take the DOT token... */
1186 skip_token(&val
, (unsigned *)0, cfile
);
1188 /* The next token should be an identifier... */
1189 token
= next_token (&val
, (unsigned *)0, cfile
);
1190 if (!is_identifier (token
)) {
1191 parse_warn (cfile
, "expecting identifier after '.'");
1193 skip_to_semi (cfile
);
1194 return DHCP_R_BADPARSE
;
1197 /* Look up the option name hash table for the specified
1199 universe
= (struct universe
*)0;
1200 if (!universe_hash_lookup (&universe
, universe_hash
,
1202 parse_warn (cfile
, "no option space named %s.", uname
);
1203 skip_to_semi (cfile
);
1204 return ISC_R_NOTFOUND
;
1207 /* Use the default hash table, which contains all the
1208 standard dhcp option names. */
1210 universe
= &dhcp_universe
;
1213 /* Look up the actual option info... */
1214 option_name_hash_lookup(opt
, universe
->name_hash
, val
, 0, MDL
);
1217 /* If we didn't get an option structure, it's an undefined option. */
1221 /* If the option name is of the form unknown-[decimal], use
1222 * the trailing decimal value to find the option definition.
1223 * If there is no definition, construct one. This is to
1224 * support legacy use of unknown options in config files or
1227 } else if (strncasecmp(val
, "unknown-", 8) == 0) {
1230 /* Option code 0 is always illegal for us, thanks
1231 * to the option decoder.
1233 if (code
== 0 || code
== universe
->end
) {
1234 parse_warn(cfile
, "Option codes 0 and %u are illegal "
1235 "in the %s space.", universe
->end
,
1237 skip_to_semi(cfile
);
1239 return ISC_R_FAILURE
;
1242 /* It's odd to think of unknown option codes as
1243 * being known, but this means we know what the
1244 * parsed name is talking about.
1249 option_code_hash_lookup(opt
, universe
->code_hash
,
1253 /* If we did not find an option of that code,
1254 * manufacture an unknown-xxx option definition.
1255 * Its single reference will ensure that it is
1256 * deleted once the option is recycled out of
1257 * existence (by the parent).
1259 if (option
== NULL
) {
1260 option
= new_option(val
, MDL
);
1261 option
->universe
= universe
;
1262 option
->code
= code
;
1263 option
->format
= default_option_format
;
1264 option_reference(opt
, option
, MDL
);
1266 log_info("option %s has been redefined as option %s. "
1267 "Please update your configs if neccessary.",
1269 /* If we've been told to allocate, that means that this
1270 * (might) be an option code definition, so we'll create
1271 * an option structure and return it for the parent to
1274 } else if (allocate
) {
1275 option
= new_option(val
, MDL
);
1276 option
-> universe
= universe
;
1277 option_reference(opt
, option
, MDL
);
1279 parse_warn(cfile
, "no option named %s in space %s",
1280 val
, universe
->name
);
1281 skip_to_semi (cfile
);
1283 return ISC_R_NOTFOUND
;
1286 /* Free the initial identifier token. */
1288 return ISC_R_SUCCESS
;
1291 /* IDENTIFIER [WIDTHS] SEMI
1292 * WIDTHS ~= LENGTH WIDTH NUMBER
1296 void parse_option_space_decl (cfile
)
1297 struct parse
*cfile
;
1301 struct universe
**ua
, *nu
;
1303 int tsize
=1, lsize
=1, hsize
= 0;
1305 skip_token(&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
1306 which was checked by the
1308 token
= next_token (&val
, (unsigned *)0, cfile
);
1309 if (!is_identifier (token
)) {
1310 parse_warn (cfile
, "expecting identifier.");
1311 skip_to_semi (cfile
);
1314 nu
= new_universe (MDL
);
1316 log_fatal ("No memory for new option space.");
1318 /* Set up the server option universe... */
1319 nu_name
= dmalloc (strlen (val
) + 1, MDL
);
1321 log_fatal ("No memory for new option space name.");
1322 strcpy (nu_name
, val
);
1323 nu
-> name
= nu_name
;
1326 token
= next_token(&val
, NULL
, cfile
);
1332 token
= next_token(&val
, NULL
, cfile
);
1333 if (token
!= WIDTH
) {
1334 parse_warn(cfile
, "expecting width token.");
1338 token
= next_token(&val
, NULL
, cfile
);
1339 if (token
!= NUMBER
) {
1340 parse_warn(cfile
, "expecting number 1, 2, 4.");
1350 hsize
= BYTE_NAME_HASH_SIZE
;
1354 hsize
= WORD_NAME_HASH_SIZE
;
1358 hsize
= QUAD_NAME_HASH_SIZE
;
1361 parse_warn(cfile
, "invalid code width (%d), "
1362 "expecting a 1, 2 or 4.",
1369 token
= next_token(&val
, NULL
, cfile
);
1370 if (token
!= WIDTH
) {
1371 parse_warn(cfile
, "expecting width token.");
1375 token
= next_token(&val
, NULL
, cfile
);
1376 if (token
!= NUMBER
) {
1377 parse_warn(cfile
, "expecting number 1 or 2.");
1382 if (lsize
!= 1 && lsize
!= 2) {
1383 parse_warn(cfile
, "invalid length width (%d) "
1384 "expecting 1 or 2.", lsize
);
1391 token
= next_token(&val
, NULL
, cfile
);
1392 if (token
!= SIZE
) {
1393 parse_warn(cfile
, "expecting size token.");
1397 token
= next_token(&val
, NULL
, cfile
);
1398 if (token
!= NUMBER
) {
1399 parse_warn(cfile
, "expecting a 10base number");
1403 /* (2^31)-1 is the highest Mersenne prime we should
1407 if (hsize
< 0 || hsize
> 0x7FFFFFFF) {
1408 parse_warn(cfile
, "invalid hash length: %d",
1416 parse_warn(cfile
, "Unexpected token.");
1418 } while (token
!= SEMI
);
1421 hsize
= DEFAULT_SPACE_HASH_SIZE
;
1423 nu
-> lookup_func
= lookup_hashed_option
;
1424 nu
-> option_state_dereference
= hashed_option_state_dereference
;
1425 nu
-> foreach
= hashed_option_space_foreach
;
1426 nu
-> save_func
= save_hashed_option
;
1427 nu
-> delete_func
= delete_hashed_option
;
1428 nu
-> encapsulate
= hashed_option_space_encapsulate
;
1429 nu
-> decode
= parse_option_buffer
;
1430 nu
-> length_size
= lsize
;
1431 nu
-> tag_size
= tsize
;
1434 nu
->get_tag
= getUChar
;
1435 nu
->store_tag
= putUChar
;
1438 nu
->get_tag
= getUShort
;
1439 nu
->store_tag
= putUShort
;
1442 nu
->get_tag
= getULong
;
1443 nu
->store_tag
= putULong
;
1446 log_fatal("Impossible condition at %s:%d.", MDL
);
1450 nu
->get_length
= NULL
;
1451 nu
->store_length
= NULL
;
1454 nu
->get_length
= getUChar
;
1455 nu
->store_length
= putUChar
;
1458 nu
->get_length
= getUShort
;
1459 nu
->store_length
= putUShort
;
1462 log_fatal("Impossible condition at %s:%d.", MDL
);
1464 nu
-> index
= universe_count
++;
1465 if (nu
-> index
>= universe_max
) {
1466 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
1468 log_fatal ("No memory to expand option space array.");
1469 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
1471 dfree (universes
, MDL
);
1474 universes
[nu
-> index
] = nu
;
1475 if (!option_name_new_hash(&nu
->name_hash
, hsize
, MDL
) ||
1476 !option_code_new_hash(&nu
->code_hash
, hsize
, MDL
))
1477 log_fatal("Can't allocate %s option hash table.", nu
->name
);
1478 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
1482 dfree(nu_name
, MDL
);
1486 /* This is faked up to look good right now. Ideally, this should do a
1487 recursive parse and allow arbitrary data structure definitions, but for
1488 now it just allows you to specify a single type, an array of single types,
1489 a sequence of types, or an array of sequences of types.
1491 ocd :== NUMBER EQUALS ocsd SEMI
1493 ocsd :== ocsd_type |
1494 ocsd_type_sequence |
1495 ARRAY OF ocsd_simple_type_sequence
1497 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
1499 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
1501 ocsd_types :== ocsd_type |
1502 ocsd_types ocsd_type
1504 ocsd_type :== ocsd_simple_type |
1505 ARRAY OF ocsd_simple_type
1507 ocsd_simple_types :== ocsd_simple_type |
1508 ocsd_simple_types ocsd_simple_type
1510 ocsd_simple_type :== BOOLEAN |
1512 SIGNED INTEGER NUMBER |
1513 UNSIGNED INTEGER NUMBER |
1517 ENCAPSULATE identifier */
1519 int parse_option_code_definition (cfile
, option
)
1520 struct parse
*cfile
;
1521 struct option
*option
;
1524 enum dhcp_token token
;
1525 struct option
*oldopt
;
1526 unsigned arrayp
= 0;
1528 int no_more_in_record
= 0;
1534 int has_encapsulation
= 0;
1535 struct universe
*encapsulated
;
1537 /* Parse the option code. */
1538 token
= next_token (&val
, (unsigned *)0, cfile
);
1539 if (token
!= NUMBER
) {
1540 parse_warn (cfile
, "expecting option code number.");
1541 skip_to_semi (cfile
);
1544 option
-> code
= atoi (val
);
1546 token
= next_token (&val
, (unsigned *)0, cfile
);
1547 if (token
!= EQUAL
) {
1548 parse_warn (cfile
, "expecting \"=\"");
1549 skip_to_semi (cfile
);
1553 /* See if this is an array. */
1554 token
= next_token (&val
, (unsigned *)0, cfile
);
1555 if (token
== ARRAY
) {
1556 token
= next_token (&val
, (unsigned *)0, cfile
);
1558 parse_warn (cfile
, "expecting \"of\".");
1559 skip_to_semi (cfile
);
1563 token
= next_token (&val
, (unsigned *)0, cfile
);
1566 if (token
== LBRACE
) {
1568 token
= next_token (&val
, (unsigned *)0, cfile
);
1571 /* At this point we're expecting a data type. */
1573 if (has_encapsulation
) {
1575 "encapsulate must always be the last item.");
1576 skip_to_semi (cfile
);
1583 parse_warn (cfile
, "no nested arrays.");
1584 skip_to_rbrace (cfile
, recordp
);
1586 skip_to_semi (cfile
);
1589 token
= next_token (&val
, (unsigned *)0, cfile
);
1591 parse_warn (cfile
, "expecting \"of\".");
1592 skip_to_semi (cfile
);
1595 arrayp
= recordp
+ 1;
1596 token
= next_token (&val
, (unsigned *)0, cfile
);
1597 if ((recordp
) && (token
== LBRACE
)) {
1599 "only uniform array inside record.");
1600 skip_to_rbrace (cfile
, recordp
+ 1);
1601 skip_to_semi (cfile
);
1611 token
= next_token (&val
, (unsigned *)0, cfile
);
1612 if (token
!= NUMBER
) {
1613 parse_warn (cfile
, "expecting number.");
1614 skip_to_rbrace (cfile
, recordp
);
1616 skip_to_semi (cfile
);
1619 switch (atoi (val
)) {
1621 type
= is_signed
? 'b' : 'B';
1624 type
= is_signed
? 's' : 'S';
1627 type
= is_signed
? 'l' : 'L';
1631 "%s bit precision is not supported.", val
);
1632 skip_to_rbrace (cfile
, recordp
);
1634 skip_to_semi (cfile
);
1641 token
= next_token (&val
, (unsigned *)0, cfile
);
1642 if (token
!= INTEGER
) {
1643 parse_warn (cfile
, "expecting \"integer\" keyword.");
1644 skip_to_rbrace (cfile
, recordp
);
1646 skip_to_semi (cfile
);
1664 /* Consume optional compression indicator. */
1665 token
= peek_token(&val
, NULL
, cfile
);
1666 if (token
== COMPRESSED
) {
1667 skip_token(&val
, NULL
, cfile
);
1668 tokbuf
[tokix
++] = 'D';
1677 parse_warn (cfile
, "arrays of text strings not %s",
1679 skip_to_rbrace (cfile
, recordp
);
1681 skip_to_semi (cfile
);
1684 no_more_in_record
= 1;
1691 token
= next_token (&val
, (unsigned *)0, cfile
);
1692 if (!is_identifier (token
)) {
1694 "expecting option space identifier");
1695 skip_to_semi (cfile
);
1698 encapsulated
= NULL
;
1699 if (!universe_hash_lookup(&encapsulated
, universe_hash
,
1700 val
, strlen(val
), MDL
)) {
1701 parse_warn(cfile
, "unknown option space %s", val
);
1702 skip_to_semi (cfile
);
1705 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1707 tokbuf
[tokix
++] = 'E';
1708 strcpy (&tokbuf
[tokix
], val
);
1709 tokix
+= strlen (val
);
1711 has_encapsulation
= 1;
1717 parse_warn (cfile
, "array incompatible with zerolen.");
1718 skip_to_rbrace (cfile
, recordp
);
1720 skip_to_semi (cfile
);
1723 no_more_in_record
= 1;
1727 parse_warn (cfile
, "unknown data type %s", val
);
1728 skip_to_rbrace (cfile
, recordp
);
1730 skip_to_semi (cfile
);
1734 if (tokix
== sizeof tokbuf
) {
1736 parse_warn (cfile
, "too many types in record.");
1737 skip_to_rbrace (cfile
, recordp
);
1739 skip_to_semi (cfile
);
1742 tokbuf
[tokix
++] = type
;
1745 token
= next_token (&val
, (unsigned *)0, cfile
);
1746 if (arrayp
> recordp
) {
1747 if (tokix
== sizeof tokbuf
) {
1749 "too many types in record.");
1750 skip_to_rbrace (cfile
, 1);
1751 skip_to_semi (cfile
);
1755 tokbuf
[tokix
++] = 'a';
1757 if (token
== COMMA
) {
1758 if (no_more_in_record
) {
1760 "%s must be at end of record.",
1761 type
== 't' ? "text" : "string");
1762 skip_to_rbrace (cfile
, 1);
1764 skip_to_semi (cfile
);
1767 token
= next_token (&val
, (unsigned *)0, cfile
);
1770 if (token
!= RBRACE
) {
1771 parse_warn (cfile
, "expecting right brace.");
1772 skip_to_rbrace (cfile
, 1);
1774 skip_to_semi (cfile
);
1778 if (!parse_semi (cfile
)) {
1779 parse_warn (cfile
, "semicolon expected.");
1780 skip_to_semi (cfile
);
1782 skip_to_semi (cfile
);
1785 if (has_encapsulation
&& arrayp
) {
1787 "Arrays of encapsulations don't make sense.");
1790 s
= dmalloc(tokix
+ (arrayp
? 1 : 0) + 1, MDL
);
1792 log_fatal("no memory for option format.");
1794 memcpy(s
, tokbuf
, tokix
);
1796 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1800 option
-> format
= s
;
1803 option_code_hash_lookup(&oldopt
, option
->universe
->code_hash
,
1804 &option
->code
, 0, MDL
);
1805 if (oldopt
!= NULL
) {
1807 * XXX: This illegalizes a configuration syntax that was
1808 * valid in 3.0.x, where multiple name->code mappings are
1809 * given, but only one code->name mapping survives. It is
1810 * unclear what can or should be done at this point, but it
1811 * seems best to retain 3.0.x behaviour for upgrades to go
1814 option_name_hash_delete(option->universe->name_hash,
1815 oldopt->name, 0, MDL);
1817 option_code_hash_delete(option
->universe
->code_hash
,
1818 &oldopt
->code
, 0, MDL
);
1820 option_dereference(&oldopt
, MDL
);
1822 option_code_hash_add(option
->universe
->code_hash
, &option
->code
, 0,
1824 option_name_hash_add(option
->universe
->name_hash
, option
->name
, 0,
1826 if (has_encapsulation
) {
1827 /* INSIST(tokbuf[0] == 'E'); */
1828 /* INSIST(encapsulated != NULL); */
1829 if (!option_code_hash_lookup(&encapsulated
->enc_opt
,
1830 option
->universe
->code_hash
,
1831 &option
->code
, 0, MDL
)) {
1832 log_fatal("error finding encapsulated option (%s:%d)",
1840 * base64 :== NUMBER_OR_STRING
1843 int parse_base64 (data
, cfile
)
1844 struct data_string
*data
;
1845 struct parse
*cfile
;
1850 static unsigned char
1851 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1852 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1853 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1854 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1855 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1856 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1857 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1858 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1859 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1860 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1861 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1862 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1863 struct string_list
*bufs
= NULL
,
1870 /* It's possible for a + or a / to cause a base64 quantity to be
1871 tokenized into more than one token, so we have to parse them all
1872 in before decoding. */
1876 (void)next_token(&val
, &l
, cfile
);
1877 t
= dmalloc(l
+ sizeof(*t
), MDL
);
1879 log_fatal("no memory for base64 buffer.");
1880 memset(t
, 0, (sizeof(*t
)) - 1);
1881 memcpy(t
->string
, val
, l
+ 1);
1888 (void)peek_token(&val
, NULL
, cfile
);
1890 for (i
= 0; val
[i
]; i
++) {
1891 /* Check to see if the character is valid. It
1892 may be out of range or within the right range
1893 but not used in the mapping */
1894 if (((val
[i
] < ' ') || (val
[i
] > 'z')) ||
1895 ((from64
[val
[i
] - ' '] > 63) && (val
[i
] != '='))) {
1897 break; /* no need to continue for loop */
1900 } while (valid_base64
);
1903 data
->len
= (data
->len
* 3) / 4;
1904 if (!buffer_allocate(&data
->buffer
, data
->len
, MDL
)) {
1905 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1912 for (t
= bufs
; t
; t
= t
->next
) {
1913 for (i
= 0; t
->string
[i
]; i
++) {
1914 unsigned foo
= t
->string
[i
];
1915 if (terminated
&& foo
!= '=') {
1917 "stuff after base64 '=' terminator: %s.",
1921 if ((foo
< ' ') || (foo
> 'z')) {
1924 "invalid base64 character %d.",
1927 data_string_forget(data
, MDL
);
1933 foo
= from64
[foo
- ' '];
1936 acc
= (acc
<< 6) + foo
;
1941 data
->buffer
->data
[j
++] = (acc
>> 4);
1946 data
->buffer
->data
[j
++] = (acc
>> 2);
1950 data
->buffer
->data
[j
++] = acc
;
1961 "partial base64 value left over: %d.",
1966 data
->data
= data
->buffer
->data
;
1968 for (t
= bufs
; t
; t
= last
) {
1980 * colon-separated-hex-list :== NUMBER |
1981 * NUMBER COLON colon-separated-hex-list
1984 int parse_cshl (data
, cfile
)
1985 struct data_string
*data
;
1986 struct parse
*cfile
;
1988 u_int8_t ibuf
[128];
1991 struct option_tag
*sl
= (struct option_tag
*)0;
1992 struct option_tag
*next
, **last
= &sl
;
1993 enum dhcp_token token
;
1998 token
= next_token (&val
, (unsigned *)0, cfile
);
1999 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
2000 parse_warn (cfile
, "expecting hexadecimal number.");
2001 skip_to_semi (cfile
);
2002 for (; sl
; sl
= next
) {
2008 if (ilen
== sizeof ibuf
) {
2009 next
= (struct option_tag
*)
2011 sizeof (struct option_tag
), MDL
);
2013 log_fatal ("no memory for string list.");
2014 memcpy (next
-> data
, ibuf
, ilen
);
2016 last
= &next
-> next
;
2020 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
2022 token
= peek_token (&val
, (unsigned *)0, cfile
);
2025 skip_token(&val
, (unsigned *)0, cfile
);
2028 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
2029 log_fatal ("no memory to store octet data.");
2030 data
-> data
= &data
-> buffer
-> data
[0];
2031 data
-> len
= tlen
+ ilen
;
2032 data
-> terminated
= 0;
2034 rvp
= &data
-> buffer
-> data
[0];
2037 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
2043 memcpy (rvp
, ibuf
, ilen
);
2048 * executable-statements :== executable-statement executable-statements |
2049 * executable-statement
2051 * executable-statement :==
2053 * ADD class-name SEMI |
2055 * OPTION option-parameter SEMI |
2056 * SUPERSEDE option-parameter SEMI |
2057 * PREPEND option-parameter SEMI |
2058 * APPEND option-parameter SEMI
2061 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
2062 struct executable_statement
**statements
;
2063 struct parse
*cfile
;
2065 enum expression_context case_context
;
2067 struct executable_statement
**next
;
2070 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
2071 next
= &((*next
) -> next
);
2077 int parse_executable_statement (result
, cfile
, lose
, case_context
)
2078 struct executable_statement
**result
;
2079 struct parse
*cfile
;
2081 enum expression_context case_context
;
2083 #if defined(ENABLE_EXECUTE)
2085 struct expression
**ep
;
2087 enum dhcp_token token
;
2090 struct option
*option
=NULL
;
2091 struct option_cache
*cache
;
2095 struct dns_zone
*zone
;
2096 isc_result_t status
;
2099 token
= peek_token (&val
, (unsigned *)0, cfile
);
2101 case DB_TIME_FORMAT
:
2102 skip_token(&val
, NULL
, cfile
);
2103 token
= next_token(&val
, NULL
, cfile
);
2104 if (token
== DEFAULT
) {
2105 db_time_format
= DEFAULT_TIME_FORMAT
;
2106 } else if (token
== LOCAL
) {
2107 db_time_format
= LOCAL_TIME_FORMAT
;
2109 parse_warn(cfile
, "Expecting 'local' or 'default'.");
2111 skip_to_semi(cfile
);
2116 token
= next_token(&val
, NULL
, cfile
);
2117 if (token
!= SEMI
) {
2118 parse_warn(cfile
, "Expecting a semicolon.");
2123 /* We're done here. */
2127 skip_token(&val
, (unsigned *)0, cfile
);
2128 return parse_if_statement (result
, cfile
, lose
);
2131 skip_token(&val
, (unsigned *)0, cfile
);
2132 token
= next_token (&val
, (unsigned *)0, cfile
);
2133 if (token
!= STRING
) {
2134 parse_warn (cfile
, "expecting class name.");
2135 skip_to_semi (cfile
);
2139 cta
= (struct class *)0;
2140 status
= find_class (&cta
, val
, MDL
);
2141 if (status
!= ISC_R_SUCCESS
) {
2142 parse_warn (cfile
, "class %s: %s",
2143 val
, isc_result_totext (status
));
2144 skip_to_semi (cfile
);
2148 if (!parse_semi (cfile
)) {
2152 if (!executable_statement_allocate (result
, MDL
))
2153 log_fatal ("no memory for new statement.");
2154 (*result
) -> op
= add_statement
;
2155 (*result
) -> data
.add
= cta
;
2159 skip_token(&val
, (unsigned *)0, cfile
);
2160 if (!parse_semi (cfile
)) {
2164 if (!executable_statement_allocate (result
, MDL
))
2165 log_fatal ("no memory for new statement.");
2166 (*result
) -> op
= break_statement
;
2170 skip_token(&val
, (unsigned *)0, cfile
);
2172 status
= parse_option_name (cfile
, 0, &known
, &option
);
2173 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2177 status
= parse_option_statement(result
, cfile
, 1, option
,
2178 send_option_statement
);
2179 option_dereference(&option
, MDL
);
2184 skip_token(&val
, (unsigned *)0, cfile
);
2186 status
= parse_option_name (cfile
, 0, &known
, &option
);
2187 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2191 status
= parse_option_statement(result
, cfile
, 1, option
,
2192 supersede_option_statement
);
2193 option_dereference(&option
, MDL
);
2205 skip_token(&val
, (unsigned *)0, cfile
);
2206 cache
= (struct option_cache
*)0;
2207 if (!parse_allow_deny (&cache
, cfile
, flag
))
2209 if (!executable_statement_allocate (result
, MDL
))
2210 log_fatal ("no memory for new statement.");
2211 (*result
) -> op
= supersede_option_statement
;
2212 (*result
) -> data
.option
= cache
;
2216 skip_token(&val
, (unsigned *)0, cfile
);
2217 token
= peek_token (&val
, (unsigned *)0, cfile
);
2219 goto switch_default
;
2221 status
= parse_option_name (cfile
, 0, &known
, &option
);
2222 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2226 status
= parse_option_statement(result
, cfile
, 1, option
,
2227 default_option_statement
);
2228 option_dereference(&option
, MDL
);
2232 skip_token(&val
, (unsigned *)0, cfile
);
2234 status
= parse_option_name (cfile
, 0, &known
, &option
);
2235 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2239 status
= parse_option_statement(result
, cfile
, 1, option
,
2240 prepend_option_statement
);
2241 option_dereference(&option
, MDL
);
2245 skip_token(&val
, (unsigned *)0, cfile
);
2247 status
= parse_option_name (cfile
, 0, &known
, &option
);
2248 if (status
!= ISC_R_SUCCESS
|| option
== NULL
) {
2252 status
= parse_option_statement(result
, cfile
, 1, option
,
2253 append_option_statement
);
2254 option_dereference(&option
, MDL
);
2258 skip_token(&val
, (unsigned *)0, cfile
);
2259 return parse_on_statement (result
, cfile
, lose
);
2262 skip_token(&val
, (unsigned *)0, cfile
);
2263 return parse_switch_statement (result
, cfile
, lose
);
2266 skip_token(&val
, (unsigned *)0, cfile
);
2267 if (case_context
== context_any
) {
2269 "case statement in inappropriate scope.");
2271 skip_to_semi (cfile
);
2274 return parse_case_statement (result
,
2275 cfile
, lose
, case_context
);
2278 skip_token(&val
, (unsigned *)0, cfile
);
2279 if (case_context
== context_any
) {
2280 parse_warn (cfile
, "switch default statement in %s",
2281 "inappropriate scope.");
2286 if (!executable_statement_allocate (result
, MDL
))
2287 log_fatal ("no memory for default statement.");
2288 (*result
) -> op
= default_statement
;
2294 skip_token(&val
, (unsigned *)0, cfile
);
2295 if (token
== DEFINE
)
2300 token
= next_token (&val
, (unsigned *)0, cfile
);
2301 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2303 "%s can't be a variable name", val
);
2305 skip_to_semi (cfile
);
2310 if (!executable_statement_allocate (result
, MDL
))
2311 log_fatal ("no memory for set statement.");
2312 (*result
) -> op
= flag
? define_statement
: set_statement
;
2313 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
2314 if (!(*result
)->data
.set
.name
)
2315 log_fatal ("can't allocate variable name");
2316 strcpy ((*result
) -> data
.set
.name
, val
);
2317 token
= next_token (&val
, (unsigned *)0, cfile
);
2319 if (token
== LPAREN
) {
2320 struct string_list
*head
, *cur
, *new;
2321 struct expression
*expr
;
2322 head
= cur
= (struct string_list
*)0;
2324 token
= next_token (&val
,
2325 (unsigned *)0, cfile
);
2326 if (token
== RPAREN
)
2328 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2330 "expecting argument name");
2331 skip_to_rbrace (cfile
, 0);
2333 executable_statement_dereference
2337 new = ((struct string_list
*)
2338 dmalloc (sizeof (struct string_list
) +
2339 strlen (val
), MDL
));
2341 log_fatal ("can't allocate string.");
2342 memset (new, 0, sizeof *new);
2343 strcpy (new -> string
, val
);
2350 token
= next_token (&val
,
2351 (unsigned *)0, cfile
);
2352 } while (token
== COMMA
);
2354 if (token
!= RPAREN
) {
2355 parse_warn (cfile
, "expecting right paren.");
2357 skip_to_semi (cfile
);
2359 executable_statement_dereference (result
, MDL
);
2363 token
= next_token (&val
, (unsigned *)0, cfile
);
2364 if (token
!= LBRACE
) {
2365 parse_warn (cfile
, "expecting left brace.");
2369 expr
= (struct expression
*)0;
2370 if (!(expression_allocate (&expr
, MDL
)))
2371 log_fatal ("can't allocate expression.");
2372 expr
-> op
= expr_function
;
2373 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
2374 log_fatal ("can't allocate fundef.");
2375 expr
-> data
.func
-> args
= head
;
2376 (*result
) -> data
.set
.expr
= expr
;
2378 if (!(parse_executable_statements
2379 (&expr
-> data
.func
-> statements
, cfile
, lose
,
2385 token
= next_token (&val
, (unsigned *)0, cfile
);
2386 if (token
!= RBRACE
) {
2387 parse_warn (cfile
, "expecting rigt brace.");
2391 if (token
!= EQUAL
) {
2393 "expecting '=' in %s statement.",
2394 flag
? "define" : "set");
2398 if (!parse_expression (&(*result
) -> data
.set
.expr
,
2399 cfile
, lose
, context_any
,
2400 (struct expression
**)0,
2404 "expecting expression.");
2407 skip_to_semi (cfile
);
2408 executable_statement_dereference (result
, MDL
);
2411 if (!parse_semi (cfile
)) {
2413 executable_statement_dereference (result
, MDL
);
2420 skip_token(&val
, (unsigned *)0, cfile
);
2421 token
= next_token (&val
, (unsigned *)0, cfile
);
2422 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2424 "%s can't be a variable name", val
);
2425 skip_to_semi (cfile
);
2430 if (!executable_statement_allocate (result
, MDL
))
2431 log_fatal ("no memory for set statement.");
2432 (*result
) -> op
= unset_statement
;
2433 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
2434 if (!(*result
)->data
.unset
)
2435 log_fatal ("can't allocate variable name");
2436 strcpy ((*result
) -> data
.unset
, val
);
2437 if (!parse_semi (cfile
)) {
2439 executable_statement_dereference (result
, MDL
);
2445 skip_token(&val
, (unsigned *)0, cfile
);
2446 if (!executable_statement_allocate (result
, MDL
))
2447 log_fatal ("no memory for eval statement.");
2448 (*result
) -> op
= eval_statement
;
2450 if (!parse_expression (&(*result
) -> data
.eval
,
2451 cfile
, lose
, context_data
, /* XXX */
2452 (struct expression
**)0, expr_none
)) {
2455 "expecting data expression.");
2458 skip_to_semi (cfile
);
2459 executable_statement_dereference (result
, MDL
);
2462 if (!parse_semi (cfile
)) {
2464 executable_statement_dereference (result
, MDL
);
2469 #ifdef ENABLE_EXECUTE
2470 skip_token(&val
, NULL
, cfile
);
2472 if (!executable_statement_allocate (result
, MDL
))
2473 log_fatal ("no memory for execute statement.");
2474 (*result
)->op
= execute_statement
;
2476 token
= next_token(&val
, NULL
, cfile
);
2477 if (token
!= LPAREN
) {
2478 parse_warn(cfile
, "left parenthesis expected.");
2479 skip_to_semi(cfile
);
2484 token
= next_token(&val
, &len
, cfile
);
2485 if (token
!= STRING
) {
2486 parse_warn(cfile
, "Expecting a quoted string.");
2487 skip_to_semi(cfile
);
2492 (*result
)->data
.execute
.command
= dmalloc(len
+ 1, MDL
);
2493 if ((*result
)->data
.execute
.command
== NULL
)
2494 log_fatal("can't allocate command name");
2495 strcpy((*result
)->data
.execute
.command
, val
);
2497 ep
= &(*result
)->data
.execute
.arglist
;
2498 (*result
)->data
.execute
.argc
= 0;
2500 while((token
= next_token(&val
, NULL
, cfile
)) == COMMA
) {
2501 if (!expression_allocate(ep
, MDL
))
2502 log_fatal ("can't allocate expression");
2504 if (!parse_data_expression (&(*ep
) -> data
.arg
.val
,
2508 "expecting expression.");
2511 skip_to_semi(cfile
);
2515 ep
= &(*ep
)->data
.arg
.next
;
2516 (*result
)->data
.execute
.argc
++;
2519 if (token
!= RPAREN
) {
2520 parse_warn(cfile
, "right parenthesis expected.");
2521 skip_to_semi(cfile
);
2526 if (!parse_semi (cfile
)) {
2528 executable_statement_dereference (result
, MDL
);
2530 #else /* ! ENABLE_EXECUTE */
2531 parse_warn(cfile
, "define ENABLE_EXECUTE in site.h to "
2532 "enable execute(); expressions.");
2533 skip_to_semi(cfile
);
2536 #endif /* ENABLE_EXECUTE */
2540 skip_token(&val
, (unsigned *)0, cfile
);
2542 if (!executable_statement_allocate (result
, MDL
))
2543 log_fatal ("no memory for return statement.");
2544 (*result
) -> op
= return_statement
;
2546 if (!parse_expression (&(*result
) -> data
.retval
,
2547 cfile
, lose
, context_data
,
2548 (struct expression
**)0, expr_none
)) {
2551 "expecting data expression.");
2554 skip_to_semi (cfile
);
2555 executable_statement_dereference (result
, MDL
);
2558 if (!parse_semi (cfile
)) {
2560 executable_statement_dereference (result
, MDL
);
2566 skip_token(&val
, (unsigned *)0, cfile
);
2568 if (!executable_statement_allocate (result
, MDL
))
2569 log_fatal ("no memory for log statement.");
2570 (*result
) -> op
= log_statement
;
2572 token
= next_token (&val
, (unsigned *)0, cfile
);
2573 if (token
!= LPAREN
) {
2574 parse_warn (cfile
, "left parenthesis expected.");
2575 skip_to_semi (cfile
);
2580 token
= peek_token (&val
, (unsigned *)0, cfile
);
2582 if (token
== FATAL
) {
2583 (*result
) -> data
.log
.priority
= log_priority_fatal
;
2584 } else if (token
== ERROR
) {
2585 (*result
) -> data
.log
.priority
= log_priority_error
;
2586 } else if (token
== TOKEN_DEBUG
) {
2587 (*result
) -> data
.log
.priority
= log_priority_debug
;
2588 } else if (token
== INFO
) {
2589 (*result
) -> data
.log
.priority
= log_priority_info
;
2591 (*result
) -> data
.log
.priority
= log_priority_debug
;
2595 skip_token(&val
, (unsigned *)0, cfile
);
2596 token
= next_token (&val
, (unsigned *)0, cfile
);
2597 if (token
!= COMMA
) {
2598 parse_warn (cfile
, "comma expected.");
2599 skip_to_semi (cfile
);
2605 if (!(parse_data_expression
2606 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
2607 skip_to_semi (cfile
);
2612 token
= next_token (&val
, (unsigned *)0, cfile
);
2613 if (token
!= RPAREN
) {
2614 parse_warn (cfile
, "right parenthesis expected.");
2615 skip_to_semi (cfile
);
2620 token
= next_token (&val
, (unsigned *)0, cfile
);
2621 if (token
!= SEMI
) {
2622 parse_warn (cfile
, "semicolon expected.");
2623 skip_to_semi (cfile
);
2629 /* Not really a statement, but we parse it here anyway
2630 because it's appropriate for all DHCP agents with
2633 skip_token(&val
, (unsigned *)0, cfile
);
2634 zone
= (struct dns_zone
*)0;
2635 if (!dns_zone_allocate (&zone
, MDL
))
2636 log_fatal ("no memory for new zone.");
2637 zone
-> name
= parse_host_name (cfile
);
2638 if (!zone
-> name
) {
2639 parse_warn (cfile
, "expecting hostname.");
2642 skip_to_semi (cfile
);
2643 dns_zone_dereference (&zone
, MDL
);
2646 i
= strlen (zone
-> name
);
2647 if (zone
-> name
[i
- 1] != '.') {
2648 s
= dmalloc ((unsigned)i
+ 2, MDL
);
2650 parse_warn (cfile
, "no trailing '.' on zone");
2653 strcpy (s
, zone
-> name
);
2656 dfree (zone
-> name
, MDL
);
2659 if (!parse_zone (zone
, cfile
))
2661 status
= enter_dns_zone (zone
);
2662 if (status
!= ISC_R_SUCCESS
) {
2663 parse_warn (cfile
, "dns zone key %s: %s",
2664 zone
-> name
, isc_result_totext (status
));
2665 dns_zone_dereference (&zone
, MDL
);
2668 dns_zone_dereference (&zone
, MDL
);
2671 /* Also not really a statement, but same idea as above. */
2673 skip_token(&val
, (unsigned *)0, cfile
);
2674 if (!parse_key (cfile
)) {
2681 if (config_universe
&& is_identifier (token
)) {
2682 option
= (struct option
*)0;
2683 option_name_hash_lookup(&option
,
2684 config_universe
->name_hash
,
2687 skip_token(&val
, (unsigned *)0, cfile
);
2688 status
= parse_option_statement
2689 (result
, cfile
, 1, option
,
2690 supersede_option_statement
);
2691 option_dereference(&option
, MDL
);
2696 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2697 /* This is rather ugly. Since function calls are
2698 data expressions, fake up an eval statement. */
2699 if (!executable_statement_allocate (result
, MDL
))
2700 log_fatal ("no memory for eval statement.");
2701 (*result
) -> op
= eval_statement
;
2703 if (!parse_expression (&(*result
) -> data
.eval
,
2704 cfile
, lose
, context_data
,
2705 (struct expression
**)0,
2708 parse_warn (cfile
, "expecting "
2712 skip_to_semi (cfile
);
2713 executable_statement_dereference (result
, MDL
);
2716 if (!parse_semi (cfile
)) {
2718 executable_statement_dereference (result
, MDL
);
2731 /* zone-statements :== zone-statement |
2732 zone-statement zone-statements
2734 PRIMARY ip-addresses SEMI |
2735 SECONDARY ip-addresses SEMI |
2736 PRIMARY6 ip-address6 SEMI |
2737 SECONDARY6 ip-address6 SEMI |
2739 ip-addresses :== ip-addr-or-hostname |
2740 ip-addr-or-hostname COMMA ip-addresses
2741 key-reference :== KEY STRING |
2744 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2749 struct option_cache
*oc
;
2752 token
= next_token (&val
, (unsigned *)0, cfile
);
2753 if (token
!= LBRACE
) {
2754 parse_warn (cfile
, "expecting left brace");
2759 token
= peek_token (&val
, (unsigned *)0, cfile
);
2762 if (zone
-> primary
) {
2764 "more than one primary.");
2765 skip_to_semi (cfile
);
2768 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2769 log_fatal ("can't allocate primary option cache.");
2770 oc
= zone
-> primary
;
2774 if (zone
-> secondary
) {
2775 parse_warn (cfile
, "more than one secondary.");
2776 skip_to_semi (cfile
);
2779 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2780 log_fatal ("can't allocate secondary.");
2781 oc
= zone
-> secondary
;
2783 skip_token(&val
, (unsigned *)0, cfile
);
2785 struct expression
*expr
= (struct expression
*)0;
2786 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2788 "expecting IP addr or hostname.");
2789 skip_to_semi (cfile
);
2792 if (oc
-> expression
) {
2793 struct expression
*old
=
2794 (struct expression
*)0;
2795 expression_reference (&old
,
2798 expression_dereference (&oc
-> expression
,
2800 if (!make_concat (&oc
-> expression
,
2802 log_fatal ("no memory for concat.");
2803 expression_dereference (&expr
, MDL
);
2804 expression_dereference (&old
, MDL
);
2806 expression_reference (&oc
-> expression
,
2808 expression_dereference (&expr
, MDL
);
2810 token
= next_token (&val
, (unsigned *)0, cfile
);
2811 } while (token
== COMMA
);
2812 if (token
!= SEMI
) {
2813 parse_warn (cfile
, "expecting semicolon.");
2814 skip_to_semi (cfile
);
2820 if (zone
->primary6
) {
2821 parse_warn(cfile
, "more than one primary6.");
2822 skip_to_semi(cfile
);
2825 if (!option_cache_allocate (&zone
->primary6
, MDL
))
2826 log_fatal("can't allocate primary6 option cache.");
2827 oc
= zone
->primary6
;
2831 if (zone
->secondary6
) {
2832 parse_warn(cfile
, "more than one secondary6.");
2833 skip_to_semi(cfile
);
2836 if (!option_cache_allocate (&zone
->secondary6
, MDL
))
2837 log_fatal("can't allocate secondary6 "
2839 oc
= zone
->secondary6
;
2841 skip_token(&val
, NULL
, cfile
);
2843 struct expression
*expr
= NULL
;
2844 if (parse_ip6_addr_expr(&expr
, cfile
) == 0) {
2845 parse_warn(cfile
, "expecting IPv6 addr.");
2846 skip_to_semi(cfile
);
2849 if (oc
->expression
) {
2850 struct expression
*old
= NULL
;
2851 expression_reference(&old
, oc
->expression
,
2853 expression_dereference(&oc
->expression
,
2855 if (!make_concat(&oc
->expression
,
2857 log_fatal("no memory for concat.");
2858 expression_dereference(&expr
, MDL
);
2859 expression_dereference(&old
, MDL
);
2861 expression_reference(&oc
->expression
,
2863 expression_dereference(&expr
, MDL
);
2865 token
= next_token(&val
, NULL
, cfile
);
2866 } while (token
== COMMA
);
2867 if (token
!= SEMI
) {
2868 parse_warn(cfile
, "expecting semicolon.");
2869 skip_to_semi(cfile
);
2875 skip_token(&val
, NULL
, cfile
);
2876 token
= peek_token(&val
, NULL
, cfile
);
2877 if (token
== STRING
) {
2878 skip_token(&val
, NULL
, cfile
);
2881 key_name
= parse_host_name(cfile
);
2883 parse_warn(cfile
, "expecting key name.");
2884 skip_to_semi(cfile
);
2890 log_fatal("Multiple key definitions for zone %s.",
2893 if (omapi_auth_key_lookup_name(&zone
->key
, val
) !=
2895 parse_warn(cfile
, "unknown key %s", val
);
2897 dfree(key_name
, MDL
);
2898 if (!parse_semi(cfile
))
2908 token
= next_token(&val
, NULL
, cfile
);
2909 if (token
!= RBRACE
) {
2910 parse_warn(cfile
, "expecting right brace.");
2916 /* key-statements :== key-statement |
2917 key-statement key-statements
2919 ALGORITHM host-name SEMI |
2920 secret-definition SEMI
2921 secret-definition :== SECRET base64val |
2924 int parse_key (struct parse
*cfile
)
2929 struct auth_key
*key
;
2930 struct data_string ds
;
2931 isc_result_t status
;
2934 key
= (struct auth_key
*)0;
2935 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2936 log_fatal ("no memory for key");
2938 token
= peek_token (&val
, (unsigned *)0, cfile
);
2939 if (token
== STRING
) {
2940 skip_token(&val
, (unsigned *)0, cfile
);
2941 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2943 log_fatal ("no memory for key name.");
2944 strcpy (key
-> name
, val
);
2947 key
-> name
= parse_host_name (cfile
);
2949 parse_warn (cfile
, "expecting key name.");
2950 skip_to_semi (cfile
);
2955 token
= next_token (&val
, (unsigned *)0, cfile
);
2956 if (token
!= LBRACE
) {
2957 parse_warn (cfile
, "expecting left brace");
2962 token
= next_token (&val
, (unsigned *)0, cfile
);
2965 if (key
-> algorithm
) {
2967 "key %s: too many algorithms",
2971 key
-> algorithm
= parse_host_name (cfile
);
2972 if (!key
-> algorithm
) {
2974 "expecting key algorithm name.");
2977 if (!parse_semi (cfile
))
2979 /* If the algorithm name isn't an FQDN, tack on
2980 the .SIG-ALG.REG.NET. domain. */
2981 s
= strrchr (key
-> algorithm
, '.');
2983 static char add
[] = ".SIG-ALG.REG.INT.";
2984 s
= dmalloc (strlen (key
-> algorithm
) +
2987 log_error ("no memory for key %s.",
2991 strcpy (s
, key
-> algorithm
);
2993 dfree (key
-> algorithm
, MDL
);
2994 key
-> algorithm
= s
;
2996 /* If there is no trailing '.', hack one in. */
2997 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2999 log_error ("no memory for key %s.",
3003 strcpy (s
, key
-> algorithm
);
3005 dfree (key
-> algorithm
, MDL
);
3006 key
-> algorithm
= s
;
3012 parse_warn (cfile
, "key %s: too many secrets",
3017 memset (&ds
, 0, sizeof(ds
));
3018 if (!parse_base64 (&ds
, cfile
))
3020 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
3022 if (status
!= ISC_R_SUCCESS
)
3024 memcpy (key
-> key
-> value
,
3025 ds
.buffer
-> data
, ds
.len
);
3026 data_string_forget (&ds
, MDL
);
3028 if (!parse_semi (cfile
))
3037 if (token
!= RBRACE
) {
3038 parse_warn (cfile
, "expecting right brace.");
3041 /* Allow the BIND 8 syntax, which has a semicolon after each
3043 token
= peek_token (&val
, (unsigned *)0, cfile
);
3044 if (token
== SEMI
) {
3045 skip_token(&val
, (unsigned *)0, cfile
);
3048 /* Remember the key. */
3049 status
= omapi_auth_key_enter (key
);
3050 if (status
!= ISC_R_SUCCESS
) {
3051 parse_warn (cfile
, "tsig key %s: %s",
3052 key
-> name
, isc_result_totext (status
));
3055 omapi_auth_key_dereference (&key
, MDL
);
3059 skip_to_rbrace (cfile
, 1);
3061 omapi_auth_key_dereference (&key
, MDL
);
3066 * on-statement :== event-types LBRACE executable-statements RBRACE
3067 * event-types :== event-type OR event-types |
3069 * event-type :== EXPIRY | COMMIT | RELEASE
3072 int parse_on_statement (result
, cfile
, lose
)
3073 struct executable_statement
**result
;
3074 struct parse
*cfile
;
3077 enum dhcp_token token
;
3080 if (!executable_statement_allocate (result
, MDL
))
3081 log_fatal ("no memory for new statement.");
3082 (*result
) -> op
= on_statement
;
3085 token
= next_token (&val
, (unsigned *)0, cfile
);
3088 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
3092 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
3096 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
3100 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
3104 parse_warn (cfile
, "expecting a lease event type");
3105 skip_to_semi (cfile
);
3107 executable_statement_dereference (result
, MDL
);
3110 token
= next_token (&val
, (unsigned *)0, cfile
);
3111 } while (token
== OR
);
3113 /* Semicolon means no statements. */
3117 if (token
!= LBRACE
) {
3118 parse_warn (cfile
, "left brace expected.");
3119 skip_to_semi (cfile
);
3121 executable_statement_dereference (result
, MDL
);
3124 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
3125 cfile
, lose
, context_any
)) {
3127 /* Try to even things up. */
3129 token
= next_token (&val
,
3130 (unsigned *)0, cfile
);
3131 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3132 executable_statement_dereference (result
, MDL
);
3136 token
= next_token (&val
, (unsigned *)0, cfile
);
3137 if (token
!= RBRACE
) {
3138 parse_warn (cfile
, "right brace expected.");
3139 skip_to_semi (cfile
);
3141 executable_statement_dereference (result
, MDL
);
3148 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
3152 int parse_switch_statement (result
, cfile
, lose
)
3153 struct executable_statement
**result
;
3154 struct parse
*cfile
;
3157 enum dhcp_token token
;
3160 if (!executable_statement_allocate (result
, MDL
))
3161 log_fatal ("no memory for new statement.");
3162 (*result
) -> op
= switch_statement
;
3164 token
= next_token (&val
, (unsigned *)0, cfile
);
3165 if (token
!= LPAREN
) {
3166 parse_warn (cfile
, "expecting left brace.");
3169 skip_to_semi (cfile
);
3171 executable_statement_dereference (result
, MDL
);
3175 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
3176 cfile
, lose
, context_data_or_numeric
,
3177 (struct expression
**)0, expr_none
)) {
3180 "expecting data or numeric expression.");
3186 token
= next_token (&val
, (unsigned *)0, cfile
);
3187 if (token
!= RPAREN
) {
3188 parse_warn (cfile
, "right paren expected.");
3192 token
= next_token (&val
, (unsigned *)0, cfile
);
3193 if (token
!= LBRACE
) {
3194 parse_warn (cfile
, "left brace expected.");
3197 if (!(parse_executable_statements
3198 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
3199 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
3200 ? context_data
: context_numeric
)))) {
3202 skip_to_rbrace (cfile
, 1);
3203 executable_statement_dereference (result
, MDL
);
3207 token
= next_token (&val
, (unsigned *)0, cfile
);
3208 if (token
!= RBRACE
) {
3209 parse_warn (cfile
, "right brace expected.");
3216 * case-statement :== CASE expr COLON
3220 int parse_case_statement (result
, cfile
, lose
, case_context
)
3221 struct executable_statement
**result
;
3222 struct parse
*cfile
;
3224 enum expression_context case_context
;
3226 enum dhcp_token token
;
3229 if (!executable_statement_allocate (result
, MDL
))
3230 log_fatal ("no memory for new statement.");
3231 (*result
) -> op
= case_statement
;
3233 if (!parse_expression (&(*result
) -> data
.c_case
,
3234 cfile
, lose
, case_context
,
3235 (struct expression
**)0, expr_none
))
3238 parse_warn (cfile
, "expecting %s expression.",
3239 (case_context
== context_data
3240 ? "data" : "numeric"));
3244 skip_to_semi (cfile
);
3245 executable_statement_dereference (result
, MDL
);
3249 token
= next_token (&val
, (unsigned *)0, cfile
);
3250 if (token
!= COLON
) {
3251 parse_warn (cfile
, "colon expected.");
3258 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
3261 * else-statement :== <null> |
3262 * ELSE LBRACE executable-statements RBRACE |
3263 * ELSE IF if-statement |
3264 * ELSIF if-statement
3267 int parse_if_statement (result
, cfile
, lose
)
3268 struct executable_statement
**result
;
3269 struct parse
*cfile
;
3272 enum dhcp_token token
;
3276 if (!executable_statement_allocate (result
, MDL
))
3277 log_fatal ("no memory for if statement.");
3279 (*result
) -> op
= if_statement
;
3281 token
= peek_token (&val
, (unsigned *)0, cfile
);
3282 if (token
== LPAREN
) {
3284 skip_token(&val
, (unsigned *)0, cfile
);
3289 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
3292 parse_warn (cfile
, "boolean expression expected.");
3293 executable_statement_dereference (result
, MDL
);
3297 #if defined (DEBUG_EXPRESSION_PARSE)
3298 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
3301 token
= next_token (&val
, (unsigned *)0, cfile
);
3302 if (token
!= RPAREN
) {
3303 parse_warn (cfile
, "expecting right paren.");
3305 executable_statement_dereference (result
, MDL
);
3309 token
= next_token (&val
, (unsigned *)0, cfile
);
3310 if (token
!= LBRACE
) {
3311 parse_warn (cfile
, "left brace expected.");
3312 skip_to_semi (cfile
);
3314 executable_statement_dereference (result
, MDL
);
3317 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
3318 cfile
, lose
, context_any
)) {
3320 /* Try to even things up. */
3322 token
= next_token (&val
,
3323 (unsigned *)0, cfile
);
3324 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
3325 executable_statement_dereference (result
, MDL
);
3329 token
= next_token (&val
, (unsigned *)0, cfile
);
3330 if (token
!= RBRACE
) {
3331 parse_warn (cfile
, "right brace expected.");
3332 skip_to_semi (cfile
);
3334 executable_statement_dereference (result
, MDL
);
3337 token
= peek_token (&val
, (unsigned *)0, cfile
);
3338 if (token
== ELSE
) {
3339 skip_token(&val
, (unsigned *)0, cfile
);
3340 token
= peek_token (&val
, (unsigned *)0, cfile
);
3342 skip_token(&val
, (unsigned *)0, cfile
);
3343 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3347 "expecting if statement");
3348 executable_statement_dereference (result
, MDL
);
3352 } else if (token
!= LBRACE
) {
3353 parse_warn (cfile
, "left brace or if expected.");
3354 skip_to_semi (cfile
);
3356 executable_statement_dereference (result
, MDL
);
3359 skip_token(&val
, (unsigned *)0, cfile
);
3360 if (!(parse_executable_statements
3361 (&(*result
) -> data
.ie
.fc
,
3362 cfile
, lose
, context_any
))) {
3363 executable_statement_dereference (result
, MDL
);
3366 token
= next_token (&val
, (unsigned *)0, cfile
);
3367 if (token
!= RBRACE
) {
3368 parse_warn (cfile
, "right brace expected.");
3369 skip_to_semi (cfile
);
3371 executable_statement_dereference (result
, MDL
);
3375 } else if (token
== ELSIF
) {
3376 skip_token(&val
, (unsigned *)0, cfile
);
3377 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
3381 "expecting conditional.");
3382 executable_statement_dereference (result
, MDL
);
3387 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
3393 * boolean_expression :== CHECK STRING |
3394 * NOT boolean-expression |
3395 * data-expression EQUAL data-expression |
3396 * data-expression BANG EQUAL data-expression |
3397 * data-expression REGEX_MATCH data-expression |
3398 * boolean-expression AND boolean-expression |
3399 * boolean-expression OR boolean-expression
3400 * EXISTS OPTION-NAME
3403 int parse_boolean_expression (expr
, cfile
, lose
)
3404 struct expression
**expr
;
3405 struct parse
*cfile
;
3408 /* Parse an expression... */
3409 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
3410 (struct expression
**)0, expr_none
))
3413 if (!is_boolean_expression (*expr
) &&
3414 (*expr
) -> op
!= expr_variable_reference
&&
3415 (*expr
) -> op
!= expr_funcall
) {
3416 parse_warn (cfile
, "Expecting a boolean expression.");
3418 expression_dereference (expr
, MDL
);
3424 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
3426 int parse_boolean (cfile
)
3427 struct parse
*cfile
;
3432 (void)next_token(&val
, NULL
, cfile
);
3433 if (!strcasecmp (val
, "true")
3434 || !strcasecmp (val
, "on"))
3436 else if (!strcasecmp (val
, "false")
3437 || !strcasecmp (val
, "off"))
3441 "boolean value (true/false/on/off) expected");
3442 skip_to_semi (cfile
);
3451 * data_expression :== SUBSTRING LPAREN data-expression COMMA
3452 * numeric-expression COMMA
3453 * numeric-expression RPAREN |
3454 * CONCAT LPAREN data-expression COMMA
3455 * data-expression RPAREN
3456 * SUFFIX LPAREN data_expression COMMA
3457 * numeric-expression RPAREN |
3458 * LCASE LPAREN data_expression RPAREN |
3459 * UCASE LPAREN data_expression RPAREN |
3460 * OPTION option_name |
3462 * PACKET LPAREN numeric-expression COMMA
3463 * numeric-expression RPAREN |
3464 * V6RELAY LPAREN numeric-expression COMMA
3465 * data-expression RPAREN |
3467 * colon_separated_hex_list
3470 int parse_data_expression (expr
, cfile
, lose
)
3471 struct expression
**expr
;
3472 struct parse
*cfile
;
3475 /* Parse an expression... */
3476 if (!parse_expression (expr
, cfile
, lose
, context_data
,
3477 (struct expression
**)0, expr_none
))
3480 if (!is_data_expression (*expr
) &&
3481 (*expr
) -> op
!= expr_variable_reference
&&
3482 (*expr
) -> op
!= expr_funcall
) {
3483 expression_dereference (expr
, MDL
);
3484 parse_warn (cfile
, "Expecting a data expression.");
3492 * numeric-expression :== EXTRACT_INT LPAREN data-expression
3493 * COMMA number RPAREN |
3497 int parse_numeric_expression (expr
, cfile
, lose
)
3498 struct expression
**expr
;
3499 struct parse
*cfile
;
3502 /* Parse an expression... */
3503 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
3504 (struct expression
**)0, expr_none
))
3507 if (!is_numeric_expression (*expr
) &&
3508 (*expr
) -> op
!= expr_variable_reference
&&
3509 (*expr
) -> op
!= expr_funcall
) {
3510 expression_dereference (expr
, MDL
);
3511 parse_warn (cfile
, "Expecting a numeric expression.");
3518 /* Parse a subexpression that does not contain a binary operator. */
3520 int parse_non_binary (expr
, cfile
, lose
, context
)
3521 struct expression
**expr
;
3522 struct parse
*cfile
;
3524 enum expression_context context
;
3526 enum dhcp_token token
;
3528 struct collection
*col
;
3529 struct expression
*nexp
, **ep
;
3532 isc_result_t status
;
3535 token
= peek_token (&val
, (unsigned *)0, cfile
);
3537 /* Check for unary operators... */
3540 skip_token(&val
, (unsigned *)0, cfile
);
3541 token
= next_token (&val
, (unsigned *)0, cfile
);
3542 if (token
!= STRING
) {
3543 parse_warn (cfile
, "string expected.");
3544 skip_to_semi (cfile
);
3548 for (col
= collections
; col
; col
= col
-> next
)
3549 if (!strcmp (col
-> name
, val
))
3552 parse_warn (cfile
, "unknown collection.");
3556 if (!expression_allocate (expr
, MDL
))
3557 log_fatal ("can't allocate expression");
3558 (*expr
) -> op
= expr_check
;
3559 (*expr
) -> data
.check
= col
;
3563 skip_token(&val
, NULL
, cfile
);
3564 if (!expression_allocate (expr
, MDL
))
3565 log_fatal ("can't allocate expression");
3566 (*expr
)->op
= expr_not
;
3567 if (!parse_non_binary (&(*expr
)->data
.not,
3568 cfile
, lose
, context_boolean
)) {
3570 parse_warn (cfile
, "expression expected");
3571 skip_to_semi (cfile
);
3574 expression_dereference (expr
, MDL
);
3577 if (!is_boolean_expression ((*expr
) -> data
.not)) {
3579 parse_warn (cfile
, "boolean expression expected");
3580 skip_to_semi (cfile
);
3581 expression_dereference (expr
, MDL
);
3587 skip_token(&val
, (unsigned *)0, cfile
);
3588 if (!parse_expression (expr
, cfile
, lose
, context
,
3589 (struct expression
**)0, expr_none
)) {
3591 parse_warn (cfile
, "expression expected");
3592 skip_to_semi (cfile
);
3597 token
= next_token (&val
, (unsigned *)0, cfile
);
3598 if (token
!= RPAREN
) {
3600 parse_warn (cfile
, "right paren expected");
3601 skip_to_semi (cfile
);
3607 skip_token(&val
, NULL
, cfile
);
3608 if (!expression_allocate (expr
, MDL
))
3609 log_fatal ("can't allocate expression");
3610 (*expr
)->op
= expr_exists
;
3612 /* Pass reference directly to expression structure. */
3613 status
= parse_option_name(cfile
, 0, &known
,
3614 &(*expr
)->data
.option
);
3615 if (status
!= ISC_R_SUCCESS
||
3616 (*expr
)->data
.option
== NULL
) {
3618 expression_dereference (expr
, MDL
);
3624 skip_token(&val
, (unsigned *)0, cfile
);
3625 if (!expression_allocate (expr
, MDL
))
3626 log_fatal ("can't allocate expression");
3627 (*expr
) -> op
= expr_static
;
3631 skip_token(&val
, (unsigned *)0, cfile
);
3632 if (!expression_allocate (expr
, MDL
))
3633 log_fatal ("can't allocate expression");
3634 (*expr
) -> op
= expr_known
;
3638 skip_token(&val
, (unsigned *)0, cfile
);
3639 if (!expression_allocate (expr
, MDL
))
3640 log_fatal ("can't allocate expression");
3641 (*expr
) -> op
= expr_substring
;
3643 token
= next_token (&val
, (unsigned *)0, cfile
);
3644 if (token
!= LPAREN
) {
3646 expression_dereference (expr
, MDL
);
3647 parse_warn (cfile
, "left parenthesis expected.");
3652 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
3655 expression_dereference (expr
, MDL
);
3658 "expecting data expression.");
3659 skip_to_semi (cfile
);
3665 token
= next_token (&val
, (unsigned *)0, cfile
);
3666 if (token
!= COMMA
) {
3668 expression_dereference (expr
, MDL
);
3669 parse_warn (cfile
, "comma expected.");
3675 if (!parse_numeric_expression
3676 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
3680 "expecting numeric expression.");
3681 skip_to_semi (cfile
);
3684 expression_dereference (expr
, MDL
);
3688 token
= next_token (&val
, (unsigned *)0, cfile
);
3692 if (!parse_numeric_expression
3693 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
3696 token
= next_token (&val
, (unsigned *)0, cfile
);
3697 if (token
!= RPAREN
) {
3699 parse_warn (cfile
, "right parenthesis expected.");
3701 expression_dereference (expr
, MDL
);
3707 skip_token(&val
, (unsigned *)0, cfile
);
3708 if (!expression_allocate (expr
, MDL
))
3709 log_fatal ("can't allocate expression");
3710 (*expr
) -> op
= expr_suffix
;
3712 token
= next_token (&val
, (unsigned *)0, cfile
);
3713 if (token
!= LPAREN
)
3716 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
3720 token
= next_token (&val
, (unsigned *)0, cfile
);
3724 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
3728 token
= next_token (&val
, (unsigned *)0, cfile
);
3729 if (token
!= RPAREN
)
3734 skip_token(&val
, (unsigned *)0, cfile
);
3735 if (!expression_allocate(expr
, MDL
))
3736 log_fatal ("can't allocate expression");
3737 (*expr
)->op
= expr_lcase
;
3739 token
= next_token(&val
, (unsigned *)0, cfile
);
3740 if (token
!= LPAREN
)
3743 if (!parse_data_expression(&(*expr
)->data
.lcase
, cfile
, lose
))
3746 token
= next_token(&val
, (unsigned *)0, cfile
);
3747 if (token
!= RPAREN
)
3752 skip_token(&val
, (unsigned *)0, cfile
);
3753 if (!expression_allocate(expr
, MDL
))
3754 log_fatal ("can't allocate expression");
3755 (*expr
)->op
= expr_ucase
;
3757 token
= next_token (&val
, (unsigned *)0, cfile
);
3758 if (token
!= LPAREN
)
3761 if (!parse_data_expression(&(*expr
)->data
.ucase
,
3765 token
= next_token(&val
, (unsigned *)0, cfile
);
3766 if (token
!= RPAREN
)
3771 skip_token(&val
, (unsigned *)0, cfile
);
3772 if (!expression_allocate (expr
, MDL
))
3773 log_fatal ("can't allocate expression");
3774 (*expr
) -> op
= expr_concat
;
3776 token
= next_token (&val
, (unsigned *)0, cfile
);
3777 if (token
!= LPAREN
)
3780 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3784 token
= next_token (&val
, (unsigned *)0, cfile
);
3789 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3793 token
= next_token (&val
, (unsigned *)0, cfile
);
3795 if (token
== COMMA
) {
3796 nexp
= (struct expression
*)0;
3797 if (!expression_allocate (&nexp
, MDL
))
3798 log_fatal ("can't allocate at CONCAT2");
3799 nexp
-> op
= expr_concat
;
3800 expression_reference (&nexp
-> data
.concat
[0],
3802 expression_dereference (expr
, MDL
);
3803 expression_reference (expr
, nexp
, MDL
);
3804 expression_dereference (&nexp
, MDL
);
3805 goto concat_another
;
3808 if (token
!= RPAREN
)
3812 case BINARY_TO_ASCII
:
3813 skip_token(&val
, (unsigned *)0, cfile
);
3814 if (!expression_allocate (expr
, MDL
))
3815 log_fatal ("can't allocate expression");
3816 (*expr
) -> op
= expr_binary_to_ascii
;
3818 token
= next_token (&val
, (unsigned *)0, cfile
);
3819 if (token
!= LPAREN
)
3822 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3826 token
= next_token (&val
, (unsigned *)0, cfile
);
3830 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3834 token
= next_token (&val
, (unsigned *)0, cfile
);
3838 if (!parse_data_expression (&(*expr
) -> data
.b2a
.separator
,
3842 token
= next_token (&val
, (unsigned *)0, cfile
);
3846 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3850 token
= next_token (&val
, (unsigned *)0, cfile
);
3851 if (token
!= RPAREN
)
3856 skip_token(&val
, (unsigned *)0, cfile
);
3857 if (!expression_allocate (expr
, MDL
))
3858 log_fatal ("can't allocate expression");
3859 (*expr
) -> op
= expr_reverse
;
3861 token
= next_token (&val
, (unsigned *)0, cfile
);
3862 if (token
!= LPAREN
)
3865 if (!(parse_numeric_expression
3866 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3869 token
= next_token (&val
, (unsigned *)0, cfile
);
3873 if (!(parse_data_expression
3874 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3877 token
= next_token (&val
, (unsigned *)0, cfile
);
3878 if (token
!= RPAREN
)
3883 /* pick (a, b, c) actually produces an internal representation
3884 that looks like pick (a, pick (b, pick (c, nil))). */
3885 skip_token(&val
, (unsigned *)0, cfile
);
3886 if (!(expression_allocate (expr
, MDL
)))
3887 log_fatal ("can't allocate expression");
3889 token
= next_token (&val
, (unsigned *)0, cfile
);
3890 if (token
!= LPAREN
)
3893 nexp
= (struct expression
*)0;
3894 expression_reference (&nexp
, *expr
, MDL
);
3896 nexp
-> op
= expr_pick_first_value
;
3897 if (!(parse_data_expression
3898 (&nexp
-> data
.pick_first_value
.car
,
3902 token
= next_token (&val
, (unsigned *)0, cfile
);
3903 if (token
== COMMA
) {
3904 struct expression
*foo
= (struct expression
*)0;
3905 if (!expression_allocate (&foo
, MDL
))
3906 log_fatal ("can't allocate expr");
3907 expression_reference
3908 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3909 expression_dereference (&nexp
, MDL
);
3910 expression_reference (&nexp
, foo
, MDL
);
3911 expression_dereference (&foo
, MDL
);
3913 } while (token
== COMMA
);
3914 expression_dereference (&nexp
, MDL
);
3916 if (token
!= RPAREN
)
3922 if (!expression_allocate (expr
, MDL
))
3923 log_fatal ("can't allocate expression");
3924 (*expr
) -> op
= (token
== OPTION
3926 : expr_config_option
);
3927 skip_token(&val
, (unsigned *)0, cfile
);
3929 /* Pass reference directly to expression structure. */
3930 status
= parse_option_name(cfile
, 0, &known
,
3931 &(*expr
)->data
.option
);
3932 if (status
!= ISC_R_SUCCESS
||
3933 (*expr
)->data
.option
== NULL
) {
3935 expression_dereference (expr
, MDL
);
3941 skip_token(&val
, (unsigned *)0, cfile
);
3942 if (!expression_allocate (expr
, MDL
))
3943 log_fatal ("can't allocate expression");
3944 (*expr
) -> op
= expr_hardware
;
3947 case LEASED_ADDRESS
:
3948 skip_token(&val
, (unsigned *)0, cfile
);
3949 if (!expression_allocate (expr
, MDL
))
3950 log_fatal ("can't allocate expression");
3951 (*expr
) -> op
= expr_leased_address
;
3955 skip_token(&val
, (unsigned *)0, cfile
);
3956 if (!expression_allocate (expr
, MDL
))
3957 log_fatal ("can't allocate expression");
3958 (*expr
) -> op
= expr_client_state
;
3962 skip_token(&val
, (unsigned *)0, cfile
);
3963 if (!expression_allocate (expr
, MDL
))
3964 log_fatal ("can't allocate expression");
3965 (*expr
) -> op
= expr_filename
;
3969 skip_token(&val
, (unsigned *)0, cfile
);
3970 if (!expression_allocate (expr
, MDL
))
3971 log_fatal ("can't allocate expression");
3972 (*expr
) -> op
= expr_sname
;
3976 skip_token(&val
, (unsigned *)0, cfile
);
3977 if (!expression_allocate (expr
, MDL
))
3978 log_fatal ("can't allocate expression");
3979 (*expr
) -> op
= expr_lease_time
;
3983 skip_token(&val
, (unsigned *)0, cfile
);
3984 if (!expression_allocate (expr
, MDL
))
3985 log_fatal ("can't allocate expression");
3986 (*expr
) -> op
= expr_null
;
3989 case HOST_DECL_NAME
:
3990 skip_token(&val
, (unsigned *)0, cfile
);
3991 if (!expression_allocate (expr
, MDL
))
3992 log_fatal ("can't allocate expression");
3993 (*expr
) -> op
= expr_host_decl_name
;
3997 skip_token(&val
, (unsigned *)0, cfile
);
3998 if (!expression_allocate (expr
, MDL
))
3999 log_fatal ("can't allocate expression");
4000 (*expr
) -> op
= expr_packet
;
4002 token
= next_token (&val
, (unsigned *)0, cfile
);
4003 if (token
!= LPAREN
)
4006 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
4010 token
= next_token (&val
, (unsigned *)0, cfile
);
4014 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
4018 token
= next_token (&val
, (unsigned *)0, cfile
);
4019 if (token
!= RPAREN
)
4024 skip_token(&val
, &len
, cfile
);
4025 if (!make_const_data (expr
, (const unsigned char *)val
,
4027 log_fatal ("can't make constant string expression.");
4031 skip_token(&val
, (unsigned *)0, cfile
);
4032 token
= next_token (&val
, (unsigned *)0, cfile
);
4033 if (token
!= LPAREN
) {
4034 parse_warn (cfile
, "left parenthesis expected.");
4039 if (!expression_allocate (expr
, MDL
))
4040 log_fatal ("can't allocate expression");
4042 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
4046 "expecting data expression.");
4047 skip_to_semi (cfile
);
4050 expression_dereference (expr
, MDL
);
4054 token
= next_token (&val
, (unsigned *)0, cfile
);
4055 if (token
!= COMMA
) {
4056 parse_warn (cfile
, "comma expected.");
4058 expression_dereference (expr
, MDL
);
4062 token
= next_token (&val
, (unsigned *)0, cfile
);
4063 if (token
!= NUMBER
) {
4064 parse_warn (cfile
, "number expected.");
4066 expression_dereference (expr
, MDL
);
4069 switch (atoi (val
)) {
4071 (*expr
) -> op
= expr_extract_int8
;
4075 (*expr
) -> op
= expr_extract_int16
;
4079 (*expr
) -> op
= expr_extract_int32
;
4084 "unsupported integer size %d", atoi (val
));
4086 skip_to_semi (cfile
);
4087 expression_dereference (expr
, MDL
);
4091 token
= next_token (&val
, (unsigned *)0, cfile
);
4092 if (token
!= RPAREN
) {
4093 parse_warn (cfile
, "right parenthesis expected.");
4095 expression_dereference (expr
, MDL
);
4101 skip_token(&val
, (unsigned *)0, cfile
);
4102 token
= next_token (&val
, (unsigned *)0, cfile
);
4103 if (token
!= LPAREN
) {
4104 parse_warn (cfile
, "left parenthesis expected.");
4109 if (!expression_allocate (expr
, MDL
))
4110 log_fatal ("can't allocate expression");
4112 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
4114 parse_warn (cfile
, "expecting numeric expression.");
4115 skip_to_semi (cfile
);
4117 expression_dereference (expr
, MDL
);
4121 token
= next_token (&val
, (unsigned *)0, cfile
);
4122 if (token
!= COMMA
) {
4123 parse_warn (cfile
, "comma expected.");
4125 expression_dereference (expr
, MDL
);
4129 token
= next_token (&val
, (unsigned *)0, cfile
);
4130 if (token
!= NUMBER
) {
4131 parse_warn (cfile
, "number expected.");
4133 expression_dereference (expr
, MDL
);
4136 switch (atoi (val
)) {
4138 (*expr
) -> op
= expr_encode_int8
;
4142 (*expr
) -> op
= expr_encode_int16
;
4146 (*expr
) -> op
= expr_encode_int32
;
4151 "unsupported integer size %d", atoi (val
));
4153 skip_to_semi (cfile
);
4154 expression_dereference (expr
, MDL
);
4158 token
= next_token (&val
, (unsigned *)0, cfile
);
4159 if (token
!= RPAREN
) {
4160 parse_warn (cfile
, "right parenthesis expected.");
4162 expression_dereference (expr
, MDL
);
4168 /* If we're in a numeric context, this should just be a
4169 number, by itself. */
4170 if (context
== context_numeric
||
4171 context
== context_data_or_numeric
) {
4172 skip_token(&val
, (unsigned *)0, cfile
);
4173 if (!expression_allocate (expr
, MDL
))
4174 log_fatal ("can't allocate expression");
4175 (*expr
) -> op
= expr_const_int
;
4176 (*expr
) -> data
.const_int
= atoi (val
);
4180 case NUMBER_OR_NAME
:
4181 if (!expression_allocate (expr
, MDL
))
4182 log_fatal ("can't allocate expression");
4184 (*expr
) -> op
= expr_const_data
;
4185 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
4186 expression_dereference (expr
, MDL
);
4195 skip_token(&val
, (unsigned *)0, cfile
);
4196 if (!expression_allocate (expr
, MDL
))
4197 log_fatal ("can't allocate expression");
4198 (*expr
) -> op
= expr_const_int
;
4199 (*expr
) -> data
.const_int
= known
;
4203 known
= ISC_R_SUCCESS
;
4207 known
= DHCP_R_NOTAUTH
;
4211 known
= ISC_R_NOTIMPLEMENTED
;
4215 known
= DHCP_R_NOTZONE
;
4219 known
= DHCP_R_NXDOMAIN
;
4223 known
= DHCP_R_NXRRSET
;
4227 known
= DHCP_R_REFUSED
;
4231 known
= DHCP_R_SERVFAIL
;
4235 known
= DHCP_R_YXDOMAIN
;
4239 known
= DHCP_R_YXRRSET
;
4247 known
= S_REBOOTING
;
4251 known
= S_SELECTING
;
4255 known
= S_REQUESTING
;
4267 known
= S_REBINDING
;
4271 skip_token(&val
, (unsigned *)0, cfile
);
4272 token
= next_token (&val
, (unsigned *)0, cfile
);
4273 if (token
!= LPAREN
)
4276 token
= next_token (&val
, (unsigned *)0, cfile
);
4277 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
4278 parse_warn (cfile
, "%s can't be a variable name", val
);
4279 skip_to_semi (cfile
);
4284 if (!expression_allocate (expr
, MDL
))
4285 log_fatal ("can't allocate expression");
4286 (*expr
) -> op
= expr_variable_exists
;
4287 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
4288 if (!(*expr
)->data
.variable
)
4289 log_fatal ("can't allocate variable name");
4290 strcpy ((*expr
) -> data
.variable
, val
);
4291 token
= next_token (&val
, (unsigned *)0, cfile
);
4292 if (token
!= RPAREN
)
4296 /* This parses 'gethostname()'. */
4298 skip_token(&val
, NULL
, cfile
);
4299 if (!expression_allocate(expr
, MDL
))
4300 log_fatal("can't allocate expression");
4301 (*expr
)->op
= expr_gethostname
;
4303 token
= next_token(NULL
, NULL
, cfile
);
4304 if (token
!= LPAREN
)
4307 token
= next_token(NULL
, NULL
, cfile
);
4308 if (token
!= RPAREN
)
4313 skip_token(&val
, NULL
, cfile
);
4314 token
= next_token(NULL
, NULL
, cfile
);
4315 if (token
!= LPAREN
)
4318 /* The argument is a quoted string. */
4319 token
= next_token(&val
, NULL
, cfile
);
4320 if (token
!= STRING
) {
4321 parse_warn(cfile
, "Expecting quoted literal: "
4322 "\"foo.example.com\"");
4323 skip_to_semi(cfile
);
4327 if (!make_host_lookup(expr
, val
))
4328 log_fatal("Error creating gethostbyname() internal "
4329 "record. (%s:%d)", MDL
);
4331 token
= next_token(NULL
, NULL
, cfile
);
4332 if (token
!= RPAREN
)
4337 skip_token(&val
, NULL
, cfile
);
4338 if (!expression_allocate (expr
, MDL
))
4339 log_fatal ("can't allocate expression");
4340 (*expr
)->op
= expr_v6relay
;
4342 token
= next_token (&val
, NULL
, cfile
);
4343 if (token
!= LPAREN
)
4346 if (!parse_numeric_expression (&(*expr
)->data
.v6relay
.relay
,
4350 token
= next_token (&val
, NULL
, cfile
);
4354 if (!parse_data_expression (&(*expr
)->data
.v6relay
.roption
,
4358 token
= next_token (&val
, NULL
, cfile
);
4360 if (token
!= RPAREN
)
4364 /* Not a valid start to an expression... */
4366 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
4369 skip_token(&val
, (unsigned *)0, cfile
);
4371 /* Save the name of the variable being referenced. */
4372 cptr
= dmalloc (strlen (val
) + 1, MDL
);
4374 log_fatal ("can't allocate variable name");
4377 /* Simple variable reference, as far as we can tell. */
4378 token
= peek_token (&val
, (unsigned *)0, cfile
);
4379 if (token
!= LPAREN
) {
4380 if (!expression_allocate (expr
, MDL
))
4381 log_fatal ("can't allocate expression");
4382 (*expr
) -> op
= expr_variable_reference
;
4383 (*expr
) -> data
.variable
= cptr
;
4387 skip_token(&val
, (unsigned *)0, cfile
);
4388 if (!expression_allocate (expr
, MDL
))
4389 log_fatal ("can't allocate expression");
4390 (*expr
) -> op
= expr_funcall
;
4391 (*expr
) -> data
.funcall
.name
= cptr
;
4393 /* Now parse the argument list. */
4394 ep
= &(*expr
) -> data
.funcall
.arglist
;
4396 if (!expression_allocate (ep
, MDL
))
4397 log_fatal ("can't allocate expression");
4398 (*ep
) -> op
= expr_arg
;
4399 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
4400 cfile
, lose
, context_any
,
4401 (struct expression
**)0,
4405 "expecting expression.");
4408 skip_to_semi (cfile
);
4409 expression_dereference (expr
, MDL
);
4412 ep
= &((*ep
) -> data
.arg
.next
);
4413 token
= next_token (&val
, (unsigned *)0, cfile
);
4414 } while (token
== COMMA
);
4415 if (token
!= RPAREN
) {
4416 parse_warn (cfile
, "Right parenthesis expected.");
4417 skip_to_semi (cfile
);
4419 expression_dereference (expr
, MDL
);
4427 /* Parse an expression. */
4429 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
4430 struct expression
**expr
;
4431 struct parse
*cfile
;
4433 enum expression_context context
;
4434 struct expression
**plhs
;
4437 enum dhcp_token token
;
4439 struct expression
*rhs
= (struct expression
*)0, *tmp
;
4440 struct expression
*lhs
= (struct expression
*)0;
4441 enum expr_op next_op
;
4442 enum expression_context
4443 lhs_context
= context_any
,
4444 rhs_context
= context_any
;
4446 /* Consume the left hand side we were passed. */
4448 expression_reference (&lhs
, *plhs
, MDL
);
4449 expression_dereference (plhs
, MDL
);
4453 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
4454 /* If we already have a left-hand side, then it's not
4455 okay for there not to be a right-hand side here, so
4456 we need to flag it as an error. */
4460 "expecting right-hand side.");
4462 skip_to_semi (cfile
);
4464 expression_dereference (&lhs
, MDL
);
4469 /* At this point, rhs contains either an entire subexpression,
4470 or at least a left-hand-side. If we do not see a binary token
4471 as the next token, we're done with the expression. */
4473 token
= peek_token (&val
, (unsigned *)0, cfile
);
4476 skip_token(&val
, (unsigned *)0, cfile
);
4477 token
= peek_token (&val
, (unsigned *)0, cfile
);
4478 if (token
!= EQUAL
) {
4479 parse_warn (cfile
, "! in boolean context without =");
4481 skip_to_semi (cfile
);
4483 expression_dereference (&lhs
, MDL
);
4486 next_op
= expr_not_equal
;
4487 context
= expression_context (rhs
);
4491 next_op
= expr_equal
;
4492 context
= expression_context (rhs
);
4497 skip_token(&val
, NULL
, cfile
);
4498 token
= peek_token(&val
, NULL
, cfile
);
4501 next_op
= expr_iregex_match
;
4502 else if (token
== EQUAL
)
4503 next_op
= expr_regex_match
;
4505 parse_warn(cfile
, "expecting ~= or ~~ operator");
4507 skip_to_semi(cfile
);
4509 expression_dereference(&lhs
, MDL
);
4513 context
= expression_context(rhs
);
4515 parse_warn(cfile
, "No support for regex operator.");
4517 skip_to_semi(cfile
);
4519 expression_dereference(&lhs
, MDL
);
4526 context
= expression_context (rhs
);
4531 context
= expression_context (rhs
);
4536 context
= expression_context (rhs
);
4540 next_op
= expr_subtract
;
4541 context
= expression_context (rhs
);
4545 next_op
= expr_divide
;
4546 context
= expression_context (rhs
);
4550 next_op
= expr_multiply
;
4551 context
= expression_context (rhs
);
4555 next_op
= expr_remainder
;
4556 context
= expression_context (rhs
);
4560 next_op
= expr_binary_and
;
4561 context
= expression_context (rhs
);
4565 next_op
= expr_binary_or
;
4566 context
= expression_context (rhs
);
4570 next_op
= expr_binary_xor
;
4571 context
= expression_context (rhs
);
4575 next_op
= expr_none
;
4578 /* If we have no lhs yet, we just parsed it. */
4580 /* If there was no operator following what we just parsed,
4581 then we're done - return it. */
4582 if (next_op
== expr_none
) {
4587 rhs
= (struct expression
*)0;
4589 skip_token(&val
, (unsigned *)0, cfile
);
4593 /* If the next binary operator is of greater precedence than the
4594 * current operator, then rhs we have parsed so far is actually
4595 * the lhs of the next operator. To get this value, we have to
4598 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4599 op_precedence (binop
, next_op
) < 0) {
4601 /* Eat the subexpression operator token, which we pass to
4602 * parse_expression...we only peek()'d earlier.
4604 skip_token(&val
, (unsigned *)0, cfile
);
4606 /* Continue parsing of the right hand side with that token. */
4608 rhs
= (struct expression
*)0;
4609 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4613 "expecting a subexpression");
4618 next_op
= expr_none
;
4621 if (binop
!= expr_none
) {
4622 rhs_context
= expression_context(rhs
);
4623 lhs_context
= expression_context(lhs
);
4625 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4626 (rhs_context
!= lhs_context
)) {
4627 parse_warn (cfile
, "illegal expression relating different types");
4628 skip_to_semi (cfile
);
4629 expression_dereference (&rhs
, MDL
);
4630 expression_dereference (&lhs
, MDL
);
4636 case expr_not_equal
:
4638 if ((rhs_context
!= context_data_or_numeric
) &&
4639 (rhs_context
!= context_data
) &&
4640 (rhs_context
!= context_numeric
) &&
4641 (rhs_context
!= context_any
)) {
4642 parse_warn (cfile
, "expecting data/numeric expression");
4643 skip_to_semi (cfile
);
4644 expression_dereference (&rhs
, MDL
);
4650 case expr_regex_match
:
4652 if (expression_context(rhs
) != context_data
) {
4653 parse_warn(cfile
, "expecting data expression");
4654 skip_to_semi(cfile
);
4655 expression_dereference(&rhs
, MDL
);
4660 /* It should not be possible to attempt to parse the right
4661 * hand side of an operator there is no support for.
4663 log_fatal("Impossible condition at %s:%d.", MDL
);
4669 if ((rhs_context
!= context_boolean
) &&
4670 (rhs_context
!= context_any
)) {
4671 parse_warn (cfile
, "expecting boolean expressions");
4672 skip_to_semi (cfile
);
4673 expression_dereference (&rhs
, MDL
);
4683 case expr_remainder
:
4684 case expr_binary_and
:
4685 case expr_binary_or
:
4686 case expr_binary_xor
:
4687 if ((rhs_context
!= context_numeric
) &&
4688 (rhs_context
!= context_any
)) {
4689 parse_warn (cfile
, "expecting numeric expressions");
4690 skip_to_semi (cfile
);
4691 expression_dereference (&rhs
, MDL
);
4702 /* Now, if we didn't find a binary operator, we're done parsing
4703 this subexpression, so combine it with the preceding binary
4704 operator and return the result. */
4705 if (next_op
== expr_none
) {
4706 if (!expression_allocate (expr
, MDL
))
4707 log_fatal ("Can't allocate expression!");
4709 (*expr
) -> op
= binop
;
4710 /* All the binary operators' data union members
4711 are the same, so we'll cheat and use the member
4712 for the equals operator. */
4713 (*expr
) -> data
.equal
[0] = lhs
;
4714 (*expr
) -> data
.equal
[1] = rhs
;
4718 /* Eat the operator token - we now know it was a binary operator... */
4719 skip_token(&val
, (unsigned *)0, cfile
);
4721 /* Now combine the LHS and the RHS using binop. */
4722 tmp
= (struct expression
*)0;
4723 if (!expression_allocate (&tmp
, MDL
))
4724 log_fatal ("No memory for equal precedence combination.");
4726 /* Store the LHS and RHS. */
4727 tmp
-> data
.equal
[0] = lhs
;
4728 tmp
-> data
.equal
[1] = rhs
;
4732 tmp
= (struct expression
*)0;
4733 rhs
= (struct expression
*)0;
4735 /* Recursions don't return until we have parsed the end of the
4736 expression, so if we recursed earlier, we can now return what
4738 if (next_op
== expr_none
) {
4748 int parse_option_data (expr
, cfile
, lookups
, option
)
4749 struct expression
**expr
;
4750 struct parse
*cfile
;
4752 struct option
*option
;
4755 const char *fmt
= NULL
;
4756 struct expression
*tmp
;
4757 enum dhcp_token token
;
4761 * Set a flag if this is an array of a simple type (i.e.,
4762 * not an array of pairs of IP addresses, or something like
4768 /* Set fmt to start of format for 'A' and one char back
4771 if ((fmt
!= NULL
) && (fmt
!= option
->format
) && (*fmt
== 'a'))
4773 else if ((fmt
== NULL
) || (*fmt
== 'A'))
4774 fmt
= option
->format
;
4776 /* 'a' means always uniform */
4777 if ((fmt
[0] != 'Z') && (tolower((unsigned char)fmt
[1]) == 'a'))
4781 if ((*fmt
== 'A') || (*fmt
== 'a'))
4784 /* consume the optional flag */
4789 if (fmt
[1] == 'o') {
4791 * A value for the current format is
4792 * optional - check to see if the next
4793 * token is a semi-colon if so we don't
4794 * need to parse it and doing so would
4795 * consume the semi-colon which our
4796 * caller is expecting to parse
4798 token
= peek_token(&val
, (unsigned *)0,
4800 if (token
== SEMI
) {
4809 if (!parse_option_token(expr
, cfile
, &fmt
, tmp
,
4810 uniform
, lookups
)) {
4811 if (fmt
[1] != 'o') {
4813 expression_dereference (&tmp
,
4821 expression_dereference (&tmp
, MDL
);
4824 } while (*fmt
!= '\0');
4826 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4827 token
= peek_token (&val
, (unsigned *)0, cfile
);
4828 /* Comma means: continue with next element in array */
4829 if (token
== COMMA
) {
4830 skip_token(&val
, (unsigned *)0, cfile
);
4833 /* no comma: end of array.
4834 'A' or end of string means: leave the loop */
4835 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4837 /* 'a' means: go on with next char */
4843 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4848 /* option-statement :== identifier DOT identifier <syntax> SEMI
4849 | identifier <syntax> SEMI
4851 Option syntax is handled specially through format strings, so it
4852 would be painful to come up with BNF for it. However, it always
4853 starts as above and ends in a SEMI. */
4855 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4856 struct executable_statement
**result
;
4857 struct parse
*cfile
;
4859 struct option
*option
;
4860 enum statement_op op
;
4863 enum dhcp_token token
;
4864 struct expression
*expr
= (struct expression
*)0;
4867 token
= peek_token (&val
, (unsigned *)0, cfile
);
4868 if ((token
== SEMI
) && (option
->format
[0] != 'Z')) {
4869 /* Eat the semicolon... */
4871 * XXXSK: I'm not sure why we should ever get here, but we
4872 * do during our startup. This confuses things if
4873 * we are parsing a zero-length option, so don't
4874 * eat the semicolon token in that case.
4876 skip_token(&val
, (unsigned *)0, cfile
);
4877 } else if (token
== EQUAL
) {
4878 /* Eat the equals sign. */
4879 skip_token(&val
, (unsigned *)0, cfile
);
4881 /* Parse a data expression and use its value for the data. */
4882 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
4883 /* In this context, we must have an executable
4884 statement, so if we found something else, it's
4888 "expecting a data expression.");
4889 skip_to_semi (cfile
);
4894 if (! parse_option_data(&expr
, cfile
, lookups
, option
))
4898 if (!parse_semi (cfile
))
4900 if (!executable_statement_allocate (result
, MDL
))
4901 log_fatal ("no memory for option statement.");
4904 if (expr
&& !option_cache (&(*result
)->data
.option
,
4905 NULL
, expr
, option
, MDL
))
4906 log_fatal ("no memory for option cache");
4909 expression_dereference (&expr
, MDL
);
4914 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4915 struct expression
**rv
;
4916 struct parse
*cfile
;
4918 struct expression
*expr
;
4923 enum dhcp_token token
;
4924 struct expression
*t
= (struct expression
*)0;
4925 unsigned char buf
[4];
4929 isc_boolean_t freeval
= ISC_FALSE
;
4931 struct enumeration_value
*e
;
4935 token
= next_token (&val
, &len
, cfile
);
4936 if (!is_identifier (token
)) {
4937 if ((*fmt
) [1] != 'o') {
4938 parse_warn (cfile
, "expecting identifier.");
4940 skip_to_semi (cfile
);
4944 if (!make_const_data (&t
, (const unsigned char *)val
,
4946 log_fatal ("No memory for %s", val
);
4950 g
= strchr (*fmt
, '.');
4953 "malformed encapsulation format (bug!)");
4954 skip_to_semi (cfile
);
4959 /* to get string value for the option */
4961 token
= peek_token (&val
, (unsigned *)0, cfile
);
4962 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4963 if (!expression_allocate (&t
, MDL
))
4965 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4966 expression_dereference (&t
, MDL
);
4969 t
-> op
= expr_const_data
;
4971 token
= next_token (&val
, &len
, cfile
);
4973 if(token
== STRING
) {
4974 if (!make_const_data (&t
,
4975 (const unsigned char *)val
,
4977 log_fatal ("No memory for \"%s\"", val
);
4979 if ((*fmt
) [1] != 'o') {
4980 parse_warn (cfile
, "expecting string "
4981 "or hexadecimal data.");
4982 skip_to_semi (cfile
);
4989 case 'D': /* Domain list... */
4990 if ((*fmt
)[1] == 'c') {
4992 /* Skip the compress-flag atom. */
4997 t
= parse_domain_list(cfile
, compress
);
5000 if ((*fmt
)[1] != 'o')
5001 skip_to_semi(cfile
);
5007 case 'd': /* Domain name... */
5008 val
= parse_host_name (cfile
);
5010 parse_warn (cfile
, "not a valid domain name.");
5011 skip_to_semi (cfile
);
5018 case 't': /* Text string... */
5019 token
= next_token (&val
, &len
, cfile
);
5020 if (token
!= STRING
&& !is_identifier (token
)) {
5021 if ((*fmt
) [1] != 'o') {
5022 parse_warn (cfile
, "expecting string.");
5024 skip_to_semi (cfile
);
5029 if (!make_const_data (&t
, (const unsigned char *)val
,
5031 log_fatal ("No memory for concatenation");
5032 if (freeval
== ISC_TRUE
) {
5033 dfree((char *)val
, MDL
);
5034 freeval
= ISC_FALSE
;
5041 g
= strchr (*fmt
, '.');
5043 parse_warn (cfile
, "malformed %s (bug!)",
5044 "enumeration format");
5046 skip_to_semi (cfile
);
5050 token
= next_token (&val
, (unsigned *)0, cfile
);
5051 if (!is_identifier (token
)) {
5053 "identifier expected");
5056 e
= find_enumeration_value (f
, (*fmt
) - f
, &len
, val
);
5058 parse_warn (cfile
, "unknown value");
5061 if (!make_const_data (&t
, &e
-> value
, len
, 0, 1, MDL
))
5065 case 'I': /* IP address or hostname. */
5067 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
5070 if (!parse_ip_addr (cfile
, &addr
))
5072 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
5078 case '6': /* IPv6 address. */
5079 if (!parse_ip6_addr(cfile
, &addr
)) {
5082 if (!make_const_data(&t
, addr
.iabuf
, addr
.len
, 0, 1, MDL
)) {
5087 case 'T': /* Lease interval. */
5088 token
= next_token (&val
, (unsigned *)0, cfile
);
5089 if (token
!= INFINITE
)
5092 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5096 case 'L': /* Unsigned 32-bit integer... */
5097 case 'l': /* Signed 32-bit integer... */
5098 token
= next_token (&val
, (unsigned *)0, cfile
);
5100 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
5102 if ((*fmt
) [1] != 'o') {
5103 parse_warn (cfile
, "expecting number.");
5105 skip_to_semi (cfile
);
5109 convert_num (cfile
, buf
, val
, 0, 32);
5110 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
5114 case 's': /* Signed 16-bit integer. */
5115 case 'S': /* Unsigned 16-bit integer. */
5116 token
= next_token (&val
, (unsigned *)0, cfile
);
5117 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5119 convert_num (cfile
, buf
, val
, 0, 16);
5120 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
5124 case 'b': /* Signed 8-bit integer. */
5125 case 'B': /* Unsigned 8-bit integer. */
5126 token
= next_token (&val
, (unsigned *)0, cfile
);
5127 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
5129 convert_num (cfile
, buf
, val
, 0, 8);
5130 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5134 case 'f': /* Boolean flag. */
5135 token
= next_token (&val
, (unsigned *)0, cfile
);
5136 if (!is_identifier (token
)) {
5137 if ((*fmt
) [1] != 'o')
5138 parse_warn (cfile
, "expecting identifier.");
5140 if ((*fmt
) [1] != 'o') {
5142 skip_to_semi (cfile
);
5146 if (!strcasecmp (val
, "true")
5147 || !strcasecmp (val
, "on"))
5149 else if (!strcasecmp (val
, "false")
5150 || !strcasecmp (val
, "off"))
5152 else if (!strcasecmp (val
, "ignore"))
5155 if ((*fmt
) [1] != 'o')
5156 parse_warn (cfile
, "expecting boolean.");
5159 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
5163 case 'Z': /* Zero-length option. */
5164 token
= peek_token (&val
, (unsigned *)0, cfile
);
5165 if (token
!= SEMI
) {
5166 parse_warn(cfile
, "semicolon expected.");
5167 skip_to_semi(cfile
);
5170 if (!make_const_data(&t
, /* expression */
5180 parse_warn (cfile
, "Bad format '%c' in parse_option_token.",
5182 skip_to_semi (cfile
);
5186 if (!make_concat (rv
, expr
, t
))
5189 expression_reference (rv
, t
, MDL
);
5190 expression_dereference (&t
, MDL
);
5194 int parse_option_decl (oc
, cfile
)
5195 struct option_cache
**oc
;
5196 struct parse
*cfile
;
5201 u_int8_t hunkbuf
[1024];
5202 unsigned hunkix
= 0;
5203 const char *fmt
, *f
;
5204 struct option
*option
=NULL
;
5205 struct iaddr ip_addr
;
5207 const u_int8_t
*cdp
;
5213 struct expression
*express
= NULL
;
5214 struct enumeration_value
*e
;
5215 isc_result_t status
;
5217 status
= parse_option_name (cfile
, 0, &known
, &option
);
5218 if (status
!= ISC_R_SUCCESS
|| option
== NULL
)
5221 fmt
= option
->format
;
5223 /* Parse the option data... */
5225 for (; *fmt
; fmt
++) {
5227 /* 'A' is an array of records, start at
5230 fmt
= option
->format
;
5235 /* 'a' is an array of the last field,
5236 * back up one format character
5241 if (*fmt
== 'o' && fmt
!= option
-> format
)
5245 fmt
= strchr (fmt
, '.');
5248 "malformed %s (bug!)",
5249 "encapsulation format");
5253 /* to get string value for the option */
5255 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
5256 sizeof hunkbuf
- hunkix
);
5260 case 't': /* Text string... */
5261 token
= peek_token (&val
,
5263 if (token
== SEMI
&& fmt
[1] == 'o') {
5267 token
= next_token (&val
,
5269 if (token
!= STRING
) {
5271 "expecting string.");
5274 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
5276 "option data buffer %s",
5280 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
5286 if (fmt
[1] == 'c') {
5292 express
= parse_domain_list(cfile
, compress
);
5294 if (express
== NULL
)
5297 if (express
->op
!= expr_const_data
) {
5298 parse_warn(cfile
, "unexpected "
5303 len
= express
->data
.const_data
.len
;
5304 cdp
= express
->data
.const_data
.data
;
5306 if ((hunkix
+ len
) > sizeof(hunkbuf
)) {
5307 parse_warn(cfile
, "option data buffer "
5311 memcpy(&hunkbuf
[hunkix
], cdp
, len
);
5314 expression_dereference(&express
, MDL
);
5319 fmt
= strchr (fmt
, '.');
5322 "malformed %s (bug!)",
5323 "enumeration format");
5326 token
= next_token (&val
,
5327 (unsigned *)0, cfile
);
5328 if (!is_identifier (token
)) {
5330 "identifier expected");
5333 e
= find_enumeration_value (f
, fmt
- f
,
5344 if (!parse_ip6_addr(cfile
, &ip_addr
))
5350 case 'I': /* IP address. */
5351 if (!parse_ip_addr (cfile
, &ip_addr
))
5357 if (hunkix
+ len
> sizeof hunkbuf
) {
5359 "option data buffer %s",
5363 memcpy (&hunkbuf
[hunkix
], dp
, len
);
5367 case 'L': /* Unsigned 32-bit integer... */
5368 case 'l': /* Signed 32-bit integer... */
5369 token
= next_token (&val
,
5370 (unsigned *)0, cfile
);
5371 if ((token
!= NUMBER
) &&
5372 (token
!= NUMBER_OR_NAME
)) {
5375 "expecting number.");
5381 convert_num (cfile
, buf
, val
, 0, 32);
5386 case 's': /* Signed 16-bit integer. */
5387 case 'S': /* Unsigned 16-bit integer. */
5388 token
= next_token (&val
,
5389 (unsigned *)0, cfile
);
5390 if ((token
!= NUMBER
) &&
5391 (token
!= NUMBER_OR_NAME
))
5393 convert_num (cfile
, buf
, val
, 0, 16);
5398 case 'b': /* Signed 8-bit integer. */
5399 case 'B': /* Unsigned 8-bit integer. */
5400 token
= next_token (&val
,
5401 (unsigned *)0, cfile
);
5402 if ((token
!= NUMBER
) &&
5403 (token
!= NUMBER_OR_NAME
))
5405 convert_num (cfile
, buf
, val
, 0, 8);
5410 case 'f': /* Boolean flag. */
5411 token
= next_token (&val
,
5412 (unsigned *)0, cfile
);
5413 if (!is_identifier (token
)) {
5415 "expecting identifier.");
5422 if (!strcasecmp (val
, "true")
5423 || !strcasecmp (val
, "on"))
5425 else if (!strcasecmp (val
, "false")
5426 || !strcasecmp (val
, "off"))
5430 "expecting boolean.");
5437 case 'Z': /* Zero-length option */
5438 token
= peek_token(&val
, (unsigned *)0, cfile
);
5439 if (token
!= SEMI
) {
5441 "semicolon expected.");
5449 log_error ("parse_option_param: Bad format %c",
5454 token
= next_token (&val
, (unsigned *)0, cfile
);
5455 } while (*fmt
&& token
== COMMA
);
5457 if (token
!= SEMI
) {
5458 parse_warn (cfile
, "semicolon expected.");
5462 bp
= (struct buffer
*)0;
5463 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
5464 log_fatal ("no memory to store option declaration.");
5465 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
5467 if (!option_cache_allocate (oc
, MDL
))
5468 log_fatal ("out of memory allocating option cache.");
5470 (*oc
) -> data
.buffer
= bp
;
5471 (*oc
) -> data
.data
= &bp
-> data
[0];
5472 (*oc
) -> data
.terminated
= nul_term
;
5473 (*oc
) -> data
.len
= hunkix
;
5474 option_reference(&(*oc
)->option
, option
, MDL
);
5475 option_dereference(&option
, MDL
);
5479 if (express
!= NULL
)
5480 expression_dereference(&express
, MDL
);
5481 skip_to_semi (cfile
);
5483 option_dereference(&option
, MDL
);
5488 /* Consider merging parse_cshl into this. */
5490 int parse_X (cfile
, buf
, max
)
5491 struct parse
*cfile
;
5499 token
= peek_token (&val
, (unsigned *)0, cfile
);
5500 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
5503 token
= next_token (&val
, (unsigned *)0, cfile
);
5504 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
5506 "expecting hexadecimal constant.");
5507 skip_to_semi (cfile
);
5510 convert_num (cfile
, &buf
[len
], val
, 16, 8);
5513 "hexadecimal constant too long.");
5514 skip_to_semi (cfile
);
5517 token
= peek_token (&val
, (unsigned *)0, cfile
);
5519 token
= next_token (&val
,
5520 (unsigned *)0, cfile
);
5521 } while (token
== COLON
);
5523 } else if (token
== STRING
) {
5524 skip_token(&val
, &len
, cfile
);
5525 if (len
+ 1 > max
) {
5526 parse_warn (cfile
, "string constant too long.");
5527 skip_to_semi (cfile
);
5530 memcpy (buf
, val
, len
+ 1);
5532 parse_warn (cfile
, "expecting string or hexadecimal data");
5533 skip_to_semi (cfile
);
5539 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
5547 do_percentm (mbuf
, fmt
);
5548 /* %Audit% This is log output. %2004.06.17,Safe%
5549 * If we truncate we hope the user can get a hint from the log.
5551 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
5552 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
5554 va_start (list
, fmt
);
5555 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
5560 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
5561 if (lix
< (sizeof lexbuf
) - 1)
5562 lexbuf
[lix
++] = ' ';
5563 if (cfile
-> token_line
[i
] == '\t') {
5564 for (; lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
5571 syslog (LOG_ERR
, "%s", mbuf
);
5572 syslog (LOG_ERR
, "%s", cfile
-> token_line
);
5573 if (cfile
-> lexchar
< 81)
5574 syslog (LOG_ERR
, "%s^", lexbuf
);
5578 IGNORE_RET (write (STDERR_FILENO
, mbuf
, strlen (mbuf
)));
5579 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5580 IGNORE_RET (write (STDERR_FILENO
, cfile
-> token_line
,
5581 strlen (cfile
-> token_line
)));
5582 IGNORE_RET (write (STDERR_FILENO
, "\n", 1));
5583 if (cfile
-> lexchar
< 81)
5584 IGNORE_RET (write (STDERR_FILENO
, lexbuf
, lix
));
5585 IGNORE_RET (write (STDERR_FILENO
, "^\n", 2));
5588 cfile
-> warnings_occurred
= 1;
5594 parse_domain_list(struct parse
*cfile
, int compress
)
5597 enum dhcp_token token
= SEMI
;
5598 struct expression
*t
= NULL
;
5599 unsigned len
, clen
= 0;
5601 unsigned char compbuf
[256 * NS_MAXCDNAME
];
5602 const unsigned char *dnptrs
[256], **lastdnptr
;
5604 memset(compbuf
, 0, sizeof(compbuf
));
5605 memset(dnptrs
, 0, sizeof(dnptrs
));
5606 dnptrs
[0] = compbuf
;
5607 lastdnptr
= &dnptrs
[255];
5610 /* Consume the COMMA token if peeked. */
5612 skip_token(&val
, NULL
, cfile
);
5614 /* Get next (or first) value. */
5615 token
= next_token(&val
, &len
, cfile
);
5617 if (token
!= STRING
) {
5618 parse_warn(cfile
, "Expecting a domain string.");
5622 /* If compression pointers are enabled, compress. If not,
5623 * just pack the names in series into the buffer.
5626 result
= MRns_name_compress(val
, compbuf
+ clen
,
5627 sizeof(compbuf
) - clen
,
5631 parse_warn(cfile
, "Error compressing domain "
5638 result
= MRns_name_pton(val
, compbuf
+ clen
,
5639 sizeof(compbuf
) - clen
);
5641 /* result == 1 means the input was fully qualified.
5642 * result == 0 means the input wasn't.
5643 * result == -1 means bad things.
5646 parse_warn(cfile
, "Error assembling domain "
5652 * We need to figure out how many bytes to increment
5653 * our buffer pointer since pton doesn't tell us.
5655 while (compbuf
[clen
] != 0)
5656 clen
+= compbuf
[clen
] + 1;
5658 /* Count the last label (0). */
5662 if (clen
> sizeof(compbuf
))
5663 log_fatal("Impossible error at %s:%d", MDL
);
5665 token
= peek_token(&val
, NULL
, cfile
);
5666 } while (token
== COMMA
);
5668 if (!make_const_data(&t
, compbuf
, clen
, 1, 1, MDL
))
5669 log_fatal("No memory for domain list object.");