3 Parser for dhclient config and lease files... */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-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: clparse.c,v 1.10 2005/08/11 17:13:21 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
42 static TIME parsed_time
;
44 struct client_config top_level_config
;
46 u_int32_t default_requested_options
[] = {
48 DHO_BROADCAST_ADDRESS
,
52 DHO_DOMAIN_NAME_SERVERS
,
57 /* client-conf-file :== client-declarations END_OF_FILE
58 client-declarations :== <nil>
60 | client-declarations client-declaration */
62 isc_result_t
read_client_conf ()
64 struct client_config
*config
;
65 struct interface_info
*ip
;
68 /* Set up the initial dhcp option universe. */
69 initialize_common_option_spaces ();
71 /* Initialize the top level client configuration. */
72 memset (&top_level_config
, 0, sizeof top_level_config
);
74 /* Set some defaults... */
75 top_level_config
.timeout
= 60;
76 top_level_config
.select_interval
= 0;
77 top_level_config
.reboot_timeout
= 10;
78 top_level_config
.retry_interval
= 300;
79 top_level_config
.backoff_cutoff
= 15;
80 top_level_config
.initial_interval
= 3;
81 top_level_config
.bootp_policy
= P_ACCEPT
;
82 top_level_config
.script_name
= path_dhclient_script
;
83 top_level_config
.requested_options
= default_requested_options
;
84 top_level_config
.omapi_port
= -1;
85 top_level_config
.do_forward_update
= 1;
87 group_allocate (&top_level_config
.on_receipt
, MDL
);
88 if (!top_level_config
.on_receipt
)
89 log_fatal ("no memory for top-level on_receipt group");
91 group_allocate (&top_level_config
.on_transmission
, MDL
);
92 if (!top_level_config
.on_transmission
)
93 log_fatal ("no memory for top-level on_transmission group");
95 status
= read_client_conf_file (path_dhclient_conf
,
96 (struct interface_info
*)0,
98 if (status
!= ISC_R_SUCCESS
) {
101 /* Set up the standard name service updater routine. */
102 parse
= (struct parse
*)0;
103 status
= new_parse (&parse
, -1, default_client_config
,
104 (sizeof default_client_config
) - 1,
105 "default client configuration", 0);
106 if (status
!= ISC_R_SUCCESS
)
107 log_fatal ("can't begin default client config!");
110 token
= peek_token (&val
, (unsigned *)0, cfile
);
111 if (token
== END_OF_FILE
)
113 parse_client_statement (cfile
,
114 (struct interface_info
*)0,
121 /* Set up state and config structures for clients that don't
122 have per-interface configuration statements. */
123 config
= (struct client_config
*)0;
124 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
126 ip
-> client
= (struct client_state
*)
127 dmalloc (sizeof (struct client_state
), MDL
);
129 log_fatal ("no memory for client state.");
130 memset (ip
-> client
, 0, sizeof *(ip
-> client
));
131 ip
-> client
-> interface
= ip
;
134 if (!ip
-> client
-> config
) {
136 config
= (struct client_config
*)
137 dmalloc (sizeof (struct client_config
),
140 log_fatal ("no memory for client config.");
141 memcpy (config
, &top_level_config
,
142 sizeof top_level_config
);
144 ip
-> client
-> config
= config
;
150 int read_client_conf_file (const char *name
, struct interface_info
*ip
,
151 struct client_config
*client
)
159 if ((file
= open (name
, O_RDONLY
)) < 0) {
161 return uerr2isc (errno
);
163 return errno
== ENOENT
? ISC_R_NOTFOUND
: ISC_R_NOPERM
;
167 cfile
= (struct parse
*)0;
168 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_conf
, 0);
171 token
= peek_token (&val
, (unsigned *)0, cfile
);
172 if (token
== END_OF_FILE
)
174 parse_client_statement (cfile
, ip
, client
);
176 token
= next_token (&val
, (unsigned *)0, cfile
);
177 status
= (cfile
-> warnings_occurred
186 /* lease-file :== client-lease-statements END_OF_FILE
187 client-lease-statements :== <nil>
188 | client-lease-statements LEASE client-lease-statement */
190 void read_client_leases ()
197 /* Open the lease file. If we can't open it, just return -
198 we can safely trust the server to remember our state. */
199 if ((file
= open (path_dhclient_db
, O_RDONLY
)) < 0)
201 cfile
= (struct parse
*)0;
202 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_db
, 0);
205 token
= next_token (&val
, (unsigned *)0, cfile
);
206 if (token
== END_OF_FILE
)
208 if (token
!= LEASE
) {
209 log_error ("Corrupt lease file - possible data loss!");
210 skip_to_semi (cfile
);
213 parse_client_lease_statement (cfile
, 0);
221 /* client-declaration :==
223 DEFAULT option-decl |
224 SUPERSEDE option-decl |
225 PREPEND option-decl |
227 hardware-declaration |
228 REQUEST option-list |
229 REQUIRE option-list |
233 SELECT_TIMEOUT number |
235 VENDOR_SPACE string |
236 interface-declaration |
237 LEASE client-lease-statement |
238 ALIAS client-lease-statement |
239 KEY key-definition */
241 void parse_client_statement (cfile
, ip
, config
)
243 struct interface_info
*ip
;
244 struct client_config
*config
;
248 struct option
*option
;
249 struct executable_statement
*stmt
;
257 switch (peek_token (&val
, (unsigned *)0, cfile
)) {
259 next_token (&val
, (unsigned *)0, cfile
);
260 token
= next_token (&val
, (unsigned *)0, cfile
);
261 if (token
!= STRING
) {
262 parse_warn (cfile
, "filename string expected.");
263 skip_to_semi (cfile
);
265 status
= read_client_conf_file (val
, ip
, config
);
266 if (status
!= ISC_R_SUCCESS
)
267 parse_warn (cfile
, "%s: bad parse.", val
);
274 next_token (&val
, (unsigned *)0, cfile
);
276 /* This may seem arbitrary, but there's a reason for
277 doing it: the authentication key database is not
278 scoped. If we allow the user to declare a key other
279 than in the outer scope, the user is very likely to
280 believe that the key will only be used in that
281 scope. If the user only wants the key to be used on
282 one interface, because it's known that the other
283 interface may be connected to an insecure net and
284 the secret key is considered sensitive, we don't
285 want to lull them into believing they've gotten
286 their way. This is a bit contrived, but people
287 tend not to be entirely rational about security. */
288 parse_warn (cfile
, "key definition not allowed here.");
289 skip_to_semi (cfile
);
296 /* REQUIRE can either start a policy statement or a
297 comma-seperated list of names of required options. */
299 next_token (&val
, (unsigned *)0, cfile
);
300 token
= peek_token (&val
, (unsigned *)0, cfile
);
301 if (token
== AUTHENTICATION
) {
305 parse_option_list (cfile
, &config
-> required_options
);
309 next_token (&val
, (unsigned *)0, cfile
);
314 next_token (&val
, (unsigned *)0, cfile
);
319 next_token (&val
, (unsigned *)0, cfile
);
324 next_token (&val
, (unsigned *)0, cfile
);
329 token
= next_token (&val
, (unsigned *)0, cfile
);
330 if (token
== AUTHENTICATION
) {
331 if (policy
!= P_PREFER
&&
332 policy
!= P_REQUIRE
&&
335 "invalid authentication policy.");
336 skip_to_semi (cfile
);
339 config
-> auth_policy
= policy
;
340 } else if (token
!= TOKEN_BOOTP
) {
341 if (policy
!= P_PREFER
&&
342 policy
!= P_IGNORE
&&
343 policy
!= P_ACCEPT
) {
344 parse_warn (cfile
, "invalid bootp policy.");
345 skip_to_semi (cfile
);
348 config
-> bootp_policy
= policy
;
350 parse_warn (cfile
, "expecting a policy type.");
351 skip_to_semi (cfile
);
357 token
= next_token (&val
, (unsigned *)0, cfile
);
359 token
= peek_token (&val
, (unsigned *)0, cfile
);
360 if (token
== SPACE
) {
363 "option space definitions %s",
364 " may not be scoped.");
365 skip_to_semi (cfile
);
368 parse_option_space_decl (cfile
);
372 option
= parse_option_name (cfile
, 1, &known
);
376 token
= next_token (&val
, (unsigned *)0, cfile
);
378 parse_warn (cfile
, "expecting \"code\" keyword.");
379 skip_to_semi (cfile
);
380 free_option (option
, MDL
);
385 "option definitions may only appear in %s",
386 "the outermost scope.");
387 skip_to_semi (cfile
);
388 free_option (option
, MDL
);
391 if (!parse_option_code_definition (cfile
, option
))
392 free_option (option
, MDL
);
396 token
= next_token (&val
, (unsigned *)0, cfile
);
397 parse_string_list (cfile
, &config
-> media
, 1);
401 token
= next_token (&val
, (unsigned *)0, cfile
);
403 parse_hardware_param (cfile
, &ip
-> hw_address
);
405 parse_warn (cfile
, "hardware address parameter %s",
406 "not allowed here.");
407 skip_to_semi (cfile
);
412 token
= next_token (&val
, (unsigned *)0, cfile
);
413 if (config
-> requested_options
== default_requested_options
)
414 config
-> requested_options
= (u_int32_t
*)0;
415 parse_option_list (cfile
, &config
-> requested_options
);
419 token
= next_token (&val
, (unsigned *)0, cfile
);
420 parse_lease_time (cfile
, &config
-> timeout
);
424 token
= next_token (&val
, (unsigned *)0, cfile
);
425 parse_lease_time (cfile
, &config
-> retry_interval
);
429 token
= next_token (&val
, (unsigned *)0, cfile
);
430 parse_lease_time (cfile
, &config
-> select_interval
);
434 token
= next_token (&val
, (unsigned *)0, cfile
);
435 token
= next_token (&val
, (unsigned *)0, cfile
);
436 if (config
!= &top_level_config
) {
438 "omapi info must be at top level.");
439 skip_to_semi (cfile
);
443 token
= next_token (&val
, (unsigned *)0, cfile
);
444 if (token
!= NUMBER
) {
446 "invalid port number: `%s'", val
);
447 skip_to_semi (cfile
);
451 if (tmp
< 0 || tmp
> 65535)
453 "invalid omapi port %d.", tmp
);
454 config
-> omapi_port
= tmp
;
457 } else if (token
== KEY
) {
458 token
= next_token (&val
, (unsigned *)0, cfile
);
459 if (token
!= STRING
&& !is_identifier (token
)) {
460 parse_warn (cfile
, "expecting key name.");
461 skip_to_semi (cfile
);
464 if (omapi_auth_key_lookup_name (&config
-> omapi_key
,
465 val
) != ISC_R_SUCCESS
)
466 parse_warn (cfile
, "unknown key %s", val
);
471 "unexpected omapi subtype: %s", val
);
472 skip_to_semi (cfile
);
476 case DO_FORWARD_UPDATE
:
477 token
= next_token (&val
, (unsigned *)0, cfile
);
478 token
= next_token (&val
, (unsigned *)0, cfile
);
479 if (!strcasecmp (val
, "on") ||
480 !strcasecmp (val
, "true"))
481 config
-> do_forward_update
= 1;
482 else if (!strcasecmp (val
, "off") ||
483 !strcasecmp (val
, "false"))
484 config
-> do_forward_update
= 0;
486 parse_warn (cfile
, "expecting boolean value.");
487 skip_to_semi (cfile
);
494 token
= next_token (&val
, (unsigned *)0, cfile
);
495 parse_lease_time (cfile
, &config
-> reboot_timeout
);
499 token
= next_token (&val
, (unsigned *)0, cfile
);
500 parse_lease_time (cfile
, &config
-> backoff_cutoff
);
503 case INITIAL_INTERVAL
:
504 token
= next_token (&val
, (unsigned *)0, cfile
);
505 parse_lease_time (cfile
, &config
-> initial_interval
);
509 token
= next_token (&val
, (unsigned *)0, cfile
);
510 parse_string (cfile
, &config
-> script_name
, (unsigned *)0);
514 token
= next_token (&val
, (unsigned *)0, cfile
);
515 token
= next_token (&val
, (unsigned *)0, cfile
);
516 if (token
!= OPTION
) {
517 parse_warn (cfile
, "expecting 'vendor option space'");
518 skip_to_semi (cfile
);
521 token
= next_token (&val
, (unsigned *)0, cfile
);
522 if (token
!= SPACE
) {
523 parse_warn (cfile
, "expecting 'vendor option space'");
524 skip_to_semi (cfile
);
527 token
= next_token (&val
, (unsigned *)0, cfile
);
528 if (!is_identifier (token
)) {
529 parse_warn (cfile
, "expecting an identifier.");
530 skip_to_semi (cfile
);
533 config
-> vendor_space_name
= dmalloc (strlen (val
) + 1, MDL
);
534 if (!config
-> vendor_space_name
)
535 log_fatal ("no memory for vendor option space name.");
536 strcpy (config
-> vendor_space_name
, val
);
537 for (i
= 0; i
< universe_count
; i
++)
538 if (!strcmp (universes
[i
] -> name
,
539 config
-> vendor_space_name
))
541 if (i
== universe_count
) {
542 log_error ("vendor option space %s not found.",
543 config
-> vendor_space_name
);
549 token
= next_token (&val
, (unsigned *)0, cfile
);
551 parse_warn (cfile
, "nested interface declaration.");
552 parse_interface_declaration (cfile
, config
, (char *)0);
556 token
= next_token (&val
, (unsigned *)0, cfile
);
557 token
= next_token (&val
, (unsigned *)0, cfile
);
558 name
= dmalloc (strlen (val
) + 1, MDL
);
560 log_fatal ("no memory for pseudo interface name");
562 parse_interface_declaration (cfile
, config
, name
);
566 token
= next_token (&val
, (unsigned *)0, cfile
);
567 parse_client_lease_statement (cfile
, 1);
571 token
= next_token (&val
, (unsigned *)0, cfile
);
572 parse_client_lease_statement (cfile
, 2);
576 token
= next_token (&val
, (unsigned *)0, cfile
);
577 parse_reject_statement (cfile
, config
);
582 stmt
= (struct executable_statement
*)0;
583 if (!parse_executable_statement (&stmt
,
584 cfile
, &lose
, context_any
)) {
586 parse_warn (cfile
, "expecting a statement.");
587 skip_to_semi (cfile
);
590 struct executable_statement
**eptr
, *sptr
;
592 (stmt
-> op
== send_option_statement
||
593 (stmt
-> op
== on_statement
&&
594 (stmt
-> data
.on
.evtypes
& ON_TRANSMISSION
)))) {
595 eptr
= &config
-> on_transmission
-> statements
;
596 if (stmt
-> op
== on_statement
) {
597 sptr
= (struct executable_statement
*)0;
598 executable_statement_reference
600 stmt
-> data
.on
.statements
, MDL
);
601 executable_statement_dereference (&stmt
,
603 executable_statement_reference (&stmt
,
606 executable_statement_dereference (&sptr
,
610 eptr
= &config
-> on_receipt
-> statements
;
613 for (; *eptr
; eptr
= &(*eptr
) -> next
)
615 executable_statement_reference (eptr
,
625 /* option-list :== option_name |
626 option_list COMMA option_name */
628 void parse_option_list (cfile
, list
)
635 pair p
= (pair
)0, q
= (pair
)0, r
;
636 struct option
*option
;
640 token
= peek_token (&val
, (unsigned *)0, cfile
);
642 token
= next_token (&val
, (unsigned *)0, cfile
);
645 if (!is_identifier (token
)) {
646 parse_warn (cfile
, "%s: expected option name.", val
);
647 token
= next_token (&val
, (unsigned *)0, cfile
);
648 skip_to_semi (cfile
);
651 option
= parse_option_name (cfile
, 0, NULL
);
653 parse_warn (cfile
, "%s: expected option name.", val
);
656 if (option
-> universe
!= &dhcp_universe
) {
658 "%s.%s: Only global options allowed.",
659 option
-> universe
-> name
, option
->name
);
660 skip_to_semi (cfile
);
665 log_fatal ("can't allocate pair for option code.");
666 r
-> car
= (caddr_t
)(long)option
-> code
;
674 token
= next_token (&val
, (unsigned *)0, cfile
);
675 } while (token
== COMMA
);
677 parse_warn (cfile
, "expecting semicolon.");
678 skip_to_semi (cfile
);
681 /* XXX we can't free the list here, because we may have copied
682 XXX it from an outer config state. */
683 *list
= (u_int32_t
*)0;
685 *list
= dmalloc ((ix
+ 1) * sizeof **list
, MDL
);
687 log_error ("no memory for option list.");
690 for (q
= p
; q
; q
= q
-> cdr
)
691 (*list
) [ix
++] = (u_int32_t
)(long)q
-> car
;
702 /* interface-declaration :==
703 INTERFACE string LBRACE client-declarations RBRACE */
705 void parse_interface_declaration (cfile
, outer_config
, name
)
707 struct client_config
*outer_config
;
712 struct client_state
*client
, **cp
;
713 struct interface_info
*ip
= (struct interface_info
*)0;
715 token
= next_token (&val
, (unsigned *)0, cfile
);
716 if (token
!= STRING
) {
717 parse_warn (cfile
, "expecting interface name (in quotes).");
718 skip_to_semi (cfile
);
722 if (!interface_or_dummy (&ip
, val
))
723 log_fatal ("Can't allocate interface %s.", val
);
725 /* If we were given a name, this is a pseudo-interface. */
727 make_client_state (&client
);
728 client
-> name
= name
;
729 client
-> interface
= ip
;
730 for (cp
= &ip
-> client
; *cp
; cp
= &((*cp
) -> next
))
735 make_client_state (&ip
-> client
);
736 ip
-> client
-> interface
= ip
;
738 client
= ip
-> client
;
741 if (!client
-> config
)
742 make_client_config (client
, outer_config
);
744 ip
-> flags
&= ~INTERFACE_AUTOMATIC
;
745 interfaces_requested
= 1;
747 token
= next_token (&val
, (unsigned *)0, cfile
);
748 if (token
!= LBRACE
) {
749 parse_warn (cfile
, "expecting left brace.");
750 skip_to_semi (cfile
);
755 token
= peek_token (&val
, (unsigned *)0, cfile
);
756 if (token
== END_OF_FILE
) {
758 "unterminated interface declaration.");
763 parse_client_statement (cfile
, ip
, client
-> config
);
765 token
= next_token (&val
, (unsigned *)0, cfile
);
768 int interface_or_dummy (struct interface_info
**pi
, const char *name
)
770 struct interface_info
*i
;
771 struct interface_info
*ip
= (struct interface_info
*)0;
774 status
= ISC_R_FAILURE
; /* XXXGCC -Wuninitialized */
776 /* Find the interface (if any) that matches the name. */
777 for (i
= interfaces
; i
; i
= i
-> next
) {
778 if (!strcmp (i
-> name
, name
)) {
779 interface_reference (&ip
, i
, MDL
);
784 /* If it's not a real interface, see if it's on the dummy list. */
786 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
787 if (!strcmp (ip
-> name
, name
)) {
788 interface_reference (&ip
, i
, MDL
);
794 /* If we didn't find an interface, make a dummy interface as
797 if ((status
= interface_allocate (&ip
, MDL
)) != ISC_R_SUCCESS
)
798 log_fatal ("Can't record interface %s: %s",
799 name
, isc_result_totext (status
));
800 strcpy (ip
-> name
, name
);
801 if (dummy_interfaces
) {
802 interface_reference (&ip
-> next
,
803 dummy_interfaces
, MDL
);
804 interface_dereference (&dummy_interfaces
, MDL
);
806 interface_reference (&dummy_interfaces
, ip
, MDL
);
809 status
= interface_reference (pi
, ip
, MDL
);
811 status
= ISC_R_FAILURE
;
812 interface_dereference (&ip
, MDL
);
813 if (status
!= ISC_R_SUCCESS
)
818 void make_client_state (state
)
819 struct client_state
**state
;
821 *state
= ((struct client_state
*)dmalloc (sizeof **state
, MDL
));
823 log_fatal ("no memory for client state\n");
824 memset (*state
, 0, sizeof **state
);
827 void make_client_config (client
, config
)
828 struct client_state
*client
;
829 struct client_config
*config
;
831 client
-> config
= (((struct client_config
*)
832 dmalloc (sizeof (struct client_config
), MDL
)));
833 if (!client
-> config
)
834 log_fatal ("no memory for client config\n");
835 memcpy (client
-> config
, config
, sizeof *config
);
836 if (!clone_group (&client
-> config
-> on_receipt
,
837 config
-> on_receipt
, MDL
) ||
838 !clone_group (&client
-> config
-> on_transmission
,
839 config
-> on_transmission
, MDL
))
840 log_fatal ("no memory for client state groups.");
843 /* client-lease-statement :==
844 RBRACE client-lease-declarations LBRACE
846 client-lease-declarations :==
848 client-lease-declaration |
849 client-lease-declarations client-lease-declaration */
852 void parse_client_lease_statement (cfile
, is_static
)
856 struct client_lease
*lease
, *lp
, *pl
, *next
;
857 struct interface_info
*ip
= (struct interface_info
*)0;
860 struct client_state
*client
= (struct client_state
*)0;
862 token
= next_token (&val
, (unsigned *)0, cfile
);
863 if (token
!= LBRACE
) {
864 parse_warn (cfile
, "expecting left brace.");
865 skip_to_semi (cfile
);
869 lease
= ((struct client_lease
*)
870 dmalloc (sizeof (struct client_lease
), MDL
));
872 log_fatal ("no memory for lease.\n");
873 memset (lease
, 0, sizeof *lease
);
874 lease
-> is_static
= is_static
;
875 if (!option_state_allocate (&lease
-> options
, MDL
))
876 log_fatal ("no memory for lease options.\n");
879 token
= peek_token (&val
, (unsigned *)0, cfile
);
880 if (token
== END_OF_FILE
) {
881 parse_warn (cfile
, "unterminated lease declaration.");
886 parse_client_lease_declaration (cfile
, lease
, &ip
, &client
);
888 token
= next_token (&val
, (unsigned *)0, cfile
);
890 /* If the lease declaration didn't include an interface
891 declaration that we recognized, it's of no use to us. */
893 destroy_client_lease (lease
);
897 /* Make sure there's a client state structure... */
899 make_client_state (&ip
-> client
);
900 ip
-> client
-> interface
= ip
;
903 client
= ip
-> client
;
905 /* If this is an alias lease, it doesn't need to be sorted in. */
906 if (is_static
== 2) {
907 ip
-> client
-> alias
= lease
;
911 /* The new lease may supersede a lease that's not the
912 active lease but is still on the lease list, so scan the
913 lease list looking for a lease with the same address, and
914 if we find it, toss it. */
915 pl
= (struct client_lease
*)0;
916 for (lp
= client
-> leases
; lp
; lp
= next
) {
918 if (lp
-> address
.len
== lease
-> address
.len
&&
919 !memcmp (lp
-> address
.iabuf
, lease
-> address
.iabuf
,
920 lease
-> address
.len
)) {
921 /* If the lease we found is a static lease, and
922 this one expires earlier, discard this one. */
924 lp
->expiry
> lease
->expiry
) {
925 destroy_client_lease(lease
);
931 client
-> leases
= next
;
932 destroy_client_lease (lp
);
938 /* If this is a preloaded lease, just put it on the list of recorded
939 leases - don't make it the active lease. */
941 lease
-> next
= client
-> leases
;
942 client
-> leases
= lease
;
946 /* The last lease in the lease file on a particular interface is
947 the active lease for that interface. Of course, we don't know
948 what the last lease in the file is until we've parsed the whole
949 file, so at this point, we assume that the lease we just parsed
950 is the active lease for its interface. If there's already
951 an active lease for the interface, and this lease is for the same
952 ip address, then we just toss the old active lease and replace
953 it with this one. If this lease is for a different address,
954 then if the old active lease has expired, we dump it; if not,
955 we put it on the list of leases for this interface which are
956 still valid but no longer active. */
957 if (client
-> active
) {
958 if (client
-> active
-> expiry
< cur_time
)
959 destroy_client_lease (client
-> active
);
960 else if (client
-> active
-> address
.len
==
961 lease
-> address
.len
&&
962 !memcmp (client
-> active
-> address
.iabuf
,
963 lease
-> address
.iabuf
,
964 lease
-> address
.len
))
965 destroy_client_lease (client
-> active
);
967 client
-> active
-> next
= client
-> leases
;
968 client
-> leases
= client
-> active
;
971 client
-> active
= lease
;
976 /* client-lease-declaration :==
979 FIXED_ADDR ip_address |
988 void parse_client_lease_declaration (cfile
, lease
, ipp
, clientp
)
990 struct client_lease
*lease
;
991 struct interface_info
**ipp
;
992 struct client_state
**clientp
;
996 struct interface_info
*ip
;
997 struct option_cache
*oc
;
998 struct client_state
*client
= (struct client_state
*)0;
1000 switch (next_token (&val
, (unsigned *)0, cfile
)) {
1001 #if !defined (SMALL)
1003 token
= next_token (&val
, (unsigned *)0, cfile
);
1004 if (token
!= STRING
&& !is_identifier (token
)) {
1005 parse_warn (cfile
, "expecting key name.");
1006 skip_to_semi (cfile
);
1009 if (omapi_auth_key_lookup_name (&lease
-> key
, val
) !=
1011 parse_warn (cfile
, "unknown key %s", val
);
1016 lease
-> is_bootp
= 1;
1020 token
= next_token (&val
, (unsigned *)0, cfile
);
1021 if (token
!= STRING
) {
1023 "expecting interface name (in quotes).");
1024 skip_to_semi (cfile
);
1027 interface_or_dummy (ipp
, val
);
1031 token
= next_token (&val
, (unsigned *)0, cfile
);
1034 parse_warn (cfile
, "state name precedes interface.");
1037 for (client
= ip
-> client
; client
; client
= client
-> next
)
1038 if (client
-> name
&& !strcmp (client
-> name
, val
))
1042 "lease specified for unknown pseudo.");
1047 if (!parse_ip_addr (cfile
, &lease
-> address
))
1052 parse_string_list (cfile
, &lease
-> medium
, 0);
1056 parse_string (cfile
, &lease
-> filename
, (unsigned *)0);
1060 parse_string (cfile
, &lease
-> server_name
, (unsigned *)0);
1064 lease
-> renewal
= parse_date (cfile
);
1068 lease
-> rebind
= parse_date (cfile
);
1072 lease
-> expiry
= parse_date (cfile
);
1076 oc
= (struct option_cache
*)0;
1077 if (parse_option_decl (&oc
, cfile
)) {
1078 save_option (oc
-> option
-> universe
,
1079 lease
-> options
, oc
);
1080 option_cache_dereference (&oc
, MDL
);
1085 parse_warn (cfile
, "expecting lease declaration.");
1086 skip_to_semi (cfile
);
1089 token
= next_token (&val
, (unsigned *)0, cfile
);
1090 if (token
!= SEMI
) {
1091 parse_warn (cfile
, "expecting semicolon.");
1092 skip_to_semi (cfile
);
1096 void parse_string_list (cfile
, lp
, multiple
)
1097 struct parse
*cfile
;
1098 struct string_list
**lp
;
1103 struct string_list
*cur
, *tmp
;
1105 /* Find the last medium in the media list. */
1107 for (cur
= *lp
; cur
-> next
; cur
= cur
-> next
)
1110 cur
= (struct string_list
*)0;
1114 token
= next_token (&val
, (unsigned *)0, cfile
);
1115 if (token
!= STRING
) {
1116 parse_warn (cfile
, "Expecting media options.");
1117 skip_to_semi (cfile
);
1121 tmp
= ((struct string_list
*)
1122 dmalloc (strlen (val
) + sizeof (struct string_list
),
1125 log_fatal ("no memory for string list entry.");
1127 strcpy (tmp
-> string
, val
);
1128 tmp
-> next
= (struct string_list
*)0;
1130 /* Store this medium at the end of the media list. */
1137 token
= next_token (&val
, (unsigned *)0, cfile
);
1138 } while (multiple
&& token
== COMMA
);
1140 if (token
!= SEMI
) {
1141 parse_warn (cfile
, "expecting semicolon.");
1142 skip_to_semi (cfile
);
1146 void parse_reject_statement (cfile
, config
)
1147 struct parse
*cfile
;
1148 struct client_config
*config
;
1153 struct iaddrlist
*list
;
1156 if (!parse_ip_addr (cfile
, &addr
)) {
1157 parse_warn (cfile
, "expecting IP address.");
1158 skip_to_semi (cfile
);
1162 list
= (struct iaddrlist
*)dmalloc (sizeof (struct iaddrlist
),
1165 log_fatal ("no memory for reject list!");
1167 list
-> addr
= addr
;
1168 list
-> next
= config
-> reject_list
;
1169 config
-> reject_list
= list
;
1171 token
= next_token (&val
, (unsigned *)0, cfile
);
1172 } while (token
== COMMA
);
1174 if (token
!= SEMI
) {
1175 parse_warn (cfile
, "expecting semicolon.");
1176 skip_to_semi (cfile
);
1180 /* allow-deny-keyword :== BOOTP
1183 | UNKNOWN_CLIENTS */
1185 int parse_allow_deny (oc
, cfile
, flag
)
1186 struct option_cache
**oc
;
1187 struct parse
*cfile
;
1191 parse_warn (cfile
, "allow/deny/ignore not permitted here.");
1192 skip_to_semi (cfile
);