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$ 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
)
315 enum dhcp_token token
;
318 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
319 &addr
-> len
, DOT
, 10, 8))
325 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
326 * hardware-type :== ETHERNET | TOKEN_RING | FDDI
329 void parse_hardware_param (cfile
, hardware
)
331 struct hardware
*hardware
;
334 enum dhcp_token token
;
338 token
= next_token (&val
, (unsigned *)0, cfile
);
341 hardware
-> hbuf
[0] = HTYPE_ETHER
;
344 hardware
-> hbuf
[0] = HTYPE_IEEE802
;
347 hardware
-> hbuf
[0] = HTYPE_FDDI
;
350 if (!strncmp (val
, "unknown-", 8)) {
351 hardware
-> hbuf
[0] = atoi (&val
[8]);
354 "expecting a network hardware type");
355 skip_to_semi (cfile
);
361 /* Parse the hardware address information. Technically,
362 it would make a lot of sense to restrict the length of the
363 data we'll accept here to the length of a particular hardware
364 address type. Unfortunately, there are some broken clients
365 out there that put bogus data in the chaddr buffer, and we accept
366 that data in the lease file rather than simply failing on such
369 token
= peek_token (&val
, (unsigned *)0, cfile
);
371 hardware
-> hlen
= 1;
374 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
377 hardware
-> hlen
= 1;
380 if (hlen
+ 1 > sizeof hardware
-> hbuf
) {
382 parse_warn (cfile
, "hardware address too long");
384 hardware
-> hlen
= hlen
+ 1;
385 memcpy ((unsigned char *)&hardware
-> hbuf
[1], t
, hlen
);
386 if (hlen
+ 1 < sizeof hardware
-> hbuf
)
387 memset (&hardware
-> hbuf
[hlen
+ 1], 0,
388 (sizeof hardware
-> hbuf
) - hlen
- 1);
393 token
= next_token (&val
, (unsigned *)0, cfile
);
395 parse_warn (cfile
, "expecting semicolon.");
396 skip_to_semi (cfile
);
400 /* lease-time :== NUMBER SEMI */
402 void parse_lease_time (cfile
, timep
)
407 enum dhcp_token token
;
409 token
= next_token (&val
, (unsigned *)0, cfile
);
410 if (token
!= NUMBER
) {
411 parse_warn (cfile
, "Expecting numeric lease time");
412 skip_to_semi (cfile
);
415 convert_num (cfile
, (unsigned char *)timep
, val
, 10, 32);
416 /* Unswap the number - convert_num returns stuff in NBO. */
417 *timep
= ntohl (*timep
); /* XXX */
422 /* No BNF for numeric aggregates - that's defined by the caller. What
423 this function does is to parse a sequence of numbers seperated by
424 the token specified in seperator. If max is zero, any number of
425 numbers will be parsed; otherwise, exactly max numbers are
426 expected. Base and size tell us how to internalize the numbers
427 once they've been tokenized. */
429 unsigned char *parse_numeric_aggregate (cfile
, buf
,
430 max
, seperator
, base
, size
)
439 enum dhcp_token token
;
440 unsigned char *bufp
= buf
, *s
, *t
;
445 bufp
= (unsigned char *)dmalloc (*max
* size
/ 8, MDL
);
447 log_fatal ("no space for numeric aggregate");
454 token
= peek_token (&val
, (unsigned *)0, cfile
);
455 if (token
!= seperator
) {
458 if (token
!= RBRACE
&& token
!= LBRACE
)
459 token
= next_token (&val
,
462 parse_warn (cfile
, "too few numbers.");
464 skip_to_semi (cfile
);
465 return (unsigned char *)0;
467 token
= next_token (&val
, (unsigned *)0, cfile
);
469 token
= next_token (&val
, (unsigned *)0, cfile
);
471 if (token
== END_OF_FILE
) {
472 parse_warn (cfile
, "unexpected end of file");
476 /* Allow NUMBER_OR_NAME if base is 16. */
477 if (token
!= NUMBER
&&
478 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
479 parse_warn (cfile
, "expecting numeric value.");
480 skip_to_semi (cfile
);
481 return (unsigned char *)0;
483 /* If we can, convert the number now; otherwise, build
484 a linked list of all the numbers. */
486 convert_num (cfile
, s
, val
, base
, size
);
489 t
= (unsigned char *)dmalloc (strlen (val
) + 1, MDL
);
491 log_fatal ("no temp space for number.");
492 strcpy ((char *)t
, val
);
493 c
= cons ((caddr_t
)t
, c
);
495 } while (++count
!= *max
);
497 /* If we had to cons up a list, convert it now. */
499 bufp
= (unsigned char *)dmalloc (count
* size
/ 8, MDL
);
501 log_fatal ("no space for numeric aggregate.");
502 s
= bufp
+ count
- size
/ 8;
507 convert_num (cfile
, s
, (char *)(c
-> car
), base
, size
);
509 /* Free up temp space. */
510 dfree (c
-> car
, MDL
);
517 void convert_num (cfile
, buf
, str
, base
, size
)
524 const char *ptr
= str
;
535 /* If base wasn't specified, figure it out from the data. */
537 if (ptr
[0] == '0') {
538 if (ptr
[1] == 'x') {
541 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
554 /* XXX assumes ASCII... */
556 tval
= tval
- 'a' + 10;
557 else if (tval
>= 'A')
558 tval
= tval
- 'A' + 10;
559 else if (tval
>= '0')
562 parse_warn (cfile
, "Bogus number: %s.", str
);
567 "Bogus number %s: digit %d not in base %d",
571 val
= val
* base
+ tval
;
575 max
= (1 << (size
- 1));
577 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
582 "%s%lo exceeds max (%d) for precision.",
584 (unsigned long)val
, max
);
588 "%s%lx exceeds max (%d) for precision.",
590 (unsigned long)val
, max
);
594 "%s%lu exceeds max (%d) for precision.",
596 (unsigned long)val
, max
);
604 *buf
= -(unsigned long)val
;
607 putShort (buf
, -(long)val
);
610 putLong (buf
, -(long)val
);
614 "Unexpected integer size: %d\n", size
);
620 *buf
= (u_int8_t
)val
;
623 putUShort (buf
, (u_int16_t
)val
);
630 "Unexpected integer size: %d\n", size
);
637 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
638 * NUMBER COLON NUMBER COLON NUMBER SEMI |
639 * NUMBER NUMBER SLASH NUMBER SLASH NUMBER
640 * NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI |
643 * Dates are stored in GMT or with a timezone offset; first number is day
644 * of week; next is year/month/day; next is hours:minutes:seconds on a
645 * 24-hour clock, followed by the timezone offset in seconds, which is
649 TIME
parse_date (cfile
)
654 int tzoff
, wday
, year
, mon
, mday
, hour
, min
, sec
;
656 enum dhcp_token token
;
657 static int months
[11] = { 31, 59, 90, 120, 151, 181,
658 212, 243, 273, 304, 334 };
660 /* Day of week, or "never"... */
661 token
= next_token (&val
, (unsigned *)0, cfile
);
662 if (token
== NEVER
) {
663 if (!parse_semi (cfile
))
668 if (token
!= NUMBER
) {
669 parse_warn (cfile
, "numeric day of week expected.");
671 skip_to_semi (cfile
);
677 token
= next_token (&val
, (unsigned *)0, cfile
);
678 if (token
!= NUMBER
) {
679 parse_warn (cfile
, "numeric year expected.");
681 skip_to_semi (cfile
);
685 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
686 somebody invents a time machine, I think we can safely disregard
687 it. This actually works around a stupid Y2K bug that was present
688 in a very early beta release of dhcpd. */
693 /* Slash seperating year from month... */
694 token
= next_token (&val
, (unsigned *)0, cfile
);
695 if (token
!= SLASH
) {
697 "expected slash seperating year from month.");
699 skip_to_semi (cfile
);
704 token
= next_token (&val
, (unsigned *)0, cfile
);
705 if (token
!= NUMBER
) {
706 parse_warn (cfile
, "numeric month expected.");
708 skip_to_semi (cfile
);
711 mon
= atoi (val
) - 1;
713 /* Slash seperating month from day... */
714 token
= next_token (&val
, (unsigned *)0, cfile
);
715 if (token
!= SLASH
) {
717 "expected slash seperating month from day.");
719 skip_to_semi (cfile
);
723 /* Day of month... */
724 token
= next_token (&val
, (unsigned *)0, cfile
);
725 if (token
!= NUMBER
) {
726 parse_warn (cfile
, "numeric day of month expected.");
728 skip_to_semi (cfile
);
734 token
= next_token (&val
, (unsigned *)0, cfile
);
735 if (token
!= NUMBER
) {
736 parse_warn (cfile
, "numeric hour expected.");
738 skip_to_semi (cfile
);
743 /* Colon seperating hour from minute... */
744 token
= next_token (&val
, (unsigned *)0, cfile
);
745 if (token
!= COLON
) {
747 "expected colon seperating hour from minute.");
749 skip_to_semi (cfile
);
754 token
= next_token (&val
, (unsigned *)0, cfile
);
755 if (token
!= NUMBER
) {
756 parse_warn (cfile
, "numeric minute expected.");
758 skip_to_semi (cfile
);
763 /* Colon seperating minute from second... */
764 token
= next_token (&val
, (unsigned *)0, cfile
);
765 if (token
!= COLON
) {
767 "expected colon seperating hour from minute.");
769 skip_to_semi (cfile
);
774 token
= next_token (&val
, (unsigned *)0, cfile
);
775 if (token
!= NUMBER
) {
776 parse_warn (cfile
, "numeric minute expected.");
778 skip_to_semi (cfile
);
783 token
= peek_token (&val
, (unsigned *)0, cfile
);
784 if (token
== NUMBER
) {
785 token
= next_token (&val
, (unsigned *)0, cfile
);
790 /* Make sure the date ends in a semicolon... */
791 if (!parse_semi (cfile
))
794 /* Guess the time value... */
795 guess
= ((((((365 * (year
- 70) + /* Days in years since '70 */
796 (year
- 69) / 4 + /* Leap days since '70 */
797 (mon
/* Days in months this year */
800 (mon
> 1 && /* Leap day this year */
801 !((year
- 72) & 3)) +
802 mday
- 1) * 24) + /* Day of month */
804 min
) * 60) + sec
+ tzoff
;
806 /* This guess could be wrong because of leap seconds or other
807 weirdness we don't know about that the system does. For
808 now, we're just going to accept the guess, but at some point
809 it might be nice to do a successive approximation here to
810 get an exact value. Even if the error is small, if the
811 server is restarted frequently (and thus the lease database
812 is reread), the error could accumulate into something
819 * option-name :== IDENTIFIER |
820 IDENTIFIER . IDENTIFIER
823 struct option
*parse_option_name (cfile
, allocate
, known
)
829 enum dhcp_token token
;
831 struct universe
*universe
;
832 struct option
*option
;
834 token
= next_token (&val
, (unsigned *)0, cfile
);
835 if (!is_identifier (token
)) {
837 "expecting identifier after option keyword.");
839 skip_to_semi (cfile
);
840 return (struct option
*)0;
842 uname
= dmalloc (strlen (val
) + 1, MDL
);
844 log_fatal ("no memory for uname information.");
846 token
= peek_token (&val
, (unsigned *)0, cfile
);
848 /* Go ahead and take the DOT token... */
849 token
= next_token (&val
, (unsigned *)0, cfile
);
851 /* The next token should be an identifier... */
852 token
= next_token (&val
, (unsigned *)0, cfile
);
853 if (!is_identifier (token
)) {
854 parse_warn (cfile
, "expecting identifier after '.'");
856 skip_to_semi (cfile
);
857 return (struct option
*)0;
860 /* Look up the option name hash table for the specified
862 universe
= (struct universe
*)0;
863 if (!universe_hash_lookup (&universe
, universe_hash
,
865 parse_warn (cfile
, "no option space named %s.", uname
);
866 skip_to_semi (cfile
);
867 return (struct option
*)0;
870 /* Use the default hash table, which contains all the
871 standard dhcp option names. */
873 universe
= &dhcp_universe
;
876 /* Look up the actual option info... */
877 option
= (struct option
*)0;
878 option_hash_lookup (&option
, universe
-> hash
, val
, 0, MDL
);
880 /* If we didn't get an option structure, it's an undefined option. */
885 /* If we've been told to allocate, that means that this
886 (might) be an option code definition, so we'll create
887 an option structure just in case. */
889 option
= new_option (MDL
);
891 option
-> name
= val
;
895 s
= dmalloc (strlen (val
) + 1, MDL
);
897 log_fatal ("no memory for option %s.%s",
898 universe
-> name
, val
);
902 option
-> universe
= universe
;
907 parse_warn (cfile
, "no option named %s", val
);
909 parse_warn (cfile
, "no option named %s in space %s",
911 skip_to_semi (cfile
);
912 return (struct option
*)0;
915 /* Free the initial identifier token. */
920 /* IDENTIFIER SEMI */
922 void parse_option_space_decl (cfile
)
927 struct universe
**ua
, *nu
;
930 next_token (&val
, (unsigned *)0, cfile
); /* Discard the SPACE token,
931 which was checked by the
933 token
= next_token (&val
, (unsigned *)0, cfile
);
934 if (!is_identifier (token
)) {
935 parse_warn (cfile
, "expecting identifier.");
936 skip_to_semi (cfile
);
939 nu
= new_universe (MDL
);
941 log_fatal ("No memory for new option space.");
943 /* Set up the server option universe... */
944 s
= dmalloc (strlen (val
) + 1, MDL
);
946 log_fatal ("No memory for new option space name.");
949 nu
-> lookup_func
= lookup_hashed_option
;
950 nu
-> option_state_dereference
=
951 hashed_option_state_dereference
;
952 nu
-> foreach
= hashed_option_space_foreach
;
953 nu
-> save_func
= save_hashed_option
;
954 nu
-> delete_func
= delete_hashed_option
;
955 nu
-> encapsulate
= hashed_option_space_encapsulate
;
956 nu
-> decode
= parse_option_buffer
;
957 nu
-> length_size
= 1;
959 nu
-> store_tag
= putUChar
;
960 nu
-> store_length
= putUChar
;
961 nu
-> index
= universe_count
++;
962 if (nu
-> index
>= universe_max
) {
963 ua
= dmalloc (universe_max
* 2 * sizeof *ua
, MDL
);
965 log_fatal ("No memory to expand option space array.");
966 memcpy (ua
, universes
, universe_max
* sizeof *ua
);
968 dfree (universes
, MDL
);
971 universes
[nu
-> index
] = nu
;
972 option_new_hash (&nu
-> hash
, 1, MDL
);
974 log_fatal ("Can't allocate %s option hash table.", nu
-> name
);
975 universe_hash_add (universe_hash
, nu
-> name
, 0, nu
, MDL
);
979 /* This is faked up to look good right now. Ideally, this should do a
980 recursive parse and allow arbitrary data structure definitions, but for
981 now it just allows you to specify a single type, an array of single types,
982 a sequence of types, or an array of sequences of types.
984 ocd :== NUMBER EQUALS ocsd SEMI
988 ARRAY OF ocsd_simple_type_sequence
990 ocsd_type_sequence :== LBRACE ocsd_types RBRACE
992 ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE
994 ocsd_types :== ocsd_type |
997 ocsd_type :== ocsd_simple_type |
998 ARRAY OF ocsd_simple_type
1000 ocsd_simple_types :== ocsd_simple_type |
1001 ocsd_simple_types ocsd_simple_type
1003 ocsd_simple_type :== BOOLEAN |
1005 SIGNED INTEGER NUMBER |
1006 UNSIGNED INTEGER NUMBER |
1010 ENCAPSULATE identifier */
1012 int parse_option_code_definition (cfile
, option
)
1013 struct parse
*cfile
;
1014 struct option
*option
;
1017 enum dhcp_token token
;
1018 unsigned arrayp
= 0;
1020 int no_more_in_record
= 0;
1027 int has_encapsulation
= 0;
1029 /* Parse the option code. */
1030 token
= next_token (&val
, (unsigned *)0, cfile
);
1031 if (token
!= NUMBER
) {
1032 parse_warn (cfile
, "expecting option code number.");
1033 skip_to_semi (cfile
);
1036 option
-> code
= atoi (val
);
1038 token
= next_token (&val
, (unsigned *)0, cfile
);
1039 if (token
!= EQUAL
) {
1040 parse_warn (cfile
, "expecting \"=\"");
1041 skip_to_semi (cfile
);
1045 /* See if this is an array. */
1046 token
= next_token (&val
, (unsigned *)0, cfile
);
1047 if (token
== ARRAY
) {
1048 token
= next_token (&val
, (unsigned *)0, cfile
);
1050 parse_warn (cfile
, "expecting \"of\".");
1051 skip_to_semi (cfile
);
1055 token
= next_token (&val
, (unsigned *)0, cfile
);
1058 if (token
== LBRACE
) {
1060 token
= next_token (&val
, (unsigned *)0, cfile
);
1063 /* At this point we're expecting a data type. */
1065 if (has_encapsulation
) {
1067 "encapsulate must always be the last item.");
1068 skip_to_semi (cfile
);
1075 parse_warn (cfile
, "no nested arrays.");
1076 skip_to_rbrace (cfile
, recordp
);
1078 skip_to_semi (cfile
);
1081 token
= next_token (&val
, (unsigned *)0, cfile
);
1083 parse_warn (cfile
, "expecting \"of\".");
1084 skip_to_semi (cfile
);
1087 arrayp
= recordp
+ 1;
1088 token
= next_token (&val
, (unsigned *)0, cfile
);
1089 if ((recordp
) && (token
== LBRACE
)) {
1091 "only uniform array inside record.");
1092 skip_to_rbrace (cfile
, recordp
+ 1);
1093 skip_to_semi (cfile
);
1103 token
= next_token (&val
, (unsigned *)0, cfile
);
1104 if (token
!= NUMBER
) {
1105 parse_warn (cfile
, "expecting number.");
1106 skip_to_rbrace (cfile
, recordp
);
1108 skip_to_semi (cfile
);
1111 switch (atoi (val
)) {
1113 type
= is_signed
? 'b' : 'B';
1116 type
= is_signed
? 's' : 'S';
1119 type
= is_signed
? 'l' : 'L';
1123 "%s bit precision is not supported.", val
);
1124 skip_to_rbrace (cfile
, recordp
);
1126 skip_to_semi (cfile
);
1133 token
= next_token (&val
, (unsigned *)0, cfile
);
1134 if (token
!= INTEGER
) {
1135 parse_warn (cfile
, "expecting \"integer\" keyword.");
1136 skip_to_rbrace (cfile
, recordp
);
1138 skip_to_semi (cfile
);
1156 parse_warn (cfile
, "arrays of text strings not %s",
1158 skip_to_rbrace (cfile
, recordp
);
1160 skip_to_semi (cfile
);
1163 no_more_in_record
= 1;
1170 token
= next_token (&val
, (unsigned *)0, cfile
);
1171 if (!is_identifier (token
)) {
1173 "expecting option space identifier");
1174 skip_to_semi (cfile
);
1177 if (strlen (val
) + tokix
+ 2 > sizeof (tokbuf
))
1179 tokbuf
[tokix
++] = 'E';
1180 strcpy (&tokbuf
[tokix
], val
);
1181 tokix
+= strlen (val
);
1183 has_encapsulation
= 1;
1187 parse_warn (cfile
, "unknown data type %s", val
);
1188 skip_to_rbrace (cfile
, recordp
);
1190 skip_to_semi (cfile
);
1194 if (tokix
== sizeof tokbuf
) {
1196 parse_warn (cfile
, "too many types in record.");
1197 skip_to_rbrace (cfile
, recordp
);
1199 skip_to_semi (cfile
);
1202 tokbuf
[tokix
++] = type
;
1205 token
= next_token (&val
, (unsigned *)0, cfile
);
1206 if (arrayp
> recordp
) {
1207 if (tokix
== sizeof tokbuf
) {
1209 "too many types in record.");
1210 skip_to_rbrace (cfile
, 1);
1211 skip_to_semi (cfile
);
1215 tokbuf
[tokix
++] = 'a';
1217 if (token
== COMMA
) {
1218 if (no_more_in_record
) {
1220 "%s must be at end of record.",
1221 type
== 't' ? "text" : "string");
1222 skip_to_rbrace (cfile
, 1);
1224 skip_to_semi (cfile
);
1227 token
= next_token (&val
, (unsigned *)0, cfile
);
1230 if (token
!= RBRACE
) {
1231 parse_warn (cfile
, "expecting right brace.");
1232 skip_to_rbrace (cfile
, 1);
1234 skip_to_semi (cfile
);
1238 if (!parse_semi (cfile
)) {
1239 parse_warn (cfile
, "semicolon expected.");
1240 skip_to_semi (cfile
);
1242 skip_to_semi (cfile
);
1245 if (has_encapsulation
&& arrayp
) {
1247 "Arrays of encapsulations don't make sense.");
1250 if (has_encapsulation
&& tokbuf
[0] == 'E')
1251 has_encapsulation
= 0;
1252 s
= dmalloc (tokix
+
1254 (has_encapsulation
? 1 : 0) + 1, MDL
);
1256 log_fatal ("no memory for option format.");
1257 if (has_encapsulation
)
1259 memcpy (s
+ has_encapsulation
, tokbuf
, tokix
);
1260 tokix
+= has_encapsulation
;
1262 s
[tokix
++] = (arrayp
> recordp
) ? 'a' : 'A';
1264 option
-> format
= s
;
1265 if (option
-> universe
-> options
[option
-> code
]) {
1266 /* XXX Free the option, but we can't do that now because they
1267 XXX may start out static. */
1269 option
-> universe
-> options
[option
-> code
] = option
;
1270 option_hash_add (option
-> universe
-> hash
,
1271 (const char *)option
-> name
,
1277 * base64 :== NUMBER_OR_STRING
1280 int parse_base64 (data
, cfile
)
1281 struct data_string
*data
;
1282 struct parse
*cfile
;
1284 enum dhcp_token token
;
1288 static unsigned char
1289 from64
[] = {64, 64, 64, 64, 64, 64, 64, 64, /* \"#$%&' */
1290 64, 64, 64, 62, 64, 64, 64, 63, /* ()*+,-./ */
1291 52, 53, 54, 55, 56, 57, 58, 59, /* 01234567 */
1292 60, 61, 64, 64, 64, 64, 64, 64, /* 89:;<=>? */
1293 64, 0, 1, 2, 3, 4, 5, 6, /* @ABCDEFG */
1294 7, 8, 9, 10, 11, 12, 13, 14, /* HIJKLMNO */
1295 15, 16, 17, 18, 19, 20, 21, 22, /* PQRSTUVW */
1296 23, 24, 25, 64, 64, 64, 64, 64, /* XYZ[\]^_ */
1297 64, 26, 27, 28, 29, 30, 31, 32, /* 'abcdefg */
1298 33, 34, 35, 36, 37, 38, 39, 40, /* hijklmno */
1299 41, 42, 43, 44, 45, 46, 47, 48, /* pqrstuvw */
1300 49, 50, 51, 64, 64, 64, 64, 64}; /* xyz{|}~ */
1301 struct string_list
*bufs
= (struct string_list
*)0,
1302 *last
= (struct string_list
*)0,
1307 /* It's possible for a + or a / to cause a base64 quantity to be
1308 tokenized into more than one token, so we have to parse them all
1309 in before decoding. */
1313 token
= next_token (&val
, &l
, cfile
);
1314 t
= dmalloc (l
+ sizeof *t
, MDL
);
1316 log_fatal ("no memory for base64 buffer.");
1317 memset (t
, 0, (sizeof *t
) - 1);
1318 memcpy (t
-> string
, val
, l
+ 1);
1325 token
= peek_token (&val
, (unsigned *)0, cfile
);
1326 } while (token
== NUMBER_OR_NAME
|| token
== NAME
|| token
== EQUAL
||
1327 token
== NUMBER
|| token
== PLUS
|| token
== SLASH
||
1331 data
-> len
= (data
-> len
* 3) / 4;
1332 if (!buffer_allocate (&data
-> buffer
, data
-> len
, MDL
)) {
1333 parse_warn (cfile
, "can't allocate buffer for base64 data.");
1335 data
-> data
= (unsigned char *)0;
1340 for (t
= bufs
; t
; t
= t
-> next
) {
1341 for (i
= 0; t
-> string
[i
]; i
++) {
1342 unsigned foo
= t
-> string
[i
];
1343 if (terminated
&& foo
!= '=') {
1345 "stuff after base64 '=' terminator: %s.",
1349 if (foo
< ' ' || foo
> 'z') {
1352 "invalid base64 character %d.",
1355 data_string_forget (data
, MDL
);
1361 foo
= from64
[foo
- ' '];
1364 acc
= (acc
<< 6) + foo
;
1369 data
-> buffer
-> data
[j
++] = (acc
>> 4);
1374 data
-> buffer
-> data
[j
++] = (acc
>> 2);
1378 data
-> buffer
-> data
[j
++] = acc
;
1389 "partial base64 value left over: %d.",
1394 data
-> data
= data
-> buffer
-> data
;
1396 for (t
= bufs
; t
; t
= last
) {
1408 * colon-seperated-hex-list :== NUMBER |
1409 * NUMBER COLON colon-seperated-hex-list
1412 int parse_cshl (data
, cfile
)
1413 struct data_string
*data
;
1414 struct parse
*cfile
;
1416 u_int8_t ibuf
[128];
1419 struct option_tag
*sl
= (struct option_tag
*)0;
1420 struct option_tag
*next
, **last
= &sl
;
1421 enum dhcp_token token
;
1426 token
= next_token (&val
, (unsigned *)0, cfile
);
1427 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
1428 parse_warn (cfile
, "expecting hexadecimal number.");
1429 skip_to_semi (cfile
);
1430 for (; sl
; sl
= next
) {
1436 if (ilen
== sizeof ibuf
) {
1437 next
= (struct option_tag
*)
1439 sizeof (struct option_tag
), MDL
);
1441 log_fatal ("no memory for string list.");
1442 memcpy (next
-> data
, ibuf
, ilen
);
1444 last
= &next
-> next
;
1448 convert_num (cfile
, &ibuf
[ilen
++], val
, 16, 8);
1450 token
= peek_token (&val
, (unsigned *)0, cfile
);
1453 token
= next_token (&val
, (unsigned *)0, cfile
);
1456 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, MDL
))
1457 log_fatal ("no memory to store octet data.");
1458 data
-> data
= &data
-> buffer
-> data
[0];
1459 data
-> len
= tlen
+ ilen
;
1460 data
-> terminated
= 0;
1462 rvp
= &data
-> buffer
-> data
[0];
1465 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
1471 memcpy (rvp
, ibuf
, ilen
);
1476 * executable-statements :== executable-statement executable-statements |
1477 * executable-statement
1479 * executable-statement :==
1481 * ADD class-name SEMI |
1483 * OPTION option-parameter SEMI |
1484 * SUPERSEDE option-parameter SEMI |
1485 * PREPEND option-parameter SEMI |
1486 * APPEND option-parameter SEMI
1489 int parse_executable_statements (statements
, cfile
, lose
, case_context
)
1490 struct executable_statement
**statements
;
1491 struct parse
*cfile
;
1493 enum expression_context case_context
;
1495 struct executable_statement
**next
;
1498 while (parse_executable_statement (next
, cfile
, lose
, case_context
))
1499 next
= &((*next
) -> next
);
1505 int parse_executable_statement (result
, cfile
, lose
, case_context
)
1506 struct executable_statement
**result
;
1507 struct parse
*cfile
;
1509 enum expression_context case_context
;
1511 enum dhcp_token token
;
1513 struct executable_statement base
;
1515 struct option
*option
;
1516 struct option_cache
*cache
;
1520 struct dns_zone
*zone
;
1521 isc_result_t status
;
1524 token
= peek_token (&val
, (unsigned *)0, cfile
);
1527 next_token (&val
, (unsigned *)0, cfile
);
1528 return parse_if_statement (result
, cfile
, lose
);
1531 token
= next_token (&val
, (unsigned *)0, cfile
);
1532 token
= next_token (&val
, (unsigned *)0, cfile
);
1533 if (token
!= STRING
) {
1534 parse_warn (cfile
, "expecting class name.");
1535 skip_to_semi (cfile
);
1539 cta
= (struct class *)0;
1540 status
= find_class (&cta
, val
, MDL
);
1541 if (status
!= ISC_R_SUCCESS
) {
1542 parse_warn (cfile
, "class %s: %s",
1543 val
, isc_result_totext (status
));
1544 skip_to_semi (cfile
);
1548 if (!parse_semi (cfile
)) {
1552 if (!executable_statement_allocate (result
, MDL
))
1553 log_fatal ("no memory for new statement.");
1554 (*result
) -> op
= add_statement
;
1555 (*result
) -> data
.add
= cta
;
1559 token
= next_token (&val
, (unsigned *)0, cfile
);
1560 if (!parse_semi (cfile
)) {
1564 if (!executable_statement_allocate (result
, MDL
))
1565 log_fatal ("no memory for new statement.");
1566 (*result
) -> op
= break_statement
;
1570 token
= next_token (&val
, (unsigned *)0, cfile
);
1572 option
= parse_option_name (cfile
, 0, &known
);
1577 return parse_option_statement (result
, cfile
, 1, option
,
1578 send_option_statement
);
1582 token
= next_token (&val
, (unsigned *)0, cfile
);
1584 option
= parse_option_name (cfile
, 0, &known
);
1589 return parse_option_statement (result
, cfile
, 1, option
,
1590 supersede_option_statement
);
1601 token
= next_token (&val
, (unsigned *)0, cfile
);
1602 cache
= (struct option_cache
*)0;
1603 if (!parse_allow_deny (&cache
, cfile
, flag
))
1605 if (!executable_statement_allocate (result
, MDL
))
1606 log_fatal ("no memory for new statement.");
1607 (*result
) -> op
= supersede_option_statement
;
1608 (*result
) -> data
.option
= cache
;
1612 token
= next_token (&val
, (unsigned *)0, cfile
);
1613 token
= peek_token (&val
, (unsigned *)0, cfile
);
1615 goto switch_default
;
1617 option
= parse_option_name (cfile
, 0, &known
);
1622 return parse_option_statement (result
, cfile
, 1, option
,
1623 default_option_statement
);
1626 token
= next_token (&val
, (unsigned *)0, cfile
);
1628 option
= parse_option_name (cfile
, 0, &known
);
1633 return parse_option_statement (result
, cfile
, 1, option
,
1634 prepend_option_statement
);
1637 token
= next_token (&val
, (unsigned *)0, cfile
);
1639 option
= parse_option_name (cfile
, 0, &known
);
1644 return parse_option_statement (result
, cfile
, 1, option
,
1645 append_option_statement
);
1648 token
= next_token (&val
, (unsigned *)0, cfile
);
1649 return parse_on_statement (result
, cfile
, lose
);
1652 token
= next_token (&val
, (unsigned *)0, cfile
);
1653 return parse_switch_statement (result
, cfile
, lose
);
1656 token
= next_token (&val
, (unsigned *)0, cfile
);
1657 if (case_context
== context_any
) {
1659 "case statement in inappropriate scope.");
1661 skip_to_semi (cfile
);
1664 return parse_case_statement (result
,
1665 cfile
, lose
, case_context
);
1668 token
= next_token (&val
, (unsigned *)0, cfile
);
1669 if (case_context
== context_any
) {
1670 parse_warn (cfile
, "switch default statement in %s",
1671 "inappropriate scope.");
1676 if (!executable_statement_allocate (result
, MDL
))
1677 log_fatal ("no memory for default statement.");
1678 (*result
) -> op
= default_statement
;
1684 token
= next_token (&val
, (unsigned *)0, cfile
);
1685 if (token
== DEFINE
)
1690 token
= next_token (&val
, (unsigned *)0, cfile
);
1691 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1693 "%s can't be a variable name", val
);
1695 skip_to_semi (cfile
);
1700 if (!executable_statement_allocate (result
, MDL
))
1701 log_fatal ("no memory for set statement.");
1702 (*result
) -> op
= flag
? define_statement
: set_statement
;
1703 (*result
) -> data
.set
.name
= dmalloc (strlen (val
) + 1, MDL
);
1704 if (!(*result
)->data
.set
.name
)
1705 log_fatal ("can't allocate variable name");
1706 strcpy ((*result
) -> data
.set
.name
, val
);
1707 token
= next_token (&val
, (unsigned *)0, cfile
);
1709 if (token
== LPAREN
) {
1710 struct string_list
*head
, *cur
, *new;
1711 struct expression
*expr
;
1712 head
= cur
= (struct string_list
*)0;
1714 token
= next_token (&val
,
1715 (unsigned *)0, cfile
);
1716 if (token
== RPAREN
)
1718 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1720 "expecting argument name");
1721 skip_to_rbrace (cfile
, 0);
1723 executable_statement_dereference
1727 new = ((struct string_list
*)
1728 dmalloc (sizeof (struct string_list
) +
1729 strlen (val
), MDL
));
1731 log_fatal ("can't allocate string.");
1732 memset (new, 0, sizeof *new);
1733 strcpy (new -> string
, val
);
1740 token
= next_token (&val
,
1741 (unsigned *)0, cfile
);
1742 } while (token
== COMMA
);
1744 if (token
!= RPAREN
) {
1745 parse_warn (cfile
, "expecting right paren.");
1747 skip_to_semi (cfile
);
1749 executable_statement_dereference (result
, MDL
);
1753 token
= next_token (&val
, (unsigned *)0, cfile
);
1754 if (token
!= LBRACE
) {
1755 parse_warn (cfile
, "expecting left brace.");
1759 expr
= (struct expression
*)0;
1760 if (!(expression_allocate (&expr
, MDL
)))
1761 log_fatal ("can't allocate expression.");
1762 expr
-> op
= expr_function
;
1763 if (!fundef_allocate (&expr
-> data
.func
, MDL
))
1764 log_fatal ("can't allocate fundef.");
1765 expr
-> data
.func
-> args
= head
;
1766 (*result
) -> data
.set
.expr
= expr
;
1768 if (!(parse_executable_statements
1769 (&expr
-> data
.func
-> statements
, cfile
, lose
,
1775 token
= next_token (&val
, (unsigned *)0, cfile
);
1776 if (token
!= RBRACE
) {
1777 parse_warn (cfile
, "expecting rigt brace.");
1781 if (token
!= EQUAL
) {
1783 "expecting '=' in %s statement.",
1784 flag
? "define" : "set");
1788 if (!parse_expression (&(*result
) -> data
.set
.expr
,
1789 cfile
, lose
, context_any
,
1790 (struct expression
**)0,
1794 "expecting expression.");
1797 skip_to_semi (cfile
);
1798 executable_statement_dereference (result
, MDL
);
1801 if (!parse_semi (cfile
)) {
1803 executable_statement_dereference (result
, MDL
);
1810 token
= next_token (&val
, (unsigned *)0, cfile
);
1812 token
= next_token (&val
, (unsigned *)0, cfile
);
1813 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
1815 "%s can't be a variable name", val
);
1817 skip_to_semi (cfile
);
1822 if (!executable_statement_allocate (result
, MDL
))
1823 log_fatal ("no memory for set statement.");
1824 (*result
) -> op
= unset_statement
;
1825 (*result
) -> data
.unset
= dmalloc (strlen (val
) + 1, MDL
);
1826 if (!(*result
)->data
.unset
)
1827 log_fatal ("can't allocate variable name");
1828 strcpy ((*result
) -> data
.unset
, val
);
1829 if (!parse_semi (cfile
)) {
1831 executable_statement_dereference (result
, MDL
);
1837 token
= next_token (&val
, (unsigned *)0, cfile
);
1839 if (!executable_statement_allocate (result
, MDL
))
1840 log_fatal ("no memory for eval statement.");
1841 (*result
) -> op
= eval_statement
;
1843 if (!parse_expression (&(*result
) -> data
.eval
,
1844 cfile
, lose
, context_data
, /* XXX */
1845 (struct expression
**)0, expr_none
)) {
1848 "expecting data expression.");
1851 skip_to_semi (cfile
);
1852 executable_statement_dereference (result
, MDL
);
1855 if (!parse_semi (cfile
)) {
1857 executable_statement_dereference (result
, MDL
);
1862 token
= next_token (&val
, (unsigned *)0, cfile
);
1864 if (!executable_statement_allocate (result
, MDL
))
1865 log_fatal ("no memory for return statement.");
1866 (*result
) -> op
= return_statement
;
1868 if (!parse_expression (&(*result
) -> data
.retval
,
1869 cfile
, lose
, context_data
,
1870 (struct expression
**)0, expr_none
)) {
1873 "expecting data expression.");
1876 skip_to_semi (cfile
);
1877 executable_statement_dereference (result
, MDL
);
1880 if (!parse_semi (cfile
)) {
1882 executable_statement_dereference (result
, MDL
);
1888 token
= next_token (&val
, (unsigned *)0, cfile
);
1890 if (!executable_statement_allocate (result
, MDL
))
1891 log_fatal ("no memory for log statement.");
1892 (*result
) -> op
= log_statement
;
1894 token
= next_token (&val
, (unsigned *)0, cfile
);
1895 if (token
!= LPAREN
) {
1896 parse_warn (cfile
, "left parenthesis expected.");
1897 skip_to_semi (cfile
);
1902 token
= peek_token (&val
, (unsigned *)0, cfile
);
1904 if (token
== FATAL
) {
1905 (*result
) -> data
.log
.priority
= log_priority_fatal
;
1906 } else if (token
== ERROR
) {
1907 (*result
) -> data
.log
.priority
= log_priority_error
;
1908 } else if (token
== TOKEN_DEBUG
) {
1909 (*result
) -> data
.log
.priority
= log_priority_debug
;
1910 } else if (token
== INFO
) {
1911 (*result
) -> data
.log
.priority
= log_priority_info
;
1913 (*result
) -> data
.log
.priority
= log_priority_debug
;
1917 token
= next_token (&val
, (unsigned *)0, cfile
);
1918 token
= next_token (&val
, (unsigned *)0, cfile
);
1919 if (token
!= COMMA
) {
1920 parse_warn (cfile
, "comma expected.");
1921 skip_to_semi (cfile
);
1927 if (!(parse_data_expression
1928 (&(*result
) -> data
.log
.expr
, cfile
, lose
))) {
1929 skip_to_semi (cfile
);
1934 token
= next_token (&val
, (unsigned *)0, cfile
);
1935 if (token
!= RPAREN
) {
1936 parse_warn (cfile
, "right parenthesis expected.");
1937 skip_to_semi (cfile
);
1942 token
= next_token (&val
, (unsigned *)0, cfile
);
1943 if (token
!= SEMI
) {
1944 parse_warn (cfile
, "semicolon expected.");
1945 skip_to_semi (cfile
);
1951 /* Not really a statement, but we parse it here anyway
1952 because it's appropriate for all DHCP agents with
1955 token
= next_token (&val
, (unsigned *)0, cfile
);
1956 zone
= (struct dns_zone
*)0;
1957 if (!dns_zone_allocate (&zone
, MDL
))
1958 log_fatal ("no memory for new zone.");
1959 zone
-> name
= parse_host_name (cfile
);
1960 if (!zone
-> name
) {
1961 parse_warn (cfile
, "expecting hostname.");
1964 skip_to_semi (cfile
);
1965 dns_zone_dereference (&zone
, MDL
);
1968 i
= strlen (zone
-> name
);
1969 if (zone
-> name
[i
- 1] != '.') {
1970 s
= dmalloc ((unsigned)i
+ 2, MDL
);
1972 parse_warn (cfile
, "no trailing '.' on zone");
1975 strcpy (s
, zone
-> name
);
1978 dfree (zone
-> name
, MDL
);
1981 if (!parse_zone (zone
, cfile
))
1983 status
= enter_dns_zone (zone
);
1984 if (status
!= ISC_R_SUCCESS
) {
1985 parse_warn (cfile
, "dns zone key %s: %s",
1986 zone
-> name
, isc_result_totext (status
));
1987 dns_zone_dereference (&zone
, MDL
);
1990 dns_zone_dereference (&zone
, MDL
);
1993 /* Also not really a statement, but same idea as above. */
1995 token
= next_token (&val
, (unsigned *)0, cfile
);
1996 if (!parse_key (cfile
)) {
2003 if (config_universe
&& is_identifier (token
)) {
2004 option
= (struct option
*)0;
2005 option_hash_lookup (&option
, config_universe
-> hash
,
2008 token
= next_token (&val
,
2009 (unsigned *)0, cfile
);
2010 return parse_option_statement
2011 (result
, cfile
, 1, option
,
2012 supersede_option_statement
);
2016 if (token
== NUMBER_OR_NAME
|| token
== NAME
) {
2017 /* This is rather ugly. Since function calls are
2018 data expressions, fake up an eval statement. */
2019 if (!executable_statement_allocate (result
, MDL
))
2020 log_fatal ("no memory for eval statement.");
2021 (*result
) -> op
= eval_statement
;
2023 if (!parse_expression (&(*result
) -> data
.eval
,
2024 cfile
, lose
, context_data
,
2025 (struct expression
**)0,
2028 parse_warn (cfile
, "expecting "
2032 skip_to_semi (cfile
);
2033 executable_statement_dereference (result
, MDL
);
2036 if (!parse_semi (cfile
)) {
2038 executable_statement_dereference (result
, MDL
);
2051 /* zone-statements :== zone-statement |
2052 zone-statement zone-statements
2054 PRIMARY ip-addresses SEMI |
2055 SECONDARY ip-addresses SEMI |
2057 ip-addresses :== ip-addr-or-hostname |
2058 ip-addr-or-hostname COMMA ip-addresses
2059 key-reference :== KEY STRING |
2062 int parse_zone (struct dns_zone
*zone
, struct parse
*cfile
)
2067 struct option_cache
*oc
;
2070 token
= next_token (&val
, (unsigned *)0, cfile
);
2071 if (token
!= LBRACE
) {
2072 parse_warn (cfile
, "expecting left brace");
2077 token
= peek_token (&val
, (unsigned *)0, cfile
);
2080 if (zone
-> primary
) {
2082 "more than one primary.");
2083 skip_to_semi (cfile
);
2086 if (!option_cache_allocate (&zone
-> primary
, MDL
))
2087 log_fatal ("can't allocate primary option cache.");
2088 oc
= zone
-> primary
;
2092 if (zone
-> secondary
) {
2093 parse_warn (cfile
, "more than one secondary.");
2094 skip_to_semi (cfile
);
2097 if (!option_cache_allocate (&zone
-> secondary
, MDL
))
2098 log_fatal ("can't allocate secondary.");
2099 oc
= zone
-> secondary
;
2101 token
= next_token (&val
, (unsigned *)0, cfile
);
2103 struct expression
*expr
= (struct expression
*)0;
2104 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
2106 "expecting IP addr or hostname.");
2107 skip_to_semi (cfile
);
2110 if (oc
-> expression
) {
2111 struct expression
*old
=
2112 (struct expression
*)0;
2113 expression_reference (&old
,
2116 expression_dereference (&oc
-> expression
,
2118 if (!make_concat (&oc
-> expression
,
2120 log_fatal ("no memory for concat.");
2121 expression_dereference (&expr
, MDL
);
2122 expression_dereference (&old
, MDL
);
2124 expression_reference (&oc
-> expression
,
2126 expression_dereference (&expr
, MDL
);
2128 token
= next_token (&val
, (unsigned *)0, cfile
);
2129 } while (token
== COMMA
);
2130 if (token
!= SEMI
) {
2131 parse_warn (cfile
, "expecting semicolon.");
2132 skip_to_semi (cfile
);
2138 token
= next_token (&val
, (unsigned *)0, cfile
);
2139 token
= peek_token (&val
, (unsigned *)0, cfile
);
2140 if (token
== STRING
) {
2141 token
= next_token (&val
, (unsigned *)0, cfile
);
2142 key_name
= (char *)0;
2144 key_name
= parse_host_name (cfile
);
2146 parse_warn (cfile
, "expecting key name.");
2147 skip_to_semi (cfile
);
2152 if (omapi_auth_key_lookup_name (&zone
-> key
, val
) !=
2154 parse_warn (cfile
, "unknown key %s", val
);
2156 dfree (key_name
, MDL
);
2157 if (!parse_semi (cfile
))
2167 token
= next_token (&val
, (unsigned *)0, cfile
);
2168 if (token
!= RBRACE
) {
2169 parse_warn (cfile
, "expecting right brace.");
2175 /* key-statements :== key-statement |
2176 key-statement key-statements
2178 ALGORITHM host-name SEMI |
2179 secret-definition SEMI
2180 secret-definition :== SECRET base64val |
2183 int parse_key (struct parse
*cfile
)
2188 struct auth_key
*key
;
2189 struct data_string ds
;
2190 isc_result_t status
;
2193 key
= (struct auth_key
*)0;
2194 if (omapi_auth_key_new (&key
, MDL
) != ISC_R_SUCCESS
)
2195 log_fatal ("no memory for key");
2197 token
= peek_token (&val
, (unsigned *)0, cfile
);
2198 if (token
== STRING
) {
2199 token
= next_token (&val
, (unsigned *)0, cfile
);
2200 key
-> name
= dmalloc (strlen (val
) + 1, MDL
);
2202 log_fatal ("no memory for key name.");
2203 strcpy (key
-> name
, val
);
2206 key
-> name
= parse_host_name (cfile
);
2208 parse_warn (cfile
, "expecting key name.");
2209 skip_to_semi (cfile
);
2214 token
= next_token (&val
, (unsigned *)0, cfile
);
2215 if (token
!= LBRACE
) {
2216 parse_warn (cfile
, "expecting left brace");
2221 token
= next_token (&val
, (unsigned *)0, cfile
);
2224 if (key
-> algorithm
) {
2226 "key %s: too many algorithms",
2230 key
-> algorithm
= parse_host_name (cfile
);
2231 if (!key
-> algorithm
) {
2233 "expecting key algorithm name.");
2236 if (!parse_semi (cfile
))
2238 /* If the algorithm name isn't an FQDN, tack on
2239 the .SIG-ALG.REG.NET. domain. */
2240 s
= strrchr (key
-> algorithm
, '.');
2242 static char add
[] = ".SIG-ALG.REG.INT.";
2243 s
= dmalloc (strlen (key
-> algorithm
) +
2246 log_error ("no memory for key %s.",
2250 strcpy (s
, key
-> algorithm
);
2252 dfree (key
-> algorithm
, MDL
);
2253 key
-> algorithm
= s
;
2255 /* If there is no trailing '.', hack one in. */
2256 s
= dmalloc (strlen (key
-> algorithm
) + 2, MDL
);
2258 log_error ("no memory for key %s.",
2262 strcpy (s
, key
-> algorithm
);
2264 dfree (key
-> algorithm
, MDL
);
2265 key
-> algorithm
= s
;
2271 parse_warn (cfile
, "key %s: too many secrets",
2276 memset (&ds
, 0, sizeof(ds
));
2277 if (!parse_base64 (&ds
, cfile
))
2279 status
= omapi_data_string_new (&key
-> key
, ds
.len
,
2281 if (status
!= ISC_R_SUCCESS
)
2283 memcpy (key
-> key
-> value
,
2284 ds
.buffer
-> data
, ds
.len
);
2285 data_string_forget (&ds
, MDL
);
2287 if (!parse_semi (cfile
))
2296 if (token
!= RBRACE
) {
2297 parse_warn (cfile
, "expecting right brace.");
2300 /* Allow the BIND 8 syntax, which has a semicolon after each
2302 token
= peek_token (&val
, (unsigned *)0, cfile
);
2304 token
= next_token (&val
, (unsigned *)0, cfile
);
2306 /* Remember the key. */
2307 status
= omapi_auth_key_enter (key
);
2308 if (status
!= ISC_R_SUCCESS
) {
2309 parse_warn (cfile
, "tsig key %s: %s",
2310 key
-> name
, isc_result_totext (status
));
2313 omapi_auth_key_dereference (&key
, MDL
);
2317 skip_to_rbrace (cfile
, 1);
2319 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 option
*option
;
2792 struct expression
*nexp
, **ep
;
2794 enum expr_op opcode
;
2797 struct executable_statement
*stmt
;
2800 isc_result_t status
, code
;
2803 token
= peek_token (&val
, (unsigned *)0, cfile
);
2805 /* Check for unary operators... */
2808 token
= next_token (&val
, (unsigned *)0, cfile
);
2809 token
= next_token (&val
, (unsigned *)0, cfile
);
2810 if (token
!= STRING
) {
2811 parse_warn (cfile
, "string expected.");
2812 skip_to_semi (cfile
);
2816 for (col
= collections
; col
; col
= col
-> next
)
2817 if (!strcmp (col
-> name
, val
))
2820 parse_warn (cfile
, "unknown collection.");
2824 if (!expression_allocate (expr
, MDL
))
2825 log_fatal ("can't allocate expression");
2826 (*expr
) -> op
= expr_check
;
2827 (*expr
) -> data
.check
= col
;
2831 token
= next_token (&val
, (unsigned *)0, cfile
);
2832 if (context
== context_dns
) {
2833 token
= peek_token (&val
, (unsigned *)0, cfile
);
2836 if (!expression_allocate (expr
, MDL
))
2837 log_fatal ("can't allocate expression");
2838 (*expr
) -> op
= expr_not
;
2839 if (!parse_non_binary (&(*expr
) -> data
.not,
2840 cfile
, lose
, context_boolean
)) {
2842 parse_warn (cfile
, "expression expected");
2843 skip_to_semi (cfile
);
2846 expression_dereference (expr
, MDL
);
2849 if (!is_boolean_expression ((*expr
) -> data
.not)) {
2851 parse_warn (cfile
, "boolean expression expected");
2852 skip_to_semi (cfile
);
2853 expression_dereference (expr
, MDL
);
2859 token
= next_token (&val
, (unsigned *)0, cfile
);
2860 if (!parse_expression (expr
, cfile
, lose
, context
,
2861 (struct expression
**)0, expr_none
)) {
2863 parse_warn (cfile
, "expression expected");
2864 skip_to_semi (cfile
);
2869 token
= next_token (&val
, (unsigned *)0, cfile
);
2870 if (token
!= RPAREN
) {
2872 parse_warn (cfile
, "right paren expected");
2873 skip_to_semi (cfile
);
2879 if (context
== context_dns
)
2881 token
= next_token (&val
, (unsigned *)0, cfile
);
2882 if (!expression_allocate (expr
, MDL
))
2883 log_fatal ("can't allocate expression");
2884 (*expr
) -> op
= expr_exists
;
2886 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
2887 if (!(*expr
) -> data
.option
) {
2889 expression_dereference (expr
, MDL
);
2895 token
= next_token (&val
, (unsigned *)0, cfile
);
2896 if (!expression_allocate (expr
, MDL
))
2897 log_fatal ("can't allocate expression");
2898 (*expr
) -> op
= expr_static
;
2902 token
= next_token (&val
, (unsigned *)0, cfile
);
2903 if (!expression_allocate (expr
, MDL
))
2904 log_fatal ("can't allocate expression");
2905 (*expr
) -> op
= expr_known
;
2909 token
= next_token (&val
, (unsigned *)0, cfile
);
2910 if (!expression_allocate (expr
, MDL
))
2911 log_fatal ("can't allocate expression");
2912 (*expr
) -> op
= expr_substring
;
2914 token
= next_token (&val
, (unsigned *)0, cfile
);
2915 if (token
!= LPAREN
) {
2917 expression_dereference (expr
, MDL
);
2918 parse_warn (cfile
, "left parenthesis expected.");
2923 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
2926 expression_dereference (expr
, MDL
);
2929 "expecting data expression.");
2930 skip_to_semi (cfile
);
2936 token
= next_token (&val
, (unsigned *)0, cfile
);
2937 if (token
!= COMMA
) {
2939 expression_dereference (expr
, MDL
);
2940 parse_warn (cfile
, "comma expected.");
2946 if (!parse_numeric_expression
2947 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
2951 "expecting numeric expression.");
2952 skip_to_semi (cfile
);
2955 expression_dereference (expr
, MDL
);
2959 token
= next_token (&val
, (unsigned *)0, cfile
);
2963 if (!parse_numeric_expression
2964 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
2967 token
= next_token (&val
, (unsigned *)0, cfile
);
2968 if (token
!= RPAREN
) {
2970 parse_warn (cfile
, "right parenthesis expected.");
2972 expression_dereference (expr
, MDL
);
2978 token
= next_token (&val
, (unsigned *)0, cfile
);
2979 if (!expression_allocate (expr
, MDL
))
2980 log_fatal ("can't allocate expression");
2981 (*expr
) -> op
= expr_suffix
;
2983 token
= next_token (&val
, (unsigned *)0, cfile
);
2984 if (token
!= LPAREN
)
2987 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
2991 token
= next_token (&val
, (unsigned *)0, cfile
);
2995 if (!parse_numeric_expression (&(*expr
) -> data
.suffix
.len
,
2999 token
= next_token (&val
, (unsigned *)0, cfile
);
3000 if (token
!= RPAREN
)
3005 token
= next_token (&val
, (unsigned *)0, cfile
);
3006 if (!expression_allocate (expr
, MDL
))
3007 log_fatal ("can't allocate expression");
3008 (*expr
) -> op
= expr_concat
;
3010 token
= next_token (&val
, (unsigned *)0, cfile
);
3011 if (token
!= LPAREN
)
3014 if (!parse_data_expression (&(*expr
) -> data
.concat
[0],
3018 token
= next_token (&val
, (unsigned *)0, cfile
);
3023 if (!parse_data_expression (&(*expr
) -> data
.concat
[1],
3027 token
= next_token (&val
, (unsigned *)0, cfile
);
3029 if (token
== COMMA
) {
3030 nexp
= (struct expression
*)0;
3031 if (!expression_allocate (&nexp
, MDL
))
3032 log_fatal ("can't allocate at CONCAT2");
3033 nexp
-> op
= expr_concat
;
3034 expression_reference (&nexp
-> data
.concat
[0],
3036 expression_dereference (expr
, MDL
);
3037 expression_reference (expr
, nexp
, MDL
);
3038 expression_dereference (&nexp
, MDL
);
3039 goto concat_another
;
3042 if (token
!= RPAREN
)
3046 case BINARY_TO_ASCII
:
3047 token
= next_token (&val
, (unsigned *)0, cfile
);
3048 if (!expression_allocate (expr
, MDL
))
3049 log_fatal ("can't allocate expression");
3050 (*expr
) -> op
= expr_binary_to_ascii
;
3052 token
= next_token (&val
, (unsigned *)0, cfile
);
3053 if (token
!= LPAREN
)
3056 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.base
,
3060 token
= next_token (&val
, (unsigned *)0, cfile
);
3064 if (!parse_numeric_expression (&(*expr
) -> data
.b2a
.width
,
3068 token
= next_token (&val
, (unsigned *)0, cfile
);
3072 if (!parse_data_expression (&(*expr
) -> data
.b2a
.seperator
,
3076 token
= next_token (&val
, (unsigned *)0, cfile
);
3080 if (!parse_data_expression (&(*expr
) -> data
.b2a
.buffer
,
3084 token
= next_token (&val
, (unsigned *)0, cfile
);
3085 if (token
!= RPAREN
)
3090 token
= next_token (&val
, (unsigned *)0, cfile
);
3091 if (!expression_allocate (expr
, MDL
))
3092 log_fatal ("can't allocate expression");
3093 (*expr
) -> op
= expr_reverse
;
3095 token
= next_token (&val
, (unsigned *)0, cfile
);
3096 if (token
!= LPAREN
)
3099 if (!(parse_numeric_expression
3100 (&(*expr
) -> data
.reverse
.width
, cfile
, lose
)))
3103 token
= next_token (&val
, (unsigned *)0, cfile
);
3107 if (!(parse_data_expression
3108 (&(*expr
) -> data
.reverse
.buffer
, cfile
, lose
)))
3111 token
= next_token (&val
, (unsigned *)0, cfile
);
3112 if (token
!= RPAREN
)
3117 /* pick (a, b, c) actually produces an internal representation
3118 that looks like pick (a, pick (b, pick (c, nil))). */
3119 token
= next_token (&val
, (unsigned *)0, cfile
);
3120 if (!(expression_allocate (expr
, MDL
)))
3121 log_fatal ("can't allocate expression");
3123 token
= next_token (&val
, (unsigned *)0, cfile
);
3124 if (token
!= LPAREN
)
3127 nexp
= (struct expression
*)0;
3128 expression_reference (&nexp
, *expr
, MDL
);
3130 nexp
-> op
= expr_pick_first_value
;
3131 if (!(parse_data_expression
3132 (&nexp
-> data
.pick_first_value
.car
,
3136 token
= next_token (&val
, (unsigned *)0, cfile
);
3137 if (token
== COMMA
) {
3138 struct expression
*foo
= (struct expression
*)0;
3139 if (!expression_allocate (&foo
, MDL
))
3140 log_fatal ("can't allocate expr");
3141 expression_reference
3142 (&nexp
-> data
.pick_first_value
.cdr
, foo
, MDL
);
3143 expression_dereference (&nexp
, MDL
);
3144 expression_reference (&nexp
, foo
, MDL
);
3145 expression_dereference (&foo
, MDL
);
3147 } while (token
== COMMA
);
3148 expression_dereference (&nexp
, MDL
);
3150 if (token
!= RPAREN
)
3154 /* dns-update and dns-delete are present for historical
3155 purposes, but are deprecated in favor of ns-update
3156 in combination with update, delete, exists and not
3160 #if !defined (NSUPDATE)
3162 "Please rebuild dhcpd with --with-nsupdate.");
3164 token
= next_token (&val
, (unsigned *)0, cfile
);
3165 if (token
== DNS_UPDATE
)
3166 opcode
= expr_ns_add
;
3168 opcode
= expr_ns_delete
;
3170 token
= next_token (&val
, (unsigned *)0, cfile
);
3171 if (token
!= LPAREN
)
3174 token
= next_token (&val
, (unsigned *)0, cfile
);
3175 if (token
!= STRING
) {
3177 "parse_expression: expecting string.");
3179 skip_to_semi (cfile
);
3184 if (!strcasecmp (val
, "a"))
3186 else if (!strcasecmp (val
, "ptr"))
3188 else if (!strcasecmp (val
, "mx"))
3190 else if (!strcasecmp (val
, "cname"))
3192 else if (!strcasecmp (val
, "TXT"))
3195 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3199 s
= (opcode
== expr_ns_add
3201 : "old-dns-delete");
3202 cptr
= dmalloc (strlen (s
) + 1, MDL
);
3204 log_fatal ("can't allocate name for %s", s
);
3206 if (!expression_allocate (expr
, MDL
))
3207 log_fatal ("can't allocate expression");
3208 (*expr
) -> op
= expr_funcall
;
3209 (*expr
) -> data
.funcall
.name
= cptr
;
3211 /* Fake up a function call. */
3212 ep
= &(*expr
) -> data
.funcall
.arglist
;
3213 if (!expression_allocate (ep
, MDL
))
3214 log_fatal ("can't allocate expression");
3215 (*ep
) -> op
= expr_arg
;
3216 if (!make_const_int (&(*ep
) -> data
.arg
.val
, u
))
3217 log_fatal ("can't allocate rrtype value.");
3219 token
= next_token (&val
, (unsigned *)0, cfile
);
3222 ep
= &((*ep
) -> data
.arg
.next
);
3223 if (!expression_allocate (ep
, MDL
))
3224 log_fatal ("can't allocate expression");
3225 (*ep
) -> op
= expr_arg
;
3226 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3230 token
= next_token (&val
, (unsigned *)0, cfile
);
3234 ep
= &((*ep
) -> data
.arg
.next
);
3235 if (!expression_allocate (ep
, MDL
))
3236 log_fatal ("can't allocate expression");
3237 (*ep
) -> op
= expr_arg
;
3238 if (!(parse_data_expression (&(*ep
) -> data
.arg
.val
,
3242 if (opcode
== expr_ns_add
) {
3243 token
= next_token (&val
, (unsigned *)0, cfile
);
3247 ep
= &((*ep
) -> data
.arg
.next
);
3248 if (!expression_allocate (ep
, MDL
))
3249 log_fatal ("can't allocate expression");
3250 (*ep
) -> op
= expr_arg
;
3251 if (!(parse_numeric_expression (&(*ep
) -> data
.arg
.val
,
3254 "expecting numeric expression.");
3259 token
= next_token (&val
, (unsigned *)0, cfile
);
3260 if (token
!= RPAREN
)
3265 #if !defined (NSUPDATE)
3267 "Please rebuild dhcpd with --with-nsupdate.");
3269 token
= next_token (&val
, (unsigned *)0, cfile
);
3270 if (!expression_allocate (expr
, MDL
))
3271 log_fatal ("can't allocate expression");
3273 token
= next_token (&val
, (unsigned *)0, cfile
);
3274 if (token
!= LPAREN
)
3279 nexp
-> op
= expr_dns_transaction
;
3280 if (!(parse_dns_expression
3281 (&nexp
-> data
.dns_transaction
.car
,
3287 "expecting dns expression.");
3289 expression_dereference (expr
, MDL
);
3294 token
= next_token (&val
, (unsigned *)0, cfile
);
3296 if (token
== COMMA
) {
3297 if (!(expression_allocate
3298 (&nexp
-> data
.dns_transaction
.cdr
,
3301 ("can't allocate expression");
3302 nexp
= nexp
-> data
.dns_transaction
.cdr
;
3304 } while (token
== COMMA
);
3306 if (token
!= RPAREN
)
3310 /* NOT EXISTS is special cased above... */
3312 token
= peek_token (&val
, (unsigned *)0, cfile
);
3313 if (token
!= EXISTS
) {
3314 parse_warn (cfile
, "expecting DNS prerequisite.");
3318 opcode
= expr_ns_not_exists
;
3321 opcode
= expr_ns_add
;
3324 opcode
= expr_ns_delete
;
3327 opcode
= expr_ns_exists
;
3329 token
= next_token (&val
, (unsigned *)0, cfile
);
3331 #if !defined (NSUPDATE)
3333 "Please rebuild dhcpd with --with-nsupdate.");
3335 if (!expression_allocate (expr
, MDL
))
3336 log_fatal ("can't allocate expression");
3337 (*expr
) -> op
= opcode
;
3339 token
= next_token (&val
, (unsigned *)0, cfile
);
3340 if (token
!= LPAREN
)
3343 token
= next_token (&val
, (unsigned *)0, cfile
);
3344 if (!is_identifier (token
) && token
!= NUMBER
) {
3345 parse_warn (cfile
, "expecting identifier or number.");
3347 expression_dereference (expr
, MDL
);
3348 skip_to_semi (cfile
);
3353 if (token
== NUMBER
)
3354 (*expr
) -> data
.ns_add
.rrclass
= atoi (val
);
3355 else if (!strcasecmp (val
, "in"))
3356 (*expr
) -> data
.ns_add
.rrclass
= C_IN
;
3357 else if (!strcasecmp (val
, "chaos"))
3358 (*expr
) -> data
.ns_add
.rrclass
= C_CHAOS
;
3359 else if (!strcasecmp (val
, "hs"))
3360 (*expr
) -> data
.ns_add
.rrclass
= C_HS
;
3362 parse_warn (cfile
, "unexpected rrclass: %s", val
);
3366 token
= next_token (&val
, (unsigned *)0, cfile
);
3370 token
= next_token (&val
, (unsigned *)0, cfile
);
3371 if (!is_identifier (token
) && token
!= NUMBER
) {
3372 parse_warn (cfile
, "expecting identifier or number.");
3376 if (token
== NUMBER
)
3377 (*expr
) -> data
.ns_add
.rrtype
= atoi (val
);
3378 else if (!strcasecmp (val
, "a"))
3379 (*expr
) -> data
.ns_add
.rrtype
= T_A
;
3380 else if (!strcasecmp (val
, "ptr"))
3381 (*expr
) -> data
.ns_add
.rrtype
= T_PTR
;
3382 else if (!strcasecmp (val
, "mx"))
3383 (*expr
) -> data
.ns_add
.rrtype
= T_MX
;
3384 else if (!strcasecmp (val
, "cname"))
3385 (*expr
) -> data
.ns_add
.rrtype
= T_CNAME
;
3386 else if (!strcasecmp (val
, "TXT"))
3387 (*expr
) -> data
.ns_add
.rrtype
= T_TXT
;
3389 parse_warn (cfile
, "unexpected rrtype: %s", val
);
3393 token
= next_token (&val
, (unsigned *)0, cfile
);
3397 if (!(parse_data_expression
3398 (&(*expr
) -> data
.ns_add
.rrname
, cfile
, lose
)))
3401 token
= next_token (&val
, (unsigned *)0, cfile
);
3405 if (!(parse_data_expression
3406 (&(*expr
) -> data
.ns_add
.rrdata
, cfile
, lose
)))
3409 if (opcode
== expr_ns_add
) {
3410 token
= next_token (&val
, (unsigned *)0, cfile
);
3414 if (!(parse_numeric_expression
3415 (&(*expr
) -> data
.ns_add
.ttl
, cfile
,
3419 "expecting numeric expression.");
3424 token
= next_token (&val
, (unsigned *)0, cfile
);
3425 if (token
!= RPAREN
)
3431 if (!expression_allocate (expr
, MDL
))
3432 log_fatal ("can't allocate expression");
3433 (*expr
) -> op
= (token
== OPTION
3435 : expr_config_option
);
3436 token
= next_token (&val
, (unsigned *)0, cfile
);
3438 (*expr
) -> data
.option
= parse_option_name (cfile
, 0, &known
);
3439 if (!(*expr
) -> data
.option
) {
3441 expression_dereference (expr
, MDL
);
3447 token
= next_token (&val
, (unsigned *)0, cfile
);
3448 if (!expression_allocate (expr
, MDL
))
3449 log_fatal ("can't allocate expression");
3450 (*expr
) -> op
= expr_hardware
;
3453 case LEASED_ADDRESS
:
3454 token
= next_token (&val
, (unsigned *)0, cfile
);
3455 if (!expression_allocate (expr
, MDL
))
3456 log_fatal ("can't allocate expression");
3457 (*expr
) -> op
= expr_leased_address
;
3461 token
= next_token (&val
, (unsigned *)0, cfile
);
3462 if (!expression_allocate (expr
, MDL
))
3463 log_fatal ("can't allocate expression");
3464 (*expr
) -> op
= expr_client_state
;
3468 token
= next_token (&val
, (unsigned *)0, cfile
);
3469 if (!expression_allocate (expr
, MDL
))
3470 log_fatal ("can't allocate expression");
3471 (*expr
) -> op
= expr_filename
;
3475 token
= next_token (&val
, (unsigned *)0, cfile
);
3476 if (!expression_allocate (expr
, MDL
))
3477 log_fatal ("can't allocate expression");
3478 (*expr
) -> op
= expr_sname
;
3482 token
= next_token (&val
, (unsigned *)0, cfile
);
3483 if (!expression_allocate (expr
, MDL
))
3484 log_fatal ("can't allocate expression");
3485 (*expr
) -> op
= expr_lease_time
;
3489 token
= next_token (&val
, (unsigned *)0, cfile
);
3490 if (!expression_allocate (expr
, MDL
))
3491 log_fatal ("can't allocate expression");
3492 (*expr
) -> op
= expr_null
;
3495 case HOST_DECL_NAME
:
3496 token
= next_token (&val
, (unsigned *)0, cfile
);
3497 if (!expression_allocate (expr
, MDL
))
3498 log_fatal ("can't allocate expression");
3499 (*expr
) -> op
= expr_host_decl_name
;
3502 case UPDATED_DNS_RR
:
3503 token
= next_token (&val
, (unsigned *)0, cfile
);
3505 token
= next_token (&val
, (unsigned *)0, cfile
);
3506 if (token
!= LPAREN
)
3509 token
= next_token (&val
, (unsigned *)0, cfile
);
3510 if (token
!= STRING
) {
3511 parse_warn (cfile
, "expecting string.");
3516 if (!strcasecmp (val
, "a"))
3517 s
= "ddns-fwd-name";
3518 else if (!strcasecmp (val
, "ptr"))
3519 s
= "ddns-rev-name";
3521 parse_warn (cfile
, "invalid DNS rrtype: %s", val
);
3525 token
= next_token (&val
, (unsigned *)0, cfile
);
3526 if (token
!= RPAREN
)
3529 if (!expression_allocate (expr
, MDL
))
3530 log_fatal ("can't allocate expression");
3531 (*expr
) -> op
= expr_variable_reference
;
3532 (*expr
) -> data
.variable
=
3533 dmalloc (strlen (s
) + 1, MDL
);
3534 if (!(*expr
) -> data
.variable
)
3535 log_fatal ("can't allocate variable name.");
3536 strcpy ((*expr
) -> data
.variable
, s
);
3540 token
= next_token (&val
, (unsigned *)0, cfile
);
3541 if (!expression_allocate (expr
, MDL
))
3542 log_fatal ("can't allocate expression");
3543 (*expr
) -> op
= expr_packet
;
3545 token
= next_token (&val
, (unsigned *)0, cfile
);
3546 if (token
!= LPAREN
)
3549 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
3553 token
= next_token (&val
, (unsigned *)0, cfile
);
3557 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
3561 token
= next_token (&val
, (unsigned *)0, cfile
);
3562 if (token
!= RPAREN
)
3567 token
= next_token (&val
, &len
, cfile
);
3568 if (!make_const_data (expr
, (const unsigned char *)val
,
3570 log_fatal ("can't make constant string expression.");
3574 token
= next_token (&val
, (unsigned *)0, cfile
);
3575 token
= next_token (&val
, (unsigned *)0, cfile
);
3576 if (token
!= LPAREN
) {
3577 parse_warn (cfile
, "left parenthesis expected.");
3582 if (!expression_allocate (expr
, MDL
))
3583 log_fatal ("can't allocate expression");
3585 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
3589 "expecting data expression.");
3590 skip_to_semi (cfile
);
3593 expression_dereference (expr
, MDL
);
3597 token
= next_token (&val
, (unsigned *)0, cfile
);
3598 if (token
!= COMMA
) {
3599 parse_warn (cfile
, "comma expected.");
3601 expression_dereference (expr
, MDL
);
3605 token
= next_token (&val
, (unsigned *)0, cfile
);
3606 if (token
!= NUMBER
) {
3607 parse_warn (cfile
, "number expected.");
3609 expression_dereference (expr
, MDL
);
3612 switch (atoi (val
)) {
3614 (*expr
) -> op
= expr_extract_int8
;
3618 (*expr
) -> op
= expr_extract_int16
;
3622 (*expr
) -> op
= expr_extract_int32
;
3627 "unsupported integer size %d", atoi (val
));
3629 skip_to_semi (cfile
);
3630 expression_dereference (expr
, MDL
);
3634 token
= next_token (&val
, (unsigned *)0, cfile
);
3635 if (token
!= RPAREN
) {
3636 parse_warn (cfile
, "right parenthesis expected.");
3638 expression_dereference (expr
, MDL
);
3644 token
= next_token (&val
, (unsigned *)0, cfile
);
3645 token
= next_token (&val
, (unsigned *)0, cfile
);
3646 if (token
!= LPAREN
) {
3647 parse_warn (cfile
, "left parenthesis expected.");
3652 if (!expression_allocate (expr
, MDL
))
3653 log_fatal ("can't allocate expression");
3655 if (!parse_numeric_expression (&(*expr
) -> data
.encode_int
,
3657 parse_warn (cfile
, "expecting numeric expression.");
3658 skip_to_semi (cfile
);
3660 expression_dereference (expr
, MDL
);
3664 token
= next_token (&val
, (unsigned *)0, cfile
);
3665 if (token
!= COMMA
) {
3666 parse_warn (cfile
, "comma expected.");
3668 expression_dereference (expr
, MDL
);
3672 token
= next_token (&val
, (unsigned *)0, cfile
);
3673 if (token
!= NUMBER
) {
3674 parse_warn (cfile
, "number expected.");
3676 expression_dereference (expr
, MDL
);
3679 switch (atoi (val
)) {
3681 (*expr
) -> op
= expr_encode_int8
;
3685 (*expr
) -> op
= expr_encode_int16
;
3689 (*expr
) -> op
= expr_encode_int32
;
3694 "unsupported integer size %d", atoi (val
));
3696 skip_to_semi (cfile
);
3697 expression_dereference (expr
, MDL
);
3701 token
= next_token (&val
, (unsigned *)0, cfile
);
3702 if (token
!= RPAREN
) {
3703 parse_warn (cfile
, "right parenthesis expected.");
3705 expression_dereference (expr
, MDL
);
3711 /* If we're in a numeric context, this should just be a
3712 number, by itself. */
3713 if (context
== context_numeric
||
3714 context
== context_data_or_numeric
) {
3715 next_token (&val
, (unsigned *)0, cfile
);
3716 if (!expression_allocate (expr
, MDL
))
3717 log_fatal ("can't allocate expression");
3718 (*expr
) -> op
= expr_const_int
;
3719 (*expr
) -> data
.const_int
= atoi (val
);
3723 case NUMBER_OR_NAME
:
3724 if (!expression_allocate (expr
, MDL
))
3725 log_fatal ("can't allocate expression");
3727 (*expr
) -> op
= expr_const_data
;
3728 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
3729 expression_dereference (expr
, MDL
);
3738 token
= next_token (&val
, (unsigned *)0, cfile
);
3739 if (!expression_allocate (expr
, MDL
))
3740 log_fatal ("can't allocate expression");
3741 (*expr
) -> op
= expr_const_int
;
3742 (*expr
) -> data
.const_int
= known
;
3746 known
= ISC_R_SUCCESS
;
3750 known
= ISC_R_NOTAUTH
;
3754 known
= ISC_R_NOTIMPLEMENTED
;
3758 known
= ISC_R_NOTZONE
;
3762 known
= ISC_R_NXDOMAIN
;
3766 known
= ISC_R_NXRRSET
;
3770 known
= ISC_R_REFUSED
;
3774 known
= ISC_R_SERVFAIL
;
3778 known
= ISC_R_YXDOMAIN
;
3782 known
= ISC_R_YXRRSET
;
3790 known
= S_REBOOTING
;
3794 known
= S_SELECTING
;
3798 known
= S_REQUESTING
;
3810 known
= S_REBINDING
;
3814 token
= next_token (&val
, (unsigned *)0, cfile
);
3815 token
= next_token (&val
, (unsigned *)0, cfile
);
3816 if (token
!= LPAREN
)
3819 token
= next_token (&val
, (unsigned *)0, cfile
);
3820 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
3821 parse_warn (cfile
, "%s can't be a variable name", val
);
3822 skip_to_semi (cfile
);
3827 if (!expression_allocate (expr
, MDL
))
3828 log_fatal ("can't allocate expression");
3829 (*expr
) -> op
= expr_variable_exists
;
3830 (*expr
) -> data
.variable
= dmalloc (strlen (val
) + 1, MDL
);
3831 if (!(*expr
)->data
.variable
)
3832 log_fatal ("can't allocate variable name");
3833 strcpy ((*expr
) -> data
.variable
, val
);
3834 token
= next_token (&val
, (unsigned *)0, cfile
);
3835 if (token
!= RPAREN
)
3839 /* Not a valid start to an expression... */
3841 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
)
3844 token
= next_token (&val
, (unsigned *)0, cfile
);
3846 /* Save the name of the variable being referenced. */
3847 cptr
= dmalloc (strlen (val
) + 1, MDL
);
3849 log_fatal ("can't allocate variable name");
3852 /* Simple variable reference, as far as we can tell. */
3853 token
= peek_token (&val
, (unsigned *)0, cfile
);
3854 if (token
!= LPAREN
) {
3855 if (!expression_allocate (expr
, MDL
))
3856 log_fatal ("can't allocate expression");
3857 (*expr
) -> op
= expr_variable_reference
;
3858 (*expr
) -> data
.variable
= cptr
;
3862 token
= next_token (&val
, (unsigned *)0, cfile
);
3863 if (!expression_allocate (expr
, MDL
))
3864 log_fatal ("can't allocate expression");
3865 (*expr
) -> op
= expr_funcall
;
3866 (*expr
) -> data
.funcall
.name
= cptr
;
3868 /* Now parse the argument list. */
3869 ep
= &(*expr
) -> data
.funcall
.arglist
;
3871 if (!expression_allocate (ep
, MDL
))
3872 log_fatal ("can't allocate expression");
3873 (*ep
) -> op
= expr_arg
;
3874 if (!parse_expression (&(*ep
) -> data
.arg
.val
,
3875 cfile
, lose
, context_any
,
3876 (struct expression
**)0,
3880 "expecting expression.");
3883 skip_to_semi (cfile
);
3884 expression_dereference (expr
, MDL
);
3887 ep
= &((*ep
) -> data
.arg
.next
);
3888 token
= next_token (&val
, (unsigned *)0, cfile
);
3889 } while (token
== COMMA
);
3890 if (token
!= RPAREN
) {
3891 parse_warn (cfile
, "Right parenthesis expected.");
3892 skip_to_semi (cfile
);
3894 expression_dereference (expr
, MDL
);
3902 /* Parse an expression. */
3904 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
3905 struct expression
**expr
;
3906 struct parse
*cfile
;
3908 enum expression_context context
;
3909 struct expression
**plhs
;
3912 enum dhcp_token token
;
3914 struct expression
*rhs
= (struct expression
*)0, *tmp
;
3915 struct expression
*lhs
= (struct expression
*)0;
3916 enum expr_op next_op
;
3917 enum expression_context
3918 lhs_context
= context_any
,
3919 rhs_context
= context_any
;
3921 /* Consume the left hand side we were passed. */
3923 expression_reference (&lhs
, *plhs
, MDL
);
3924 expression_dereference (plhs
, MDL
);
3928 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
3929 /* If we already have a left-hand side, then it's not
3930 okay for there not to be a right-hand side here, so
3931 we need to flag it as an error. */
3935 "expecting right-hand side.");
3937 skip_to_semi (cfile
);
3939 expression_dereference (&lhs
, MDL
);
3944 /* At this point, rhs contains either an entire subexpression,
3945 or at least a left-hand-side. If we do not see a binary token
3946 as the next token, we're done with the expression. */
3948 token
= peek_token (&val
, (unsigned *)0, cfile
);
3951 token
= next_token (&val
, (unsigned *)0, cfile
);
3952 token
= peek_token (&val
, (unsigned *)0, cfile
);
3953 if (token
!= EQUAL
) {
3954 parse_warn (cfile
, "! in boolean context without =");
3956 skip_to_semi (cfile
);
3958 expression_dereference (&lhs
, MDL
);
3961 next_op
= expr_not_equal
;
3962 context
= expression_context (rhs
);
3966 next_op
= expr_equal
;
3967 context
= expression_context (rhs
);
3972 context
= expression_context (rhs
);
3977 context
= expression_context (rhs
);
3982 context
= expression_context (rhs
);
3986 next_op
= expr_subtract
;
3987 context
= expression_context (rhs
);
3991 next_op
= expr_divide
;
3992 context
= expression_context (rhs
);
3996 next_op
= expr_multiply
;
3997 context
= expression_context (rhs
);
4001 next_op
= expr_remainder
;
4002 context
= expression_context (rhs
);
4006 next_op
= expr_binary_and
;
4007 context
= expression_context (rhs
);
4011 next_op
= expr_binary_or
;
4012 context
= expression_context (rhs
);
4016 next_op
= expr_binary_xor
;
4017 context
= expression_context (rhs
);
4021 next_op
= expr_none
;
4024 /* If we have no lhs yet, we just parsed it. */
4026 /* If there was no operator following what we just parsed,
4027 then we're done - return it. */
4028 if (next_op
== expr_none
) {
4033 rhs
= (struct expression
*)0;
4035 next_token (&val
, (unsigned *)0, cfile
);
4039 /* If the next binary operator is of greater precedence than the
4040 * current operator, then rhs we have parsed so far is actually
4041 * the lhs of the next operator. To get this value, we have to
4044 if (binop
!= expr_none
&& next_op
!= expr_none
&&
4045 op_precedence (binop
, next_op
) < 0) {
4047 /* Eat the subexpression operator token, which we pass to
4048 * parse_expression...we only peek()'d earlier.
4050 token
= next_token (&val
, (unsigned *)0, cfile
);
4052 /* Continue parsing of the right hand side with that token. */
4054 rhs
= (struct expression
*)0;
4055 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
4059 "expecting a subexpression");
4064 next_op
= expr_none
;
4067 if (binop
!= expr_none
) {
4068 rhs_context
= expression_context(rhs
);
4069 lhs_context
= expression_context(lhs
);
4071 if ((rhs_context
!= context_any
) && (lhs_context
!= context_any
) &&
4072 (rhs_context
!= lhs_context
)) {
4073 parse_warn (cfile
, "illegal expression relating different types");
4074 skip_to_semi (cfile
);
4075 expression_dereference (&rhs
, MDL
);
4076 expression_dereference (&lhs
, MDL
);
4082 case expr_not_equal
:
4084 if ((rhs_context
!= context_data_or_numeric
) &&
4085 (rhs_context
!= context_data
) &&
4086 (rhs_context
!= context_numeric
) &&
4087 (rhs_context
!= context_any
)) {
4088 parse_warn (cfile
, "expecting data/numeric expression");
4089 skip_to_semi (cfile
);
4090 expression_dereference (&rhs
, MDL
);
4098 if ((rhs_context
!= context_boolean
) &&
4099 (rhs_context
!= context_any
)) {
4100 parse_warn (cfile
, "expecting boolean expressions");
4101 skip_to_semi (cfile
);
4102 expression_dereference (&rhs
, MDL
);
4112 case expr_remainder
:
4113 case expr_binary_and
:
4114 case expr_binary_or
:
4115 case expr_binary_xor
:
4116 if ((rhs_context
!= context_numeric
) &&
4117 (rhs_context
!= context_any
)) {
4118 parse_warn (cfile
, "expecting numeric expressions");
4119 skip_to_semi (cfile
);
4120 expression_dereference (&rhs
, MDL
);
4131 /* Now, if we didn't find a binary operator, we're done parsing
4132 this subexpression, so combine it with the preceding binary
4133 operator and return the result. */
4134 if (next_op
== expr_none
) {
4135 if (!expression_allocate (expr
, MDL
))
4136 log_fatal ("Can't allocate expression!");
4138 (*expr
) -> op
= binop
;
4139 /* All the binary operators' data union members
4140 are the same, so we'll cheat and use the member
4141 for the equals operator. */
4142 (*expr
) -> data
.equal
[0] = lhs
;
4143 (*expr
) -> data
.equal
[1] = rhs
;
4147 /* Eat the operator token - we now know it was a binary operator... */
4148 token
= next_token (&val
, (unsigned *)0, cfile
);
4150 /* Now combine the LHS and the RHS using binop. */
4151 tmp
= (struct expression
*)0;
4152 if (!expression_allocate (&tmp
, MDL
))
4153 log_fatal ("No memory for equal precedence combination.");
4155 /* Store the LHS and RHS. */
4156 tmp
-> data
.equal
[0] = lhs
;
4157 tmp
-> data
.equal
[1] = rhs
;
4161 tmp
= (struct expression
*)0;
4162 rhs
= (struct expression
*)0;
4164 /* Recursions don't return until we have parsed the end of the
4165 expression, so if we recursed earlier, we can now return what
4167 if (next_op
== expr_none
) {
4176 /* option-statement :== identifier DOT identifier <syntax> SEMI
4177 | identifier <syntax> SEMI
4179 Option syntax is handled specially through format strings, so it
4180 would be painful to come up with BNF for it. However, it always
4181 starts as above and ends in a SEMI. */
4183 int parse_option_statement (result
, cfile
, lookups
, option
, op
)
4184 struct executable_statement
**result
;
4185 struct parse
*cfile
;
4187 struct option
*option
;
4188 enum statement_op op
;
4191 enum dhcp_token token
;
4192 const char *fmt
= NULL
;
4193 struct expression
*expr
= (struct expression
*)0;
4194 struct expression
*tmp
;
4196 struct executable_statement
*stmt
;
4199 token
= peek_token (&val
, (unsigned *)0, cfile
);
4200 if (token
== SEMI
) {
4201 /* Eat the semicolon... */
4202 token
= next_token (&val
, (unsigned *)0, cfile
);
4206 if (token
== EQUAL
) {
4207 /* Eat the equals sign. */
4208 token
= next_token (&val
, (unsigned *)0, cfile
);
4210 /* Parse a data expression and use its value for the data. */
4211 if (!parse_data_expression (&expr
, cfile
, &lose
)) {
4212 /* In this context, we must have an executable
4213 statement, so if we found something else, it's
4217 "expecting a data expression.");
4218 skip_to_semi (cfile
);
4223 /* We got a valid expression, so use it. */
4227 /* Parse the option data... */
4229 /* Set a flag if this is an array of a simple type (i.e.,
4230 not an array of pairs of IP addresses, or something
4232 int uniform
= option
-> format
[1] == 'A';
4235 /* Set fmt to start of format for 'A' and one char back
4237 if ((fmt
!= NULL
) &&
4238 (fmt
!= option
-> format
) && (*fmt
== 'a'))
4241 fmt
= ((fmt
== NULL
) ||
4242 (*fmt
== 'A')) ? option
-> format
: fmt
;
4244 /* 'a' means always uniform */
4245 uniform
|= (fmt
[1] == 'a');
4247 for ( ; *fmt
; fmt
++) {
4248 if ((*fmt
== 'A') || (*fmt
== 'a'))
4253 expr
= (struct expression
*)0;
4254 if (!parse_option_token (&expr
, cfile
, &fmt
,
4255 tmp
, uniform
, lookups
)) {
4256 if (fmt
[1] != 'o') {
4258 expression_dereference (&tmp
,
4263 tmp
= (struct expression
*)0;
4266 expression_dereference (&tmp
, MDL
);
4268 if ((*fmt
== 'A') || (*fmt
== 'a')) {
4269 token
= peek_token (&val
, (unsigned *)0, cfile
);
4270 /* Comma means: continue with next element in array */
4271 if (token
== COMMA
) {
4272 token
= next_token (&val
,
4273 (unsigned *)0, cfile
);
4276 /* no comma: end of array.
4277 'A' or end of string means: leave the loop */
4278 if ((*fmt
== 'A') || (fmt
[1] == '\0'))
4280 /* 'a' means: go on with next char */
4286 } while ((*fmt
== 'A') || (*fmt
== 'a'));
4289 if (!parse_semi (cfile
))
4291 if (!executable_statement_allocate (result
, MDL
))
4292 log_fatal ("no memory for option statement.");
4293 (*result
) -> op
= op
;
4294 if (expr
&& !option_cache (&(*result
) -> data
.option
,
4295 (struct data_string
*)0, expr
, option
, MDL
))
4296 log_fatal ("no memory for option cache");
4298 expression_dereference (&expr
, MDL
);
4302 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
4303 struct expression
**rv
;
4304 struct parse
*cfile
;
4306 struct expression
*expr
;
4311 enum dhcp_token token
;
4312 struct expression
*t
= (struct expression
*)0;
4313 unsigned char buf
[4];
4319 struct enumeration_value
*e
;
4323 token
= next_token (&val
, &len
, cfile
);
4324 if (!is_identifier (token
)) {
4325 if ((*fmt
) [1] != 'o') {
4326 parse_warn (cfile
, "expecting identifier.");
4328 skip_to_semi (cfile
);
4332 if (!make_const_data (&t
, (const unsigned char *)val
,
4334 log_fatal ("No memory for %s", val
);
4338 g
= strchr (*fmt
, '.');
4341 "malformed encapsulation format (bug!)");
4342 skip_to_semi (cfile
);
4347 token
= peek_token (&val
, (unsigned *)0, cfile
);
4348 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4349 if (!expression_allocate (&t
, MDL
))
4351 if (!parse_cshl (&t
-> data
.const_data
, cfile
)) {
4352 expression_dereference (&t
, MDL
);
4355 t
-> op
= expr_const_data
;
4357 token
= next_token (&val
, &len
, cfile
);
4359 if(token
== STRING
) {
4360 if (!make_const_data (&t
,
4361 (const unsigned char *)val
,
4363 log_fatal ("No memory for \"%s\"", val
);
4364 } else if ((*fmt
) [1] != 'o') {
4365 parse_warn (cfile
, "expecting string %s.",
4366 "or hexadecimal data");
4367 skip_to_semi (cfile
);
4374 case 'd': /* Domain name... */
4375 val
= parse_host_name (cfile
);
4377 parse_warn (cfile
, "not a valid domain name.");
4378 skip_to_semi (cfile
);
4384 case 't': /* Text string... */
4385 token
= next_token (&val
, &len
, cfile
);
4386 if (token
!= STRING
&& !is_identifier (token
)) {
4387 if ((*fmt
) [1] != 'o') {
4388 parse_warn (cfile
, "expecting string.");
4390 skip_to_semi (cfile
);
4395 if (!make_const_data (&t
, (const unsigned char *)val
,
4397 log_fatal ("No memory for concatenation");
4402 g
= strchr (*fmt
, '.');
4404 parse_warn (cfile
, "malformed %s (bug!)",
4405 "enumeration format");
4407 skip_to_semi (cfile
);
4411 token
= next_token (&val
, (unsigned *)0, cfile
);
4412 if (!is_identifier (token
)) {
4414 "identifier expected");
4417 e
= find_enumeration_value (f
, (*fmt
) - f
, val
);
4419 parse_warn (cfile
, "unknown value");
4422 if (!make_const_data (&t
, &e
-> value
, 1, 0, 1, MDL
))
4426 case 'I': /* IP address or hostname. */
4428 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
4431 if (!parse_ip_addr (cfile
, &addr
))
4433 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
,
4439 case 'T': /* Lease interval. */
4440 token
= next_token (&val
, (unsigned *)0, cfile
);
4441 if (token
!= INFINITE
)
4444 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4448 case 'L': /* Unsigned 32-bit integer... */
4449 case 'l': /* Signed 32-bit integer... */
4450 token
= next_token (&val
, (unsigned *)0, cfile
);
4452 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
)) {
4454 if ((*fmt
) [1] != 'o') {
4455 parse_warn (cfile
, "expecting number.");
4457 skip_to_semi (cfile
);
4461 convert_num (cfile
, buf
, val
, 0, 32);
4462 if (!make_const_data (&t
, buf
, 4, 0, 1, MDL
))
4466 case 's': /* Signed 16-bit integer. */
4467 case 'S': /* Unsigned 16-bit integer. */
4468 token
= next_token (&val
, (unsigned *)0, cfile
);
4469 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4471 convert_num (cfile
, buf
, val
, 0, 16);
4472 if (!make_const_data (&t
, buf
, 2, 0, 1, MDL
))
4476 case 'b': /* Signed 8-bit integer. */
4477 case 'B': /* Unsigned 8-bit integer. */
4478 token
= next_token (&val
, (unsigned *)0, cfile
);
4479 if ((token
!= NUMBER
) && (token
!= NUMBER_OR_NAME
))
4481 convert_num (cfile
, buf
, val
, 0, 8);
4482 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4486 case 'f': /* Boolean flag. */
4487 token
= next_token (&val
, (unsigned *)0, cfile
);
4488 if (!is_identifier (token
)) {
4489 if ((*fmt
) [1] != 'o')
4490 parse_warn (cfile
, "expecting identifier.");
4492 if ((*fmt
) [1] != 'o') {
4494 skip_to_semi (cfile
);
4498 if (!strcasecmp (val
, "true")
4499 || !strcasecmp (val
, "on"))
4501 else if (!strcasecmp (val
, "false")
4502 || !strcasecmp (val
, "off"))
4504 else if (!strcasecmp (val
, "ignore"))
4507 if ((*fmt
) [1] != 'o')
4508 parse_warn (cfile
, "expecting boolean.");
4511 if (!make_const_data (&t
, buf
, 1, 0, 1, MDL
))
4516 parse_warn (cfile
, "Bad format %c in parse_option_token.",
4518 skip_to_semi (cfile
);
4522 if (!make_concat (rv
, expr
, t
))
4525 expression_reference (rv
, t
, MDL
);
4526 expression_dereference (&t
, MDL
);
4530 int parse_option_decl (oc
, cfile
)
4531 struct option_cache
**oc
;
4532 struct parse
*cfile
;
4537 u_int8_t hunkbuf
[1024];
4538 unsigned hunkix
= 0;
4539 const char *fmt
, *f
;
4540 struct option
*option
;
4541 struct iaddr ip_addr
;
4547 struct enumeration_value
*e
;
4549 option
= parse_option_name (cfile
, 0, &known
);
4553 /* Parse the option data... */
4555 /* Set a flag if this is an array of a simple type (i.e.,
4556 not an array of pairs of IP addresses, or something
4558 int uniform
= option
-> format
[1] == 'A';
4560 for (fmt
= option
-> format
; *fmt
; fmt
++) {
4565 fmt
= strchr (fmt
, '.');
4568 "malformed %s (bug!)",
4569 "encapsulation format");
4570 skip_to_semi (cfile
);
4574 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
4575 sizeof hunkbuf
- hunkix
);
4579 case 't': /* Text string... */
4580 token
= next_token (&val
,
4582 if (token
!= STRING
) {
4584 "expecting string.");
4585 skip_to_semi (cfile
);
4588 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
4590 "option data buffer %s",
4592 skip_to_semi (cfile
);
4595 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
4602 fmt
= strchr (fmt
, '.');
4605 "malformed %s (bug!)",
4606 "enumeration format");
4608 skip_to_semi (cfile
);
4611 token
= next_token (&val
,
4612 (unsigned *)0, cfile
);
4613 if (!is_identifier (token
)) {
4615 "identifier expected");
4618 e
= find_enumeration_value (f
, fmt
- f
, val
);
4628 case 'I': /* IP address. */
4629 if (!parse_ip_addr (cfile
, &ip_addr
))
4635 if (hunkix
+ len
> sizeof hunkbuf
) {
4637 "option data buffer %s",
4639 skip_to_semi (cfile
);
4642 memcpy (&hunkbuf
[hunkix
], dp
, len
);
4646 case 'L': /* Unsigned 32-bit integer... */
4647 case 'l': /* Signed 32-bit integer... */
4648 token
= next_token (&val
,
4649 (unsigned *)0, cfile
);
4650 if ((token
!= NUMBER
) &&
4651 (token
!= NUMBER_OR_NAME
)) {
4654 "expecting number.");
4656 skip_to_semi (cfile
);
4659 convert_num (cfile
, buf
, val
, 0, 32);
4664 case 's': /* Signed 16-bit integer. */
4665 case 'S': /* Unsigned 16-bit integer. */
4666 token
= next_token (&val
,
4667 (unsigned *)0, cfile
);
4668 if ((token
!= NUMBER
) &&
4669 (token
!= NUMBER_OR_NAME
))
4671 convert_num (cfile
, buf
, val
, 0, 16);
4676 case 'b': /* Signed 8-bit integer. */
4677 case 'B': /* Unsigned 8-bit integer. */
4678 token
= next_token (&val
,
4679 (unsigned *)0, cfile
);
4680 if ((token
!= NUMBER
) &&
4681 (token
!= NUMBER_OR_NAME
))
4683 convert_num (cfile
, buf
, val
, 0, 8);
4688 case 'f': /* Boolean flag. */
4689 token
= next_token (&val
,
4690 (unsigned *)0, cfile
);
4691 if (!is_identifier (token
)) {
4693 "expecting identifier.");
4696 skip_to_semi (cfile
);
4699 if (!strcasecmp (val
, "true")
4700 || !strcasecmp (val
, "on"))
4702 else if (!strcasecmp (val
, "false")
4703 || !strcasecmp (val
, "off"))
4707 "expecting boolean.");
4715 log_error ("parse_option_param: Bad format %c",
4717 skip_to_semi (cfile
);
4721 token
= next_token (&val
, (unsigned *)0, cfile
);
4722 } while (*fmt
== 'A' && token
== COMMA
);
4724 if (token
!= SEMI
) {
4725 parse_warn (cfile
, "semicolon expected.");
4726 skip_to_semi (cfile
);
4730 bp
= (struct buffer
*)0;
4731 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
4732 log_fatal ("no memory to store option declaration.");
4734 log_fatal ("out of memory allocating option data.");
4735 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
4737 if (!option_cache_allocate (oc
, MDL
))
4738 log_fatal ("out of memory allocating option cache.");
4740 (*oc
) -> data
.buffer
= bp
;
4741 (*oc
) -> data
.data
= &bp
-> data
[0];
4742 (*oc
) -> data
.terminated
= nul_term
;
4743 (*oc
) -> data
.len
= hunkix
;
4744 (*oc
) -> option
= option
;
4748 /* Consider merging parse_cshl into this. */
4750 int parse_X (cfile
, buf
, max
)
4751 struct parse
*cfile
;
4760 token
= peek_token (&val
, (unsigned *)0, cfile
);
4761 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
4764 token
= next_token (&val
, (unsigned *)0, cfile
);
4765 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
4767 "expecting hexadecimal constant.");
4768 skip_to_semi (cfile
);
4771 convert_num (cfile
, &buf
[len
], val
, 16, 8);
4774 "hexadecimal constant too long.");
4775 skip_to_semi (cfile
);
4778 token
= peek_token (&val
, (unsigned *)0, cfile
);
4780 token
= next_token (&val
,
4781 (unsigned *)0, cfile
);
4782 } while (token
== COLON
);
4784 } else if (token
== STRING
) {
4785 token
= next_token (&val
, &len
, cfile
);
4786 if (len
+ 1 > max
) {
4787 parse_warn (cfile
, "string constant too long.");
4788 skip_to_semi (cfile
);
4791 memcpy (buf
, val
, len
+ 1);
4793 parse_warn (cfile
, "expecting string or hexadecimal data");
4794 skip_to_semi (cfile
);
4800 int parse_warn (struct parse
*cfile
, const char *fmt
, ...)
4808 do_percentm (mbuf
, fmt
);
4809 /* %Audit% This is log output. %2004.06.17,Safe%
4810 * If we truncate we hope the user can get a hint from the log.
4812 snprintf (fbuf
, sizeof fbuf
, "%s line %d: %s",
4813 cfile
-> tlname
, cfile
-> lexline
, mbuf
);
4815 va_start (list
, fmt
);
4816 vsnprintf (mbuf
, sizeof mbuf
, fbuf
, list
);
4821 cfile
-> token_line
[i
] && i
< (cfile
-> lexchar
- 1); i
++) {
4822 if (lix
< (sizeof lexbuf
) - 1)
4823 lexbuf
[lix
++] = ' ';
4824 if (cfile
-> token_line
[i
] == '\t') {
4826 lix
< (sizeof lexbuf
) - 1 && (lix
& 7); lix
++)
4833 syslog (log_priority
| LOG_ERR
, "%s", mbuf
);
4834 syslog (log_priority
| LOG_ERR
, "%s", cfile
-> token_line
);
4835 if (cfile
-> lexchar
< 81)
4836 syslog (log_priority
| LOG_ERR
, "%s^", lexbuf
);
4840 write (STDERR_FILENO
, mbuf
, strlen (mbuf
));
4841 write (STDERR_FILENO
, "\n", 1);
4842 write (STDERR_FILENO
, cfile
-> token_line
,
4843 strlen (cfile
-> token_line
));
4844 write (STDERR_FILENO
, "\n", 1);
4845 if (cfile
-> lexchar
< 81)
4846 write (STDERR_FILENO
, lexbuf
, lix
);
4847 write (STDERR_FILENO
, "^\n", 2);
4850 cfile
-> warnings_occurred
= 1;