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$ 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 client_state
*state
;
66 struct interface_info
*ip
;
69 /* Set up the initial dhcp option universe. */
70 initialize_common_option_spaces ();
72 /* Initialize the top level client configuration. */
73 memset (&top_level_config
, 0, sizeof top_level_config
);
75 /* Set some defaults... */
76 top_level_config
.timeout
= 60;
77 top_level_config
.select_interval
= 0;
78 top_level_config
.reboot_timeout
= 10;
79 top_level_config
.retry_interval
= 300;
80 top_level_config
.backoff_cutoff
= 15;
81 top_level_config
.initial_interval
= 3;
82 top_level_config
.bootp_policy
= P_ACCEPT
;
83 top_level_config
.script_name
= path_dhclient_script
;
84 top_level_config
.requested_options
= default_requested_options
;
85 top_level_config
.omapi_port
= -1;
86 top_level_config
.do_forward_update
= 1;
88 group_allocate (&top_level_config
.on_receipt
, MDL
);
89 if (!top_level_config
.on_receipt
)
90 log_fatal ("no memory for top-level on_receipt group");
92 group_allocate (&top_level_config
.on_transmission
, MDL
);
93 if (!top_level_config
.on_transmission
)
94 log_fatal ("no memory for top-level on_transmission group");
96 status
= read_client_conf_file (path_dhclient_conf
,
97 (struct interface_info
*)0,
99 if (status
!= ISC_R_SUCCESS
) {
102 /* Set up the standard name service updater routine. */
103 parse
= (struct parse
*)0;
104 status
= new_parse (&parse
, -1, default_client_config
,
105 (sizeof default_client_config
) - 1,
106 "default client configuration", 0);
107 if (status
!= ISC_R_SUCCESS
)
108 log_fatal ("can't begin default client config!");
111 token
= peek_token (&val
, (unsigned *)0, cfile
);
112 if (token
== END_OF_FILE
)
114 parse_client_statement (cfile
,
115 (struct interface_info
*)0,
122 /* Set up state and config structures for clients that don't
123 have per-interface configuration statements. */
124 config
= (struct client_config
*)0;
125 for (ip
= interfaces
; ip
; ip
= ip
-> next
) {
127 ip
-> client
= (struct client_state
*)
128 dmalloc (sizeof (struct client_state
), MDL
);
130 log_fatal ("no memory for client state.");
131 memset (ip
-> client
, 0, sizeof *(ip
-> client
));
132 ip
-> client
-> interface
= ip
;
135 if (!ip
-> client
-> config
) {
137 config
= (struct client_config
*)
138 dmalloc (sizeof (struct client_config
),
141 log_fatal ("no memory for client config.");
142 memcpy (config
, &top_level_config
,
143 sizeof top_level_config
);
145 ip
-> client
-> config
= config
;
151 int read_client_conf_file (const char *name
, struct interface_info
*ip
,
152 struct client_config
*client
)
160 if ((file
= open (name
, O_RDONLY
)) < 0)
161 return uerr2isc (errno
);
163 cfile
= (struct parse
*)0;
164 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_conf
, 0);
167 token
= peek_token (&val
, (unsigned *)0, cfile
);
168 if (token
== END_OF_FILE
)
170 parse_client_statement (cfile
, ip
, client
);
172 token
= next_token (&val
, (unsigned *)0, cfile
);
173 status
= (cfile
-> warnings_occurred
182 /* lease-file :== client-lease-statements END_OF_FILE
183 client-lease-statements :== <nil>
184 | client-lease-statements LEASE client-lease-statement */
186 void read_client_leases ()
193 /* Open the lease file. If we can't open it, just return -
194 we can safely trust the server to remember our state. */
195 if ((file
= open (path_dhclient_db
, O_RDONLY
)) < 0)
197 cfile
= (struct parse
*)0;
198 new_parse (&cfile
, file
, (char *)0, 0, path_dhclient_db
, 0);
201 token
= next_token (&val
, (unsigned *)0, cfile
);
202 if (token
== END_OF_FILE
)
204 if (token
!= LEASE
) {
205 log_error ("Corrupt lease file - possible data loss!");
206 skip_to_semi (cfile
);
209 parse_client_lease_statement (cfile
, 0);
217 /* client-declaration :==
219 DEFAULT option-decl |
220 SUPERSEDE option-decl |
221 PREPEND option-decl |
223 hardware-declaration |
224 REQUEST option-list |
225 REQUIRE option-list |
229 SELECT_TIMEOUT number |
231 VENDOR_SPACE string |
232 interface-declaration |
233 LEASE client-lease-statement |
234 ALIAS client-lease-statement |
235 KEY key-definition */
237 void parse_client_statement (cfile
, ip
, config
)
239 struct interface_info
*ip
;
240 struct client_config
*config
;
244 struct option
*option
;
245 struct executable_statement
*stmt
, **p
;
246 enum statement_op op
;
249 struct data_string key_id
;
255 switch (peek_token (&val
, (unsigned *)0, cfile
)) {
257 next_token (&val
, (unsigned *)0, cfile
);
258 token
= next_token (&val
, (unsigned *)0, cfile
);
259 if (token
!= STRING
) {
260 parse_warn (cfile
, "filename string expected.");
261 skip_to_semi (cfile
);
263 status
= read_client_conf_file (val
, ip
, config
);
264 if (status
!= ISC_R_SUCCESS
)
265 parse_warn (cfile
, "%s: bad parse.", val
);
271 next_token (&val
, (unsigned *)0, cfile
);
273 /* This may seem arbitrary, but there's a reason for
274 doing it: the authentication key database is not
275 scoped. If we allow the user to declare a key other
276 than in the outer scope, the user is very likely to
277 believe that the key will only be used in that
278 scope. If the user only wants the key to be used on
279 one interface, because it's known that the other
280 interface may be connected to an insecure net and
281 the secret key is considered sensitive, we don't
282 want to lull them into believing they've gotten
283 their way. This is a bit contrived, but people
284 tend not to be entirely rational about security. */
285 parse_warn (cfile
, "key definition not allowed here.");
286 skip_to_semi (cfile
);
292 /* REQUIRE can either start a policy statement or a
293 comma-seperated list of names of required options. */
295 next_token (&val
, (unsigned *)0, cfile
);
296 token
= peek_token (&val
, (unsigned *)0, cfile
);
297 if (token
== AUTHENTICATION
) {
301 parse_option_list (cfile
, &config
-> required_options
);
305 next_token (&val
, (unsigned *)0, cfile
);
310 next_token (&val
, (unsigned *)0, cfile
);
315 next_token (&val
, (unsigned *)0, cfile
);
320 next_token (&val
, (unsigned *)0, cfile
);
325 token
= next_token (&val
, (unsigned *)0, cfile
);
326 if (token
== AUTHENTICATION
) {
327 if (policy
!= P_PREFER
&&
328 policy
!= P_REQUIRE
&&
331 "invalid authentication policy.");
332 skip_to_semi (cfile
);
335 config
-> auth_policy
= policy
;
336 } else if (token
!= TOKEN_BOOTP
) {
337 if (policy
!= P_PREFER
&&
338 policy
!= P_IGNORE
&&
339 policy
!= P_ACCEPT
) {
340 parse_warn (cfile
, "invalid bootp policy.");
341 skip_to_semi (cfile
);
344 config
-> bootp_policy
= policy
;
346 parse_warn (cfile
, "expecting a policy type.");
347 skip_to_semi (cfile
);
353 token
= next_token (&val
, (unsigned *)0, cfile
);
355 token
= peek_token (&val
, (unsigned *)0, cfile
);
356 if (token
== SPACE
) {
359 "option space definitions %s",
360 " may not be scoped.");
361 skip_to_semi (cfile
);
364 parse_option_space_decl (cfile
);
368 option
= parse_option_name (cfile
, 1, &known
);
372 token
= next_token (&val
, (unsigned *)0, cfile
);
374 parse_warn (cfile
, "expecting \"code\" keyword.");
375 skip_to_semi (cfile
);
376 free_option (option
, MDL
);
381 "option definitions may only appear in %s",
382 "the outermost scope.");
383 skip_to_semi (cfile
);
384 free_option (option
, MDL
);
387 if (!parse_option_code_definition (cfile
, option
))
388 free_option (option
, MDL
);
392 token
= next_token (&val
, (unsigned *)0, cfile
);
393 parse_string_list (cfile
, &config
-> media
, 1);
397 token
= next_token (&val
, (unsigned *)0, cfile
);
399 parse_hardware_param (cfile
, &ip
-> hw_address
);
401 parse_warn (cfile
, "hardware address parameter %s",
402 "not allowed here.");
403 skip_to_semi (cfile
);
408 token
= next_token (&val
, (unsigned *)0, cfile
);
409 if (config
-> requested_options
== default_requested_options
)
410 config
-> requested_options
= (u_int32_t
*)0;
411 parse_option_list (cfile
, &config
-> requested_options
);
415 token
= next_token (&val
, (unsigned *)0, cfile
);
416 parse_lease_time (cfile
, &config
-> timeout
);
420 token
= next_token (&val
, (unsigned *)0, cfile
);
421 parse_lease_time (cfile
, &config
-> retry_interval
);
425 token
= next_token (&val
, (unsigned *)0, cfile
);
426 parse_lease_time (cfile
, &config
-> select_interval
);
430 token
= next_token (&val
, (unsigned *)0, cfile
);
431 token
= next_token (&val
, (unsigned *)0, cfile
);
434 "unexpected omapi subtype: %s", val
);
435 skip_to_semi (cfile
);
438 token
= next_token (&val
, (unsigned *)0, cfile
);
439 if (token
!= NUMBER
) {
440 parse_warn (cfile
, "invalid port number: `%s'", val
);
441 skip_to_semi (cfile
);
445 if (tmp
< 0 || tmp
> 65535)
446 parse_warn (cfile
, "invalid omapi port %d.", tmp
);
447 else if (config
!= &top_level_config
)
449 "omapi port only works at top level.");
451 config
-> omapi_port
= tmp
;
455 case DO_FORWARD_UPDATE
:
456 token
= next_token (&val
, (unsigned *)0, cfile
);
457 token
= next_token (&val
, (unsigned *)0, cfile
);
458 if (!strcasecmp (val
, "on") ||
459 !strcasecmp (val
, "true"))
460 config
-> do_forward_update
= 1;
461 else if (!strcasecmp (val
, "off") ||
462 !strcasecmp (val
, "false"))
463 config
-> do_forward_update
= 0;
465 parse_warn (cfile
, "expecting boolean value.");
466 skip_to_semi (cfile
);
473 token
= next_token (&val
, (unsigned *)0, cfile
);
474 parse_lease_time (cfile
, &config
-> reboot_timeout
);
478 token
= next_token (&val
, (unsigned *)0, cfile
);
479 parse_lease_time (cfile
, &config
-> backoff_cutoff
);
482 case INITIAL_INTERVAL
:
483 token
= next_token (&val
, (unsigned *)0, cfile
);
484 parse_lease_time (cfile
, &config
-> initial_interval
);
488 token
= next_token (&val
, (unsigned *)0, cfile
);
489 parse_string (cfile
, &config
-> script_name
, (unsigned *)0);
493 token
= next_token (&val
, (unsigned *)0, cfile
);
494 token
= next_token (&val
, (unsigned *)0, cfile
);
495 if (token
!= OPTION
) {
496 parse_warn (cfile
, "expecting 'vendor option space'");
497 skip_to_semi (cfile
);
500 token
= next_token (&val
, (unsigned *)0, cfile
);
501 if (token
!= SPACE
) {
502 parse_warn (cfile
, "expecting 'vendor option space'");
503 skip_to_semi (cfile
);
506 token
= next_token (&val
, (unsigned *)0, cfile
);
507 if (!is_identifier (token
)) {
508 parse_warn (cfile
, "expecting an identifier.");
509 skip_to_semi (cfile
);
512 config
-> vendor_space_name
= dmalloc (strlen (val
) + 1, MDL
);
513 if (!config
-> vendor_space_name
)
514 log_fatal ("no memory for vendor option space name.");
515 strcpy (config
-> vendor_space_name
, val
);
516 for (i
= 0; i
< universe_count
; i
++)
517 if (!strcmp (universes
[i
] -> name
,
518 config
-> vendor_space_name
))
520 if (i
== universe_count
) {
521 log_error ("vendor option space %s not found.",
522 config
-> vendor_space_name
);
528 token
= next_token (&val
, (unsigned *)0, cfile
);
530 parse_warn (cfile
, "nested interface declaration.");
531 parse_interface_declaration (cfile
, config
, (char *)0);
535 token
= next_token (&val
, (unsigned *)0, cfile
);
536 token
= next_token (&val
, (unsigned *)0, cfile
);
537 name
= dmalloc (strlen (val
) + 1, MDL
);
539 log_fatal ("no memory for pseudo interface name");
541 parse_interface_declaration (cfile
, config
, name
);
545 token
= next_token (&val
, (unsigned *)0, cfile
);
546 parse_client_lease_statement (cfile
, 1);
550 token
= next_token (&val
, (unsigned *)0, cfile
);
551 parse_client_lease_statement (cfile
, 2);
555 token
= next_token (&val
, (unsigned *)0, cfile
);
556 parse_reject_statement (cfile
, config
);
561 stmt
= (struct executable_statement
*)0;
562 if (!parse_executable_statement (&stmt
,
563 cfile
, &lose
, context_any
)) {
565 parse_warn (cfile
, "expecting a statement.");
566 skip_to_semi (cfile
);
569 struct executable_statement
**eptr
, *sptr
;
571 (stmt
-> op
== send_option_statement
||
572 (stmt
-> op
== on_statement
&&
573 (stmt
-> data
.on
.evtypes
& ON_TRANSMISSION
)))) {
574 eptr
= &config
-> on_transmission
-> statements
;
575 if (stmt
-> op
== on_statement
) {
576 sptr
= (struct executable_statement
*)0;
577 executable_statement_reference
579 stmt
-> data
.on
.statements
, MDL
);
580 executable_statement_dereference (&stmt
,
582 executable_statement_reference (&stmt
,
585 executable_statement_dereference (&sptr
,
589 eptr
= &config
-> on_receipt
-> statements
;
592 for (; *eptr
; eptr
= &(*eptr
) -> next
)
594 executable_statement_reference (eptr
,
604 /* option-list :== option_name |
605 option_list COMMA option_name */
607 void parse_option_list (cfile
, list
)
614 pair p
= (pair
)0, q
= (pair
)0, r
;
615 struct option
*option
;
619 token
= peek_token (&val
, (unsigned *)0, cfile
);
621 token
= next_token (&val
, (unsigned *)0, cfile
);
624 if (!is_identifier (token
)) {
625 parse_warn (cfile
, "%s: expected option name.", val
);
626 token
= next_token (&val
, (unsigned *)0, cfile
);
627 skip_to_semi (cfile
);
630 option
= parse_option_name (cfile
, 0, NULL
);
632 parse_warn (cfile
, "%s: expected option name.", val
);
635 if (option
-> universe
!= &dhcp_universe
) {
637 "%s.%s: Only global options allowed.",
638 option
-> universe
-> name
, option
->name
);
639 skip_to_semi (cfile
);
644 log_fatal ("can't allocate pair for option code.");
645 r
-> car
= (caddr_t
)(long)option
-> code
;
653 token
= next_token (&val
, (unsigned *)0, cfile
);
654 } while (token
== COMMA
);
656 parse_warn (cfile
, "expecting semicolon.");
657 skip_to_semi (cfile
);
660 /* XXX we can't free the list here, because we may have copied
661 XXX it from an outer config state. */
662 *list
= (u_int32_t
*)0;
664 *list
= dmalloc ((ix
+ 1) * sizeof **list
, MDL
);
666 log_error ("no memory for option list.");
669 for (q
= p
; q
; q
= q
-> cdr
)
670 (*list
) [ix
++] = (u_int32_t
)(long)q
-> car
;
681 /* interface-declaration :==
682 INTERFACE string LBRACE client-declarations RBRACE */
684 void parse_interface_declaration (cfile
, outer_config
, name
)
686 struct client_config
*outer_config
;
691 struct client_state
*client
, **cp
;
692 struct interface_info
*ip
= (struct interface_info
*)0;
694 token
= next_token (&val
, (unsigned *)0, cfile
);
695 if (token
!= STRING
) {
696 parse_warn (cfile
, "expecting interface name (in quotes).");
697 skip_to_semi (cfile
);
701 if (!interface_or_dummy (&ip
, val
))
702 log_fatal ("Can't allocate interface %s.", val
);
704 /* If we were given a name, this is a pseudo-interface. */
706 make_client_state (&client
);
707 client
-> name
= name
;
708 client
-> interface
= ip
;
709 for (cp
= &ip
-> client
; *cp
; cp
= &((*cp
) -> next
))
714 make_client_state (&ip
-> client
);
715 ip
-> client
-> interface
= ip
;
717 client
= ip
-> client
;
720 if (!client
-> config
)
721 make_client_config (client
, outer_config
);
723 ip
-> flags
&= ~INTERFACE_AUTOMATIC
;
724 interfaces_requested
= 1;
726 token
= next_token (&val
, (unsigned *)0, cfile
);
727 if (token
!= LBRACE
) {
728 parse_warn (cfile
, "expecting left brace.");
729 skip_to_semi (cfile
);
734 token
= peek_token (&val
, (unsigned *)0, cfile
);
735 if (token
== END_OF_FILE
) {
737 "unterminated interface declaration.");
742 parse_client_statement (cfile
, ip
, client
-> config
);
744 token
= next_token (&val
, (unsigned *)0, cfile
);
747 int interface_or_dummy (struct interface_info
**pi
, const char *name
)
749 struct interface_info
*i
;
750 struct interface_info
*ip
= (struct interface_info
*)0;
753 /* Find the interface (if any) that matches the name. */
754 for (i
= interfaces
; i
; i
= i
-> next
) {
755 if (!strcmp (i
-> name
, name
)) {
756 interface_reference (&ip
, i
, MDL
);
761 /* If it's not a real interface, see if it's on the dummy list. */
763 for (ip
= dummy_interfaces
; ip
; ip
= ip
-> next
) {
764 if (!strcmp (ip
-> name
, name
)) {
765 interface_reference (&ip
, i
, MDL
);
771 /* If we didn't find an interface, make a dummy interface as
774 if ((status
= interface_allocate (&ip
, MDL
)) != ISC_R_SUCCESS
)
775 log_fatal ("Can't record interface %s: %s",
776 name
, isc_result_totext (status
));
777 strcpy (ip
-> name
, name
);
778 if (dummy_interfaces
) {
779 interface_reference (&ip
-> next
,
780 dummy_interfaces
, MDL
);
781 interface_dereference (&dummy_interfaces
, MDL
);
783 interface_reference (&dummy_interfaces
, ip
, MDL
);
786 status
= interface_reference (pi
, ip
, MDL
);
788 status
= ISC_R_FAILURE
;
789 interface_dereference (&ip
, MDL
);
790 if (status
!= ISC_R_SUCCESS
)
795 void make_client_state (state
)
796 struct client_state
**state
;
798 *state
= ((struct client_state
*)dmalloc (sizeof **state
, MDL
));
800 log_fatal ("no memory for client state\n");
801 memset (*state
, 0, sizeof **state
);
804 void make_client_config (client
, config
)
805 struct client_state
*client
;
806 struct client_config
*config
;
808 client
-> config
= (((struct client_config
*)
809 dmalloc (sizeof (struct client_config
), MDL
)));
810 if (!client
-> config
)
811 log_fatal ("no memory for client config\n");
812 memcpy (client
-> config
, config
, sizeof *config
);
813 if (!clone_group (&client
-> config
-> on_receipt
,
814 config
-> on_receipt
, MDL
) ||
815 !clone_group (&client
-> config
-> on_transmission
,
816 config
-> on_transmission
, MDL
))
817 log_fatal ("no memory for client state groups.");
820 /* client-lease-statement :==
821 RBRACE client-lease-declarations LBRACE
823 client-lease-declarations :==
825 client-lease-declaration |
826 client-lease-declarations client-lease-declaration */
829 void parse_client_lease_statement (cfile
, is_static
)
833 struct client_lease
*lease
, *lp
, *pl
, *next
;
834 struct interface_info
*ip
= (struct interface_info
*)0;
837 struct client_state
*client
= (struct client_state
*)0;
839 token
= next_token (&val
, (unsigned *)0, cfile
);
840 if (token
!= LBRACE
) {
841 parse_warn (cfile
, "expecting left brace.");
842 skip_to_semi (cfile
);
846 lease
= ((struct client_lease
*)
847 dmalloc (sizeof (struct client_lease
), MDL
));
849 log_fatal ("no memory for lease.\n");
850 memset (lease
, 0, sizeof *lease
);
851 lease
-> is_static
= is_static
;
852 if (!option_state_allocate (&lease
-> options
, MDL
))
853 log_fatal ("no memory for lease options.\n");
856 token
= peek_token (&val
, (unsigned *)0, cfile
);
857 if (token
== END_OF_FILE
) {
858 parse_warn (cfile
, "unterminated lease declaration.");
863 parse_client_lease_declaration (cfile
, lease
, &ip
, &client
);
865 token
= next_token (&val
, (unsigned *)0, cfile
);
867 /* If the lease declaration didn't include an interface
868 declaration that we recognized, it's of no use to us. */
870 destroy_client_lease (lease
);
874 /* Make sure there's a client state structure... */
876 make_client_state (&ip
-> client
);
877 ip
-> client
-> interface
= ip
;
880 client
= ip
-> client
;
882 /* If this is an alias lease, it doesn't need to be sorted in. */
883 if (is_static
== 2) {
884 ip
-> client
-> alias
= lease
;
888 /* The new lease may supersede a lease that's not the
889 active lease but is still on the lease list, so scan the
890 lease list looking for a lease with the same address, and
891 if we find it, toss it. */
892 pl
= (struct client_lease
*)0;
893 for (lp
= client
-> leases
; lp
; lp
= next
) {
895 if (lp
-> address
.len
== lease
-> address
.len
&&
896 !memcmp (lp
-> address
.iabuf
, lease
-> address
.iabuf
,
897 lease
-> address
.len
)) {
901 client
-> leases
= next
;
902 destroy_client_lease (lp
);
908 /* If this is a preloaded lease, just put it on the list of recorded
909 leases - don't make it the active lease. */
911 lease
-> next
= client
-> leases
;
912 client
-> leases
= lease
;
916 /* The last lease in the lease file on a particular interface is
917 the active lease for that interface. Of course, we don't know
918 what the last lease in the file is until we've parsed the whole
919 file, so at this point, we assume that the lease we just parsed
920 is the active lease for its interface. If there's already
921 an active lease for the interface, and this lease is for the same
922 ip address, then we just toss the old active lease and replace
923 it with this one. If this lease is for a different address,
924 then if the old active lease has expired, we dump it; if not,
925 we put it on the list of leases for this interface which are
926 still valid but no longer active. */
927 if (client
-> active
) {
928 if (client
-> active
-> expiry
< cur_time
)
929 destroy_client_lease (client
-> active
);
930 else if (client
-> active
-> address
.len
==
931 lease
-> address
.len
&&
932 !memcmp (client
-> active
-> address
.iabuf
,
933 lease
-> address
.iabuf
,
934 lease
-> address
.len
))
935 destroy_client_lease (client
-> active
);
937 client
-> active
-> next
= client
-> leases
;
938 client
-> leases
= client
-> active
;
941 client
-> active
= lease
;
946 /* client-lease-declaration :==
949 FIXED_ADDR ip_address |
958 void parse_client_lease_declaration (cfile
, lease
, ipp
, clientp
)
960 struct client_lease
*lease
;
961 struct interface_info
**ipp
;
962 struct client_state
**clientp
;
967 struct interface_info
*ip
;
968 struct option_cache
*oc
;
969 struct client_state
*client
= (struct client_state
*)0;
970 struct data_string key_id
;
972 switch (next_token (&val
, (unsigned *)0, cfile
)) {
974 token
= next_token (&val
, (unsigned *)0, cfile
);
975 if (token
!= STRING
&& !is_identifier (token
)) {
976 parse_warn (cfile
, "expecting key name.");
977 skip_to_semi (cfile
);
980 if (omapi_auth_key_lookup_name (&lease
-> key
, val
) !=
982 parse_warn (cfile
, "unknown key %s", val
);
986 lease
-> is_bootp
= 1;
990 token
= next_token (&val
, (unsigned *)0, cfile
);
991 if (token
!= STRING
) {
993 "expecting interface name (in quotes).");
994 skip_to_semi (cfile
);
997 interface_or_dummy (ipp
, val
);
1001 token
= next_token (&val
, (unsigned *)0, cfile
);
1004 parse_warn (cfile
, "state name precedes interface.");
1007 for (client
= ip
-> client
; client
; client
= client
-> next
)
1008 if (client
-> name
&& !strcmp (client
-> name
, val
))
1012 "lease specified for unknown pseudo.");
1017 if (!parse_ip_addr (cfile
, &lease
-> address
))
1022 parse_string_list (cfile
, &lease
-> medium
, 0);
1026 parse_string (cfile
, &lease
-> filename
, (unsigned *)0);
1030 parse_string (cfile
, &lease
-> server_name
, (unsigned *)0);
1034 lease
-> renewal
= parse_date (cfile
);
1038 lease
-> rebind
= parse_date (cfile
);
1042 lease
-> expiry
= parse_date (cfile
);
1046 oc
= (struct option_cache
*)0;
1047 if (parse_option_decl (&oc
, cfile
)) {
1048 save_option (oc
-> option
-> universe
,
1049 lease
-> options
, oc
);
1050 option_cache_dereference (&oc
, MDL
);
1055 parse_warn (cfile
, "expecting lease declaration.");
1056 skip_to_semi (cfile
);
1059 token
= next_token (&val
, (unsigned *)0, cfile
);
1060 if (token
!= SEMI
) {
1061 parse_warn (cfile
, "expecting semicolon.");
1062 skip_to_semi (cfile
);
1066 void parse_string_list (cfile
, lp
, multiple
)
1067 struct parse
*cfile
;
1068 struct string_list
**lp
;
1073 struct string_list
*cur
, *tmp
;
1075 /* Find the last medium in the media list. */
1077 for (cur
= *lp
; cur
-> next
; cur
= cur
-> next
)
1080 cur
= (struct string_list
*)0;
1084 token
= next_token (&val
, (unsigned *)0, cfile
);
1085 if (token
!= STRING
) {
1086 parse_warn (cfile
, "Expecting media options.");
1087 skip_to_semi (cfile
);
1091 tmp
= ((struct string_list
*)
1092 dmalloc (strlen (val
) + sizeof (struct string_list
),
1095 log_fatal ("no memory for string list entry.");
1097 strcpy (tmp
-> string
, val
);
1098 tmp
-> next
= (struct string_list
*)0;
1100 /* Store this medium at the end of the media list. */
1107 token
= next_token (&val
, (unsigned *)0, cfile
);
1108 } while (multiple
&& token
== COMMA
);
1110 if (token
!= SEMI
) {
1111 parse_warn (cfile
, "expecting semicolon.");
1112 skip_to_semi (cfile
);
1116 void parse_reject_statement (cfile
, config
)
1117 struct parse
*cfile
;
1118 struct client_config
*config
;
1123 struct iaddrlist
*list
;
1126 if (!parse_ip_addr (cfile
, &addr
)) {
1127 parse_warn (cfile
, "expecting IP address.");
1128 skip_to_semi (cfile
);
1132 list
= (struct iaddrlist
*)dmalloc (sizeof (struct iaddrlist
),
1135 log_fatal ("no memory for reject list!");
1137 list
-> addr
= addr
;
1138 list
-> next
= config
-> reject_list
;
1139 config
-> reject_list
= list
;
1141 token
= next_token (&val
, (unsigned *)0, cfile
);
1142 } while (token
== COMMA
);
1144 if (token
!= SEMI
) {
1145 parse_warn (cfile
, "expecting semicolon.");
1146 skip_to_semi (cfile
);
1150 /* allow-deny-keyword :== BOOTP
1153 | UNKNOWN_CLIENTS */
1155 int parse_allow_deny (oc
, cfile
, flag
)
1156 struct option_cache
**oc
;
1157 struct parse
*cfile
;
1160 enum dhcp_token token
;
1162 unsigned char rf
= flag
;
1163 struct expression
*data
= (struct expression
*)0;
1166 parse_warn (cfile
, "allow/deny/ignore not permitted here.");
1167 skip_to_semi (cfile
);