3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id: parse.c,v 1.9 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
42 /* Enumerations can be specified in option formats, and are used for
43 parsing, so we define the routines that manage them here. */
45 struct enumeration
*enumerations
;
47 void add_enumeration (struct enumeration
*enumeration
)
49 enumeration
-> next
= enumerations
;
50 enumerations
= enumeration
;
53 struct enumeration
*find_enumeration (const char *name
, int length
)
55 struct enumeration
*e
;
57 for (e
= enumerations
; e
; e
= e
-> next
)
58 if (strlen (e
-> name
) == length
&&
59 !memcmp (e
-> name
, name
, (unsigned)length
))
61 return (struct enumeration
*)0;
64 struct enumeration_value
*find_enumeration_value (const char *name
,
68 struct enumeration
*e
;
71 e
= find_enumeration (name
, length
);
73 for (i
= 0; e
-> values
[i
].name
; i
++) {
74 if (!strcmp (value
, e
-> values
[i
].name
))
75 return &e
-> values
[i
];
78 return (struct enumeration_value
*)0;
81 /* Skip to the semicolon ending the current statement. If we encounter
82 braces, the matching closing brace terminates the statement. If we
83 encounter a right brace but haven't encountered a left brace, return
84 leaving the brace in the token buffer for the caller. If we see a
85 semicolon and haven't seen a left brace, return. This lets us skip
90 statement foo bar { statement { } }
95 void skip_to_semi (cfile
)
98 skip_to_rbrace (cfile
, 0);
101 void skip_to_rbrace (cfile
, brace_count
)
105 enum dhcp_token token
;
108 #if defined (DEBUG_TOKEN)
109 log_error ("skip_to_rbrace: %d\n", brace_count
);
112 token
= peek_token (&val
, (unsigned *)0, cfile
);
113 if (token
== RBRACE
) {
114 token
= next_token (&val
, (unsigned *)0, cfile
);
120 } else if (token
== LBRACE
) {
122 } else if (token
== SEMI
&& !brace_count
) {
123 token
= next_token (&val
, (unsigned *)0, cfile
);
125 } else if (token
== EOL
) {
126 /* EOL only happens when parsing /etc/resolv.conf,
127 and we treat it like a semicolon because the
128 resolv.conf file is line-oriented. */
129 token
= next_token (&val
, (unsigned *)0, cfile
);
132 token
= next_token (&val
, (unsigned *)0, cfile
);
133 } while (token
!= END_OF_FILE
);
136 int parse_semi (cfile
)
139 enum dhcp_token token
;
142 token
= next_token (&val
, (unsigned *)0, cfile
);
144 parse_warn (cfile
, "semicolon expected.");
145 skip_to_semi (cfile
);
151 /* string-parameter :== STRING SEMI */
153 int parse_string (cfile
, sptr
, lptr
)
159 enum dhcp_token token
;
163 token
= next_token (&val
, &len
, cfile
);
164 if (token
!= STRING
) {
165 parse_warn (cfile
, "expecting a string");
166 skip_to_semi (cfile
);
169 s
= (char *)dmalloc (len
+ 1, MDL
);
171 log_fatal ("no memory for string %s.", val
);
172 memcpy (s
, val
, len
+ 1);
174 if (!parse_semi (cfile
)) {
188 * hostname :== IDENTIFIER
190 * | hostname DOT IDENTIFIER
193 char *parse_host_name (cfile
)
197 enum dhcp_token token
;
204 /* Read a dotted hostname... */
206 /* Read a token, which should be an identifier. */
207 token
= peek_token (&val
, (unsigned *)0, cfile
);
208 if (!is_identifier (token
) && token
!= NUMBER
)
210 token
= next_token (&val
, (unsigned *)0, cfile
);
212 /* Store this identifier... */
213 if (!(s
= (char *)dmalloc (strlen (val
) + 1, MDL
)))
214 log_fatal ("can't allocate temp space for hostname.");
216 c
= cons ((caddr_t
)s
, c
);
217 len
+= strlen (s
) + 1;
218 /* Look for a dot; if it's there, keep going, otherwise
220 token
= peek_token (&val
, (unsigned *)0, cfile
);
222 token
= next_token (&val
, (unsigned *)0, cfile
);
226 } while (token
== DOT
);
228 /* Should be at least one token. */
232 /* Assemble the hostname together into a string. */
233 if (!(s
= (char *)dmalloc (len
+ ltid
, MDL
)))
234 log_fatal ("can't allocate space for hostname.");
241 unsigned l
= strlen ((char *)(c
-> car
));
243 memcpy (t
, (char *)(c
-> car
), l
);
244 /* Free up temp space. */
245 dfree (c
-> car
, MDL
);
254 /* ip-addr-or-hostname :== ip-address | hostname
255 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
257 Parse an ip address or a hostname. If uniform is zero, put in
258 an expr_substring node to limit hostnames that evaluate to more
259 than one IP address. */
261 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
262 struct expression
**expr
;
267 enum dhcp_token token
;
268 unsigned char addr
[4];
269 unsigned len
= sizeof addr
;
271 struct expression
*x
= (struct expression
*)0;
273 token
= peek_token (&val
, (unsigned *)0, cfile
);
274 if (is_identifier (token
)) {
275 name
= parse_host_name (cfile
);
278 if (!make_host_lookup (expr
, name
)) {
284 if (!make_limit (&x
, *expr
, 4))
286 expression_dereference (expr
, MDL
);
289 } else if (token
== NUMBER
) {
290 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
292 return make_const_data (expr
, addr
, len
, 0, 1, MDL
);
294 if (token
!= RBRACE
&& token
!= LBRACE
)
295 token
= next_token (&val
, (unsigned *)0, cfile
);
296 parse_warn (cfile
, "%s (%d): expecting IP address or hostname",
299 skip_to_semi (cfile
);
307 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
310 int parse_ip_addr (cfile
, addr
)
316 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
317 &addr
-> len
, DOT
, 10, 8))
323 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
324 * hardware-type :== ETHERNET | TOKEN_RING | FDDI
327 void parse_hardware_param (cfile
, hardware
)
329 struct hardware
*hardware
;
332 enum dhcp_token token
;
336 token
= next_token (&val
, (unsigned *)0, cfile
);
339 hardware
-> hbuf
[0] = HTYPE_ETHER
;
342 hardware
-> hbuf
[0] = HTYPE_IEEE802
;
345 hardware
-> hbuf
[0] = HTYPE_FDDI
;
348 if (!strncmp (val
, "unknown-", 8)) {
349 hardware
-> hbuf
[0] = atoi (&val
[8]);
352 "expecting a network hardware type");
353 skip_to_semi (cfile
);
359 /* Parse the hardware address information. Technically,
360 it would make a lot of sense to restrict the length of the
361 data we'll accept here to the length of a particular hardware
362 address type. Unfortunately, there are some broken clients
363 out there that put bogus data in the chaddr buffer, and we accept
364 that data in the lease file rather than simply failing on such
367 token
= peek_token (&val
, (unsigned *)0, cfile
);
369 hardware
-> hlen
= 1;
372 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
375 hardware
-> hlen
= 1;
378 if (hlen
+ 1 > sizeof hardware
-> hbuf
) {
380 parse_warn (cfile
, "hardware address too long");
382 hardware
-> hlen
= hlen
+ 1;
383 memcpy ((unsigned char *)&hardware
-> hbuf
[1], t
, hlen
);
384 if (hlen
+ 1 < sizeof hardware
-> hbuf
)
385 memset (&hardware
-> hbuf
[hlen
+ 1], 0,
386 (sizeof hardware
-> hbuf
) - hlen
- 1);
391 token
= next_token (&val
, (unsigned *)0, cfile
);
393 parse_warn (cfile
, "expecting semicolon.");
394 skip_to_semi (cfile
);
398 /* lease-time :== NUMBER SEMI */
400 void parse_lease_time (cfile
, timep
)
405 enum dhcp_token token
;
407 token
= next_token (&val
, (unsigned *)0, cfile
);
408 if (token
!= NUMBER
) {
409 parse_warn (cfile
, "Expecting numeric lease time");
410 skip_to_semi (cfile
);
413 convert_num (cfile
, (unsigned char *)timep
, val
, 10, 32);
414 /* Unswap the number - convert_num returns stuff in NBO. */
415 *timep
= ntohl (*timep
); /* XXX */
420 /* No BNF for numeric aggregates - that's defined by the caller. What
421 this function does is to parse a sequence of numbers seperated by
422 the token specified in seperator. If max is zero, any number of
423 numbers will be parsed; otherwise, exactly max numbers are
424 expected. Base and size tell us how to internalize the numbers
425 once they've been tokenized. */
427 unsigned char *parse_numeric_aggregate (cfile
, buf
,
428 max
, seperator
, base
, size
)
437 enum dhcp_token token
;
438 unsigned char *bufp
= buf
, *s
, *t
;
443 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
445 log_fatal ("no space for numeric aggregate");
452 token
= peek_token (&val
, (unsigned *)0, cfile
);
453 if (token
!= seperator
) {
456 if (token
!= RBRACE
&& token
!= LBRACE
)
457 token
= next_token (&val
,
460 parse_warn (cfile
, "too few numbers.");
462 skip_to_semi (cfile
);
463 return (unsigned char *)0;
465 token
= next_token (&val
, (unsigned *)0, cfile
);
467 token
= next_token (&val
, (unsigned *)0, cfile
);
469 if (token
== END_OF_FILE
) {
470 parse_warn (cfile
, "unexpected end of file");
474 /* Allow NUMBER_OR_NAME if base is 16. */
475 if (token
!= NUMBER
&&
476 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
477 parse_warn (cfile
, "expecting numeric value.");
478 skip_to_semi (cfile
);
479 return (unsigned char *)0;
481 /* If we can, convert the number now; otherwise, build
482 a linked list of all the numbers. */
484 convert_num (cfile
, s
, val
, base
, size
);
487 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
489 log_fatal ("no temp space for number.");
490 strcpy ((char *)t
, val
);
491 c
= cons ((caddr_t
)t
, c
);
493 } while (++count
!= *max
);
495 /* If we had to cons up a list, convert it now. */
497 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
499 log_fatal ("no space for numeric aggregate.");
500 s
= bufp
+ count
- size
/ 8;
505 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
507 /* Free up temp space. */
508 dfree (c
-> car
, MDL
);
515 void convert_num (cfile
, buf
, str
, base
, size
)
522 const char *ptr
= str
;
533 /* If base wasn't specified, figure it out from the data. */
535 if (ptr
[0] == '0') {
536 if (ptr
[1] == 'x') {
539 } else if (isdigit ((unsigned char)ptr
[1])) {
552 /* XXX assumes ASCII... */
554 tval
= tval
- 'a' + 10;
555 else if (tval
>= 'A')
556 tval
= tval
- 'A' + 10;
557 else if (tval
>= '0')
560 parse_warn (cfile
, "Bogus number: %s.", str
);
565 "Bogus number %s: digit %d not in base %d",
569 val
= val
* base
+ tval
;
573 max
= (1 << (size
- 1));
575 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
580 "%s%lo exceeds max (%d) for precision.",
582 (unsigned long)val
, max
);
586 "%s%lx exceeds max (%d) for precision.",
588 (unsigned long)val
, max
);
592 "%s%lu exceeds max (%d) for precision.",
594 (unsigned long)val
, max
);
602 *buf
= -(unsigned long)val
;
605 putShort (buf
, -(long)val
);
608 putLong (buf
, -(long)val
);
612 "Unexpected integer size: %d\n", size
);
618 *buf
= (u_int8_t
)val
;
621 putUShort (buf
, (u_int16_t
)val
);
628 "Unexpected integer size: %d\n", size
);
635 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
636 * NUMBER COLON NUMBER COLON NUMBER SEMI |
637 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
638 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
641 * Dates are stored in GMT or with a timezone offset; first number is day
642 * of week; next is year/month/day; next is hours:minutes:seconds on a
643 * 24-hour clock, followed by the timezone offset in seconds, which is
647 TIME
parse_date (cfile
)
651 int tzoff
, wday
, year
, mon
, mday
, hour
, min
, sec
;
653 enum dhcp_token token
;
654 static int months
[11] = { 31, 59, 90, 120, 151, 181,
655 212, 243, 273, 304, 334 };
657 /* Day of week, or "never"... */
658 token
= next_token (&val
, (unsigned *)0, cfile
);
659 if (token
== NEVER
) {
660 if (!parse_semi (cfile
))
665 if (token
!= NUMBER
) {
666 parse_warn (cfile
, "numeric day of week expected.");
668 skip_to_semi (cfile
);
674 token
= next_token (&val
, (unsigned *)0, cfile
);
675 if (token
!= NUMBER
) {
676 parse_warn (cfile
, "numeric year expected.");
678 skip_to_semi (cfile
);
682 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
683 somebody invents a time machine, I think we can safely disregard
684 it. This actually works around a stupid Y2K bug that was present
685 in a very early beta release of dhcpd. */
690 /* Slash seperating year from month... */
691 token
= next_token (&val
, (unsigned *)0, cfile
);
692 if (token
!= SLASH
) {
694 "expected slash seperating year from month.");
696 skip_to_semi (cfile
);
701 token
= next_token (&val
, (unsigned *)0, cfile
);
702 if (token
!= NUMBER
) {
703 parse_warn (cfile
, "numeric month expected.");
705 skip_to_semi (cfile
);
708 mon
= atoi (val
) - 1;
710 /* Slash seperating month from day... */
711 token
= next_token (&val
, (unsigned *)0, cfile
);
712 if (token
!= SLASH
) {
714 "expected slash seperating month from day.");
716 skip_to_semi (cfile
);
720 /* Day of month... */
721 token
= next_token (&val
, (unsigned *)0, cfile
);
722 if (token
!= NUMBER
) {
723 parse_warn (cfile
, "numeric day of month expected.");
725 skip_to_semi (cfile
);
731 token
= next_token (&val
, (unsigned *)0, cfile
);
732 if (token
!= NUMBER
) {
733 parse_warn (cfile
, "numeric hour expected.");
735 skip_to_semi (cfile
);
740 /* Colon seperating hour from minute... */
741 token
= next_token (&val
, (unsigned *)0, cfile
);
742 if (token
!= COLON
) {
744 "expected colon seperating hour from minute.");
746 skip_to_semi (cfile
);
751 token
= next_token (&val
, (unsigned *)0, cfile
);
752 if (token
!= NUMBER
) {
753 parse_warn (cfile
, "numeric minute expected.");
755 skip_to_semi (cfile
);
760 /* Colon seperating minute from second... */
761 token
= next_token (&val
, (unsigned *)0, cfile
);
762 if (token
!= COLON
) {
764 "expected colon seperating hour from minute.");
766 skip_to_semi (cfile
);
771 token
= next_token (&val
, (unsigned *)0, cfile
);
772 if (token
!= NUMBER
) {
773 parse_warn (cfile
, "numeric minute expected.");
775 skip_to_semi (cfile
);
780 token
= peek_token (&val
, (unsigned *)0, cfile
);
781 if (token
== NUMBER
) {
782 token
= next_token (&val
, (unsigned *)0, cfile
);
787 /* Make sure the date ends in a semicolon... */
788 if (!parse_semi (cfile
))
791 /* Guess the time value... */
792 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
793 (year
- 69) / 4 + /* Leap days since '70 */
794 (mon
/* Days in months this year */
797 (mon
> 1 && /* Leap day this year */
798 !((year
- 72) & 3)) +
799 mday
- 1) * 24) + /* Day of month */
801 min
) * 60) + sec
+ tzoff
;
803 /* This guess could be wrong because of leap seconds or other
804 weirdness we don't know about that the system does. For
805 now, we're just going to accept the guess, but at some point
806 it might be nice to do a successive approximation here to
807 get an exact value. Even if the error is small, if the
808 server is restarted frequently (and thus the lease database
809 is reread), the error could accumulate into something
816 * option-name :== IDENTIFIER |
817 IDENTIFIER . IDENTIFIER
820 struct option
*parse_option_name (cfile
, allocate
, known
)
826 enum dhcp_token token
;
828 struct universe
*universe
;
829 struct option
*option
;
831 token
= next_token (&val
, (unsigned *)0, cfile
);
832 if (!is_identifier (token
)) {
834 "expecting identifier after option keyword.");
836 skip_to_semi (cfile
);
837 return (struct option
*)0;
839 uname
= dmalloc (strlen (val
) + 1, MDL
);
841 log_fatal ("no memory for uname information.");
843 token
= peek_token (&val
, (unsigned *)0, cfile
);
845 /* Go ahead and take the DOT token... */
846 token
= next_token (&val
, (unsigned *)0, cfile
);
848 /* The next token should be an identifier... */
849 token
= next_token (&val
, (unsigned *)0, cfile
);
850 if (!is_identifier (token
)) {
851 parse_warn (cfile
, "expecting identifier after '.'");
853 skip_to_semi (cfile
);
854 return (struct option
*)0;
857 /* Look up the option name hash table for the specified
859 universe
= (struct universe
*)0;
860 if (!universe_hash_lookup (&universe
, universe_hash
,
862 parse_warn (cfile
, "no option space named %s.", uname
);
863 skip_to_semi (cfile
);
864 return (struct option
*)0;
867 /* Use the default hash table, which contains all the
868 standard dhcp option names. */
870 universe
= &dhcp_universe
;
873 /* Look up the actual option info... */
874 option
= (struct option
*)0;
875 option_hash_lookup (&option
, universe
-> hash
, val
, 0, MDL
);
877 /* If we didn't get an option structure, it's an undefined option. */
882 /* If we've been told to allocate, that means that this
883 (might) be an option code definition, so we'll create
884 an option structure just in case. */
886 option
= new_option (MDL
);
888 option
-> name
= val
;
892 s
= dmalloc (strlen (val
) + 1, MDL
);
894 log_fatal ("no memory for option %s.%s",
895 universe
-> name
, val
);
899 option
-> universe
= universe
;
904 parse_warn (cfile
, "no option named %s", val
);
906 parse_warn (cfile
, "no option named %s in space %s",
908 skip_to_semi (cfile
);
909 return (struct option
*)0;
912 /* Free the initial identifier token. */
917 /* IDENTIFIER SEMI */
919 void parse_option_space_decl (cfile
)
924 struct universe
**ua
, *nu
;
927 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
928 which was checked by the
930 token
= next_token (&val
, (unsigned *)0, cfile
);
931 if (!is_identifier (token
)) {
932 parse_warn (cfile
, "expecting identifier.");
933 skip_to_semi (cfile
);
936 nu
= new_universe (MDL
);
938 log_fatal ("No memory for new option space.");
940 /* Set up the server option universe... */
941 s
= dmalloc (strlen (val
) + 1, MDL
);
943 log_fatal ("No memory for new option space name.");
946 nu
-> lookup_func
= lookup_hashed_option
;
947 nu
-> option_state_dereference
=
948 hashed_option_state_dereference
;
949 nu
-> foreach
= hashed_option_space_foreach
;
950 nu
-> save_func
= save_hashed_option
;
951 nu
-> delete_func
= delete_hashed_option
;
952 nu
-> encapsulate
= hashed_option_space_encapsulate
;
953 nu
-> decode
= parse_option_buffer
;
954 nu
-> length_size
= 1;
956 nu
-> store_tag
= putUChar
;
957 nu
-> store_length
= putUChar
;
958 nu
-> index
= universe_count
++;
959 if (nu
-> index
>= universe_max
) {
960 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
962 log_fatal ("No memory to expand option space array.");
963 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
965 dfree (universes
, MDL
);
968 universes
[nu
-> index
] = nu
;
969 option_new_hash (&nu
-> hash
, 1, MDL
);
971 log_fatal ("Can't allocate %s option hash table.", nu
-> name
);
972 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
976 /* This is faked up to look good right now. Ideally, this should do a
977 recursive parse and allow arbitrary data structure definitions, but for
978 now it just allows you to specify a single type, an array of single types,
979 a sequence of types, or an array of sequences of types.
981 ocd :== NUMBER EQUALS ocsd SEMI
985 ARRAY OF ocsd_simple_type_sequence
987 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
989 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
991 ocsd_types :== ocsd_type |
994 ocsd_type :== ocsd_simple_type |
995 ARRAY OF ocsd_simple_type
997 ocsd_simple_types :== ocsd_simple_type |
998 ocsd_simple_types ocsd_simple_type
1000 ocsd_simple_type :== BOOLEAN |
1002 SIGNED INTEGER NUMBER |
1003 UNSIGNED INTEGER NUMBER |
1007 ENCAPSULATE identifier */
1009 int parse_option_code_definition (cfile
, option
)
1010 struct parse
*cfile
;
1011 struct option
*option
;
1014 enum dhcp_token token
;
1015 unsigned arrayp
= 0;
1017 int no_more_in_record
= 0;
1023 int has_encapsulation
= 0;
1025 /* Parse the option code. */
1026 token
= next_token (&val
, (unsigned *)0, cfile
);
1027 if (token
!= NUMBER
) {
1028 parse_warn (cfile
, "expecting option code number.");
1029 skip_to_semi (cfile
);
1032 option
-> code
= atoi (val
);
1034 token
= next_token (&val
, (unsigned *)0, cfile
);
1035 if (token
!= EQUAL
) {
1036 parse_warn (cfile
, "expecting \"=\"");
1037 skip_to_semi (cfile
);
1041 /* See if this is an array. */
1042 token
= next_token (&val
, (unsigned *)0, cfile
);
1043 if (token
== ARRAY
) {
1044 token
= next_token (&val
, (unsigned *)0, cfile
);
1046 parse_warn (cfile
, "expecting \"of\".");
1047 skip_to_semi (cfile
);
1051 token
= next_token (&val
, (unsigned *)0, cfile
);
1054 if (token
== LBRACE
) {
1056 token
= next_token (&val
, (unsigned *)0, cfile
);
1059 /* At this point we're expecting a data type. */
1061 if (has_encapsulation
) {
1063 "encapsulate must always be the last item.");
1064 skip_to_semi (cfile
);
1071 parse_warn (cfile
, "no nested arrays.");
1072 skip_to_rbrace (cfile
, recordp
);
1074 skip_to_semi (cfile
);
1077 token
= next_token (&val
, (unsigned *)0, cfile
);
1079 parse_warn (cfile
, "expecting \"of\".");
1080 skip_to_semi (cfile
);
1083 arrayp
= recordp
+ 1;
1084 token
= next_token (&val
, (unsigned *)0, cfile
);
1085 if ((recordp
) && (token
== LBRACE
)) {
1087 "only uniform array inside record.");
1088 skip_to_rbrace (cfile
, recordp
+ 1);
1089 skip_to_semi (cfile
);
1099 token
= next_token (&val
, (unsigned *)0, cfile
);
1100 if (token
!= NUMBER
) {
1101 parse_warn (cfile
, "expecting number.");
1102 skip_to_rbrace (cfile
, recordp
);
1104 skip_to_semi (cfile
);
1107 switch (atoi (val
)) {
1109 type
= is_signed
? 'b' : 'B';
1112 type
= is_signed
? 's' : 'S';
1115 type
= is_signed
? 'l' : 'L';
1119 "%s bit precision is not supported.", val
);
1120 skip_to_rbrace (cfile
, recordp
);
1122 skip_to_semi (cfile
);
1129 token
= next_token (&val
, (unsigned *)0, cfile
);
1130 if (token
!= INTEGER
) {
1131 parse_warn (cfile
, "expecting \"integer\" keyword.");
1132 skip_to_rbrace (cfile
, recordp
);
1134 skip_to_semi (cfile
);
1152 parse_warn (cfile
, "arrays of text strings not %s",
1154 skip_to_rbrace (cfile
, recordp
);
1156 skip_to_semi (cfile
);
1159 no_more_in_record
= 1;
1166 token
= next_token (&val
, (unsigned *)0, cfile
);
1167 if (!is_identifier (token
)) {
1169 "expecting option space identifier");
1170 skip_to_semi (cfile
);
1173 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1175 tokbuf
[tokix
++] = 'E';
1176 strcpy (&tokbuf
[tokix
], val
);
1177 tokix
+= strlen (val
);
1179 has_encapsulation
= 1;
1183 parse_warn (cfile
, "unknown data type %s", val
);
1184 skip_to_rbrace (cfile
, recordp
);
1186 skip_to_semi (cfile
);
1190 if (tokix
== sizeof tokbuf
) {
1192 parse_warn (cfile
, "too many types in record.");
1193 skip_to_rbrace (cfile
, recordp
);
1195 skip_to_semi (cfile
);
1198 tokbuf
[tokix
++] = type
;
1201 token
= next_token (&val
, (unsigned *)0, cfile
);
1202 if (arrayp
> recordp
) {
1203 if (tokix
== sizeof tokbuf
) {
1205 "too many types in record.");
1206 skip_to_rbrace (cfile
, 1);
1207 skip_to_semi (cfile
);
1211 tokbuf
[tokix
++] = 'a';
1213 if (token
== COMMA
) {
1214 if (no_more_in_record
) {
1216 "%s must be at end of record.",
1217 type
== 't' ? "text" : "string");
1218 skip_to_rbrace (cfile
, 1);
1220 skip_to_semi (cfile
);
1223 token
= next_token (&val
, (unsigned *)0, cfile
);
1226 if (token
!= RBRACE
) {
1227 parse_warn (cfile
, "expecting right brace.");
1228 skip_to_rbrace (cfile
, 1);
1230 skip_to_semi (cfile
);
1234 if (!parse_semi (cfile
)) {
1235 parse_warn (cfile
, "semicolon expected.");
1236 skip_to_semi (cfile
);
1238 skip_to_semi (cfile
);
1241 if (has_encapsulation
&& arrayp
) {
1243 "Arrays of encapsulations don't make sense.");
1246 if (has_encapsulation
&& tokbuf
[0] == 'E')
1247 has_encapsulation
= 0;
1248 s
= dmalloc (tokix
+
1250 (has_encapsulation
? 1 : 0) + 1, MDL
);
1252 log_fatal ("no memory for option format.");
1253 if (has_encapsulation
)
1255 memcpy (s
+ has_encapsulation
, tokbuf
, tokix
);
1256 tokix
+= has_encapsulation
;
1258 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1260 option
-> format
= s
;
1261 if (option
-> universe
-> options
[option
-> code
]) {
1262 /* XXX Free the option, but we can't do that now because they
1263 XXX may start out static. */
1265 option
-> universe
-> options
[option
-> code
] = option
;
1266 option_hash_add (option
-> universe
-> hash
,
1267 (const char *)option
-> name
,
1273 * base64 :== NUMBER_OR_STRING
1276 int parse_base64 (data
, cfile
)
1277 struct data_string
*data
;
1278 struct parse
*cfile
;
1280 enum dhcp_token token
;
1284 static unsigned char
1285 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1286 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1287 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1288 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1289 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1290 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1291 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1292 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1293 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1294 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1295 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1296 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1297 struct string_list
*bufs
= (struct string_list
*)0,
1298 *last
= (struct string_list
*)0,
1303 /* It's possible for a + or a / to cause a base64 quantity to be
1304 tokenized into more than one token, so we have to parse them all
1305 in before decoding. */
1309 token
= next_token (&val
, &l
, cfile
);
1310 t
= dmalloc (l
+ sizeof *t
, MDL
);
1312 log_fatal ("no memory for base64 buffer.");
1313 memset (t
, 0, (sizeof *t
) - 1);
1314 memcpy (t
-> string
, val
, l
+ 1);
1321 token
= peek_token (&val
, (unsigned *)0, cfile
);
1322 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1323 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1327 data
-> len
= (data
-> len
* 3) / 4;
1328 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1329 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1331 data
-> data
= (unsigned char *)0;
1336 for (t
= bufs
; t
; t
= t
-> next
) {
1337 for (i
= 0; t
-> string
[i
]; i
++) {
1338 unsigned foo
= t
-> string
[i
];
1339 if (terminated
&& foo
!= '=') {
1341 "stuff after base64 '=' terminator: %s.",
1345 if (foo
< ' ' || foo
> 'z') {
1348 "invalid base64 character %d.",
1351 data_string_forget (data
, MDL
);
1357 foo
= from64
[foo
- ' '];
1360 acc
= (acc
<< 6) + foo
;
1365 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1370 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1374 data
-> buffer
-> data
[j
++] = acc
;
1385 "partial base64 value left over: %d.",
1390 data
-> data
= data
-> buffer
-> data
;
1392 for (t
= bufs
; t
; t
= last
) {
1404 * colon-seperated-hex-list :== NUMBER |
1405 * NUMBER COLON colon-seperated-hex-list
1408 int parse_cshl (data
, cfile
)
1409 struct data_string
*data
;
1410 struct parse
*cfile
;
1412 u_int8_t ibuf
[128];
1415 struct option_tag
*sl
= (struct option_tag
*)0;
1416 struct option_tag
*next
, **last
= &sl
;
1417 enum dhcp_token token
;
1422 token
= next_token (&val
, (unsigned *)0, cfile
);
1423 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1424 parse_warn (cfile
, "expecting hexadecimal number.");
1425 skip_to_semi (cfile
);
1426 for (; sl
; sl
= next
) {
1432 if (ilen
== sizeof ibuf
) {
1433 next
= (struct option_tag
*)
1435 sizeof (struct option_tag
), MDL
);
1437 log_fatal ("no memory for string list.");
1438 memcpy (next
-> data
, ibuf
, ilen
);
1440 last
= &next
-> next
;
1444 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1446 token
= peek_token (&val
, (unsigned *)0, cfile
);
1449 token
= next_token (&val
, (unsigned *)0, cfile
);
1452 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1453 log_fatal ("no memory to store octet data.");
1454 data
-> data
= &data
-> buffer
-> data
[0];
1455 data
-> len
= tlen
+ ilen
;
1456 data
-> terminated
= 0;
1458 rvp
= &data
-> buffer
-> data
[0];
1461 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
1467 memcpy (rvp
, ibuf
, ilen
);
1472 * executable-statements :== executable-statement executable-statements |
1473 * executable-statement
1475 * executable-statement :==
1477 * ADD class-name SEMI |
1479 * OPTION option-parameter SEMI |
1480 * SUPERSEDE option-parameter SEMI |
1481 * PREPEND option-parameter SEMI |
1482 * APPEND option-parameter SEMI
1485 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
1486 struct executable_statement
**statements
;
1487 struct parse
*cfile
;
1489 enum expression_context case_context
;
1491 struct executable_statement
**next
;
1494 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
1495 next
= &((*next
) -> next
);
1501 int parse_executable_statement (result
, cfile
, lose
, case_context
)
1502 struct executable_statement
**result
;
1503 struct parse
*cfile
;
1505 enum expression_context case_context
;
1507 enum dhcp_token token
;
1510 struct option
*option
;
1511 struct option_cache
*cache
;
1515 struct dns_zone
*zone
;
1516 isc_result_t status
;
1519 token
= peek_token (&val
, (unsigned *)0, cfile
);
1522 next_token (&val
, (unsigned *)0, cfile
);
1523 return parse_if_statement (result
, cfile
, lose
);
1526 token
= next_token (&val
, (unsigned *)0, cfile
);
1527 token
= next_token (&val
, (unsigned *)0, cfile
);
1528 if (token
!= STRING
) {
1529 parse_warn (cfile
, "expecting class name.");
1530 skip_to_semi (cfile
);
1534 cta
= (struct class *)0;
1535 status
= find_class (&cta
, val
, MDL
);
1536 if (status
!= ISC_R_SUCCESS
) {
1537 parse_warn (cfile
, "class %s: %s",
1538 val
, isc_result_totext (status
));
1539 skip_to_semi (cfile
);
1543 if (!parse_semi (cfile
)) {
1547 if (!executable_statement_allocate (result
, MDL
))
1548 log_fatal ("no memory for new statement.");
1549 (*result
) -> op
= add_statement
;
1550 (*result
) -> data
.add
= cta
;
1554 token
= next_token (&val
, (unsigned *)0, cfile
);
1555 if (!parse_semi (cfile
)) {
1559 if (!executable_statement_allocate (result
, MDL
))
1560 log_fatal ("no memory for new statement.");
1561 (*result
) -> op
= break_statement
;
1565 token
= next_token (&val
, (unsigned *)0, cfile
);
1567 option
= parse_option_name (cfile
, 0, &known
);
1572 return parse_option_statement (result
, cfile
, 1, option
,
1573 send_option_statement
);
1577 token
= next_token (&val
, (unsigned *)0, cfile
);
1579 option
= parse_option_name (cfile
, 0, &known
);
1584 return parse_option_statement (result
, cfile
, 1, option
,
1585 supersede_option_statement
);
1596 token
= next_token (&val
, (unsigned *)0, cfile
);
1597 cache
= (struct option_cache
*)0;
1598 if (!parse_allow_deny (&cache
, cfile
, flag
))
1600 if (!executable_statement_allocate (result
, MDL
))
1601 log_fatal ("no memory for new statement.");
1602 (*result
) -> op
= supersede_option_statement
;
1603 (*result
) -> data
.option
= cache
;
1607 token
= next_token (&val
, (unsigned *)0, cfile
);
1608 token
= peek_token (&val
, (unsigned *)0, cfile
);
1610 goto switch_default
;
1612 option
= parse_option_name (cfile
, 0, &known
);
1617 return parse_option_statement (result
, cfile
, 1, option
,
1618 default_option_statement
);
1621 token
= next_token (&val
, (unsigned *)0, cfile
);
1623 option
= parse_option_name (cfile
, 0, &known
);
1628 return parse_option_statement (result
, cfile
, 1, option
,
1629 prepend_option_statement
);
1632 token
= next_token (&val
, (unsigned *)0, cfile
);
1634 option
= parse_option_name (cfile
, 0, &known
);
1639 return parse_option_statement (result
, cfile
, 1, option
,
1640 append_option_statement
);
1643 token
= next_token (&val
, (unsigned *)0, cfile
);
1644 return parse_on_statement (result
, cfile
, lose
);
1647 token
= next_token (&val
, (unsigned *)0, cfile
);
1648 return parse_switch_statement (result
, cfile
, lose
);
1651 token
= next_token (&val
, (unsigned *)0, cfile
);
1652 if (case_context
== context_any
) {
1654 "case statement in inappropriate scope.");
1656 skip_to_semi (cfile
);
1659 return parse_case_statement (result
,
1660 cfile
, lose
, case_context
);
1663 token
= next_token (&val
, (unsigned *)0, cfile
);
1664 if (case_context
== context_any
) {
1665 parse_warn (cfile
, "switch default statement in %s",
1666 "inappropriate scope.");
1671 if (!executable_statement_allocate (result
, MDL
))
1672 log_fatal ("no memory for default statement.");
1673 (*result
) -> op
= default_statement
;
1679 token
= next_token (&val
, (unsigned *)0, cfile
);
1680 if (token
== DEFINE
)
1685 token
= next_token (&val
, (unsigned *)0, cfile
);
1686 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1688 "%s can't be a variable name", val
);
1690 skip_to_semi (cfile
);
1695 if (!executable_statement_allocate (result
, MDL
))
1696 log_fatal ("no memory for set statement.");
1697 (*result
) -> op
= flag
? define_statement
: set_statement
;
1698 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
1699 if (!(*result
)->data
.set
.name
)
1700 log_fatal ("can't allocate variable name");
1701 strcpy ((*result
) -> data
.set
.name
, val
);
1702 token
= next_token (&val
, (unsigned *)0, cfile
);
1704 if (token
== LPAREN
) {
1705 struct string_list
*head
, *cur
, *new;
1706 struct expression
*expr
;
1707 head
= cur
= (struct string_list
*)0;
1709 token
= next_token (&val
,
1710 (unsigned *)0, cfile
);
1711 if (token
== RPAREN
)
1713 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1715 "expecting argument name");
1716 skip_to_rbrace (cfile
, 0);
1718 executable_statement_dereference
1722 new = ((struct string_list
*)
1723 dmalloc (sizeof (struct string_list
) +
1724 strlen (val
), MDL
));
1726 log_fatal ("can't allocate string.");
1727 memset (new, 0, sizeof *new);
1728 strcpy (new -> string
, val
);
1735 token
= next_token (&val
,
1736 (unsigned *)0, cfile
);
1737 } while (token
== COMMA
);
1739 if (token
!= RPAREN
) {
1740 parse_warn (cfile
, "expecting right paren.");
1742 skip_to_semi (cfile
);
1744 executable_statement_dereference (result
, MDL
);
1748 token
= next_token (&val
, (unsigned *)0, cfile
);
1749 if (token
!= LBRACE
) {
1750 parse_warn (cfile
, "expecting left brace.");
1754 expr
= (struct expression
*)0;
1755 if (!(expression_allocate (&expr
, MDL
)))
1756 log_fatal ("can't allocate expression.");
1757 expr
-> op
= expr_function
;
1758 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
1759 log_fatal ("can't allocate fundef.");
1760 expr
-> data
.func
-> args
= head
;
1761 (*result
) -> data
.set
.expr
= expr
;
1763 if (!(parse_executable_statements
1764 (&expr
-> data
.func
-> statements
, cfile
, lose
,
1770 token
= next_token (&val
, (unsigned *)0, cfile
);
1771 if (token
!= RBRACE
) {
1772 parse_warn (cfile
, "expecting rigt brace.");
1776 if (token
!= EQUAL
) {
1778 "expecting '=' in %s statement.",
1779 flag
? "define" : "set");
1783 if (!parse_expression (&(*result
) -> data
.set
.expr
,
1784 cfile
, lose
, context_any
,
1785 (struct expression
**)0,
1789 "expecting expression.");
1792 skip_to_semi (cfile
);
1793 executable_statement_dereference (result
, MDL
);
1796 if (!parse_semi (cfile
)) {
1798 executable_statement_dereference (result
, MDL
);
1805 token
= next_token (&val
, (unsigned *)0, cfile
);
1807 token
= next_token (&val
, (unsigned *)0, cfile
);
1808 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1810 "%s can't be a variable name", val
);
1811 skip_to_semi (cfile
);
1816 if (!executable_statement_allocate (result
, MDL
))
1817 log_fatal ("no memory for set statement.");
1818 (*result
) -> op
= unset_statement
;
1819 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
1820 if (!(*result
)->data
.unset
)
1821 log_fatal ("can't allocate variable name");
1822 strcpy ((*result
) -> data
.unset
, val
);
1823 if (!parse_semi (cfile
)) {
1825 executable_statement_dereference (result
, MDL
);
1831 token
= next_token (&val
, (unsigned *)0, cfile
);
1833 if (!executable_statement_allocate (result
, MDL
))
1834 log_fatal ("no memory for eval statement.");
1835 (*result
) -> op
= eval_statement
;
1837 if (!parse_expression (&(*result
) -> data
.eval
,
1838 cfile
, lose
, context_data
, /* XXX */
1839 (struct expression
**)0, expr_none
)) {
1842 "expecting data expression.");
1845 skip_to_semi (cfile
);
1846 executable_statement_dereference (result
, MDL
);
1849 if (!parse_semi (cfile
)) {
1851 executable_statement_dereference (result
, MDL
);
1856 token
= next_token (&val
, (unsigned *)0, cfile
);
1858 if (!executable_statement_allocate (result
, MDL
))
1859 log_fatal ("no memory for return statement.");
1860 (*result
) -> op
= return_statement
;
1862 if (!parse_expression (&(*result
) -> data
.retval
,
1863 cfile
, lose
, context_data
,
1864 (struct expression
**)0, expr_none
)) {
1867 "expecting data expression.");
1870 skip_to_semi (cfile
);
1871 executable_statement_dereference (result
, MDL
);
1874 if (!parse_semi (cfile
)) {
1876 executable_statement_dereference (result
, MDL
);
1882 token
= next_token (&val
, (unsigned *)0, cfile
);
1884 if (!executable_statement_allocate (result
, MDL
))
1885 log_fatal ("no memory for log statement.");
1886 (*result
) -> op
= log_statement
;
1888 token
= next_token (&val
, (unsigned *)0, cfile
);
1889 if (token
!= LPAREN
) {
1890 parse_warn (cfile
, "left parenthesis expected.");
1891 skip_to_semi (cfile
);
1896 token
= peek_token (&val
, (unsigned *)0, cfile
);
1898 if (token
== FATAL
) {
1899 (*result
) -> data
.log
.priority
= log_priority_fatal
;
1900 } else if (token
== ERROR
) {
1901 (*result
) -> data
.log
.priority
= log_priority_error
;
1902 } else if (token
== TOKEN_DEBUG
) {
1903 (*result
) -> data
.log
.priority
= log_priority_debug
;
1904 } else if (token
== INFO
) {
1905 (*result
) -> data
.log
.priority
= log_priority_info
;
1907 (*result
) -> data
.log
.priority
= log_priority_debug
;
1911 token
= next_token (&val
, (unsigned *)0, cfile
);
1912 token
= next_token (&val
, (unsigned *)0, cfile
);
1913 if (token
!= COMMA
) {
1914 parse_warn (cfile
, "comma expected.");
1915 skip_to_semi (cfile
);
1921 if (!(parse_data_expression
1922 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
1923 skip_to_semi (cfile
);
1928 token
= next_token (&val
, (unsigned *)0, cfile
);
1929 if (token
!= RPAREN
) {
1930 parse_warn (cfile
, "right parenthesis expected.");
1931 skip_to_semi (cfile
);
1936 token
= next_token (&val
, (unsigned *)0, cfile
);
1937 if (token
!= SEMI
) {
1938 parse_warn (cfile
, "semicolon expected.");
1939 skip_to_semi (cfile
);
1945 /* Not really a statement, but we parse it here anyway
1946 because it's appropriate for all DHCP agents with
1949 token
= next_token (&val
, (unsigned *)0, cfile
);
1950 zone
= (struct dns_zone
*)0;
1951 if (!dns_zone_allocate (&zone
, MDL
))
1952 log_fatal ("no memory for new zone.");
1953 zone
-> name
= parse_host_name (cfile
);
1954 if (!zone
-> name
) {
1955 parse_warn (cfile
, "expecting hostname.");
1958 skip_to_semi (cfile
);
1959 dns_zone_dereference (&zone
, MDL
);
1962 i
= strlen (zone
-> name
);
1963 if (zone
-> name
[i
- 1] != '.') {
1964 s
= dmalloc ((unsigned)i
+ 2, MDL
);
1966 parse_warn (cfile
, "no trailing '.' on zone");
1969 strcpy (s
, zone
-> name
);
1972 dfree (zone
-> name
, MDL
);
1975 if (!parse_zone (zone
, cfile
))
1977 status
= enter_dns_zone (zone
);
1978 if (status
!= ISC_R_SUCCESS
) {
1979 parse_warn (cfile
, "dns zone key %s: %s",
1980 zone
-> name
, isc_result_totext (status
));
1981 dns_zone_dereference (&zone
, MDL
);
1984 dns_zone_dereference (&zone
, MDL
);
1987 /* Also not really a statement, but same idea as above. */
1988 #if !defined (SMALL)
1990 token
= next_token (&val
, (unsigned *)0, cfile
);
1991 if (!parse_key (cfile
)) {
1999 if (config_universe
&& is_identifier (token
)) {
2000 option
= (struct option
*)0;
2001 option_hash_lookup (&option
, config_universe
-> hash
,
2004 token
= next_token (&val
,
2005 (unsigned *)0, cfile
);
2006 return parse_option_statement
2007 (result
, cfile
, 1, option
,
2008 supersede_option_statement
);
2012 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2013 /* This is rather ugly. Since function calls are
2014 data expressions, fake up an eval statement. */
2015 if (!executable_statement_allocate (result
, MDL
))
2016 log_fatal ("no memory for eval statement.");
2017 (*result
) -> op
= eval_statement
;
2019 if (!parse_expression (&(*result
) -> data
.eval
,
2020 cfile
, lose
, context_data
,
2021 (struct expression
**)0,
2024 parse_warn (cfile
, "expecting "
2028 skip_to_semi (cfile
);
2029 executable_statement_dereference (result
, MDL
);
2032 if (!parse_semi (cfile
)) {
2034 executable_statement_dereference (result
, MDL
);
2047 /* zone-statements :== zone-statement |
2048 zone-statement zone-statements
2050 PRIMARY ip-addresses SEMI |
2051 SECONDARY ip-addresses SEMI |
2053 ip-addresses :== ip-addr-or-hostname |
2054 ip-addr-or-hostname COMMA ip-addresses
2055 key-reference :== KEY STRING |
2058 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2063 struct option_cache
*oc
;
2066 token
= next_token (&val
, (unsigned *)0, cfile
);
2067 if (token
!= LBRACE
) {
2068 parse_warn (cfile
, "expecting left brace");
2073 token
= peek_token (&val
, (unsigned *)0, cfile
);
2076 if (zone
-> primary
) {
2078 "more than one primary.");
2079 skip_to_semi (cfile
);
2082 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2083 log_fatal ("can't allocate primary option cache.");
2084 oc
= zone
-> primary
;
2088 if (zone
-> secondary
) {
2089 parse_warn (cfile
, "more than one secondary.");
2090 skip_to_semi (cfile
);
2093 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2094 log_fatal ("can't allocate secondary.");
2095 oc
= zone
-> secondary
;
2097 token
= next_token (&val
, (unsigned *)0, cfile
);
2099 struct expression
*expr
= (struct expression
*)0;
2100 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2102 "expecting IP addr or hostname.");
2103 skip_to_semi (cfile
);
2106 if (oc
-> expression
) {
2107 struct expression
*old
=
2108 (struct expression
*)0;
2109 expression_reference (&old
,
2112 expression_dereference (&oc
-> expression
,
2114 if (!make_concat (&oc
-> expression
,
2116 log_fatal ("no memory for concat.");
2117 expression_dereference (&expr
, MDL
);
2118 expression_dereference (&old
, MDL
);
2120 expression_reference (&oc
-> expression
,
2122 expression_dereference (&expr
, MDL
);
2124 token
= next_token (&val
, (unsigned *)0, cfile
);
2125 } while (token
== COMMA
);
2126 if (token
!= SEMI
) {
2127 parse_warn (cfile
, "expecting semicolon.");
2128 skip_to_semi (cfile
);
2133 #if !defined (SMALL)
2135 token
= next_token (&val
, (unsigned *)0, cfile
);
2136 token
= peek_token (&val
, (unsigned *)0, cfile
);
2137 if (token
== STRING
) {
2138 token
= next_token (&val
, (unsigned *)0, cfile
);
2139 key_name
= (char *)0;
2141 key_name
= parse_host_name (cfile
);
2143 parse_warn (cfile
, "expecting key name.");
2144 skip_to_semi (cfile
);
2149 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2151 parse_warn (cfile
, "unknown key %s", val
);
2153 dfree (key_name
, MDL
);
2154 if (!parse_semi (cfile
))
2165 token
= next_token (&val
, (unsigned *)0, cfile
);
2166 if (token
!= RBRACE
) {
2167 parse_warn (cfile
, "expecting right brace.");
2173 /* key-statements :== key-statement |
2174 key-statement key-statements
2176 ALGORITHM host-name SEMI |
2177 secret-definition SEMI
2178 secret-definition :== SECRET base64val |
2181 #if !defined (SMALL)
2182 int parse_key (struct parse
*cfile
)
2187 struct auth_key
*key
;
2188 struct data_string ds
;
2189 isc_result_t status
;
2192 key
= (struct auth_key
*)0;
2193 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2194 log_fatal ("no memory for key");
2196 token
= peek_token (&val
, (unsigned *)0, cfile
);
2197 if (token
== STRING
) {
2198 token
= next_token (&val
, (unsigned *)0, cfile
);
2199 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2201 log_fatal ("no memory for key name.");
2202 strcpy (key
-> name
, val
);
2205 key
-> name
= parse_host_name (cfile
);
2207 parse_warn (cfile
, "expecting key name.");
2208 skip_to_semi (cfile
);
2213 token
= next_token (&val
, (unsigned *)0, cfile
);
2214 if (token
!= LBRACE
) {
2215 parse_warn (cfile
, "expecting left brace");
2220 token
= next_token (&val
, (unsigned *)0, cfile
);
2223 if (key
-> algorithm
) {
2225 "key %s: too many algorithms",
2229 key
-> algorithm
= parse_host_name (cfile
);
2230 if (!key
-> algorithm
) {
2232 "expecting key algorithm name.");
2235 if (!parse_semi (cfile
))
2237 /* If the algorithm name isn't an FQDN, tack on
2238 the .SIG-ALG.REG.NET. domain. */
2239 s
= strrchr (key
-> algorithm
, '.');
2241 static char add
[] = ".SIG-ALG.REG.INT.";
2242 s
= dmalloc (strlen (key
-> algorithm
) +
2245 log_error ("no memory for key %s.",
2249 strcpy (s
, key
-> algorithm
);
2251 dfree (key
-> algorithm
, MDL
);
2252 key
-> algorithm
= s
;
2254 /* If there is no trailing '.', hack one in. */
2255 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2257 log_error ("no memory for key %s.",
2261 strcpy (s
, key
-> algorithm
);
2263 dfree (key
-> algorithm
, MDL
);
2264 key
-> algorithm
= s
;
2270 parse_warn (cfile
, "key %s: too many secrets",
2275 memset (&ds
, 0, sizeof(ds
));
2276 if (!parse_base64 (&ds
, cfile
))
2278 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2280 if (status
!= ISC_R_SUCCESS
)
2282 memcpy (key
-> key
-> value
,
2283 ds
.buffer
-> data
, ds
.len
);
2284 data_string_forget (&ds
, MDL
);
2286 if (!parse_semi (cfile
))
2295 if (token
!= RBRACE
) {
2296 parse_warn (cfile
, "expecting right brace.");
2299 /* Allow the BIND 8 syntax, which has a semicolon after each
2301 token
= peek_token (&val
, (unsigned *)0, cfile
);
2303 token
= next_token (&val
, (unsigned *)0, cfile
);
2305 /* Remember the key. */
2306 status
= omapi_auth_key_enter (key
);
2307 if (status
!= ISC_R_SUCCESS
) {
2308 parse_warn (cfile
, "tsig key %s: %s",
2309 key
-> name
, isc_result_totext (status
));
2312 omapi_auth_key_dereference (&key
, MDL
);
2316 skip_to_rbrace (cfile
, 1);
2318 omapi_auth_key_dereference (&key
, MDL
);
2324 * on-statement :== event-types LBRACE executable-statements RBRACE
2325 * event-types :== event-type OR event-types |
2327 * event-type :== EXPIRY | COMMIT | RELEASE
2330 int parse_on_statement (result
, cfile
, lose
)
2331 struct executable_statement
**result
;
2332 struct parse
*cfile
;
2335 enum dhcp_token token
;
2338 if (!executable_statement_allocate (result
, MDL
))
2339 log_fatal ("no memory for new statement.");
2340 (*result
) -> op
= on_statement
;
2343 token
= next_token (&val
, (unsigned *)0, cfile
);
2346 (*result
) -> data
.on
.evtypes
|= ON_EXPIRY
;
2350 (*result
) -> data
.on
.evtypes
|= ON_COMMIT
;
2354 (*result
) -> data
.on
.evtypes
|= ON_RELEASE
;
2358 (*result
) -> data
.on
.evtypes
|= ON_TRANSMISSION
;
2362 parse_warn (cfile
, "expecting a lease event type");
2363 skip_to_semi (cfile
);
2365 executable_statement_dereference (result
, MDL
);
2368 token
= next_token (&val
, (unsigned *)0, cfile
);
2369 } while (token
== OR
);
2371 /* Semicolon means no statements. */
2375 if (token
!= LBRACE
) {
2376 parse_warn (cfile
, "left brace expected.");
2377 skip_to_semi (cfile
);
2379 executable_statement_dereference (result
, MDL
);
2382 if (!parse_executable_statements (&(*result
) -> data
.on
.statements
,
2383 cfile
, lose
, context_any
)) {
2385 /* Try to even things up. */
2387 token
= next_token (&val
,
2388 (unsigned *)0, cfile
);
2389 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
2390 executable_statement_dereference (result
, MDL
);
2394 token
= next_token (&val
, (unsigned *)0, cfile
);
2395 if (token
!= RBRACE
) {
2396 parse_warn (cfile
, "right brace expected.");
2397 skip_to_semi (cfile
);
2399 executable_statement_dereference (result
, MDL
);
2406 * switch-statement :== LPAREN expr RPAREN LBRACE executable-statements RBRACE
2410 int parse_switch_statement (result
, cfile
, lose
)
2411 struct executable_statement
**result
;
2412 struct parse
*cfile
;
2415 enum dhcp_token token
;
2418 if (!executable_statement_allocate (result
, MDL
))
2419 log_fatal ("no memory for new statement.");
2420 (*result
) -> op
= switch_statement
;
2422 token
= next_token (&val
, (unsigned *)0, cfile
);
2423 if (token
!= LPAREN
) {
2424 parse_warn (cfile
, "expecting left brace.");
2427 skip_to_semi (cfile
);
2429 executable_statement_dereference (result
, MDL
);
2433 if (!parse_expression (&(*result
) -> data
.s_switch
.expr
,
2434 cfile
, lose
, context_data_or_numeric
,
2435 (struct expression
**)0, expr_none
)) {
2438 "expecting data or numeric expression.");
2444 token
= next_token (&val
, (unsigned *)0, cfile
);
2445 if (token
!= RPAREN
) {
2446 parse_warn (cfile
, "right paren expected.");
2450 token
= next_token (&val
, (unsigned *)0, cfile
);
2451 if (token
!= LBRACE
) {
2452 parse_warn (cfile
, "left brace expected.");
2455 if (!(parse_executable_statements
2456 (&(*result
) -> data
.s_switch
.statements
, cfile
, lose
,
2457 (is_data_expression ((*result
) -> data
.s_switch
.expr
)
2458 ? context_data
: context_numeric
)))) {
2460 skip_to_rbrace (cfile
, 1);
2461 executable_statement_dereference (result
, MDL
);
2465 token
= next_token (&val
, (unsigned *)0, cfile
);
2466 if (token
!= RBRACE
) {
2467 parse_warn (cfile
, "right brace expected.");
2474 * case-statement :== CASE expr COLON
2478 int parse_case_statement (result
, cfile
, lose
, case_context
)
2479 struct executable_statement
**result
;
2480 struct parse
*cfile
;
2482 enum expression_context case_context
;
2484 enum dhcp_token token
;
2487 if (!executable_statement_allocate (result
, MDL
))
2488 log_fatal ("no memory for new statement.");
2489 (*result
) -> op
= case_statement
;
2491 if (!parse_expression (&(*result
) -> data
.c_case
,
2492 cfile
, lose
, case_context
,
2493 (struct expression
**)0, expr_none
))
2496 parse_warn (cfile
, "expecting %s expression.",
2497 (case_context
== context_data
2498 ? "data" : "numeric"));
2502 skip_to_semi (cfile
);
2503 executable_statement_dereference (result
, MDL
);
2507 token
= next_token (&val
, (unsigned *)0, cfile
);
2508 if (token
!= COLON
) {
2509 parse_warn (cfile
, "colon expected.");
2516 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
2519 * else-statement :== <null> |
2520 * ELSE LBRACE executable-statements RBRACE |
2521 * ELSE IF if-statement |
2522 * ELSIF if-statement
2525 int parse_if_statement (result
, cfile
, lose
)
2526 struct executable_statement
**result
;
2527 struct parse
*cfile
;
2530 enum dhcp_token token
;
2534 if (!executable_statement_allocate (result
, MDL
))
2535 log_fatal ("no memory for if statement.");
2537 (*result
) -> op
= if_statement
;
2539 token
= peek_token (&val
, (unsigned *)0, cfile
);
2540 if (token
== LPAREN
) {
2542 next_token (&val
, (unsigned *)0, cfile
);
2547 if (!parse_boolean_expression (&(*result
) -> data
.ie
.expr
,
2550 parse_warn (cfile
, "boolean expression expected.");
2551 executable_statement_dereference (result
, MDL
);
2555 #if defined (DEBUG_EXPRESSION_PARSE)
2556 print_expression ("if condition", (*result
) -> data
.ie
.expr
);
2559 token
= next_token (&val
, (unsigned *)0, cfile
);
2560 if (token
!= RPAREN
) {
2561 parse_warn (cfile
, "expecting right paren.");
2563 executable_statement_dereference (result
, MDL
);
2567 token
= next_token (&val
, (unsigned *)0, cfile
);
2568 if (token
!= LBRACE
) {
2569 parse_warn (cfile
, "left brace expected.");
2570 skip_to_semi (cfile
);
2572 executable_statement_dereference (result
, MDL
);
2575 if (!parse_executable_statements (&(*result
) -> data
.ie
.tc
,
2576 cfile
, lose
, context_any
)) {
2578 /* Try to even things up. */
2580 token
= next_token (&val
,
2581 (unsigned *)0, cfile
);
2582 } while (token
!= END_OF_FILE
&& token
!= RBRACE
);
2583 executable_statement_dereference (result
, MDL
);
2587 token
= next_token (&val
, (unsigned *)0, cfile
);
2588 if (token
!= RBRACE
) {
2589 parse_warn (cfile
, "right brace expected.");
2590 skip_to_semi (cfile
);
2592 executable_statement_dereference (result
, MDL
);
2595 token
= peek_token (&val
, (unsigned *)0, cfile
);
2596 if (token
== ELSE
) {
2597 token
= next_token (&val
, (unsigned *)0, cfile
);
2598 token
= peek_token (&val
, (unsigned *)0, cfile
);
2600 token
= next_token (&val
, (unsigned *)0, cfile
);
2601 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
2605 "expecting if statement");
2606 executable_statement_dereference (result
, MDL
);
2610 } else if (token
!= LBRACE
) {
2611 parse_warn (cfile
, "left brace or if expected.");
2612 skip_to_semi (cfile
);
2614 executable_statement_dereference (result
, MDL
);
2617 token
= next_token (&val
, (unsigned *)0, cfile
);
2618 if (!(parse_executable_statements
2619 (&(*result
) -> data
.ie
.fc
,
2620 cfile
, lose
, context_any
))) {
2621 executable_statement_dereference (result
, MDL
);
2624 token
= next_token (&val
, (unsigned *)0, cfile
);
2625 if (token
!= RBRACE
) {
2626 parse_warn (cfile
, "right brace expected.");
2627 skip_to_semi (cfile
);
2629 executable_statement_dereference (result
, MDL
);
2633 } else if (token
== ELSIF
) {
2634 token
= next_token (&val
, (unsigned *)0, cfile
);
2635 if (!parse_if_statement (&(*result
) -> data
.ie
.fc
,
2639 "expecting conditional.");
2640 executable_statement_dereference (result
, MDL
);
2645 (*result
) -> data
.ie
.fc
= (struct executable_statement
*)0;
2651 * boolean_expression :== CHECK STRING |
2652 * NOT boolean-expression |
2653 * data-expression EQUAL data-expression |
2654 * data-expression BANG EQUAL data-expression |
2655 * boolean-expression AND boolean-expression |
2656 * boolean-expression OR boolean-expression
2657 * EXISTS OPTION-NAME
2660 int parse_boolean_expression (expr
, cfile
, lose
)
2661 struct expression
**expr
;
2662 struct parse
*cfile
;
2665 /* Parse an expression... */
2666 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
2667 (struct expression
**)0, expr_none
))
2670 if (!is_boolean_expression (*expr
) &&
2671 (*expr
) -> op
!= expr_variable_reference
&&
2672 (*expr
) -> op
!= expr_funcall
) {
2673 parse_warn (cfile
, "Expecting a boolean expression.");
2675 expression_dereference (expr
, MDL
);
2682 * data_expression :== SUBSTRING LPAREN data-expression COMMA
2683 * numeric-expression COMMA
2684 * numeric-expression RPAREN |
2685 * CONCAT LPAREN data-expression COMMA
2686 data-expression RPAREN
2687 * SUFFIX LPAREN data_expression COMMA
2688 * numeric-expression RPAREN |
2689 * OPTION option_name |
2691 * PACKET LPAREN numeric-expression COMMA
2692 * numeric-expression RPAREN |
2694 * colon_seperated_hex_list
2697 int parse_data_expression (expr
, cfile
, lose
)
2698 struct expression
**expr
;
2699 struct parse
*cfile
;
2702 /* Parse an expression... */
2703 if (!parse_expression (expr
, cfile
, lose
, context_data
,
2704 (struct expression
**)0, expr_none
))
2707 if (!is_data_expression (*expr
) &&
2708 (*expr
) -> op
!= expr_variable_reference
&&
2709 (*expr
) -> op
!= expr_funcall
) {
2710 expression_dereference (expr
, MDL
);
2711 parse_warn (cfile
, "Expecting a data expression.");
2719 * numeric-expression :== EXTRACT_INT LPAREN data-expression
2720 * COMMA number RPAREN |
2724 int parse_numeric_expression (expr
, cfile
, lose
)
2725 struct expression
**expr
;
2726 struct parse
*cfile
;
2729 /* Parse an expression... */
2730 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
2731 (struct expression
**)0, expr_none
))
2734 if (!is_numeric_expression (*expr
) &&
2735 (*expr
) -> op
!= expr_variable_reference
&&
2736 (*expr
) -> op
!= expr_funcall
) {
2737 expression_dereference (expr
, MDL
);
2738 parse_warn (cfile
, "Expecting a numeric expression.");
2746 * dns-expression :==
2747 * UPDATE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2748 * data-expression COMMA numeric-expression RPAREN
2749 * DELETE LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2750 * data-expression RPAREN
2751 * EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2752 * data-expression RPAREN
2753 * NOT EXISTS LPAREN ns-class COMMA ns-type COMMA data-expression COMMA
2754 * data-expression RPAREN
2755 * ns-class :== IN | CHAOS | HS | NUMBER
2756 * ns-type :== A | PTR | MX | TXT | NUMBER
2759 int parse_dns_expression (expr
, cfile
, lose
)
2760 struct expression
**expr
;
2761 struct parse
*cfile
;
2764 /* Parse an expression... */
2765 if (!parse_expression (expr
, cfile
, lose
, context_dns
,
2766 (struct expression
**)0, expr_none
))
2769 if (!is_dns_expression (*expr
) &&
2770 (*expr
) -> op
!= expr_variable_reference
&&
2771 (*expr
) -> op
!= expr_funcall
) {
2772 expression_dereference (expr
, MDL
);
2773 parse_warn (cfile
, "Expecting a dns update subexpression.");
2780 /* Parse a subexpression that does not contain a binary operator. */
2782 int parse_non_binary (expr
, cfile
, lose
, context
)
2783 struct expression
**expr
;
2784 struct parse
*cfile
;
2786 enum expression_context context
;
2788 enum dhcp_token token
;
2790 struct collection
*col
;
2791 struct expression
*nexp
, **ep
;
2793 enum expr_op opcode
;
2799 token
= peek_token (&val
, (unsigned *)0, cfile
);
2801 /* Check for unary operators... */
2804 token
= next_token (&val
, (unsigned *)0, cfile
);
2805 token
= next_token (&val
, (unsigned *)0, cfile
);
2806 if (token
!= STRING
) {
2807 parse_warn (cfile
, "string expected.");
2808 skip_to_semi (cfile
);
2812 for (col
= collections
; col
; col
= col
-> next
)
2813 if (!strcmp (col
-> name
, val
))
2816 parse_warn (cfile
, "unknown collection.");
2820 if (!expression_allocate (expr
, MDL
))
2821 log_fatal ("can't allocate expression");
2822 (*expr
) -> op
= expr_check
;
2823 (*expr
) -> data
.check
= col
;
2827 token
= next_token (&val
, (unsigned *)0, cfile
);
2828 if (context
== context_dns
) {
2829 token
= peek_token (&val
, (unsigned *)0, cfile
);
2832 if (!expression_allocate (expr
, MDL
))
2833 log_fatal ("can't allocate expression");
2834 (*expr
) -> op
= expr_not
;
2835 if (!parse_non_binary (&(*expr
) -> data
.not,
2836 cfile
, lose
, context_boolean
)) {
2838 parse_warn (cfile
, "expression expected");
2839 skip_to_semi (cfile
);
2842 expression_dereference (expr
, MDL
);
2845 if (!is_boolean_expression ((*expr
) -> data
.not)) {
2847 parse_warn (cfile
, "boolean expression expected");
2848 skip_to_semi (cfile
);
2849 expression_dereference (expr
, MDL
);
2855 token
= next_token (&val
, (unsigned *)0, cfile
);
2856 if (!parse_expression (expr
, cfile
, lose
, context
,
2857 (struct expression
**)0, expr_none
)) {
2859 parse_warn (cfile
, "expression expected");
2860 skip_to_semi (cfile
);
2865 token
= next_token (&val
, (unsigned *)0, cfile
);
2866 if (token
!= RPAREN
) {
2868 parse_warn (cfile
, "right paren expected");
2869 skip_to_semi (cfile
);
2875 if (context
== context_dns
)
2877 token
= next_token (&val
, (unsigned *)0, cfile
);
2878 if (!expression_allocate (expr
, MDL
))
2879 log_fatal ("can't allocate expression");
2880 (*expr
) -> op
= expr_exists
;
2882 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
2883 if (!(*expr
) -> data
.option
) {
2885 expression_dereference (expr
, MDL
);
2891 token
= next_token (&val
, (unsigned *)0, cfile
);
2892 if (!expression_allocate (expr
, MDL
))
2893 log_fatal ("can't allocate expression");
2894 (*expr
) -> op
= expr_static
;
2898 token
= next_token (&val
, (unsigned *)0, cfile
);
2899 if (!expression_allocate (expr
, MDL
))
2900 log_fatal ("can't allocate expression");
2901 (*expr
) -> op
= expr_known
;
2905 token
= next_token (&val
, (unsigned *)0, cfile
);
2906 if (!expression_allocate (expr
, MDL
))
2907 log_fatal ("can't allocate expression");
2908 (*expr
) -> op
= expr_substring
;
2910 token
= next_token (&val
, (unsigned *)0, cfile
);
2911 if (token
!= LPAREN
) {
2913 expression_dereference (expr
, MDL
);
2914 parse_warn (cfile
, "left parenthesis expected.");
2919 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
2922 expression_dereference (expr
, MDL
);
2925 "expecting data expression.");
2926 skip_to_semi (cfile
);
2932 token
= next_token (&val
, (unsigned *)0, cfile
);
2933 if (token
!= COMMA
) {
2935 expression_dereference (expr
, MDL
);
2936 parse_warn (cfile
, "comma expected.");
2942 if (!parse_numeric_expression
2943 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
2947 "expecting numeric expression.");
2948 skip_to_semi (cfile
);
2951 expression_dereference (expr
, MDL
);
2955 token
= next_token (&val
, (unsigned *)0, cfile
);
2959 if (!parse_numeric_expression
2960 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
2963 token
= next_token (&val
, (unsigned *)0, cfile
);
2964 if (token
!= RPAREN
) {
2966 parse_warn (cfile
, "right parenthesis expected.");
2968 expression_dereference (expr
, MDL
);
2974 token
= next_token (&val
, (unsigned *)0, cfile
);
2975 if (!expression_allocate (expr
, MDL
))
2976 log_fatal ("can't allocate expression");
2977 (*expr
) -> op
= expr_suffix
;
2979 token
= next_token (&val
, (unsigned *)0, cfile
);
2980 if (token
!= LPAREN
)
2983 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
2987 token
= next_token (&val
, (unsigned *)0, cfile
);
2991 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
2995 token
= next_token (&val
, (unsigned *)0, cfile
);
2996 if (token
!= RPAREN
)
3001 token
= next_token (&val
, (unsigned *)0, cfile
);
3002 if (!expression_allocate (expr
, MDL
))
3003 log_fatal ("can't allocate expression");
3004 (*expr
) -> op
= expr_concat
;
3006 token
= next_token (&val
, (unsigned *)0, cfile
);
3007 if (token
!= LPAREN
)
3010 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3014 token
= next_token (&val
, (unsigned *)0, cfile
);
3019 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3023 token
= next_token (&val
, (unsigned *)0, cfile
);
3025 if (token
== COMMA
) {
3026 nexp
= (struct expression
*)0;
3027 if (!expression_allocate (&nexp
, MDL
))
3028 log_fatal ("can't allocate at CONCAT2");
3029 nexp
-> op
= expr_concat
;
3030 expression_reference (&nexp
-> data
.concat
[0],
3032 expression_dereference (expr
, MDL
);
3033 expression_reference (expr
, nexp
, MDL
);
3034 expression_dereference (&nexp
, MDL
);
3035 goto concat_another
;
3038 if (token
!= RPAREN
)
3042 case BINARY_TO_ASCII
:
3043 token
= next_token (&val
, (unsigned *)0, cfile
);
3044 if (!expression_allocate (expr
, MDL
))
3045 log_fatal ("can't allocate expression");
3046 (*expr
) -> op
= expr_binary_to_ascii
;
3048 token
= next_token (&val
, (unsigned *)0, cfile
);
3049 if (token
!= LPAREN
)
3052 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3056 token
= next_token (&val
, (unsigned *)0, cfile
);
3060 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3064 token
= next_token (&val
, (unsigned *)0, cfile
);
3068 if (!parse_data_expression (&(*expr
) -> data
.b2a
.seperator
,
3072 token
= next_token (&val
, (unsigned *)0, cfile
);
3076 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3080 token
= next_token (&val
, (unsigned *)0, cfile
);
3081 if (token
!= RPAREN
)
3086 token
= next_token (&val
, (unsigned *)0, cfile
);
3087 if (!expression_allocate (expr
, MDL
))
3088 log_fatal ("can't allocate expression");
3089 (*expr
) -> op
= expr_reverse
;
3091 token
= next_token (&val
, (unsigned *)0, cfile
);
3092 if (token
!= LPAREN
)
3095 if (!(parse_numeric_expression
3096 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3099 token
= next_token (&val
, (unsigned *)0, cfile
);
3103 if (!(parse_data_expression
3104 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3107 token
= next_token (&val
, (unsigned *)0, cfile
);
3108 if (token
!= RPAREN
)
3113 /* pick (a, b, c) actually produces an internal representation
3114 that looks like pick (a, pick (b, pick (c, nil))). */
3115 token
= next_token (&val
, (unsigned *)0, cfile
);
3116 if (!(expression_allocate (expr
, MDL
)))
3117 log_fatal ("can't allocate expression");
3119 token
= next_token (&val
, (unsigned *)0, cfile
);
3120 if (token
!= LPAREN
)
3123 nexp
= (struct expression
*)0;
3124 expression_reference (&nexp
, *expr
, MDL
);
3126 nexp
-> op
= expr_pick_first_value
;
3127 if (!(parse_data_expression
3128 (&nexp
-> data
.pick_first_value
.car
,
3132 token
= next_token (&val
, (unsigned *)0, cfile
);
3133 if (token
== COMMA
) {
3134 struct expression
*foo
= (struct expression
*)0;
3135 if (!expression_allocate (&foo
, MDL
))
3136 log_fatal ("can't allocate expr");
3137 expression_reference
3138 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3139 expression_dereference (&nexp
, MDL
);
3140 expression_reference (&nexp
, foo
, MDL
);
3141 expression_dereference (&foo
, MDL
);
3143 } while (token
== COMMA
);
3144 expression_dereference (&nexp
, MDL
);
3146 if (token
!= RPAREN
)
3150 /* dns-update and dns-delete are present for historical
3151 purposes, but are deprecated in favor of ns-update
3152 in combination with update, delete, exists and not
3156 #if !defined (NSUPDATE)
3158 "Please rebuild dhcpd with --with-nsupdate.");
3160 token
= next_token (&val
, (unsigned *)0, cfile
);
3161 if (token
== DNS_UPDATE
)
3162 opcode
= expr_ns_add
;
3164 opcode
= expr_ns_delete
;
3166 token
= next_token (&val
, (unsigned *)0, cfile
);
3167 if (token
!= LPAREN
)
3170 token
= next_token (&val
, (unsigned *)0, cfile
);
3171 if (token
!= STRING
) {
3173 "parse_expression: expecting string.");
3175 skip_to_semi (cfile
);
3180 if (!strcasecmp (val
, "a"))
3182 else if (!strcasecmp (val
, "ptr"))
3184 else if (!strcasecmp (val
, "mx"))
3186 else if (!strcasecmp (val
, "cname"))
3188 else if (!strcasecmp (val
, "TXT"))
3191 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3195 s
= (opcode
== expr_ns_add
3197 : "old-dns-delete");
3198 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3200 log_fatal ("can't allocate name for %s", s
);
3202 if (!expression_allocate (expr
, MDL
))
3203 log_fatal ("can't allocate expression");
3204 (*expr
) -> op
= expr_funcall
;
3205 (*expr
) -> data
.funcall
.name
= cptr
;
3207 /* Fake up a function call. */
3208 ep
= &(*expr
) -> data
.funcall
.arglist
;
3209 if (!expression_allocate (ep
, MDL
))
3210 log_fatal ("can't allocate expression");
3211 (*ep
) -> op
= expr_arg
;
3212 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3213 log_fatal ("can't allocate rrtype value.");
3215 token
= next_token (&val
, (unsigned *)0, cfile
);
3218 ep
= &((*ep
) -> data
.arg
.next
);
3219 if (!expression_allocate (ep
, MDL
))
3220 log_fatal ("can't allocate expression");
3221 (*ep
) -> op
= expr_arg
;
3222 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3226 token
= next_token (&val
, (unsigned *)0, cfile
);
3230 ep
= &((*ep
) -> data
.arg
.next
);
3231 if (!expression_allocate (ep
, MDL
))
3232 log_fatal ("can't allocate expression");
3233 (*ep
) -> op
= expr_arg
;
3234 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3238 if (opcode
== expr_ns_add
) {
3239 token
= next_token (&val
, (unsigned *)0, cfile
);
3243 ep
= &((*ep
) -> data
.arg
.next
);
3244 if (!expression_allocate (ep
, MDL
))
3245 log_fatal ("can't allocate expression");
3246 (*ep
) -> op
= expr_arg
;
3247 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
3250 "expecting numeric expression.");
3255 token
= next_token (&val
, (unsigned *)0, cfile
);
3256 if (token
!= RPAREN
)
3261 #if !defined (NSUPDATE)
3263 "Please rebuild dhcpd with --with-nsupdate.");
3265 token
= next_token (&val
, (unsigned *)0, cfile
);
3266 if (!expression_allocate (expr
, MDL
))
3267 log_fatal ("can't allocate expression");
3269 token
= next_token (&val
, (unsigned *)0, cfile
);
3270 if (token
!= LPAREN
)
3275 nexp
-> op
= expr_dns_transaction
;
3276 if (!(parse_dns_expression
3277 (&nexp
-> data
.dns_transaction
.car
,
3283 "expecting dns expression.");
3284 expression_dereference (expr
, MDL
);
3289 token
= next_token (&val
, (unsigned *)0, cfile
);
3291 if (token
== COMMA
) {
3292 if (!(expression_allocate
3293 (&nexp
-> data
.dns_transaction
.cdr
,
3296 ("can't allocate expression");
3297 nexp
= nexp
-> data
.dns_transaction
.cdr
;
3299 } while (token
== COMMA
);
3301 if (token
!= RPAREN
)
3305 /* NOT EXISTS is special cased above... */
3307 token
= peek_token (&val
, (unsigned *)0, cfile
);
3308 if (token
!= EXISTS
) {
3309 parse_warn (cfile
, "expecting DNS prerequisite.");
3313 opcode
= expr_ns_not_exists
;
3316 opcode
= expr_ns_add
;
3319 opcode
= expr_ns_delete
;
3322 opcode
= expr_ns_exists
;
3324 token
= next_token (&val
, (unsigned *)0, cfile
);
3326 #if !defined (NSUPDATE)
3328 "Please rebuild dhcpd with --with-nsupdate.");
3330 if (!expression_allocate (expr
, MDL
))
3331 log_fatal ("can't allocate expression");
3332 (*expr
) -> op
= opcode
;
3334 token
= next_token (&val
, (unsigned *)0, cfile
);
3335 if (token
!= LPAREN
)
3338 token
= next_token (&val
, (unsigned *)0, cfile
);
3339 if (!is_identifier (token
) && token
!= NUMBER
) {
3340 parse_warn (cfile
, "expecting identifier or number.");
3342 expression_dereference (expr
, MDL
);
3343 skip_to_semi (cfile
);
3348 if (token
== NUMBER
)
3349 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
3350 else if (!strcasecmp (val
, "in"))
3351 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
3352 else if (!strcasecmp (val
, "chaos"))
3353 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
3354 else if (!strcasecmp (val
, "hs"))
3355 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
3357 parse_warn (cfile
, "unexpected rrclass: %s", val
);
3361 token
= next_token (&val
, (unsigned *)0, cfile
);
3365 token
= next_token (&val
, (unsigned *)0, cfile
);
3366 if (!is_identifier (token
) && token
!= NUMBER
) {
3367 parse_warn (cfile
, "expecting identifier or number.");
3371 if (token
== NUMBER
)
3372 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
3373 else if (!strcasecmp (val
, "a"))
3374 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
3375 else if (!strcasecmp (val
, "ptr"))
3376 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
3377 else if (!strcasecmp (val
, "mx"))
3378 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
3379 else if (!strcasecmp (val
, "cname"))
3380 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
3381 else if (!strcasecmp (val
, "TXT"))
3382 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
3384 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3388 token
= next_token (&val
, (unsigned *)0, cfile
);
3392 if (!(parse_data_expression
3393 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
3396 token
= next_token (&val
, (unsigned *)0, cfile
);
3400 if (!(parse_data_expression
3401 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
3404 if (opcode
== expr_ns_add
) {
3405 token
= next_token (&val
, (unsigned *)0, cfile
);
3409 if (!(parse_numeric_expression
3410 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
3414 "expecting numeric expression.");
3419 token
= next_token (&val
, (unsigned *)0, cfile
);
3420 if (token
!= RPAREN
)
3426 if (!expression_allocate (expr
, MDL
))
3427 log_fatal ("can't allocate expression");
3428 (*expr
) -> op
= (token
== OPTION
3430 : expr_config_option
);
3431 token
= next_token (&val
, (unsigned *)0, cfile
);
3433 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
3434 if (!(*expr
) -> data
.option
) {
3436 expression_dereference (expr
, MDL
);
3442 token
= next_token (&val
, (unsigned *)0, cfile
);
3443 if (!expression_allocate (expr
, MDL
))
3444 log_fatal ("can't allocate expression");
3445 (*expr
) -> op
= expr_hardware
;
3448 case LEASED_ADDRESS
:
3449 token
= next_token (&val
, (unsigned *)0, cfile
);
3450 if (!expression_allocate (expr
, MDL
))
3451 log_fatal ("can't allocate expression");
3452 (*expr
) -> op
= expr_leased_address
;
3456 token
= next_token (&val
, (unsigned *)0, cfile
);
3457 if (!expression_allocate (expr
, MDL
))
3458 log_fatal ("can't allocate expression");
3459 (*expr
) -> op
= expr_client_state
;
3463 token
= next_token (&val
, (unsigned *)0, cfile
);
3464 if (!expression_allocate (expr
, MDL
))
3465 log_fatal ("can't allocate expression");
3466 (*expr
) -> op
= expr_filename
;
3470 token
= next_token (&val
, (unsigned *)0, cfile
);
3471 if (!expression_allocate (expr
, MDL
))
3472 log_fatal ("can't allocate expression");
3473 (*expr
) -> op
= expr_sname
;
3477 token
= next_token (&val
, (unsigned *)0, cfile
);
3478 if (!expression_allocate (expr
, MDL
))
3479 log_fatal ("can't allocate expression");
3480 (*expr
) -> op
= expr_lease_time
;
3484 token
= next_token (&val
, (unsigned *)0, cfile
);
3485 if (!expression_allocate (expr
, MDL
))
3486 log_fatal ("can't allocate expression");
3487 (*expr
) -> op
= expr_null
;
3490 case HOST_DECL_NAME
:
3491 token
= next_token (&val
, (unsigned *)0, cfile
);
3492 if (!expression_allocate (expr
, MDL
))
3493 log_fatal ("can't allocate expression");
3494 (*expr
) -> op
= expr_host_decl_name
;
3497 case UPDATED_DNS_RR
:
3498 token
= next_token (&val
, (unsigned *)0, cfile
);
3500 token
= next_token (&val
, (unsigned *)0, cfile
);
3501 if (token
!= LPAREN
)
3504 token
= next_token (&val
, (unsigned *)0, cfile
);
3505 if (token
!= STRING
) {
3506 parse_warn (cfile
, "expecting string.");
3511 if (!strcasecmp (val
, "a"))
3512 s
= "ddns-fwd-name";
3513 else if (!strcasecmp (val
, "ptr"))
3514 s
= "ddns-rev-name";
3516 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
3520 token
= next_token (&val
, (unsigned *)0, cfile
);
3521 if (token
!= RPAREN
)
3524 if (!expression_allocate (expr
, MDL
))
3525 log_fatal ("can't allocate expression");
3526 (*expr
) -> op
= expr_variable_reference
;
3527 (*expr
) -> data
.variable
=
3528 dmalloc (strlen (s
) + 1, MDL
);
3529 if (!(*expr
) -> data
.variable
)
3530 log_fatal ("can't allocate variable name.");
3531 strcpy ((*expr
) -> data
.variable
, s
);
3535 token
= next_token (&val
, (unsigned *)0, cfile
);
3536 if (!expression_allocate (expr
, MDL
))
3537 log_fatal ("can't allocate expression");
3538 (*expr
) -> op
= expr_packet
;
3540 token
= next_token (&val
, (unsigned *)0, cfile
);
3541 if (token
!= LPAREN
)
3544 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
3548 token
= next_token (&val
, (unsigned *)0, cfile
);
3552 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
3556 token
= next_token (&val
, (unsigned *)0, cfile
);
3557 if (token
!= RPAREN
)
3562 token
= next_token (&val
, &len
, cfile
);
3563 if (!make_const_data (expr
, (const unsigned char *)val
,
3565 log_fatal ("can't make constant string expression.");
3569 token
= next_token (&val
, (unsigned *)0, cfile
);
3570 token
= next_token (&val
, (unsigned *)0, cfile
);
3571 if (token
!= LPAREN
) {
3572 parse_warn (cfile
, "left parenthesis expected.");
3577 if (!expression_allocate (expr
, MDL
))
3578 log_fatal ("can't allocate expression");
3580 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
3584 "expecting data expression.");
3585 skip_to_semi (cfile
);
3588 expression_dereference (expr
, MDL
);
3592 token
= next_token (&val
, (unsigned *)0, cfile
);
3593 if (token
!= COMMA
) {
3594 parse_warn (cfile
, "comma expected.");
3596 expression_dereference (expr
, MDL
);
3600 token
= next_token (&val
, (unsigned *)0, cfile
);
3601 if (token
!= NUMBER
) {
3602 parse_warn (cfile
, "number expected.");
3604 expression_dereference (expr
, MDL
);
3607 switch (atoi (val
)) {
3609 (*expr
) -> op
= expr_extract_int8
;
3613 (*expr
) -> op
= expr_extract_int16
;
3617 (*expr
) -> op
= expr_extract_int32
;
3622 "unsupported integer size %d", atoi (val
));
3624 skip_to_semi (cfile
);
3625 expression_dereference (expr
, MDL
);
3629 token
= next_token (&val
, (unsigned *)0, cfile
);
3630 if (token
!= RPAREN
) {
3631 parse_warn (cfile
, "right parenthesis expected.");
3633 expression_dereference (expr
, MDL
);
3639 token
= next_token (&val
, (unsigned *)0, cfile
);
3640 token
= next_token (&val
, (unsigned *)0, cfile
);
3641 if (token
!= LPAREN
) {
3642 parse_warn (cfile
, "left parenthesis expected.");
3647 if (!expression_allocate (expr
, MDL
))
3648 log_fatal ("can't allocate expression");
3650 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
3652 parse_warn (cfile
, "expecting numeric expression.");
3653 skip_to_semi (cfile
);
3655 expression_dereference (expr
, MDL
);
3659 token
= next_token (&val
, (unsigned *)0, cfile
);
3660 if (token
!= COMMA
) {
3661 parse_warn (cfile
, "comma expected.");
3663 expression_dereference (expr
, MDL
);
3667 token
= next_token (&val
, (unsigned *)0, cfile
);
3668 if (token
!= NUMBER
) {
3669 parse_warn (cfile
, "number expected.");
3671 expression_dereference (expr
, MDL
);
3674 switch (atoi (val
)) {
3676 (*expr
) -> op
= expr_encode_int8
;
3680 (*expr
) -> op
= expr_encode_int16
;
3684 (*expr
) -> op
= expr_encode_int32
;
3689 "unsupported integer size %d", atoi (val
));
3691 skip_to_semi (cfile
);
3692 expression_dereference (expr
, MDL
);
3696 token
= next_token (&val
, (unsigned *)0, cfile
);
3697 if (token
!= RPAREN
) {
3698 parse_warn (cfile
, "right parenthesis expected.");
3700 expression_dereference (expr
, MDL
);
3706 /* If we're in a numeric context, this should just be a
3707 number, by itself. */
3708 if (context
== context_numeric
||
3709 context
== context_data_or_numeric
) {
3710 next_token (&val
, (unsigned *)0, cfile
);
3711 if (!expression_allocate (expr
, MDL
))
3712 log_fatal ("can't allocate expression");
3713 (*expr
) -> op
= expr_const_int
;
3714 (*expr
) -> data
.const_int
= atoi (val
);
3718 case NUMBER_OR_NAME
:
3719 if (!expression_allocate (expr
, MDL
))
3720 log_fatal ("can't allocate expression");
3722 (*expr
) -> op
= expr_const_data
;
3723 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
3724 expression_dereference (expr
, MDL
);
3733 token
= next_token (&val
, (unsigned *)0, cfile
);
3734 if (!expression_allocate (expr
, MDL
))
3735 log_fatal ("can't allocate expression");
3736 (*expr
) -> op
= expr_const_int
;
3737 (*expr
) -> data
.const_int
= known
;
3741 known
= ISC_R_SUCCESS
;
3745 known
= ISC_R_NOTAUTH
;
3749 known
= ISC_R_NOTIMPLEMENTED
;
3753 known
= ISC_R_NOTZONE
;
3757 known
= ISC_R_NXDOMAIN
;
3761 known
= ISC_R_NXRRSET
;
3765 known
= ISC_R_REFUSED
;
3769 known
= ISC_R_SERVFAIL
;
3773 known
= ISC_R_YXDOMAIN
;
3777 known
= ISC_R_YXRRSET
;
3785 known
= S_REBOOTING
;
3789 known
= S_SELECTING
;
3793 known
= S_REQUESTING
;
3805 known
= S_REBINDING
;
3809 token
= next_token (&val
, (unsigned *)0, cfile
);
3810 token
= next_token (&val
, (unsigned *)0, cfile
);
3811 if (token
!= LPAREN
)
3814 token
= next_token (&val
, (unsigned *)0, cfile
);
3815 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
3816 parse_warn (cfile
, "%s can't be a variable name", val
);
3817 skip_to_semi (cfile
);
3822 if (!expression_allocate (expr
, MDL
))
3823 log_fatal ("can't allocate expression");
3824 (*expr
) -> op
= expr_variable_exists
;
3825 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
3826 if (!(*expr
)->data
.variable
)
3827 log_fatal ("can't allocate variable name");
3828 strcpy ((*expr
) -> data
.variable
, val
);
3829 token
= next_token (&val
, (unsigned *)0, cfile
);
3830 if (token
!= RPAREN
)
3834 /* Not a valid start to an expression... */
3836 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
3839 token
= next_token (&val
, (unsigned *)0, cfile
);
3841 /* Save the name of the variable being referenced. */
3842 cptr
= dmalloc (strlen (val
) + 1, MDL
);
3844 log_fatal ("can't allocate variable name");
3847 /* Simple variable reference, as far as we can tell. */
3848 token
= peek_token (&val
, (unsigned *)0, cfile
);
3849 if (token
!= LPAREN
) {
3850 if (!expression_allocate (expr
, MDL
))
3851 log_fatal ("can't allocate expression");
3852 (*expr
) -> op
= expr_variable_reference
;
3853 (*expr
) -> data
.variable
= cptr
;
3857 token
= next_token (&val
, (unsigned *)0, cfile
);
3858 if (!expression_allocate (expr
, MDL
))
3859 log_fatal ("can't allocate expression");
3860 (*expr
) -> op
= expr_funcall
;
3861 (*expr
) -> data
.funcall
.name
= cptr
;
3863 /* Now parse the argument list. */
3864 ep
= &(*expr
) -> data
.funcall
.arglist
;
3866 if (!expression_allocate (ep
, MDL
))
3867 log_fatal ("can't allocate expression");
3868 (*ep
) -> op
= expr_arg
;
3869 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
3870 cfile
, lose
, context_any
,
3871 (struct expression
**)0,
3875 "expecting expression.");
3878 skip_to_semi (cfile
);
3879 expression_dereference (expr
, MDL
);
3882 ep
= &((*ep
) -> data
.arg
.next
);
3883 token
= next_token (&val
, (unsigned *)0, cfile
);
3884 } while (token
== COMMA
);
3885 if (token
!= RPAREN
) {
3886 parse_warn (cfile
, "Right parenthesis expected.");
3887 skip_to_semi (cfile
);
3889 expression_dereference (expr
, MDL
);
3897 /* Parse an expression. */
3899 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
3900 struct expression
**expr
;
3901 struct parse
*cfile
;
3903 enum expression_context context
;
3904 struct expression
**plhs
;
3907 enum dhcp_token token
;
3909 struct expression
*rhs
= (struct expression
*)0, *tmp
;
3910 struct expression
*lhs
= (struct expression
*)0;
3911 enum expr_op next_op
;
3912 enum expression_context
3913 lhs_context
= context_any
,
3914 rhs_context
= context_any
;
3916 /* Consume the left hand side we were passed. */
3918 expression_reference (&lhs
, *plhs
, MDL
);
3919 expression_dereference (plhs
, MDL
);
3923 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
3924 /* If we already have a left-hand side, then it's not
3925 okay for there not to be a right-hand side here, so
3926 we need to flag it as an error. */
3930 "expecting right-hand side.");
3932 skip_to_semi (cfile
);
3934 expression_dereference (&lhs
, MDL
);
3939 /* At this point, rhs contains either an entire subexpression,
3940 or at least a left-hand-side. If we do not see a binary token
3941 as the next token, we're done with the expression. */
3943 token
= peek_token (&val
, (unsigned *)0, cfile
);
3946 token
= next_token (&val
, (unsigned *)0, cfile
);
3947 token
= peek_token (&val
, (unsigned *)0, cfile
);
3948 if (token
!= EQUAL
) {
3949 parse_warn (cfile
, "! in boolean context without =");
3951 skip_to_semi (cfile
);
3953 expression_dereference (&lhs
, MDL
);
3956 next_op
= expr_not_equal
;
3957 context
= expression_context (rhs
);
3961 next_op
= expr_equal
;
3962 context
= expression_context (rhs
);
3967 context
= expression_context (rhs
);
3972 context
= expression_context (rhs
);
3977 context
= expression_context (rhs
);
3981 next_op
= expr_subtract
;
3982 context
= expression_context (rhs
);
3986 next_op
= expr_divide
;
3987 context
= expression_context (rhs
);
3991 next_op
= expr_multiply
;
3992 context
= expression_context (rhs
);
3996 next_op
= expr_remainder
;
3997 context
= expression_context (rhs
);
4001 next_op
= expr_binary_and
;
4002 context
= expression_context (rhs
);
4006 next_op
= expr_binary_or
;
4007 context
= expression_context (rhs
);
4011 next_op
= expr_binary_xor
;
4012 context
= expression_context (rhs
);
4016 next_op
= expr_none
;
4019 /* If we have no lhs yet, we just parsed it. */
4021 /* If there was no operator following what we just parsed,
4022 then we're done - return it. */
4023 if (next_op
== expr_none
) {
4028 rhs
= (struct expression
*)0;
4030 next_token (&val
, (unsigned *)0, cfile
);
4034 /* If the next binary operator is of greater precedence than the
4035 * current operator, then rhs we have parsed so far is actually
4036 * the lhs of the next operator. To get this value, we have to
4039 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4040 op_precedence (binop
, next_op
) < 0) {
4042 /* Eat the subexpression operator token, which we pass to
4043 * parse_expression...we only peek()'d earlier.
4045 token
= next_token (&val
, (unsigned *)0, cfile
);
4047 /* Continue parsing of the right hand side with that token. */
4049 rhs
= (struct expression
*)0;
4050 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4054 "expecting a subexpression");
4059 next_op
= expr_none
;
4062 if (binop
!= expr_none
) {
4063 rhs_context
= expression_context(rhs
);
4064 lhs_context
= expression_context(lhs
);
4066 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4067 (rhs_context
!= lhs_context
)) {
4068 parse_warn (cfile
, "illegal expression relating different types");
4069 skip_to_semi (cfile
);
4070 expression_dereference (&rhs
, MDL
);
4071 expression_dereference (&lhs
, MDL
);
4077 case expr_not_equal
:
4079 if ((rhs_context
!= context_data_or_numeric
) &&
4080 (rhs_context
!= context_data
) &&
4081 (rhs_context
!= context_numeric
) &&
4082 (rhs_context
!= context_any
)) {
4083 parse_warn (cfile
, "expecting data/numeric expression");
4084 skip_to_semi (cfile
);
4085 expression_dereference (&rhs
, MDL
);
4093 if ((rhs_context
!= context_boolean
) &&
4094 (rhs_context
!= context_any
)) {
4095 parse_warn (cfile
, "expecting boolean expressions");
4096 skip_to_semi (cfile
);
4097 expression_dereference (&rhs
, MDL
);
4107 case expr_remainder
:
4108 case expr_binary_and
:
4109 case expr_binary_or
:
4110 case expr_binary_xor
:
4111 if ((rhs_context
!= context_numeric
) &&
4112 (rhs_context
!= context_any
)) {
4113 parse_warn (cfile
, "expecting numeric expressions");
4114 skip_to_semi (cfile
);
4115 expression_dereference (&rhs
, MDL
);
4126 /* Now, if we didn't find a binary operator, we're done parsing
4127 this subexpression, so combine it with the preceding binary
4128 operator and return the result. */
4129 if (next_op
== expr_none
) {
4130 if (!expression_allocate (expr
, MDL
))
4131 log_fatal ("Can't allocate expression!");
4133 (*expr
) -> op
= binop
;
4134 /* All the binary operators' data union members
4135 are the same, so we'll cheat and use the member
4136 for the equals operator. */
4137 (*expr
) -> data
.equal
[0] = lhs
;
4138 (*expr
) -> data
.equal
[1] = rhs
;
4142 /* Eat the operator token - we now know it was a binary operator... */
4143 token
= next_token (&val
, (unsigned *)0, cfile
);
4145 /* Now combine the LHS and the RHS using binop. */
4146 tmp
= (struct expression
*)0;
4147 if (!expression_allocate (&tmp
, MDL
))
4148 log_fatal ("No memory for equal precedence combination.");
4150 /* Store the LHS and RHS. */
4151 tmp
-> data
.equal
[0] = lhs
;
4152 tmp
-> data
.equal
[1] = rhs
;
4156 tmp
= (struct expression
*)0;
4157 rhs
= (struct expression
*)0;
4159 /* Recursions don't return until we have parsed the end of the
4160 expression, so if we recursed earlier, we can now return what
4162 if (next_op
== expr_none
) {
4171 /* option-statement :== identifier DOT identifier <syntax> SEMI
4172 | identifier <syntax> SEMI
4174 Option syntax is handled specially through format strings, so it
4175 would be painful to come up with BNF for it. However, it always
4176 starts as above and ends in a SEMI. */
4178 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4179 struct executable_statement
**result
;
4180 struct parse
*cfile
;
4182 struct option
*option
;
4183 enum statement_op op
;
4186 enum dhcp_token token
;
4187 const char *fmt
= NULL
;
4188 struct expression
*expr
= (struct expression
*)0;
4189 struct expression
*tmp
;
4192 token
= peek_token (&val
, (unsigned *)0, cfile
);
4193 if (token
== SEMI
) {
4194 /* Eat the semicolon... */
4195 token
= next_token (&val
, (unsigned *)0, cfile
);
4199 if (token
== EQUAL
) {
4200 /* Eat the equals sign. */
4201 token
= next_token (&val
, (unsigned *)0, cfile
);
4203 /* Parse a data expression and use its value for the data. */
4204 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
4205 /* In this context, we must have an executable
4206 statement, so if we found something else, it's
4210 "expecting a data expression.");
4211 skip_to_semi (cfile
);
4216 /* We got a valid expression, so use it. */
4220 /* Parse the option data... */
4222 /* Set a flag if this is an array of a simple type (i.e.,
4223 not an array of pairs of IP addresses, or something
4225 int uniform
= option
-> format
[1] == 'A';
4228 /* Set fmt to start of format for 'A' and one char back
4230 if ((fmt
!= NULL
) &&
4231 (fmt
!= option
-> format
) && (*fmt
== 'a'))
4234 fmt
= ((fmt
== NULL
) ||
4235 (*fmt
== 'A')) ? option
-> format
: fmt
;
4237 /* 'a' means always uniform */
4238 uniform
|= (fmt
[1] == 'a');
4240 for ( ; *fmt
; fmt
++) {
4241 if ((*fmt
== 'A') || (*fmt
== 'a'))
4246 expr
= (struct expression
*)0;
4247 if (!parse_option_token (&expr
, cfile
, &fmt
,
4248 tmp
, uniform
, lookups
)) {
4249 if (fmt
[1] != 'o') {
4251 expression_dereference (&tmp
,
4256 tmp
= (struct expression
*)0;
4259 expression_dereference (&tmp
, MDL
);
4261 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4262 token
= peek_token (&val
, (unsigned *)0, cfile
);
4263 /* Comma means: continue with next element in array */
4264 if (token
== COMMA
) {
4265 token
= next_token (&val
,
4266 (unsigned *)0, cfile
);
4269 /* no comma: end of array.
4270 'A' or end of string means: leave the loop */
4271 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4273 /* 'a' means: go on with next char */
4279 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4282 if (!parse_semi (cfile
))
4284 if (!executable_statement_allocate (result
, MDL
))
4285 log_fatal ("no memory for option statement.");
4286 (*result
) -> op
= op
;
4287 if (expr
&& !option_cache (&(*result
) -> data
.option
,
4288 (struct data_string
*)0, expr
, option
, MDL
))
4289 log_fatal ("no memory for option cache");
4291 expression_dereference (&expr
, MDL
);
4295 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4296 struct expression
**rv
;
4297 struct parse
*cfile
;
4299 struct expression
*expr
;
4304 enum dhcp_token token
;
4305 struct expression
*t
= (struct expression
*)0;
4306 unsigned char buf
[4];
4310 struct enumeration_value
*e
;
4314 token
= next_token (&val
, &len
, cfile
);
4315 if (!is_identifier (token
)) {
4316 if ((*fmt
) [1] != 'o') {
4317 parse_warn (cfile
, "expecting identifier.");
4319 skip_to_semi (cfile
);
4323 if (!make_const_data (&t
, (const unsigned char *)val
,
4325 log_fatal ("No memory for %s", val
);
4329 g
= strchr (*fmt
, '.');
4332 "malformed encapsulation format (bug!)");
4333 skip_to_semi (cfile
);
4338 token
= peek_token (&val
, (unsigned *)0, cfile
);
4339 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4340 if (!expression_allocate (&t
, MDL
))
4342 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4343 expression_dereference (&t
, MDL
);
4346 t
-> op
= expr_const_data
;
4348 token
= next_token (&val
, &len
, cfile
);
4350 if(token
== STRING
) {
4351 if (!make_const_data (&t
,
4352 (const unsigned char *)val
,
4354 log_fatal ("No memory for \"%s\"", val
);
4355 } else if ((*fmt
) [1] != 'o') {
4356 parse_warn (cfile
, "expecting string %s.",
4357 "or hexadecimal data");
4358 skip_to_semi (cfile
);
4365 case 'd': /* Domain name... */
4366 val
= parse_host_name (cfile
);
4368 parse_warn (cfile
, "not a valid domain name.");
4369 skip_to_semi (cfile
);
4375 case 't': /* Text string... */
4376 token
= next_token (&val
, &len
, cfile
);
4377 if (token
!= STRING
&& !is_identifier (token
)) {
4378 if ((*fmt
) [1] != 'o') {
4379 parse_warn (cfile
, "expecting string.");
4381 skip_to_semi (cfile
);
4386 if (!make_const_data (&t
, (const unsigned char *)val
,
4388 log_fatal ("No memory for concatenation");
4393 g
= strchr (*fmt
, '.');
4395 parse_warn (cfile
, "malformed %s (bug!)",
4396 "enumeration format");
4398 skip_to_semi (cfile
);
4402 token
= next_token (&val
, (unsigned *)0, cfile
);
4403 if (!is_identifier (token
)) {
4405 "identifier expected");
4408 e
= find_enumeration_value (f
, (*fmt
) - f
, val
);
4410 parse_warn (cfile
, "unknown value");
4413 if (!make_const_data (&t
, &e
-> value
, 1, 0, 1, MDL
))
4417 case 'I': /* IP address or hostname. */
4419 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
4422 if (!parse_ip_addr (cfile
, &addr
))
4424 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
4430 case 'T': /* Lease interval. */
4431 token
= next_token (&val
, (unsigned *)0, cfile
);
4432 if (token
!= INFINITE
)
4435 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4439 case 'L': /* Unsigned 32-bit integer... */
4440 case 'l': /* Signed 32-bit integer... */
4441 token
= next_token (&val
, (unsigned *)0, cfile
);
4443 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
4445 if ((*fmt
) [1] != 'o') {
4446 parse_warn (cfile
, "expecting number.");
4448 skip_to_semi (cfile
);
4452 convert_num (cfile
, buf
, val
, 0, 32);
4453 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4457 case 's': /* Signed 16-bit integer. */
4458 case 'S': /* Unsigned 16-bit integer. */
4459 token
= next_token (&val
, (unsigned *)0, cfile
);
4460 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4462 convert_num (cfile
, buf
, val
, 0, 16);
4463 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
4467 case 'b': /* Signed 8-bit integer. */
4468 case 'B': /* Unsigned 8-bit integer. */
4469 token
= next_token (&val
, (unsigned *)0, cfile
);
4470 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4472 convert_num (cfile
, buf
, val
, 0, 8);
4473 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4477 case 'f': /* Boolean flag. */
4478 token
= next_token (&val
, (unsigned *)0, cfile
);
4479 if (!is_identifier (token
)) {
4480 if ((*fmt
) [1] != 'o')
4481 parse_warn (cfile
, "expecting identifier.");
4483 if ((*fmt
) [1] != 'o') {
4485 skip_to_semi (cfile
);
4489 if (!strcasecmp (val
, "true")
4490 || !strcasecmp (val
, "on"))
4492 else if (!strcasecmp (val
, "false")
4493 || !strcasecmp (val
, "off"))
4495 else if (!strcasecmp (val
, "ignore"))
4498 if ((*fmt
) [1] != 'o')
4499 parse_warn (cfile
, "expecting boolean.");
4502 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4507 parse_warn (cfile
, "Bad format %c in parse_option_token.",
4509 skip_to_semi (cfile
);
4513 if (!make_concat (rv
, expr
, t
))
4516 expression_reference (rv
, t
, MDL
);
4517 expression_dereference (&t
, MDL
);
4521 int parse_option_decl (oc
, cfile
)
4522 struct option_cache
**oc
;
4523 struct parse
*cfile
;
4528 u_int8_t hunkbuf
[1024];
4529 unsigned hunkix
= 0;
4530 const char *fmt
, *f
;
4531 struct option
*option
;
4532 struct iaddr ip_addr
;
4538 struct enumeration_value
*e
;
4540 option
= parse_option_name (cfile
, 0, &known
);
4544 /* Parse the option data... */
4546 /* Set a flag if this is an array of a simple type (i.e.,
4547 not an array of pairs of IP addresses, or something
4550 for (fmt
= option
-> format
; *fmt
; fmt
++) {
4555 fmt
= strchr (fmt
, '.');
4558 "malformed %s (bug!)",
4559 "encapsulation format");
4560 skip_to_semi (cfile
);
4564 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
4565 sizeof hunkbuf
- hunkix
);
4569 case 't': /* Text string... */
4570 token
= next_token (&val
,
4572 if (token
!= STRING
) {
4574 "expecting string.");
4575 skip_to_semi (cfile
);
4578 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
4580 "option data buffer %s",
4582 skip_to_semi (cfile
);
4585 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
4592 fmt
= strchr (fmt
, '.');
4595 "malformed %s (bug!)",
4596 "enumeration format");
4598 skip_to_semi (cfile
);
4601 token
= next_token (&val
,
4602 (unsigned *)0, cfile
);
4603 if (!is_identifier (token
)) {
4605 "identifier expected");
4608 e
= find_enumeration_value (f
, fmt
- f
, val
);
4618 case 'I': /* IP address. */
4619 if (!parse_ip_addr (cfile
, &ip_addr
))
4625 if (hunkix
+ len
> sizeof hunkbuf
) {
4627 "option data buffer %s",
4629 skip_to_semi (cfile
);
4632 memcpy (&hunkbuf
[hunkix
], dp
, len
);
4636 case 'L': /* Unsigned 32-bit integer... */
4637 case 'l': /* Signed 32-bit integer... */
4638 token
= next_token (&val
,
4639 (unsigned *)0, cfile
);
4640 if ((token
!= NUMBER
) &&
4641 (token
!= NUMBER_OR_NAME
)) {
4644 "expecting number.");
4646 skip_to_semi (cfile
);
4649 convert_num (cfile
, buf
, val
, 0, 32);
4654 case 's': /* Signed 16-bit integer. */
4655 case 'S': /* Unsigned 16-bit integer. */
4656 token
= next_token (&val
,
4657 (unsigned *)0, cfile
);
4658 if ((token
!= NUMBER
) &&
4659 (token
!= NUMBER_OR_NAME
))
4661 convert_num (cfile
, buf
, val
, 0, 16);
4666 case 'b': /* Signed 8-bit integer. */
4667 case 'B': /* Unsigned 8-bit integer. */
4668 token
= next_token (&val
,
4669 (unsigned *)0, cfile
);
4670 if ((token
!= NUMBER
) &&
4671 (token
!= NUMBER_OR_NAME
))
4673 convert_num (cfile
, buf
, val
, 0, 8);
4678 case 'f': /* Boolean flag. */
4679 token
= next_token (&val
,
4680 (unsigned *)0, cfile
);
4681 if (!is_identifier (token
)) {
4683 "expecting identifier.");
4686 skip_to_semi (cfile
);
4689 if (!strcasecmp (val
, "true")
4690 || !strcasecmp (val
, "on"))
4692 else if (!strcasecmp (val
, "false")
4693 || !strcasecmp (val
, "off"))
4697 "expecting boolean.");
4705 log_error ("parse_option_param: Bad format %c",
4707 skip_to_semi (cfile
);
4711 token
= next_token (&val
, (unsigned *)0, cfile
);
4712 } while (*fmt
== 'A' && token
== COMMA
);
4714 if (token
!= SEMI
) {
4715 parse_warn (cfile
, "semicolon expected.");
4716 skip_to_semi (cfile
);
4720 bp
= (struct buffer
*)0;
4721 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
4722 log_fatal ("no memory to store option declaration.");
4724 log_fatal ("out of memory allocating option data.");
4725 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
4727 if (!option_cache_allocate (oc
, MDL
))
4728 log_fatal ("out of memory allocating option cache.");
4730 (*oc
) -> data
.buffer
= bp
;
4731 (*oc
) -> data
.data
= &bp
-> data
[0];
4732 (*oc
) -> data
.terminated
= nul_term
;
4733 (*oc
) -> data
.len
= hunkix
;
4734 (*oc
) -> option
= option
;
4738 /* Consider merging parse_cshl into this. */
4740 int parse_X (cfile
, buf
, max
)
4741 struct parse
*cfile
;
4749 token
= peek_token (&val
, (unsigned *)0, cfile
);
4750 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4753 token
= next_token (&val
, (unsigned *)0, cfile
);
4754 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
4756 "expecting hexadecimal constant.");
4757 skip_to_semi (cfile
);
4760 convert_num (cfile
, &buf
[len
], val
, 16, 8);
4763 "hexadecimal constant too long.");
4764 skip_to_semi (cfile
);
4767 token
= peek_token (&val
, (unsigned *)0, cfile
);
4769 token
= next_token (&val
,
4770 (unsigned *)0, cfile
);
4771 } while (token
== COLON
);
4773 } else if (token
== STRING
) {
4774 token
= next_token (&val
, &len
, cfile
);
4775 if (len
+ 1 > max
) {
4776 parse_warn (cfile
, "string constant too long.");
4777 skip_to_semi (cfile
);
4780 memcpy (buf
, val
, len
+ 1);
4782 parse_warn (cfile
, "expecting string or hexadecimal data");
4783 skip_to_semi (cfile
);
4789 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
4797 do_percentm (mbuf
, fmt
);
4798 /* %Audit% This is log output. %2004.06.17,Safe%
4799 * If we truncate we hope the user can get a hint from the log.
4801 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
4802 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
4804 va_start (list
, fmt
);
4807 vsnprintf (mbuf
, sizeof mbuf
, fmt
, list
);
4813 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
4814 if (lix
< (sizeof lexbuf
) - 1)
4815 lexbuf
[lix
++] = ' ';
4816 if (cfile
-> token_line
[i
] == '\t') {
4818 lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
4825 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
4826 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
4827 if (cfile
-> lexchar
< 81)
4828 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
4832 write (STDERR_FILENO
, mbuf
, strlen (mbuf
));
4833 write (STDERR_FILENO
, "\n", 1);
4834 write (STDERR_FILENO
, cfile
-> token_line
,
4835 strlen (cfile
-> token_line
));
4836 write (STDERR_FILENO
, "\n", 1);
4837 if (cfile
-> lexchar
< 81)
4838 write (STDERR_FILENO
, lexbuf
, lix
);
4839 write (STDERR_FILENO
, "^\n", 2);
4842 cfile
-> warnings_occurred
= 1;