3 Common parser code for dhcpd and dhclient. */
6 * Copyright (c) 1996-1999 Internet Software Consortium.
7 * Use is subject to license terms which appear in the file named
8 * ISC-LICENSE that should have accompanied this file when you
9 * received it. If a file named ISC-LICENSE did not accompany this
10 * file, or you are not sure the one you have is correct, you may
11 * obtain an applicable copy of the license at:
13 * http://www.isc.org/isc-license-1.0.html.
15 * This file is part of the ISC DHCP distribution. The documentation
16 * associated with this file is listed in the file DOCUMENTATION,
17 * included in the top-level directory of this release.
19 * Support and other services are available for ISC products - see
20 * http://www.isc.org for more information.
24 static char copyright
[] =
25 "$Id: parse.c,v 1.16 1999/03/16 05:50:36 mellon Exp $ Copyright (c) 1995, 1996, 1997, 1998, 1999 The Internet Software Consortium. All rights reserved.\n";
31 /* Skip to the semicolon ending the current statement. If we encounter
32 braces, the matching closing brace terminates the statement. If we
33 encounter a right brace but haven't encountered a left brace, return
34 leaving the brace in the token buffer for the caller. If we see a
35 semicolon and haven't seen a left brace, return. This lets us skip
40 statement foo bar { statement { } }
45 void skip_to_semi (cfile
)
48 skip_to_rbrace (cfile
, 0);
51 void skip_to_rbrace (cfile
, brace_count
)
55 enum dhcp_token token
;
59 token
= peek_token (&val
, cfile
);
60 if (token
== RBRACE
) {
61 token
= next_token (&val
, cfile
);
67 } else if (token
== LBRACE
) {
69 } else if (token
== SEMI
&& !brace_count
) {
70 token
= next_token (&val
, cfile
);
72 } else if (token
== EOL
) {
73 /* EOL only happens when parsing /etc/resolv.conf,
74 and we treat it like a semicolon because the
75 resolv.conf file is line-oriented. */
76 token
= next_token (&val
, cfile
);
79 token
= next_token (&val
, cfile
);
80 } while (token
!= EOF
);
83 int parse_semi (cfile
)
86 enum dhcp_token token
;
89 token
= next_token (&val
, cfile
);
91 parse_warn ("semicolon expected.");
98 /* string-parameter :== STRING SEMI */
100 char *parse_string (cfile
)
104 enum dhcp_token token
;
107 token
= next_token (&val
, cfile
);
108 if (token
!= STRING
) {
109 parse_warn ("filename must be a string");
110 skip_to_semi (cfile
);
113 s
= (char *)malloc (strlen (val
) + 1);
115 log_fatal ("no memory for string %s.", val
);
118 if (!parse_semi (cfile
))
124 * hostname :== IDENTIFIER
126 * | hostname DOT IDENTIFIER
129 char *parse_host_name (cfile
)
133 enum dhcp_token token
;
139 /* Read a dotted hostname... */
141 /* Read a token, which should be an identifier. */
142 token
= peek_token (&val
, cfile
);
143 if (!is_identifier (token
) && token
!= NUMBER
)
145 token
= next_token (&val
, cfile
);
147 /* Store this identifier... */
148 if (!(s
= (char *)malloc (strlen (val
) + 1)))
149 log_fatal ("can't allocate temp space for hostname.");
151 c
= cons ((caddr_t
)s
, c
);
152 len
+= strlen (s
) + 1;
153 /* Look for a dot; if it's there, keep going, otherwise
155 token
= peek_token (&val
, cfile
);
157 token
= next_token (&val
, cfile
);
158 } while (token
== DOT
);
160 /* Assemble the hostname together into a string. */
161 if (!(s
= (char *)malloc (len
)))
162 log_fatal ("can't allocate space for hostname.");
167 int l
= strlen ((char *)(c
-> car
));
169 memcpy (t
, (char *)(c
-> car
), l
);
170 /* Free up temp space. */
180 /* ip-addr-or-hostname :== ip-address | hostname
181 ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
183 Parse an ip address or a hostname. If uniform is zero, put in
184 an expr_substring node to limit hostnames that evaluate to more
185 than one IP address. */
187 int parse_ip_addr_or_hostname (expr
, cfile
, uniform
)
188 struct expression
**expr
;
193 enum dhcp_token token
;
194 unsigned char addr
[4];
195 int len
= sizeof addr
;
197 struct expression
*x
= (struct expression
*)0;
199 token
= peek_token (&val
, cfile
);
200 if (is_identifier (token
)) {
201 name
= parse_host_name (cfile
);
204 if (!make_host_lookup (expr
, name
))
207 if (!make_limit (&x
, *expr
, 4))
209 expression_dereference (expr
,
210 "parse_ip_addr_or_hostname");
213 } else if (token
== NUMBER
) {
214 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
216 return make_const_data (expr
, addr
, len
, 0, 1);
218 if (token
!= RBRACE
&& token
!= LBRACE
)
219 token
= next_token (&val
, cfile
);
220 parse_warn ("%s (%d): expecting IP address or hostname",
223 skip_to_semi (cfile
);
231 * ip-address :== NUMBER DOT NUMBER DOT NUMBER DOT NUMBER
234 int parse_ip_addr (cfile
, addr
)
239 enum dhcp_token token
;
242 if (parse_numeric_aggregate (cfile
, addr
-> iabuf
,
243 &addr
-> len
, DOT
, 10, 8))
249 * hardware-parameter :== HARDWARE hardware-type colon-seperated-hex-list SEMI
250 * hardware-type :== ETHERNET | TOKEN_RING
253 void parse_hardware_param (cfile
, hardware
)
255 struct hardware
*hardware
;
258 enum dhcp_token token
;
262 token
= next_token (&val
, cfile
);
265 hardware
-> htype
= HTYPE_ETHER
;
268 hardware
-> htype
= HTYPE_IEEE802
;
271 hardware
-> htype
= HTYPE_FDDI
;
274 parse_warn ("expecting a network hardware type");
275 skip_to_semi (cfile
);
279 /* Parse the hardware address information. Technically,
280 it would make a lot of sense to restrict the length of the
281 data we'll accept here to the length of a particular hardware
282 address type. Unfortunately, there are some broken clients
283 out there that put bogus data in the chaddr buffer, and we accept
284 that data in the lease file rather than simply failing on such
287 t
= parse_numeric_aggregate (cfile
, (unsigned char *)0, &hlen
,
291 if (hlen
> sizeof hardware
-> haddr
) {
293 parse_warn ("hardware address too long");
295 hardware
-> hlen
= hlen
;
296 memcpy ((unsigned char *)&hardware
-> haddr
[0],
297 t
, hardware
-> hlen
);
298 if (hlen
< sizeof hardware
-> haddr
)
299 memset (&hardware
-> haddr
[hlen
], 0,
300 (sizeof hardware
-> haddr
) - hlen
);
304 token
= next_token (&val
, cfile
);
306 parse_warn ("expecting semicolon.");
307 skip_to_semi (cfile
);
311 /* lease-time :== NUMBER SEMI */
313 void parse_lease_time (cfile
, timep
)
318 enum dhcp_token token
;
320 token
= next_token (&val
, cfile
);
321 if (token
!= NUMBER
) {
322 parse_warn ("Expecting numeric lease time");
323 skip_to_semi (cfile
);
326 convert_num ((unsigned char *)timep
, val
, 10, 32);
327 /* Unswap the number - convert_num returns stuff in NBO. */
328 *timep
= ntohl (*timep
); /* XXX */
333 /* No BNF for numeric aggregates - that's defined by the caller. What
334 this function does is to parse a sequence of numbers seperated by
335 the token specified in seperator. If max is zero, any number of
336 numbers will be parsed; otherwise, exactly max numbers are
337 expected. Base and size tell us how to internalize the numbers
338 once they've been tokenized. */
340 unsigned char *parse_numeric_aggregate (cfile
, buf
,
341 max
, seperator
, base
, size
)
350 enum dhcp_token token
;
351 unsigned char *bufp
= buf
, *s
, *t
;
356 bufp
= (unsigned char *)malloc (*max
* size
/ 8);
358 log_fatal ("can't allocate space for numeric aggregate");
364 token
= peek_token (&val
, cfile
);
365 if (token
!= seperator
) {
368 if (token
!= RBRACE
&& token
!= LBRACE
)
369 token
= next_token (&val
, cfile
);
370 parse_warn ("too few numbers.");
372 skip_to_semi (cfile
);
373 return (unsigned char *)0;
375 token
= next_token (&val
, cfile
);
377 token
= next_token (&val
, cfile
);
380 parse_warn ("unexpected end of file");
384 /* Allow NUMBER_OR_NAME if base is 16. */
385 if (token
!= NUMBER
&&
386 (base
!= 16 || token
!= NUMBER_OR_NAME
)) {
387 parse_warn ("expecting numeric value.");
388 skip_to_semi (cfile
);
389 return (unsigned char *)0;
391 /* If we can, convert the number now; otherwise, build
392 a linked list of all the numbers. */
394 convert_num (s
, val
, base
, size
);
397 t
= (unsigned char *)malloc (strlen (val
) + 1);
399 log_fatal ("no temp space for number.");
400 strcpy ((char *)t
, val
);
401 c
= cons ((caddr_t
)t
, c
);
403 } while (++count
!= *max
);
405 /* If we had to cons up a list, convert it now. */
407 bufp
= (unsigned char *)malloc (count
* size
/ 8);
409 log_fatal ("can't allocate space for numeric aggregate.");
410 s
= bufp
+ count
- size
/ 8;
415 convert_num (s
, (char *)(c
-> car
), base
, size
);
417 /* Free up temp space. */
425 void convert_num (buf
, str
, base
, size
)
442 /* If base wasn't specified, figure it out from the data. */
444 if (ptr
[0] == '0') {
445 if (ptr
[1] == 'x') {
448 } else if (isascii (ptr
[1]) && isdigit (ptr
[1])) {
461 /* XXX assumes ASCII... */
463 tval
= tval
- 'a' + 10;
464 else if (tval
>= 'A')
465 tval
= tval
- 'A' + 10;
466 else if (tval
>= '0')
469 log_error ("Bogus number: %s.", str
);
473 log_error ("Bogus number: %s: digit %d not in base %d\n",
477 val
= val
* base
+ tval
;
481 max
= (1 << (size
- 1));
483 max
= (1 << (size
- 1)) + ((1 << (size
- 1)) - 1);
487 log_error ("value %s%o exceeds max (%d) for precision.",
488 negative
? "-" : "", val
, max
);
491 log_error ("value %s%x exceeds max (%d) for precision.",
492 negative
? "-" : "", val
, max
);
495 log_error ("value %s%u exceeds max (%d) for precision.",
496 negative
? "-" : "", val
, max
);
504 *buf
= -(unsigned long)val
;
507 putShort (buf
, -(unsigned long)val
);
510 putLong (buf
, -(unsigned long)val
);
513 log_error ("Unexpected integer size: %d\n", size
);
519 *buf
= (u_int8_t
)val
;
522 putUShort (buf
, (u_int16_t
)val
);
528 log_error ("Unexpected integer size: %d\n", size
);
535 * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
536 * NUMBER COLON NUMBER COLON NUMBER SEMI
538 * Dates are always in GMT; first number is day of week; next is
539 * year/month/day; next is hours:minutes:seconds on a 24-hour
543 TIME
parse_date (cfile
)
549 enum dhcp_token token
;
550 static int months
[11] = { 31, 59, 90, 120, 151, 181,
551 212, 243, 273, 304, 334 };
554 token
= next_token (&val
, cfile
);
555 if (token
!= NUMBER
) {
556 parse_warn ("numeric day of week expected.");
558 skip_to_semi (cfile
);
561 tm
.tm_wday
= atoi (val
);
564 token
= next_token (&val
, cfile
);
565 if (token
!= NUMBER
) {
566 parse_warn ("numeric year expected.");
568 skip_to_semi (cfile
);
572 /* Note: the following is not a Y2K bug - it's a Y1.9K bug. Until
573 somebody invents a time machine, I think we can safely disregard
574 it. This actually works around a stupid Y2K bug that was present
575 in a very early beta release of dhcpd. */
576 tm
.tm_year
= atoi (val
);
577 if (tm
.tm_year
> 1900)
580 /* Slash seperating year from month... */
581 token
= next_token (&val
, cfile
);
582 if (token
!= SLASH
) {
583 parse_warn ("expected slash seperating year from month.");
585 skip_to_semi (cfile
);
590 token
= next_token (&val
, cfile
);
591 if (token
!= NUMBER
) {
592 parse_warn ("numeric month expected.");
594 skip_to_semi (cfile
);
597 tm
.tm_mon
= atoi (val
) - 1;
599 /* Slash seperating month from day... */
600 token
= next_token (&val
, cfile
);
601 if (token
!= SLASH
) {
602 parse_warn ("expected slash seperating month from day.");
604 skip_to_semi (cfile
);
609 token
= next_token (&val
, cfile
);
610 if (token
!= NUMBER
) {
611 parse_warn ("numeric day of month expected.");
613 skip_to_semi (cfile
);
616 tm
.tm_mday
= atoi (val
);
619 token
= next_token (&val
, cfile
);
620 if (token
!= NUMBER
) {
621 parse_warn ("numeric hour expected.");
623 skip_to_semi (cfile
);
626 tm
.tm_hour
= atoi (val
);
628 /* Colon seperating hour from minute... */
629 token
= next_token (&val
, cfile
);
630 if (token
!= COLON
) {
631 parse_warn ("expected colon seperating hour from minute.");
633 skip_to_semi (cfile
);
638 token
= next_token (&val
, cfile
);
639 if (token
!= NUMBER
) {
640 parse_warn ("numeric minute expected.");
642 skip_to_semi (cfile
);
645 tm
.tm_min
= atoi (val
);
647 /* Colon seperating minute from second... */
648 token
= next_token (&val
, cfile
);
649 if (token
!= COLON
) {
650 parse_warn ("expected colon seperating hour from minute.");
652 skip_to_semi (cfile
);
657 token
= next_token (&val
, cfile
);
658 if (token
!= NUMBER
) {
659 parse_warn ("numeric minute expected.");
661 skip_to_semi (cfile
);
664 tm
.tm_sec
= atoi (val
);
667 /* XXX */ /* We assume that mktime does not use tm_yday. */
670 /* Make sure the date ends in a semicolon... */
671 if (!parse_semi (cfile
))
674 /* Guess the time value... */
675 guess
= ((((((365 * (tm
.tm_year
- 70) + /* Days in years since '70 */
676 (tm
.tm_year
- 69) / 4 + /* Leap days since '70 */
677 (tm
.tm_mon
/* Days in months this year */
678 ? months
[tm
.tm_mon
- 1]
680 (tm
.tm_mon
> 1 && /* Leap day this year */
681 !((tm
.tm_year
- 72) & 3)) +
682 tm
.tm_mday
- 1) * 24) + /* Day of month */
684 tm
.tm_min
) * 60) + tm
.tm_sec
;
686 /* This guess could be wrong because of leap seconds or other
687 weirdness we don't know about that the system does. For
688 now, we're just going to accept the guess, but at some point
689 it might be nice to do a successive approximation here to
690 get an exact value. Even if the error is small, if the
691 server is restarted frequently (and thus the lease database
692 is reread), the error could accumulate into something
699 * option-name :== IDENTIFIER |
700 IDENTIFIER . IDENTIFIER
703 struct option
*parse_option_name (cfile
)
707 enum dhcp_token token
;
709 struct universe
*universe
;
710 struct option
*option
;
712 token
= next_token (&val
, cfile
);
713 if (!is_identifier (token
)) {
714 parse_warn ("expecting identifier after option keyword.");
716 skip_to_semi (cfile
);
717 return (struct option
*)0;
719 vendor
= malloc (strlen (val
) + 1);
721 log_fatal ("no memory for vendor information.");
722 strcpy (vendor
, val
);
723 token
= peek_token (&val
, cfile
);
725 /* Go ahead and take the DOT token... */
726 token
= next_token (&val
, cfile
);
728 /* The next token should be an identifier... */
729 token
= next_token (&val
, cfile
);
730 if (!is_identifier (token
)) {
731 parse_warn ("expecting identifier after '.'");
733 skip_to_semi (cfile
);
734 return (struct option
*)0;
737 /* Look up the option name hash table for the specified
739 universe
= ((struct universe
*)
740 hash_lookup (&universe_hash
,
741 (unsigned char *)vendor
, 0));
742 /* If it's not there, we can't parse the rest of the
745 parse_warn ("no vendor named %s.", vendor
);
746 skip_to_semi (cfile
);
747 return (struct option
*)0;
750 /* Use the default hash table, which contains all the
751 standard dhcp option names. */
753 universe
= &dhcp_universe
;
756 /* Look up the actual option info... */
757 option
= (struct option
*)hash_lookup (universe
-> hash
,
758 (unsigned char *)val
, 0);
760 /* If we didn't get an option structure, it's an undefined option. */
763 parse_warn ("no option named %s", val
);
765 parse_warn ("no option named %s for vendor %s",
767 skip_to_semi (cfile
);
768 return (struct option
*)0;
771 /* Free the initial identifier token. */
777 * colon-seperated-hex-list :== NUMBER |
778 * NUMBER COLON colon-seperated-hex-list
781 int parse_cshl (data
, cfile
)
782 struct data_string
*data
;
788 struct option_tag
*sl
= (struct option_tag
*)0;
789 struct option_tag
*next
, **last
= &sl
;
790 enum dhcp_token token
;
795 token
= next_token (&val
, cfile
);
796 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
797 parse_warn ("expecting hexadecimal number.");
798 skip_to_semi (cfile
);
799 for (; sl
; sl
= next
) {
801 dfree (sl
, "parse_cshl");
805 if (ilen
== sizeof ibuf
) {
806 next
= (struct option_tag
*)
808 sizeof (struct option_tag
),
811 log_fatal ("no memory for string list.");
812 memcpy (next
-> data
, ibuf
, ilen
);
814 last
= &next
-> next
;
818 convert_num (&ibuf
[ilen
++], val
, 16, 8);
820 token
= peek_token (&val
, cfile
);
823 token
= next_token (&val
, cfile
);
826 if (!buffer_allocate (&data
-> buffer
, tlen
+ ilen
, "parse_cshl"))
827 log_fatal ("no memory to store octet data.");
828 data
-> data
= &data
-> buffer
-> data
[0];
829 data
-> len
= tlen
+ ilen
;
830 data
-> terminated
= 0;
832 rvp
= &data
-> data
[0];
835 memcpy (rvp
, sl
-> data
, sizeof ibuf
);
837 dfree (sl
, "parse_cshl");
841 memcpy (rvp
, ibuf
, ilen
);
846 * executable-statements :== executable-statement executable-statements |
847 * executable-statement
849 * executable-statement :==
851 * ADD class-name SEMI |
853 * OPTION option-parameter SEMI |
854 * SUPERSEDE option-parameter SEMI |
855 * PREPEND option-parameter SEMI |
856 * APPEND option-parameter SEMI
859 struct executable_statement
*parse_executable_statements (cfile
, lose
)
863 struct executable_statement
*head
, **next
;
866 while ((*next
= parse_executable_statement (cfile
, lose
)))
867 next
= &((*next
) -> next
);
870 return (struct executable_statement
*)0;
873 struct executable_statement
*parse_executable_statement (cfile
, lose
)
877 enum dhcp_token token
;
879 struct executable_statement
*stmt
, base
;
881 struct option
*option
;
883 switch (peek_token (&val
, cfile
)) {
885 next_token (&val
, cfile
);
886 stmt
= parse_if_statement (cfile
, lose
);
889 token
= next_token (&val
, cfile
);
890 token
= next_token (&val
, cfile
);
891 if (token
!= STRING
) {
892 parse_warn ("expecting class name.");
893 skip_to_semi (cfile
);
895 return (struct executable_statement
*)0;
897 cta
= find_class (val
);
899 parse_warn ("unknown class %s.", val
);
900 skip_to_semi (cfile
);
902 return (struct executable_statement
*)0;
904 if (!parse_semi (cfile
)) {
906 return (struct executable_statement
*)0;
908 memset (&base
, 0, sizeof base
);
909 base
.op
= add_statement
;
914 token
= next_token (&val
, cfile
);
915 if (!parse_semi (cfile
)) {
917 return (struct executable_statement
*)0;
919 memset (&base
, 0, sizeof base
);
920 base
.op
= break_statement
;
925 parse_warn ("send not appropriate here.");
926 skip_to_semi (cfile
);
927 return (struct executable_statement
*)0;
931 token
= next_token (&val
, cfile
);
932 option
= parse_option_name (cfile
);
935 return (struct executable_statement
*)0;
937 return parse_option_statement (cfile
, 1, option
,
938 supersede_option_statement
);
941 token
= next_token (&val
, cfile
);
942 option
= parse_option_name (cfile
);
945 return (struct executable_statement
*)0;
947 return parse_option_statement (cfile
, 1, option
,
948 default_option_statement
);
951 token
= next_token (&val
, cfile
);
952 option
= parse_option_name (cfile
);
955 return (struct executable_statement
*)0;
957 return parse_option_statement (cfile
, 1, option
,
958 prepend_option_statement
);
961 token
= next_token (&val
, cfile
);
962 option
= parse_option_name (cfile
);
965 return (struct executable_statement
*)0;
967 return parse_option_statement (cfile
, 1, option
,
968 append_option_statement
);
972 return (struct executable_statement
*)0;
975 stmt
= ((struct executable_statement
*)
976 dmalloc (sizeof (struct executable_statement
),
977 "parse_executable_statement"));
979 log_fatal ("no memory for new statement.");
985 * if-statement :== boolean-expression LBRACE executable-statements RBRACE
988 * else-statement :== <null> |
989 * ELSE LBRACE executable-statements RBRACE |
990 * ELSE IF if-statement |
994 struct executable_statement
*parse_if_statement (cfile
, lose
)
998 enum dhcp_token token
;
1000 struct executable_statement
*stmt
;
1001 struct expression
*if_condition
;
1002 struct executable_statement
*true, *false;
1004 if_condition
= (struct expression
*)0;
1005 if (!parse_boolean_expression (&if_condition
, cfile
, lose
)) {
1007 parse_warn ("boolean expression expected.");
1008 return (struct executable_statement
*)0;
1010 #if defined (DEBUG_EXPRESSION_PARSE)
1011 print_expression ("if condition", if_condition
);
1013 token
= next_token (&val
, cfile
);
1014 if (token
!= LBRACE
) {
1015 parse_warn ("left brace expected.");
1016 skip_to_semi (cfile
);
1018 return (struct executable_statement
*)0;
1020 true = parse_executable_statements (cfile
, lose
);
1021 token
= next_token (&val
, cfile
);
1023 /* Try to even things up. */
1025 token
= next_token (&val
, cfile
);
1026 } while (token
!= EOF
&& token
!= RBRACE
);
1027 return (struct executable_statement
*)0;
1029 if (token
!= RBRACE
) {
1030 parse_warn ("right brace expected.");
1031 skip_to_semi (cfile
);
1033 return (struct executable_statement
*)0;
1035 token
= peek_token (&val
, cfile
);
1036 if (token
== ELSE
) {
1037 token
= next_token (&val
, cfile
);
1038 token
= peek_token (&val
, cfile
);
1040 token
= next_token (&val
, cfile
);
1041 false = parse_if_statement (cfile
, lose
);
1043 return (struct executable_statement
*)0;
1044 } else if (token
!= LBRACE
) {
1045 parse_warn ("left brace or if expected.");
1046 skip_to_semi (cfile
);
1048 return (struct executable_statement
*)0;
1050 token
= next_token (&val
, cfile
);
1051 false = parse_executable_statements (cfile
, lose
);
1053 return (struct executable_statement
*)0;
1054 token
= next_token (&val
, cfile
);
1055 if (token
!= RBRACE
) {
1056 parse_warn ("right brace expected.");
1057 skip_to_semi (cfile
);
1059 return (struct executable_statement
*)0;
1062 } else if (token
== ELSIF
) {
1063 token
= next_token (&val
, cfile
);
1064 false = parse_if_statement (cfile
, lose
);
1066 return (struct executable_statement
*)0;
1068 false = (struct executable_statement
*)0;
1070 stmt
= ((struct executable_statement
*)
1071 dmalloc (sizeof (struct executable_statement
),
1072 "parse_if_statement"));
1074 log_fatal ("no memory for if statement.");
1075 memset (stmt
, 0, sizeof *stmt
);
1076 stmt
-> op
= if_statement
;
1077 stmt
-> data
.ie
.expr
= if_condition
;
1078 stmt
-> data
.ie
.true = true;
1079 stmt
-> data
.ie
.false = false;
1084 * boolean_expression :== CHECK STRING |
1085 * NOT boolean-expression |
1086 * data-expression EQUAL data-expression |
1087 * boolean-expression AND boolean-expression |
1088 * boolean-expression OR boolean-expression
1089 * EXISTS OPTION-NAME
1092 int parse_boolean_expression (expr
, cfile
, lose
)
1093 struct expression
**expr
;
1097 /* Parse an expression... */
1098 if (!parse_expression (expr
, cfile
, lose
, context_boolean
,
1099 (struct expression
**)0, expr_none
))
1102 if (!is_boolean_expression (*expr
)) {
1103 parse_warn ("Expecting a boolean expression.");
1111 * data_expression :== SUBSTRING LPAREN data-expression COMMA
1112 * numeric-expression COMMA
1113 * numeric-expression RPAREN |
1114 * SUFFIX LPAREN data_expression COMMA
1115 * numeric-expression |
1116 * OPTION option_name |
1118 * PACKET LPAREN numeric-expression COMMA
1119 * numeric-expression RPAREN |
1121 * colon_seperated_hex_list
1124 int parse_data_expression (expr
, cfile
, lose
)
1125 struct expression
**expr
;
1129 /* Parse an expression... */
1130 if (!parse_expression (expr
, cfile
, lose
, context_data
,
1131 (struct expression
**)0, expr_none
))
1134 if (!is_data_expression (*expr
)) {
1135 parse_warn ("Expecting a data expression.");
1143 * numeric-expression :== EXTRACT_INT LPAREN data-expression
1144 * COMMA number RPAREN |
1148 int parse_numeric_expression (expr
, cfile
, lose
)
1149 struct expression
**expr
;
1153 /* Parse an expression... */
1154 if (!parse_expression (expr
, cfile
, lose
, context_numeric
,
1155 (struct expression
**)0, expr_none
))
1158 if (!is_numeric_expression (*expr
)) {
1159 parse_warn ("Expecting a numeric expression.");
1166 /* Parse a subexpression that does not contain a binary operator. */
1168 int parse_non_binary (expr
, cfile
, lose
, context
)
1169 struct expression
**expr
;
1172 enum expression_context context
;
1174 enum dhcp_token token
;
1176 struct collection
*col
;
1177 struct option
*option
;
1179 token
= peek_token (&val
, cfile
);
1181 /* Check for unary operators... */
1184 token
= next_token (&val
, cfile
);
1185 token
= next_token (&val
, cfile
);
1186 if (token
!= STRING
) {
1187 parse_warn ("string expected.");
1188 skip_to_semi (cfile
);
1192 for (col
= collections
; col
; col
= col
-> next
)
1193 if (!strcmp (col
-> name
, val
))
1196 parse_warn ("unknown collection.");
1200 if (!expression_allocate (expr
, "parse_expression: CHECK"))
1201 log_fatal ("can't allocate expression");
1202 (*expr
) -> op
= expr_check
;
1203 (*expr
) -> data
.check
= col
;
1207 token
= next_token (&val
, cfile
);
1208 if (!expression_allocate (expr
, "parse_expression: NOT"))
1209 log_fatal ("can't allocate expression");
1210 (*expr
) -> op
= expr_not
;
1211 if (!parse_non_binary (&(*expr
) -> data
.not,
1212 cfile
, lose
, context
)) {
1214 parse_warn ("expression expected");
1215 skip_to_semi (cfile
);
1218 expression_dereference (expr
, "parse_expression: NOT");
1224 token
= next_token (&val
, cfile
);
1225 if (!expression_allocate (expr
, "parse_expression: EXISTS"))
1226 log_fatal ("can't allocate expression");
1227 (*expr
) -> op
= expr_exists
;
1228 (*expr
) -> data
.option
= parse_option_name (cfile
);
1229 if (!(*expr
) -> data
.option
) {
1231 expression_dereference (expr
,
1232 "parse_expression: EXISTS");
1238 token
= next_token (&val
, cfile
);
1239 if (!expression_allocate (expr
, "parse_expression: SUBSTRING"))
1240 log_fatal ("can't allocate expression");
1241 (*expr
) -> op
= expr_substring
;
1243 token
= next_token (&val
, cfile
);
1244 if (token
!= LPAREN
) {
1246 expression_dereference (expr
,
1247 "parse_expression: nolparen");
1248 parse_warn ("left parenthesis expected.");
1253 if (!parse_data_expression (&(*expr
) -> data
.substring
.expr
,
1256 expression_dereference (expr
,
1257 "parse_expression: nodata");
1258 parse_warn ("expecting data expression.");
1259 skip_to_semi (cfile
);
1264 token
= next_token (&val
, cfile
);
1265 if (token
!= COMMA
) {
1267 expression_dereference (expr
,
1268 "parse_expression: nocomma1");
1269 parse_warn ("comma expected.");
1275 if (!parse_numeric_expression
1276 (&(*expr
) -> data
.substring
.offset
,cfile
, lose
)) {
1279 parse_warn ("expecting numeric expression.");
1280 skip_to_semi (cfile
);
1283 expression_dereference (expr
,
1284 "parse_expression: nonum");
1288 token
= next_token (&val
, cfile
);
1292 if (!parse_numeric_expression
1293 (&(*expr
) -> data
.substring
.len
, cfile
, lose
))
1296 token
= next_token (&val
, cfile
);
1297 if (token
!= RPAREN
) {
1299 parse_warn ("right parenthesis expected.");
1301 expression_dereference (expr
,
1302 "parse_expression: norparen");
1308 token
= next_token (&val
, cfile
);
1309 if (!expression_allocate (expr
, "parse_expression: SUFFIX"))
1310 log_fatal ("can't allocate expression");
1311 (*expr
) -> op
= expr_suffix
;
1313 token
= next_token (&val
, cfile
);
1314 if (token
!= LPAREN
)
1317 if (!parse_data_expression (&(*expr
) -> data
.suffix
.expr
,
1321 token
= next_token (&val
, cfile
);
1325 if (!parse_data_expression (&(*expr
) -> data
.suffix
.len
,
1329 token
= next_token (&val
, cfile
);
1330 if (token
!= RPAREN
)
1335 token
= next_token (&val
, cfile
);
1336 if (!expression_allocate (expr
, "parse_expression: OPTION"))
1337 log_fatal ("can't allocate expression");
1338 (*expr
) -> op
= expr_option
;
1339 (*expr
) -> data
.option
= parse_option_name (cfile
);
1340 if (!(*expr
) -> data
.option
) {
1342 expression_dereference (expr
,
1343 "parse_expression: OPTION");
1349 token
= next_token (&val
, cfile
);
1350 if (!expression_allocate (expr
, "parse_expression: HARDWARE"))
1351 log_fatal ("can't allocate expression");
1352 (*expr
) -> op
= expr_hardware
;
1356 token
= next_token (&val
, cfile
);
1357 if (!expression_allocate (expr
, "parse_expression: PACKET"))
1358 log_fatal ("can't allocate expression");
1359 (*expr
) -> op
= expr_packet
;
1361 token
= next_token (&val
, cfile
);
1362 if (token
!= LPAREN
)
1365 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.offset
,
1369 token
= next_token (&val
, cfile
);
1373 if (!parse_numeric_expression (&(*expr
) -> data
.packet
.len
,
1377 token
= next_token (&val
, cfile
);
1378 if (token
!= RPAREN
)
1383 token
= next_token (&val
, cfile
);
1384 if (!make_const_data (expr
, val
, strlen (val
), 1, 1))
1385 log_fatal ("can't make constant string expression.");
1389 token
= next_token (&val
, cfile
);
1390 token
= next_token (&val
, cfile
);
1391 if (token
!= LPAREN
) {
1392 parse_warn ("left parenthesis expected.");
1397 if (!expression_allocate (expr
,
1398 "parse_expression: EXTRACT_INT"))
1399 log_fatal ("can't allocate expression");
1401 if (!parse_data_expression (&(*expr
) -> data
.extract_int
,
1403 parse_warn ("expecting data expression.");
1404 skip_to_semi (cfile
);
1406 expression_dereference
1407 (expr
, "parse_expression: EXTRACT_INT");
1411 token
= next_token (&val
, cfile
);
1412 if (token
!= COMMA
) {
1413 parse_warn ("comma expected.");
1418 token
= next_token (&val
, cfile
);
1419 if (token
!= NUMBER
) {
1420 parse_warn ("number expected.");
1424 switch (atoi (val
)) {
1426 (*expr
) -> op
= expr_extract_int8
;
1430 (*expr
) -> op
= expr_extract_int16
;
1434 (*expr
) -> op
= expr_extract_int32
;
1438 parse_warn ("unsupported integer size %d", atoi (val
));
1440 skip_to_semi (cfile
);
1441 expression_dereference
1442 (expr
, "parse_expression: EXTRACT_INT");
1446 token
= next_token (&val
, cfile
);
1447 if (token
!= RPAREN
) {
1448 parse_warn ("right parenthesis expected.");
1455 if (!expression_allocate (expr
,
1456 "parse_expression: NUMBER"))
1457 log_fatal ("can't allocate expression");
1459 /* If we're in a numeric context, this should just be a
1460 number, by itself. */
1461 if (context
== context_numeric
) {
1462 next_token (&val
, cfile
); /* Eat the number. */
1463 (*expr
) -> op
= expr_const_int
;
1464 (*expr
) -> data
.const_int
= atoi (val
);
1468 case NUMBER_OR_NAME
:
1469 (*expr
) -> op
= expr_const_data
;
1470 if (!parse_cshl (&(*expr
) -> data
.const_data
, cfile
)) {
1471 expression_dereference (expr
,
1472 "parse_expression: cshl");
1477 /* Not a valid start to an expression... */
1484 /* Parse an expression. */
1486 int parse_expression (expr
, cfile
, lose
, context
, plhs
, binop
)
1487 struct expression
**expr
;
1490 enum expression_context context
;
1491 struct expression
**plhs
;
1494 enum dhcp_token token
;
1496 struct expression
*rhs
= (struct expression
*)0, *tmp
;
1497 struct expression
*lhs
;
1498 enum expr_op next_op
;
1500 /* Consume the left hand side we were passed. */
1503 *plhs
= (struct expression
*)0;
1505 lhs
= (struct expression
*)0;
1508 if (!parse_non_binary (&rhs
, cfile
, lose
, context
)) {
1509 /* If we already have a left-hand side, then it's not
1510 okay for there not to be a right-hand side here, so
1511 we need to flag it as an error. */
1514 parse_warn ("expecting right-hand side.");
1516 skip_to_semi (cfile
);
1518 expression_dereference (&lhs
, "parse_expression");
1523 /* At this point, rhs contains either an entire subexpression,
1524 or at least a left-hand-side. If we do not see a binary token
1525 as the next token, we're done with the expression. */
1527 token
= peek_token (&val
, cfile
);
1530 next_op
= expr_equal
;
1542 next_op
= expr_none
;
1545 /* If we have no lhs yet, we just parsed it. */
1547 /* If there was no operator following what we just parsed,
1548 then we're done - return it. */
1549 if (next_op
== expr_none
) {
1554 rhs
= (struct expression
*)0;
1556 next_token (&val
, cfile
); /* Consume the operator. */
1560 /* Now, if we didn't find a binary operator, we're done parsing
1561 this subexpression, so combine it with the preceding binary
1562 operator and return the result. */
1563 if (next_op
== expr_none
) {
1564 if (!expression_allocate (expr
,
1565 "parse_expression: COMBINE"))
1566 log_fatal ("Can't allocate expression!");
1568 (*expr
) -> op
= binop
;
1569 /* All the binary operators' data union members
1570 are the same, so we'll cheat and use the member
1571 for the equals operator. */
1572 (*expr
) -> data
.equal
[0] = lhs
;
1573 (*expr
) -> data
.equal
[1] = rhs
;
1577 /* Eat the operator token - we now know it was a binary operator... */
1578 token
= next_token (&val
, cfile
);
1580 /* If the binary operator we saw previously has a lower precedence
1581 than the next operator, then the rhs we just parsed for that
1582 operator is actually the lhs of the operator with the higher
1583 precedence - to get the real rhs, we need to recurse on the
1585 if (binop
!= expr_none
&&
1586 op_precedence (binop
, next_op
) < 0) {
1588 rhs
= (struct expression
*)0;
1589 if (!parse_expression (&rhs
, cfile
, lose
, op_context (next_op
),
1592 parse_warn ("expecting a subexpression");
1597 next_op
= expr_none
;
1600 /* Now combine the LHS and the RHS using binop. */
1601 tmp
= (struct expression
*)0;
1602 if (!expression_allocate (&tmp
, "parse_expression: COMBINE2"))
1603 log_fatal ("No memory for equal precedence combination.");
1605 /* Store the LHS and RHS. */
1606 tmp
-> data
.equal
[0] = lhs
;
1607 tmp
-> data
.equal
[1] = rhs
;
1611 tmp
= (struct expression
*)0;
1612 rhs
= (struct expression
*)0;
1614 /* Recursions don't return until we have parsed the end of the
1615 expression, so if we recursed earlier, we can now return what
1617 if (next_op
== expr_none
) {
1626 /* option-statement :== identifier DOT identifier <syntax> SEMI
1627 | identifier <syntax> SEMI
1629 Option syntax is handled specially through format strings, so it
1630 would be painful to come up with BNF for it. However, it always
1631 starts as above and ends in a SEMI. */
1633 struct executable_statement
*parse_option_statement (cfile
, lookups
,
1637 struct option
*option
;
1638 enum statement_op op
;
1641 enum dhcp_token token
;
1643 struct expression
*expr
= (struct expression
*)0;
1644 struct expression
*tmp
;
1646 struct executable_statement
*stmt
;
1649 token
= peek_token (&val
, cfile
);
1650 if (token
== SEMI
) {
1651 /* Eat the semicolon... */
1652 token
= next_token (&val
, cfile
);
1656 /* Parse the option data... */
1658 /* Set a flag if this is an array of a simple type (i.e.,
1659 not an array of pairs of IP addresses, or something
1661 int uniform
= option
-> format
[1] == 'A';
1663 for (fmt
= option
-> format
; *fmt
; fmt
++) {
1667 expr
= (struct expression
*)0;
1668 if (!parse_option_token (&expr
, cfile
, fmt
,
1669 tmp
, uniform
, lookups
)) {
1670 expression_dereference
1671 (&tmp
, "parse_option_statement");
1672 return (struct executable_statement
*)0;
1675 expression_dereference
1676 (&tmp
, "parse_option_statement");
1679 token
= peek_token (&val
, cfile
);
1680 if (token
== COMMA
) {
1681 token
= next_token (&val
, cfile
);
1686 } while (*fmt
== 'A');
1692 /* See if there's a data expression, and if so, use it rather than
1693 the standard format. */
1694 expr
= parse_data_expression (cfile
, &lose
);
1696 /* Found a data expression, but it was bogus? */
1698 return (struct executable_statement
*)0;
1702 if (!parse_semi (cfile
))
1703 return (struct executable_statement
*)0;
1704 stmt
= ((struct executable_statement
*)
1705 dmalloc (sizeof *stmt
, "parse_option_statement"));
1706 memset (stmt
, 0, sizeof *stmt
);
1708 if (expr
&& !option_cache (&stmt
-> data
.option
,
1709 (struct data_string
*)0, expr
, option
))
1710 log_fatal ("no memory for option cache in parse_option_statement");
1714 int parse_option_token (rv
, cfile
, fmt
, expr
, uniform
, lookups
)
1715 struct expression
**rv
;
1718 struct expression
*expr
;
1723 enum dhcp_token token
;
1724 struct expression
*t
= (struct expression
*)0;
1725 unsigned char buf
[4];
1732 token
= peek_token (&val
, cfile
);
1733 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
1734 if (!expression_allocate (&t
, "parse_option_token"))
1736 if (!parse_cshl (&t
-> data
.const_data
, cfile
))
1738 t
-> op
= expr_const_data
;
1739 } else if (token
== STRING
) {
1740 token
= next_token (&val
, cfile
);
1741 if (!make_const_data (&t
, (unsigned char *) val
,
1742 strlen (val
), 1, 1))
1743 log_fatal ("No memory for concatenation");
1745 parse_warn ("expecting string %s.",
1746 "or hexadecimal data");
1747 skip_to_semi (cfile
);
1752 case 't': /* Text string... */
1753 token
= next_token (&val
, cfile
);
1754 if (token
!= STRING
&& !is_identifier (token
)) {
1755 parse_warn ("expecting string.");
1757 skip_to_semi (cfile
);
1760 if (!make_const_data (&t
, (unsigned char *)val
,
1761 strlen (val
), 1, 1))
1762 log_fatal ("No memory for concatenation");
1765 case 'I': /* IP address or hostname. */
1767 if (!parse_ip_addr_or_hostname (&t
, cfile
, uniform
))
1770 if (!parse_ip_addr (cfile
, &addr
))
1772 if (!make_const_data (&t
, addr
.iabuf
, addr
.len
, 0, 1))
1777 case 'L': /* Unsigned 32-bit integer... */
1778 case 'l': /* Signed 32-bit integer... */
1779 token
= next_token (&val
, cfile
);
1780 if (token
!= NUMBER
) {
1782 parse_warn ("expecting number.");
1784 skip_to_semi (cfile
);
1787 convert_num (buf
, val
, 0, 32);
1788 if (!make_const_data (&t
, buf
, 4, 0, 1))
1792 case 's': /* Signed 16-bit integer. */
1793 case 'S': /* Unsigned 16-bit integer. */
1794 token
= next_token (&val
, cfile
);
1795 if (token
!= NUMBER
)
1797 convert_num (buf
, val
, 0, 16);
1798 if (!make_const_data (&t
, buf
, 2, 0, 1))
1802 case 'b': /* Signed 8-bit integer. */
1803 case 'B': /* Unsigned 8-bit integer. */
1804 token
= next_token (&val
, cfile
);
1805 if (token
!= NUMBER
)
1807 convert_num (buf
, val
, 0, 8);
1808 if (!make_const_data (&t
, buf
, 1, 0, 1))
1812 case 'f': /* Boolean flag. */
1813 token
= next_token (&val
, cfile
);
1814 if (!is_identifier (token
)) {
1815 parse_warn ("expecting identifier.");
1818 skip_to_semi (cfile
);
1821 if (!strcasecmp (val
, "true")
1822 || !strcasecmp (val
, "on"))
1824 else if (!strcasecmp (val
, "false")
1825 || !strcasecmp (val
, "off"))
1828 parse_warn ("expecting boolean.");
1831 if (!make_const_data (&t
, buf
, 1, 0, 1))
1836 log_error ("Bad format %c in parse_option_param.",
1838 skip_to_semi (cfile
);
1842 if (!make_concat (rv
, expr
, t
))
1844 expression_dereference (&t
, "parse_option_token");
1850 int parse_auth_key (key_id
, cfile
)
1851 struct data_string
*key_id
;
1854 struct data_string key_data
;
1856 enum dhcp_token token
;
1857 struct auth_key
*key
, *old_key
= (struct auth_key
*)0;
1859 memset (&key_data
, 0, sizeof key_data
);
1861 if (!parse_cshl (key_id
, cfile
))
1864 key
= auth_key_lookup (key_id
);
1866 token
= peek_token (&val
, cfile
);
1867 if (token
== SEMI
) {
1869 parse_warn ("reference to undefined key %s",
1870 print_hex_1 (key_id
-> len
,
1873 data_string_forget (key_id
, "parse_auth_key");
1875 if (!parse_cshl (&key_data
, cfile
))
1878 parse_warn ("redefinition of key %s",
1879 print_hex_1 (key_id
-> len
,
1884 key
= new_auth_key (key_data
.len
, "parse_auth_key");
1886 log_fatal ("No memory for key %s",
1887 print_hex_1 (key_id
-> len
,
1890 key
-> length
= key_data
.len
;
1891 memcpy (key
-> data
, key_data
.data
, key_data
.len
);
1892 enter_auth_key (key_id
, key
);
1893 data_string_forget (&key_data
, "parse_auth_key");
1897 return key_id
-> len
? 1 : 0;