3 Parser for dhcpd config file... */
6 * Copyright (c) 2004-2015 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
25 * https://www.isc.org/
29 /*! \file server/confpars.c */
33 static unsigned char global_host_once
= 1;
35 static int parse_binding_value(struct parse
*cfile
,
36 struct binding_value
*value
);
39 trace_type_t
*trace_readconf_type
;
40 trace_type_t
*trace_readleases_type
;
42 void parse_trace_setup ()
44 trace_readconf_type
= trace_type_register ("readconf", (void *)0,
46 trace_conf_stop
, MDL
);
47 trace_readleases_type
= trace_type_register ("readleases", (void *)0,
49 trace_conf_stop
, MDL
);
53 /* conf-file :== parameters declarations END_OF_FILE
54 parameters :== <nil> | parameter | parameters parameter
55 declarations :== <nil> | declaration | declarations declaration */
57 isc_result_t
readconf ()
61 res
= read_conf_file (path_dhcpd_conf
, root_group
, ROOT_GROUP
, 0);
62 #if defined(LDAP_CONFIGURATION)
63 if (res
!= ISC_R_SUCCESS
)
66 return ldap_read_config ();
72 isc_result_t
read_conf_file (const char *filename
, struct group
*group
,
73 int group_type
, int leasep
)
86 ttype
= trace_readleases_type
;
88 ttype
= trace_readconf_type
;
90 /* If we're in playback, we need to snarf the contents of the
91 named file out of the playback file rather than trying to
93 if (trace_playback ()) {
96 status
= trace_get_file (ttype
, filename
, &tflen
, &dbuf
);
97 if (status
!= ISC_R_SUCCESS
)
101 /* What we get back is filename\0contents, where contents is
102 terminated just by the length. So we figure out the length
103 of the filename, and subtract that and the NUL from the
104 total length to get the length of the contents of the file.
105 We make fbuf a pointer to the contents of the file, and
106 leave dbuf as it is so we can free it later. */
107 tflen
= strlen (dbuf
);
108 ulen
= ulen
- tflen
- 1;
109 fbuf
= dbuf
+ tflen
+ 1;
114 if ((file
= open (filename
, O_RDONLY
)) < 0) {
116 log_error ("Can't open lease database %s: %m --",
118 log_error (" check for failed database %s!",
120 log_error ("Please read the dhcpd.leases manual%s",
122 log_fatal ("don't know what to do about this.");
124 log_fatal ("Can't open %s: %m", filename
);
128 cfile
= (struct parse
*)0;
129 #if defined (TRACING)
130 flen
= lseek (file
, (off_t
)0, SEEK_END
);
133 log_fatal ("Can't lseek on %s: %m", filename
);
135 if (lseek (file
, (off_t
)0, SEEK_SET
) < 0)
137 /* Can't handle files greater than 2^31-1. */
138 if (flen
> 0x7FFFFFFFUL
)
139 log_fatal ("%s: file is too long to buffer.", filename
);
142 /* Allocate a buffer that will be what's written to the tracefile,
143 and also will be what we parse from. */
144 tflen
= strlen (filename
);
145 dbuf
= dmalloc (ulen
+ tflen
+ 1, MDL
);
147 log_fatal ("No memory for %s (%d bytes)",
150 /* Copy the name into the beginning, nul-terminated. */
151 strcpy (dbuf
, filename
);
153 /* Load the file in after the NUL. */
154 fbuf
= dbuf
+ tflen
+ 1;
155 result
= read (file
, fbuf
, ulen
);
157 log_fatal ("Can't read in %s: %m", filename
);
159 log_fatal ("%s: short read of %d bytes instead of %d.",
160 filename
, ulen
, result
);
163 /* If we're recording, write out the filename and file contents. */
165 trace_write_packet (ttype
, ulen
+ tflen
+ 1, dbuf
, MDL
);
166 status
= new_parse(&cfile
, -1, fbuf
, ulen
, filename
, 0); /* XXX */
168 status
= new_parse(&cfile
, file
, NULL
, 0, filename
, 0);
170 if (status
!= ISC_R_SUCCESS
|| cfile
== NULL
)
174 status
= lease_file_subparse (cfile
);
176 status
= conf_file_subparse (cfile
, group
, group_type
);
178 #if defined (TRACING)
184 #if defined (TRACING)
185 void trace_conf_input (trace_type_t
*ttype
, unsigned len
, char *data
)
190 struct parse
*cfile
= (struct parse
*)0;
191 static int postconf_initialized
;
192 static int leaseconf_initialized
;
195 /* Do what's done above, except that we don't have to read in the
196 data, because it's already been read for us. */
197 tflen
= strlen (data
);
198 flen
= len
- tflen
- 1;
199 fbuf
= data
+ tflen
+ 1;
201 /* If we're recording, write out the filename and file contents. */
203 trace_write_packet (ttype
, len
, data
, MDL
);
205 status
= new_parse(&cfile
, -1, fbuf
, flen
, data
, 0);
206 if (status
== ISC_R_SUCCESS
|| cfile
!= NULL
) {
207 if (ttype
== trace_readleases_type
)
208 lease_file_subparse (cfile
);
210 conf_file_subparse (cfile
, root_group
, ROOT_GROUP
);
214 /* Postconfiguration needs to be done after the config file
216 if (!postconf_initialized
&& ttype
== trace_readconf_type
) {
217 postconf_initialization (0);
218 postconf_initialized
= 1;
221 if (!leaseconf_initialized
&& ttype
== trace_readleases_type
) {
223 leaseconf_initialized
= 1;
228 void trace_conf_stop (trace_type_t
*ttype
) { }
231 /* conf-file :== parameters declarations END_OF_FILE
232 parameters :== <nil> | parameter | parameters parameter
233 declarations :== <nil> | declaration | declarations declaration */
235 isc_result_t
conf_file_subparse (struct parse
*cfile
, struct group
*group
,
239 enum dhcp_token token
;
244 token
= peek_token (&val
, (unsigned *)0, cfile
);
245 if (token
== END_OF_FILE
)
247 declaration
= parse_statement (cfile
, group
, group_type
,
248 (struct host_decl
*)0,
251 skip_token(&val
, (unsigned *)0, cfile
);
253 status
= cfile
->warnings_occurred
? DHCP_R_BADPARSE
: ISC_R_SUCCESS
;
257 /* lease-file :== lease-declarations END_OF_FILE
258 lease-statements :== <nil>
260 | lease-declarations lease-declaration */
262 isc_result_t
lease_file_subparse (struct parse
*cfile
)
265 enum dhcp_token token
;
269 token
= next_token (&val
, (unsigned *)0, cfile
);
270 if (token
== END_OF_FILE
)
272 if (token
== LEASE
) {
273 struct lease
*lease
= (struct lease
*)0;
274 if (parse_lease_declaration (&lease
, cfile
)) {
276 lease_dereference (&lease
, MDL
);
279 "possibly corrupt lease file");
280 } else if (token
== IA_NA
) {
281 parse_ia_na_declaration(cfile
);
282 } else if (token
== IA_TA
) {
283 parse_ia_ta_declaration(cfile
);
284 } else if (token
== IA_PD
) {
285 parse_ia_pd_declaration(cfile
);
286 } else if (token
== CLASS
) {
287 parse_class_declaration(0, cfile
, root_group
,
289 } else if (token
== SUBCLASS
) {
290 parse_class_declaration(0, cfile
, root_group
,
291 CLASS_TYPE_SUBCLASS
);
292 } else if (token
== HOST
) {
293 parse_host_declaration (cfile
, root_group
);
294 } else if (token
== GROUP
) {
295 parse_group_declaration (cfile
, root_group
);
296 #if defined (FAILOVER_PROTOCOL)
297 } else if (token
== FAILOVER
) {
298 parse_failover_state_declaration
299 (cfile
, (dhcp_failover_state_t
*)0);
302 } else if (token
== SERVER_DUID
) {
303 parse_server_duid(cfile
);
306 log_error ("Corrupt lease file - possible data loss!");
307 skip_to_semi (cfile
);
312 status
= cfile
->warnings_occurred
? DHCP_R_BADPARSE
: ISC_R_SUCCESS
;
316 /* statement :== parameter | declaration
318 parameter :== DEFAULT_LEASE_TIME lease_time
319 | MAX_LEASE_TIME lease_time
320 | DYNAMIC_BOOTP_LEASE_CUTOFF date
321 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
322 | BOOT_UNKNOWN_CLIENTS boolean
323 | ONE_LEASE_PER_CLIENT boolean
324 | GET_LEASE_HOSTNAMES boolean
325 | USE_HOST_DECL_NAME boolean
326 | NEXT_SERVER ip-addr-or-hostname SEMI
328 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
329 | FILENAME string-parameter
330 | SERVER_NAME string-parameter
332 | fixed-address-parameter
333 | ALLOW allow-deny-keyword
334 | DENY allow-deny-keyword
335 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
339 declaration :== host-declaration
341 | shared-network-declaration
343 | VENDOR_CLASS class-declaration
344 | USER_CLASS class-declaration
345 | RANGE address-range-declaration */
347 int parse_statement (cfile
, group
, type
, host_decl
, declaration
)
351 struct host_decl
*host_decl
;
354 enum dhcp_token token
;
356 struct shared_network
*share
;
358 struct hardware hardware
;
359 struct executable_statement
*et
, *ep
;
360 struct option
*option
= NULL
;
361 struct option_cache
*cache
;
367 token
= peek_token (&val
, (unsigned *)0, cfile
);
371 skip_token(&val
, (unsigned *)0, cfile
);
372 token
= next_token (&val
, (unsigned *)0, cfile
);
373 if (token
!= STRING
) {
374 parse_warn (cfile
, "filename string expected.");
375 skip_to_semi (cfile
);
377 status
= read_conf_file (val
, group
, type
, 0);
378 if (status
!= ISC_R_SUCCESS
)
379 parse_warn (cfile
, "%s: bad parse.", val
);
385 skip_token(&val
, (unsigned *)0, cfile
);
386 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
) {
387 if (global_host_once
&&
388 (type
== SUBNET_DECL
|| type
== SHARED_NET_DECL
)) {
389 global_host_once
= 0;
390 log_error("WARNING: Host declarations are "
391 "global. They are not limited to "
392 "the scope you declared them in.");
395 parse_host_declaration (cfile
, group
);
398 "host declarations not allowed here.");
399 skip_to_semi (cfile
);
404 skip_token(&val
, (unsigned *)0, cfile
);
405 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
406 parse_group_declaration (cfile
, group
);
409 "group declarations not allowed here.");
410 skip_to_semi (cfile
);
415 skip_token(&val
, (unsigned *)0, cfile
);
416 if (type
== SHARED_NET_DECL
||
418 type
== SUBNET_DECL
||
419 type
== CLASS_DECL
) {
420 parse_warn (cfile
, "shared-network parameters not %s.",
422 skip_to_semi (cfile
);
426 parse_shared_net_declaration (cfile
, group
);
431 skip_token(&val
, (unsigned *)0, cfile
);
432 if (type
== HOST_DECL
|| type
== SUBNET_DECL
||
433 type
== CLASS_DECL
) {
435 "subnet declarations not allowed here.");
436 skip_to_semi (cfile
);
440 /* If we're in a subnet declaration, just do the parse. */
441 if (group
->shared_network
!= NULL
) {
442 if (token
== SUBNET
) {
443 parse_subnet_declaration(cfile
,
444 group
->shared_network
);
446 parse_subnet6_declaration(cfile
,
447 group
->shared_network
);
453 * Otherwise, cons up a fake shared network structure
454 * and populate it with the lone subnet...because the
455 * intention most likely is to refer to the entire link
456 * by shorthand, any configuration inside the subnet is
457 * actually placed in the shared-network's group.
461 status
= shared_network_allocate (&share
, MDL
);
462 if (status
!= ISC_R_SUCCESS
)
463 log_fatal ("Can't allocate shared subnet: %s",
464 isc_result_totext (status
));
465 if (!clone_group (&share
-> group
, group
, MDL
))
466 log_fatal ("Can't allocate group for shared net");
467 shared_network_reference (&share
-> group
-> shared_network
,
471 * This is an implicit shared network, not explicit in
474 share
->flags
|= SHARED_IMPLICIT
;
476 if (token
== SUBNET
) {
477 parse_subnet_declaration(cfile
, share
);
479 parse_subnet6_declaration(cfile
, share
);
482 /* share -> subnets is the subnet we just parsed. */
483 if (share
->subnets
) {
484 interface_reference(&share
->interface
,
485 share
->subnets
->interface
,
488 /* Make the shared network name from network number. */
489 if (token
== SUBNET
) {
490 n
= piaddrmask(&share
->subnets
->net
,
491 &share
->subnets
->netmask
);
493 n
= piaddrcidr(&share
->subnets
->net
,
494 share
->subnets
->prefix_len
);
497 share
->name
= strdup(n
);
499 if (share
->name
== NULL
)
500 log_fatal("Out of memory allocating default "
501 "shared network name (\"%s\").", n
);
503 /* Copy the authoritative parameter from the subnet,
504 since there is no opportunity to declare it here. */
505 share
->group
->authoritative
=
506 share
->subnets
->group
->authoritative
;
507 enter_shared_network(share
);
509 shared_network_dereference(&share
, MDL
);
513 skip_token(&val
, (unsigned *)0, cfile
);
514 if (type
== CLASS_DECL
) {
516 "class declarations not allowed here.");
517 skip_to_semi (cfile
);
520 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_VENDOR
);
524 skip_token(&val
, (unsigned *)0, cfile
);
525 if (type
== CLASS_DECL
) {
527 "class declarations not allowed here.");
528 skip_to_semi (cfile
);
531 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_USER
);
535 skip_token(&val
, (unsigned *)0, cfile
);
536 if (type
== CLASS_DECL
) {
538 "class declarations not allowed here.");
539 skip_to_semi (cfile
);
542 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_CLASS
);
546 skip_token(&val
, (unsigned *)0, cfile
);
547 if (type
== CLASS_DECL
) {
549 "class declarations not allowed here.");
550 skip_to_semi (cfile
);
553 parse_class_declaration(NULL
, cfile
, group
,
554 CLASS_TYPE_SUBCLASS
);
558 skip_token(&val
, (unsigned *)0, cfile
);
559 memset (&hardware
, 0, sizeof hardware
);
560 if (host_decl
&& memcmp(&hardware
, &(host_decl
->interface
),
561 sizeof(hardware
)) != 0) {
562 parse_warn(cfile
, "Host %s hardware address already "
563 "configured.", host_decl
->name
);
567 parse_hardware_param (cfile
, &hardware
);
569 host_decl
-> interface
= hardware
;
571 parse_warn (cfile
, "hardware address parameter %s",
572 "not allowed here.");
577 skip_token(&val
, NULL
, cfile
);
579 if (parse_fixed_addr_param(&cache
, cfile
, token
)) {
581 if (host_decl
->fixed_addr
) {
582 option_cache_dereference(&cache
, MDL
);
584 "Only one fixed address "
585 "declaration per host.");
587 host_decl
->fixed_addr
= cache
;
591 "fixed-address parameter not "
593 option_cache_dereference(&cache
, MDL
);
599 skip_token(&val
, (unsigned *)0, cfile
);
600 if (type
== POOL_DECL
) {
601 parse_warn (cfile
, "pool declared within pool.");
603 } else if (type
!= SUBNET_DECL
&& type
!= SHARED_NET_DECL
) {
604 parse_warn (cfile
, "pool declared outside of network");
607 parse_pool_statement (cfile
, group
, type
);
612 skip_token(&val
, (unsigned *)0, cfile
);
613 if (type
!= SUBNET_DECL
|| !group
-> subnet
) {
615 "range declaration not allowed here.");
616 skip_to_semi (cfile
);
619 parse_address_range (cfile
, group
, type
, (struct pool
*)0,
625 skip_token(NULL
, NULL
, cfile
);
626 if ((type
!= SUBNET_DECL
) || (group
->subnet
== NULL
)) {
628 "range6 declaration not allowed here.");
632 parse_address_range6(cfile
, group
, NULL
);
636 skip_token(NULL
, NULL
, cfile
);
637 if ((type
!= SUBNET_DECL
) || (group
->subnet
== NULL
)) {
639 "prefix6 declaration not allowed here.");
643 parse_prefix6(cfile
, group
, NULL
);
647 skip_token(&val
, NULL
, cfile
);
650 "fixed-prefix6 declaration not "
655 parse_fixed_prefix6(cfile
, host_decl
);
659 skip_token(&val
, NULL
, cfile
);
660 if (type
== POOL_DECL
) {
661 parse_warn (cfile
, "pool6 declared within pool.");
663 } else if (type
!= SUBNET_DECL
) {
664 parse_warn (cfile
, "pool6 declared outside of network");
667 parse_pool6_statement (cfile
, group
, type
);
674 skip_token(&val
, (unsigned *)0, cfile
);
675 token
= next_token (&val
, (unsigned *)0, cfile
);
678 group
-> authoritative
= 0;
681 parse_warn (cfile
, "expecting assertion");
682 skip_to_semi (cfile
);
687 skip_token(&val
, (unsigned *)0, cfile
);
688 group
-> authoritative
= 1;
690 if (type
== HOST_DECL
)
691 parse_warn (cfile
, "authority makes no sense here.");
695 /* "server-identifier" is a special hack, equivalent to
696 "option dhcp-server-identifier". */
697 case SERVER_IDENTIFIER
:
698 code
= DHO_DHCP_SERVER_IDENTIFIER
;
699 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
701 log_fatal("Server identifier not in hash (%s:%d).",
703 skip_token(&val
, (unsigned *)0, cfile
);
707 skip_token(&val
, (unsigned *)0, cfile
);
708 token
= peek_token (&val
, (unsigned *)0, cfile
);
709 if (token
== SPACE
) {
710 if (type
!= ROOT_GROUP
) {
712 "option space definitions %s",
713 "may not be scoped.");
714 skip_to_semi (cfile
);
717 parse_option_space_decl (cfile
);
722 status
= parse_option_name(cfile
, 1, &known
, &option
);
723 if (status
== ISC_R_SUCCESS
) {
724 token
= peek_token (&val
, (unsigned *)0, cfile
);
726 if (type
!= ROOT_GROUP
) {
728 "option definitions%s",
729 " may not be scoped.");
730 skip_to_semi (cfile
);
731 option_dereference(&option
, MDL
);
734 skip_token(&val
, (unsigned *)0, cfile
);
737 * If the option was known, remove it from the
738 * code and name hashes before redefining it.
741 option_name_hash_delete(
742 option
->universe
->name_hash
,
743 option
->name
, 0, MDL
);
744 option_code_hash_delete(
745 option
->universe
->code_hash
,
746 &option
->code
, 0, MDL
);
749 parse_option_code_definition(cfile
, option
);
750 option_dereference(&option
, MDL
);
754 /* If this wasn't an option code definition, don't
755 allow an unknown option. */
757 parse_warn (cfile
, "unknown option %s.%s",
758 option
-> universe
-> name
,
760 skip_to_semi (cfile
);
761 option_dereference(&option
, MDL
);
766 et
= (struct executable_statement
*)0;
767 if (!parse_option_statement
768 (&et
, cfile
, 1, option
,
769 supersede_option_statement
))
771 option_dereference(&option
, MDL
);
772 goto insert_statement
;
779 if (type
!= ROOT_GROUP
&& type
!= SHARED_NET_DECL
) {
780 parse_warn (cfile
, "failover peers may only be %s",
781 "defined in shared-network");
782 log_error ("declarations and the outer scope.");
783 skip_to_semi (cfile
);
786 token
= next_token (&val
, (unsigned *)0, cfile
);
787 #if defined (FAILOVER_PROTOCOL)
788 parse_failover_peer (cfile
, group
, type
);
790 parse_warn (cfile
, "No failover support.");
791 skip_to_semi (cfile
);
797 parse_server_duid_conf(cfile
);
802 et
= (struct executable_statement
*)0;
804 if (!parse_executable_statement (&et
, cfile
, &lose
,
809 "expecting a declaration");
812 "expecting a parameter %s",
814 skip_to_semi (cfile
);
821 if (group
-> statements
) {
824 /* If this set of statements is only referenced
825 by this group, just add the current statement
826 to the end of the chain. */
827 for (ep
= group
-> statements
; ep
-> next
;
829 if (ep
-> refcnt
> 1) /* XXX */
832 executable_statement_reference (&ep
-> next
,
834 executable_statement_dereference (&et
, MDL
);
838 /* Otherwise, make a parent chain, and put the
839 current group statements first and the new
840 statement in the next pointer. */
841 ep
= (struct executable_statement
*)0;
842 if (!executable_statement_allocate (&ep
, MDL
))
843 log_fatal ("No memory for statements.");
844 ep
-> op
= statements_statement
;
845 executable_statement_reference (&ep
-> data
.statements
,
848 executable_statement_reference (&ep
-> next
, et
, MDL
);
849 executable_statement_dereference (&group
-> statements
,
851 executable_statement_reference (&group
-> statements
,
853 executable_statement_dereference (&ep
, MDL
);
855 executable_statement_reference (&group
-> statements
,
858 executable_statement_dereference (&et
, MDL
);
865 #if defined (FAILOVER_PROTOCOL)
866 void parse_failover_peer (cfile
, group
, type
)
871 enum dhcp_token token
;
873 dhcp_failover_state_t
*peer
;
878 unsigned hba_len
= sizeof hba
;
880 struct expression
*expr
;
882 dhcp_failover_config_t
*cp
;
884 token
= next_token (&val
, (unsigned *)0, cfile
);
886 parse_warn (cfile
, "expecting \"peer\"");
887 skip_to_semi (cfile
);
891 token
= next_token (&val
, (unsigned *)0, cfile
);
892 if (is_identifier (token
) || token
== STRING
) {
893 name
= dmalloc (strlen (val
) + 1, MDL
);
895 log_fatal ("no memory for peer name %s", name
);
898 parse_warn (cfile
, "expecting failover peer name.");
899 skip_to_semi (cfile
);
903 /* See if there's a peer declaration by this name. */
904 peer
= (dhcp_failover_state_t
*)0;
905 find_failover_peer (&peer
, name
, MDL
);
907 token
= next_token (&val
, (unsigned *)0, cfile
);
909 if (type
!= SHARED_NET_DECL
)
910 parse_warn (cfile
, "failover peer reference not %s",
911 "in shared-network declaration");
914 parse_warn (cfile
, "reference to unknown%s%s",
915 " failover peer ", name
);
919 dhcp_failover_state_reference
920 (&group
-> shared_network
-> failover_peer
,
923 dhcp_failover_state_dereference (&peer
, MDL
);
926 } else if (token
== STATE
) {
928 parse_warn (cfile
, "state declaration for unknown%s%s",
929 " failover peer ", name
);
933 parse_failover_state_declaration (cfile
, peer
);
934 dhcp_failover_state_dereference (&peer
, MDL
);
937 } else if (token
!= LBRACE
) {
938 parse_warn (cfile
, "expecting left brace");
939 skip_to_semi (cfile
);
942 /* Make sure this isn't a redeclaration. */
944 parse_warn (cfile
, "redeclaration of failover peer %s", name
);
945 skip_to_rbrace (cfile
, 1);
946 dhcp_failover_state_dereference (&peer
, MDL
);
951 status
= dhcp_failover_state_allocate (&peer
, MDL
);
952 if (status
!= ISC_R_SUCCESS
)
953 log_fatal ("Can't allocate failover peer %s: %s",
954 name
, isc_result_totext (status
));
962 token
= next_token (&val
, (unsigned *)0, cfile
);
968 peer
-> i_am
= primary
;
972 peer
-> i_am
= secondary
;
975 "secondary may not define %s",
976 "load balance settings.");
980 cp
= &peer
-> partner
;
984 expr
= (struct expression
*)0;
985 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
986 skip_to_rbrace (cfile
, 1);
987 dhcp_failover_state_dereference (&peer
, MDL
);
990 option_cache (&cp
-> address
,
991 (struct data_string
*)0, expr
,
992 (struct option
*)0, MDL
);
993 expression_dereference (&expr
, MDL
);
997 token
= next_token (&val
, (unsigned *)0, cfile
);
998 if (token
!= NUMBER
) {
999 parse_warn (cfile
, "expecting number");
1000 skip_to_rbrace (cfile
, 1);
1002 cp
-> port
= atoi (val
);
1005 case MAX_LEASE_MISBALANCE
:
1006 tp
= &peer
->max_lease_misbalance
;
1009 case MAX_LEASE_OWNERSHIP
:
1010 tp
= &peer
->max_lease_ownership
;
1014 tp
= &peer
->max_balance
;
1018 tp
= &peer
->min_balance
;
1021 case AUTO_PARTNER_DOWN
:
1022 tp
= &peer
->auto_partner_down
;
1025 case MAX_RESPONSE_DELAY
:
1026 tp
= &cp
-> max_response_delay
;
1028 token
= next_token (&val
, (unsigned *)0, cfile
);
1029 if (token
!= NUMBER
) {
1030 parse_warn (cfile
, "expecting number.");
1031 skip_to_rbrace (cfile
, 1);
1032 dhcp_failover_state_dereference (&peer
, MDL
);
1038 case MAX_UNACKED_UPDATES
:
1039 tp
= &cp
-> max_flying_updates
;
1048 if (peer
-> i_am
== secondary
)
1050 "secondary may not define %s",
1051 "load balance settings.");
1052 if (!parse_numeric_aggregate (cfile
, hba
, &hba_len
,
1054 skip_to_rbrace (cfile
, 1);
1055 dhcp_failover_state_dereference (&peer
, MDL
);
1058 if (hba_len
!= 32) {
1060 "HBA must be exactly 32 bytes.");
1064 peer
-> hba
= dmalloc (32, MDL
);
1066 dfree (peer
-> name
, MDL
);
1069 memcpy (peer
-> hba
, hba
, 32);
1073 token
= next_token (&val
, (unsigned *)0, cfile
);
1074 if (peer
-> i_am
== secondary
)
1076 "secondary may not define %s",
1077 "load balance settings.");
1078 if (token
!= NUMBER
) {
1079 parse_warn (cfile
, "expecting number");
1080 skip_to_rbrace (cfile
, 1);
1081 dhcp_failover_state_dereference (&peer
, MDL
);
1086 parse_warn (cfile
, "split must be between "
1087 "0 and 256, inclusive");
1089 memset (hba
, 0, sizeof hba
);
1090 for (i
= 0; i
< split
; i
++) {
1092 hba
[i
/ 8] |= (1 << (i
& 7));
1099 token
= next_token (&val
, (unsigned *)0, cfile
);
1100 if (token
!= BALANCE
) {
1101 parse_warn (cfile
, "expecting 'balance'");
1103 skip_to_rbrace (cfile
, 1);
1106 token
= next_token (&val
, (unsigned *)0, cfile
);
1107 if (token
!= TOKEN_MAX
) {
1108 parse_warn (cfile
, "expecting 'max'");
1111 token
= next_token (&val
, (unsigned *)0, cfile
);
1112 if (token
!= SECONDS
) {
1113 parse_warn (cfile
, "expecting 'secs'");
1116 token
= next_token (&val
, (unsigned *)0, cfile
);
1117 if (token
!= NUMBER
) {
1118 parse_warn (cfile
, "expecting number");
1121 peer
-> load_balance_max_secs
= atoi (val
);
1126 "invalid statement in peer declaration");
1127 skip_to_rbrace (cfile
, 1);
1128 dhcp_failover_state_dereference (&peer
, MDL
);
1131 if (token
!= RBRACE
&& !parse_semi (cfile
)) {
1132 skip_to_rbrace (cfile
, 1);
1133 dhcp_failover_state_dereference (&peer
, MDL
);
1136 } while (token
!= RBRACE
);
1138 /* me.address can be null; the failover link initiate code tries to
1139 * derive a reasonable address to use.
1141 if (!peer
-> partner
.address
)
1142 parse_warn (cfile
, "peer address may not be omitted");
1145 peer
->me
.port
= DEFAULT_FAILOVER_PORT
;
1146 if (!peer
->partner
.port
)
1147 peer
->partner
.port
= DEFAULT_FAILOVER_PORT
;
1149 if (peer
-> i_am
== primary
) {
1152 "primary failover server must have hba or split.");
1153 } else if (!peer
-> mclt
) {
1155 "primary failover server must have mclt.");
1159 if (!peer
->max_lease_misbalance
)
1160 peer
->max_lease_misbalance
= DEFAULT_MAX_LEASE_MISBALANCE
;
1161 if (!peer
->max_lease_ownership
)
1162 peer
->max_lease_ownership
= DEFAULT_MAX_LEASE_OWNERSHIP
;
1163 if (!peer
->max_balance
)
1164 peer
->max_balance
= DEFAULT_MAX_BALANCE_TIME
;
1165 if (!peer
->min_balance
)
1166 peer
->min_balance
= DEFAULT_MIN_BALANCE_TIME
;
1167 if (!peer
->me
.max_flying_updates
)
1168 peer
->me
.max_flying_updates
= DEFAULT_MAX_FLYING_UPDATES
;
1169 if (!peer
->me
.max_response_delay
)
1170 peer
->me
.max_response_delay
= DEFAULT_MAX_RESPONSE_DELAY
;
1172 if (type
== SHARED_NET_DECL
)
1173 group
->shared_network
->failover_peer
= peer
;
1175 /* Set the initial state. */
1176 if (peer
-> i_am
== primary
) {
1177 peer
-> me
.state
= recover
;
1178 peer
-> me
.stos
= cur_time
;
1179 peer
-> partner
.state
= unknown_state
;
1180 peer
-> partner
.stos
= cur_time
;
1182 peer
-> me
.state
= recover
;
1183 peer
-> me
.stos
= cur_time
;
1184 peer
-> partner
.state
= unknown_state
;
1185 peer
-> partner
.stos
= cur_time
;
1188 status
= enter_failover_peer (peer
);
1189 if (status
!= ISC_R_SUCCESS
)
1190 parse_warn (cfile
, "failover peer %s: %s",
1191 peer
-> name
, isc_result_totext (status
));
1192 dhcp_failover_state_dereference (&peer
, MDL
);
1195 void parse_failover_state_declaration (struct parse
*cfile
,
1196 dhcp_failover_state_t
*peer
)
1198 enum dhcp_token token
;
1201 dhcp_failover_state_t
*state
;
1202 dhcp_failover_config_t
*cp
;
1205 token
= next_token (&val
, (unsigned *)0, cfile
);
1206 if (token
!= PEER
) {
1207 parse_warn (cfile
, "expecting \"peer\"");
1208 skip_to_semi (cfile
);
1212 token
= next_token (&val
, (unsigned *)0, cfile
);
1213 if (is_identifier (token
) || token
== STRING
) {
1214 name
= dmalloc (strlen (val
) + 1, MDL
);
1216 log_fatal ("failover peer name %s: no memory",
1220 parse_warn (cfile
, "expecting failover peer name.");
1221 skip_to_semi (cfile
);
1225 /* See if there's a peer declaration by this name. */
1226 state
= (dhcp_failover_state_t
*)0;
1227 find_failover_peer (&state
, name
, MDL
);
1229 parse_warn (cfile
, "unknown failover peer: %s", name
);
1230 skip_to_semi (cfile
);
1234 token
= next_token (&val
, (unsigned *)0, cfile
);
1235 if (token
!= STATE
) {
1236 parse_warn (cfile
, "expecting 'state'");
1238 skip_to_semi (cfile
);
1242 state
= (dhcp_failover_state_t
*)0;
1243 dhcp_failover_state_reference (&state
, peer
, MDL
);
1245 token
= next_token (&val
, (unsigned *)0, cfile
);
1246 if (token
!= LBRACE
) {
1247 parse_warn (cfile
, "expecting left brace");
1249 skip_to_semi (cfile
);
1250 dhcp_failover_state_dereference (&state
, MDL
);
1254 token
= next_token (&val
, (unsigned *)0, cfile
);
1261 token
= next_token (&val
, (unsigned *)0, cfile
);
1262 if (token
!= STATE
) {
1263 parse_warn (cfile
, "expecting 'state'");
1266 parse_failover_state (cfile
,
1267 &cp
-> state
, &cp
-> stos
);
1271 cp
= &state
-> partner
;
1275 if (state
-> i_am
== primary
) {
1277 "mclt not valid for primary");
1280 token
= next_token (&val
, (unsigned *)0, cfile
);
1281 if (token
!= NUMBER
) {
1282 parse_warn (cfile
, "expecting a number.");
1285 state
-> mclt
= atoi (val
);
1290 parse_warn (cfile
, "expecting state setting.");
1292 skip_to_rbrace (cfile
, 1);
1293 dhcp_failover_state_dereference (&state
, MDL
);
1296 } while (token
!= RBRACE
);
1297 dhcp_failover_state_dereference (&state
, MDL
);
1300 void parse_failover_state (cfile
, state
, stos
)
1301 struct parse
*cfile
;
1302 enum failover_state
*state
;
1305 enum dhcp_token token
;
1307 enum failover_state state_in
;
1310 token
= next_token (&val
, (unsigned *)0, cfile
);
1313 state_in
= unknown_state
;
1317 state_in
= partner_down
;
1324 case COMMUNICATIONS_INTERRUPTED
:
1325 state_in
= communications_interrupted
;
1329 state_in
= conflict_done
;
1332 case RESOLUTION_INTERRUPTED
:
1333 state_in
= resolution_interrupted
;
1336 case POTENTIAL_CONFLICT
:
1337 state_in
= potential_conflict
;
1345 state_in
= recover_wait
;
1349 state_in
= recover_done
;
1353 state_in
= shut_down
;
1365 parse_warn (cfile
, "unknown failover state");
1366 skip_to_semi (cfile
);
1370 token
= next_token (&val
, (unsigned *)0, cfile
);
1371 if (token
== SEMI
) {
1375 parse_warn (cfile
, "expecting \"at\"");
1376 skip_to_semi (cfile
);
1380 stos_in
= parse_date (cfile
);
1385 /* Now that we've apparently gotten a clean parse, we
1386 can trust that this is a state that was fully committed to
1387 disk, so we can install it. */
1391 #endif /* defined (FAILOVER_PROTOCOL) */
1395 * \brief Parse allow and deny statements
1397 * This function handles the common processing code for permit and deny
1398 * statements in the parse_pool_statement and parse_pool6_statement functions.
1399 * It reads in the configuration and constructs a new permit structure that it
1400 * attachs to the permit_head passed in from the caller.
1402 * The allow or deny token should already be consumed, this function expects
1403 * one of the following:
1408 * authenticated clients;
1409 * unauthenticated clients;
1411 * dynamic bootp clients;
1412 * members of <class name>;
1415 * \param[in] cfile = the configuration file being parsed
1416 * \param[in] permit_head = the head of the permit list (permit or prohibit)
1417 * to which to attach the newly created permit structure
1418 * \param[in] is_allow = 1 if this is being invoked for an allow statement
1419 * = 0 if this is being invoked for a deny statement
1420 * \param[in] valid_from = pointers to the time values from the enclosing pool
1421 * \param[in] valid_until or pond structure. One of them will be filled in if
1422 * the configuration includes an "after" clause
1425 void get_permit(cfile
, permit_head
, is_allow
, valid_from
, valid_until
)
1426 struct parse
*cfile
;
1427 struct permit
**permit_head
;
1429 TIME
*valid_from
, *valid_until
;
1431 enum dhcp_token token
;
1432 struct permit
*permit
;
1434 int need_clients
= 1;
1437 /* Create our permit structure */
1438 permit
= new_permit(MDL
);
1440 log_fatal ("no memory for permit");
1442 token
= next_token(&val
, NULL
, cfile
);
1445 permit
->type
= permit_unknown_clients
;
1450 permit
->type
= permit_known_clients
;
1453 case UNKNOWN_CLIENTS
:
1455 permit
->type
= permit_unknown_clients
;
1459 permit
->type
= permit_known_clients
;
1463 permit
->type
= permit_authenticated_clients
;
1466 case UNAUTHENTICATED
:
1467 permit
->type
= permit_unauthenticated_clients
;
1471 permit
->type
= permit_all_clients
;
1475 permit
->type
= permit_dynamic_bootp_clients
;
1476 if (next_token (&val
, NULL
, cfile
) != TOKEN_BOOTP
) {
1477 parse_warn (cfile
, "expecting \"bootp\"");
1478 skip_to_semi (cfile
);
1479 free_permit (permit
, MDL
);
1486 if (next_token (&val
, NULL
, cfile
) != OF
) {
1487 parse_warn (cfile
, "expecting \"of\"");
1488 skip_to_semi (cfile
);
1489 free_permit (permit
, MDL
);
1492 if (next_token (&val
, NULL
, cfile
) != STRING
) {
1493 parse_warn (cfile
, "expecting class name.");
1494 skip_to_semi (cfile
);
1495 free_permit (permit
, MDL
);
1498 permit
->type
= permit_class
;
1499 permit
->class = NULL
;
1500 find_class(&permit
->class, val
, MDL
);
1502 parse_warn(cfile
, "no such class: %s", val
);
1507 if (*valid_from
|| *valid_until
) {
1508 parse_warn(cfile
, "duplicate \"after\" clause.");
1509 skip_to_semi(cfile
);
1510 free_permit(permit
, MDL
);
1513 t
= parse_date_core(cfile
);
1514 permit
->type
= permit_after
;
1524 parse_warn (cfile
, "expecting permit type.");
1525 skip_to_semi (cfile
);
1526 free_permit (permit
, MDL
);
1531 * The need_clients flag is set if we are expecting the
1534 if ((need_clients
!= 0) &&
1535 (next_token (&val
, NULL
, cfile
) != CLIENTS
)) {
1536 parse_warn (cfile
, "expecting \"clients\"");
1537 skip_to_semi (cfile
);
1538 free_permit (permit
, MDL
);
1542 while (*permit_head
)
1543 permit_head
= &((*permit_head
)->next
);
1544 *permit_head
= permit
;
1550 /* Permit_list_match returns 1 if every element of the permit list in lhs
1551 also appears in rhs. Note that this doesn't by itself mean that the
1552 two lists are equal - to check for equality, permit_list_match has to
1553 return 1 with (list1, list2) and with (list2, list1). */
1555 int permit_list_match (struct permit
*lhs
, struct permit
*rhs
)
1557 struct permit
*plp
, *prp
;
1564 for (plp
= lhs
; plp
; plp
= plp
-> next
) {
1566 for (prp
= rhs
; prp
; prp
= prp
-> next
) {
1567 if (prp
-> type
== plp
-> type
&&
1568 (prp
-> type
!= permit_class
||
1569 prp
-> class == plp
-> class)) {
1582 * \brief Parse a pool statement
1584 * Pool statements are used to group declarations and permit & deny information
1585 * with a specific address range. They must be declared within a shared network
1586 * or subnet and there may be multiple pools withing a shared network or subnet.
1587 * Each pool may have a different set of permit or deny options.
1589 * \param[in] cfile = the configuration file being parsed
1590 * \param[in] group = the group structure for this pool
1591 * \param[in] type = the type of the enclosing statement. This must be
1592 * SHARED_NET_DECL or SUBNET_DECL for this function.
1595 * void - This function either parses the statement and updates the structures
1596 * or it generates an error message and possible halts the program if
1597 * it encounters a problem.
1599 void parse_pool_statement (cfile
, group
, type
)
1600 struct parse
*cfile
;
1601 struct group
*group
;
1604 enum dhcp_token token
;
1607 struct pool
*pool
, **p
, *pp
;
1608 int declaration
= 0;
1609 isc_result_t status
;
1610 struct lease
*lpchain
= NULL
, *lp
;
1613 status
= pool_allocate(&pool
, MDL
);
1614 if (status
!= ISC_R_SUCCESS
)
1615 log_fatal ("no memory for pool: %s",
1616 isc_result_totext (status
));
1618 if (type
== SUBNET_DECL
)
1619 shared_network_reference(&pool
->shared_network
,
1620 group
->subnet
->shared_network
,
1622 else if (type
== SHARED_NET_DECL
)
1623 shared_network_reference(&pool
->shared_network
,
1624 group
->shared_network
, MDL
);
1626 parse_warn(cfile
, "Dynamic pools are only valid inside "
1627 "subnet or shared-network statements.");
1628 skip_to_semi(cfile
);
1632 if (pool
->shared_network
== NULL
||
1633 !clone_group(&pool
->group
, pool
->shared_network
->group
, MDL
))
1634 log_fatal("can't clone pool group.");
1636 #if defined (FAILOVER_PROTOCOL)
1637 /* Inherit the failover peer from the shared network. */
1638 if (pool
->shared_network
->failover_peer
)
1639 dhcp_failover_state_reference
1640 (&pool
->failover_peer
,
1641 pool
->shared_network
->failover_peer
, MDL
);
1644 if (!parse_lbrace(cfile
)) {
1645 pool_dereference(&pool
, MDL
);
1650 token
= peek_token(&val
, NULL
, cfile
);
1653 skip_token(&val
, NULL
, cfile
);
1654 token
= next_token(&val
, NULL
, cfile
);
1655 if (token
!= FAILOVER
||
1656 (token
= next_token(&val
, NULL
, cfile
)) != PEER
) {
1658 "expecting \"failover peer\".");
1659 skip_to_semi(cfile
);
1662 #if defined (FAILOVER_PROTOCOL)
1663 if (pool
->failover_peer
)
1664 dhcp_failover_state_dereference
1665 (&pool
->failover_peer
, MDL
);
1669 #if defined (FAILOVER_PROTOCOL)
1671 skip_token(&val
, NULL
, cfile
);
1672 token
= next_token (&val
, NULL
, cfile
);
1673 if (token
!= PEER
) {
1674 parse_warn(cfile
, "expecting 'peer'.");
1675 skip_to_semi(cfile
);
1678 token
= next_token(&val
, NULL
, cfile
);
1679 if (token
!= STRING
) {
1680 parse_warn(cfile
, "expecting string.");
1681 skip_to_semi(cfile
);
1684 if (pool
->failover_peer
)
1685 dhcp_failover_state_dereference
1686 (&pool
->failover_peer
, MDL
);
1687 status
= find_failover_peer(&pool
->failover_peer
,
1689 if (status
!= ISC_R_SUCCESS
)
1691 "failover peer %s: %s", val
,
1692 isc_result_totext (status
));
1694 pool
->failover_peer
->pool_count
++;
1700 skip_token(&val
, NULL
, cfile
);
1701 parse_address_range (cfile
, group
, type
,
1705 skip_token(&val
, NULL
, cfile
);
1706 get_permit(cfile
, &pool
->permit_list
, 1,
1707 &pool
->valid_from
, &pool
->valid_until
);
1711 skip_token(&val
, NULL
, cfile
);
1712 get_permit(cfile
, &pool
->prohibit_list
, 0,
1713 &pool
->valid_from
, &pool
->valid_until
);
1717 skip_token(&val
, NULL
, cfile
);
1723 * We can get to END_OF_FILE if, for instance,
1724 * the parse_statement() reads all available tokens
1725 * and leaves us at the end.
1727 parse_warn(cfile
, "unexpected end of file");
1731 declaration
= parse_statement(cfile
, pool
->group
,
1738 /* See if there's already a pool into which we can merge this one. */
1739 for (pp
= pool
->shared_network
->pools
; pp
; pp
= pp
->next
) {
1740 if (pp
->group
->statements
!= pool
->group
->statements
)
1742 #if defined (FAILOVER_PROTOCOL)
1743 if (pool
->failover_peer
!= pp
->failover_peer
)
1746 if (!permit_list_match(pp
->permit_list
,
1747 pool
->permit_list
) ||
1748 !permit_list_match(pool
->permit_list
,
1750 !permit_list_match(pp
->prohibit_list
,
1751 pool
->prohibit_list
) ||
1752 !permit_list_match(pool
->prohibit_list
,
1756 /* Okay, we can merge these two pools. All we have to
1757 do is fix up the leases, which all point to their pool. */
1758 for (lp
= lpchain
; lp
; lp
= lp
->next
) {
1759 pool_dereference(&lp
->pool
, MDL
);
1760 pool_reference(&lp
->pool
, pp
, MDL
);
1765 /* If we didn't succeed in merging this pool into another, put
1768 p
= &pool
->shared_network
->pools
;
1769 for (; *p
; p
= &((*p
)->next
))
1771 pool_reference(p
, pool
, MDL
);
1774 /* Don't allow a pool declaration with no addresses, since it is
1775 probably a configuration error. */
1777 parse_warn(cfile
, "Pool declaration with no address range.");
1778 log_error("Pool declarations must always contain at least");
1779 log_error("one range statement.");
1783 /* Dereference the lease chain. */
1786 lease_reference(&lp
, lpchain
, MDL
);
1787 lease_dereference(&lpchain
, MDL
);
1789 lease_reference(&lpchain
, lp
->next
, MDL
);
1790 lease_dereference(&lp
->next
, MDL
);
1791 lease_dereference(&lp
, MDL
);
1794 pool_dereference(&pool
, MDL
);
1797 /* Expect a left brace; if there isn't one, skip over the rest of the
1798 statement and return zero; otherwise, return 1. */
1800 int parse_lbrace (cfile
)
1801 struct parse
*cfile
;
1803 enum dhcp_token token
;
1806 token
= next_token (&val
, (unsigned *)0, cfile
);
1807 if (token
!= LBRACE
) {
1808 parse_warn (cfile
, "expecting left brace.");
1809 skip_to_semi (cfile
);
1816 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1818 void parse_host_declaration (cfile
, group
)
1819 struct parse
*cfile
;
1820 struct group
*group
;
1823 enum dhcp_token token
;
1824 struct host_decl
*host
;
1826 int declaration
= 0;
1829 isc_result_t status
;
1831 struct option
*option
;
1832 struct expression
*expr
= NULL
;
1834 name
= parse_host_name (cfile
);
1836 parse_warn (cfile
, "expecting a name for host declaration.");
1837 skip_to_semi (cfile
);
1841 host
= (struct host_decl
*)0;
1842 status
= host_allocate (&host
, MDL
);
1843 if (status
!= ISC_R_SUCCESS
)
1844 log_fatal ("can't allocate host decl struct %s: %s",
1845 name
, isc_result_totext (status
));
1846 host
-> name
= name
;
1847 if (!clone_group (&host
-> group
, group
, MDL
)) {
1848 log_fatal ("can't clone group for host %s", name
);
1850 host_dereference (&host
, MDL
);
1854 if (!parse_lbrace (cfile
))
1858 token
= peek_token (&val
, (unsigned *)0, cfile
);
1859 if (token
== RBRACE
) {
1860 skip_token(&val
, (unsigned *)0, cfile
);
1863 if (token
== END_OF_FILE
) {
1864 skip_token(&val
, (unsigned *)0, cfile
);
1865 parse_warn (cfile
, "unexpected end of file");
1868 /* If the host declaration was created by the server,
1869 remember to save it. */
1870 if (token
== DYNAMIC
) {
1872 skip_token(&val
, (unsigned *)0, cfile
);
1873 if (!parse_semi (cfile
))
1877 /* If the host declaration was created by the server,
1878 remember to save it. */
1879 if (token
== TOKEN_DELETED
) {
1881 skip_token(&val
, (unsigned *)0, cfile
);
1882 if (!parse_semi (cfile
))
1887 if (token
== GROUP
) {
1888 struct group_object
*go
;
1889 skip_token(&val
, (unsigned *)0, cfile
);
1890 token
= next_token (&val
, (unsigned *)0, cfile
);
1891 if (token
!= STRING
&& !is_identifier (token
)) {
1893 "expecting string or identifier.");
1894 skip_to_rbrace (cfile
, 1);
1897 go
= (struct group_object
*)0;
1898 if (!group_hash_lookup (&go
, group_name_hash
,
1899 val
, strlen (val
), MDL
)) {
1900 parse_warn (cfile
, "unknown group %s in host %s",
1903 if (host
-> named_group
)
1904 group_object_dereference
1905 (&host
-> named_group
, MDL
);
1906 group_object_reference (&host
-> named_group
,
1908 group_object_dereference (&go
, MDL
);
1910 if (!parse_semi (cfile
))
1917 unsigned char *t
= 0;
1920 skip_token(&val
, (unsigned *)0, cfile
);
1921 data_string_forget (&host
-> client_identifier
, MDL
);
1923 if (host
->client_identifier
.len
!= 0) {
1924 parse_warn(cfile
, "Host %s already has a "
1925 "client identifier.",
1930 /* See if it's a string or a cshl. */
1931 token
= peek_token (&val
, (unsigned *)0, cfile
);
1932 if (token
== STRING
) {
1933 skip_token(&val
, &len
, cfile
);
1935 host
-> client_identifier
.terminated
= 1;
1938 t
= parse_numeric_aggregate
1940 (unsigned char *)0, &len
, ':', 16, 8);
1943 "expecting hex list.");
1944 skip_to_semi (cfile
);
1946 s
= (const char *)t
;
1948 if (!buffer_allocate
1949 (&host
-> client_identifier
.buffer
,
1950 len
+ host
-> client_identifier
.terminated
, MDL
))
1951 log_fatal ("no memory for uid for host %s.",
1953 host
-> client_identifier
.data
=
1954 host
-> client_identifier
.buffer
-> data
;
1955 host
-> client_identifier
.len
= len
;
1956 memcpy (host
-> client_identifier
.buffer
-> data
, s
,
1957 len
+ host
-> client_identifier
.terminated
);
1961 if (!parse_semi (cfile
))
1966 if (token
== HOST_IDENTIFIER
) {
1967 if (host
->host_id_option
!= NULL
) {
1969 "only one host-identifier allowed "
1971 skip_to_rbrace(cfile
, 1);
1974 skip_token(&val
, NULL
, cfile
);
1975 token
= next_token(&val
, NULL
, cfile
);
1976 if (token
== V6RELOPT
) {
1977 token
= next_token(&val
, NULL
, cfile
);
1978 if (token
!= NUMBER
) {
1980 "host-identifier v6relopt "
1981 "must have a number");
1982 skip_to_rbrace(cfile
, 1);
1985 host
->relays
= atoi(val
);
1986 if (host
->relays
< 0) {
1988 "host-identifier v6relopt "
1989 "must have a number >= 0");
1990 skip_to_rbrace(cfile
, 1);
1993 } else if (token
!= OPTION
) {
1995 "host-identifier must be an option"
1997 skip_to_rbrace(cfile
, 1);
2002 status
= parse_option_name(cfile
, 1, &known
, &option
);
2003 if ((status
!= ISC_R_SUCCESS
) || (option
== NULL
)) {
2007 parse_warn(cfile
, "unknown option %s.%s",
2008 option
->universe
->name
,
2010 skip_to_rbrace(cfile
, 1);
2014 if (! parse_option_data(&expr
, cfile
, 1, option
)) {
2015 skip_to_rbrace(cfile
, 1);
2016 option_dereference(&option
, MDL
);
2020 if (!parse_semi(cfile
)) {
2021 skip_to_rbrace(cfile
, 1);
2022 expression_dereference(&expr
, MDL
);
2023 option_dereference(&option
, MDL
);
2027 option_reference(&host
->host_id_option
, option
, MDL
);
2028 option_dereference(&option
, MDL
);
2029 data_string_copy(&host
->host_id
,
2030 &expr
->data
.const_data
, MDL
);
2031 expression_dereference(&expr
, MDL
);
2035 declaration
= parse_statement(cfile
, host
->group
, HOST_DECL
,
2040 struct host_decl
*hp
= (struct host_decl
*)0;
2041 if (host_hash_lookup (&hp
, host_name_hash
,
2042 (unsigned char *)host
-> name
,
2043 strlen (host
-> name
), MDL
)) {
2044 delete_host (hp
, 0);
2045 host_dereference (&hp
, MDL
);
2048 if (host
-> named_group
&& host
-> named_group
-> group
) {
2049 if (host
-> group
-> statements
||
2050 (host
-> group
-> authoritative
!=
2051 host
-> named_group
-> group
-> authoritative
)) {
2052 if (host
-> group
-> next
)
2053 group_dereference (&host
-> group
-> next
,
2055 group_reference (&host
-> group
-> next
,
2056 host
-> named_group
-> group
,
2059 group_dereference (&host
-> group
, MDL
);
2060 group_reference (&host
-> group
,
2061 host
-> named_group
-> group
,
2067 host
-> flags
|= HOST_DECL_DYNAMIC
;
2069 host
-> flags
|= HOST_DECL_STATIC
;
2071 status
= enter_host (host
, dynamicp
, 0);
2072 if (status
!= ISC_R_SUCCESS
)
2073 parse_warn (cfile
, "host %s: %s", host
-> name
,
2074 isc_result_totext (status
));
2076 host_dereference (&host
, MDL
);
2079 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
2082 int parse_class_declaration (cp
, cfile
, group
, type
)
2084 struct parse
*cfile
;
2085 struct group
*group
;
2089 enum dhcp_token token
;
2090 struct class *class = NULL
, *pc
= NULL
;
2091 int declaration
= 0;
2093 struct data_string data
;
2096 struct executable_statement
*stmt
= NULL
;
2098 isc_result_t status
= ISC_R_FAILURE
;
2099 int matchedonce
= 0;
2100 int submatchedonce
= 0;
2103 token
= next_token (&val
, NULL
, cfile
);
2104 if (token
!= STRING
) {
2105 parse_warn (cfile
, "Expecting class name");
2106 skip_to_semi (cfile
);
2110 /* See if there's already a class with the specified name. */
2111 find_class (&pc
, val
, MDL
);
2113 /* If it is a class, we're updating it. If it's any of the other
2114 * types (subclass, vendor or user class), the named class is a
2115 * reference to the parent class so its mandatory.
2117 if (pc
&& (type
== CLASS_TYPE_CLASS
)) {
2118 class_reference(&class, pc
, MDL
);
2120 class_dereference(&pc
, MDL
);
2121 } else if (!pc
&& (type
!= CLASS_TYPE_CLASS
)) {
2122 parse_warn(cfile
, "no class named %s", val
);
2123 skip_to_semi(cfile
);
2127 /* The old vendor-class and user-class declarations had an implicit
2128 match. We don't do the implicit match anymore. Instead, for
2129 backward compatibility, we have an implicit-vendor-class and an
2130 implicit-user-class. vendor-class and user-class declarations
2131 are turned into subclasses of the implicit classes, and the
2132 submatch expression of the implicit classes extracts the contents of
2133 the vendor class or user class. */
2134 if ((type
== CLASS_TYPE_VENDOR
) || (type
== CLASS_TYPE_USER
)) {
2135 data
.len
= strlen (val
);
2137 if (!buffer_allocate (&data
.buffer
, data
.len
+ 1, MDL
))
2138 log_fatal ("no memory for class name.");
2139 data
.data
= &data
.buffer
-> data
[0];
2140 data
.terminated
= 1;
2142 tname
= type
? "implicit-vendor-class" : "implicit-user-class";
2143 } else if (type
== CLASS_TYPE_CLASS
) {
2150 name
= dmalloc (strlen (tname
) + 1, MDL
);
2152 log_fatal ("No memory for class name %s.", tname
);
2157 /* If this is a straight subclass, parse the hash string. */
2158 if (type
== CLASS_TYPE_SUBCLASS
) {
2159 token
= peek_token (&val
, NULL
, cfile
);
2160 if (token
== STRING
) {
2161 skip_token(&val
, &data
.len
, cfile
);
2164 if (!buffer_allocate (&data
.buffer
,
2165 data
.len
+ 1, MDL
)) {
2167 class_dereference (&pc
, MDL
);
2171 data
.terminated
= 1;
2172 data
.data
= &data
.buffer
-> data
[0];
2173 memcpy ((char *)data
.buffer
-> data
, val
,
2175 } else if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
2176 memset (&data
, 0, sizeof data
);
2177 if (!parse_cshl (&data
, cfile
)) {
2179 class_dereference (&pc
, MDL
);
2183 parse_warn (cfile
, "Expecting string or hex list.");
2185 class_dereference (&pc
, MDL
);
2190 /* See if there's already a class in the hash table matching the
2192 if (type
!= CLASS_TYPE_CLASS
)
2193 class_hash_lookup (&class, pc
-> hash
,
2194 (const char *)data
.data
, data
.len
, MDL
);
2196 /* If we didn't find an existing class, allocate a new one. */
2198 /* Allocate the class structure... */
2199 if (type
== CLASS_TYPE_SUBCLASS
) {
2200 status
= subclass_allocate (&class, MDL
);
2202 status
= class_allocate (&class, MDL
);
2205 group_reference (&class -> group
, pc
-> group
, MDL
);
2206 class_reference (&class -> superclass
, pc
, MDL
);
2207 class -> lease_limit
= pc
-> lease_limit
;
2208 if (class -> lease_limit
) {
2209 class -> billed_leases
=
2210 dmalloc (class -> lease_limit
*
2211 sizeof (struct lease
*), MDL
);
2212 if (!class -> billed_leases
)
2213 log_fatal ("no memory for billing");
2214 memset (class -> billed_leases
, 0,
2215 (class -> lease_limit
*
2216 sizeof (struct lease
*)));
2218 data_string_copy (&class -> hash_string
, &data
, MDL
);
2220 !class_new_hash (&pc
->hash
, SCLASS_HASH_SIZE
, MDL
))
2221 log_fatal ("No memory for subclass hash.");
2222 class_hash_add (pc
-> hash
,
2223 (const char *)class -> hash_string
.data
,
2224 class -> hash_string
.len
,
2225 (void *)class, MDL
);
2228 group_dereference(&class->group
, MDL
);
2229 if (!clone_group (&class -> group
, group
, MDL
))
2230 log_fatal ("no memory to clone class group.");
2233 /* If this is an implicit vendor or user class, add a
2234 statement that causes the vendor or user class ID to
2235 be sent back in the reply. */
2236 if (type
== CLASS_TYPE_VENDOR
|| type
== CLASS_TYPE_USER
) {
2238 if (!executable_statement_allocate (&stmt
, MDL
))
2239 log_fatal ("no memory for class statement.");
2240 stmt
-> op
= supersede_option_statement
;
2241 if (option_cache_allocate (&stmt
-> data
.option
,
2243 stmt
-> data
.option
-> data
= data
;
2244 code
= (type
== CLASS_TYPE_VENDOR
)
2245 ? DHO_VENDOR_CLASS_IDENTIFIER
2247 option_code_hash_lookup(
2248 &stmt
->data
.option
->option
,
2249 dhcp_universe
.code_hash
,
2252 class -> statements
= stmt
;
2255 /* Save the name, if there is one. */
2256 if (class->name
!= NULL
)
2257 dfree(class->name
, MDL
);
2261 if (type
!= CLASS_TYPE_CLASS
)
2262 data_string_forget(&data
, MDL
);
2264 /* Spawned classes don't have to have their own settings. */
2265 if (class -> superclass
) {
2266 token
= peek_token (&val
, NULL
, cfile
);
2267 if (token
== SEMI
) {
2268 skip_token(&val
, NULL
, cfile
);
2271 status
= class_reference (cp
, class, MDL
);
2272 class_dereference (&class, MDL
);
2274 class_dereference (&pc
, MDL
);
2275 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2277 /* Give the subclass its own group. */
2278 if (!clone_group (&class -> group
, class -> group
, MDL
))
2279 log_fatal ("can't clone class group.");
2283 if (!parse_lbrace (cfile
)) {
2284 class_dereference (&class, MDL
);
2286 class_dereference (&pc
, MDL
);
2291 token
= peek_token (&val
, NULL
, cfile
);
2292 if (token
== RBRACE
) {
2293 skip_token(&val
, NULL
, cfile
);
2295 } else if (token
== END_OF_FILE
) {
2296 skip_token(&val
, NULL
, cfile
);
2297 parse_warn (cfile
, "unexpected end of file");
2299 } else if (token
== DYNAMIC
) {
2300 class->flags
|= CLASS_DECL_DYNAMIC
;
2301 skip_token(&val
, NULL
, cfile
);
2302 if (!parse_semi (cfile
))
2305 } else if (token
== TOKEN_DELETED
) {
2306 class->flags
|= CLASS_DECL_DELETED
;
2307 skip_token(&val
, NULL
, cfile
);
2308 if (!parse_semi (cfile
))
2311 } else if (token
== MATCH
) {
2314 "invalid match in subclass.");
2315 skip_to_semi (cfile
);
2318 skip_token(&val
, NULL
, cfile
);
2319 token
= peek_token (&val
, NULL
, cfile
);
2322 skip_token(&val
, NULL
, cfile
);
2324 parse_warn(cfile
, "A class may only have "
2325 "one 'match if' clause.");
2326 skip_to_semi(cfile
);
2331 expression_dereference(&class->expr
, MDL
);
2332 if (!parse_boolean_expression (&class->expr
, cfile
,
2336 "expecting boolean expr.");
2337 skip_to_semi (cfile
);
2340 #if defined (DEBUG_EXPRESSION_PARSE)
2341 print_expression ("class match",
2346 } else if (token
== SPAWN
) {
2347 skip_token(&val
, NULL
, cfile
);
2350 "invalid spawn in subclass.");
2351 skip_to_semi (cfile
);
2354 class -> spawning
= 1;
2355 token
= next_token (&val
, NULL
, cfile
);
2356 if (token
!= WITH
) {
2358 "expecting with after spawn");
2359 skip_to_semi (cfile
);
2363 if (submatchedonce
) {
2365 "can't override existing %s.",
2367 skip_to_semi (cfile
);
2371 if (class->submatch
)
2372 expression_dereference(&class->submatch
, MDL
);
2373 if (!parse_data_expression (&class -> submatch
,
2377 "expecting data expr.");
2378 skip_to_semi (cfile
);
2381 #if defined (DEBUG_EXPRESSION_PARSE)
2382 print_expression ("class submatch",
2387 } else if (token
== LEASE
) {
2388 skip_token(&val
, NULL
, cfile
);
2389 token
= next_token (&val
, NULL
, cfile
);
2390 if (token
!= LIMIT
) {
2391 parse_warn (cfile
, "expecting \"limit\"");
2393 skip_to_semi (cfile
);
2396 token
= next_token (&val
, NULL
, cfile
);
2397 if (token
!= NUMBER
) {
2398 parse_warn (cfile
, "expecting a number");
2400 skip_to_semi (cfile
);
2403 class -> lease_limit
= atoi (val
);
2404 if (class->billed_leases
)
2405 dfree(class->billed_leases
, MDL
);
2406 class -> billed_leases
=
2407 dmalloc (class -> lease_limit
*
2408 sizeof (struct lease
*), MDL
);
2409 if (!class -> billed_leases
)
2410 log_fatal ("no memory for billed leases.");
2411 memset (class -> billed_leases
, 0,
2412 (class -> lease_limit
*
2413 sizeof (struct lease
*)));
2414 have_billing_classes
= 1;
2417 declaration
= parse_statement (cfile
, class -> group
,
2423 if (class->flags
& CLASS_DECL_DELETED
) {
2424 if (type
== CLASS_TYPE_CLASS
) {
2425 struct class *theclass
= NULL
;
2427 status
= find_class(&theclass
, class->name
, MDL
);
2428 if (status
== ISC_R_SUCCESS
) {
2429 delete_class(theclass
, 0);
2430 class_dereference(&theclass
, MDL
);
2433 class_hash_delete(pc
->hash
,
2434 (char *)class->hash_string
.data
,
2435 class->hash_string
.len
, MDL
);
2437 } else if (type
== CLASS_TYPE_CLASS
&& new) {
2438 if (!collections
-> classes
)
2439 class_reference (&collections
-> classes
, class, MDL
);
2442 for (c
= collections
-> classes
;
2443 c
-> nic
; c
= c
-> nic
)
2445 class_reference (&c
-> nic
, class, MDL
);
2449 if (cp
) /* should always be 0??? */
2450 status
= class_reference (cp
, class, MDL
);
2451 class_dereference (&class, MDL
);
2453 class_dereference (&pc
, MDL
);
2454 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2457 /* shared-network-declaration :==
2458 hostname LBRACE declarations parameters RBRACE */
2460 void parse_shared_net_declaration (cfile
, group
)
2461 struct parse
*cfile
;
2462 struct group
*group
;
2465 enum dhcp_token token
;
2466 struct shared_network
*share
;
2468 int declaration
= 0;
2469 isc_result_t status
;
2471 share
= (struct shared_network
*)0;
2472 status
= shared_network_allocate (&share
, MDL
);
2473 if (status
!= ISC_R_SUCCESS
)
2474 log_fatal ("Can't allocate shared subnet: %s",
2475 isc_result_totext (status
));
2476 if (clone_group (&share
-> group
, group
, MDL
) == 0) {
2477 log_fatal ("Can't clone group for shared net");
2479 shared_network_reference (&share
-> group
-> shared_network
,
2482 /* Get the name of the shared network... */
2483 token
= peek_token (&val
, (unsigned *)0, cfile
);
2484 if (token
== STRING
) {
2485 skip_token(&val
, (unsigned *)0, cfile
);
2488 parse_warn (cfile
, "zero-length shared network name");
2489 val
= "<no-name-given>";
2491 name
= dmalloc (strlen (val
) + 1, MDL
);
2493 log_fatal ("no memory for shared network name");
2496 name
= parse_host_name (cfile
);
2499 "expecting a name for shared-network");
2500 skip_to_semi (cfile
);
2501 shared_network_dereference (&share
, MDL
);
2505 share
-> name
= name
;
2507 if (!parse_lbrace (cfile
)) {
2508 shared_network_dereference (&share
, MDL
);
2513 token
= peek_token (&val
, (unsigned *)0, cfile
);
2514 if (token
== RBRACE
) {
2515 skip_token(&val
, (unsigned *)0, cfile
);
2516 if (!share
-> subnets
)
2518 "empty shared-network decl");
2520 enter_shared_network (share
);
2521 shared_network_dereference (&share
, MDL
);
2523 } else if (token
== END_OF_FILE
) {
2524 skip_token(&val
, (unsigned *)0, cfile
);
2525 parse_warn (cfile
, "unexpected end of file");
2527 } else if (token
== INTERFACE
) {
2528 skip_token(&val
, (unsigned *)0, cfile
);
2529 token
= next_token (&val
, (unsigned *)0, cfile
);
2530 new_shared_network_interface (cfile
, share
, val
);
2531 if (!parse_semi (cfile
))
2536 declaration
= parse_statement (cfile
, share
-> group
,
2538 (struct host_decl
*)0,
2541 shared_network_dereference (&share
, MDL
);
2546 common_subnet_parsing(struct parse
*cfile
,
2547 struct shared_network
*share
,
2548 struct subnet
*subnet
) {
2549 enum dhcp_token token
;
2550 struct subnet
*t
, *u
;
2552 int declaration
= 0;
2554 enter_subnet(subnet
);
2556 if (!parse_lbrace(cfile
)) {
2557 subnet_dereference(&subnet
, MDL
);
2562 token
= peek_token(&val
, NULL
, cfile
);
2563 if (token
== RBRACE
) {
2564 skip_token(&val
, NULL
, cfile
);
2566 } else if (token
== END_OF_FILE
) {
2567 skip_token(&val
, NULL
, cfile
);
2568 parse_warn (cfile
, "unexpected end of file");
2570 } else if (token
== INTERFACE
) {
2571 skip_token(&val
, NULL
, cfile
);
2572 token
= next_token(&val
, NULL
, cfile
);
2573 new_shared_network_interface(cfile
, share
, val
);
2574 if (!parse_semi(cfile
))
2578 declaration
= parse_statement(cfile
, subnet
->group
,
2584 /* Add the subnet to the list of subnets in this shared net. */
2585 if (share
->subnets
== NULL
) {
2586 subnet_reference(&share
->subnets
, subnet
, MDL
);
2589 for (t
= share
->subnets
; t
->next_sibling
; t
= t
->next_sibling
) {
2590 if (subnet_inner_than(subnet
, t
, 0)) {
2591 subnet_reference(&subnet
->next_sibling
, t
, MDL
);
2593 subnet_dereference(&u
->next_sibling
,
2595 subnet_reference(&u
->next_sibling
,
2598 subnet_dereference(&share
->subnets
,
2600 subnet_reference(&share
->subnets
,
2603 subnet_dereference(&subnet
, MDL
);
2608 subnet_reference(&t
->next_sibling
, subnet
, MDL
);
2610 subnet_dereference(&subnet
, MDL
);
2614 /* subnet-declaration :==
2615 net NETMASK netmask RBRACE parameters declarations LBRACE */
2617 void parse_subnet_declaration (cfile
, share
)
2618 struct parse
*cfile
;
2619 struct shared_network
*share
;
2622 enum dhcp_token token
;
2623 struct subnet
*subnet
;
2625 unsigned char addr
[4];
2626 unsigned len
= sizeof addr
;
2627 isc_result_t status
;
2629 subnet
= (struct subnet
*)0;
2630 status
= subnet_allocate (&subnet
, MDL
);
2631 if (status
!= ISC_R_SUCCESS
)
2632 log_fatal ("Allocation of new subnet failed: %s",
2633 isc_result_totext (status
));
2634 shared_network_reference (&subnet
-> shared_network
, share
, MDL
);
2637 * If our parent shared network was implicitly created by the software,
2638 * and not explicitly configured by the user, then we actually put all
2639 * configuration scope in the parent (the shared network and subnet
2640 * share the same {}-level scope).
2642 * Otherwise, we clone the parent group and continue as normal.
2644 if (share
->flags
& SHARED_IMPLICIT
) {
2645 group_reference(&subnet
->group
, share
->group
, MDL
);
2647 if (!clone_group(&subnet
->group
, share
->group
, MDL
)) {
2648 log_fatal("Allocation of group for new subnet failed.");
2651 subnet_reference (&subnet
-> group
-> subnet
, subnet
, MDL
);
2653 /* Get the network number... */
2654 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2655 subnet_dereference (&subnet
, MDL
);
2658 memcpy (iaddr
.iabuf
, addr
, len
);
2660 subnet
-> net
= iaddr
;
2662 token
= next_token (&val
, (unsigned *)0, cfile
);
2663 if (token
!= NETMASK
) {
2664 parse_warn (cfile
, "Expecting netmask");
2665 skip_to_semi (cfile
);
2669 /* Get the netmask... */
2670 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2671 subnet_dereference (&subnet
, MDL
);
2674 memcpy (iaddr
.iabuf
, addr
, len
);
2676 subnet
-> netmask
= iaddr
;
2678 /* Validate the network number/netmask pair. */
2679 if (host_addr (subnet
-> net
, subnet
-> netmask
)) {
2682 maskstr
= strdup (piaddr (subnet
-> netmask
));
2684 "subnet %s netmask %s: bad subnet number/mask combination.",
2685 piaddr (subnet
-> net
), maskstr
);
2687 subnet_dereference (&subnet
, MDL
);
2688 skip_to_semi (cfile
);
2692 common_subnet_parsing(cfile
, share
, subnet
);
2695 /* subnet6-declaration :==
2696 net / bits RBRACE parameters declarations LBRACE */
2699 parse_subnet6_declaration(struct parse
*cfile
, struct shared_network
*share
) {
2700 #if !defined(DHCPv6)
2701 parse_warn(cfile
, "No DHCPv6 support.");
2702 skip_to_semi(cfile
);
2703 #else /* defined(DHCPv6) */
2704 struct subnet
*subnet
;
2705 isc_result_t status
;
2706 enum dhcp_token token
;
2710 const static int mask
[] = { 0x00, 0x80, 0xC0, 0xE0,
2711 0xF0, 0xF8, 0xFC, 0xFE };
2714 if (local_family
!= AF_INET6
) {
2715 parse_warn(cfile
, "subnet6 statement is only supported "
2717 skip_to_semi(cfile
);
2722 status
= subnet_allocate(&subnet
, MDL
);
2723 if (status
!= ISC_R_SUCCESS
) {
2724 log_fatal("Allocation of new subnet failed: %s",
2725 isc_result_totext(status
));
2727 shared_network_reference(&subnet
->shared_network
, share
, MDL
);
2730 * If our parent shared network was implicitly created by the software,
2731 * and not explicitly configured by the user, then we actually put all
2732 * configuration scope in the parent (the shared network and subnet
2733 * share the same {}-level scope).
2735 * Otherwise, we clone the parent group and continue as normal.
2737 if (share
->flags
& SHARED_IMPLICIT
) {
2738 group_reference(&subnet
->group
, share
->group
, MDL
);
2740 if (!clone_group(&subnet
->group
, share
->group
, MDL
)) {
2741 log_fatal("Allocation of group for new subnet failed.");
2744 subnet_reference(&subnet
->group
->subnet
, subnet
, MDL
);
2746 if (!parse_ip6_addr(cfile
, &subnet
->net
)) {
2747 subnet_dereference(&subnet
, MDL
);
2751 token
= next_token(&val
, NULL
, cfile
);
2752 if (token
!= SLASH
) {
2753 parse_warn(cfile
, "Expecting a '/'.");
2754 skip_to_semi(cfile
);
2758 token
= next_token(&val
, NULL
, cfile
);
2759 if (token
!= NUMBER
) {
2760 parse_warn(cfile
, "Expecting a number.");
2761 skip_to_semi(cfile
);
2765 subnet
->prefix_len
= strtol(val
, &endp
, 10);
2766 if ((subnet
->prefix_len
< 0) ||
2767 (subnet
->prefix_len
> 128) ||
2769 parse_warn(cfile
, "Expecting a number between 0 and 128.");
2770 skip_to_semi(cfile
);
2774 if (!is_cidr_mask_valid(&subnet
->net
, subnet
->prefix_len
)) {
2775 parse_warn(cfile
, "New subnet mask too short.");
2776 skip_to_semi(cfile
);
2783 subnet
->netmask
.len
= 16;
2784 ofs
= subnet
->prefix_len
/ 8;
2785 if (ofs
< subnet
->netmask
.len
) {
2786 subnet
->netmask
.iabuf
[ofs
] = mask
[subnet
->prefix_len
% 8];
2788 while (--ofs
>= 0) {
2789 subnet
->netmask
.iabuf
[ofs
] = 0xFF;
2792 /* Validate the network number/netmask pair. */
2793 iaddr
= subnet_number(subnet
->net
, subnet
->netmask
);
2794 if (memcmp(&iaddr
, &subnet
->net
, 16) != 0) {
2796 "subnet %s/%d: prefix not long enough for address.",
2797 piaddr(subnet
->net
), subnet
->prefix_len
);
2798 subnet_dereference(&subnet
, MDL
);
2799 skip_to_semi(cfile
);
2803 if (!common_subnet_parsing(cfile
, share
, subnet
)) {
2806 #endif /* defined(DHCPv6) */
2809 /* group-declaration :== RBRACE parameters declarations LBRACE */
2811 void parse_group_declaration (cfile
, group
)
2812 struct parse
*cfile
;
2813 struct group
*group
;
2816 enum dhcp_token token
;
2818 int declaration
= 0;
2819 struct group_object
*t
= NULL
;
2820 isc_result_t status
;
2827 if (!clone_group(&g
, group
, MDL
))
2828 log_fatal("no memory for explicit group.");
2830 token
= peek_token(&val
, NULL
, cfile
);
2831 if (is_identifier (token
) || token
== STRING
) {
2832 skip_token(&val
, NULL
, cfile
);
2834 name
= dmalloc(strlen(val
) + 1, MDL
);
2836 log_fatal("no memory for group decl name %s", val
);
2840 if (!parse_lbrace(cfile
)) {
2841 group_dereference(&g
, MDL
);
2846 token
= peek_token(&val
, NULL
, cfile
);
2847 if (token
== RBRACE
) {
2848 skip_token(&val
, NULL
, cfile
);
2850 } else if (token
== END_OF_FILE
) {
2851 skip_token(&val
, NULL
, cfile
);
2852 parse_warn(cfile
, "unexpected end of file");
2854 } else if (token
== TOKEN_DELETED
) {
2855 skip_token(&val
, NULL
, cfile
);
2858 } else if (token
== DYNAMIC
) {
2859 skip_token(&val
, NULL
, cfile
);
2862 } else if (token
== STATIC
) {
2863 skip_token(&val
, NULL
, cfile
);
2867 declaration
= parse_statement(cfile
, g
, GROUP_DECL
,
2873 if (group_name_hash
) {
2875 if (group_hash_lookup(&t
, group_name_hash
,
2877 strlen(name
), MDL
)) {
2883 status
= group_object_allocate(&t
, MDL
);
2884 if (status
!= ISC_R_SUCCESS
)
2885 log_fatal("no memory for group decl %s: %s",
2886 val
, isc_result_totext(status
));
2887 group_reference(&t
->group
, g
, MDL
);
2889 /* no need to include deletedp as it's handled above */
2890 t
->flags
= ((staticp
? GROUP_OBJECT_STATIC
: 0) |
2891 (dynamicp
? GROUP_OBJECT_DYNAMIC
: 0));
2892 supersede_group(t
, 0);
2895 group_object_dereference(&t
, MDL
);
2899 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2900 ip-addrs-or-hostnames :== ip-addr-or-hostname
2901 | ip-addrs-or-hostnames ip-addr-or-hostname */
2904 parse_fixed_addr_param(struct option_cache
**oc
,
2905 struct parse
*cfile
,
2906 enum dhcp_token type
) {
2909 enum dhcp_token token
;
2910 struct expression
*expr
= NULL
;
2911 struct expression
*tmp
, *new;
2916 if (type
== FIXED_ADDR
) {
2917 parse_ok
= parse_ip_addr_or_hostname(&tmp
, cfile
, 1);
2919 /* INSIST(type == FIXED_ADDR6); */
2920 parse_ok
= parse_ip6_addr_expr(&tmp
, cfile
);
2925 status
= make_concat(&new, expr
, tmp
);
2926 expression_dereference(&expr
, MDL
);
2927 expression_dereference(&tmp
, MDL
);
2937 expression_dereference (&expr
, MDL
);
2941 token
= peek_token(&val
, NULL
, cfile
);
2942 if (token
== COMMA
) {
2943 token
= next_token(&val
, NULL
, cfile
);
2945 } while (token
== COMMA
);
2947 if (!parse_semi(cfile
)) {
2949 expression_dereference (&expr
, MDL
);
2954 status
= option_cache(oc
, NULL
, expr
, NULL
, MDL
);
2955 expression_dereference(&expr
, MDL
);
2959 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2961 lease_parameters :== <nil>
2963 | lease_parameters lease_parameter
2965 lease_parameter :== STARTS date
2968 | HARDWARE hardware-parameter
2969 | UID hex_numbers SEMI
2970 | HOSTNAME hostname SEMI
2971 | CLIENT_HOSTNAME hostname SEMI
2972 | CLASS identifier SEMI
2973 | DYNAMIC_BOOTP SEMI */
2975 int parse_lease_declaration (struct lease
**lp
, struct parse
*cfile
)
2978 enum dhcp_token token
;
2979 unsigned char addr
[4];
2980 unsigned len
= sizeof addr
;
2984 struct lease
*lease
;
2985 struct executable_statement
*on
;
2988 int noequal
, newbinding
;
2989 struct binding
*binding
;
2990 struct binding_value
*nv
;
2991 isc_result_t status
;
2992 struct option_cache
*oc
;
2994 binding_state_t new_state
;
2995 unsigned buflen
= 0;
2996 struct class *class;
2998 lease
= (struct lease
*)0;
2999 status
= lease_allocate (&lease
, MDL
);
3000 if (status
!= ISC_R_SUCCESS
)
3003 /* Get the address for which the lease has been issued. */
3004 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
3005 lease_dereference (&lease
, MDL
);
3008 memcpy (lease
-> ip_addr
.iabuf
, addr
, len
);
3009 lease
-> ip_addr
.len
= len
;
3011 if (!parse_lbrace (cfile
)) {
3012 lease_dereference (&lease
, MDL
);
3017 token
= next_token (&val
, (unsigned *)0, cfile
);
3018 if (token
== RBRACE
)
3020 else if (token
== END_OF_FILE
) {
3021 parse_warn (cfile
, "unexpected end of file");
3024 strncpy (tbuf
, val
, sizeof tbuf
);
3025 tbuf
[(sizeof tbuf
) - 1] = 0;
3027 /* Parse any of the times associated with the lease. */
3036 t
= parse_date (cfile
);
3040 lease
-> starts
= t
;
3068 default: /* for gcc, we'll never get here. */
3069 log_fatal ("Impossible error at %s:%d.", MDL
);
3074 /* Colon-separated hexadecimal octets... */
3077 token
= peek_token (&val
, (unsigned *)0, cfile
);
3078 if (token
== STRING
) {
3079 unsigned char *tuid
;
3080 skip_token(&val
, &buflen
, cfile
);
3081 if (buflen
< sizeof lease
-> uid_buf
) {
3082 tuid
= lease
-> uid_buf
;
3084 sizeof lease
-> uid_buf
;
3086 tuid
= ((unsigned char *)
3087 dmalloc (buflen
, MDL
));
3089 log_error ("no space for uid");
3090 lease_dereference (&lease
,
3094 lease
-> uid_max
= buflen
;
3096 lease
-> uid_len
= buflen
;
3097 memcpy (tuid
, val
, lease
-> uid_len
);
3098 lease
-> uid
= tuid
;
3101 lease
-> uid
= (parse_numeric_aggregate
3102 (cfile
, (unsigned char *)0,
3103 &buflen
, ':', 16, 8));
3104 if (!lease
-> uid
) {
3105 lease_dereference (&lease
, MDL
);
3108 lease
-> uid_len
= buflen
;
3109 lease
-> uid_max
= buflen
;
3110 if (lease
-> uid_len
== 0) {
3111 lease
-> uid
= (unsigned char *)0;
3112 parse_warn (cfile
, "zero-length uid");
3119 if (!lease
-> uid
) {
3120 log_fatal ("No memory for lease uid");
3126 token
= next_token (&val
, (unsigned *)0, cfile
);
3127 if (!is_identifier (token
)) {
3129 skip_to_rbrace (cfile
, 1);
3130 lease_dereference (&lease
, MDL
);
3134 /* for now, we aren't using this. */
3139 parse_hardware_param (cfile
,
3140 &lease
-> hardware_addr
);
3143 case TOKEN_RESERVED
:
3145 lease
->flags
|= RESERVED_LEASE
;
3151 lease
-> flags
|= BOOTP_LEASE
;
3155 /* XXX: Reverse compatibility? */
3156 case TOKEN_ABANDONED
:
3158 lease
-> binding_state
= FTS_ABANDONED
;
3159 lease
-> next_binding_state
= FTS_ABANDONED
;
3165 token
= next_token (&val
, (unsigned *)0, cfile
);
3166 if (token
!= BINDING
) {
3167 parse_warn (cfile
, "expecting 'binding'");
3168 skip_to_semi (cfile
);
3171 goto do_binding_state
;
3175 token
= next_token(&val
, NULL
, cfile
);
3176 if (token
!= BINDING
) {
3177 parse_warn(cfile
, "expecting 'binding'");
3178 skip_to_semi(cfile
);
3181 goto do_binding_state
;
3187 token
= next_token (&val
, (unsigned *)0, cfile
);
3188 if (token
!= STATE
) {
3189 parse_warn (cfile
, "expecting 'state'");
3190 skip_to_semi (cfile
);
3193 token
= next_token (&val
, (unsigned *)0, cfile
);
3195 case TOKEN_ABANDONED
:
3196 new_state
= FTS_ABANDONED
;
3199 new_state
= FTS_FREE
;
3202 new_state
= FTS_ACTIVE
;
3205 new_state
= FTS_EXPIRED
;
3207 case TOKEN_RELEASED
:
3208 new_state
= FTS_RELEASED
;
3211 new_state
= FTS_RESET
;
3214 new_state
= FTS_BACKUP
;
3217 /* RESERVED and BOOTP states preserved for
3218 * compatibleness with older versions.
3220 case TOKEN_RESERVED
:
3221 new_state
= FTS_ACTIVE
;
3222 lease
->flags
|= RESERVED_LEASE
;
3225 new_state
= FTS_ACTIVE
;
3226 lease
->flags
|= BOOTP_LEASE
;
3231 "%s: expecting a binding state.",
3233 skip_to_semi (cfile
);
3237 if (seenbit
== 256) {
3238 lease
-> binding_state
= new_state
;
3241 * Apply default/conservative next/rewind
3242 * binding states if they haven't been set
3243 * yet. These defaults will be over-ridden if
3244 * they are set later in parsing.
3246 if (!(seenmask
& 128))
3247 lease
->next_binding_state
= new_state
;
3249 /* The most conservative rewind state. */
3250 if (!(seenmask
& 512))
3251 lease
->rewind_binding_state
= new_state
;
3252 } else if (seenbit
== 128)
3253 lease
-> next_binding_state
= new_state
;
3254 else if (seenbit
== 512)
3255 lease
->rewind_binding_state
= new_state
;
3257 log_fatal("Impossible condition at %s:%d.",
3263 case CLIENT_HOSTNAME
:
3265 token
= peek_token (&val
, (unsigned *)0, cfile
);
3266 if (token
== STRING
) {
3267 if (!parse_string (cfile
,
3268 &lease
-> client_hostname
,
3270 lease_dereference (&lease
, MDL
);
3274 lease
-> client_hostname
=
3275 parse_host_name (cfile
);
3276 if (lease
-> client_hostname
)
3280 "expecting a hostname.");
3281 skip_to_semi (cfile
);
3282 lease_dereference (&lease
, MDL
);
3290 class = (struct class *)0;
3291 token
= next_token (&val
, (unsigned *)0, cfile
);
3292 if (token
== CLASS
) {
3293 token
= next_token (&val
,
3294 (unsigned *)0, cfile
);
3295 if (token
!= STRING
) {
3296 parse_warn (cfile
, "expecting string");
3298 skip_to_semi (cfile
);
3302 if (lease
-> billing_class
)
3303 class_dereference (&lease
-> billing_class
,
3305 find_class (&class, val
, MDL
);
3308 "unknown class %s", val
);
3310 } else if (token
== SUBCLASS
) {
3311 if (lease
-> billing_class
)
3312 class_dereference (&lease
-> billing_class
,
3314 parse_class_declaration(&class, cfile
, NULL
,
3315 CLASS_TYPE_SUBCLASS
);
3317 parse_warn (cfile
, "expecting \"class\"");
3319 skip_to_semi (cfile
);
3322 class_reference (&lease
-> billing_class
,
3324 class_dereference (&class, MDL
);
3329 on
= (struct executable_statement
*)0;
3331 if (!parse_on_statement (&on
, cfile
, &lose
)) {
3332 skip_to_rbrace (cfile
, 1);
3333 lease_dereference (&lease
, MDL
);
3337 if ((on
->data
.on
.evtypes
& ON_EXPIRY
) &&
3338 on
->data
.on
.statements
) {
3340 executable_statement_reference
3341 (&lease
->on_star
.on_expiry
,
3342 on
->data
.on
.statements
, MDL
);
3344 if ((on
->data
.on
.evtypes
& ON_RELEASE
) &&
3345 on
->data
.on
.statements
) {
3347 executable_statement_reference
3348 (&lease
->on_star
.on_release
,
3349 on
->data
.on
.statements
, MDL
);
3351 executable_statement_dereference (&on
, MDL
);
3358 oc
= (struct option_cache
*)0;
3359 if (parse_option_decl (&oc
, cfile
)) {
3360 if (oc
-> option
-> universe
!=
3363 "agent option expected.");
3364 option_cache_dereference (&oc
, MDL
);
3367 if (!lease
-> agent_options
&&
3368 !(option_chain_head_allocate
3369 (&lease
-> agent_options
, MDL
))) {
3370 log_error ("no memory to stash agent option");
3373 for (p
= &lease
-> agent_options
-> first
;
3374 *p
; p
= &((*p
) -> cdr
))
3377 option_cache_reference (((struct option_cache
**)
3378 &((*p
) -> car
)), oc
, MDL
);
3379 option_cache_dereference (&oc
, MDL
);
3386 token
= next_token (&val
, (unsigned *)0, cfile
);
3387 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
3389 "%s can't be a variable name",
3392 skip_to_semi (cfile
);
3393 lease_dereference (&lease
, MDL
);
3400 binding
= find_binding (lease
-> scope
, val
);
3402 binding
= (struct binding
*)0;
3405 if (!lease
-> scope
)
3406 if (!(binding_scope_allocate
3407 (&lease
-> scope
, MDL
)))
3408 log_fatal ("no memory for scope");
3409 binding
= dmalloc (sizeof *binding
, MDL
);
3411 log_fatal ("No memory for lease %s.",
3413 memset (binding
, 0, sizeof *binding
);
3415 dmalloc (strlen (val
) + 1, MDL
);
3416 if (!binding
-> name
)
3417 log_fatal ("No memory for binding %s.",
3419 strcpy (binding
-> name
, val
);
3426 if (!binding_value_allocate(&nv
, MDL
))
3427 log_fatal("no memory for binding value.");
3430 token
= next_token (&val
, (unsigned *)0, cfile
);
3431 if (token
!= EQUAL
) {
3433 "expecting '=' in set statement.");
3438 if (!parse_binding_value(cfile
, nv
)) {
3439 binding_value_dereference(&nv
, MDL
);
3440 lease_dereference(&lease
, MDL
);
3445 binding_value_reference(&binding
->value
,
3447 binding
->next
= lease
->scope
->bindings
;
3448 lease
->scope
->bindings
= binding
;
3450 binding_value_dereference(&binding
->value
, MDL
);
3451 binding_value_reference(&binding
->value
,
3455 binding_value_dereference(&nv
, MDL
);
3461 if (!strcasecmp (val
, "ddns-fwd-name")) {
3465 } else if (!strcasecmp (val
, "ddns-rev-name")) {
3470 parse_warn(cfile
, "Unexpected configuration "
3472 skip_to_semi (cfile
);
3474 lease_dereference (&lease
, MDL
);
3478 if (seenmask
& seenbit
) {
3480 "Too many %s parameters in lease %s\n",
3481 tbuf
, piaddr (lease
-> ip_addr
));
3483 seenmask
|= seenbit
;
3487 /* If no binding state is specified, make one up. */
3488 if (!(seenmask
& 256)) {
3489 if (lease
->ends
> cur_time
||
3490 lease
->on_star
.on_expiry
|| lease
->on_star
.on_release
)
3491 lease
->binding_state
= FTS_ACTIVE
;
3492 #if defined (FAILOVER_PROTOCOL)
3493 else if (lease
->pool
&& lease
->pool
->failover_peer
)
3494 lease
->binding_state
= FTS_EXPIRED
;
3497 lease
->binding_state
= FTS_FREE
;
3498 if (lease
->binding_state
== FTS_ACTIVE
) {
3499 #if defined (FAILOVER_PROTOCOL)
3500 if (lease
->pool
&& lease
->pool
->failover_peer
)
3501 lease
->next_binding_state
= FTS_EXPIRED
;
3504 lease
->next_binding_state
= FTS_FREE
;
3506 lease
->next_binding_state
= lease
->binding_state
;
3508 /* The most conservative rewind state implies no rewind. */
3509 lease
->rewind_binding_state
= lease
->binding_state
;
3512 if (!(seenmask
& 65536))
3513 lease
->tstp
= lease
->ends
;
3515 lease_reference (lp
, lease
, MDL
);
3516 lease_dereference (&lease
, MDL
);
3520 /* Parse the right side of a 'binding value'.
3522 * set foo = "bar"; is a string
3523 * set foo = false; is a boolean
3524 * set foo = %31; is a numeric value.
3527 parse_binding_value(struct parse
*cfile
, struct binding_value
*value
)
3529 struct data_string
*data
;
3535 if ((cfile
== NULL
) || (value
== NULL
))
3536 log_fatal("Invalid arguments at %s:%d.", MDL
);
3538 token
= peek_token(&val
, NULL
, cfile
);
3539 if (token
== STRING
) {
3540 skip_token(&val
, &buflen
, cfile
);
3542 value
->type
= binding_data
;
3543 value
->value
.data
.len
= buflen
;
3545 data
= &value
->value
.data
;
3547 if (!buffer_allocate(&data
->buffer
, buflen
+ 1, MDL
))
3548 log_fatal ("No memory for binding.");
3550 memcpy(data
->buffer
->data
, val
, buflen
+ 1);
3552 data
->data
= data
->buffer
->data
;
3553 data
->terminated
= 1;
3554 } else if (token
== NUMBER_OR_NAME
) {
3555 value
->type
= binding_data
;
3557 data
= &value
->value
.data
;
3558 s
= parse_numeric_aggregate(cfile
, NULL
, &data
->len
,
3561 skip_to_semi(cfile
);
3566 if (!buffer_allocate(&data
->buffer
, data
->len
+ 1,
3568 log_fatal("No memory for binding.");
3570 memcpy(data
->buffer
->data
, s
, data
->len
);
3571 data
->data
= data
->buffer
->data
;
3575 } else if (token
== PERCENT
) {
3576 skip_token(&val
, NULL
, cfile
);
3577 token
= next_token(&val
, NULL
, cfile
);
3578 if (token
!= NUMBER
) {
3579 parse_warn(cfile
, "expecting decimal number.");
3581 skip_to_semi(cfile
);
3584 value
->type
= binding_numeric
;
3585 value
->value
.intval
= atol(val
);
3586 } else if (token
== NAME
) {
3587 token
= next_token(&val
, NULL
, cfile
);
3588 value
->type
= binding_boolean
;
3589 if (!strcasecmp(val
, "true"))
3590 value
->value
.boolean
= 1;
3591 else if (!strcasecmp(val
, "false"))
3592 value
->value
.boolean
= 0;
3594 parse_warn(cfile
, "expecting true or false");
3596 skip_to_semi(cfile
);
3600 parse_warn (cfile
, "expecting a constant value.");
3602 skip_to_semi (cfile
);
3609 /* address-range-declaration :== ip-address ip-address SEMI
3610 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3612 void parse_address_range (cfile
, group
, type
, inpool
, lpchain
)
3613 struct parse
*cfile
;
3614 struct group
*group
;
3616 struct pool
*inpool
;
3617 struct lease
**lpchain
;
3619 struct iaddr low
, high
, net
;
3620 unsigned char addr
[4];
3621 unsigned len
= sizeof addr
;
3622 enum dhcp_token token
;
3625 struct subnet
*subnet
;
3626 struct shared_network
*share
;
3628 isc_result_t status
;
3630 if ((token
= peek_token (&val
,
3631 (unsigned *)0, cfile
)) == DYNAMIC_BOOTP
) {
3632 skip_token(&val
, (unsigned *)0, cfile
);
3636 /* Get the bottom address in the range... */
3637 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3639 memcpy (low
.iabuf
, addr
, len
);
3642 /* Only one address? */
3643 token
= peek_token (&val
, (unsigned *)0, cfile
);
3647 /* Get the top address in the range... */
3648 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3650 memcpy (high
.iabuf
, addr
, len
);
3654 token
= next_token (&val
, (unsigned *)0, cfile
);
3655 if (token
!= SEMI
) {
3656 parse_warn (cfile
, "semicolon expected.");
3657 skip_to_semi (cfile
);
3661 if (type
== SUBNET_DECL
) {
3662 subnet
= group
-> subnet
;
3663 share
= subnet
-> shared_network
;
3665 share
= group
-> shared_network
;
3666 for (subnet
= share
-> subnets
;
3667 subnet
; subnet
= subnet
-> next_sibling
) {
3668 net
= subnet_number (low
, subnet
-> netmask
);
3669 if (addr_eq (net
, subnet
-> net
))
3673 parse_warn (cfile
, "address range not on network %s",
3674 group
-> shared_network
-> name
);
3675 log_error ("Be sure to place pool statement after %s",
3676 "related subnet declarations.");
3682 struct pool
*last
= (struct pool
*)0;
3684 /* If we're permitting dynamic bootp for this range,
3685 then look for a pool with an empty prohibit list and
3686 a permit list with one entry that permits all clients. */
3687 for (pool
= share
-> pools
; pool
; pool
= pool
-> next
) {
3688 if ((!dynamic
&& !pool
-> permit_list
&&
3689 pool
-> prohibit_list
&&
3690 !pool
-> prohibit_list
-> next
&&
3691 (pool
-> prohibit_list
-> type
==
3692 permit_dynamic_bootp_clients
)) ||
3693 (dynamic
&& !pool
-> prohibit_list
&&
3694 pool
-> permit_list
&&
3695 !pool
-> permit_list
-> next
&&
3696 (pool
-> permit_list
-> type
==
3697 permit_all_clients
))) {
3703 /* If we didn't get a pool, make one. */
3706 status
= pool_allocate (&pool
, MDL
);
3707 if (status
!= ISC_R_SUCCESS
)
3708 log_fatal ("no memory for ad-hoc pool: %s",
3709 isc_result_totext (status
));
3710 p
= new_permit (MDL
);
3712 log_fatal ("no memory for ad-hoc permit.");
3714 /* Dynamic pools permit all clients. Otherwise
3715 we prohibit BOOTP clients. */
3717 p
-> type
= permit_all_clients
;
3718 pool
-> permit_list
= p
;
3720 p
-> type
= permit_dynamic_bootp_clients
;
3721 pool
-> prohibit_list
= p
;
3725 pool_reference (&last
-> next
, pool
, MDL
);
3727 pool_reference (&share
-> pools
, pool
, MDL
);
3728 shared_network_reference (&pool
-> shared_network
,
3730 if (!clone_group (&pool
-> group
, share
-> group
, MDL
))
3731 log_fatal ("no memory for anon pool group.");
3733 pool
= (struct pool
*)0;
3735 pool_reference (&pool
, last
, MDL
);
3737 pool_reference (&pool
, share
-> pools
, MDL
);
3740 pool
= (struct pool
*)0;
3741 pool_reference (&pool
, inpool
, MDL
);
3744 #if defined (FAILOVER_PROTOCOL)
3745 if (pool
-> failover_peer
&& dynamic
) {
3746 /* Doctor, do you think I'm overly sensitive
3747 about getting bug reports I can't fix? */
3748 parse_warn (cfile
, "dynamic-bootp flag is %s",
3749 "not permitted for address");
3750 log_error ("range declarations where there is a failover");
3751 log_error ("peer in scope. If you wish to declare an");
3752 log_error ("address range from which dynamic bootp leases");
3753 log_error ("can be allocated, please declare it within a");
3754 log_error ("pool declaration that also contains the \"no");
3755 log_error ("failover\" statement. The failover protocol");
3756 log_error ("itself does not permit dynamic bootp - this");
3757 log_error ("is not a limitation specific to the ISC DHCP");
3758 log_error ("server. Please don't ask me to defend this");
3759 log_error ("until you have read and really tried %s",
3761 log_error ("the failover protocol specification.");
3763 /* We don't actually bomb at this point - instead,
3764 we let parse_lease_file notice the error and
3765 bomb at that point - it's easier. */
3767 #endif /* FAILOVER_PROTOCOL */
3769 /* Create the new address range... */
3770 new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
);
3771 pool_dereference (&pool
, MDL
);
3776 add_ipv6_pool_to_subnet(struct subnet
*subnet
, u_int16_t type
,
3777 struct iaddr
*lo_addr
, int bits
, int units
,
3778 struct ipv6_pond
*pond
) {
3779 struct ipv6_pool
*pool
;
3780 struct in6_addr tmp_in6_addr
;
3782 struct ipv6_pool
**tmp
;
3787 if (lo_addr
->len
!= sizeof(tmp_in6_addr
)) {
3788 log_fatal("Internal error: Attempt to add non-IPv6 address "
3789 "to IPv6 shared network.");
3791 memcpy(&tmp_in6_addr
, lo_addr
->iabuf
, sizeof(tmp_in6_addr
));
3793 if (ipv6_pool_allocate(&pool
, type
, &tmp_in6_addr
,
3794 bits
, units
, MDL
) != ISC_R_SUCCESS
) {
3795 log_fatal("Out of memory");
3799 * Add to our global IPv6 pool set.
3801 if (add_ipv6_pool(pool
) != ISC_R_SUCCESS
) {
3802 log_fatal ("Out of memory");
3806 * Link the pool to its network.
3808 pool
->subnet
= NULL
;
3809 subnet_reference(&pool
->subnet
, subnet
, MDL
);
3810 pool
->shared_network
= NULL
;
3811 shared_network_reference(&pool
->shared_network
,
3812 subnet
->shared_network
, MDL
);
3813 pool
->ipv6_pond
= NULL
;
3814 ipv6_pond_reference(&pool
->ipv6_pond
, pond
, MDL
);
3817 * Increase our array size for ipv6_pools in the pond
3819 if (pond
->ipv6_pools
== NULL
) {
3823 while (pond
->ipv6_pools
[num_pools
] != NULL
) {
3827 tmp
= dmalloc(sizeof(struct ipv6_pool
*) * (num_pools
+ 2), MDL
);
3829 log_fatal("Out of memory");
3831 if (num_pools
> 0) {
3832 memcpy(tmp
, pond
->ipv6_pools
,
3833 sizeof(struct ipv6_pool
*) * num_pools
);
3835 if (pond
->ipv6_pools
!= NULL
) {
3836 dfree(pond
->ipv6_pools
, MDL
);
3838 pond
->ipv6_pools
= tmp
;
3841 * Record this pool in our array of pools for this shared network.
3843 ipv6_pool_reference(&pond
->ipv6_pools
[num_pools
], pool
, MDL
);
3844 pond
->ipv6_pools
[num_pools
+1] = NULL
;
3846 /* Update the number of elements in the pond. Conveniently
3847 * we have the total size of the block in bits and the amount
3848 * we would allocate per element in units. For an address units
3849 * will always be 128, for a prefix it will be something else.
3851 * We need to make sure the number of elements isn't too large
3852 * to track. If so, we flag it to avoid wasting time with log
3853 * threshold logic. We also emit a log stating that log-threshold
3854 * will be disabled for the shared-network but that's done
3855 * elsewhere via report_log_threshold().
3859 /* Only bother if we aren't already flagged as jumbo */
3860 if (pond
->jumbo_range
== 0) {
3861 if ((units
- bits
) > (sizeof(isc_uint64_t
) * 8)) {
3862 pond
->jumbo_range
= 1;
3863 pond
->num_total
= POND_TRACK_MAX
;
3866 isc_uint64_t space_left
3867 = POND_TRACK_MAX
- pond
->num_total
;
3869 = (isc_uint64_t
)(1) << (units
- bits
);
3871 if (addon
> space_left
) {
3872 pond
->jumbo_range
= 1;
3873 pond
->num_total
= POND_TRACK_MAX
;
3875 pond
->num_total
+= addon
;
3883 * \brief Find or create a default pond
3885 * Find or create an ipv6_pond on which to attach the ipv6_pools. We
3886 * check the shared network to see if there is a general purpose
3887 * entry - this will have an empty prohibit list and a permit list
3888 * with a single entry that permits all clients. If the shared
3889 * network doesn't have one of them create it and attach it to
3890 * the shared network and the return argument.
3892 * This function is used when we have a range6 or prefix6 statement
3893 * inside a subnet6 statement but outside of a pool6 statement.
3894 * This routine constructs the missing ipv6_pond structure so
3896 * shared_network -> ipv6_pond -> ipv6_pool
3898 * \param[in] group = a pointer to the group structure from which
3899 * we can find the subnet and shared netowrk
3901 * \param[out] ret_pond = a pointer to space for the pointer to
3902 * the structure to return
3908 add_ipv6_pond_to_network(struct group
*group
,
3909 struct ipv6_pond
**ret_pond
) {
3911 struct ipv6_pond
*pond
= NULL
, *last
= NULL
;
3913 isc_result_t status
;
3914 struct shared_network
*shared
= group
->subnet
->shared_network
;
3916 for (pond
= shared
->ipv6_pond
; pond
; pond
= pond
->next
) {
3917 if ((pond
->group
->statements
== group
->statements
) &&
3918 (pond
->prohibit_list
== NULL
) &&
3919 (pond
->permit_list
!= NULL
) &&
3920 (pond
->permit_list
->next
== NULL
) &&
3921 (pond
->permit_list
->type
== permit_all_clients
)) {
3922 ipv6_pond_reference(ret_pond
, pond
, MDL
);
3928 /* no pond available, make one */
3929 status
= ipv6_pond_allocate(&pond
, MDL
);
3930 if (status
!= ISC_R_SUCCESS
)
3931 log_fatal ("no memory for ad-hoc ipv6 pond: %s",
3932 isc_result_totext (status
));
3933 p
= new_permit (MDL
);
3935 log_fatal ("no memory for ad-hoc ipv6 permit.");
3937 /* we permit all clients */
3938 p
->type
= permit_all_clients
;
3939 pond
->permit_list
= p
;
3941 /* and attach the pond to the return argument and the shared network */
3942 ipv6_pond_reference(ret_pond
, pond
, MDL
);
3944 if (shared
->ipv6_pond
)
3945 ipv6_pond_reference(&last
->next
, pond
, MDL
);
3947 ipv6_pond_reference(&shared
->ipv6_pond
, pond
, MDL
);
3949 shared_network_reference(&pond
->shared_network
, shared
, MDL
);
3950 if (!clone_group (&pond
->group
, group
, MDL
))
3951 log_fatal ("no memory for anon pool group.");
3953 ipv6_pond_dereference(&pond
, MDL
);
3958 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
3959 | ip-address6 SLASH number SEMI
3960 | ip-address6 [SLASH number] TEMPORARY SEMI */
3963 parse_address_range6(struct parse
*cfile
,
3964 struct group
*group
,
3965 struct ipv6_pond
*inpond
) {
3966 struct iaddr lo
, hi
;
3968 enum dhcp_token token
;
3970 struct iaddrcidrnetlist
*nets
, net
;
3971 struct iaddrcidrnetlist
*p
;
3972 u_int16_t type
= D6O_IA_NA
;
3973 struct ipv6_pond
*pond
= NULL
;
3975 if (local_family
!= AF_INET6
) {
3976 parse_warn(cfile
, "range6 statement is only supported "
3978 skip_to_semi(cfile
);
3982 /* This is enforced by the caller, this is just a sanity check. */
3983 if (group
->subnet
== NULL
)
3984 log_fatal("Impossible condition at %s:%d.", MDL
);
3987 * Read starting address.
3989 if (!parse_ip6_addr(cfile
, &lo
)) {
3993 /* Make sure starting address is within the subnet */
3994 if (!addr_eq(group
->subnet
->net
,
3995 subnet_number(lo
, group
->subnet
->netmask
))) {
3996 parse_warn(cfile
, "range6 start address is outside the subnet");
3997 skip_to_semi(cfile
);
4002 * zero out the net entry in case we use it
4004 memset(&net
, 0, sizeof(net
));
4005 net
.cidrnet
.lo_addr
= lo
;
4008 * See if we we're using range or CIDR notation or TEMPORARY
4010 token
= peek_token(&val
, NULL
, cfile
);
4011 if (token
== SLASH
) {
4013 * '/' means CIDR notation, so read the bits we want.
4015 skip_token(NULL
, NULL
, cfile
);
4016 token
= next_token(&val
, NULL
, cfile
);
4017 if (token
!= NUMBER
) {
4018 parse_warn(cfile
, "expecting number");
4019 skip_to_semi(cfile
);
4022 net
.cidrnet
.bits
= atoi(val
);
4023 bits
= net
.cidrnet
.bits
;
4024 if ((bits
< 0) || (bits
> 128)) {
4025 parse_warn(cfile
, "networks have 0 to 128 bits");
4026 skip_to_semi(cfile
);
4029 if (bits
< group
->subnet
->prefix_len
) {
4031 "network mask smaller than subnet mask");
4032 skip_to_semi(cfile
);
4035 if (!is_cidr_mask_valid(&net
.cidrnet
.lo_addr
, bits
)) {
4036 parse_warn(cfile
, "network mask too short");
4037 skip_to_semi(cfile
);
4041 * can be temporary (RFC 4941 like)
4043 token
= peek_token(&val
, NULL
, cfile
);
4044 if (token
== TEMPORARY
) {
4046 parse_warn(cfile
, "temporary mask too short");
4048 parse_warn(cfile
, "temporary singleton?");
4049 skip_token(NULL
, NULL
, cfile
);
4055 } else if (token
== TEMPORARY
) {
4057 * temporary (RFC 4941)
4060 skip_token(NULL
, NULL
, cfile
);
4061 net
.cidrnet
.bits
= 64;
4062 if (!is_cidr_mask_valid(&net
.cidrnet
.lo_addr
,
4063 net
.cidrnet
.bits
)) {
4064 parse_warn(cfile
, "network mask too short");
4065 skip_to_semi(cfile
);
4073 * No '/', so we are looking for the end address of
4076 if (!parse_ip6_addr(cfile
, &hi
)) {
4080 /* Make sure ending address is within the subnet */
4081 if (!addr_eq(group
->subnet
->net
,
4082 subnet_number(hi
, group
->subnet
->netmask
))) {
4084 "range6 end address is outside the subnet");
4085 skip_to_semi(cfile
);
4090 * Convert our range to a set of CIDR networks.
4093 if (range2cidr(&nets
, &lo
, &hi
) != ISC_R_SUCCESS
) {
4094 log_fatal("Error converting range to CIDR networks");
4100 * See if we have a pond for this set of pools.
4101 * If the caller supplied one we use it, otherwise
4102 * check the shared network
4105 if (inpond
!= NULL
) {
4106 ipv6_pond_reference(&pond
, inpond
, MDL
);
4108 add_ipv6_pond_to_network(group
, &pond
);
4111 /* Now that we have a pond add the nets we have parsed */
4112 for (p
=nets
; p
!= NULL
; p
=p
->next
) {
4113 add_ipv6_pool_to_subnet(group
->subnet
, type
,
4114 &p
->cidrnet
.lo_addr
,
4115 p
->cidrnet
.bits
, 128, pond
);
4118 /* if we allocated a list free it now */
4120 free_iaddrcidrnetlist(&nets
);
4122 ipv6_pond_dereference(&pond
, MDL
);
4124 token
= next_token(NULL
, NULL
, cfile
);
4125 if (token
!= SEMI
) {
4126 parse_warn(cfile
, "semicolon expected.");
4127 skip_to_semi(cfile
);
4132 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4135 parse_prefix6(struct parse
*cfile
,
4136 struct group
*group
,
4137 struct ipv6_pond
*inpond
) {
4138 struct iaddr lo
, hi
;
4140 enum dhcp_token token
;
4142 struct iaddrcidrnetlist
*nets
;
4143 struct iaddrcidrnetlist
*p
;
4144 struct ipv6_pond
*pond
= NULL
;
4146 if (local_family
!= AF_INET6
) {
4147 parse_warn(cfile
, "prefix6 statement is only supported "
4149 skip_to_semi(cfile
);
4153 /* This is enforced by the caller, so it's just a sanity check. */
4154 if (group
->subnet
== NULL
)
4155 log_fatal("Impossible condition at %s:%d.", MDL
);
4158 * Read starting and ending address.
4160 if (!parse_ip6_addr(cfile
, &lo
)) {
4164 /* Make sure starting prefix is within the subnet */
4165 if (!addr_eq(group
->subnet
->net
,
4166 subnet_number(lo
, group
->subnet
->netmask
))) {
4167 parse_warn(cfile
, "prefix6 start prefix"
4168 " is outside the subnet");
4169 skip_to_semi(cfile
);
4173 if (!parse_ip6_addr(cfile
, &hi
)) {
4177 /* Make sure ending prefix is within the subnet */
4178 if (!addr_eq(group
->subnet
->net
,
4179 subnet_number(hi
, group
->subnet
->netmask
))) {
4180 parse_warn(cfile
, "prefix6 end prefix"
4181 " is outside the subnet");
4182 skip_to_semi(cfile
);
4187 * Next is '/' number ';'.
4189 token
= next_token(NULL
, NULL
, cfile
);
4190 if (token
!= SLASH
) {
4191 parse_warn(cfile
, "expecting '/'");
4193 skip_to_semi(cfile
);
4196 token
= next_token(&val
, NULL
, cfile
);
4197 if (token
!= NUMBER
) {
4198 parse_warn(cfile
, "expecting number");
4200 skip_to_semi(cfile
);
4204 if ((bits
<= 0) || (bits
>= 128)) {
4205 parse_warn(cfile
, "networks have 0 to 128 bits (exclusive)");
4208 if (bits
< group
->subnet
->prefix_len
) {
4209 parse_warn(cfile
, "network mask smaller than subnet mask");
4210 skip_to_semi(cfile
);
4213 if (!is_cidr_mask_valid(&lo
, bits
) ||
4214 !is_cidr_mask_valid(&hi
, bits
)) {
4215 parse_warn(cfile
, "network mask too short");
4216 skip_to_semi(cfile
);
4219 token
= next_token(NULL
, NULL
, cfile
);
4220 if (token
!= SEMI
) {
4221 parse_warn(cfile
, "semicolon expected.");
4222 skip_to_semi(cfile
);
4227 * Convert our range to a set of CIDR networks.
4230 if (range2cidr(&nets
, &lo
, &hi
) != ISC_R_SUCCESS
) {
4231 log_fatal("Error converting prefix to CIDR");
4235 * See if we have a pond for this set of pools.
4236 * If the caller supplied one we use it, otherwise
4237 * check the shared network
4240 if (inpond
!= NULL
) {
4241 ipv6_pond_reference(&pond
, inpond
, MDL
);
4243 add_ipv6_pond_to_network(group
, &pond
);
4246 for (p
= nets
; p
!= NULL
; p
= p
->next
) {
4247 /* Normalize and check. */
4248 if (p
->cidrnet
.bits
== 128) {
4249 p
->cidrnet
.bits
= bits
;
4251 if (p
->cidrnet
.bits
> bits
) {
4252 parse_warn(cfile
, "impossible mask length");
4255 add_ipv6_pool_to_subnet(group
->subnet
, D6O_IA_PD
,
4256 &p
->cidrnet
.lo_addr
,
4257 p
->cidrnet
.bits
, bits
, pond
);
4260 free_iaddrcidrnetlist(&nets
);
4263 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4266 parse_fixed_prefix6(struct parse
*cfile
, struct host_decl
*host_decl
) {
4267 struct iaddrcidrnetlist
*ia
, **h
;
4268 enum dhcp_token token
;
4272 * Get the head of the fixed-prefix list.
4274 h
= &host_decl
->fixed_prefix
;
4279 while (*h
!= NULL
) {
4284 * Allocate a new iaddrcidrnetlist structure.
4286 ia
= dmalloc(sizeof(*ia
), MDL
);
4288 log_fatal("Out of memory");
4294 if (!parse_ip6_addr(cfile
, &ia
->cidrnet
.lo_addr
)) {
4298 token
= next_token(NULL
, NULL
, cfile
);
4299 if (token
!= SLASH
) {
4301 parse_warn(cfile
, "expecting '/'");
4303 skip_to_semi(cfile
);
4306 token
= next_token(&val
, NULL
, cfile
);
4307 if (token
!= NUMBER
) {
4309 parse_warn(cfile
, "expecting number");
4311 skip_to_semi(cfile
);
4314 token
= next_token(NULL
, NULL
, cfile
);
4315 if (token
!= SEMI
) {
4317 parse_warn(cfile
, "semicolon expected.");
4318 skip_to_semi(cfile
);
4325 ia
->cidrnet
.bits
= atoi(val
);
4326 if ((ia
->cidrnet
.bits
< 0) || (ia
->cidrnet
.bits
> 128)) {
4328 parse_warn(cfile
, "networks have 0 to 128 bits");
4331 if (!is_cidr_mask_valid(&ia
->cidrnet
.lo_addr
, ia
->cidrnet
.bits
)) {
4333 parse_warn(cfile
, "network mask too short");
4346 * \brief Parse a pool6 statement
4348 * Pool statements are used to group declarations and permit & deny information
4349 * with a specific address range. They must be declared within a shared network
4350 * or subnet and there may be multiple pools withing a shared network or subnet.
4351 * Each pool may have a different set of permit or deny options.
4353 * \param[in] cfile = the configuration file being parsed
4354 * \param[in] group = the group structure for this pool
4355 * \param[in] type = the type of the enclosing statement. This must be
4356 * SUBNET_DECL for this function.
4359 * void - This function either parses the statement and updates the structures
4360 * or it generates an error message and possible halts the program if
4361 * it encounters a problem.
4363 void parse_pool6_statement (cfile
, group
, type
)
4364 struct parse
*cfile
;
4365 struct group
*group
;
4368 enum dhcp_token token
;
4371 struct ipv6_pond
*pond
, **p
;
4372 int declaration
= 0;
4373 isc_result_t status
;
4376 status
= ipv6_pond_allocate(&pond
, MDL
);
4377 if (status
!= ISC_R_SUCCESS
)
4378 log_fatal("no memory for pool6: %s",
4379 isc_result_totext (status
));
4381 if (type
== SUBNET_DECL
)
4382 shared_network_reference(&pond
->shared_network
,
4383 group
->subnet
->shared_network
,
4386 parse_warn(cfile
, "pool6s are only valid inside "
4387 "subnet statements.");
4388 ipv6_pond_dereference(&pond
, MDL
);
4389 skip_to_semi(cfile
);
4393 if (clone_group(&pond
->group
, group
, MDL
) == 0)
4394 log_fatal("can't clone pool6 group.");
4396 if (parse_lbrace(cfile
) == 0) {
4397 ipv6_pond_dereference(&pond
, MDL
);
4402 token
= peek_token(&val
, NULL
, cfile
);
4405 skip_token(NULL
, NULL
, cfile
);
4406 parse_address_range6(cfile
, group
, pond
);
4410 skip_token(NULL
, NULL
, cfile
);
4411 parse_prefix6(cfile
, group
, pond
);
4415 skip_token(NULL
, NULL
, cfile
);
4416 get_permit(cfile
, &pond
->permit_list
, 1,
4417 &pond
->valid_from
, &pond
->valid_until
);
4421 skip_token(NULL
, NULL
, cfile
);
4422 get_permit(cfile
, &pond
->prohibit_list
, 0,
4423 &pond
->valid_from
, &pond
->valid_until
);
4427 skip_token(&val
, NULL
, cfile
);
4433 * We can get to END_OF_FILE if, for instance,
4434 * the parse_statement() reads all available tokens
4435 * and leaves us at the end.
4437 parse_warn(cfile
, "unexpected end of file");
4441 declaration
= parse_statement(cfile
, pond
->group
,
4449 * A possible optimization is to see if this pond can be merged into
4450 * an already existing pond. But I'll pass on that for now as we need
4451 * to repoint the leases to the other pond which is annoying. SAR
4455 * Add this pond to the list (will need updating if we add the
4459 p
= &pond
->shared_network
->ipv6_pond
;
4460 for (; *p
; p
= &((*p
)->next
))
4462 ipv6_pond_reference(p
, pond
, MDL
);
4464 /* Don't allow a pool6 declaration with no addresses or
4465 prefixes, since it is probably a configuration error. */
4466 if (pond
->ipv6_pools
== NULL
) {
4467 parse_warn (cfile
, "Pool6 declaration with no %s.",
4468 "address range6 or prefix6");
4469 log_error ("Pool6 declarations must always contain at least");
4470 log_error ("one range6 or prefix6 statement.");
4474 ipv6_pond_dereference(&pond
, MDL
);
4481 /* allow-deny-keyword :== BOOTP
4484 | UNKNOWN_CLIENTS */
4486 int parse_allow_deny (oc
, cfile
, flag
)
4487 struct option_cache
**oc
;
4488 struct parse
*cfile
;
4491 enum dhcp_token token
;
4493 unsigned char rf
= flag
;
4495 struct option
*option
= NULL
;
4496 struct expression
*data
= (struct expression
*)0;
4499 if (!make_const_data (&data
, &rf
, 1, 0, 1, MDL
))
4502 token
= next_token (&val
, (unsigned *)0, cfile
);
4505 code
= SV_ALLOW_BOOTP
;
4509 code
= SV_ALLOW_BOOTING
;
4513 code
= SV_DYNAMIC_BOOTP
;
4516 case UNKNOWN_CLIENTS
:
4517 code
= SV_BOOT_UNKNOWN_CLIENTS
;
4521 code
= SV_DUPLICATES
;
4528 case CLIENT_UPDATES
:
4529 code
= SV_CLIENT_UPDATES
;
4533 code
= SV_LEASEQUERY
;
4537 parse_warn (cfile
, "expecting allow/deny key");
4538 skip_to_semi (cfile
);
4539 expression_dereference (&data
, MDL
);
4542 /* Reference on option is passed to option cache. */
4543 if (!option_code_hash_lookup(&option
, server_universe
.code_hash
,
4545 log_fatal("Unable to find server option %u (%s:%d).",
4547 status
= option_cache(oc
, NULL
, data
, option
, MDL
);
4548 expression_dereference (&data
, MDL
);
4554 parse_ia_na_declaration(struct parse
*cfile
) {
4555 #if !defined(DHCPv6)
4556 parse_warn(cfile
, "No DHCPv6 support.");
4557 skip_to_semi(cfile
);
4558 #else /* defined(DHCPv6) */
4559 enum dhcp_token token
;
4562 struct ia_xx
*old_ia
;
4566 binding_state_t state
;
4570 struct iasubopt
*iaaddr
;
4571 struct ipv6_pool
*pool
;
4572 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4573 isc_boolean_t newbinding
;
4574 struct binding_scope
*scope
= NULL
;
4575 struct binding
*bnd
;
4576 struct binding_value
*nv
= NULL
;
4577 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
4580 if (local_family
!= AF_INET6
) {
4581 parse_warn(cfile
, "IA_NA is only supported in DHCPv6 mode.");
4582 skip_to_semi(cfile
);
4586 token
= next_token(&val
, &len
, cfile
);
4587 if (token
!= STRING
) {
4588 parse_warn(cfile
, "corrupt lease file; "
4589 "expecting an iaid+ia_na string");
4590 skip_to_semi(cfile
);
4594 parse_warn(cfile
, "corrupt lease file; "
4595 "iaid+ia_na string too short");
4596 skip_to_semi(cfile
);
4600 memcpy(&iaid
, val
, 4);
4602 if (ia_allocate(&ia
, iaid
, val
+4, len
-4, MDL
) != ISC_R_SUCCESS
) {
4603 log_fatal("Out of memory.");
4605 ia
->ia_type
= D6O_IA_NA
;
4607 token
= next_token(&val
, NULL
, cfile
);
4608 if (token
!= LBRACE
) {
4609 parse_warn(cfile
, "corrupt lease file; expecting left brace");
4610 skip_to_semi(cfile
);
4615 token
= next_token(&val
, NULL
, cfile
);
4616 if (token
== RBRACE
) break;
4618 if (token
== CLTT
) {
4619 ia
->cltt
= parse_date (cfile
);
4623 if (token
!= IAADDR
) {
4624 parse_warn(cfile
, "corrupt lease file; "
4625 "expecting IAADDR or right brace");
4626 skip_to_semi(cfile
);
4630 if (!parse_ip6_addr(cfile
, &iaddr
)) {
4631 parse_warn(cfile
, "corrupt lease file; "
4632 "expecting IPv6 address");
4633 skip_to_semi(cfile
);
4637 token
= next_token(&val
, NULL
, cfile
);
4638 if (token
!= LBRACE
) {
4639 parse_warn(cfile
, "corrupt lease file; "
4640 "expecting left brace");
4641 skip_to_semi(cfile
);
4649 token
= next_token(&val
, NULL
, cfile
);
4650 if (token
== RBRACE
) break;
4653 /* Lease binding state. */
4655 token
= next_token(&val
, NULL
, cfile
);
4656 if (token
!= STATE
) {
4657 parse_warn(cfile
, "corrupt lease file; "
4659 skip_to_semi(cfile
);
4662 token
= next_token(&val
, NULL
, cfile
);
4664 case TOKEN_ABANDONED
:
4665 state
= FTS_ABANDONED
;
4674 state
= FTS_EXPIRED
;
4676 case TOKEN_RELEASED
:
4677 state
= FTS_RELEASED
;
4685 skip_to_semi(cfile
);
4689 token
= next_token(&val
, NULL
, cfile
);
4690 if (token
!= SEMI
) {
4691 parse_warn(cfile
, "corrupt lease file; "
4697 /* Lease preferred lifetime. */
4698 case PREFERRED_LIFE
:
4699 token
= next_token(&val
, NULL
, cfile
);
4700 if (token
!= NUMBER
) {
4701 parse_warn(cfile
, "%s is not a valid "
4704 skip_to_semi(cfile
);
4707 prefer
= atoi (val
);
4710 * Currently we peek for the semi-colon to
4711 * allow processing of older lease files that
4712 * don't have the semi-colon. Eventually we
4713 * should remove the peeking code.
4715 token
= peek_token(&val
, NULL
, cfile
);
4716 if (token
== SEMI
) {
4717 skip_token(&val
, NULL
, cfile
);
4720 "corrupt lease file; "
4721 "expecting semicolon.");
4725 /* Lease valid lifetime. */
4727 token
= next_token(&val
, NULL
, cfile
);
4728 if (token
!= NUMBER
) {
4729 parse_warn(cfile
, "%s is not a valid "
4732 skip_to_semi(cfile
);
4738 * Currently we peek for the semi-colon to
4739 * allow processing of older lease files that
4740 * don't have the semi-colon. Eventually we
4741 * should remove the peeking code.
4743 token
= peek_token(&val
, NULL
, cfile
);
4744 if (token
== SEMI
) {
4745 skip_token(&val
, NULL
, cfile
);
4748 "corrupt lease file; "
4749 "expecting semicolon.");
4753 /* Lease expiration time. */
4755 end_time
= parse_date(cfile
);
4758 /* Lease binding scopes. */
4760 token
= next_token(&val
, NULL
, cfile
);
4761 if ((token
!= NAME
) &&
4762 (token
!= NUMBER_OR_NAME
)) {
4763 parse_warn(cfile
, "%s is not a valid "
4766 skip_to_semi(cfile
);
4771 bnd
= find_binding(scope
, val
);
4773 if (!binding_scope_allocate(&scope
,
4775 log_fatal("Out of memory for "
4784 bnd
= dmalloc(sizeof(*bnd
),
4787 log_fatal("No memory for "
4791 bnd
->name
= dmalloc(strlen(val
) + 1,
4793 if (bnd
->name
== NULL
) {
4794 log_fatal("No memory for "
4797 strcpy(bnd
->name
, val
);
4799 newbinding
= ISC_TRUE
;
4801 newbinding
= ISC_FALSE
;
4804 if (!binding_value_allocate(&nv
, MDL
)) {
4805 log_fatal("no memory for binding "
4809 token
= next_token(NULL
, NULL
, cfile
);
4810 if (token
!= EQUAL
) {
4811 parse_warn(cfile
, "expecting '=' in "
4816 if (!parse_binding_value(cfile
, nv
)) {
4818 binding_value_dereference(&nv
, MDL
);
4819 binding_scope_dereference(&scope
, MDL
);
4824 binding_value_reference(&bnd
->value
,
4826 bnd
->next
= scope
->bindings
;
4827 scope
->bindings
= bnd
;
4829 binding_value_dereference(&bnd
->value
,
4831 binding_value_reference(&bnd
->value
,
4835 binding_value_dereference(&nv
, MDL
);
4842 * Depending on the user config we may
4843 * have one or two on statements. We
4844 * need to save information about both
4845 * of them until we allocate the
4846 * iasubopt to hold them.
4848 if (on_star
[0] == NULL
) {
4849 if (!parse_on_statement (&on_star
[0],
4856 skip_to_rbrace (cfile
, 1);
4860 if (!parse_on_statement (&on_star
[1],
4867 skip_to_rbrace (cfile
, 1);
4875 parse_warn(cfile
, "corrupt lease file; "
4876 "expecting ia_na contents, "
4878 skip_to_semi(cfile
);
4883 if (state
== FTS_LAST
+1) {
4884 parse_warn(cfile
, "corrupt lease file; "
4885 "missing state in iaaddr");
4888 if (end_time
== -1) {
4889 parse_warn(cfile
, "corrupt lease file; "
4890 "missing end time in iaaddr");
4895 if (iasubopt_allocate(&iaaddr
, MDL
) != ISC_R_SUCCESS
) {
4896 log_fatal("Out of memory.");
4898 memcpy(&iaaddr
->addr
, iaddr
.iabuf
, sizeof(iaaddr
->addr
));
4900 iaaddr
->state
= state
;
4901 iaaddr
->prefer
= prefer
;
4902 iaaddr
->valid
= valid
;
4903 if (iaaddr
->state
== FTS_RELEASED
)
4904 iaaddr
->hard_lifetime_end_time
= end_time
;
4906 if (scope
!= NULL
) {
4907 binding_scope_reference(&iaaddr
->scope
, scope
, MDL
);
4908 binding_scope_dereference(&scope
, MDL
);
4912 * Check on both on statements. Because of how we write the
4913 * lease file we know which is which if we have two but it's
4914 * easier to write the code to be independent. We do assume
4915 * that the statements won't overlap.
4918 (i
< 2) && on_star
[i
] != NULL
;
4920 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
4921 on_star
[i
]->data
.on
.statements
) {
4922 executable_statement_reference
4923 (&iaaddr
->on_star
.on_expiry
,
4924 on_star
[i
]->data
.on
.statements
, MDL
);
4926 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
4927 on_star
[i
]->data
.on
.statements
) {
4928 executable_statement_reference
4929 (&iaaddr
->on_star
.on_release
,
4930 on_star
[i
]->data
.on
.statements
, MDL
);
4932 executable_statement_dereference (&on_star
[i
], MDL
);
4935 /* find the pool this address is in */
4937 if (find_ipv6_pool(&pool
, D6O_IA_NA
,
4938 &iaaddr
->addr
) != ISC_R_SUCCESS
) {
4939 inet_ntop(AF_INET6
, &iaaddr
->addr
,
4940 addr_buf
, sizeof(addr_buf
));
4941 parse_warn(cfile
, "no pool found for address %s",
4946 /* remove old information */
4947 if (cleanup_lease6(ia_na_active
, pool
,
4948 iaaddr
, ia
) != ISC_R_SUCCESS
) {
4949 inet_ntop(AF_INET6
, &iaaddr
->addr
,
4950 addr_buf
, sizeof(addr_buf
));
4951 parse_warn(cfile
, "duplicate na lease for address %s",
4956 * if we like the lease we add it to our various structues
4957 * otherwise we leave it and it will get cleaned when we
4958 * do the iasubopt_dereference.
4960 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
4961 ia_add_iasubopt(ia
, iaaddr
, MDL
);
4962 ia_reference(&iaaddr
->ia
, ia
, MDL
);
4963 add_lease6(pool
, iaaddr
, end_time
);
4966 iasubopt_dereference(&iaaddr
, MDL
);
4967 ipv6_pool_dereference(&pool
, MDL
);
4971 * If we have an existing record for this IA_NA, remove it.
4974 if (ia_hash_lookup(&old_ia
, ia_na_active
,
4975 (unsigned char *)ia
->iaid_duid
.data
,
4976 ia
->iaid_duid
.len
, MDL
)) {
4977 ia_hash_delete(ia_na_active
,
4978 (unsigned char *)ia
->iaid_duid
.data
,
4979 ia
->iaid_duid
.len
, MDL
);
4980 ia_dereference(&old_ia
, MDL
);
4984 * If we have addresses, add this, otherwise don't bother.
4986 if (ia
->num_iasubopt
> 0) {
4987 ia_hash_add(ia_na_active
,
4988 (unsigned char *)ia
->iaid_duid
.data
,
4989 ia
->iaid_duid
.len
, ia
, MDL
);
4991 ia_dereference(&ia
, MDL
);
4992 #endif /* defined(DHCPv6) */
4996 parse_ia_ta_declaration(struct parse
*cfile
) {
4997 #if !defined(DHCPv6)
4998 parse_warn(cfile
, "No DHCPv6 support.");
4999 skip_to_semi(cfile
);
5000 #else /* defined(DHCPv6) */
5001 enum dhcp_token token
;
5004 struct ia_xx
*old_ia
;
5008 binding_state_t state
;
5012 struct iasubopt
*iaaddr
;
5013 struct ipv6_pool
*pool
;
5014 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5015 isc_boolean_t newbinding
;
5016 struct binding_scope
*scope
= NULL
;
5017 struct binding
*bnd
;
5018 struct binding_value
*nv
= NULL
;
5019 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
5022 if (local_family
!= AF_INET6
) {
5023 parse_warn(cfile
, "IA_TA is only supported in DHCPv6 mode.");
5024 skip_to_semi(cfile
);
5028 token
= next_token(&val
, &len
, cfile
);
5029 if (token
!= STRING
) {
5030 parse_warn(cfile
, "corrupt lease file; "
5031 "expecting an iaid+ia_ta string");
5032 skip_to_semi(cfile
);
5036 parse_warn(cfile
, "corrupt lease file; "
5037 "iaid+ia_ta string too short");
5038 skip_to_semi(cfile
);
5042 memcpy(&iaid
, val
, 4);
5044 if (ia_allocate(&ia
, iaid
, val
+4, len
-4, MDL
) != ISC_R_SUCCESS
) {
5045 log_fatal("Out of memory.");
5047 ia
->ia_type
= D6O_IA_TA
;
5049 token
= next_token(&val
, NULL
, cfile
);
5050 if (token
!= LBRACE
) {
5051 parse_warn(cfile
, "corrupt lease file; expecting left brace");
5052 skip_to_semi(cfile
);
5057 token
= next_token(&val
, NULL
, cfile
);
5058 if (token
== RBRACE
) break;
5060 if (token
== CLTT
) {
5061 ia
->cltt
= parse_date (cfile
);
5065 if (token
!= IAADDR
) {
5066 parse_warn(cfile
, "corrupt lease file; "
5067 "expecting IAADDR or right brace");
5068 skip_to_semi(cfile
);
5072 if (!parse_ip6_addr(cfile
, &iaddr
)) {
5073 parse_warn(cfile
, "corrupt lease file; "
5074 "expecting IPv6 address");
5075 skip_to_semi(cfile
);
5079 token
= next_token(&val
, NULL
, cfile
);
5080 if (token
!= LBRACE
) {
5081 parse_warn(cfile
, "corrupt lease file; "
5082 "expecting left brace");
5083 skip_to_semi(cfile
);
5091 token
= next_token(&val
, NULL
, cfile
);
5092 if (token
== RBRACE
) break;
5095 /* Lease binding state. */
5097 token
= next_token(&val
, NULL
, cfile
);
5098 if (token
!= STATE
) {
5099 parse_warn(cfile
, "corrupt lease file; "
5101 skip_to_semi(cfile
);
5104 token
= next_token(&val
, NULL
, cfile
);
5106 case TOKEN_ABANDONED
:
5107 state
= FTS_ABANDONED
;
5116 state
= FTS_EXPIRED
;
5118 case TOKEN_RELEASED
:
5119 state
= FTS_RELEASED
;
5127 skip_to_semi(cfile
);
5131 token
= next_token(&val
, NULL
, cfile
);
5132 if (token
!= SEMI
) {
5133 parse_warn(cfile
, "corrupt lease file; "
5139 /* Lease preferred lifetime. */
5140 case PREFERRED_LIFE
:
5141 token
= next_token(&val
, NULL
, cfile
);
5142 if (token
!= NUMBER
) {
5143 parse_warn(cfile
, "%s is not a valid "
5146 skip_to_semi(cfile
);
5149 prefer
= atoi (val
);
5152 * Currently we peek for the semi-colon to
5153 * allow processing of older lease files that
5154 * don't have the semi-colon. Eventually we
5155 * should remove the peeking code.
5157 token
= peek_token(&val
, NULL
, cfile
);
5158 if (token
== SEMI
) {
5159 skip_token(&val
, NULL
, cfile
);
5162 "corrupt lease file; "
5163 "expecting semicolon.");
5167 /* Lease valid lifetime. */
5169 token
= next_token(&val
, NULL
, cfile
);
5170 if (token
!= NUMBER
) {
5171 parse_warn(cfile
, "%s is not a valid "
5174 skip_to_semi(cfile
);
5180 * Currently we peek for the semi-colon to
5181 * allow processing of older lease files that
5182 * don't have the semi-colon. Eventually we
5183 * should remove the peeking code.
5185 token
= peek_token(&val
, NULL
, cfile
);
5186 if (token
== SEMI
) {
5187 skip_token(&val
, NULL
, cfile
);
5190 "corrupt lease file; "
5191 "expecting semicolon.");
5195 /* Lease expiration time. */
5197 end_time
= parse_date(cfile
);
5200 /* Lease binding scopes. */
5202 token
= next_token(&val
, NULL
, cfile
);
5203 if ((token
!= NAME
) &&
5204 (token
!= NUMBER_OR_NAME
)) {
5205 parse_warn(cfile
, "%s is not a valid "
5208 skip_to_semi(cfile
);
5213 bnd
= find_binding(scope
, val
);
5215 if (!binding_scope_allocate(&scope
,
5217 log_fatal("Out of memory for "
5226 bnd
= dmalloc(sizeof(*bnd
),
5229 log_fatal("No memory for "
5233 bnd
->name
= dmalloc(strlen(val
) + 1,
5235 if (bnd
->name
== NULL
) {
5236 log_fatal("No memory for "
5239 strcpy(bnd
->name
, val
);
5241 newbinding
= ISC_TRUE
;
5243 newbinding
= ISC_FALSE
;
5246 if (!binding_value_allocate(&nv
, MDL
)) {
5247 log_fatal("no memory for binding "
5251 token
= next_token(NULL
, NULL
, cfile
);
5252 if (token
!= EQUAL
) {
5253 parse_warn(cfile
, "expecting '=' in "
5258 if (!parse_binding_value(cfile
, nv
)) {
5260 binding_value_dereference(&nv
, MDL
);
5261 binding_scope_dereference(&scope
, MDL
);
5266 binding_value_reference(&bnd
->value
,
5268 bnd
->next
= scope
->bindings
;
5269 scope
->bindings
= bnd
;
5271 binding_value_dereference(&bnd
->value
,
5273 binding_value_reference(&bnd
->value
,
5277 binding_value_dereference(&nv
, MDL
);
5284 * Depending on the user config we may
5285 * have one or two on statements. We
5286 * need to save information about both
5287 * of them until we allocate the
5288 * iasubopt to hold them.
5290 if (on_star
[0] == NULL
) {
5291 if (!parse_on_statement (&on_star
[0],
5298 skip_to_rbrace (cfile
, 1);
5302 if (!parse_on_statement (&on_star
[1],
5309 skip_to_rbrace (cfile
, 1);
5317 parse_warn(cfile
, "corrupt lease file; "
5318 "expecting ia_ta contents, "
5320 skip_to_semi(cfile
);
5325 if (state
== FTS_LAST
+1) {
5326 parse_warn(cfile
, "corrupt lease file; "
5327 "missing state in iaaddr");
5330 if (end_time
== -1) {
5331 parse_warn(cfile
, "corrupt lease file; "
5332 "missing end time in iaaddr");
5337 if (iasubopt_allocate(&iaaddr
, MDL
) != ISC_R_SUCCESS
) {
5338 log_fatal("Out of memory.");
5340 memcpy(&iaaddr
->addr
, iaddr
.iabuf
, sizeof(iaaddr
->addr
));
5342 iaaddr
->state
= state
;
5343 iaaddr
->prefer
= prefer
;
5344 iaaddr
->valid
= valid
;
5345 if (iaaddr
->state
== FTS_RELEASED
)
5346 iaaddr
->hard_lifetime_end_time
= end_time
;
5348 if (scope
!= NULL
) {
5349 binding_scope_reference(&iaaddr
->scope
, scope
, MDL
);
5350 binding_scope_dereference(&scope
, MDL
);
5354 * Check on both on statements. Because of how we write the
5355 * lease file we know which is which if we have two but it's
5356 * easier to write the code to be independent. We do assume
5357 * that the statements won't overlap.
5360 (i
< 2) && on_star
[i
] != NULL
;
5362 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
5363 on_star
[i
]->data
.on
.statements
) {
5364 executable_statement_reference
5365 (&iaaddr
->on_star
.on_expiry
,
5366 on_star
[i
]->data
.on
.statements
, MDL
);
5368 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
5369 on_star
[i
]->data
.on
.statements
) {
5370 executable_statement_reference
5371 (&iaaddr
->on_star
.on_release
,
5372 on_star
[i
]->data
.on
.statements
, MDL
);
5374 executable_statement_dereference (&on_star
[i
], MDL
);
5377 /* find the pool this address is in */
5379 if (find_ipv6_pool(&pool
, D6O_IA_TA
,
5380 &iaaddr
->addr
) != ISC_R_SUCCESS
) {
5381 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5382 addr_buf
, sizeof(addr_buf
));
5383 parse_warn(cfile
, "no pool found for address %s",
5388 /* remove old information */
5389 if (cleanup_lease6(ia_ta_active
, pool
,
5390 iaaddr
, ia
) != ISC_R_SUCCESS
) {
5391 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5392 addr_buf
, sizeof(addr_buf
));
5393 parse_warn(cfile
, "duplicate ta lease for address %s",
5398 * if we like the lease we add it to our various structues
5399 * otherwise we leave it and it will get cleaned when we
5400 * do the iasubopt_dereference.
5402 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
5403 ia_add_iasubopt(ia
, iaaddr
, MDL
);
5404 ia_reference(&iaaddr
->ia
, ia
, MDL
);
5405 add_lease6(pool
, iaaddr
, end_time
);
5408 ipv6_pool_dereference(&pool
, MDL
);
5409 iasubopt_dereference(&iaaddr
, MDL
);
5413 * If we have an existing record for this IA_TA, remove it.
5416 if (ia_hash_lookup(&old_ia
, ia_ta_active
,
5417 (unsigned char *)ia
->iaid_duid
.data
,
5418 ia
->iaid_duid
.len
, MDL
)) {
5419 ia_hash_delete(ia_ta_active
,
5420 (unsigned char *)ia
->iaid_duid
.data
,
5421 ia
->iaid_duid
.len
, MDL
);
5422 ia_dereference(&old_ia
, MDL
);
5426 * If we have addresses, add this, otherwise don't bother.
5428 if (ia
->num_iasubopt
> 0) {
5429 ia_hash_add(ia_ta_active
,
5430 (unsigned char *)ia
->iaid_duid
.data
,
5431 ia
->iaid_duid
.len
, ia
, MDL
);
5433 ia_dereference(&ia
, MDL
);
5434 #endif /* defined(DHCPv6) */
5438 parse_ia_pd_declaration(struct parse
*cfile
) {
5439 #if !defined(DHCPv6)
5440 parse_warn(cfile
, "No DHCPv6 support.");
5441 skip_to_semi(cfile
);
5442 #else /* defined(DHCPv6) */
5443 enum dhcp_token token
;
5446 struct ia_xx
*old_ia
;
5451 binding_state_t state
;
5455 struct iasubopt
*iapref
;
5456 struct ipv6_pool
*pool
;
5457 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5458 isc_boolean_t newbinding
;
5459 struct binding_scope
*scope
= NULL
;
5460 struct binding
*bnd
;
5461 struct binding_value
*nv
= NULL
;
5462 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
5465 if (local_family
!= AF_INET6
) {
5466 parse_warn(cfile
, "IA_PD is only supported in DHCPv6 mode.");
5467 skip_to_semi(cfile
);
5471 token
= next_token(&val
, &len
, cfile
);
5472 if (token
!= STRING
) {
5473 parse_warn(cfile
, "corrupt lease file; "
5474 "expecting an iaid+ia_pd string");
5475 skip_to_semi(cfile
);
5479 parse_warn(cfile
, "corrupt lease file; "
5480 "iaid+ia_pd string too short");
5481 skip_to_semi(cfile
);
5485 memcpy(&iaid
, val
, 4);
5487 if (ia_allocate(&ia
, iaid
, val
+4, len
-4, MDL
) != ISC_R_SUCCESS
) {
5488 log_fatal("Out of memory.");
5490 ia
->ia_type
= D6O_IA_PD
;
5492 token
= next_token(&val
, NULL
, cfile
);
5493 if (token
!= LBRACE
) {
5494 parse_warn(cfile
, "corrupt lease file; expecting left brace");
5495 skip_to_semi(cfile
);
5500 token
= next_token(&val
, NULL
, cfile
);
5501 if (token
== RBRACE
) break;
5503 if (token
== CLTT
) {
5504 ia
->cltt
= parse_date (cfile
);
5508 if (token
!= IAPREFIX
) {
5509 parse_warn(cfile
, "corrupt lease file; expecting "
5510 "IAPREFIX or right brace");
5511 skip_to_semi(cfile
);
5515 if (!parse_ip6_prefix(cfile
, &iaddr
, &plen
)) {
5516 parse_warn(cfile
, "corrupt lease file; "
5517 "expecting IPv6 prefix");
5518 skip_to_semi(cfile
);
5522 token
= next_token(&val
, NULL
, cfile
);
5523 if (token
!= LBRACE
) {
5524 parse_warn(cfile
, "corrupt lease file; "
5525 "expecting left brace");
5526 skip_to_semi(cfile
);
5534 token
= next_token(&val
, NULL
, cfile
);
5535 if (token
== RBRACE
) break;
5538 /* Prefix binding state. */
5540 token
= next_token(&val
, NULL
, cfile
);
5541 if (token
!= STATE
) {
5542 parse_warn(cfile
, "corrupt lease file; "
5544 skip_to_semi(cfile
);
5547 token
= next_token(&val
, NULL
, cfile
);
5549 case TOKEN_ABANDONED
:
5550 state
= FTS_ABANDONED
;
5559 state
= FTS_EXPIRED
;
5561 case TOKEN_RELEASED
:
5562 state
= FTS_RELEASED
;
5570 skip_to_semi(cfile
);
5574 token
= next_token(&val
, NULL
, cfile
);
5575 if (token
!= SEMI
) {
5576 parse_warn(cfile
, "corrupt lease file; "
5582 /* Lease preferred lifetime. */
5583 case PREFERRED_LIFE
:
5584 token
= next_token(&val
, NULL
, cfile
);
5585 if (token
!= NUMBER
) {
5586 parse_warn(cfile
, "%s is not a valid "
5589 skip_to_semi(cfile
);
5592 prefer
= atoi (val
);
5595 * Currently we peek for the semi-colon to
5596 * allow processing of older lease files that
5597 * don't have the semi-colon. Eventually we
5598 * should remove the peeking code.
5600 token
= peek_token(&val
, NULL
, cfile
);
5601 if (token
== SEMI
) {
5602 skip_token(&val
, NULL
, cfile
);
5605 "corrupt lease file; "
5606 "expecting semicolon.");
5610 /* Lease valid lifetime. */
5612 token
= next_token(&val
, NULL
, cfile
);
5613 if (token
!= NUMBER
) {
5614 parse_warn(cfile
, "%s is not a valid "
5617 skip_to_semi(cfile
);
5623 * Currently we peek for the semi-colon to
5624 * allow processing of older lease files that
5625 * don't have the semi-colon. Eventually we
5626 * should remove the peeking code.
5628 token
= peek_token(&val
, NULL
, cfile
);
5629 if (token
== SEMI
) {
5630 skip_token(&val
, NULL
, cfile
);
5633 "corrupt lease file; "
5634 "expecting semicolon.");
5638 /* Prefix expiration time. */
5640 end_time
= parse_date(cfile
);
5643 /* Prefix binding scopes. */
5645 token
= next_token(&val
, NULL
, cfile
);
5646 if ((token
!= NAME
) &&
5647 (token
!= NUMBER_OR_NAME
)) {
5648 parse_warn(cfile
, "%s is not a valid "
5651 skip_to_semi(cfile
);
5656 bnd
= find_binding(scope
, val
);
5658 if (!binding_scope_allocate(&scope
,
5660 log_fatal("Out of memory for "
5669 bnd
= dmalloc(sizeof(*bnd
),
5672 log_fatal("No memory for "
5676 bnd
->name
= dmalloc(strlen(val
) + 1,
5678 if (bnd
->name
== NULL
) {
5679 log_fatal("No memory for "
5682 strcpy(bnd
->name
, val
);
5684 newbinding
= ISC_TRUE
;
5686 newbinding
= ISC_FALSE
;
5689 if (!binding_value_allocate(&nv
, MDL
)) {
5690 log_fatal("no memory for binding "
5694 token
= next_token(NULL
, NULL
, cfile
);
5695 if (token
!= EQUAL
) {
5696 parse_warn(cfile
, "expecting '=' in "
5701 if (!parse_binding_value(cfile
, nv
)) {
5703 binding_value_dereference(&nv
, MDL
);
5704 binding_scope_dereference(&scope
, MDL
);
5709 binding_value_reference(&bnd
->value
,
5711 bnd
->next
= scope
->bindings
;
5712 scope
->bindings
= bnd
;
5714 binding_value_dereference(&bnd
->value
,
5716 binding_value_reference(&bnd
->value
,
5720 binding_value_dereference(&nv
, MDL
);
5727 * Depending on the user config we may
5728 * have one or two on statements. We
5729 * need to save information about both
5730 * of them until we allocate the
5731 * iasubopt to hold them.
5733 if (on_star
[0] == NULL
) {
5734 if (!parse_on_statement (&on_star
[0],
5741 skip_to_rbrace (cfile
, 1);
5745 if (!parse_on_statement (&on_star
[1],
5752 skip_to_rbrace (cfile
, 1);
5760 parse_warn(cfile
, "corrupt lease file; "
5761 "expecting ia_pd contents, "
5763 skip_to_semi(cfile
);
5768 if (state
== FTS_LAST
+1) {
5769 parse_warn(cfile
, "corrupt lease file; "
5770 "missing state in iaprefix");
5773 if (end_time
== -1) {
5774 parse_warn(cfile
, "corrupt lease file; "
5775 "missing end time in iaprefix");
5780 if (iasubopt_allocate(&iapref
, MDL
) != ISC_R_SUCCESS
) {
5781 log_fatal("Out of memory.");
5783 memcpy(&iapref
->addr
, iaddr
.iabuf
, sizeof(iapref
->addr
));
5784 iapref
->plen
= plen
;
5785 iapref
->state
= state
;
5786 iapref
->prefer
= prefer
;
5787 iapref
->valid
= valid
;
5788 if (iapref
->state
== FTS_RELEASED
)
5789 iapref
->hard_lifetime_end_time
= end_time
;
5791 if (scope
!= NULL
) {
5792 binding_scope_reference(&iapref
->scope
, scope
, MDL
);
5793 binding_scope_dereference(&scope
, MDL
);
5797 * Check on both on statements. Because of how we write the
5798 * lease file we know which is which if we have two but it's
5799 * easier to write the code to be independent. We do assume
5800 * that the statements won't overlap.
5803 (i
< 2) && on_star
[i
] != NULL
;
5805 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
5806 on_star
[i
]->data
.on
.statements
) {
5807 executable_statement_reference
5808 (&iapref
->on_star
.on_expiry
,
5809 on_star
[i
]->data
.on
.statements
, MDL
);
5811 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
5812 on_star
[i
]->data
.on
.statements
) {
5813 executable_statement_reference
5814 (&iapref
->on_star
.on_release
,
5815 on_star
[i
]->data
.on
.statements
, MDL
);
5817 executable_statement_dereference (&on_star
[i
], MDL
);
5820 /* find the pool this address is in */
5822 if (find_ipv6_pool(&pool
, D6O_IA_PD
,
5823 &iapref
->addr
) != ISC_R_SUCCESS
) {
5824 inet_ntop(AF_INET6
, &iapref
->addr
,
5825 addr_buf
, sizeof(addr_buf
));
5826 parse_warn(cfile
, "no pool found for address %s",
5831 /* remove old information */
5832 if (cleanup_lease6(ia_pd_active
, pool
,
5833 iapref
, ia
) != ISC_R_SUCCESS
) {
5834 inet_ntop(AF_INET6
, &iapref
->addr
,
5835 addr_buf
, sizeof(addr_buf
));
5836 parse_warn(cfile
, "duplicate pd lease for address %s",
5841 * if we like the lease we add it to our various structues
5842 * otherwise we leave it and it will get cleaned when we
5843 * do the iasubopt_dereference.
5845 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
5846 ia_add_iasubopt(ia
, iapref
, MDL
);
5847 ia_reference(&iapref
->ia
, ia
, MDL
);
5848 add_lease6(pool
, iapref
, end_time
);
5851 ipv6_pool_dereference(&pool
, MDL
);
5852 iasubopt_dereference(&iapref
, MDL
);
5856 * If we have an existing record for this IA_PD, remove it.
5859 if (ia_hash_lookup(&old_ia
, ia_pd_active
,
5860 (unsigned char *)ia
->iaid_duid
.data
,
5861 ia
->iaid_duid
.len
, MDL
)) {
5862 ia_hash_delete(ia_pd_active
,
5863 (unsigned char *)ia
->iaid_duid
.data
,
5864 ia
->iaid_duid
.len
, MDL
);
5865 ia_dereference(&old_ia
, MDL
);
5869 * If we have prefixes, add this, otherwise don't bother.
5871 if (ia
->num_iasubopt
> 0) {
5872 ia_hash_add(ia_pd_active
,
5873 (unsigned char *)ia
->iaid_duid
.data
,
5874 ia
->iaid_duid
.len
, ia
, MDL
);
5876 ia_dereference(&ia
, MDL
);
5877 #endif /* defined(DHCPv6) */
5882 * When we parse a server-duid statement in a lease file, we are
5883 * looking at the saved server DUID from a previous run. In this case
5884 * we expect it to be followed by the binary representation of the
5885 * DUID stored in a string:
5887 * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
5890 parse_server_duid(struct parse
*cfile
) {
5891 enum dhcp_token token
;
5894 struct data_string duid
;
5896 token
= next_token(&val
, &len
, cfile
);
5897 if (token
!= STRING
) {
5898 parse_warn(cfile
, "corrupt lease file; expecting a DUID");
5899 skip_to_semi(cfile
);
5903 memset(&duid
, 0, sizeof(duid
));
5905 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
5906 log_fatal("Out of memory storing DUID");
5908 duid
.data
= (unsigned char *)duid
.buffer
->data
;
5909 memcpy(duid
.buffer
->data
, val
, len
);
5911 set_server_duid(&duid
);
5913 data_string_forget(&duid
, MDL
);
5915 token
= next_token(&val
, &len
, cfile
);
5916 if (token
!= SEMI
) {
5917 parse_warn(cfile
, "corrupt lease file; expecting a semicolon");
5918 skip_to_semi(cfile
);
5924 * When we parse a server-duid statement in a config file, we will
5925 * have the type of the server DUID to generate, and possibly the
5926 * actual value defined.
5929 * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
5931 * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
5932 * server-duid en 2495 "enterprise-specific-identifier-1234";
5935 parse_server_duid_conf(struct parse
*cfile
) {
5936 enum dhcp_token token
;
5939 u_int32_t enterprise_number
;
5941 struct data_string ll_addr
;
5943 struct data_string duid
;
5947 * Consume the SERVER_DUID token.
5949 skip_token(NULL
, NULL
, cfile
);
5952 * Obtain the DUID type.
5954 token
= next_token(&val
, NULL
, cfile
);
5957 * Enterprise is the easiest - enterprise number and raw data
5962 * Get enterprise number and identifier.
5964 token
= next_token(&val
, NULL
, cfile
);
5965 if (token
!= NUMBER
) {
5966 parse_warn(cfile
, "enterprise number expected");
5967 skip_to_semi(cfile
);
5970 enterprise_number
= atoi(val
);
5972 token
= next_token(&val
, &len
, cfile
);
5973 if (token
!= STRING
) {
5974 parse_warn(cfile
, "identifier expected");
5975 skip_to_semi(cfile
);
5982 memset(&duid
, 0, sizeof(duid
));
5983 duid
.len
= 2 + 4 + len
;
5984 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
5985 log_fatal("Out of memory storing DUID");
5987 duid
.data
= (unsigned char *)duid
.buffer
->data
;
5988 putUShort(duid
.buffer
->data
, DUID_EN
);
5989 putULong(duid
.buffer
->data
+ 2, enterprise_number
);
5990 memcpy(duid
.buffer
->data
+ 6, val
, len
);
5992 set_server_duid(&duid
);
5993 data_string_forget(&duid
, MDL
);
5997 * Next easiest is the link-layer DUID. It consists only of
5998 * the LL directive, or optionally the specific value to use.
6000 * If we have LL only, then we set the type. If we have the
6001 * value, then we set the actual DUID.
6003 else if (token
== LL
) {
6004 if (peek_token(NULL
, NULL
, cfile
) == SEMI
) {
6005 set_server_duid_type(DUID_LL
);
6008 * Get our hardware type and address.
6010 token
= next_token(NULL
, NULL
, cfile
);
6013 ll_type
= HTYPE_ETHER
;
6016 ll_type
= HTYPE_IEEE802
;
6019 ll_type
= HTYPE_FDDI
;
6022 parse_warn(cfile
, "hardware type expected");
6023 skip_to_semi(cfile
);
6026 memset(&ll_addr
, 0, sizeof(ll_addr
));
6027 if (!parse_cshl(&ll_addr
, cfile
)) {
6034 memset(&duid
, 0, sizeof(duid
));
6035 duid
.len
= 2 + 2 + ll_addr
.len
;
6036 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6037 log_fatal("Out of memory storing DUID");
6039 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6040 putUShort(duid
.buffer
->data
, DUID_LL
);
6041 putUShort(duid
.buffer
->data
+ 2, ll_type
);
6042 memcpy(duid
.buffer
->data
+ 4,
6043 ll_addr
.data
, ll_addr
.len
);
6045 set_server_duid(&duid
);
6046 data_string_forget(&duid
, MDL
);
6047 data_string_forget(&ll_addr
, MDL
);
6052 * Finally the link-layer DUID plus time. It consists only of
6053 * the LLT directive, or optionally the specific value to use.
6055 * If we have LLT only, then we set the type. If we have the
6056 * value, then we set the actual DUID.
6058 else if (token
== LLT
) {
6059 if (peek_token(NULL
, NULL
, cfile
) == SEMI
) {
6060 set_server_duid_type(DUID_LLT
);
6063 * Get our hardware type, timestamp, and address.
6065 token
= next_token(NULL
, NULL
, cfile
);
6068 ll_type
= HTYPE_ETHER
;
6071 ll_type
= HTYPE_IEEE802
;
6074 ll_type
= HTYPE_FDDI
;
6077 parse_warn(cfile
, "hardware type expected");
6078 skip_to_semi(cfile
);
6082 token
= next_token(&val
, NULL
, cfile
);
6083 if (token
!= NUMBER
) {
6084 parse_warn(cfile
, "timestamp expected");
6085 skip_to_semi(cfile
);
6088 llt_time
= atoi(val
);
6090 memset(&ll_addr
, 0, sizeof(ll_addr
));
6091 if (!parse_cshl(&ll_addr
, cfile
)) {
6098 memset(&duid
, 0, sizeof(duid
));
6099 duid
.len
= 2 + 2 + 4 + ll_addr
.len
;
6100 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6101 log_fatal("Out of memory storing DUID");
6103 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6104 putUShort(duid
.buffer
->data
, DUID_LLT
);
6105 putUShort(duid
.buffer
->data
+ 2, ll_type
);
6106 putULong(duid
.buffer
->data
+ 4, llt_time
);
6107 memcpy(duid
.buffer
->data
+ 8,
6108 ll_addr
.data
, ll_addr
.len
);
6110 set_server_duid(&duid
);
6111 data_string_forget(&duid
, MDL
);
6112 data_string_forget(&ll_addr
, MDL
);
6117 * If users want they can use a number for DUID types.
6118 * This is useful for supporting future, not-yet-defined
6121 * In this case, they have to put in the complete value.
6123 * This also works for existing DUID types of course.
6125 else if (token
== NUMBER
) {
6126 duid_type_num
= atoi(val
);
6128 token
= next_token(&val
, &len
, cfile
);
6129 if (token
!= STRING
) {
6130 parse_warn(cfile
, "identifier expected");
6131 skip_to_semi(cfile
);
6138 memset(&duid
, 0, sizeof(duid
));
6140 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6141 log_fatal("Out of memory storing DUID");
6143 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6144 putUShort(duid
.buffer
->data
, duid_type_num
);
6145 memcpy(duid
.buffer
->data
+ 2, val
, len
);
6147 set_server_duid(&duid
);
6148 data_string_forget(&duid
, MDL
);
6152 * Anything else is an error.
6155 parse_warn(cfile
, "DUID type of LLT, EN, or LL expected");
6156 skip_to_semi(cfile
);
6161 * Finally consume our trailing semicolon.
6163 token
= next_token(NULL
, NULL
, cfile
);
6164 if (token
!= SEMI
) {
6165 parse_warn(cfile
, "semicolon expected");
6166 skip_to_semi(cfile
);