3 Parser for dhclient config and lease files... */
6 * Copyright (c) 1996-2000 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: clparse.c,v 1.41 2000/01/26 14:55:26 mellon Exp $ Copyright (c) 1997 The Internet Software Consortium. All rights reserved.\n";
30 static TIME parsed_time
;
32 struct client_config top_level_config
;
34 u_int32_t default_requested_options
[] = {
36 DHO_BROADCAST_ADDRESS
,
40 DHO_DOMAIN_NAME_SERVERS
,
45 /* client-conf-file :== client-declarations EOF
46 client-declarations :== <nil>
48 | client-declarations client-declaration */
50 isc_result_t
read_client_conf ()
57 struct client_config
*config
;
58 struct client_state
*state
;
59 struct interface_info
*ip
;
62 /* Set up the initial dhcp option universe. */
63 initialize_common_option_spaces ();
65 /* Initialize the top level client configuration. */
66 memset (&top_level_config
, 0, sizeof top_level_config
);
68 /* Set some defaults... */
69 top_level_config
.timeout
= 60;
70 top_level_config
.select_interval
= 0;
71 top_level_config
.reboot_timeout
= 10;
72 top_level_config
.retry_interval
= 300;
73 top_level_config
.backoff_cutoff
= 15;
74 top_level_config
.initial_interval
= 3;
75 top_level_config
.bootp_policy
= P_ACCEPT
;
76 top_level_config
.script_name
= "/etc/dhclient-script";
77 top_level_config
.requested_options
= default_requested_options
;
79 top_level_config
.on_receipt
= new_group (MDL
);
80 if (!top_level_config
.on_receipt
)
81 log_fatal ("no memory for top-level on_receipt group");
83 top_level_config
.on_transmission
= new_group (MDL
);
84 if (!top_level_config
.on_transmission
)
85 log_fatal ("no memory for top-level on_transmission group");
87 if ((file
= open (path_dhclient_conf
, O_RDONLY
)) >= 0) {
88 cfile
= (struct parse
*)0;
89 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_conf
);
92 token
= peek_token (&val
, cfile
);
95 parse_client_statement (cfile
,
96 (struct interface_info
*)0,
99 token
= next_token (&val
, cfile
); /* Clear the peek buffer */
100 status
= (cfile
-> warnings_occurred
107 /* Set up state and config structures for clients that don't
108 have per-interface configuration statements. */
109 config
= (struct client_config
*)0;
110 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
112 ip
-> client
= (struct client_state
*)
113 dmalloc (sizeof (struct client_state
), MDL
);
115 log_fatal ("no memory for client state.");
116 memset (ip
-> client
, 0, sizeof *(ip
-> client
));
117 ip
-> client
-> interface
= ip
;
120 if (!ip
-> client
-> config
) {
122 config
= (struct client_config
*)
123 dmalloc (sizeof (struct client_config
),
126 log_fatal ("no memory for client config.");
127 memcpy (config
, &top_level_config
,
128 sizeof top_level_config
);
130 ip
-> client
-> config
= config
;
136 /* lease-file :== client-lease-statements EOF
137 client-lease-statements :== <nil>
138 | client-lease-statements LEASE client-lease-statement */
140 void read_client_leases ()
147 /* Open the lease file. If we can't open it, just return -
148 we can safely trust the server to remember our state. */
149 if ((file
= open (path_dhclient_db
, O_RDONLY
)) < 0)
151 cfile
= (struct parse
*)0;
152 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_db
);
155 token
= next_token (&val
, cfile
);
158 if (token
!= LEASE
) {
159 log_error ("Corrupt lease file - possible data loss!");
160 skip_to_semi (cfile
);
163 parse_client_lease_statement (cfile
, 0);
171 /* client-declaration :==
173 DEFAULT option-decl |
174 SUPERSEDE option-decl |
175 PREPEND option-decl |
177 hardware-declaration |
178 REQUEST option-list |
179 REQUIRE option-list |
183 SELECT_TIMEOUT number |
185 interface-declaration |
186 LEASE client-lease-statement |
187 ALIAS client-lease-statement |
188 AUTH_KEY key_id key_data */
190 void parse_client_statement (cfile
, ip
, config
)
192 struct interface_info
*ip
;
193 struct client_config
*config
;
197 struct option
*option
;
198 struct executable_statement
*stmt
, **p
;
199 enum statement_op op
;
202 struct data_string key_id
;
206 switch (peek_token (&val
, cfile
)) {
208 next_token (&val
, cfile
);
210 /* This may seem arbitrary, but there's a reason for
211 doing it: the authentication key database is not
212 scoped. If we allow the user to declare a key other
213 than in the outer scope, the user is very likely to
214 believe that the key will only be used in that
215 scope. If the user only wants the key to be used on
216 one interface, because it's known that the other
217 interface may be connected to an insecure net and
218 the secret key is considered sensitive, we don't
219 want to lull them into believing they've gotten
220 their way. This is a bit contrived, but people
221 tend not to be entirely rational about security. */
222 parse_warn (cfile
, "auth-key not allowed here.");
223 skip_to_semi (cfile
);
226 memset (&key_id
, 0, sizeof key_id
);
227 if (parse_auth_key (&key_id
, cfile
))
228 data_string_forget (&key_id
, MDL
);
231 /* REQUIRE can either start a policy statement or a
232 comma-seperated list of names of required options. */
234 next_token (&val
, cfile
);
235 token
= peek_token (&val
, cfile
);
236 if (token
== AUTHENTICATION
) {
240 parse_option_list (cfile
, &config
-> required_options
);
244 next_token (&val
, cfile
);
249 next_token (&val
, cfile
);
254 next_token (&val
, cfile
);
259 next_token (&val
, cfile
);
264 token
= next_token (&val
, cfile
);
265 if (token
== AUTHENTICATION
) {
266 if (policy
!= P_PREFER
&&
267 policy
!= P_REQUIRE
&&
270 "invalid authentication policy.");
271 skip_to_semi (cfile
);
274 config
-> auth_policy
= policy
;
275 } else if (token
!= BOOTP
) {
276 if (policy
!= P_PREFER
&&
277 policy
!= P_IGNORE
&&
278 policy
!= P_ACCEPT
) {
279 parse_warn (cfile
, "invalid bootp policy.");
280 skip_to_semi (cfile
);
283 config
-> bootp_policy
= policy
;
285 parse_warn (cfile
, "expecting a policy type.");
286 skip_to_semi (cfile
);
292 p
= &config
-> on_transmission
-> statements
;
293 op
= supersede_option_statement
;
295 token
= next_token (&val
, cfile
);
297 option
= parse_option_name (cfile
, 0, &known
);
300 stmt
= (struct executable_statement
*)0;
301 if (!parse_option_statement (&stmt
, cfile
, 1, option
, op
))
303 for (; *p
; p
= &((*p
) -> next
))
305 executable_statement_reference (p
, stmt
, MDL
);
306 stmt
-> next
= (struct executable_statement
*)0;
310 token
= next_token (&val
, cfile
);
312 token
= peek_token (&val
, cfile
);
313 if (token
== SPACE
) {
316 "option space definitions %s",
317 " may not be scoped.");
318 skip_to_semi (cfile
);
321 parse_option_space_decl (cfile
);
325 option
= parse_option_name (cfile
, 1, &known
);
329 token
= next_token (&val
, cfile
);
331 parse_warn (cfile
, "expecting \"code\" keyword.");
332 skip_to_semi (cfile
);
333 free_option (option
, MDL
);
338 "option definitions may only appear in %s",
339 "the outermost scope.");
340 skip_to_semi (cfile
);
341 free_option (option
, MDL
);
344 if (!parse_option_code_definition (cfile
, option
))
345 free_option (option
, MDL
);
349 p
= &config
-> on_receipt
-> statements
;
350 op
= default_option_statement
;
354 p
= &config
-> on_receipt
-> statements
;
355 op
= supersede_option_statement
;
359 p
= &config
-> on_receipt
-> statements
;
360 op
= append_option_statement
;
364 p
= &config
-> on_receipt
-> statements
;
365 op
= prepend_option_statement
;
369 token
= next_token (&val
, cfile
);
370 parse_string_list (cfile
, &config
-> media
, 1);
374 token
= next_token (&val
, cfile
);
376 parse_hardware_param (cfile
, &ip
-> hw_address
);
378 parse_warn (cfile
, "hardware address parameter %s",
379 "not allowed here.");
380 skip_to_semi (cfile
);
385 token
= next_token (&val
, cfile
);
386 if (config
-> requested_options
== default_requested_options
)
387 config
-> requested_options
= (u_int32_t
*)0;
388 parse_option_list (cfile
, &config
-> requested_options
);
392 token
= next_token (&val
, cfile
);
393 parse_lease_time (cfile
, &config
-> timeout
);
397 token
= next_token (&val
, cfile
);
398 parse_lease_time (cfile
, &config
-> retry_interval
);
402 token
= next_token (&val
, cfile
);
403 parse_lease_time (cfile
, &config
-> select_interval
);
407 token
= next_token (&val
, cfile
);
408 parse_lease_time (cfile
, &config
-> reboot_timeout
);
412 token
= next_token (&val
, cfile
);
413 parse_lease_time (cfile
, &config
-> backoff_cutoff
);
416 case INITIAL_INTERVAL
:
417 token
= next_token (&val
, cfile
);
418 parse_lease_time (cfile
, &config
-> initial_interval
);
422 token
= next_token (&val
, cfile
);
423 config
-> script_name
= parse_string (cfile
);
427 token
= next_token (&val
, cfile
);
429 parse_warn (cfile
, "nested interface declaration.");
430 parse_interface_declaration (cfile
, config
, (char *)0);
434 token
= next_token (&val
, cfile
);
435 token
= next_token (&val
, cfile
);
436 name
= dmalloc (strlen (val
) + 1, MDL
);
438 log_fatal ("no memory for pseudo interface name");
440 parse_interface_declaration (cfile
, config
, name
);
444 token
= next_token (&val
, cfile
);
445 parse_client_lease_statement (cfile
, 1);
449 token
= next_token (&val
, cfile
);
450 parse_client_lease_statement (cfile
, 2);
454 token
= next_token (&val
, cfile
);
455 parse_reject_statement (cfile
, config
);
460 stmt
= (struct executable_statement
*)0;
461 if (!parse_executable_statement (&stmt
,
462 cfile
, &lose
, context_any
)) {
464 parse_warn (cfile
, "expecting a statement.");
465 skip_to_semi (cfile
);
468 if (!config
-> on_receipt
-> statements
) {
469 executable_statement_reference
470 (&config
-> on_receipt
-> statements
,
473 struct executable_statement
*s
;
474 for (s
= config
-> on_receipt
-> statements
;
475 s
-> next
; s
= s
-> next
)
477 executable_statement_reference (&s
-> next
,
487 int parse_X (cfile
, buf
, max
)
497 token
= peek_token (&val
, cfile
);
498 if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
501 token
= next_token (&val
, cfile
);
502 if (token
!= NUMBER
&& token
!= NUMBER_OR_NAME
) {
504 "expecting hexadecimal constant.");
505 skip_to_semi (cfile
);
508 convert_num (cfile
, &buf
[len
], val
, 16, 8);
511 "hexadecimal constant too long.");
512 skip_to_semi (cfile
);
515 token
= peek_token (&val
, cfile
);
517 token
= next_token (&val
, cfile
);
518 } while (token
== COLON
);
520 } else if (token
== STRING
) {
521 token
= next_token (&val
, cfile
);
524 parse_warn (cfile
, "string constant too long.");
525 skip_to_semi (cfile
);
528 memcpy (buf
, val
, len
+ 1);
530 parse_warn (cfile
, "expecting string or hexadecimal data");
531 skip_to_semi (cfile
);
537 /* option-list :== option_name |
538 option_list COMMA option_name */
540 void parse_option_list (cfile
, list
)
547 pair p
= (pair
)0, q
, r
;
551 token
= next_token (&val
, cfile
);
554 if (!is_identifier (token
)) {
555 parse_warn (cfile
, "%s: expected option name.", val
);
556 skip_to_semi (cfile
);
559 for (i
= 0; i
< 256; i
++) {
560 if (!strcasecmp (dhcp_options
[i
].name
, val
))
564 parse_warn (cfile
, "%s: expected option name.", val
);
565 skip_to_semi (cfile
);
570 log_fatal ("can't allocate pair for option code.");
571 r
-> car
= (caddr_t
)i
;
579 token
= next_token (&val
, cfile
);
580 } while (token
== COMMA
);
582 parse_warn (cfile
, "expecting semicolon.");
583 skip_to_semi (cfile
);
589 *list
= dmalloc ((ix
+ 1) * sizeof **list
, MDL
);
591 log_error ("no memory for option list.");
594 for (q
= p
; q
; q
= q
-> cdr
)
595 (*list
) [ix
++] = (u_int32_t
)q
-> car
;
606 /* interface-declaration :==
607 INTERFACE string LBRACE client-declarations RBRACE */
609 void parse_interface_declaration (cfile
, outer_config
, name
)
611 struct client_config
*outer_config
;
616 struct client_state
*client
, **cp
;
617 struct interface_info
*ip
;
619 token
= next_token (&val
, cfile
);
620 if (token
!= STRING
) {
621 parse_warn (cfile
, "expecting interface name (in quotes).");
622 skip_to_semi (cfile
);
626 ip
= interface_or_dummy (val
);
628 /* If we were given a name, this is a pseudo-interface. */
630 make_client_state (&client
);
631 client
-> name
= name
;
632 client
-> interface
= ip
;
633 for (cp
= &ip
-> client
; *cp
; cp
= &((*cp
) -> next
))
638 make_client_state (&ip
-> client
);
639 ip
-> client
-> interface
= ip
;
641 client
= ip
-> client
;
644 if (!client
-> config
)
645 make_client_config (client
, outer_config
);
647 ip
-> flags
&= ~INTERFACE_AUTOMATIC
;
648 interfaces_requested
= 1;
650 token
= next_token (&val
, cfile
);
651 if (token
!= LBRACE
) {
652 parse_warn (cfile
, "expecting left brace.");
653 skip_to_semi (cfile
);
658 token
= peek_token (&val
, cfile
);
661 "unterminated interface declaration.");
666 parse_client_statement (cfile
, ip
, client
-> config
);
668 token
= next_token (&val
, cfile
);
671 struct interface_info
*interface_or_dummy (name
)
674 struct interface_info
*ip
;
676 /* Find the interface (if any) that matches the name. */
677 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
678 if (!strcmp (ip
-> name
, name
))
682 /* If it's not a real interface, see if it's on the dummy list. */
684 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
685 if (!strcmp (ip
-> name
, name
))
690 /* If we didn't find an interface, make a dummy interface as
693 ip
= (struct interface_info
*)dmalloc (sizeof *ip
, MDL
);
695 log_fatal ("No memory to record interface %s", name
);
696 memset (ip
, 0, sizeof *ip
);
697 strcpy (ip
-> name
, name
);
698 ip
-> next
= dummy_interfaces
;
699 dummy_interfaces
= ip
;
704 void make_client_state (state
)
705 struct client_state
**state
;
707 *state
= ((struct client_state
*)dmalloc (sizeof **state
, MDL
));
709 log_fatal ("no memory for client state\n");
710 memset (*state
, 0, sizeof **state
);
713 void make_client_config (client
, config
)
714 struct client_state
*client
;
715 struct client_config
*config
;
717 client
-> config
= (((struct client_config
*)
718 dmalloc (sizeof (struct client_config
), MDL
)));
719 if (!client
-> config
)
720 log_fatal ("no memory for client config\n");
721 memcpy (client
-> config
, config
, sizeof *config
);
722 client
-> config
-> on_receipt
=
723 clone_group (config
-> on_receipt
, MDL
);
724 client
-> config
-> on_transmission
=
725 clone_group (config
-> on_transmission
, MDL
);
728 /* client-lease-statement :==
729 RBRACE client-lease-declarations LBRACE
731 client-lease-declarations :==
733 client-lease-declaration |
734 client-lease-declarations client-lease-declaration */
737 void parse_client_lease_statement (cfile
, is_static
)
741 struct client_lease
*lease
, *lp
, *pl
;
742 struct interface_info
*ip
= (struct interface_info
*)0;
745 struct client_state
*client
= (struct client_state
*)0;
747 token
= next_token (&val
, cfile
);
748 if (token
!= LBRACE
) {
749 parse_warn (cfile
, "expecting left brace.");
750 skip_to_semi (cfile
);
754 lease
= ((struct client_lease
*)
755 dmalloc (sizeof (struct client_lease
), MDL
));
757 log_fatal ("no memory for lease.\n");
758 memset (lease
, 0, sizeof *lease
);
759 lease
-> is_static
= is_static
;
760 if (!option_state_allocate (&lease
-> options
, MDL
))
761 log_fatal ("no memory for lease options.\n");
764 token
= peek_token (&val
, cfile
);
766 parse_warn (cfile
, "unterminated lease declaration.");
771 parse_client_lease_declaration (cfile
, lease
, &ip
, &client
);
773 token
= next_token (&val
, cfile
);
775 /* If the lease declaration didn't include an interface
776 declaration that we recognized, it's of no use to us. */
778 destroy_client_lease (lease
);
782 /* Make sure there's a client state structure... */
784 make_client_state (&ip
-> client
);
785 ip
-> client
-> interface
= ip
;
788 client
= ip
-> client
;
790 /* If this is an alias lease, it doesn't need to be sorted in. */
791 if (is_static
== 2) {
792 ip
-> client
-> alias
= lease
;
796 /* The new lease may supersede a lease that's not the
797 active lease but is still on the lease list, so scan the
798 lease list looking for a lease with the same address, and
799 if we find it, toss it. */
800 pl
= (struct client_lease
*)0;
801 for (lp
= client
-> leases
; lp
; lp
= lp
-> next
) {
802 if (lp
-> address
.len
== lease
-> address
.len
&&
803 !memcmp (lp
-> address
.iabuf
, lease
-> address
.iabuf
,
804 lease
-> address
.len
)) {
806 pl
-> next
= lp
-> next
;
808 client
-> leases
= lp
-> next
;
809 destroy_client_lease (lp
);
814 /* If this is a preloaded lease, just put it on the list of recorded
815 leases - don't make it the active lease. */
817 lease
-> next
= client
-> leases
;
818 client
-> leases
= lease
;
822 /* The last lease in the lease file on a particular interface is
823 the active lease for that interface. Of course, we don't know
824 what the last lease in the file is until we've parsed the whole
825 file, so at this point, we assume that the lease we just parsed
826 is the active lease for its interface. If there's already
827 an active lease for the interface, and this lease is for the same
828 ip address, then we just toss the old active lease and replace
829 it with this one. If this lease is for a different address,
830 then if the old active lease has expired, we dump it; if not,
831 we put it on the list of leases for this interface which are
832 still valid but no longer active. */
833 if (client
-> active
) {
834 if (client
-> active
-> expiry
< cur_time
)
835 destroy_client_lease (client
-> active
);
836 else if (client
-> active
-> address
.len
==
837 lease
-> address
.len
&&
838 !memcmp (client
-> active
-> address
.iabuf
,
839 lease
-> address
.iabuf
,
840 lease
-> address
.len
))
841 destroy_client_lease (client
-> active
);
843 client
-> active
-> next
= client
-> leases
;
844 client
-> leases
= client
-> active
;
847 client
-> active
= lease
;
852 /* client-lease-declaration :==
855 FIXED_ADDR ip_address |
864 void parse_client_lease_declaration (cfile
, lease
, ipp
, clientp
)
866 struct client_lease
*lease
;
867 struct interface_info
**ipp
;
868 struct client_state
**clientp
;
873 struct interface_info
*ip
;
874 struct option_cache
*oc
;
875 struct client_state
*client
= (struct client_state
*)0;
876 struct data_string key_id
;
878 switch (next_token (&val
, cfile
)) {
880 memset (&key_id
, 0, sizeof key_id
);
881 if (parse_auth_key (&key_id
, cfile
)) {
882 data_string_copy (&lease
-> auth_key_id
, &key_id
, MDL
);
883 data_string_forget (&key_id
, MDL
);
887 lease
-> is_bootp
= 1;
891 token
= next_token (&val
, cfile
);
892 if (token
!= STRING
) {
894 "expecting interface name (in quotes).");
895 skip_to_semi (cfile
);
898 ip
= interface_or_dummy (val
);
903 token
= next_token (&val
, cfile
);
906 parse_warn (cfile
, "state name precedes interface.");
909 for (client
= ip
-> client
; client
; client
= client
-> next
)
910 if (client
-> name
&& !strcmp (client
-> name
, val
))
914 "lease specified for unknown pseudo.");
919 if (!parse_ip_addr (cfile
, &lease
-> address
))
924 parse_string_list (cfile
, &lease
-> medium
, 0);
928 lease
-> filename
= parse_string (cfile
);
932 lease
-> server_name
= parse_string (cfile
);
936 lease
-> renewal
= parse_date (cfile
);
940 lease
-> rebind
= parse_date (cfile
);
944 lease
-> expiry
= parse_date (cfile
);
948 oc
= (struct option_cache
*)0;
949 if (parse_option_decl (&oc
, cfile
)) {
950 save_option (oc
-> option
-> universe
,
951 lease
-> options
, oc
);
952 option_cache_dereference (&oc
, MDL
);
957 parse_warn (cfile
, "expecting lease declaration.");
958 skip_to_semi (cfile
);
961 token
= next_token (&val
, cfile
);
963 parse_warn (cfile
, "expecting semicolon.");
964 skip_to_semi (cfile
);
968 int parse_option_decl (oc
, cfile
)
969 struct option_cache
**oc
;
975 u_int8_t hunkbuf
[1024];
978 struct option
*option
;
979 struct iaddr ip_addr
;
986 option
= parse_option_name (cfile
, 0, &known
);
990 /* Parse the option data... */
992 /* Set a flag if this is an array of a simple type (i.e.,
993 not an array of pairs of IP addresses, or something
995 int uniform
= option
-> format
[1] == 'A';
997 for (fmt
= option
-> format
; *fmt
; fmt
++) {
1002 len
= parse_X (cfile
, &hunkbuf
[hunkix
],
1003 sizeof hunkbuf
- hunkix
);
1007 case 't': /* Text string... */
1008 token
= next_token (&val
, cfile
);
1009 if (token
!= STRING
) {
1011 "expecting string.");
1012 skip_to_semi (cfile
);
1016 if (hunkix
+ len
+ 1 > sizeof hunkbuf
) {
1018 "option data buffer %s",
1020 skip_to_semi (cfile
);
1023 memcpy (&hunkbuf
[hunkix
], val
, len
+ 1);
1028 case 'I': /* IP address. */
1029 if (!parse_ip_addr (cfile
, &ip_addr
))
1035 if (hunkix
+ len
> sizeof hunkbuf
) {
1037 "option data buffer %s",
1039 skip_to_semi (cfile
);
1042 memcpy (&hunkbuf
[hunkix
], dp
, len
);
1046 case 'L': /* Unsigned 32-bit integer... */
1047 case 'l': /* Signed 32-bit integer... */
1048 token
= next_token (&val
, cfile
);
1049 if (token
!= NUMBER
) {
1052 "expecting number.");
1054 skip_to_semi (cfile
);
1057 convert_num (cfile
, buf
, val
, 0, 32);
1062 case 's': /* Signed 16-bit integer. */
1063 case 'S': /* Unsigned 16-bit integer. */
1064 token
= next_token (&val
, cfile
);
1065 if (token
!= NUMBER
)
1067 convert_num (cfile
, buf
, val
, 0, 16);
1072 case 'b': /* Signed 8-bit integer. */
1073 case 'B': /* Unsigned 8-bit integer. */
1074 token
= next_token (&val
, cfile
);
1075 if (token
!= NUMBER
)
1077 convert_num (cfile
, buf
, val
, 0, 8);
1082 case 'f': /* Boolean flag. */
1083 token
= next_token (&val
, cfile
);
1084 if (!is_identifier (token
)) {
1086 "expecting identifier.");
1089 skip_to_semi (cfile
);
1092 if (!strcasecmp (val
, "true")
1093 || !strcasecmp (val
, "on"))
1095 else if (!strcasecmp (val
, "false")
1096 || !strcasecmp (val
, "off"))
1100 "expecting boolean.");
1108 log_error ("parse_option_param: Bad format %c",
1110 skip_to_semi (cfile
);
1114 token
= next_token (&val
, cfile
);
1115 } while (*fmt
== 'A' && token
== COMMA
);
1117 if (token
!= SEMI
) {
1118 parse_warn (cfile
, "semicolon expected.");
1119 skip_to_semi (cfile
);
1123 bp
= (struct buffer
*)0;
1124 if (!buffer_allocate (&bp
, hunkix
+ nul_term
, MDL
))
1125 log_fatal ("no memory to store option declaration.");
1127 log_fatal ("out of memory allocating option data.");
1128 memcpy (bp
-> data
, hunkbuf
, hunkix
+ nul_term
);
1130 if (!option_cache_allocate (oc
, MDL
))
1131 log_fatal ("out of memory allocating option cache.");
1133 (*oc
) -> data
.buffer
= bp
;
1134 (*oc
) -> data
.data
= &bp
-> data
[0];
1135 (*oc
) -> data
.terminated
= nul_term
;
1136 (*oc
) -> data
.len
= hunkix
;
1137 (*oc
) -> option
= option
;
1141 void parse_string_list (cfile
, lp
, multiple
)
1142 struct parse
*cfile
;
1143 struct string_list
**lp
;
1148 struct string_list
*cur
, *tmp
;
1150 /* Find the last medium in the media list. */
1152 for (cur
= *lp
; cur
-> next
; cur
= cur
-> next
)
1155 cur
= (struct string_list
*)0;
1159 token
= next_token (&val
, cfile
);
1160 if (token
!= STRING
) {
1161 parse_warn (cfile
, "Expecting media options.");
1162 skip_to_semi (cfile
);
1166 tmp
= ((struct string_list
*)
1167 dmalloc (strlen (val
) + 1 +
1168 sizeof (struct string_list
*), MDL
));
1170 log_fatal ("no memory for string list entry.");
1172 strcpy (tmp
-> string
, val
);
1173 tmp
-> next
= (struct string_list
*)0;
1175 /* Store this medium at the end of the media list. */
1182 token
= next_token (&val
, cfile
);
1183 } while (multiple
&& token
== COMMA
);
1185 if (token
!= SEMI
) {
1186 parse_warn (cfile
, "expecting semicolon.");
1187 skip_to_semi (cfile
);
1191 void parse_reject_statement (cfile
, config
)
1192 struct parse
*cfile
;
1193 struct client_config
*config
;
1198 struct iaddrlist
*list
;
1201 if (!parse_ip_addr (cfile
, &addr
)) {
1202 parse_warn (cfile
, "expecting IP address.");
1203 skip_to_semi (cfile
);
1207 list
= (struct iaddrlist
*)dmalloc (sizeof (struct iaddrlist
),
1210 log_fatal ("no memory for reject list!");
1212 list
-> addr
= addr
;
1213 list
-> next
= config
-> reject_list
;
1214 config
-> reject_list
= list
;
1216 token
= next_token (&val
, cfile
);
1217 } while (token
== COMMA
);
1219 if (token
!= SEMI
) {
1220 parse_warn (cfile
, "expecting semicolon.");
1221 skip_to_semi (cfile
);
1225 /* allow-deny-keyword :== BOOTP
1228 | UNKNOWN_CLIENTS */
1230 int parse_allow_deny (oc
, cfile
, flag
)
1231 struct option_cache
**oc
;
1232 struct parse
*cfile
;
1235 enum dhcp_token token
;
1237 unsigned char rf
= flag
;
1238 struct expression
*data
= (struct expression
*)0;
1241 parse_warn (cfile
, "allow/deny/ignore not permitted here.");
1242 skip_to_semi (cfile
);