3 Parser for dhcpd config file... */
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id: confpars.c,v 1.159 2006/07/25 13:26:00 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
42 static TIME parsed_time
;
43 static unsigned char global_host_once
= 1;
46 trace_type_t
*trace_readconf_type
;
47 trace_type_t
*trace_readleases_type
;
49 void parse_trace_setup ()
51 trace_readconf_type
= trace_type_register ("readconf", (void *)0,
53 trace_conf_stop
, MDL
);
54 trace_readleases_type
= trace_type_register ("readleases", (void *)0,
56 trace_conf_stop
, MDL
);
60 /* conf-file :== parameters declarations END_OF_FILE
61 parameters :== <nil> | parameter | parameters parameter
62 declarations :== <nil> | declaration | declarations declaration */
64 isc_result_t
readconf ()
66 return read_conf_file (path_dhcpd_conf
, root_group
, ROOT_GROUP
, 0);
69 isc_result_t
read_conf_file (const char *filename
, struct group
*group
,
70 int group_type
, int leasep
)
83 ttype
= trace_readleases_type
;
85 ttype
= trace_readconf_type
;
87 /* If we're in playback, we need to snarf the contents of the
88 named file out of the playback file rather than trying to
90 if (trace_playback ()) {
93 status
= trace_get_file (ttype
, filename
, &tflen
, &dbuf
);
94 if (status
!= ISC_R_SUCCESS
)
98 /* What we get back is filename\0contents, where contents is
99 terminated just by the length. So we figure out the length
100 of the filename, and subtract that and the NUL from the
101 total length to get the length of the contents of the file.
102 We make fbuf a pointer to the contents of the file, and
103 leave dbuf as it is so we can free it later. */
104 tflen
= strlen (dbuf
);
105 ulen
= ulen
- tflen
- 1;
106 fbuf
= dbuf
+ tflen
+ 1;
111 if ((file
= open (filename
, O_RDONLY
)) < 0) {
113 log_error ("Can't open lease database %s: %m --",
115 log_error (" check for failed database %s!",
117 log_error ("Please read the dhcpd.leases manual%s",
119 log_fatal ("don't know what to do about this.");
121 log_fatal ("Can't open %s: %m", filename
);
125 cfile
= (struct parse
*)0;
126 #if defined (TRACING)
127 flen
= lseek (file
, (off_t
)0, SEEK_END
);
130 log_fatal ("Can't lseek on %s: %m", filename
);
132 if (lseek (file
, (off_t
)0, SEEK_SET
) < 0)
134 /* Can't handle files greater than 2^31-1. */
135 if (flen
> 0x7FFFFFFFUL
)
136 log_fatal ("%s: file is too long to buffer.", filename
);
139 /* Allocate a buffer that will be what's written to the tracefile,
140 and also will be what we parse from. */
141 tflen
= strlen (filename
);
142 dbuf
= dmalloc (ulen
+ tflen
+ 1, MDL
);
144 log_fatal ("No memory for %s (%d bytes)",
147 /* Copy the name into the beginning, nul-terminated. */
148 strcpy (dbuf
, filename
);
150 /* Load the file in after the NUL. */
151 fbuf
= dbuf
+ tflen
+ 1;
152 result
= read (file
, fbuf
, ulen
);
154 log_fatal ("Can't read in %s: %m", filename
);
156 log_fatal ("%s: short read of %d bytes instead of %d.",
157 filename
, ulen
, result
);
160 /* If we're recording, write out the filename and file contents. */
162 trace_write_packet (ttype
, ulen
+ tflen
+ 1, dbuf
, MDL
);
163 new_parse (&cfile
, -1, fbuf
, ulen
, filename
, 0); /* XXX */
165 new_parse (&cfile
, file
, (char *)0, 0, filename
, 0);
168 status
= lease_file_subparse (cfile
);
170 status
= conf_file_subparse (cfile
, group
, group_type
);
172 #if defined (TRACING)
178 #if defined (TRACING)
179 void trace_conf_input (trace_type_t
*ttype
, unsigned len
, char *data
)
184 struct parse
*cfile
= (struct parse
*)0;
185 static int postconf_initialized
;
186 static int leaseconf_initialized
;
188 /* Do what's done above, except that we don't have to read in the
189 data, because it's already been read for us. */
190 tflen
= strlen (data
);
191 flen
= len
- tflen
- 1;
192 fbuf
= data
+ tflen
+ 1;
194 /* If we're recording, write out the filename and file contents. */
196 trace_write_packet (ttype
, len
, data
, MDL
);
197 new_parse (&cfile
, -1, fbuf
, flen
, data
, 0);
198 if (ttype
== trace_readleases_type
)
199 lease_file_subparse (cfile
);
201 conf_file_subparse (cfile
, root_group
, ROOT_GROUP
);
204 /* Postconfiguration needs to be done after the config file
206 if (!postconf_initialized
&& ttype
== trace_readconf_type
) {
207 postconf_initialization (0);
208 postconf_initialized
= 1;
211 if (!leaseconf_initialized
&& ttype
== trace_readleases_type
) {
213 leaseconf_initialized
= 1;
218 void trace_conf_stop (trace_type_t
*ttype
) { }
221 /* conf-file :== parameters declarations END_OF_FILE
222 parameters :== <nil> | parameter | parameters parameter
223 declarations :== <nil> | declaration | declarations declaration */
225 isc_result_t
conf_file_subparse (struct parse
*cfile
, struct group
*group
,
229 enum dhcp_token token
;
234 token
= peek_token (&val
, (unsigned *)0, cfile
);
235 if (token
== END_OF_FILE
)
237 declaration
= parse_statement (cfile
, group
, group_type
,
238 (struct host_decl
*)0,
241 token
= next_token (&val
, (unsigned *)0, cfile
);
243 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
247 /* lease-file :== lease-declarations END_OF_FILE
248 lease-statments :== <nil>
250 | lease-declarations lease-declaration */
252 isc_result_t
lease_file_subparse (struct parse
*cfile
)
255 enum dhcp_token token
;
259 token
= next_token (&val
, (unsigned *)0, cfile
);
260 if (token
== END_OF_FILE
)
262 if (token
== LEASE
) {
263 struct lease
*lease
= (struct lease
*)0;
264 if (parse_lease_declaration (&lease
, cfile
)) {
266 lease_dereference (&lease
, MDL
);
269 "possibly corrupt lease file");
270 } else if (token
== CLASS
) {
271 parse_class_declaration(0, cfile
, root_group
,
273 } else if (token
== SUBCLASS
) {
274 parse_class_declaration(0, cfile
, root_group
,
275 CLASS_TYPE_SUBCLASS
);
276 } else if (token
== HOST
) {
277 parse_host_declaration (cfile
, root_group
);
278 } else if (token
== GROUP
) {
279 parse_group_declaration (cfile
, root_group
);
280 #if defined (FAILOVER_PROTOCOL)
281 } else if (token
== FAILOVER
) {
282 parse_failover_state_declaration
283 (cfile
, (dhcp_failover_state_t
*)0);
286 log_error ("Corrupt lease file - possible data loss!");
287 skip_to_semi (cfile
);
292 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
296 /* statement :== parameter | declaration
298 parameter :== DEFAULT_LEASE_TIME lease_time
299 | MAX_LEASE_TIME lease_time
300 | DYNAMIC_BOOTP_LEASE_CUTOFF date
301 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
302 | BOOT_UNKNOWN_CLIENTS boolean
303 | ONE_LEASE_PER_CLIENT boolean
304 | GET_LEASE_HOSTNAMES boolean
305 | USE_HOST_DECL_NAME boolean
306 | NEXT_SERVER ip-addr-or-hostname SEMI
308 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
309 | FILENAME string-parameter
310 | SERVER_NAME string-parameter
312 | fixed-address-parameter
313 | ALLOW allow-deny-keyword
314 | DENY allow-deny-keyword
315 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
319 declaration :== host-declaration
321 | shared-network-declaration
323 | VENDOR_CLASS class-declaration
324 | USER_CLASS class-declaration
325 | RANGE address-range-declaration */
327 int parse_statement (cfile
, group
, type
, host_decl
, declaration
)
331 struct host_decl
*host_decl
;
334 enum dhcp_token token
;
336 struct shared_network
*share
;
338 struct expression
*expr
;
339 struct data_string data
;
340 struct hardware hardware
;
341 struct executable_statement
*et
, *ep
;
342 struct option
*option
= NULL
;
343 struct option_cache
*cache
;
345 struct data_string key_id
;
350 token
= peek_token (&val
, (unsigned *)0, cfile
);
354 next_token (&val
, (unsigned *)0, cfile
);
355 token
= next_token (&val
, (unsigned *)0, cfile
);
356 if (token
!= STRING
) {
357 parse_warn (cfile
, "filename string expected.");
358 skip_to_semi (cfile
);
360 status
= read_conf_file (val
, group
, type
, 0);
361 if (status
!= ISC_R_SUCCESS
)
362 parse_warn (cfile
, "%s: bad parse.", val
);
368 next_token (&val
, (unsigned *)0, cfile
);
369 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
) {
370 if (global_host_once
&&
371 (type
== SUBNET_DECL
|| type
== SHARED_NET_DECL
)) {
372 global_host_once
= 0;
373 log_error("WARNING: Host declarations are "
374 "global. They are not limited to "
375 "the scope you declared them in.");
378 parse_host_declaration (cfile
, group
);
381 "host declarations not allowed here.");
382 skip_to_semi (cfile
);
387 next_token (&val
, (unsigned *)0, cfile
);
388 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
389 parse_group_declaration (cfile
, group
);
392 "group declarations not allowed here.");
393 skip_to_semi (cfile
);
398 next_token (&val
, (unsigned *)0, cfile
);
399 if (type
== SHARED_NET_DECL
||
401 type
== SUBNET_DECL
||
402 type
== CLASS_DECL
) {
403 parse_warn (cfile
, "shared-network parameters not %s.",
405 skip_to_semi (cfile
);
409 parse_shared_net_declaration (cfile
, group
);
413 next_token (&val
, (unsigned *)0, cfile
);
414 if (type
== HOST_DECL
|| type
== SUBNET_DECL
||
415 type
== CLASS_DECL
) {
417 "subnet declarations not allowed here.");
418 skip_to_semi (cfile
);
422 /* If we're in a subnet declaration, just do the parse. */
423 if (group
-> shared_network
) {
424 parse_subnet_declaration (cfile
,
425 group
-> shared_network
);
429 /* Otherwise, cons up a fake shared network structure
430 and populate it with the lone subnet... */
432 share
= (struct shared_network
*)0;
433 status
= shared_network_allocate (&share
, MDL
);
434 if (status
!= ISC_R_SUCCESS
)
435 log_fatal ("Can't allocate shared subnet: %s",
436 isc_result_totext (status
));
437 if (!clone_group (&share
-> group
, group
, MDL
))
438 log_fatal ("Can't allocate group for shared net");
439 shared_network_reference (&share
-> group
-> shared_network
,
442 parse_subnet_declaration (cfile
, share
);
444 /* share -> subnets is the subnet we just parsed. */
445 if (share
-> subnets
) {
446 interface_reference (&share
-> interface
,
447 share
-> subnets
-> interface
,
450 /* Make the shared network name from network number. */
451 n
= piaddrmask (share
-> subnets
-> net
,
452 share
-> subnets
-> netmask
, MDL
);
455 /* Copy the authoritative parameter from the subnet,
456 since there is no opportunity to declare it here. */
457 share
-> group
-> authoritative
=
458 share
-> subnets
-> group
-> authoritative
;
459 enter_shared_network (share
);
461 shared_network_dereference (&share
, MDL
);
465 next_token (&val
, (unsigned *)0, cfile
);
466 if (type
== CLASS_DECL
) {
468 "class declarations not allowed here.");
469 skip_to_semi (cfile
);
472 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_VENDOR
);
476 next_token (&val
, (unsigned *)0, cfile
);
477 if (type
== CLASS_DECL
) {
479 "class declarations not allowed here.");
480 skip_to_semi (cfile
);
483 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_USER
);
487 next_token (&val
, (unsigned *)0, cfile
);
488 if (type
== CLASS_DECL
) {
490 "class declarations not allowed here.");
491 skip_to_semi (cfile
);
494 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_CLASS
);
498 next_token (&val
, (unsigned *)0, cfile
);
499 if (type
== CLASS_DECL
) {
501 "class declarations not allowed here.");
502 skip_to_semi (cfile
);
505 parse_class_declaration(NULL
, cfile
, group
,
506 CLASS_TYPE_SUBCLASS
);
510 next_token (&val
, (unsigned *)0, cfile
);
511 memset (&hardware
, 0, sizeof hardware
);
512 if (host_decl
&& memcmp(&hardware
, &(host_decl
->interface
),
513 sizeof(hardware
)) != 0) {
514 parse_warn(cfile
, "Host %s hardware address already "
515 "configured.", host_decl
->name
);
519 parse_hardware_param (cfile
, &hardware
);
521 host_decl
-> interface
= hardware
;
523 parse_warn (cfile
, "hardware address parameter %s",
524 "not allowed here.");
528 next_token (&val
, (unsigned *)0, cfile
);
529 cache
= (struct option_cache
*)0;
530 if (parse_fixed_addr_param (&cache
, cfile
)) {
532 if (host_decl
-> fixed_addr
) {
533 option_cache_dereference (&cache
, MDL
);
535 "Only one fixed address%s",
536 " declaration per host.");
538 host_decl
-> fixed_addr
= cache
;
542 "fixed-address parameter not %s",
544 option_cache_dereference (&cache
, MDL
);
550 next_token (&val
, (unsigned *)0, cfile
);
551 if (type
!= SUBNET_DECL
&& type
!= SHARED_NET_DECL
) {
552 parse_warn (cfile
, "pool declared outside of network");
554 if (type
== POOL_DECL
) {
555 parse_warn (cfile
, "pool declared within pool.");
557 parse_pool_statement (cfile
, group
, type
);
561 next_token (&val
, (unsigned *)0, cfile
);
562 if (type
!= SUBNET_DECL
|| !group
-> subnet
) {
564 "range declaration not allowed here.");
565 skip_to_semi (cfile
);
568 parse_address_range (cfile
, group
, type
, (struct pool
*)0,
573 token
= next_token (&val
, (unsigned *)0, cfile
);
574 token
= next_token (&val
, (unsigned *)0, cfile
);
577 group
-> authoritative
= 0;
580 parse_warn (cfile
, "expecting assertion");
581 skip_to_semi (cfile
);
586 token
= next_token (&val
, (unsigned *)0, cfile
);
587 group
-> authoritative
= 1;
589 if (type
== HOST_DECL
)
590 parse_warn (cfile
, "authority makes no sense here.");
594 /* "server-identifier" is a special hack, equivalent to
595 "option dhcp-server-identifier". */
596 case SERVER_IDENTIFIER
:
597 code
= DHO_DHCP_SERVER_IDENTIFIER
;
598 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
600 log_fatal("Server identifier not in hash (%s:%d).",
602 token
= next_token (&val
, (unsigned *)0, cfile
);
606 token
= next_token (&val
, (unsigned *)0, cfile
);
607 token
= peek_token (&val
, (unsigned *)0, cfile
);
608 if (token
== SPACE
) {
609 if (type
!= ROOT_GROUP
) {
611 "option space definitions %s",
612 "may not be scoped.");
613 skip_to_semi (cfile
);
616 parse_option_space_decl (cfile
);
621 status
= parse_option_name(cfile
, 1, &known
, &option
);
622 if (status
== ISC_R_SUCCESS
) {
623 token
= peek_token (&val
, (unsigned *)0, cfile
);
625 if (type
!= ROOT_GROUP
) {
627 "option definitions%s",
628 " may not be scoped.");
629 skip_to_semi (cfile
);
630 option_dereference(&option
, MDL
);
633 next_token (&val
, (unsigned *)0, cfile
);
634 parse_option_code_definition(cfile
, option
);
635 option_dereference(&option
, MDL
);
639 /* If this wasn't an option code definition, don't
640 allow an unknown option. */
642 parse_warn (cfile
, "unknown option %s.%s",
643 option
-> universe
-> name
,
645 skip_to_semi (cfile
);
646 option_dereference(&option
, MDL
);
651 et
= (struct executable_statement
*)0;
652 if (!parse_option_statement
653 (&et
, cfile
, 1, option
,
654 supersede_option_statement
))
656 option_dereference(&option
, MDL
);
657 goto insert_statement
;
664 if (type
!= ROOT_GROUP
&& type
!= SHARED_NET_DECL
) {
665 parse_warn (cfile
, "failover peers may only be %s",
666 "defined in shared-network");
667 log_error ("declarations and the outer scope.");
668 skip_to_semi (cfile
);
671 token
= next_token (&val
, (unsigned *)0, cfile
);
672 #if defined (FAILOVER_PROTOCOL)
673 parse_failover_peer (cfile
, group
, type
);
675 parse_warn (cfile
, "No failover support.");
676 skip_to_semi (cfile
);
681 et
= (struct executable_statement
*)0;
683 if (!parse_executable_statement (&et
, cfile
, &lose
,
688 "expecting a declaration");
691 "expecting a parameter %s",
693 skip_to_semi (cfile
);
700 if (group
-> statements
) {
703 /* If this set of statements is only referenced
704 by this group, just add the current statement
705 to the end of the chain. */
706 for (ep
= group
-> statements
; ep
-> next
;
708 if (ep
-> refcnt
> 1) /* XXX */
711 executable_statement_reference (&ep
-> next
,
713 executable_statement_dereference (&et
, MDL
);
717 /* Otherwise, make a parent chain, and put the
718 current group statements first and the new
719 statement in the next pointer. */
720 ep
= (struct executable_statement
*)0;
721 if (!executable_statement_allocate (&ep
, MDL
))
722 log_fatal ("No memory for statements.");
723 ep
-> op
= statements_statement
;
724 executable_statement_reference (&ep
-> data
.statements
,
727 executable_statement_reference (&ep
-> next
, et
, MDL
);
728 executable_statement_dereference (&group
-> statements
,
730 executable_statement_reference (&group
-> statements
,
732 executable_statement_dereference (&ep
, MDL
);
734 executable_statement_reference (&group
-> statements
,
737 executable_statement_dereference (&et
, MDL
);
744 #if defined (FAILOVER_PROTOCOL)
745 void parse_failover_peer (cfile
, group
, type
)
750 enum dhcp_token token
;
752 dhcp_failover_state_t
*peer
;
757 unsigned hba_len
= sizeof hba
;
759 struct expression
*expr
;
761 dhcp_failover_config_t
*cp
;
763 token
= next_token (&val
, (unsigned *)0, cfile
);
765 parse_warn (cfile
, "expecting \"peer\"");
766 skip_to_semi (cfile
);
770 token
= next_token (&val
, (unsigned *)0, cfile
);
771 if (is_identifier (token
) || token
== STRING
) {
772 name
= dmalloc (strlen (val
) + 1, MDL
);
774 log_fatal ("no memory for peer name %s", name
);
777 parse_warn (cfile
, "expecting failover peer name.");
778 skip_to_semi (cfile
);
782 /* See if there's a peer declaration by this name. */
783 peer
= (dhcp_failover_state_t
*)0;
784 find_failover_peer (&peer
, name
, MDL
);
786 token
= next_token (&val
, (unsigned *)0, cfile
);
789 if (type
!= SHARED_NET_DECL
)
790 parse_warn (cfile
, "failover peer reference not %s",
791 "in shared-network declaration");
794 parse_warn (cfile
, "reference to unknown%s%s",
795 " failover peer ", name
);
798 dhcp_failover_state_reference
799 (&group
-> shared_network
-> failover_peer
,
802 dhcp_failover_state_dereference (&peer
, MDL
);
804 } else if (token
== STATE
) {
806 parse_warn (cfile
, "state declaration for unknown%s%s",
807 " failover peer ", name
);
810 parse_failover_state_declaration (cfile
, peer
);
811 dhcp_failover_state_dereference (&peer
, MDL
);
813 } else if (token
!= LBRACE
) {
814 parse_warn (cfile
, "expecting left brace");
815 skip_to_semi (cfile
);
818 /* Make sure this isn't a redeclaration. */
820 parse_warn (cfile
, "redeclaration of failover peer %s", name
);
821 skip_to_rbrace (cfile
, 1);
822 dhcp_failover_state_dereference (&peer
, MDL
);
826 status
= dhcp_failover_state_allocate (&peer
, MDL
);
827 if (status
!= ISC_R_SUCCESS
)
828 log_fatal ("Can't allocate failover peer %s: %s",
829 name
, isc_result_totext (status
));
837 token
= next_token (&val
, (unsigned *)0, cfile
);
843 peer
-> i_am
= primary
;
847 peer
-> i_am
= secondary
;
850 "secondary may not define %s",
851 "load balance settings.");
855 cp
= &peer
-> partner
;
859 expr
= (struct expression
*)0;
860 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
861 skip_to_rbrace (cfile
, 1);
862 dhcp_failover_state_dereference (&peer
, MDL
);
865 option_cache (&cp
-> address
,
866 (struct data_string
*)0, expr
,
867 (struct option
*)0, MDL
);
868 expression_dereference (&expr
, MDL
);
872 token
= next_token (&val
, (unsigned *)0, cfile
);
873 if (token
!= NUMBER
) {
874 parse_warn (cfile
, "expecting number");
875 skip_to_rbrace (cfile
, 1);
877 cp
-> port
= atoi (val
);
880 case MAX_LEASE_MISBALANCE
:
881 tp
= &peer
->max_lease_misbalance
;
884 case MAX_LEASE_OWNERSHIP
:
885 tp
= &peer
->max_lease_ownership
;
889 tp
= &peer
->max_balance
;
893 tp
= &peer
->min_balance
;
896 case MAX_RESPONSE_DELAY
:
897 tp
= &cp
-> max_response_delay
;
899 token
= next_token (&val
, (unsigned *)0, cfile
);
900 if (token
!= NUMBER
) {
901 parse_warn (cfile
, "expecting number.");
902 skip_to_rbrace (cfile
, 1);
903 dhcp_failover_state_dereference (&peer
, MDL
);
909 case MAX_UNACKED_UPDATES
:
910 tp
= &cp
-> max_flying_updates
;
919 if (peer
-> i_am
== secondary
)
921 "secondary may not define %s",
922 "load balance settings.");
923 if (!parse_numeric_aggregate (cfile
, hba
, &hba_len
,
925 skip_to_rbrace (cfile
, 1);
926 dhcp_failover_state_dereference (&peer
, MDL
);
931 "HBA must be exactly 32 bytes.");
936 peer
-> hba
= dmalloc (32, MDL
);
938 dfree (peer
-> name
, MDL
);
941 memcpy (peer
-> hba
, hba
, 32);
945 token
= next_token (&val
, (unsigned *)0, cfile
);
946 if (peer
-> i_am
== secondary
)
948 "secondary may not define %s",
949 "load balance settings.");
950 if (token
!= NUMBER
) {
951 parse_warn (cfile
, "expecting number");
953 skip_to_rbrace (cfile
, 1);
954 dhcp_failover_state_dereference (&peer
, MDL
);
959 parse_warn (cfile
, "split must be < 256");
961 memset (hba
, 0, sizeof hba
);
962 for (i
= 0; i
< split
; i
++) {
964 hba
[i
/ 8] |= (1 << (i
& 7));
971 token
= next_token (&val
, (unsigned *)0, cfile
);
972 if (token
!= BALANCE
) {
973 parse_warn (cfile
, "expecting 'balance'");
975 skip_to_rbrace (cfile
, 1);
978 token
= next_token (&val
, (unsigned *)0, cfile
);
979 if (token
!= TOKEN_MAX
) {
980 parse_warn (cfile
, "expecting 'max'");
983 token
= next_token (&val
, (unsigned *)0, cfile
);
984 if (token
!= SECONDS
) {
985 parse_warn (cfile
, "expecting 'secs'");
988 token
= next_token (&val
, (unsigned *)0, cfile
);
989 if (token
!= NUMBER
) {
990 parse_warn (cfile
, "expecting number");
993 peer
-> load_balance_max_secs
= atoi (val
);
998 "invalid statement in peer declaration");
999 skip_to_rbrace (cfile
, 1);
1000 dhcp_failover_state_dereference (&peer
, MDL
);
1003 if (token
!= RBRACE
&& !parse_semi (cfile
)) {
1004 skip_to_rbrace (cfile
, 1);
1005 dhcp_failover_state_dereference (&peer
, MDL
);
1008 } while (token
!= RBRACE
);
1010 /* me.address can be null; the failover link initiate code tries to
1011 * derive a reasonable address to use.
1013 if (!peer
-> partner
.address
)
1014 parse_warn (cfile
, "peer address may not be omitted");
1016 /* XXX - when/if we get a port number assigned, just set as default */
1017 if (!peer
-> me
.port
)
1018 parse_warn (cfile
, "local port may not be omitted");
1019 if (!peer
-> partner
.port
)
1020 parse_warn (cfile
, "peer port may not be omitted");
1022 if (peer
-> i_am
== primary
) {
1025 "primary failover server must have hba or split.");
1026 } else if (!peer
-> mclt
) {
1028 "primary failover server must have mclt.");
1032 if (!peer
->max_lease_misbalance
)
1033 peer
->max_lease_misbalance
= DEFAULT_MAX_LEASE_MISBALANCE
;
1034 if (!peer
->max_lease_ownership
)
1035 peer
->max_lease_ownership
= DEFAULT_MAX_LEASE_OWNERSHIP
;
1036 if (!peer
->max_balance
)
1037 peer
->max_balance
= DEFAULT_MAX_BALANCE_TIME
;
1038 if (!peer
->min_balance
)
1039 peer
->min_balance
= DEFAULT_MIN_BALANCE_TIME
;
1040 if (!peer
->me
.max_flying_updates
)
1041 peer
->me
.max_flying_updates
= DEFAULT_MAX_FLYING_UPDATES
;
1042 if (!peer
->me
.max_response_delay
)
1043 peer
->me
.max_response_delay
= DEFAULT_MAX_RESPONSE_DELAY
;
1045 if (type
== SHARED_NET_DECL
)
1046 group
->shared_network
->failover_peer
= peer
;
1048 /* Set the initial state. */
1049 if (peer
-> i_am
== primary
) {
1050 peer
-> me
.state
= recover
;
1051 peer
-> me
.stos
= cur_time
;
1052 peer
-> partner
.state
= unknown_state
;
1053 peer
-> partner
.stos
= cur_time
;
1055 peer
-> me
.state
= recover
;
1056 peer
-> me
.stos
= cur_time
;
1057 peer
-> partner
.state
= unknown_state
;
1058 peer
-> partner
.stos
= cur_time
;
1061 status
= enter_failover_peer (peer
);
1062 if (status
!= ISC_R_SUCCESS
)
1063 parse_warn (cfile
, "failover peer %s: %s",
1064 peer
-> name
, isc_result_totext (status
));
1065 dhcp_failover_state_dereference (&peer
, MDL
);
1068 void parse_failover_state_declaration (struct parse
*cfile
,
1069 dhcp_failover_state_t
*peer
)
1071 enum dhcp_token token
;
1074 dhcp_failover_state_t
*state
;
1075 dhcp_failover_config_t
*cp
;
1078 token
= next_token (&val
, (unsigned *)0, cfile
);
1079 if (token
!= PEER
) {
1080 parse_warn (cfile
, "expecting \"peer\"");
1081 skip_to_semi (cfile
);
1085 token
= next_token (&val
, (unsigned *)0, cfile
);
1086 if (is_identifier (token
) || token
== STRING
) {
1087 name
= dmalloc (strlen (val
) + 1, MDL
);
1089 log_fatal ("failover peer name %s: no memory",
1093 parse_warn (cfile
, "expecting failover peer name.");
1094 skip_to_semi (cfile
);
1098 /* See if there's a peer declaration by this name. */
1099 state
= (dhcp_failover_state_t
*)0;
1100 find_failover_peer (&state
, name
, MDL
);
1102 parse_warn (cfile
, "unknown failover peer: %s", name
);
1103 skip_to_semi (cfile
);
1107 token
= next_token (&val
, (unsigned *)0, cfile
);
1108 if (token
!= STATE
) {
1109 parse_warn (cfile
, "expecting 'state'");
1111 skip_to_semi (cfile
);
1115 state
= (dhcp_failover_state_t
*)0;
1116 dhcp_failover_state_reference (&state
, peer
, MDL
);
1118 token
= next_token (&val
, (unsigned *)0, cfile
);
1119 if (token
!= LBRACE
) {
1120 parse_warn (cfile
, "expecting left brace");
1122 skip_to_semi (cfile
);
1123 dhcp_failover_state_dereference (&state
, MDL
);
1127 token
= next_token (&val
, (unsigned *)0, cfile
);
1134 token
= next_token (&val
, (unsigned *)0, cfile
);
1135 if (token
!= STATE
) {
1136 parse_warn (cfile
, "expecting 'state'");
1139 parse_failover_state (cfile
,
1140 &cp
-> state
, &cp
-> stos
);
1144 cp
= &state
-> partner
;
1148 if (state
-> i_am
== primary
) {
1150 "mclt not valid for primary");
1153 token
= next_token (&val
, (unsigned *)0, cfile
);
1154 if (token
!= NUMBER
) {
1155 parse_warn (cfile
, "expecting a number.");
1158 state
-> mclt
= atoi (val
);
1163 parse_warn (cfile
, "expecting state setting.");
1165 skip_to_rbrace (cfile
, 1);
1166 dhcp_failover_state_dereference (&state
, MDL
);
1169 } while (token
!= RBRACE
);
1170 dhcp_failover_state_dereference (&state
, MDL
);
1173 void parse_failover_state (cfile
, state
, stos
)
1174 struct parse
*cfile
;
1175 enum failover_state
*state
;
1178 enum dhcp_token token
;
1180 enum failover_state state_in
;
1183 token
= next_token (&val
, (unsigned *)0, cfile
);
1186 state_in
= unknown_state
;
1190 state_in
= partner_down
;
1197 case COMMUNICATIONS_INTERRUPTED
:
1198 state_in
= communications_interrupted
;
1201 case RESOLUTION_INTERRUPTED
:
1202 state_in
= resolution_interrupted
;
1205 case POTENTIAL_CONFLICT
:
1206 state_in
= potential_conflict
;
1214 state_in
= recover_wait
;
1218 state_in
= recover_done
;
1222 state_in
= shut_down
;
1234 parse_warn (cfile
, "unknown failover state");
1235 skip_to_semi (cfile
);
1239 token
= next_token (&val
, (unsigned *)0, cfile
);
1240 if (token
== SEMI
) {
1244 parse_warn (cfile
, "expecting \"at\"");
1245 skip_to_semi (cfile
);
1249 stos_in
= parse_date (cfile
);
1254 /* Now that we've apparently gotten a clean parse, we
1255 can trust that this is a state that was fully committed to
1256 disk, so we can install it. */
1260 #endif /* defined (FAILOVER_PROTOCOL) */
1262 /* Permit_list_match returns 1 if every element of the permit list in lhs
1263 also appears in rhs. Note that this doesn't by itself mean that the
1264 two lists are equal - to check for equality, permit_list_match has to
1265 return 1 with (list1, list2) and with (list2, list1). */
1267 int permit_list_match (struct permit
*lhs
, struct permit
*rhs
)
1269 struct permit
*plp
, *prp
;
1276 for (plp
= lhs
; plp
; plp
= plp
-> next
) {
1278 for (prp
= rhs
; prp
; prp
= prp
-> next
) {
1279 if (prp
-> type
== plp
-> type
&&
1280 (prp
-> type
!= permit_class
||
1281 prp
-> class == plp
-> class)) {
1292 void parse_pool_statement (cfile
, group
, type
)
1293 struct parse
*cfile
;
1294 struct group
*group
;
1297 enum dhcp_token token
;
1300 struct pool
*pool
, **p
, *pp
;
1301 struct permit
*permit
;
1302 struct permit
**permit_head
;
1303 int declaration
= 0;
1304 isc_result_t status
;
1305 struct lease
*lpchain
= (struct lease
*)0, *lp
;
1307 pool
= (struct pool
*)0;
1308 status
= pool_allocate (&pool
, MDL
);
1309 if (status
!= ISC_R_SUCCESS
)
1310 log_fatal ("no memory for pool: %s",
1311 isc_result_totext (status
));
1313 if (type
== SUBNET_DECL
)
1314 shared_network_reference (&pool
-> shared_network
,
1315 group
-> subnet
-> shared_network
,
1318 shared_network_reference (&pool
-> shared_network
,
1319 group
-> shared_network
, MDL
);
1321 if (!clone_group (&pool
-> group
, pool
-> shared_network
-> group
, MDL
))
1322 log_fatal ("can't clone pool group.");
1324 #if defined (FAILOVER_PROTOCOL)
1325 /* Inherit the failover peer from the shared network. */
1326 if (pool
-> shared_network
-> failover_peer
)
1327 dhcp_failover_state_reference
1328 (&pool
-> failover_peer
,
1329 pool
-> shared_network
-> failover_peer
, MDL
);
1332 if (!parse_lbrace (cfile
)) {
1333 pool_dereference (&pool
, MDL
);
1338 token
= peek_token (&val
, (unsigned *)0, cfile
);
1341 next_token (&val
, (unsigned *)0, cfile
);
1342 token
= next_token (&val
, (unsigned *)0, cfile
);
1343 if (token
!= FAILOVER
||
1344 (token
= next_token (&val
, (unsigned *)0,
1347 "expecting \"failover peer\".");
1348 skip_to_semi (cfile
);
1351 #if defined (FAILOVER_PROTOCOL)
1352 if (pool
-> failover_peer
)
1353 dhcp_failover_state_dereference
1354 (&pool
-> failover_peer
, MDL
);
1358 #if defined (FAILOVER_PROTOCOL)
1360 next_token (&val
, (unsigned *)0, cfile
);
1361 token
= next_token (&val
, (unsigned *)0, cfile
);
1362 if (token
!= PEER
) {
1363 parse_warn (cfile
, "expecting 'peer'.");
1364 skip_to_semi (cfile
);
1367 token
= next_token (&val
, (unsigned *)0, cfile
);
1368 if (token
!= STRING
) {
1369 parse_warn (cfile
, "expecting string.");
1370 skip_to_semi (cfile
);
1373 if (pool
-> failover_peer
)
1374 dhcp_failover_state_dereference
1375 (&pool
-> failover_peer
, MDL
);
1376 status
= find_failover_peer (&pool
-> failover_peer
,
1378 if (status
!= ISC_R_SUCCESS
)
1380 "failover peer %s: %s", val
,
1381 isc_result_totext (status
));
1383 pool
-> failover_peer
-> pool_count
++;
1389 next_token (&val
, (unsigned *)0, cfile
);
1390 parse_address_range (cfile
, group
, type
,
1394 permit_head
= &pool
-> permit_list
;
1396 permit
= new_permit (MDL
);
1398 log_fatal ("no memory for permit");
1399 next_token (&val
, (unsigned *)0, cfile
);
1400 token
= next_token (&val
, (unsigned *)0, cfile
);
1403 permit
-> type
= permit_unknown_clients
;
1405 if (next_token (&val
, (unsigned *)0,
1406 cfile
) != CLIENTS
) {
1408 "expecting \"clients\"");
1409 skip_to_semi (cfile
);
1410 free_permit (permit
, MDL
);
1416 permit
-> type
= permit_known_clients
;
1419 case UNKNOWN_CLIENTS
:
1420 permit
-> type
= permit_unknown_clients
;
1424 permit
-> type
= permit_known_clients
;
1428 permit
-> type
= permit_authenticated_clients
;
1431 case UNAUTHENTICATED
:
1433 permit_unauthenticated_clients
;
1437 permit
-> type
= permit_all_clients
;
1442 permit
-> type
= permit_dynamic_bootp_clients
;
1443 if (next_token (&val
, (unsigned *)0,
1444 cfile
) != TOKEN_BOOTP
) {
1446 "expecting \"bootp\"");
1447 skip_to_semi (cfile
);
1448 free_permit (permit
, MDL
);
1454 if (next_token (&val
, (unsigned *)0,
1456 parse_warn (cfile
, "expecting \"of\"");
1457 skip_to_semi (cfile
);
1458 free_permit (permit
, MDL
);
1461 if (next_token (&val
, (unsigned *)0,
1464 "expecting class name.");
1465 skip_to_semi (cfile
);
1466 free_permit (permit
, MDL
);
1469 permit
-> type
= permit_class
;
1470 permit
-> class = (struct class *)0;
1471 find_class (&permit
-> class, val
, MDL
);
1472 if (!permit
-> class)
1474 "no such class: %s", val
);
1478 parse_warn (cfile
, "expecting permit type.");
1479 skip_to_semi (cfile
);
1482 while (*permit_head
)
1483 permit_head
= &((*permit_head
) -> next
);
1484 *permit_head
= permit
;
1489 permit_head
= &pool
-> prohibit_list
;
1493 next_token (&val
, (unsigned *)0, cfile
);
1498 declaration
= parse_statement (cfile
, pool
-> group
,
1500 (struct host_decl
*)0,
1506 #if defined (FAILOVER_PROTOCOL)
1507 /* We can't do failover on a pool that supports dynamic bootp,
1508 because BOOTP doesn't support leases, and failover absolutely
1509 depends on lease timing. */
1510 if (pool
-> failover_peer
) {
1511 /* This search order matches the search orders later in
1512 * execution - deny first, if not denied, check permit
1513 * list. A dynamic bootp client may be known or unknown,
1514 * it may belong to a member of a class, but it definitely
1515 * will not be authenticated since that requires DHCP
1516 * to work. So a dynamic bootp client is definitely not
1517 * an authenticated client, and we can't say for sure about
1520 * So we nag the user.
1522 for (permit
= pool
-> prohibit_list
; permit
;
1523 permit
= permit
-> next
) {
1524 if (permit
-> type
== permit_dynamic_bootp_clients
||
1525 permit
-> type
== permit_unauthenticated_clients
||
1526 permit
-> type
== permit_all_clients
)
1530 permit
= pool
-> permit_list
;
1534 permit_authenticated_clients
) {
1536 "pools with failover peers %s",
1537 "may not permit dynamic bootp.");
1538 log_error ("Either write a \"%s\" %s",
1540 "statement and use disjoint");
1541 log_error ("pools, or%s (%s) %s",
1542 " don't permit dynamic bootp",
1543 "\"deny dynamic bootp clients;\"",
1545 log_error ("This is a protocol,%s %s",
1546 " limitation, not an ISC DHCP",
1548 log_error ("please don't request an %s",
1549 "enhancement or ask why this is.");
1554 permit
= permit
-> next
;
1558 #endif /* FAILOVER_PROTOCOL */
1560 /* See if there's already a pool into which we can merge this one. */
1561 for (pp
= pool
-> shared_network
-> pools
; pp
; pp
= pp
-> next
) {
1564 if (pp
-> group
-> statements
!= pool
-> group
-> statements
)
1566 #if defined (FAILOVER_PROTOCOL)
1567 if (pool
-> failover_peer
!= pp
-> failover_peer
)
1570 if (!permit_list_match (pp
-> permit_list
,
1571 pool
-> permit_list
) ||
1572 !permit_list_match (pool
-> permit_list
,
1573 pp
-> permit_list
) ||
1574 !permit_list_match (pp
-> prohibit_list
,
1575 pool
-> prohibit_list
) ||
1576 !permit_list_match (pool
-> prohibit_list
,
1577 pp
-> prohibit_list
))
1580 /* Okay, we can merge these two pools. All we have to
1581 do is fix up the leases, which all point to their pool. */
1582 for (lp
= lpchain
; lp
; lp
= lp
-> next
) {
1583 pool_dereference (&lp
-> pool
, MDL
);
1584 pool_reference (&lp
-> pool
, pp
, MDL
);
1589 /* If we didn't succeed in merging this pool into another, put
1592 p
= &pool
-> shared_network
-> pools
;
1593 for (; *p
; p
= &((*p
) -> next
))
1595 pool_reference (p
, pool
, MDL
);
1598 /* Don't allow a pool declaration with no addresses, since it is
1599 probably a configuration error. */
1601 parse_warn (cfile
, "Pool declaration with no address range.");
1602 log_error ("Pool declarations must always contain at least");
1603 log_error ("one range statement.");
1606 /* Dereference the lease chain. */
1607 lp
= (struct lease
*)0;
1609 lease_reference (&lp
, lpchain
, MDL
);
1610 lease_dereference (&lpchain
, MDL
);
1612 lease_reference (&lpchain
, lp
-> next
, MDL
);
1613 lease_dereference (&lp
-> next
, MDL
);
1614 lease_dereference (&lp
, MDL
);
1617 pool_dereference (&pool
, MDL
);
1620 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1622 int parse_boolean (cfile
)
1623 struct parse
*cfile
;
1625 enum dhcp_token token
;
1629 token
= next_token (&val
, (unsigned *)0, cfile
);
1630 if (!strcasecmp (val
, "true")
1631 || !strcasecmp (val
, "on"))
1633 else if (!strcasecmp (val
, "false")
1634 || !strcasecmp (val
, "off"))
1638 "boolean value (true/false/on/off) expected");
1639 skip_to_semi (cfile
);
1646 /* Expect a left brace; if there isn't one, skip over the rest of the
1647 statement and return zero; otherwise, return 1. */
1649 int parse_lbrace (cfile
)
1650 struct parse
*cfile
;
1652 enum dhcp_token token
;
1655 token
= next_token (&val
, (unsigned *)0, cfile
);
1656 if (token
!= LBRACE
) {
1657 parse_warn (cfile
, "expecting left brace.");
1658 skip_to_semi (cfile
);
1665 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1667 void parse_host_declaration (cfile
, group
)
1668 struct parse
*cfile
;
1669 struct group
*group
;
1672 enum dhcp_token token
;
1673 struct host_decl
*host
;
1675 int declaration
= 0;
1678 isc_result_t status
;
1680 name
= parse_host_name (cfile
);
1682 parse_warn (cfile
, "expecting a name for host declaration.");
1683 skip_to_semi (cfile
);
1687 host
= (struct host_decl
*)0;
1688 status
= host_allocate (&host
, MDL
);
1689 if (status
!= ISC_R_SUCCESS
)
1690 log_fatal ("can't allocate host decl struct %s: %s",
1691 name
, isc_result_totext (status
));
1692 host
-> name
= name
;
1693 if (!clone_group (&host
-> group
, group
, MDL
)) {
1694 log_fatal ("can't clone group for host %s", name
);
1696 host_dereference (&host
, MDL
);
1700 if (!parse_lbrace (cfile
))
1704 token
= peek_token (&val
, (unsigned *)0, cfile
);
1705 if (token
== RBRACE
) {
1706 token
= next_token (&val
, (unsigned *)0, cfile
);
1709 if (token
== END_OF_FILE
) {
1710 token
= next_token (&val
, (unsigned *)0, cfile
);
1711 parse_warn (cfile
, "unexpected end of file");
1714 /* If the host declaration was created by the server,
1715 remember to save it. */
1716 if (token
== DYNAMIC
) {
1718 token
= next_token (&val
, (unsigned *)0, cfile
);
1719 if (!parse_semi (cfile
))
1723 /* If the host declaration was created by the server,
1724 remember to save it. */
1725 if (token
== TOKEN_DELETED
) {
1727 token
= next_token (&val
, (unsigned *)0, cfile
);
1728 if (!parse_semi (cfile
))
1733 if (token
== GROUP
) {
1734 struct group_object
*go
;
1735 token
= next_token (&val
, (unsigned *)0, cfile
);
1736 token
= next_token (&val
, (unsigned *)0, cfile
);
1737 if (token
!= STRING
&& !is_identifier (token
)) {
1739 "expecting string or identifier.");
1740 skip_to_rbrace (cfile
, 1);
1743 go
= (struct group_object
*)0;
1744 if (!group_hash_lookup (&go
, group_name_hash
,
1745 val
, strlen (val
), MDL
)) {
1746 parse_warn (cfile
, "unknown group %s in host %s",
1749 if (host
-> named_group
)
1750 group_object_dereference
1751 (&host
-> named_group
, MDL
);
1752 group_object_reference (&host
-> named_group
,
1754 group_object_dereference (&go
, MDL
);
1756 if (!parse_semi (cfile
))
1763 unsigned char *t
= 0;
1766 token
= next_token (&val
, (unsigned *)0, cfile
);
1767 data_string_forget (&host
-> client_identifier
, MDL
);
1769 if (host
->client_identifier
.len
!= 0) {
1770 parse_warn(cfile
, "Host %s already has a "
1771 "client identifier.",
1776 /* See if it's a string or a cshl. */
1777 token
= peek_token (&val
, (unsigned *)0, cfile
);
1778 if (token
== STRING
) {
1779 token
= next_token (&val
, &len
, cfile
);
1781 host
-> client_identifier
.terminated
= 1;
1784 t
= parse_numeric_aggregate
1786 (unsigned char *)0, &len
, ':', 16, 8);
1789 "expecting hex list.");
1790 skip_to_semi (cfile
);
1792 s
= (const char *)t
;
1794 if (!buffer_allocate
1795 (&host
-> client_identifier
.buffer
,
1796 len
+ host
-> client_identifier
.terminated
, MDL
))
1797 log_fatal ("no memory for uid for host %s.",
1799 host
-> client_identifier
.data
=
1800 host
-> client_identifier
.buffer
-> data
;
1801 host
-> client_identifier
.len
= len
;
1802 memcpy (host
-> client_identifier
.buffer
-> data
, s
,
1803 len
+ host
-> client_identifier
.terminated
);
1807 if (!parse_semi (cfile
))
1811 declaration
= parse_statement (cfile
, host
-> group
,
1817 struct host_decl
*hp
= (struct host_decl
*)0;
1818 if (host_hash_lookup (&hp
, host_name_hash
,
1819 (unsigned char *)host
-> name
,
1820 strlen (host
-> name
), MDL
)) {
1821 delete_host (hp
, 0);
1822 host_dereference (&hp
, MDL
);
1825 if (host
-> named_group
&& host
-> named_group
-> group
) {
1826 if (host
-> group
-> statements
||
1827 (host
-> group
-> authoritative
!=
1828 host
-> named_group
-> group
-> authoritative
)) {
1829 if (host
-> group
-> next
)
1830 group_dereference (&host
-> group
-> next
,
1832 group_reference (&host
-> group
-> next
,
1833 host
-> named_group
-> group
,
1836 group_dereference (&host
-> group
, MDL
);
1837 group_reference (&host
-> group
,
1838 host
-> named_group
-> group
,
1844 host
-> flags
|= HOST_DECL_DYNAMIC
;
1846 host
-> flags
|= HOST_DECL_STATIC
;
1848 status
= enter_host (host
, dynamicp
, 0);
1849 if (status
!= ISC_R_SUCCESS
)
1850 parse_warn (cfile
, "host %s: %s", host
-> name
,
1851 isc_result_totext (status
));
1853 host_dereference (&host
, MDL
);
1856 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
1859 int parse_class_declaration (cp
, cfile
, group
, type
)
1861 struct parse
*cfile
;
1862 struct group
*group
;
1866 enum dhcp_token token
;
1867 struct class *class = (struct class *)0, *pc
= (struct class *)0;
1868 int declaration
= 0;
1870 struct data_string data
;
1873 struct executable_statement
*stmt
= (struct executable_statement
*)0;
1874 struct expression
*expr
;
1876 isc_result_t status
= ISC_R_FAILURE
;
1877 int matchedonce
= 0;
1878 int submatchedonce
= 0;
1881 token
= next_token (&val
, (unsigned *)0, cfile
);
1882 if (token
!= STRING
) {
1883 parse_warn (cfile
, "Expecting class name");
1884 skip_to_semi (cfile
);
1888 /* See if there's already a class with the specified name. */
1889 find_class (&pc
, val
, MDL
);
1891 /* If it is a class, we're updating it. If it's any of the other
1892 * types (subclass, vendor or user class), the named class is a
1893 * reference to the parent class so its mandatory.
1895 if (pc
&& (type
== CLASS_TYPE_CLASS
)) {
1896 class_reference(&class, pc
, MDL
);
1898 class_dereference(&pc
, MDL
);
1899 } else if (!pc
&& (type
!= CLASS_TYPE_CLASS
)) {
1900 parse_warn(cfile
, "no class named %s", val
);
1901 skip_to_semi(cfile
);
1905 /* The old vendor-class and user-class declarations had an implicit
1906 match. We don't do the implicit match anymore. Instead, for
1907 backward compatibility, we have an implicit-vendor-class and an
1908 implicit-user-class. vendor-class and user-class declarations
1909 are turned into subclasses of the implicit classes, and the
1910 submatch expression of the implicit classes extracts the contents of
1911 the vendor class or user class. */
1912 if ((type
== CLASS_TYPE_VENDOR
) || (type
== CLASS_TYPE_USER
)) {
1913 data
.len
= strlen (val
);
1914 data
.buffer
= (struct buffer
*)0;
1915 if (!buffer_allocate (&data
.buffer
, data
.len
+ 1, MDL
))
1916 log_fatal ("no memory for class name.");
1917 data
.data
= &data
.buffer
-> data
[0];
1918 data
.terminated
= 1;
1920 tname
= type
? "implicit-vendor-class" : "implicit-user-class";
1921 } else if (type
== CLASS_TYPE_CLASS
) {
1924 tname
= (const char *)0;
1928 name
= dmalloc (strlen (tname
) + 1, MDL
);
1930 log_fatal ("No memory for class name %s.", tname
);
1935 /* If this is a straight subclass, parse the hash string. */
1936 if (type
== CLASS_TYPE_SUBCLASS
) {
1937 token
= peek_token (&val
, (unsigned *)0, cfile
);
1938 if (token
== STRING
) {
1939 token
= next_token (&val
, &data
.len
, cfile
);
1940 data
.buffer
= (struct buffer
*)0;
1941 if (!buffer_allocate (&data
.buffer
,
1942 data
.len
+ 1, MDL
)) {
1944 class_dereference (&pc
, MDL
);
1948 data
.terminated
= 1;
1949 data
.data
= &data
.buffer
-> data
[0];
1950 memcpy ((char *)data
.buffer
-> data
, val
,
1952 } else if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
1953 memset (&data
, 0, sizeof data
);
1954 if (!parse_cshl (&data
, cfile
)) {
1956 class_dereference (&pc
, MDL
);
1960 parse_warn (cfile
, "Expecting string or hex list.");
1962 class_dereference (&pc
, MDL
);
1967 /* See if there's already a class in the hash table matching the
1969 if (type
!= CLASS_TYPE_CLASS
)
1970 class_hash_lookup (&class, pc
-> hash
,
1971 (const char *)data
.data
, data
.len
, MDL
);
1973 /* If we didn't find an existing class, allocate a new one. */
1975 /* Allocate the class structure... */
1976 status
= class_allocate (&class, MDL
);
1978 group_reference (&class -> group
, pc
-> group
, MDL
);
1979 class_reference (&class -> superclass
, pc
, MDL
);
1980 class -> lease_limit
= pc
-> lease_limit
;
1981 if (class -> lease_limit
) {
1982 class -> billed_leases
=
1983 dmalloc (class -> lease_limit
*
1984 sizeof (struct lease
*), MDL
);
1985 if (!class -> billed_leases
)
1986 log_fatal ("no memory for billing");
1987 memset (class -> billed_leases
, 0,
1988 (class -> lease_limit
*
1989 sizeof class -> billed_leases
));
1991 data_string_copy (&class -> hash_string
, &data
, MDL
);
1993 !class_new_hash (&pc
->hash
, SCLASS_HASH_SIZE
, MDL
))
1994 log_fatal ("No memory for subclass hash.");
1995 class_hash_add (pc
-> hash
,
1996 (const char *)class -> hash_string
.data
,
1997 class -> hash_string
.len
,
1998 (void *)class, MDL
);
2001 group_dereference(&class->group
, MDL
);
2002 if (!clone_group (&class -> group
, group
, MDL
))
2003 log_fatal ("no memory to clone class group.");
2006 /* If this is an implicit vendor or user class, add a
2007 statement that causes the vendor or user class ID to
2008 be sent back in the reply. */
2009 if (type
== CLASS_TYPE_VENDOR
|| type
== CLASS_TYPE_USER
) {
2010 stmt
= (struct executable_statement
*)0;
2011 if (!executable_statement_allocate (&stmt
, MDL
))
2012 log_fatal ("no memory for class statement.");
2013 stmt
-> op
= supersede_option_statement
;
2014 if (option_cache_allocate (&stmt
-> data
.option
,
2016 stmt
-> data
.option
-> data
= data
;
2017 code
= (type
== CLASS_TYPE_VENDOR
)
2018 ? DHO_VENDOR_CLASS_IDENTIFIER
2020 option_code_hash_lookup(
2021 &stmt
->data
.option
->option
,
2022 dhcp_universe
.code_hash
,
2025 class -> statements
= stmt
;
2028 /* Save the name, if there is one. */
2029 if (class->name
!= NULL
)
2030 dfree(class->name
, MDL
);
2034 if (type
!= CLASS_TYPE_CLASS
)
2035 data_string_forget(&data
, MDL
);
2037 /* Spawned classes don't have to have their own settings. */
2038 if (class -> superclass
) {
2039 token
= peek_token (&val
, (unsigned *)0, cfile
);
2040 if (token
== SEMI
) {
2041 next_token (&val
, (unsigned *)0, cfile
);
2043 status
= class_reference (cp
, class, MDL
);
2044 class_dereference (&class, MDL
);
2046 class_dereference (&pc
, MDL
);
2047 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2049 /* Give the subclass its own group. */
2050 if (!clone_group (&class -> group
, class -> group
, MDL
))
2051 log_fatal ("can't clone class group.");
2055 if (!parse_lbrace (cfile
)) {
2056 class_dereference (&class, MDL
);
2058 class_dereference (&pc
, MDL
);
2063 token
= peek_token (&val
, (unsigned *)0, cfile
);
2064 if (token
== RBRACE
) {
2065 token
= next_token (&val
, (unsigned *)0, cfile
);
2067 } else if (token
== END_OF_FILE
) {
2068 token
= next_token (&val
, (unsigned *)0, cfile
);
2069 parse_warn (cfile
, "unexpected end of file");
2071 } else if (token
== DYNAMIC
) {
2072 class->flags
|= CLASS_DECL_DYNAMIC
;
2073 token
= next_token (&val
, (unsigned *)0, cfile
);
2074 if (!parse_semi (cfile
))
2077 } else if (token
== TOKEN_DELETED
) {
2078 class->flags
|= CLASS_DECL_DELETED
;
2079 token
= next_token (&val
, (unsigned *)0, cfile
);
2080 if (!parse_semi (cfile
))
2083 } else if (token
== MATCH
) {
2086 "invalid match in subclass.");
2087 skip_to_semi (cfile
);
2090 token
= next_token (&val
, (unsigned *)0, cfile
);
2091 token
= peek_token (&val
, (unsigned *)0, cfile
);
2094 token
= next_token (&val
, (unsigned *)0, cfile
);
2096 parse_warn(cfile
, "A class may only have "
2097 "one 'match if' clause.");
2098 skip_to_semi(cfile
);
2103 expression_dereference(&class->expr
, MDL
);
2104 if (!parse_boolean_expression (&class->expr
, cfile
,
2108 "expecting boolean expr.");
2109 skip_to_semi (cfile
);
2112 #if defined (DEBUG_EXPRESSION_PARSE)
2113 print_expression ("class match",
2118 } else if (token
== SPAWN
) {
2119 token
= next_token (&val
, (unsigned *)0, cfile
);
2122 "invalid spawn in subclass.");
2123 skip_to_semi (cfile
);
2126 class -> spawning
= 1;
2127 token
= next_token (&val
, (unsigned *)0, cfile
);
2128 if (token
!= WITH
) {
2130 "expecting with after spawn");
2131 skip_to_semi (cfile
);
2135 if (submatchedonce
) {
2137 "can't override existing %s.",
2139 skip_to_semi (cfile
);
2143 if (class->submatch
)
2144 expression_dereference(&class->submatch
, MDL
);
2145 if (!parse_data_expression (&class -> submatch
,
2149 "expecting data expr.");
2150 skip_to_semi (cfile
);
2153 #if defined (DEBUG_EXPRESSION_PARSE)
2154 print_expression ("class submatch",
2159 } else if (token
== LEASE
) {
2160 next_token (&val
, (unsigned *)0, cfile
);
2161 token
= next_token (&val
, (unsigned *)0, cfile
);
2162 if (token
!= LIMIT
) {
2163 parse_warn (cfile
, "expecting \"limit\"");
2165 skip_to_semi (cfile
);
2168 token
= next_token (&val
, (unsigned *)0, cfile
);
2169 if (token
!= NUMBER
) {
2170 parse_warn (cfile
, "expecting a number");
2172 skip_to_semi (cfile
);
2175 class -> lease_limit
= atoi (val
);
2176 if (class->billed_leases
)
2177 dfree(class->billed_leases
, MDL
);
2178 class -> billed_leases
=
2179 dmalloc (class -> lease_limit
*
2180 sizeof (struct lease
*), MDL
);
2181 if (!class -> billed_leases
)
2182 log_fatal ("no memory for billed leases.");
2183 memset (class -> billed_leases
, 0,
2184 (class -> lease_limit
*
2185 sizeof class -> billed_leases
));
2186 have_billing_classes
= 1;
2189 declaration
= parse_statement (cfile
, class -> group
,
2191 (struct host_decl
*)0,
2196 if (class->flags
& CLASS_DECL_DELETED
) {
2197 if (type
== CLASS_TYPE_CLASS
) {
2198 struct class *theclass
= NULL
;
2200 status
= find_class(&theclass
, class->name
, MDL
);
2201 if (status
== ISC_R_SUCCESS
) {
2202 delete_class(theclass
, 0);
2203 class_dereference(&theclass
, MDL
);
2206 class_hash_delete(pc
->hash
,
2207 (char *)class->hash_string
.data
,
2208 class->hash_string
.len
, MDL
);
2210 } else if (type
== CLASS_TYPE_CLASS
&& new) {
2211 if (!collections
-> classes
)
2212 class_reference (&collections
-> classes
, class, MDL
);
2215 for (c
= collections
-> classes
;
2216 c
-> nic
; c
= c
-> nic
)
2218 class_reference (&c
-> nic
, class, MDL
);
2222 if (cp
) /* should always be 0??? */
2223 status
= class_reference (cp
, class, MDL
);
2224 class_dereference (&class, MDL
);
2226 class_dereference (&pc
, MDL
);
2227 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2230 /* shared-network-declaration :==
2231 hostname LBRACE declarations parameters RBRACE */
2233 void parse_shared_net_declaration (cfile
, group
)
2234 struct parse
*cfile
;
2235 struct group
*group
;
2238 enum dhcp_token token
;
2239 struct shared_network
*share
;
2241 int declaration
= 0;
2242 isc_result_t status
;
2244 share
= (struct shared_network
*)0;
2245 status
= shared_network_allocate (&share
, MDL
);
2246 if (status
!= ISC_R_SUCCESS
)
2247 log_fatal ("Can't allocate shared subnet: %s",
2248 isc_result_totext (status
));
2249 clone_group (&share
-> group
, group
, MDL
);
2250 shared_network_reference (&share
-> group
-> shared_network
,
2253 /* Get the name of the shared network... */
2254 token
= peek_token (&val
, (unsigned *)0, cfile
);
2255 if (token
== STRING
) {
2256 token
= next_token (&val
, (unsigned *)0, cfile
);
2259 parse_warn (cfile
, "zero-length shared network name");
2260 val
= "<no-name-given>";
2262 name
= dmalloc (strlen (val
) + 1, MDL
);
2264 log_fatal ("no memory for shared network name");
2267 name
= parse_host_name (cfile
);
2270 "expecting a name for shared-network");
2271 skip_to_semi (cfile
);
2272 shared_network_dereference (&share
, MDL
);
2276 share
-> name
= name
;
2278 if (!parse_lbrace (cfile
)) {
2279 shared_network_dereference (&share
, MDL
);
2284 token
= peek_token (&val
, (unsigned *)0, cfile
);
2285 if (token
== RBRACE
) {
2286 token
= next_token (&val
, (unsigned *)0, cfile
);
2287 if (!share
-> subnets
)
2289 "empty shared-network decl");
2291 enter_shared_network (share
);
2292 shared_network_dereference (&share
, MDL
);
2294 } else if (token
== END_OF_FILE
) {
2295 token
= next_token (&val
, (unsigned *)0, cfile
);
2296 parse_warn (cfile
, "unexpected end of file");
2298 } else if (token
== INTERFACE
) {
2299 token
= next_token (&val
, (unsigned *)0, cfile
);
2300 token
= next_token (&val
, (unsigned *)0, cfile
);
2301 new_shared_network_interface (cfile
, share
, val
);
2302 if (!parse_semi (cfile
))
2307 declaration
= parse_statement (cfile
, share
-> group
,
2309 (struct host_decl
*)0,
2312 shared_network_dereference (&share
, MDL
);
2315 /* subnet-declaration :==
2316 net NETMASK netmask RBRACE parameters declarations LBRACE */
2318 void parse_subnet_declaration (cfile
, share
)
2319 struct parse
*cfile
;
2320 struct shared_network
*share
;
2323 enum dhcp_token token
;
2324 struct subnet
*subnet
, *t
, *u
;
2326 unsigned char addr
[4];
2327 unsigned len
= sizeof addr
;
2328 int declaration
= 0;
2329 struct interface_info
*ip
;
2330 isc_result_t status
;
2332 subnet
= (struct subnet
*)0;
2333 status
= subnet_allocate (&subnet
, MDL
);
2334 if (status
!= ISC_R_SUCCESS
)
2335 log_fatal ("Allocation of new subnet failed: %s",
2336 isc_result_totext (status
));
2337 shared_network_reference (&subnet
-> shared_network
, share
, MDL
);
2338 if (!clone_group (&subnet
-> group
, share
-> group
, MDL
))
2339 log_fatal ("allocation of group for new subnet failed.");
2340 subnet_reference (&subnet
-> group
-> subnet
, subnet
, MDL
);
2342 /* Get the network number... */
2343 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2344 subnet_dereference (&subnet
, MDL
);
2347 memcpy (iaddr
.iabuf
, addr
, len
);
2349 subnet
-> net
= iaddr
;
2351 token
= next_token (&val
, (unsigned *)0, cfile
);
2352 if (token
!= NETMASK
) {
2353 parse_warn (cfile
, "Expecting netmask");
2354 skip_to_semi (cfile
);
2358 /* Get the netmask... */
2359 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2360 subnet_dereference (&subnet
, MDL
);
2363 memcpy (iaddr
.iabuf
, addr
, len
);
2365 subnet
-> netmask
= iaddr
;
2367 /* Validate the network number/netmask pair. */
2368 if (host_addr (subnet
-> net
, subnet
-> netmask
)) {
2371 maskstr
= strdup (piaddr (subnet
-> netmask
));
2373 "subnet %s netmask %s: bad subnet number/mask combination.",
2374 piaddr (subnet
-> net
), maskstr
);
2376 subnet_dereference (&subnet
, MDL
);
2377 skip_to_semi (cfile
);
2381 enter_subnet (subnet
);
2383 if (!parse_lbrace (cfile
)) {
2384 subnet_dereference (&subnet
, MDL
);
2389 token
= peek_token (&val
, (unsigned *)0, cfile
);
2390 if (token
== RBRACE
) {
2391 token
= next_token (&val
, (unsigned *)0, cfile
);
2393 } else if (token
== END_OF_FILE
) {
2394 token
= next_token (&val
, (unsigned *)0, cfile
);
2395 parse_warn (cfile
, "unexpected end of file");
2397 } else if (token
== INTERFACE
) {
2398 token
= next_token (&val
, (unsigned *)0, cfile
);
2399 token
= next_token (&val
, (unsigned *)0, cfile
);
2400 new_shared_network_interface (cfile
, share
, val
);
2401 if (!parse_semi (cfile
))
2405 declaration
= parse_statement (cfile
, subnet
-> group
,
2407 (struct host_decl
*)0,
2411 /* Add the subnet to the list of subnets in this shared net. */
2412 if (!share
-> subnets
)
2413 subnet_reference (&share
-> subnets
, subnet
, MDL
);
2415 u
= (struct subnet
*)0;
2416 for (t
= share
-> subnets
;
2417 t
-> next_sibling
; t
= t
-> next_sibling
) {
2418 if (subnet_inner_than (subnet
, t
, 0)) {
2419 subnet_reference (&subnet
-> next_sibling
,
2422 subnet_dereference (&u
-> next_sibling
,
2424 subnet_reference (&u
-> next_sibling
,
2427 subnet_dereference (&share
-> subnets
,
2429 subnet_reference (&share
-> subnets
,
2432 subnet_dereference (&subnet
, MDL
);
2437 subnet_reference (&t
-> next_sibling
, subnet
, MDL
);
2439 subnet_dereference (&subnet
, MDL
);
2442 /* group-declaration :== RBRACE parameters declarations LBRACE */
2444 void parse_group_declaration (cfile
, group
)
2445 struct parse
*cfile
;
2446 struct group
*group
;
2449 enum dhcp_token token
;
2451 int declaration
= 0;
2452 struct group_object
*t
;
2453 isc_result_t status
;
2459 g
= (struct group
*)0;
2460 if (!clone_group (&g
, group
, MDL
))
2461 log_fatal ("no memory for explicit group.");
2463 token
= peek_token (&val
, (unsigned *)0, cfile
);
2464 if (is_identifier (token
) || token
== STRING
) {
2465 next_token (&val
, (unsigned *)0, cfile
);
2467 name
= dmalloc (strlen (val
) + 1, MDL
);
2469 log_fatal ("no memory for group decl name %s", val
);
2473 if (!parse_lbrace (cfile
)) {
2474 group_dereference (&g
, MDL
);
2479 token
= peek_token (&val
, (unsigned *)0, cfile
);
2480 if (token
== RBRACE
) {
2481 token
= next_token (&val
, (unsigned *)0, cfile
);
2483 } else if (token
== END_OF_FILE
) {
2484 token
= next_token (&val
, (unsigned *)0, cfile
);
2485 parse_warn (cfile
, "unexpected end of file");
2487 } else if (token
== TOKEN_DELETED
) {
2488 token
= next_token (&val
, (unsigned *)0, cfile
);
2491 } else if (token
== DYNAMIC
) {
2492 token
= next_token (&val
, (unsigned *)0, cfile
);
2495 } else if (token
== STATIC
) {
2496 token
= next_token (&val
, (unsigned *)0, cfile
);
2500 declaration
= parse_statement (cfile
, g
, GROUP_DECL
,
2501 (struct host_decl
*)0,
2507 if (group_name_hash
) {
2508 t
= (struct group_object
*)0;
2509 if (group_hash_lookup (&t
, group_name_hash
,
2511 strlen (name
), MDL
)) {
2512 delete_group (t
, 0);
2516 t
= (struct group_object
*)0;
2517 status
= group_object_allocate (&t
, MDL
);
2518 if (status
!= ISC_R_SUCCESS
)
2519 log_fatal ("no memory for group decl %s: %s",
2520 val
, isc_result_totext (status
));
2521 group_reference (&t
-> group
, g
, MDL
);
2523 t
-> flags
= ((staticp
? GROUP_OBJECT_STATIC
: 0) |
2524 (dynamicp
? GROUP_OBJECT_DYNAMIC
: 0) |
2525 (deletedp
? GROUP_OBJECT_DELETED
: 0));
2526 supersede_group (t
, 0);
2529 group_object_dereference (&t
, MDL
);
2533 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2534 ip-addrs-or-hostnames :== ip-addr-or-hostname
2535 | ip-addrs-or-hostnames ip-addr-or-hostname */
2537 int parse_fixed_addr_param (oc
, cfile
)
2538 struct option_cache
**oc
;
2539 struct parse
*cfile
;
2542 enum dhcp_token token
;
2543 struct expression
*expr
= (struct expression
*)0;
2544 struct expression
*tmp
, *new;
2548 tmp
= (struct expression
*)0;
2549 if (parse_ip_addr_or_hostname (&tmp
, cfile
, 1)) {
2551 new = (struct expression
*)0;
2552 status
= make_concat (&new, expr
, tmp
);
2553 expression_dereference (&expr
, MDL
);
2554 expression_dereference (&tmp
, MDL
);
2562 expression_dereference (&expr
, MDL
);
2565 token
= peek_token (&val
, (unsigned *)0, cfile
);
2567 token
= next_token (&val
, (unsigned *)0, cfile
);
2568 } while (token
== COMMA
);
2570 if (!parse_semi (cfile
)) {
2572 expression_dereference (&expr
, MDL
);
2575 status
= option_cache (oc
, (struct data_string
*)0, expr
,
2576 (struct option
*)0, MDL
);
2577 expression_dereference (&expr
, MDL
);
2581 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2583 lease_parameters :== <nil>
2585 | lease_parameters lease_parameter
2587 lease_parameter :== STARTS date
2590 | HARDWARE hardware-parameter
2591 | UID hex_numbers SEMI
2592 | HOSTNAME hostname SEMI
2593 | CLIENT_HOSTNAME hostname SEMI
2594 | CLASS identifier SEMI
2595 | DYNAMIC_BOOTP SEMI */
2597 int parse_lease_declaration (struct lease
**lp
, struct parse
*cfile
)
2600 enum dhcp_token token
;
2601 unsigned char addr
[4];
2602 unsigned len
= sizeof addr
;
2606 struct lease
*lease
;
2607 struct executable_statement
*on
;
2608 struct expression
*exp
;
2609 struct data_string ds
;
2613 int noequal
, newbinding
;
2614 struct binding
*binding
;
2615 isc_result_t status
;
2616 struct option_cache
*oc
;
2618 binding_state_t new_state
;
2619 unsigned buflen
= 0;
2620 struct class *class;
2622 lease
= (struct lease
*)0;
2623 status
= lease_allocate (&lease
, MDL
);
2624 if (status
!= ISC_R_SUCCESS
)
2627 /* Get the address for which the lease has been issued. */
2628 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2629 lease_dereference (&lease
, MDL
);
2632 memcpy (lease
-> ip_addr
.iabuf
, addr
, len
);
2633 lease
-> ip_addr
.len
= len
;
2635 if (!parse_lbrace (cfile
)) {
2636 lease_dereference (&lease
, MDL
);
2641 token
= next_token (&val
, (unsigned *)0, cfile
);
2642 if (token
== RBRACE
)
2644 else if (token
== END_OF_FILE
) {
2645 parse_warn (cfile
, "unexpected end of file");
2648 strncpy (tbuf
, val
, sizeof tbuf
);
2649 tbuf
[(sizeof tbuf
) - 1] = 0;
2651 /* Parse any of the times associated with the lease. */
2660 t
= parse_date (cfile
);
2664 lease
-> starts
= t
;
2692 default: /* for gcc, we'll never get here. */
2693 log_fatal ("Impossible error at %s:%d.", MDL
);
2698 /* Colon-seperated hexadecimal octets... */
2701 token
= peek_token (&val
, (unsigned *)0, cfile
);
2702 if (token
== STRING
) {
2703 unsigned char *tuid
;
2704 token
= next_token (&val
, &buflen
, cfile
);
2705 if (buflen
< sizeof lease
-> uid_buf
) {
2706 tuid
= lease
-> uid_buf
;
2708 sizeof lease
-> uid_buf
;
2710 tuid
= ((unsigned char *)
2711 dmalloc (buflen
, MDL
));
2713 log_error ("no space for uid");
2714 lease_dereference (&lease
,
2718 lease
-> uid_max
= buflen
;
2720 lease
-> uid_len
= buflen
;
2721 memcpy (tuid
, val
, lease
-> uid_len
);
2722 lease
-> uid
= tuid
;
2725 lease
-> uid
= (parse_numeric_aggregate
2726 (cfile
, (unsigned char *)0,
2727 &buflen
, ':', 16, 8));
2728 if (!lease
-> uid
) {
2729 lease_dereference (&lease
, MDL
);
2732 lease
-> uid_len
= buflen
;
2733 lease
-> uid_max
= buflen
;
2734 if (lease
-> uid_len
== 0) {
2735 lease
-> uid
= (unsigned char *)0;
2736 parse_warn (cfile
, "zero-length uid");
2743 if (!lease
-> uid
) {
2744 log_fatal ("No memory for lease uid");
2750 token
= next_token (&val
, (unsigned *)0, cfile
);
2751 if (!is_identifier (token
)) {
2753 skip_to_rbrace (cfile
, 1);
2754 lease_dereference (&lease
, MDL
);
2758 /* for now, we aren't using this. */
2763 parse_hardware_param (cfile
,
2764 &lease
-> hardware_addr
);
2767 case TOKEN_RESERVED
:
2769 lease
->flags
|= RESERVED_LEASE
;
2775 lease
-> flags
|= BOOTP_LEASE
;
2779 /* XXX: Reverse compatibility? */
2780 case TOKEN_ABANDONED
:
2782 lease
-> binding_state
= FTS_ABANDONED
;
2783 lease
-> next_binding_state
= FTS_ABANDONED
;
2789 token
= next_token (&val
, (unsigned *)0, cfile
);
2790 if (token
!= BINDING
) {
2791 parse_warn (cfile
, "expecting 'binding'");
2792 skip_to_semi (cfile
);
2795 goto do_binding_state
;
2801 token
= next_token (&val
, (unsigned *)0, cfile
);
2802 if (token
!= STATE
) {
2803 parse_warn (cfile
, "expecting 'state'");
2804 skip_to_semi (cfile
);
2807 token
= next_token (&val
, (unsigned *)0, cfile
);
2809 case TOKEN_ABANDONED
:
2810 new_state
= FTS_ABANDONED
;
2813 new_state
= FTS_FREE
;
2816 new_state
= FTS_ACTIVE
;
2819 new_state
= FTS_EXPIRED
;
2821 case TOKEN_RELEASED
:
2822 new_state
= FTS_RELEASED
;
2825 new_state
= FTS_RESET
;
2828 new_state
= FTS_BACKUP
;
2831 /* RESERVED and BOOTP states preserved for
2832 * compatiblity with older versions.
2834 case TOKEN_RESERVED
:
2835 new_state
= FTS_ACTIVE
;
2836 lease
->flags
|= RESERVED_LEASE
;
2839 new_state
= FTS_ACTIVE
;
2840 lease
->flags
|= BOOTP_LEASE
;
2845 "%s: expecting a binding state.",
2847 skip_to_semi (cfile
);
2851 if (seenbit
== 256) {
2852 lease
-> binding_state
= new_state
;
2854 /* If no next binding state is specified, it's
2855 the same as the current state. */
2856 if (!(seenmask
& 128))
2857 lease
-> next_binding_state
= new_state
;
2859 lease
-> next_binding_state
= new_state
;
2864 case CLIENT_HOSTNAME
:
2866 token
= peek_token (&val
, (unsigned *)0, cfile
);
2867 if (token
== STRING
) {
2868 if (!parse_string (cfile
,
2869 &lease
-> client_hostname
,
2871 lease_dereference (&lease
, MDL
);
2875 lease
-> client_hostname
=
2876 parse_host_name (cfile
);
2877 if (lease
-> client_hostname
)
2881 "expecting a hostname.");
2882 skip_to_semi (cfile
);
2883 lease_dereference (&lease
, MDL
);
2891 class = (struct class *)0;
2892 token
= next_token (&val
, (unsigned *)0, cfile
);
2893 if (token
== CLASS
) {
2894 token
= next_token (&val
,
2895 (unsigned *)0, cfile
);
2896 if (token
!= STRING
) {
2897 parse_warn (cfile
, "expecting string");
2899 skip_to_semi (cfile
);
2903 if (lease
-> billing_class
)
2904 class_dereference (&lease
-> billing_class
,
2906 find_class (&class, val
, MDL
);
2909 "unknown class %s", val
);
2911 } else if (token
== SUBCLASS
) {
2912 if (lease
-> billing_class
)
2913 class_dereference (&lease
-> billing_class
,
2915 parse_class_declaration(&class, cfile
, NULL
,
2916 CLASS_TYPE_SUBCLASS
);
2918 parse_warn (cfile
, "expecting \"class\"");
2920 skip_to_semi (cfile
);
2923 class_reference (&lease
-> billing_class
,
2925 class_dereference (&class, MDL
);
2930 on
= (struct executable_statement
*)0;
2932 if (!parse_on_statement (&on
, cfile
, &lose
)) {
2933 skip_to_rbrace (cfile
, 1);
2934 lease_dereference (&lease
, MDL
);
2938 if ((on
-> data
.on
.evtypes
& ON_EXPIRY
) &&
2939 on
-> data
.on
.statements
) {
2941 executable_statement_reference
2942 (&lease
-> on_expiry
,
2943 on
-> data
.on
.statements
, MDL
);
2945 if ((on
-> data
.on
.evtypes
& ON_RELEASE
) &&
2946 on
-> data
.on
.statements
) {
2948 executable_statement_reference
2949 (&lease
-> on_release
,
2950 on
-> data
.on
.statements
, MDL
);
2952 executable_statement_dereference (&on
, MDL
);
2959 oc
= (struct option_cache
*)0;
2960 if (parse_option_decl (&oc
, cfile
)) {
2961 if (oc
-> option
-> universe
!=
2964 "agent option expected.");
2965 option_cache_dereference (&oc
, MDL
);
2968 if (!lease
-> agent_options
&&
2969 !(option_chain_head_allocate
2970 (&lease
-> agent_options
, MDL
))) {
2971 log_error ("no memory to stash agent option");
2974 for (p
= &lease
-> agent_options
-> first
;
2975 *p
; p
= &((*p
) -> cdr
))
2978 option_cache_reference (((struct option_cache
**)
2979 &((*p
) -> car
)), oc
, MDL
);
2980 option_cache_dereference (&oc
, MDL
);
2987 token
= next_token (&val
, (unsigned *)0, cfile
);
2988 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2990 "%s can't be a variable name",
2993 skip_to_semi (cfile
);
2994 lease_dereference (&lease
, MDL
);
3001 binding
= find_binding (lease
-> scope
, val
);
3003 binding
= (struct binding
*)0;
3005 if (!lease
-> scope
)
3006 if (!(binding_scope_allocate
3007 (&lease
-> scope
, MDL
)))
3008 log_fatal ("no memory for scope");
3009 binding
= dmalloc (sizeof *binding
, MDL
);
3011 log_fatal ("No memory for lease %s.",
3013 memset (binding
, 0, sizeof *binding
);
3015 dmalloc (strlen (val
) + 1, MDL
);
3016 if (!binding
-> name
)
3017 log_fatal ("No memory for binding %s.",
3019 strcpy (binding
-> name
, val
);
3022 if (binding
-> value
)
3023 binding_value_dereference (&binding
-> value
,
3028 if (!binding_value_allocate (&binding
-> value
, MDL
))
3029 log_fatal ("no memory for binding value.");
3032 token
= next_token (&val
, (unsigned *)0, cfile
);
3033 if (token
!= EQUAL
) {
3035 "expecting '=' in set statement.");
3040 token
= peek_token (&val
, (unsigned *)0, cfile
);
3041 if (token
== STRING
) {
3042 unsigned char *tuid
;
3043 token
= next_token (&val
, &buflen
, cfile
);
3044 binding
-> value
-> type
= binding_data
;
3045 binding
-> value
-> value
.data
.len
= buflen
;
3046 if (!(buffer_allocate
3047 (&binding
-> value
-> value
.data
.buffer
,
3049 log_fatal ("No memory for binding.");
3051 (binding
-> value
->
3052 value
.data
.buffer
-> data
),
3054 binding
-> value
-> value
.data
.data
=
3055 binding
-> value
-> value
.data
.buffer
-> data
;
3056 binding
-> value
-> value
.data
.terminated
= 1;
3057 } else if (token
== NUMBER_OR_NAME
) {
3058 binding
-> value
-> type
= binding_data
;
3060 (parse_numeric_aggregate
3061 (cfile
, (unsigned char *)0,
3062 &binding
-> value
-> value
.data
.len
,
3065 binding_value_dereference
3066 (&binding
-> value
, MDL
);
3067 lease_dereference (&lease
, MDL
);
3070 if (binding
-> value
-> value
.data
.len
) {
3071 if (!(buffer_allocate
3072 (&binding
-> value
-> value
.data
.buffer
,
3073 binding
-> value
-> value
.data
.len
+ 1,
3075 log_fatal ("No memory for binding.");
3076 memcpy ((binding
-> value
->
3077 value
.data
.buffer
-> data
), s
,
3078 binding
-> value
-> value
.data
.len
);
3080 binding
-> value
-> value
.data
.data
=
3081 binding
-> value
-> value
.data
.buffer
-> data
;
3083 } else if (token
== PERCENT
) {
3084 token
= next_token (&val
, (unsigned *)0, cfile
);
3085 token
= next_token (&val
, (unsigned *)0, cfile
);
3086 if (token
!= NUMBER
) {
3088 "expecting decimal number.");
3090 skip_to_semi (cfile
);
3091 binding_value_dereference
3092 (&binding
-> value
, MDL
);
3093 lease_dereference (&lease
, MDL
);
3096 binding
-> value
-> type
= binding_numeric
;
3097 binding
-> value
-> value
.intval
= atol (val
);
3098 } else if (token
== NAME
) {
3099 token
= next_token (&val
,
3100 (unsigned *)0, cfile
);
3101 binding
-> value
-> type
= binding_boolean
;
3102 if (!strcasecmp (val
, "true"))
3103 binding
-> value
-> value
.boolean
= 1;
3104 else if (!strcasecmp (val
, "false"))
3105 binding
-> value
-> value
.boolean
= 0;
3111 "expecting a constant value.");
3112 skip_to_semi (cfile
);
3113 binding_value_dereference (&binding
-> value
,
3115 lease_dereference (&lease
, MDL
);
3120 binding
-> next
= lease
-> scope
-> bindings
;
3121 lease
-> scope
-> bindings
= binding
;
3127 if (!strcasecmp (val
, "ddns-fwd-name")) {
3131 } else if (!strcasecmp (val
, "ddns-rev-name")) {
3136 skip_to_semi (cfile
);
3138 lease_dereference (&lease
, MDL
);
3142 if (seenmask
& seenbit
) {
3144 "Too many %s parameters in lease %s\n",
3145 tbuf
, piaddr (lease
-> ip_addr
));
3147 seenmask
|= seenbit
;
3151 /* If no binding state is specified, make one up. */
3152 if (!(seenmask
& 256)) {
3153 if (lease
-> ends
> cur_time
||
3154 lease
-> on_expiry
|| lease
-> on_release
)
3155 lease
-> binding_state
= FTS_ACTIVE
;
3156 #if defined (FAILOVER_PROTOCOL)
3157 else if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3158 lease
-> binding_state
= FTS_EXPIRED
;
3161 lease
-> binding_state
= FTS_FREE
;
3162 if (lease
-> binding_state
== FTS_ACTIVE
) {
3163 #if defined (FAILOVER_PROTOCOL)
3164 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3165 lease
-> next_binding_state
= FTS_EXPIRED
;
3168 lease
-> next_binding_state
= FTS_FREE
;
3170 lease
-> next_binding_state
= lease
-> binding_state
;
3173 if (!(seenmask
& 65536))
3174 lease
-> tstp
= lease
-> ends
;
3176 lease_reference (lp
, lease
, MDL
);
3177 lease_dereference (&lease
, MDL
);
3181 /* address-range-declaration :== ip-address ip-address SEMI
3182 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3184 void parse_address_range (cfile
, group
, type
, inpool
, lpchain
)
3185 struct parse
*cfile
;
3186 struct group
*group
;
3188 struct pool
*inpool
;
3189 struct lease
**lpchain
;
3191 struct iaddr low
, high
, net
;
3192 unsigned char addr
[4];
3193 unsigned len
= sizeof addr
;
3194 enum dhcp_token token
;
3197 struct subnet
*subnet
;
3198 struct shared_network
*share
;
3201 isc_result_t status
;
3203 if ((token
= peek_token (&val
,
3204 (unsigned *)0, cfile
)) == DYNAMIC_BOOTP
) {
3205 token
= next_token (&val
, (unsigned *)0, cfile
);
3209 /* Get the bottom address in the range... */
3210 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3212 memcpy (low
.iabuf
, addr
, len
);
3215 /* Only one address? */
3216 token
= peek_token (&val
, (unsigned *)0, cfile
);
3220 /* Get the top address in the range... */
3221 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3223 memcpy (high
.iabuf
, addr
, len
);
3227 token
= next_token (&val
, (unsigned *)0, cfile
);
3228 if (token
!= SEMI
) {
3229 parse_warn (cfile
, "semicolon expected.");
3230 skip_to_semi (cfile
);
3234 if (type
== SUBNET_DECL
) {
3235 subnet
= group
-> subnet
;
3236 share
= subnet
-> shared_network
;
3238 share
= group
-> shared_network
;
3239 for (subnet
= share
-> subnets
;
3240 subnet
; subnet
= subnet
-> next_sibling
) {
3241 net
= subnet_number (low
, subnet
-> netmask
);
3242 if (addr_eq (net
, subnet
-> net
))
3246 parse_warn (cfile
, "address range not on network %s",
3247 group
-> shared_network
-> name
);
3248 log_error ("Be sure to place pool statement after %s",
3249 "related subnet declarations.");
3255 struct pool
*last
= (struct pool
*)0;
3257 /* If we're permitting dynamic bootp for this range,
3258 then look for a pool with an empty prohibit list and
3259 a permit list with one entry that permits all clients. */
3260 for (pool
= share
-> pools
; pool
; pool
= pool
-> next
) {
3261 if ((!dynamic
&& !pool
-> permit_list
&&
3262 pool
-> prohibit_list
&&
3263 !pool
-> prohibit_list
-> next
&&
3264 (pool
-> prohibit_list
-> type
==
3265 permit_dynamic_bootp_clients
)) ||
3266 (dynamic
&& !pool
-> prohibit_list
&&
3267 pool
-> permit_list
&&
3268 !pool
-> permit_list
-> next
&&
3269 (pool
-> permit_list
-> type
==
3270 permit_all_clients
))) {
3276 /* If we didn't get a pool, make one. */
3279 status
= pool_allocate (&pool
, MDL
);
3280 if (status
!= ISC_R_SUCCESS
)
3281 log_fatal ("no memory for ad-hoc pool: %s",
3282 isc_result_totext (status
));
3283 p
= new_permit (MDL
);
3285 log_fatal ("no memory for ad-hoc permit.");
3287 /* Dynamic pools permit all clients. Otherwise
3288 we prohibit BOOTP clients. */
3290 p
-> type
= permit_all_clients
;
3291 pool
-> permit_list
= p
;
3293 p
-> type
= permit_dynamic_bootp_clients
;
3294 pool
-> prohibit_list
= p
;
3298 pool_reference (&last
-> next
, pool
, MDL
);
3300 pool_reference (&share
-> pools
, pool
, MDL
);
3301 shared_network_reference (&pool
-> shared_network
,
3303 if (!clone_group (&pool
-> group
, share
-> group
, MDL
))
3304 log_fatal ("no memory for anon pool group.");
3306 pool
= (struct pool
*)0;
3308 pool_reference (&pool
, last
, MDL
);
3310 pool_reference (&pool
, share
-> pools
, MDL
);
3313 pool
= (struct pool
*)0;
3314 pool_reference (&pool
, inpool
, MDL
);
3317 #if defined (FAILOVER_PROTOCOL)
3318 if (pool
-> failover_peer
&& dynamic
) {
3319 /* Doctor, do you think I'm overly sensitive
3320 about getting bug reports I can't fix? */
3321 parse_warn (cfile
, "dynamic-bootp flag is %s",
3322 "not permitted for address");
3323 log_error ("range declarations where there is a failover");
3324 log_error ("peer in scope. If you wish to declare an");
3325 log_error ("address range from which dynamic bootp leases");
3326 log_error ("can be allocated, please declare it within a");
3327 log_error ("pool declaration that also contains the \"no");
3328 log_error ("failover\" statement. The failover protocol");
3329 log_error ("itself does not permit dynamic bootp - this");
3330 log_error ("is not a limitation specific to the ISC DHCP");
3331 log_error ("server. Please don't ask me to defend this");
3332 log_error ("until you have read and really tried %s",
3334 log_error ("the failover protocol specification.");
3336 /* We don't actually bomb at this point - instead,
3337 we let parse_lease_file notice the error and
3338 bomb at that point - it's easier. */
3340 #endif /* FAILOVER_PROTOCOL */
3342 /* Create the new address range... */
3343 new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
);
3344 pool_dereference (&pool
, MDL
);
3347 /* allow-deny-keyword :== BOOTP
3350 | UNKNOWN_CLIENTS */
3352 int parse_allow_deny (oc
, cfile
, flag
)
3353 struct option_cache
**oc
;
3354 struct parse
*cfile
;
3357 enum dhcp_token token
;
3359 unsigned char rf
= flag
;
3361 struct option
*option
= NULL
;
3362 struct expression
*data
= (struct expression
*)0;
3365 if (!make_const_data (&data
, &rf
, 1, 0, 1, MDL
))
3368 token
= next_token (&val
, (unsigned *)0, cfile
);
3371 code
= SV_ALLOW_BOOTP
;
3375 code
= SV_ALLOW_BOOTING
;
3379 code
= SV_DYNAMIC_BOOTP
;
3382 case UNKNOWN_CLIENTS
:
3383 code
= SV_BOOT_UNKNOWN_CLIENTS
;
3387 code
= SV_DUPLICATES
;
3394 case CLIENT_UPDATES
:
3395 code
= SV_CLIENT_UPDATES
;
3399 code
= SV_LEASEQUERY
;
3403 parse_warn (cfile
, "expecting allow/deny key");
3404 skip_to_semi (cfile
);
3407 /* Reference on option is passed to option cache. */
3408 if (!option_code_hash_lookup(&option
, server_universe
.code_hash
,
3410 log_fatal("Unable to find server option %u (%s:%d).",
3412 status
= option_cache(oc
, NULL
, data
, option
, MDL
);
3413 expression_dereference (&data
, MDL
);