3 Parser for dhcpd config file... */
6 * Copyright (c) 2004-2016 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
);
38 static void parse_authoring_byte_order (struct parse
*cfile
);
39 static void parse_lease_id_format (struct parse
*cfile
);
41 static int parse_iaid_duid(struct parse
*cfile
, struct ia_xx
** ia
,
42 u_int32_t
*iaid
, const char* file
, int line
);
46 trace_type_t
*trace_readconf_type
;
47 trace_type_t
*trace_readleases_type
;
49 void parse_trace_setup ()
51 trace_readconf_type
= trace_type_register ("readconf", (void *)0,
53 trace_conf_stop
, MDL
);
54 trace_readleases_type
= trace_type_register ("readleases", (void *)0,
56 trace_conf_stop
, MDL
);
60 /* conf-file :== parameters declarations END_OF_FILE
61 parameters :== <nil> | parameter | parameters parameter
62 declarations :== <nil> | declaration | declarations declaration */
64 isc_result_t
readconf ()
68 res
= read_conf_file (path_dhcpd_conf
, root_group
, ROOT_GROUP
, 0);
69 #if defined(LDAP_CONFIGURATION)
70 if (res
!= ISC_R_SUCCESS
)
73 return ldap_read_config ();
79 isc_result_t
read_conf_file (const char *filename
, struct group
*group
,
80 int group_type
, int leasep
)
93 ttype
= trace_readleases_type
;
95 ttype
= trace_readconf_type
;
97 /* If we're in playback, we need to snarf the contents of the
98 named file out of the playback file rather than trying to
100 if (trace_playback ()) {
103 status
= trace_get_file (ttype
, filename
, &tflen
, &dbuf
);
104 if (status
!= ISC_R_SUCCESS
)
108 /* What we get back is filename\0contents, where contents is
109 terminated just by the length. So we figure out the length
110 of the filename, and subtract that and the NUL from the
111 total length to get the length of the contents of the file.
112 We make fbuf a pointer to the contents of the file, and
113 leave dbuf as it is so we can free it later. */
114 tflen
= strlen (dbuf
);
115 ulen
= ulen
- tflen
- 1;
116 fbuf
= dbuf
+ tflen
+ 1;
121 if ((file
= open (filename
, O_RDONLY
)) < 0) {
123 log_error ("Can't open lease database %s: %m --",
125 log_error (" check for failed database %s!",
127 log_error ("Please read the dhcpd.leases manual%s",
129 log_fatal ("don't know what to do about this.");
131 log_fatal ("Can't open %s: %m", filename
);
135 cfile
= (struct parse
*)0;
136 #if defined (TRACING)
137 flen
= lseek (file
, (off_t
)0, SEEK_END
);
140 log_fatal ("Can't lseek on %s: %m", filename
);
142 if (lseek (file
, (off_t
)0, SEEK_SET
) < 0)
144 /* Can't handle files greater than 2^31-1. */
145 if (flen
> 0x7FFFFFFFUL
)
146 log_fatal ("%s: file is too long to buffer.", filename
);
149 /* Allocate a buffer that will be what's written to the tracefile,
150 and also will be what we parse from. */
151 tflen
= strlen (filename
);
152 dbuf
= dmalloc (ulen
+ tflen
+ 1, MDL
);
154 log_fatal ("No memory for %s (%d bytes)",
157 /* Copy the name into the beginning, nul-terminated. */
158 strcpy (dbuf
, filename
);
160 /* Load the file in after the NUL. */
161 fbuf
= dbuf
+ tflen
+ 1;
162 result
= read (file
, fbuf
, ulen
);
164 log_fatal ("Can't read in %s: %m", filename
);
166 log_fatal ("%s: short read of %d bytes instead of %d.",
167 filename
, ulen
, result
);
170 /* If we're recording, write out the filename and file contents. */
172 trace_write_packet (ttype
, ulen
+ tflen
+ 1, dbuf
, MDL
);
173 status
= new_parse(&cfile
, -1, fbuf
, ulen
, filename
, 0); /* XXX */
175 status
= new_parse(&cfile
, file
, NULL
, 0, filename
, 0);
177 if (status
!= ISC_R_SUCCESS
|| cfile
== NULL
)
181 status
= lease_file_subparse (cfile
);
183 status
= conf_file_subparse (cfile
, group
, group_type
);
185 #if defined (TRACING)
191 #if defined (TRACING)
192 void trace_conf_input (trace_type_t
*ttype
, unsigned len
, char *data
)
197 struct parse
*cfile
= (struct parse
*)0;
198 static int postconf_initialized
;
199 static int leaseconf_initialized
;
202 /* Do what's done above, except that we don't have to read in the
203 data, because it's already been read for us. */
204 tflen
= strlen (data
);
205 flen
= len
- tflen
- 1;
206 fbuf
= data
+ tflen
+ 1;
208 /* If we're recording, write out the filename and file contents. */
210 trace_write_packet (ttype
, len
, data
, MDL
);
212 status
= new_parse(&cfile
, -1, fbuf
, flen
, data
, 0);
213 if (status
== ISC_R_SUCCESS
|| cfile
!= NULL
) {
214 if (ttype
== trace_readleases_type
)
215 lease_file_subparse (cfile
);
217 conf_file_subparse (cfile
, root_group
, ROOT_GROUP
);
221 /* Postconfiguration needs to be done after the config file
223 if (!postconf_initialized
&& ttype
== trace_readconf_type
) {
224 postconf_initialization (0);
225 postconf_initialized
= 1;
228 if (!leaseconf_initialized
&& ttype
== trace_readleases_type
) {
230 leaseconf_initialized
= 1;
235 void trace_conf_stop (trace_type_t
*ttype
) { }
238 /* conf-file :== parameters declarations END_OF_FILE
239 parameters :== <nil> | parameter | parameters parameter
240 declarations :== <nil> | declaration | declarations declaration */
242 isc_result_t
conf_file_subparse (struct parse
*cfile
, struct group
*group
,
246 enum dhcp_token token
;
251 token
= peek_token (&val
, (unsigned *)0, cfile
);
252 if (token
== END_OF_FILE
)
254 declaration
= parse_statement (cfile
, group
, group_type
,
255 (struct host_decl
*)0,
258 skip_token(&val
, (unsigned *)0, cfile
);
260 status
= cfile
->warnings_occurred
? DHCP_R_BADPARSE
: ISC_R_SUCCESS
;
264 /* lease-file :== lease-declarations END_OF_FILE
265 lease-statements :== <nil>
267 | lease-declarations lease-declaration */
269 isc_result_t
lease_file_subparse (struct parse
*cfile
)
272 enum dhcp_token token
;
276 token
= next_token (&val
, (unsigned *)0, cfile
);
277 if (token
== END_OF_FILE
)
279 if (token
== LEASE
) {
280 struct lease
*lease
= (struct lease
*)0;
281 if (parse_lease_declaration (&lease
, cfile
)) {
283 lease_dereference (&lease
, MDL
);
286 "possibly corrupt lease file");
287 } else if (token
== IA_NA
) {
288 parse_ia_na_declaration(cfile
);
289 } else if (token
== IA_TA
) {
290 parse_ia_ta_declaration(cfile
);
291 } else if (token
== IA_PD
) {
292 parse_ia_pd_declaration(cfile
);
293 } else if (token
== CLASS
) {
294 parse_class_declaration(0, cfile
, root_group
,
296 } else if (token
== SUBCLASS
) {
297 parse_class_declaration(0, cfile
, root_group
,
298 CLASS_TYPE_SUBCLASS
);
299 } else if (token
== HOST
) {
300 parse_host_declaration (cfile
, root_group
);
301 } else if (token
== GROUP
) {
302 parse_group_declaration (cfile
, root_group
);
303 #if defined (FAILOVER_PROTOCOL)
304 } else if (token
== FAILOVER
) {
305 parse_failover_state_declaration
306 (cfile
, (dhcp_failover_state_t
*)0);
309 } else if (token
== SERVER_DUID
) {
310 parse_server_duid(cfile
);
312 } else if (token
== AUTHORING_BYTE_ORDER
) {
313 parse_authoring_byte_order(cfile
);
315 log_error ("Corrupt lease file - possible data loss!");
316 skip_to_semi (cfile
);
321 status
= cfile
->warnings_occurred
? DHCP_R_BADPARSE
: ISC_R_SUCCESS
;
325 /* statement :== parameter | declaration
327 parameter :== DEFAULT_LEASE_TIME lease_time
328 | MAX_LEASE_TIME lease_time
329 | DYNAMIC_BOOTP_LEASE_CUTOFF date
330 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
331 | BOOT_UNKNOWN_CLIENTS boolean
332 | ONE_LEASE_PER_CLIENT boolean
333 | GET_LEASE_HOSTNAMES boolean
334 | USE_HOST_DECL_NAME boolean
335 | NEXT_SERVER ip-addr-or-hostname SEMI
337 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
338 | FILENAME string-parameter
339 | SERVER_NAME string-parameter
341 | fixed-address-parameter
342 | ALLOW allow-deny-keyword
343 | DENY allow-deny-keyword
344 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
348 declaration :== host-declaration
350 | shared-network-declaration
352 | VENDOR_CLASS class-declaration
353 | USER_CLASS class-declaration
354 | RANGE address-range-declaration */
356 int parse_statement (cfile
, group
, type
, host_decl
, declaration
)
360 struct host_decl
*host_decl
;
363 enum dhcp_token token
;
365 struct shared_network
*share
;
367 struct hardware hardware
;
368 struct executable_statement
*et
, *ep
;
369 struct option
*option
= NULL
;
370 struct option_cache
*cache
;
376 token
= peek_token (&val
, (unsigned *)0, cfile
);
380 skip_token(&val
, (unsigned *)0, cfile
);
381 token
= next_token (&val
, (unsigned *)0, cfile
);
382 if (token
!= STRING
) {
383 parse_warn (cfile
, "filename string expected.");
384 skip_to_semi (cfile
);
386 status
= read_conf_file (val
, group
, type
, 0);
387 if (status
!= ISC_R_SUCCESS
)
388 parse_warn (cfile
, "%s: bad parse.", val
);
394 skip_token(&val
, (unsigned *)0, cfile
);
395 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
) {
396 if (global_host_once
&&
397 (type
== SUBNET_DECL
|| type
== SHARED_NET_DECL
)) {
398 global_host_once
= 0;
399 log_error("WARNING: Host declarations are "
400 "global. They are not limited to "
401 "the scope you declared them in.");
404 parse_host_declaration (cfile
, group
);
407 "host declarations not allowed here.");
408 skip_to_semi (cfile
);
413 skip_token(&val
, (unsigned *)0, cfile
);
414 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
415 parse_group_declaration (cfile
, group
);
418 "group declarations not allowed here.");
419 skip_to_semi (cfile
);
424 skip_token(&val
, (unsigned *)0, cfile
);
425 if (type
== SHARED_NET_DECL
||
427 type
== SUBNET_DECL
||
428 type
== CLASS_DECL
) {
429 parse_warn (cfile
, "shared-network parameters not %s.",
431 skip_to_semi (cfile
);
435 parse_shared_net_declaration (cfile
, group
);
440 skip_token(&val
, (unsigned *)0, cfile
);
441 if (type
== HOST_DECL
|| type
== SUBNET_DECL
||
442 type
== CLASS_DECL
) {
444 "subnet declarations not allowed here.");
445 skip_to_semi (cfile
);
449 /* If we're in a subnet declaration, just do the parse. */
450 if (group
->shared_network
!= NULL
) {
451 if (token
== SUBNET
) {
452 parse_subnet_declaration(cfile
,
453 group
->shared_network
);
455 parse_subnet6_declaration(cfile
,
456 group
->shared_network
);
462 * Otherwise, cons up a fake shared network structure
463 * and populate it with the lone subnet...because the
464 * intention most likely is to refer to the entire link
465 * by shorthand, any configuration inside the subnet is
466 * actually placed in the shared-network's group.
470 status
= shared_network_allocate (&share
, MDL
);
471 if (status
!= ISC_R_SUCCESS
)
472 log_fatal ("Can't allocate shared subnet: %s",
473 isc_result_totext (status
));
474 if (!clone_group (&share
-> group
, group
, MDL
))
475 log_fatal ("Can't allocate group for shared net");
476 shared_network_reference (&share
-> group
-> shared_network
,
480 * This is an implicit shared network, not explicit in
483 share
->flags
|= SHARED_IMPLICIT
;
485 if (token
== SUBNET
) {
486 parse_subnet_declaration(cfile
, share
);
488 parse_subnet6_declaration(cfile
, share
);
491 /* share -> subnets is the subnet we just parsed. */
492 if (share
->subnets
) {
493 interface_reference(&share
->interface
,
494 share
->subnets
->interface
,
497 /* Make the shared network name from network number. */
498 if (token
== SUBNET
) {
499 n
= piaddrmask(&share
->subnets
->net
,
500 &share
->subnets
->netmask
);
502 n
= piaddrcidr(&share
->subnets
->net
,
503 share
->subnets
->prefix_len
);
506 share
->name
= strdup(n
);
508 if (share
->name
== NULL
)
509 log_fatal("Out of memory allocating default "
510 "shared network name (\"%s\").", n
);
512 /* Copy the authoritative parameter from the subnet,
513 since there is no opportunity to declare it here. */
514 share
->group
->authoritative
=
515 share
->subnets
->group
->authoritative
;
516 enter_shared_network(share
);
518 shared_network_dereference(&share
, MDL
);
522 skip_token(&val
, (unsigned *)0, cfile
);
523 if (type
== CLASS_DECL
) {
525 "class declarations not allowed here.");
526 skip_to_semi (cfile
);
529 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_VENDOR
);
533 skip_token(&val
, (unsigned *)0, cfile
);
534 if (type
== CLASS_DECL
) {
536 "class declarations not allowed here.");
537 skip_to_semi (cfile
);
540 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_USER
);
544 skip_token(&val
, (unsigned *)0, cfile
);
545 if (type
== CLASS_DECL
) {
547 "class declarations not allowed here.");
548 skip_to_semi (cfile
);
551 parse_class_declaration(NULL
, cfile
, group
, CLASS_TYPE_CLASS
);
555 skip_token(&val
, (unsigned *)0, cfile
);
556 if (type
== CLASS_DECL
) {
558 "class declarations not allowed here.");
559 skip_to_semi (cfile
);
562 parse_class_declaration(NULL
, cfile
, group
,
563 CLASS_TYPE_SUBCLASS
);
567 skip_token(&val
, (unsigned *)0, cfile
);
568 memset (&hardware
, 0, sizeof hardware
);
569 if (host_decl
&& memcmp(&hardware
, &(host_decl
->interface
),
570 sizeof(hardware
)) != 0) {
571 parse_warn(cfile
, "Host %s hardware address already "
572 "configured.", host_decl
->name
);
576 parse_hardware_param (cfile
, &hardware
);
578 host_decl
-> interface
= hardware
;
580 parse_warn (cfile
, "hardware address parameter %s",
581 "not allowed here.");
586 skip_token(&val
, NULL
, cfile
);
588 if (parse_fixed_addr_param(&cache
, cfile
, token
)) {
590 if (host_decl
->fixed_addr
) {
591 option_cache_dereference(&cache
, MDL
);
593 "Only one fixed address "
594 "declaration per host.");
596 host_decl
->fixed_addr
= cache
;
600 "fixed-address parameter not "
602 option_cache_dereference(&cache
, MDL
);
608 skip_token(&val
, (unsigned *)0, cfile
);
609 if (type
== POOL_DECL
) {
610 parse_warn (cfile
, "pool declared within pool.");
612 } else if (type
!= SUBNET_DECL
&& type
!= SHARED_NET_DECL
) {
613 parse_warn (cfile
, "pool declared outside of network");
616 parse_pool_statement (cfile
, group
, type
);
621 skip_token(&val
, (unsigned *)0, cfile
);
622 if (type
!= SUBNET_DECL
|| !group
-> subnet
) {
624 "range declaration not allowed here.");
625 skip_to_semi (cfile
);
628 parse_address_range (cfile
, group
, type
, (struct pool
*)0,
634 skip_token(NULL
, NULL
, cfile
);
635 if ((type
!= SUBNET_DECL
) || (group
->subnet
== NULL
)) {
637 "range6 declaration not allowed here.");
641 parse_address_range6(cfile
, group
, NULL
);
645 skip_token(NULL
, NULL
, cfile
);
646 if ((type
!= SUBNET_DECL
) || (group
->subnet
== NULL
)) {
648 "prefix6 declaration not allowed here.");
652 parse_prefix6(cfile
, group
, NULL
);
656 skip_token(&val
, NULL
, cfile
);
659 "fixed-prefix6 declaration not "
664 parse_fixed_prefix6(cfile
, host_decl
);
668 skip_token(&val
, NULL
, cfile
);
669 if (type
== POOL_DECL
) {
670 parse_warn (cfile
, "pool6 declared within pool.");
672 } else if (type
!= SUBNET_DECL
) {
673 parse_warn (cfile
, "pool6 declared outside of network");
676 parse_pool6_statement (cfile
, group
, type
);
683 skip_token(&val
, (unsigned *)0, cfile
);
684 token
= next_token (&val
, (unsigned *)0, cfile
);
687 group
-> authoritative
= 0;
690 parse_warn (cfile
, "expecting assertion");
691 skip_to_semi (cfile
);
696 skip_token(&val
, (unsigned *)0, cfile
);
697 group
-> authoritative
= 1;
699 if (type
== HOST_DECL
)
700 parse_warn (cfile
, "authority makes no sense here.");
704 /* "server-identifier" is a special hack, equivalent to
705 "option dhcp-server-identifier". */
706 case SERVER_IDENTIFIER
:
707 code
= DHO_DHCP_SERVER_IDENTIFIER
;
708 if (!option_code_hash_lookup(&option
, dhcp_universe
.code_hash
,
710 log_fatal("Server identifier not in hash (%s:%d).",
712 skip_token(&val
, (unsigned *)0, cfile
);
716 skip_token(&val
, (unsigned *)0, cfile
);
717 token
= peek_token (&val
, (unsigned *)0, cfile
);
718 if (token
== SPACE
) {
719 if (type
!= ROOT_GROUP
) {
721 "option space definitions %s",
722 "may not be scoped.");
723 skip_to_semi (cfile
);
726 parse_option_space_decl (cfile
);
731 status
= parse_option_name(cfile
, 1, &known
, &option
);
732 if (status
== ISC_R_SUCCESS
) {
733 token
= peek_token (&val
, (unsigned *)0, cfile
);
735 if (type
!= ROOT_GROUP
) {
737 "option definitions%s",
738 " may not be scoped.");
739 skip_to_semi (cfile
);
740 option_dereference(&option
, MDL
);
743 skip_token(&val
, (unsigned *)0, cfile
);
746 * If the option was known, remove it from the
747 * code and name hashes before redefining it.
750 option_name_hash_delete(
751 option
->universe
->name_hash
,
752 option
->name
, 0, MDL
);
753 option_code_hash_delete(
754 option
->universe
->code_hash
,
755 &option
->code
, 0, MDL
);
758 parse_option_code_definition(cfile
, option
);
759 option_dereference(&option
, MDL
);
763 /* If this wasn't an option code definition, don't
764 allow an unknown option. */
766 parse_warn (cfile
, "unknown option %s.%s",
767 option
-> universe
-> name
,
769 skip_to_semi (cfile
);
770 option_dereference(&option
, MDL
);
775 et
= (struct executable_statement
*)0;
776 if (!parse_option_statement
777 (&et
, cfile
, 1, option
,
778 supersede_option_statement
))
780 option_dereference(&option
, MDL
);
781 goto insert_statement
;
788 if (type
!= ROOT_GROUP
&& type
!= SHARED_NET_DECL
) {
789 parse_warn (cfile
, "failover peers may only be %s",
790 "defined in shared-network");
791 log_error ("declarations and the outer scope.");
792 skip_to_semi (cfile
);
795 token
= next_token (&val
, (unsigned *)0, cfile
);
796 #if defined (FAILOVER_PROTOCOL)
797 parse_failover_peer (cfile
, group
, type
);
799 parse_warn (cfile
, "No failover support.");
800 skip_to_semi (cfile
);
806 parse_server_duid_conf(cfile
);
810 case LEASE_ID_FORMAT
:
811 token
= next_token (&val
, (unsigned *)0, cfile
);
812 parse_lease_id_format(cfile
);
816 et
= (struct executable_statement
*)0;
818 if (!parse_executable_statement (&et
, cfile
, &lose
,
823 "expecting a declaration");
826 "expecting a parameter %s",
828 skip_to_semi (cfile
);
835 if (group
-> statements
) {
838 /* If this set of statements is only referenced
839 by this group, just add the current statement
840 to the end of the chain. */
841 for (ep
= group
-> statements
; ep
-> next
;
843 if (ep
-> refcnt
> 1) /* XXX */
846 executable_statement_reference (&ep
-> next
,
848 executable_statement_dereference (&et
, MDL
);
852 /* Otherwise, make a parent chain, and put the
853 current group statements first and the new
854 statement in the next pointer. */
855 ep
= (struct executable_statement
*)0;
856 if (!executable_statement_allocate (&ep
, MDL
))
857 log_fatal ("No memory for statements.");
858 ep
-> op
= statements_statement
;
859 executable_statement_reference (&ep
-> data
.statements
,
862 executable_statement_reference (&ep
-> next
, et
, MDL
);
863 executable_statement_dereference (&group
-> statements
,
865 executable_statement_reference (&group
-> statements
,
867 executable_statement_dereference (&ep
, MDL
);
869 executable_statement_reference (&group
-> statements
,
872 executable_statement_dereference (&et
, MDL
);
879 #if defined (FAILOVER_PROTOCOL)
880 void parse_failover_peer (cfile
, group
, type
)
885 enum dhcp_token token
;
887 dhcp_failover_state_t
*peer
;
892 unsigned hba_len
= sizeof hba
;
894 struct expression
*expr
;
896 dhcp_failover_config_t
*cp
;
898 token
= next_token (&val
, (unsigned *)0, cfile
);
900 parse_warn (cfile
, "expecting \"peer\"");
901 skip_to_semi (cfile
);
905 token
= next_token (&val
, (unsigned *)0, cfile
);
906 if (is_identifier (token
) || token
== STRING
) {
907 name
= dmalloc (strlen (val
) + 1, MDL
);
909 log_fatal ("no memory for peer name %s", name
);
912 parse_warn (cfile
, "expecting failover peer name.");
913 skip_to_semi (cfile
);
917 /* See if there's a peer declaration by this name. */
918 peer
= (dhcp_failover_state_t
*)0;
919 find_failover_peer (&peer
, name
, MDL
);
921 token
= next_token (&val
, (unsigned *)0, cfile
);
923 if (type
!= SHARED_NET_DECL
)
924 parse_warn (cfile
, "failover peer reference not %s",
925 "in shared-network declaration");
928 parse_warn (cfile
, "reference to unknown%s%s",
929 " failover peer ", name
);
933 dhcp_failover_state_reference
934 (&group
-> shared_network
-> failover_peer
,
937 dhcp_failover_state_dereference (&peer
, MDL
);
940 } else if (token
== STATE
) {
942 parse_warn (cfile
, "state declaration for unknown%s%s",
943 " failover peer ", name
);
947 parse_failover_state_declaration (cfile
, peer
);
948 dhcp_failover_state_dereference (&peer
, MDL
);
951 } else if (token
!= LBRACE
) {
952 parse_warn (cfile
, "expecting left brace");
953 skip_to_semi (cfile
);
956 /* Make sure this isn't a redeclaration. */
958 parse_warn (cfile
, "redeclaration of failover peer %s", name
);
959 skip_to_rbrace (cfile
, 1);
960 dhcp_failover_state_dereference (&peer
, MDL
);
965 status
= dhcp_failover_state_allocate (&peer
, MDL
);
966 if (status
!= ISC_R_SUCCESS
)
967 log_fatal ("Can't allocate failover peer %s: %s",
968 name
, isc_result_totext (status
));
976 token
= next_token (&val
, (unsigned *)0, cfile
);
982 peer
-> i_am
= primary
;
986 peer
-> i_am
= secondary
;
989 "secondary may not define %s",
990 "load balance settings.");
994 cp
= &peer
-> partner
;
998 expr
= (struct expression
*)0;
999 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
1000 skip_to_rbrace (cfile
, 1);
1001 dhcp_failover_state_dereference (&peer
, MDL
);
1004 option_cache (&cp
-> address
,
1005 (struct data_string
*)0, expr
,
1006 (struct option
*)0, MDL
);
1007 expression_dereference (&expr
, MDL
);
1011 token
= next_token (&val
, (unsigned *)0, cfile
);
1012 if (token
!= NUMBER
) {
1013 parse_warn (cfile
, "expecting number");
1014 skip_to_rbrace (cfile
, 1);
1016 cp
-> port
= atoi (val
);
1019 case MAX_LEASE_MISBALANCE
:
1020 tp
= &peer
->max_lease_misbalance
;
1023 case MAX_LEASE_OWNERSHIP
:
1024 tp
= &peer
->max_lease_ownership
;
1028 tp
= &peer
->max_balance
;
1032 tp
= &peer
->min_balance
;
1035 case AUTO_PARTNER_DOWN
:
1036 tp
= &peer
->auto_partner_down
;
1039 case MAX_RESPONSE_DELAY
:
1040 tp
= &cp
-> max_response_delay
;
1042 token
= next_token (&val
, (unsigned *)0, cfile
);
1043 if (token
!= NUMBER
) {
1044 parse_warn (cfile
, "expecting number.");
1045 skip_to_rbrace (cfile
, 1);
1046 dhcp_failover_state_dereference (&peer
, MDL
);
1052 case MAX_UNACKED_UPDATES
:
1053 tp
= &cp
-> max_flying_updates
;
1062 if (peer
-> i_am
== secondary
)
1064 "secondary may not define %s",
1065 "load balance settings.");
1066 if (!parse_numeric_aggregate (cfile
, hba
, &hba_len
,
1068 skip_to_rbrace (cfile
, 1);
1069 dhcp_failover_state_dereference (&peer
, MDL
);
1072 if (hba_len
!= 32) {
1074 "HBA must be exactly 32 bytes.");
1078 peer
-> hba
= dmalloc (32, MDL
);
1080 dfree (peer
-> name
, MDL
);
1083 memcpy (peer
-> hba
, hba
, 32);
1087 token
= next_token (&val
, (unsigned *)0, cfile
);
1088 if (peer
-> i_am
== secondary
)
1090 "secondary may not define %s",
1091 "load balance settings.");
1092 if (token
!= NUMBER
) {
1093 parse_warn (cfile
, "expecting number");
1094 skip_to_rbrace (cfile
, 1);
1095 dhcp_failover_state_dereference (&peer
, MDL
);
1100 parse_warn (cfile
, "split must be between "
1101 "0 and 256, inclusive");
1103 memset (hba
, 0, sizeof hba
);
1104 for (i
= 0; i
< split
; i
++) {
1106 hba
[i
/ 8] |= (1 << (i
& 7));
1113 token
= next_token (&val
, (unsigned *)0, cfile
);
1114 if (token
!= BALANCE
) {
1115 parse_warn (cfile
, "expecting 'balance'");
1117 skip_to_rbrace (cfile
, 1);
1120 token
= next_token (&val
, (unsigned *)0, cfile
);
1121 if (token
!= TOKEN_MAX
) {
1122 parse_warn (cfile
, "expecting 'max'");
1125 token
= next_token (&val
, (unsigned *)0, cfile
);
1126 if (token
!= SECONDS
) {
1127 parse_warn (cfile
, "expecting 'secs'");
1130 token
= next_token (&val
, (unsigned *)0, cfile
);
1131 if (token
!= NUMBER
) {
1132 parse_warn (cfile
, "expecting number");
1135 peer
-> load_balance_max_secs
= atoi (val
);
1140 "invalid statement in peer declaration");
1141 skip_to_rbrace (cfile
, 1);
1142 dhcp_failover_state_dereference (&peer
, MDL
);
1145 if (token
!= RBRACE
&& !parse_semi (cfile
)) {
1146 skip_to_rbrace (cfile
, 1);
1147 dhcp_failover_state_dereference (&peer
, MDL
);
1150 } while (token
!= RBRACE
);
1152 /* me.address can be null; the failover link initiate code tries to
1153 * derive a reasonable address to use.
1155 if (!peer
-> partner
.address
)
1156 parse_warn (cfile
, "peer address may not be omitted");
1159 peer
->me
.port
= DEFAULT_FAILOVER_PORT
;
1160 if (!peer
->partner
.port
)
1161 peer
->partner
.port
= DEFAULT_FAILOVER_PORT
;
1163 if (peer
-> i_am
== primary
) {
1166 "primary failover server must have hba or split.");
1167 } else if (!peer
-> mclt
) {
1169 "primary failover server must have mclt.");
1173 if (!peer
->max_lease_misbalance
)
1174 peer
->max_lease_misbalance
= DEFAULT_MAX_LEASE_MISBALANCE
;
1175 if (!peer
->max_lease_ownership
)
1176 peer
->max_lease_ownership
= DEFAULT_MAX_LEASE_OWNERSHIP
;
1177 if (!peer
->max_balance
)
1178 peer
->max_balance
= DEFAULT_MAX_BALANCE_TIME
;
1179 if (!peer
->min_balance
)
1180 peer
->min_balance
= DEFAULT_MIN_BALANCE_TIME
;
1181 if (!peer
->me
.max_flying_updates
)
1182 peer
->me
.max_flying_updates
= DEFAULT_MAX_FLYING_UPDATES
;
1183 if (!peer
->me
.max_response_delay
)
1184 peer
->me
.max_response_delay
= DEFAULT_MAX_RESPONSE_DELAY
;
1186 if (type
== SHARED_NET_DECL
)
1187 group
->shared_network
->failover_peer
= peer
;
1189 /* Set the initial state. */
1190 peer
->me
.state
= recover
;
1191 peer
->me
.stos
= cur_time
;
1192 peer
->partner
.state
= unknown_state
;
1193 peer
->partner
.stos
= cur_time
;
1195 status
= enter_failover_peer (peer
);
1196 if (status
!= ISC_R_SUCCESS
)
1197 parse_warn (cfile
, "failover peer %s: %s",
1198 peer
-> name
, isc_result_totext (status
));
1199 dhcp_failover_state_dereference (&peer
, MDL
);
1202 void parse_failover_state_declaration (struct parse
*cfile
,
1203 dhcp_failover_state_t
*peer
)
1205 enum dhcp_token token
;
1208 dhcp_failover_state_t
*state
;
1209 dhcp_failover_config_t
*cp
;
1212 token
= next_token (&val
, (unsigned *)0, cfile
);
1213 if (token
!= PEER
) {
1214 parse_warn (cfile
, "expecting \"peer\"");
1215 skip_to_semi (cfile
);
1219 token
= next_token (&val
, (unsigned *)0, cfile
);
1220 if (is_identifier (token
) || token
== STRING
) {
1221 name
= dmalloc (strlen (val
) + 1, MDL
);
1223 log_fatal ("failover peer name %s: no memory",
1227 parse_warn (cfile
, "expecting failover peer name.");
1228 skip_to_semi (cfile
);
1232 /* See if there's a peer declaration by this name. */
1233 state
= (dhcp_failover_state_t
*)0;
1234 find_failover_peer (&state
, name
, MDL
);
1236 parse_warn (cfile
, "unknown failover peer: %s", name
);
1237 skip_to_semi (cfile
);
1241 token
= next_token (&val
, (unsigned *)0, cfile
);
1242 if (token
!= STATE
) {
1243 parse_warn (cfile
, "expecting 'state'");
1245 skip_to_semi (cfile
);
1249 state
= (dhcp_failover_state_t
*)0;
1250 dhcp_failover_state_reference (&state
, peer
, MDL
);
1252 token
= next_token (&val
, (unsigned *)0, cfile
);
1253 if (token
!= LBRACE
) {
1254 parse_warn (cfile
, "expecting left brace");
1256 skip_to_semi (cfile
);
1257 dhcp_failover_state_dereference (&state
, MDL
);
1261 token
= next_token (&val
, (unsigned *)0, cfile
);
1268 token
= next_token (&val
, (unsigned *)0, cfile
);
1269 if (token
!= STATE
) {
1270 parse_warn (cfile
, "expecting 'state'");
1273 parse_failover_state (cfile
,
1274 &cp
-> state
, &cp
-> stos
);
1278 cp
= &state
-> partner
;
1282 if (state
-> i_am
== primary
) {
1284 "mclt not valid for primary");
1287 token
= next_token (&val
, (unsigned *)0, cfile
);
1288 if (token
!= NUMBER
) {
1289 parse_warn (cfile
, "expecting a number.");
1292 state
-> mclt
= atoi (val
);
1297 parse_warn (cfile
, "expecting state setting.");
1299 skip_to_rbrace (cfile
, 1);
1300 dhcp_failover_state_dereference (&state
, MDL
);
1303 } while (token
!= RBRACE
);
1304 dhcp_failover_state_dereference (&state
, MDL
);
1307 void parse_failover_state (cfile
, state
, stos
)
1308 struct parse
*cfile
;
1309 enum failover_state
*state
;
1312 enum dhcp_token token
;
1314 enum failover_state state_in
;
1317 token
= next_token (&val
, (unsigned *)0, cfile
);
1320 state_in
= unknown_state
;
1324 state_in
= partner_down
;
1331 case COMMUNICATIONS_INTERRUPTED
:
1332 state_in
= communications_interrupted
;
1336 state_in
= conflict_done
;
1339 case RESOLUTION_INTERRUPTED
:
1340 state_in
= resolution_interrupted
;
1343 case POTENTIAL_CONFLICT
:
1344 state_in
= potential_conflict
;
1352 state_in
= recover_wait
;
1356 state_in
= recover_done
;
1360 state_in
= shut_down
;
1372 parse_warn (cfile
, "unknown failover state");
1373 skip_to_semi (cfile
);
1377 token
= next_token (&val
, (unsigned *)0, cfile
);
1378 if (token
== SEMI
) {
1382 parse_warn (cfile
, "expecting \"at\"");
1383 skip_to_semi (cfile
);
1387 stos_in
= parse_date (cfile
);
1392 /* Now that we've apparently gotten a clean parse, we
1393 can trust that this is a state that was fully committed to
1394 disk, so we can install it. */
1398 #endif /* defined (FAILOVER_PROTOCOL) */
1401 * \brief Parses an authoring-byte-order statement
1403 * A valid statement looks like this:
1405 * authoring-byte-order :==
1406 * PARSE_BYTE_ORDER TOKEN_LITTLE_ENDIAN | TOKEN_BIG_ENDIAN ;
1408 * If the global, authoring_byte_order is not zero, then either the statement
1409 * has already been parsed or the function, parse_byte_order_uint32, has
1410 * been called which set it to the default. In either case, this is invalid
1411 * so we'll log it and bail.
1413 * If the value is different from the current server's byte order, then we'll
1414 * log that fact and set authoring_byte_order to given value. This causes all
1415 * invocations of the function, parse_byte_order_uint32, to perform byte-order
1416 * conversion before returning the value.
1418 * \param cfile the current parse file
1421 void parse_authoring_byte_order (struct parse
*cfile
)
1423 enum dhcp_token token
;
1427 /* Either we've seen it already or it's after the first lease */
1428 if (authoring_byte_order
!= 0) {
1430 "authoring-byte-order specified too late.\n"
1431 "It must occur before the first lease in file\n");
1432 skip_to_semi (cfile
);
1436 token
= next_token(&val
, (unsigned *)0, cfile
);
1438 case TOKEN_LITTLE_ENDIAN
:
1439 authoring_byte_order
= LITTLE_ENDIAN
;
1441 case TOKEN_BIG_ENDIAN
:
1442 authoring_byte_order
= BIG_ENDIAN
;
1445 parse_warn(cfile
, "authoring-byte-order is invalid: "
1446 " it must be big-endian or little-endian.");
1447 skip_to_semi(cfile
);
1451 if (authoring_byte_order
!= DHCP_BYTE_ORDER
) {
1452 log_error ("WARNING: Lease file authored using different"
1453 " byte order, will attempt to convert");
1456 token
= next_token(&val
, &len
, cfile
);
1457 if (token
!= SEMI
) {
1458 parse_warn(cfile
, "corrupt lease file; expecting a semicolon");
1459 skip_to_semi(cfile
);
1465 * \brief Parses a lease-id-format statement
1467 * A valid statement looks like this:
1469 * lease-id-format :==
1470 * LEASE_ID_FORMAT TOKEN_OCTAL | TOKEN_HEX ;
1472 * This function is used to parse the lease-id-format statement. It sets the
1473 * global variable, lease_id_format.
1475 * \param cfile the current parse file
1478 void parse_lease_id_format (struct parse
*cfile
)
1480 enum dhcp_token token
;
1484 token
= next_token(&val
, NULL
, cfile
);
1487 lease_id_format
= TOKEN_OCTAL
;
1490 lease_id_format
= TOKEN_HEX
;
1493 parse_warn(cfile
, "lease-id-format is invalid: "
1494 " it must be octal or hex.");
1495 skip_to_semi(cfile
);
1499 log_debug("lease_id_format is: %s",
1500 lease_id_format
== TOKEN_OCTAL
? "octal" : "hex");
1502 token
= next_token(&val
, &len
, cfile
);
1503 if (token
!= SEMI
) {
1504 parse_warn(cfile
, "corrupt lease file; expecting a semicolon");
1505 skip_to_semi(cfile
);
1512 * \brief Parse allow and deny statements
1514 * This function handles the common processing code for permit and deny
1515 * statements in the parse_pool_statement and parse_pool6_statement functions.
1516 * It reads in the configuration and constructs a new permit structure that it
1517 * attachs to the permit_head passed in from the caller.
1519 * The allow or deny token should already be consumed, this function expects
1520 * one of the following:
1525 * authenticated clients;
1526 * unauthenticated clients;
1528 * dynamic bootp clients;
1529 * members of <class name>;
1532 * \param[in] cfile = the configuration file being parsed
1533 * \param[in] permit_head = the head of the permit list (permit or prohibit)
1534 * to which to attach the newly created permit structure
1535 * \param[in] is_allow = 1 if this is being invoked for an allow statement
1536 * = 0 if this is being invoked for a deny statement
1537 * \param[in] valid_from = pointers to the time values from the enclosing pool
1538 * \param[in] valid_until or pond structure. One of them will be filled in if
1539 * the configuration includes an "after" clause
1542 void get_permit(cfile
, permit_head
, is_allow
, valid_from
, valid_until
)
1543 struct parse
*cfile
;
1544 struct permit
**permit_head
;
1546 TIME
*valid_from
, *valid_until
;
1548 enum dhcp_token token
;
1549 struct permit
*permit
;
1551 int need_clients
= 1;
1554 /* Create our permit structure */
1555 permit
= new_permit(MDL
);
1557 log_fatal ("no memory for permit");
1559 token
= next_token(&val
, NULL
, cfile
);
1562 permit
->type
= permit_unknown_clients
;
1567 permit
->type
= permit_known_clients
;
1570 case UNKNOWN_CLIENTS
:
1572 permit
->type
= permit_unknown_clients
;
1576 permit
->type
= permit_known_clients
;
1580 permit
->type
= permit_authenticated_clients
;
1583 case UNAUTHENTICATED
:
1584 permit
->type
= permit_unauthenticated_clients
;
1588 permit
->type
= permit_all_clients
;
1592 permit
->type
= permit_dynamic_bootp_clients
;
1593 if (next_token (&val
, NULL
, cfile
) != TOKEN_BOOTP
) {
1594 parse_warn (cfile
, "expecting \"bootp\"");
1595 skip_to_semi (cfile
);
1596 free_permit (permit
, MDL
);
1603 if (next_token (&val
, NULL
, cfile
) != OF
) {
1604 parse_warn (cfile
, "expecting \"of\"");
1605 skip_to_semi (cfile
);
1606 free_permit (permit
, MDL
);
1609 if (next_token (&val
, NULL
, cfile
) != STRING
) {
1610 parse_warn (cfile
, "expecting class name.");
1611 skip_to_semi (cfile
);
1612 free_permit (permit
, MDL
);
1615 permit
->type
= permit_class
;
1616 permit
->class = NULL
;
1617 find_class(&permit
->class, val
, MDL
);
1619 parse_warn(cfile
, "no such class: %s", val
);
1624 if (*valid_from
|| *valid_until
) {
1625 parse_warn(cfile
, "duplicate \"after\" clause.");
1626 skip_to_semi(cfile
);
1627 free_permit(permit
, MDL
);
1630 t
= parse_date_core(cfile
);
1631 permit
->type
= permit_after
;
1641 parse_warn (cfile
, "expecting permit type.");
1642 skip_to_semi (cfile
);
1643 free_permit (permit
, MDL
);
1648 * The need_clients flag is set if we are expecting the
1651 if ((need_clients
!= 0) &&
1652 (next_token (&val
, NULL
, cfile
) != CLIENTS
)) {
1653 parse_warn (cfile
, "expecting \"clients\"");
1654 skip_to_semi (cfile
);
1655 free_permit (permit
, MDL
);
1659 while (*permit_head
)
1660 permit_head
= &((*permit_head
)->next
);
1661 *permit_head
= permit
;
1667 /* Permit_list_match returns 1 if every element of the permit list in lhs
1668 also appears in rhs. Note that this doesn't by itself mean that the
1669 two lists are equal - to check for equality, permit_list_match has to
1670 return 1 with (list1, list2) and with (list2, list1). */
1672 int permit_list_match (struct permit
*lhs
, struct permit
*rhs
)
1674 struct permit
*plp
, *prp
;
1681 for (plp
= lhs
; plp
; plp
= plp
-> next
) {
1683 for (prp
= rhs
; prp
; prp
= prp
-> next
) {
1684 if (prp
-> type
== plp
-> type
&&
1685 (prp
-> type
!= permit_class
||
1686 prp
-> class == plp
-> class)) {
1699 * \brief Parse a pool statement
1701 * Pool statements are used to group declarations and permit & deny information
1702 * with a specific address range. They must be declared within a shared network
1703 * or subnet and there may be multiple pools withing a shared network or subnet.
1704 * Each pool may have a different set of permit or deny options.
1706 * \param[in] cfile = the configuration file being parsed
1707 * \param[in] group = the group structure for this pool
1708 * \param[in] type = the type of the enclosing statement. This must be
1709 * SHARED_NET_DECL or SUBNET_DECL for this function.
1712 * void - This function either parses the statement and updates the structures
1713 * or it generates an error message and possible halts the program if
1714 * it encounters a problem.
1716 void parse_pool_statement (cfile
, group
, type
)
1717 struct parse
*cfile
;
1718 struct group
*group
;
1721 enum dhcp_token token
;
1724 struct pool
*pool
, **p
, *pp
;
1725 int declaration
= 0;
1726 isc_result_t status
;
1727 struct lease
*lpchain
= NULL
, *lp
;
1730 status
= pool_allocate(&pool
, MDL
);
1731 if (status
!= ISC_R_SUCCESS
)
1732 log_fatal ("no memory for pool: %s",
1733 isc_result_totext (status
));
1735 if (type
== SUBNET_DECL
)
1736 shared_network_reference(&pool
->shared_network
,
1737 group
->subnet
->shared_network
,
1739 else if (type
== SHARED_NET_DECL
)
1740 shared_network_reference(&pool
->shared_network
,
1741 group
->shared_network
, MDL
);
1743 parse_warn(cfile
, "Dynamic pools are only valid inside "
1744 "subnet or shared-network statements.");
1745 skip_to_semi(cfile
);
1749 if (pool
->shared_network
== NULL
||
1750 !clone_group(&pool
->group
, pool
->shared_network
->group
, MDL
))
1751 log_fatal("can't clone pool group.");
1753 #if defined (FAILOVER_PROTOCOL)
1754 /* Inherit the failover peer from the shared network. */
1755 if (pool
->shared_network
->failover_peer
)
1756 dhcp_failover_state_reference
1757 (&pool
->failover_peer
,
1758 pool
->shared_network
->failover_peer
, MDL
);
1761 if (!parse_lbrace(cfile
)) {
1762 pool_dereference(&pool
, MDL
);
1767 token
= peek_token(&val
, NULL
, cfile
);
1770 skip_token(&val
, NULL
, cfile
);
1771 token
= next_token(&val
, NULL
, cfile
);
1772 if (token
!= FAILOVER
||
1773 (token
= next_token(&val
, NULL
, cfile
)) != PEER
) {
1775 "expecting \"failover peer\".");
1776 skip_to_semi(cfile
);
1779 #if defined (FAILOVER_PROTOCOL)
1780 if (pool
->failover_peer
)
1781 dhcp_failover_state_dereference
1782 (&pool
->failover_peer
, MDL
);
1786 #if defined (FAILOVER_PROTOCOL)
1788 skip_token(&val
, NULL
, cfile
);
1789 token
= next_token (&val
, NULL
, cfile
);
1790 if (token
!= PEER
) {
1791 parse_warn(cfile
, "expecting 'peer'.");
1792 skip_to_semi(cfile
);
1795 token
= next_token(&val
, NULL
, cfile
);
1796 if (token
!= STRING
) {
1797 parse_warn(cfile
, "expecting string.");
1798 skip_to_semi(cfile
);
1801 if (pool
->failover_peer
)
1802 dhcp_failover_state_dereference
1803 (&pool
->failover_peer
, MDL
);
1804 status
= find_failover_peer(&pool
->failover_peer
,
1806 if (status
!= ISC_R_SUCCESS
)
1808 "failover peer %s: %s", val
,
1809 isc_result_totext (status
));
1811 pool
->failover_peer
->pool_count
++;
1817 skip_token(&val
, NULL
, cfile
);
1818 parse_address_range (cfile
, group
, type
,
1822 skip_token(&val
, NULL
, cfile
);
1823 get_permit(cfile
, &pool
->permit_list
, 1,
1824 &pool
->valid_from
, &pool
->valid_until
);
1828 skip_token(&val
, NULL
, cfile
);
1829 get_permit(cfile
, &pool
->prohibit_list
, 0,
1830 &pool
->valid_from
, &pool
->valid_until
);
1834 skip_token(&val
, NULL
, cfile
);
1840 * We can get to END_OF_FILE if, for instance,
1841 * the parse_statement() reads all available tokens
1842 * and leaves us at the end.
1844 parse_warn(cfile
, "unexpected end of file");
1848 declaration
= parse_statement(cfile
, pool
->group
,
1855 /* See if there's already a pool into which we can merge this one. */
1856 for (pp
= pool
->shared_network
->pools
; pp
; pp
= pp
->next
) {
1857 if (pp
->group
->statements
!= pool
->group
->statements
)
1859 #if defined (FAILOVER_PROTOCOL)
1860 if (pool
->failover_peer
!= pp
->failover_peer
)
1863 if (!permit_list_match(pp
->permit_list
,
1864 pool
->permit_list
) ||
1865 !permit_list_match(pool
->permit_list
,
1867 !permit_list_match(pp
->prohibit_list
,
1868 pool
->prohibit_list
) ||
1869 !permit_list_match(pool
->prohibit_list
,
1873 /* Okay, we can merge these two pools. All we have to
1874 do is fix up the leases, which all point to their pool. */
1875 for (lp
= lpchain
; lp
; lp
= lp
->next
) {
1876 pool_dereference(&lp
->pool
, MDL
);
1877 pool_reference(&lp
->pool
, pp
, MDL
);
1880 #if defined (BINARY_LEASES)
1881 /* If we are doing binary leases we also need to add the
1882 * addresses in for leasechain allocation.
1884 pp
->lease_count
+= pool
->lease_count
;
1890 /* If we didn't succeed in merging this pool into another, put
1893 p
= &pool
->shared_network
->pools
;
1894 for (; *p
; p
= &((*p
)->next
))
1896 pool_reference(p
, pool
, MDL
);
1899 /* Don't allow a pool declaration with no addresses, since it is
1900 probably a configuration error. */
1902 parse_warn(cfile
, "Pool declaration with no address range.");
1903 log_error("Pool declarations must always contain at least");
1904 log_error("one range statement.");
1908 /* Dereference the lease chain. */
1911 lease_reference(&lp
, lpchain
, MDL
);
1912 lease_dereference(&lpchain
, MDL
);
1914 lease_reference(&lpchain
, lp
->next
, MDL
);
1915 lease_dereference(&lp
->next
, MDL
);
1916 lease_dereference(&lp
, MDL
);
1919 pool_dereference(&pool
, MDL
);
1922 /* Expect a left brace; if there isn't one, skip over the rest of the
1923 statement and return zero; otherwise, return 1. */
1925 int parse_lbrace (cfile
)
1926 struct parse
*cfile
;
1928 enum dhcp_token token
;
1931 token
= next_token (&val
, (unsigned *)0, cfile
);
1932 if (token
!= LBRACE
) {
1933 parse_warn (cfile
, "expecting left brace.");
1934 skip_to_semi (cfile
);
1941 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1943 void parse_host_declaration (cfile
, group
)
1944 struct parse
*cfile
;
1945 struct group
*group
;
1948 enum dhcp_token token
;
1949 struct host_decl
*host
;
1951 int declaration
= 0;
1954 isc_result_t status
;
1956 struct option
*option
;
1957 struct expression
*expr
= NULL
;
1959 name
= parse_host_name (cfile
);
1961 parse_warn (cfile
, "expecting a name for host declaration.");
1962 skip_to_semi (cfile
);
1966 host
= (struct host_decl
*)0;
1967 status
= host_allocate (&host
, MDL
);
1968 if (status
!= ISC_R_SUCCESS
)
1969 log_fatal ("can't allocate host decl struct %s: %s",
1970 name
, isc_result_totext (status
));
1971 host
-> name
= name
;
1972 if (!clone_group (&host
-> group
, group
, MDL
)) {
1973 log_fatal ("can't clone group for host %s", name
);
1975 host_dereference (&host
, MDL
);
1979 if (!parse_lbrace (cfile
))
1983 token
= peek_token (&val
, (unsigned *)0, cfile
);
1984 if (token
== RBRACE
) {
1985 skip_token(&val
, (unsigned *)0, cfile
);
1988 if (token
== END_OF_FILE
) {
1989 skip_token(&val
, (unsigned *)0, cfile
);
1990 parse_warn (cfile
, "unexpected end of file");
1993 /* If the host declaration was created by the server,
1994 remember to save it. */
1995 if (token
== DYNAMIC
) {
1997 skip_token(&val
, (unsigned *)0, cfile
);
1998 if (!parse_semi (cfile
))
2002 /* If the host declaration was created by the server,
2003 remember to save it. */
2004 if (token
== TOKEN_DELETED
) {
2006 skip_token(&val
, (unsigned *)0, cfile
);
2007 if (!parse_semi (cfile
))
2012 if (token
== GROUP
) {
2013 struct group_object
*go
;
2014 skip_token(&val
, (unsigned *)0, cfile
);
2015 token
= next_token (&val
, (unsigned *)0, cfile
);
2016 if (token
!= STRING
&& !is_identifier (token
)) {
2018 "expecting string or identifier.");
2019 skip_to_rbrace (cfile
, 1);
2022 go
= (struct group_object
*)0;
2023 if (!group_hash_lookup (&go
, group_name_hash
,
2024 val
, strlen (val
), MDL
)) {
2025 parse_warn (cfile
, "unknown group %s in host %s",
2028 if (host
-> named_group
)
2029 group_object_dereference
2030 (&host
-> named_group
, MDL
);
2031 group_object_reference (&host
-> named_group
,
2033 group_object_dereference (&go
, MDL
);
2035 if (!parse_semi (cfile
))
2042 unsigned char *t
= 0;
2045 skip_token(&val
, (unsigned *)0, cfile
);
2046 data_string_forget (&host
-> client_identifier
, MDL
);
2048 if (host
->client_identifier
.len
!= 0) {
2049 parse_warn(cfile
, "Host %s already has a "
2050 "client identifier.",
2055 /* See if it's a string or a cshl. */
2056 token
= peek_token (&val
, (unsigned *)0, cfile
);
2057 if (token
== STRING
) {
2058 skip_token(&val
, &len
, cfile
);
2060 host
-> client_identifier
.terminated
= 1;
2063 t
= parse_numeric_aggregate
2065 (unsigned char *)0, &len
, ':', 16, 8);
2068 "expecting hex list.");
2069 skip_to_semi (cfile
);
2071 s
= (const char *)t
;
2073 if (!buffer_allocate
2074 (&host
-> client_identifier
.buffer
,
2075 len
+ host
-> client_identifier
.terminated
, MDL
))
2076 log_fatal ("no memory for uid for host %s.",
2078 host
-> client_identifier
.data
=
2079 host
-> client_identifier
.buffer
-> data
;
2080 host
-> client_identifier
.len
= len
;
2081 memcpy (host
-> client_identifier
.buffer
-> data
, s
,
2082 len
+ host
-> client_identifier
.terminated
);
2086 if (!parse_semi (cfile
))
2091 if (token
== HOST_IDENTIFIER
) {
2092 if (host
->host_id_option
!= NULL
) {
2094 "only one host-identifier allowed "
2096 skip_to_rbrace(cfile
, 1);
2099 skip_token(&val
, NULL
, cfile
);
2100 token
= next_token(&val
, NULL
, cfile
);
2101 if (token
== V6RELOPT
) {
2102 token
= next_token(&val
, NULL
, cfile
);
2103 if (token
!= NUMBER
) {
2105 "host-identifier v6relopt "
2106 "must have a number");
2107 skip_to_rbrace(cfile
, 1);
2110 host
->relays
= atoi(val
);
2111 if (host
->relays
< 0) {
2113 "host-identifier v6relopt "
2114 "must have a number >= 0");
2115 skip_to_rbrace(cfile
, 1);
2118 } else if (token
!= OPTION
) {
2120 "host-identifier must be an option"
2122 skip_to_rbrace(cfile
, 1);
2127 status
= parse_option_name(cfile
, 1, &known
, &option
);
2128 if ((status
!= ISC_R_SUCCESS
) || (option
== NULL
)) {
2132 parse_warn(cfile
, "unknown option %s.%s",
2133 option
->universe
->name
,
2135 skip_to_rbrace(cfile
, 1);
2139 if (! parse_option_data(&expr
, cfile
, 1, option
)) {
2140 skip_to_rbrace(cfile
, 1);
2141 option_dereference(&option
, MDL
);
2145 if (!parse_semi(cfile
)) {
2146 skip_to_rbrace(cfile
, 1);
2147 expression_dereference(&expr
, MDL
);
2148 option_dereference(&option
, MDL
);
2152 option_reference(&host
->host_id_option
, option
, MDL
);
2153 option_dereference(&option
, MDL
);
2154 data_string_copy(&host
->host_id
,
2155 &expr
->data
.const_data
, MDL
);
2156 expression_dereference(&expr
, MDL
);
2160 declaration
= parse_statement(cfile
, host
->group
, HOST_DECL
,
2165 struct host_decl
*hp
= (struct host_decl
*)0;
2166 if (host_hash_lookup (&hp
, host_name_hash
,
2167 (unsigned char *)host
-> name
,
2168 strlen (host
-> name
), MDL
)) {
2169 delete_host (hp
, 0);
2170 host_dereference (&hp
, MDL
);
2173 if (host
-> named_group
&& host
-> named_group
-> group
) {
2174 if (host
-> group
-> statements
||
2175 (host
-> group
-> authoritative
!=
2176 host
-> named_group
-> group
-> authoritative
)) {
2177 if (host
-> group
-> next
)
2178 group_dereference (&host
-> group
-> next
,
2180 group_reference (&host
-> group
-> next
,
2181 host
-> named_group
-> group
,
2184 group_dereference (&host
-> group
, MDL
);
2185 group_reference (&host
-> group
,
2186 host
-> named_group
-> group
,
2192 host
-> flags
|= HOST_DECL_DYNAMIC
;
2194 host
-> flags
|= HOST_DECL_STATIC
;
2196 status
= enter_host (host
, dynamicp
, 0);
2197 if (status
!= ISC_R_SUCCESS
)
2198 parse_warn (cfile
, "host %s: %s", host
-> name
,
2199 isc_result_totext (status
));
2201 host_dereference (&host
, MDL
);
2204 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
2207 int parse_class_declaration (cp
, cfile
, group
, type
)
2209 struct parse
*cfile
;
2210 struct group
*group
;
2214 enum dhcp_token token
;
2215 struct class *class = NULL
, *pc
= NULL
;
2216 int declaration
= 0;
2218 struct data_string data
;
2221 struct executable_statement
*stmt
= NULL
;
2223 isc_result_t status
= ISC_R_FAILURE
;
2224 int matchedonce
= 0;
2225 int submatchedonce
= 0;
2228 token
= next_token (&val
, NULL
, cfile
);
2229 if (token
!= STRING
) {
2230 parse_warn (cfile
, "Expecting class name");
2231 skip_to_semi (cfile
);
2235 /* See if there's already a class with the specified name. */
2236 find_class (&pc
, val
, MDL
);
2238 /* If it is a class, we're updating it. If it's any of the other
2239 * types (subclass, vendor or user class), the named class is a
2240 * reference to the parent class so its mandatory.
2242 if (pc
&& (type
== CLASS_TYPE_CLASS
)) {
2243 class_reference(&class, pc
, MDL
);
2245 class_dereference(&pc
, MDL
);
2246 } else if (!pc
&& (type
!= CLASS_TYPE_CLASS
)) {
2247 parse_warn(cfile
, "no class named %s", val
);
2248 skip_to_semi(cfile
);
2252 /* The old vendor-class and user-class declarations had an implicit
2253 match. We don't do the implicit match anymore. Instead, for
2254 backward compatibility, we have an implicit-vendor-class and an
2255 implicit-user-class. vendor-class and user-class declarations
2256 are turned into subclasses of the implicit classes, and the
2257 submatch expression of the implicit classes extracts the contents of
2258 the vendor class or user class. */
2259 if ((type
== CLASS_TYPE_VENDOR
) || (type
== CLASS_TYPE_USER
)) {
2260 data
.len
= strlen (val
);
2262 if (!buffer_allocate (&data
.buffer
, data
.len
+ 1, MDL
))
2263 log_fatal ("no memory for class name.");
2264 data
.data
= &data
.buffer
-> data
[0];
2265 data
.terminated
= 1;
2267 tname
= type
? "implicit-vendor-class" : "implicit-user-class";
2268 } else if (type
== CLASS_TYPE_CLASS
) {
2275 name
= dmalloc (strlen (tname
) + 1, MDL
);
2277 log_fatal ("No memory for class name %s.", tname
);
2282 /* If this is a straight subclass, parse the hash string. */
2283 if (type
== CLASS_TYPE_SUBCLASS
) {
2284 token
= peek_token (&val
, NULL
, cfile
);
2285 if (token
== STRING
) {
2286 skip_token(&val
, &data
.len
, cfile
);
2289 if (!buffer_allocate (&data
.buffer
,
2290 data
.len
+ 1, MDL
)) {
2292 class_dereference (&pc
, MDL
);
2296 data
.terminated
= 1;
2297 data
.data
= &data
.buffer
-> data
[0];
2298 memcpy ((char *)data
.buffer
-> data
, val
,
2300 } else if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
2301 memset (&data
, 0, sizeof data
);
2302 if (!parse_cshl (&data
, cfile
)) {
2304 class_dereference (&pc
, MDL
);
2308 parse_warn (cfile
, "Expecting string or hex list.");
2310 class_dereference (&pc
, MDL
);
2315 /* See if there's already a class in the hash table matching the
2317 if (type
!= CLASS_TYPE_CLASS
)
2318 class_hash_lookup (&class, pc
-> hash
,
2319 (const char *)data
.data
, data
.len
, MDL
);
2321 /* If we didn't find an existing class, allocate a new one. */
2323 /* Allocate the class structure... */
2324 if (type
== CLASS_TYPE_SUBCLASS
) {
2325 status
= subclass_allocate (&class, MDL
);
2327 status
= class_allocate (&class, MDL
);
2330 group_reference (&class -> group
, pc
-> group
, MDL
);
2331 class_reference (&class -> superclass
, pc
, MDL
);
2332 class -> lease_limit
= pc
-> lease_limit
;
2333 if (class -> lease_limit
) {
2334 class -> billed_leases
=
2335 dmalloc (class -> lease_limit
*
2336 sizeof (struct lease
*), MDL
);
2337 if (!class -> billed_leases
)
2338 log_fatal ("no memory for billing");
2339 memset (class -> billed_leases
, 0,
2340 (class -> lease_limit
*
2341 sizeof (struct lease
*)));
2343 data_string_copy (&class -> hash_string
, &data
, MDL
);
2345 !class_new_hash (&pc
->hash
, SCLASS_HASH_SIZE
, MDL
))
2346 log_fatal ("No memory for subclass hash.");
2347 class_hash_add (pc
-> hash
,
2348 (const char *)class -> hash_string
.data
,
2349 class -> hash_string
.len
,
2350 (void *)class, MDL
);
2353 group_dereference(&class->group
, MDL
);
2354 if (!clone_group (&class -> group
, group
, MDL
))
2355 log_fatal ("no memory to clone class group.");
2358 /* If this is an implicit vendor or user class, add a
2359 statement that causes the vendor or user class ID to
2360 be sent back in the reply. */
2361 if (type
== CLASS_TYPE_VENDOR
|| type
== CLASS_TYPE_USER
) {
2363 if (!executable_statement_allocate (&stmt
, MDL
))
2364 log_fatal ("no memory for class statement.");
2365 stmt
-> op
= supersede_option_statement
;
2366 if (option_cache_allocate (&stmt
-> data
.option
,
2368 stmt
-> data
.option
-> data
= data
;
2369 code
= (type
== CLASS_TYPE_VENDOR
)
2370 ? DHO_VENDOR_CLASS_IDENTIFIER
2372 option_code_hash_lookup(
2373 &stmt
->data
.option
->option
,
2374 dhcp_universe
.code_hash
,
2377 class -> statements
= stmt
;
2380 /* Save the name, if there is one. */
2381 if (class->name
!= NULL
)
2382 dfree(class->name
, MDL
);
2386 if (type
!= CLASS_TYPE_CLASS
)
2387 data_string_forget(&data
, MDL
);
2389 /* Spawned classes don't have to have their own settings. */
2390 if (class -> superclass
) {
2391 token
= peek_token (&val
, NULL
, cfile
);
2392 if (token
== SEMI
) {
2393 skip_token(&val
, NULL
, cfile
);
2396 status
= class_reference (cp
, class, MDL
);
2397 class_dereference (&class, MDL
);
2399 class_dereference (&pc
, MDL
);
2400 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2402 /* Give the subclass its own group. */
2403 if (!clone_group (&class -> group
, class -> group
, MDL
))
2404 log_fatal ("can't clone class group.");
2408 if (!parse_lbrace (cfile
)) {
2409 class_dereference (&class, MDL
);
2411 class_dereference (&pc
, MDL
);
2416 token
= peek_token (&val
, NULL
, cfile
);
2417 if (token
== RBRACE
) {
2418 skip_token(&val
, NULL
, cfile
);
2420 } else if (token
== END_OF_FILE
) {
2421 skip_token(&val
, NULL
, cfile
);
2422 parse_warn (cfile
, "unexpected end of file");
2424 } else if (token
== DYNAMIC
) {
2425 class->flags
|= CLASS_DECL_DYNAMIC
;
2426 skip_token(&val
, NULL
, cfile
);
2427 if (!parse_semi (cfile
))
2430 } else if (token
== TOKEN_DELETED
) {
2431 class->flags
|= CLASS_DECL_DELETED
;
2432 skip_token(&val
, NULL
, cfile
);
2433 if (!parse_semi (cfile
))
2436 } else if (token
== MATCH
) {
2439 "invalid match in subclass.");
2440 skip_to_semi (cfile
);
2443 skip_token(&val
, NULL
, cfile
);
2444 token
= peek_token (&val
, NULL
, cfile
);
2447 skip_token(&val
, NULL
, cfile
);
2449 parse_warn(cfile
, "A class may only have "
2450 "one 'match if' clause.");
2451 skip_to_semi(cfile
);
2456 expression_dereference(&class->expr
, MDL
);
2457 if (!parse_boolean_expression (&class->expr
, cfile
,
2461 "expecting boolean expr.");
2462 skip_to_semi (cfile
);
2465 #if defined (DEBUG_EXPRESSION_PARSE)
2466 print_expression ("class match",
2471 } else if (token
== SPAWN
) {
2472 skip_token(&val
, NULL
, cfile
);
2475 "invalid spawn in subclass.");
2476 skip_to_semi (cfile
);
2479 class -> spawning
= 1;
2480 token
= next_token (&val
, NULL
, cfile
);
2481 if (token
!= WITH
) {
2483 "expecting with after spawn");
2484 skip_to_semi (cfile
);
2488 if (submatchedonce
) {
2490 "can't override existing %s.",
2492 skip_to_semi (cfile
);
2496 if (class->submatch
)
2497 expression_dereference(&class->submatch
, MDL
);
2498 if (!parse_data_expression (&class -> submatch
,
2502 "expecting data expr.");
2503 skip_to_semi (cfile
);
2506 #if defined (DEBUG_EXPRESSION_PARSE)
2507 print_expression ("class submatch",
2512 } else if (token
== LEASE
) {
2513 skip_token(&val
, NULL
, cfile
);
2514 token
= next_token (&val
, NULL
, cfile
);
2515 if (token
!= LIMIT
) {
2516 parse_warn (cfile
, "expecting \"limit\"");
2518 skip_to_semi (cfile
);
2521 token
= next_token (&val
, NULL
, cfile
);
2522 if (token
!= NUMBER
) {
2523 parse_warn (cfile
, "expecting a number");
2525 skip_to_semi (cfile
);
2528 class -> lease_limit
= atoi (val
);
2529 if (class->billed_leases
)
2530 dfree(class->billed_leases
, MDL
);
2531 class -> billed_leases
=
2532 dmalloc (class -> lease_limit
*
2533 sizeof (struct lease
*), MDL
);
2534 if (!class -> billed_leases
)
2535 log_fatal ("no memory for billed leases.");
2536 memset (class -> billed_leases
, 0,
2537 (class -> lease_limit
*
2538 sizeof (struct lease
*)));
2539 have_billing_classes
= 1;
2542 declaration
= parse_statement (cfile
, class -> group
,
2548 if (class->flags
& CLASS_DECL_DELETED
) {
2549 if (type
== CLASS_TYPE_CLASS
) {
2550 struct class *theclass
= NULL
;
2552 status
= find_class(&theclass
, class->name
, MDL
);
2553 if (status
== ISC_R_SUCCESS
) {
2554 delete_class(theclass
, 0);
2555 class_dereference(&theclass
, MDL
);
2558 class_hash_delete(pc
->hash
,
2559 (char *)class->hash_string
.data
,
2560 class->hash_string
.len
, MDL
);
2562 } else if (type
== CLASS_TYPE_CLASS
&& new) {
2563 if (!collections
-> classes
)
2564 class_reference (&collections
-> classes
, class, MDL
);
2567 for (c
= collections
-> classes
;
2568 c
-> nic
; c
= c
-> nic
)
2570 class_reference (&c
-> nic
, class, MDL
);
2574 if (cp
) /* should always be 0??? */
2575 status
= class_reference (cp
, class, MDL
);
2576 class_dereference (&class, MDL
);
2578 class_dereference (&pc
, MDL
);
2579 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2582 /* shared-network-declaration :==
2583 hostname LBRACE declarations parameters RBRACE */
2585 void parse_shared_net_declaration (cfile
, group
)
2586 struct parse
*cfile
;
2587 struct group
*group
;
2590 enum dhcp_token token
;
2591 struct shared_network
*share
;
2593 int declaration
= 0;
2594 isc_result_t status
;
2596 share
= (struct shared_network
*)0;
2597 status
= shared_network_allocate (&share
, MDL
);
2598 if (status
!= ISC_R_SUCCESS
)
2599 log_fatal ("Can't allocate shared subnet: %s",
2600 isc_result_totext (status
));
2601 if (clone_group (&share
-> group
, group
, MDL
) == 0) {
2602 log_fatal ("Can't clone group for shared net");
2604 shared_network_reference (&share
-> group
-> shared_network
,
2607 /* Get the name of the shared network... */
2608 token
= peek_token (&val
, (unsigned *)0, cfile
);
2609 if (token
== STRING
) {
2610 skip_token(&val
, (unsigned *)0, cfile
);
2613 parse_warn (cfile
, "zero-length shared network name");
2614 val
= "<no-name-given>";
2616 name
= dmalloc (strlen (val
) + 1, MDL
);
2618 log_fatal ("no memory for shared network name");
2621 name
= parse_host_name (cfile
);
2624 "expecting a name for shared-network");
2625 skip_to_semi (cfile
);
2626 shared_network_dereference (&share
, MDL
);
2630 share
-> name
= name
;
2632 if (!parse_lbrace (cfile
)) {
2633 shared_network_dereference (&share
, MDL
);
2638 token
= peek_token (&val
, (unsigned *)0, cfile
);
2639 if (token
== RBRACE
) {
2640 skip_token(&val
, (unsigned *)0, cfile
);
2641 if (!share
-> subnets
)
2643 "empty shared-network decl");
2645 enter_shared_network (share
);
2646 shared_network_dereference (&share
, MDL
);
2648 } else if (token
== END_OF_FILE
) {
2649 skip_token(&val
, (unsigned *)0, cfile
);
2650 parse_warn (cfile
, "unexpected end of file");
2652 } else if (token
== INTERFACE
) {
2653 skip_token(&val
, (unsigned *)0, cfile
);
2654 token
= next_token (&val
, (unsigned *)0, cfile
);
2655 new_shared_network_interface (cfile
, share
, val
);
2656 if (!parse_semi (cfile
))
2661 declaration
= parse_statement (cfile
, share
-> group
,
2663 (struct host_decl
*)0,
2666 shared_network_dereference (&share
, MDL
);
2671 common_subnet_parsing(struct parse
*cfile
,
2672 struct shared_network
*share
,
2673 struct subnet
*subnet
) {
2674 enum dhcp_token token
;
2675 struct subnet
*t
, *u
;
2677 int declaration
= 0;
2679 enter_subnet(subnet
);
2681 if (!parse_lbrace(cfile
)) {
2682 subnet_dereference(&subnet
, MDL
);
2687 token
= peek_token(&val
, NULL
, cfile
);
2688 if (token
== RBRACE
) {
2689 skip_token(&val
, NULL
, cfile
);
2691 } else if (token
== END_OF_FILE
) {
2692 skip_token(&val
, NULL
, cfile
);
2693 parse_warn (cfile
, "unexpected end of file");
2695 } else if (token
== INTERFACE
) {
2696 skip_token(&val
, NULL
, cfile
);
2697 token
= next_token(&val
, NULL
, cfile
);
2698 new_shared_network_interface(cfile
, share
, val
);
2699 if (!parse_semi(cfile
))
2703 declaration
= parse_statement(cfile
, subnet
->group
,
2709 /* Add the subnet to the list of subnets in this shared net. */
2710 if (share
->subnets
== NULL
) {
2711 subnet_reference(&share
->subnets
, subnet
, MDL
);
2714 for (t
= share
->subnets
; t
->next_sibling
; t
= t
->next_sibling
) {
2715 if (subnet_inner_than(subnet
, t
, 0)) {
2716 subnet_reference(&subnet
->next_sibling
, t
, MDL
);
2718 subnet_dereference(&u
->next_sibling
,
2720 subnet_reference(&u
->next_sibling
,
2723 subnet_dereference(&share
->subnets
,
2725 subnet_reference(&share
->subnets
,
2728 subnet_dereference(&subnet
, MDL
);
2733 subnet_reference(&t
->next_sibling
, subnet
, MDL
);
2735 subnet_dereference(&subnet
, MDL
);
2739 /* subnet-declaration :==
2740 net NETMASK netmask RBRACE parameters declarations LBRACE */
2742 void parse_subnet_declaration (cfile
, share
)
2743 struct parse
*cfile
;
2744 struct shared_network
*share
;
2747 enum dhcp_token token
;
2748 struct subnet
*subnet
;
2750 unsigned char addr
[4];
2751 unsigned len
= sizeof addr
;
2752 isc_result_t status
;
2754 subnet
= (struct subnet
*)0;
2755 status
= subnet_allocate (&subnet
, MDL
);
2756 if (status
!= ISC_R_SUCCESS
)
2757 log_fatal ("Allocation of new subnet failed: %s",
2758 isc_result_totext (status
));
2759 shared_network_reference (&subnet
-> shared_network
, share
, MDL
);
2762 * If our parent shared network was implicitly created by the software,
2763 * and not explicitly configured by the user, then we actually put all
2764 * configuration scope in the parent (the shared network and subnet
2765 * share the same {}-level scope).
2767 * Otherwise, we clone the parent group and continue as normal.
2769 if (share
->flags
& SHARED_IMPLICIT
) {
2770 group_reference(&subnet
->group
, share
->group
, MDL
);
2772 if (!clone_group(&subnet
->group
, share
->group
, MDL
)) {
2773 log_fatal("Allocation of group for new subnet failed.");
2776 subnet_reference (&subnet
-> group
-> subnet
, subnet
, MDL
);
2778 /* Get the network number... */
2779 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2780 subnet_dereference (&subnet
, MDL
);
2783 memcpy (iaddr
.iabuf
, addr
, len
);
2785 subnet
-> net
= iaddr
;
2787 token
= next_token (&val
, (unsigned *)0, cfile
);
2788 if (token
!= NETMASK
) {
2789 parse_warn (cfile
, "Expecting netmask");
2790 skip_to_semi (cfile
);
2794 /* Get the netmask... */
2795 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2796 subnet_dereference (&subnet
, MDL
);
2799 memcpy (iaddr
.iabuf
, addr
, len
);
2801 subnet
-> netmask
= iaddr
;
2803 /* Validate the network number/netmask pair. */
2804 if (host_addr (subnet
-> net
, subnet
-> netmask
)) {
2807 /* dup it, since piaddr is re-entrant */
2808 maskstr
= strdup (piaddr (subnet
-> netmask
));
2809 if (maskstr
== NULL
) {
2810 log_fatal("Allocation of subnet maskstr failed: %s",
2811 piaddr (subnet
-> net
));
2815 "subnet %s netmask %s: bad subnet number/mask combination.",
2816 piaddr (subnet
-> net
), maskstr
);
2818 subnet_dereference (&subnet
, MDL
);
2819 skip_to_semi (cfile
);
2823 common_subnet_parsing(cfile
, share
, subnet
);
2826 /* subnet6-declaration :==
2827 net / bits RBRACE parameters declarations LBRACE */
2830 parse_subnet6_declaration(struct parse
*cfile
, struct shared_network
*share
) {
2831 #if !defined(DHCPv6)
2832 parse_warn(cfile
, "No DHCPv6 support.");
2833 skip_to_semi(cfile
);
2834 #else /* defined(DHCPv6) */
2835 struct subnet
*subnet
;
2836 isc_result_t status
;
2837 enum dhcp_token token
;
2841 const static int mask
[] = { 0x00, 0x80, 0xC0, 0xE0,
2842 0xF0, 0xF8, 0xFC, 0xFE };
2845 #if defined(DHCP4o6)
2846 if ((local_family
!= AF_INET6
) && !dhcpv4_over_dhcpv6
) {
2847 parse_warn(cfile
, "subnet6 statement is only supported "
2848 "in DHCPv6 and DHCPv4o6 modes.");
2849 skip_to_semi(cfile
);
2852 #else /* defined(DHCP4o6) */
2853 if (local_family
!= AF_INET6
) {
2854 parse_warn(cfile
, "subnet6 statement is only supported "
2856 skip_to_semi(cfile
);
2859 #endif /* !defined(DHCP4o6) */
2862 status
= subnet_allocate(&subnet
, MDL
);
2863 if (status
!= ISC_R_SUCCESS
) {
2864 log_fatal("Allocation of new subnet failed: %s",
2865 isc_result_totext(status
));
2867 shared_network_reference(&subnet
->shared_network
, share
, MDL
);
2870 * If our parent shared network was implicitly created by the software,
2871 * and not explicitly configured by the user, then we actually put all
2872 * configuration scope in the parent (the shared network and subnet
2873 * share the same {}-level scope).
2875 * Otherwise, we clone the parent group and continue as normal.
2877 if (share
->flags
& SHARED_IMPLICIT
) {
2878 group_reference(&subnet
->group
, share
->group
, MDL
);
2880 if (!clone_group(&subnet
->group
, share
->group
, MDL
)) {
2881 log_fatal("Allocation of group for new subnet failed.");
2884 subnet_reference(&subnet
->group
->subnet
, subnet
, MDL
);
2886 if (!parse_ip6_addr(cfile
, &subnet
->net
)) {
2887 subnet_dereference(&subnet
, MDL
);
2891 token
= next_token(&val
, NULL
, cfile
);
2892 if (token
!= SLASH
) {
2893 parse_warn(cfile
, "Expecting a '/'.");
2894 skip_to_semi(cfile
);
2898 token
= next_token(&val
, NULL
, cfile
);
2899 if (token
!= NUMBER
) {
2900 parse_warn(cfile
, "Expecting a number.");
2901 skip_to_semi(cfile
);
2905 subnet
->prefix_len
= strtol(val
, &endp
, 10);
2906 if ((subnet
->prefix_len
< 0) ||
2907 (subnet
->prefix_len
> 128) ||
2909 parse_warn(cfile
, "Expecting a number between 0 and 128.");
2910 skip_to_semi(cfile
);
2914 if (!is_cidr_mask_valid(&subnet
->net
, subnet
->prefix_len
)) {
2915 parse_warn(cfile
, "New subnet mask too short.");
2916 skip_to_semi(cfile
);
2923 subnet
->netmask
.len
= 16;
2924 ofs
= subnet
->prefix_len
/ 8;
2925 if (ofs
< subnet
->netmask
.len
) {
2926 subnet
->netmask
.iabuf
[ofs
] = mask
[subnet
->prefix_len
% 8];
2928 while (--ofs
>= 0) {
2929 subnet
->netmask
.iabuf
[ofs
] = 0xFF;
2932 /* Validate the network number/netmask pair. */
2933 iaddr
= subnet_number(subnet
->net
, subnet
->netmask
);
2934 if (memcmp(&iaddr
, &subnet
->net
, 16) != 0) {
2936 "subnet %s/%d: prefix not long enough for address.",
2937 piaddr(subnet
->net
), subnet
->prefix_len
);
2938 subnet_dereference(&subnet
, MDL
);
2939 skip_to_semi(cfile
);
2943 if (!common_subnet_parsing(cfile
, share
, subnet
)) {
2946 #endif /* defined(DHCPv6) */
2949 /* group-declaration :== RBRACE parameters declarations LBRACE */
2951 void parse_group_declaration (cfile
, group
)
2952 struct parse
*cfile
;
2953 struct group
*group
;
2956 enum dhcp_token token
;
2958 int declaration
= 0;
2959 struct group_object
*t
= NULL
;
2960 isc_result_t status
;
2967 if (!clone_group(&g
, group
, MDL
))
2968 log_fatal("no memory for explicit group.");
2970 token
= peek_token(&val
, NULL
, cfile
);
2971 if (is_identifier (token
) || token
== STRING
) {
2972 skip_token(&val
, NULL
, cfile
);
2974 name
= dmalloc(strlen(val
) + 1, MDL
);
2976 log_fatal("no memory for group decl name %s", val
);
2980 if (!parse_lbrace(cfile
)) {
2981 group_dereference(&g
, MDL
);
2986 token
= peek_token(&val
, NULL
, cfile
);
2987 if (token
== RBRACE
) {
2988 skip_token(&val
, NULL
, cfile
);
2990 } else if (token
== END_OF_FILE
) {
2991 skip_token(&val
, NULL
, cfile
);
2992 parse_warn(cfile
, "unexpected end of file");
2994 } else if (token
== TOKEN_DELETED
) {
2995 skip_token(&val
, NULL
, cfile
);
2998 } else if (token
== DYNAMIC
) {
2999 skip_token(&val
, NULL
, cfile
);
3002 } else if (token
== STATIC
) {
3003 skip_token(&val
, NULL
, cfile
);
3007 declaration
= parse_statement(cfile
, g
, GROUP_DECL
,
3013 if (group_name_hash
) {
3015 if (group_hash_lookup(&t
, group_name_hash
,
3017 strlen(name
), MDL
)) {
3023 status
= group_object_allocate(&t
, MDL
);
3024 if (status
!= ISC_R_SUCCESS
)
3025 log_fatal("no memory for group decl %s: %s",
3026 val
, isc_result_totext(status
));
3027 group_reference(&t
->group
, g
, MDL
);
3029 /* no need to include deletedp as it's handled above */
3030 t
->flags
= ((staticp
? GROUP_OBJECT_STATIC
: 0) |
3031 (dynamicp
? GROUP_OBJECT_DYNAMIC
: 0));
3032 supersede_group(t
, 0);
3035 group_object_dereference(&t
, MDL
);
3039 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
3040 ip-addrs-or-hostnames :== ip-addr-or-hostname
3041 | ip-addrs-or-hostnames ip-addr-or-hostname */
3044 parse_fixed_addr_param(struct option_cache
**oc
,
3045 struct parse
*cfile
,
3046 enum dhcp_token type
) {
3049 enum dhcp_token token
;
3050 struct expression
*expr
= NULL
;
3051 struct expression
*tmp
, *new;
3056 if (type
== FIXED_ADDR
) {
3057 parse_ok
= parse_ip_addr_or_hostname(&tmp
, cfile
, 1);
3059 /* INSIST(type == FIXED_ADDR6); */
3060 parse_ok
= parse_ip6_addr_expr(&tmp
, cfile
);
3065 status
= make_concat(&new, expr
, tmp
);
3066 expression_dereference(&expr
, MDL
);
3067 expression_dereference(&tmp
, MDL
);
3077 expression_dereference (&expr
, MDL
);
3081 token
= peek_token(&val
, NULL
, cfile
);
3082 if (token
== COMMA
) {
3083 token
= next_token(&val
, NULL
, cfile
);
3085 } while (token
== COMMA
);
3087 if (!parse_semi(cfile
)) {
3089 expression_dereference (&expr
, MDL
);
3094 status
= option_cache(oc
, NULL
, expr
, NULL
, MDL
);
3095 expression_dereference(&expr
, MDL
);
3099 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
3101 lease_parameters :== <nil>
3103 | lease_parameters lease_parameter
3105 lease_parameter :== STARTS date
3108 | HARDWARE hardware-parameter
3109 | UID hex_numbers SEMI
3110 | HOSTNAME hostname SEMI
3111 | CLIENT_HOSTNAME hostname SEMI
3112 | CLASS identifier SEMI
3113 | DYNAMIC_BOOTP SEMI */
3115 int parse_lease_declaration (struct lease
**lp
, struct parse
*cfile
)
3118 enum dhcp_token token
;
3119 unsigned char addr
[4];
3120 unsigned len
= sizeof addr
;
3124 struct lease
*lease
;
3125 struct executable_statement
*on
;
3128 int noequal
, newbinding
;
3129 struct binding
*binding
;
3130 struct binding_value
*nv
;
3131 isc_result_t status
;
3132 struct option_cache
*oc
;
3134 binding_state_t new_state
;
3135 unsigned buflen
= 0;
3136 struct class *class;
3138 lease
= (struct lease
*)0;
3139 status
= lease_allocate (&lease
, MDL
);
3140 if (status
!= ISC_R_SUCCESS
)
3143 /* Get the address for which the lease has been issued. */
3144 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
3145 lease_dereference (&lease
, MDL
);
3148 memcpy (lease
-> ip_addr
.iabuf
, addr
, len
);
3149 lease
-> ip_addr
.len
= len
;
3151 if (!parse_lbrace (cfile
)) {
3152 lease_dereference (&lease
, MDL
);
3157 token
= next_token (&val
, (unsigned *)0, cfile
);
3158 if (token
== RBRACE
)
3160 else if (token
== END_OF_FILE
) {
3161 parse_warn (cfile
, "unexpected end of file");
3164 strncpy (tbuf
, val
, sizeof tbuf
);
3165 tbuf
[(sizeof tbuf
) - 1] = 0;
3167 /* Parse any of the times associated with the lease. */
3176 t
= parse_date (cfile
);
3180 lease
-> starts
= t
;
3208 default: /* for gcc, we'll never get here. */
3209 log_fatal ("Impossible error at %s:%d.", MDL
);
3214 /* Colon-separated hexadecimal octets... */
3217 token
= peek_token (&val
, (unsigned *)0, cfile
);
3218 if (token
== STRING
) {
3219 unsigned char *tuid
;
3220 skip_token(&val
, &buflen
, cfile
);
3221 if (buflen
< sizeof lease
-> uid_buf
) {
3222 tuid
= lease
-> uid_buf
;
3224 sizeof lease
-> uid_buf
;
3226 tuid
= ((unsigned char *)
3227 dmalloc (buflen
, MDL
));
3229 log_error ("no space for uid");
3230 lease_dereference (&lease
,
3234 lease
-> uid_max
= buflen
;
3236 lease
-> uid_len
= buflen
;
3237 memcpy (tuid
, val
, lease
-> uid_len
);
3238 lease
-> uid
= tuid
;
3241 lease
-> uid
= (parse_numeric_aggregate
3242 (cfile
, (unsigned char *)0,
3243 &buflen
, ':', 16, 8));
3244 if (!lease
-> uid
) {
3245 lease_dereference (&lease
, MDL
);
3248 lease
-> uid_len
= buflen
;
3249 lease
-> uid_max
= buflen
;
3250 if (lease
-> uid_len
== 0) {
3251 lease
-> uid
= (unsigned char *)0;
3252 parse_warn (cfile
, "zero-length uid");
3259 if (!lease
-> uid
) {
3260 log_fatal ("No memory for lease uid");
3266 token
= next_token (&val
, (unsigned *)0, cfile
);
3267 if (!is_identifier (token
)) {
3269 skip_to_rbrace (cfile
, 1);
3270 lease_dereference (&lease
, MDL
);
3274 /* for now, we aren't using this. */
3279 parse_hardware_param (cfile
,
3280 &lease
-> hardware_addr
);
3283 case TOKEN_RESERVED
:
3285 lease
->flags
|= RESERVED_LEASE
;
3291 lease
-> flags
|= BOOTP_LEASE
;
3295 /* XXX: Reverse compatibility? */
3296 case TOKEN_ABANDONED
:
3298 lease
-> binding_state
= FTS_ABANDONED
;
3299 lease
-> next_binding_state
= FTS_ABANDONED
;
3305 token
= next_token (&val
, (unsigned *)0, cfile
);
3306 if (token
!= BINDING
) {
3307 parse_warn (cfile
, "expecting 'binding'");
3308 skip_to_semi (cfile
);
3311 goto do_binding_state
;
3315 token
= next_token(&val
, NULL
, cfile
);
3316 if (token
!= BINDING
) {
3317 parse_warn(cfile
, "expecting 'binding'");
3318 skip_to_semi(cfile
);
3321 goto do_binding_state
;
3327 token
= next_token (&val
, (unsigned *)0, cfile
);
3328 if (token
!= STATE
) {
3329 parse_warn (cfile
, "expecting 'state'");
3330 skip_to_semi (cfile
);
3333 token
= next_token (&val
, (unsigned *)0, cfile
);
3335 case TOKEN_ABANDONED
:
3336 new_state
= FTS_ABANDONED
;
3339 new_state
= FTS_FREE
;
3342 new_state
= FTS_ACTIVE
;
3345 new_state
= FTS_EXPIRED
;
3347 case TOKEN_RELEASED
:
3348 new_state
= FTS_RELEASED
;
3351 new_state
= FTS_RESET
;
3354 new_state
= FTS_BACKUP
;
3357 /* RESERVED and BOOTP states preserved for
3358 * compatibleness with older versions.
3360 case TOKEN_RESERVED
:
3361 new_state
= FTS_ACTIVE
;
3362 lease
->flags
|= RESERVED_LEASE
;
3365 new_state
= FTS_ACTIVE
;
3366 lease
->flags
|= BOOTP_LEASE
;
3371 "%s: expecting a binding state.",
3373 skip_to_semi (cfile
);
3377 if (seenbit
== 256) {
3378 lease
-> binding_state
= new_state
;
3381 * Apply default/conservative next/rewind
3382 * binding states if they haven't been set
3383 * yet. These defaults will be over-ridden if
3384 * they are set later in parsing.
3386 if (!(seenmask
& 128))
3387 lease
->next_binding_state
= new_state
;
3389 /* The most conservative rewind state. */
3390 if (!(seenmask
& 512))
3391 lease
->rewind_binding_state
= new_state
;
3392 } else if (seenbit
== 128)
3393 lease
-> next_binding_state
= new_state
;
3394 else if (seenbit
== 512)
3395 lease
->rewind_binding_state
= new_state
;
3397 log_fatal("Impossible condition at %s:%d.",
3403 case CLIENT_HOSTNAME
:
3405 token
= peek_token (&val
, (unsigned *)0, cfile
);
3406 if (token
== STRING
) {
3407 if (!parse_string (cfile
,
3408 &lease
-> client_hostname
,
3410 lease_dereference (&lease
, MDL
);
3414 lease
-> client_hostname
=
3415 parse_host_name (cfile
);
3416 if (lease
-> client_hostname
)
3420 "expecting a hostname.");
3421 skip_to_semi (cfile
);
3422 lease_dereference (&lease
, MDL
);
3430 class = (struct class *)0;
3431 token
= next_token (&val
, (unsigned *)0, cfile
);
3432 if (token
== CLASS
) {
3433 token
= next_token (&val
,
3434 (unsigned *)0, cfile
);
3435 if (token
!= STRING
) {
3436 parse_warn (cfile
, "expecting string");
3438 skip_to_semi (cfile
);
3442 if (lease
-> billing_class
)
3443 class_dereference (&lease
-> billing_class
,
3445 find_class (&class, val
, MDL
);
3448 "unknown class %s", val
);
3450 } else if (token
== SUBCLASS
) {
3451 if (lease
-> billing_class
)
3452 class_dereference (&lease
-> billing_class
,
3454 parse_class_declaration(&class, cfile
, NULL
,
3455 CLASS_TYPE_SUBCLASS
);
3457 parse_warn (cfile
, "expecting \"class\"");
3459 skip_to_semi (cfile
);
3462 class_reference (&lease
-> billing_class
,
3464 class_dereference (&class, MDL
);
3469 on
= (struct executable_statement
*)0;
3471 if (!parse_on_statement (&on
, cfile
, &lose
)) {
3472 skip_to_rbrace (cfile
, 1);
3473 lease_dereference (&lease
, MDL
);
3477 if ((on
->data
.on
.evtypes
& ON_EXPIRY
) &&
3478 on
->data
.on
.statements
) {
3480 executable_statement_reference
3481 (&lease
->on_star
.on_expiry
,
3482 on
->data
.on
.statements
, MDL
);
3484 if ((on
->data
.on
.evtypes
& ON_RELEASE
) &&
3485 on
->data
.on
.statements
) {
3487 executable_statement_reference
3488 (&lease
->on_star
.on_release
,
3489 on
->data
.on
.statements
, MDL
);
3491 executable_statement_dereference (&on
, MDL
);
3498 oc
= (struct option_cache
*)0;
3499 if (parse_option_decl (&oc
, cfile
)) {
3500 if (oc
-> option
-> universe
!=
3503 "agent option expected.");
3504 option_cache_dereference (&oc
, MDL
);
3507 if (!lease
-> agent_options
&&
3508 !(option_chain_head_allocate
3509 (&lease
-> agent_options
, MDL
))) {
3510 log_error ("no memory to stash agent option");
3513 for (p
= &lease
-> agent_options
-> first
;
3514 *p
; p
= &((*p
) -> cdr
))
3517 option_cache_reference (((struct option_cache
**)
3518 &((*p
) -> car
)), oc
, MDL
);
3519 option_cache_dereference (&oc
, MDL
);
3526 token
= next_token (&val
, (unsigned *)0, cfile
);
3527 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
3529 "%s can't be a variable name",
3532 skip_to_semi (cfile
);
3533 lease_dereference (&lease
, MDL
);
3540 binding
= find_binding (lease
-> scope
, val
);
3542 binding
= (struct binding
*)0;
3545 if (!lease
-> scope
)
3546 if (!(binding_scope_allocate
3547 (&lease
-> scope
, MDL
)))
3548 log_fatal ("no memory for scope");
3549 binding
= dmalloc (sizeof *binding
, MDL
);
3551 log_fatal ("No memory for lease %s.",
3553 memset (binding
, 0, sizeof *binding
);
3555 dmalloc (strlen (val
) + 1, MDL
);
3556 if (!binding
-> name
)
3557 log_fatal ("No memory for binding %s.",
3559 strcpy (binding
-> name
, val
);
3566 if (!binding_value_allocate(&nv
, MDL
))
3567 log_fatal("no memory for binding value.");
3570 token
= next_token (&val
, (unsigned *)0, cfile
);
3571 if (token
!= EQUAL
) {
3573 "expecting '=' in set statement.");
3578 if (!parse_binding_value(cfile
, nv
)) {
3579 binding_value_dereference(&nv
, MDL
);
3580 lease_dereference(&lease
, MDL
);
3585 binding_value_reference(&binding
->value
,
3587 binding
->next
= lease
->scope
->bindings
;
3588 lease
->scope
->bindings
= binding
;
3590 binding_value_dereference(&binding
->value
, MDL
);
3591 binding_value_reference(&binding
->value
,
3595 binding_value_dereference(&nv
, MDL
);
3601 if (!strcasecmp (val
, "ddns-fwd-name")) {
3605 } else if (!strcasecmp (val
, "ddns-rev-name")) {
3610 parse_warn(cfile
, "Unexpected configuration "
3612 skip_to_semi (cfile
);
3614 lease_dereference (&lease
, MDL
);
3618 if (seenmask
& seenbit
) {
3620 "Too many %s parameters in lease %s\n",
3621 tbuf
, piaddr (lease
-> ip_addr
));
3623 seenmask
|= seenbit
;
3627 /* If no binding state is specified, make one up. */
3628 if (!(seenmask
& 256)) {
3629 if (lease
->ends
> cur_time
||
3630 lease
->on_star
.on_expiry
|| lease
->on_star
.on_release
)
3631 lease
->binding_state
= FTS_ACTIVE
;
3632 #if defined (FAILOVER_PROTOCOL)
3633 else if (lease
->pool
&& lease
->pool
->failover_peer
)
3634 lease
->binding_state
= FTS_EXPIRED
;
3637 lease
->binding_state
= FTS_FREE
;
3638 if (lease
->binding_state
== FTS_ACTIVE
) {
3639 #if defined (FAILOVER_PROTOCOL)
3640 if (lease
->pool
&& lease
->pool
->failover_peer
)
3641 lease
->next_binding_state
= FTS_EXPIRED
;
3644 lease
->next_binding_state
= FTS_FREE
;
3646 lease
->next_binding_state
= lease
->binding_state
;
3648 /* The most conservative rewind state implies no rewind. */
3649 lease
->rewind_binding_state
= lease
->binding_state
;
3652 if (!(seenmask
& 65536))
3653 lease
->tstp
= lease
->ends
;
3655 lease_reference (lp
, lease
, MDL
);
3656 lease_dereference (&lease
, MDL
);
3660 /* Parse the right side of a 'binding value'.
3662 * set foo = "bar"; is a string
3663 * set foo = false; is a boolean
3664 * set foo = %31; is a numeric value.
3667 parse_binding_value(struct parse
*cfile
, struct binding_value
*value
)
3669 struct data_string
*data
;
3675 if ((cfile
== NULL
) || (value
== NULL
))
3676 log_fatal("Invalid arguments at %s:%d.", MDL
);
3678 token
= peek_token(&val
, NULL
, cfile
);
3679 if (token
== STRING
) {
3680 skip_token(&val
, &buflen
, cfile
);
3682 value
->type
= binding_data
;
3683 value
->value
.data
.len
= buflen
;
3685 data
= &value
->value
.data
;
3687 if (!buffer_allocate(&data
->buffer
, buflen
+ 1, MDL
))
3688 log_fatal ("No memory for binding.");
3690 memcpy(data
->buffer
->data
, val
, buflen
+ 1);
3692 data
->data
= data
->buffer
->data
;
3693 data
->terminated
= 1;
3694 } else if (token
== NUMBER_OR_NAME
) {
3695 value
->type
= binding_data
;
3697 data
= &value
->value
.data
;
3698 s
= parse_numeric_aggregate(cfile
, NULL
, &data
->len
,
3701 skip_to_semi(cfile
);
3706 if (!buffer_allocate(&data
->buffer
, data
->len
+ 1,
3708 log_fatal("No memory for binding.");
3710 memcpy(data
->buffer
->data
, s
, data
->len
);
3711 data
->data
= data
->buffer
->data
;
3715 } else if (token
== PERCENT
) {
3716 skip_token(&val
, NULL
, cfile
);
3717 token
= next_token(&val
, NULL
, cfile
);
3718 if (token
!= NUMBER
) {
3719 parse_warn(cfile
, "expecting decimal number.");
3721 skip_to_semi(cfile
);
3724 value
->type
= binding_numeric
;
3725 value
->value
.intval
= atol(val
);
3726 } else if (token
== NAME
) {
3727 token
= next_token(&val
, NULL
, cfile
);
3728 value
->type
= binding_boolean
;
3729 if (!strcasecmp(val
, "true"))
3730 value
->value
.boolean
= 1;
3731 else if (!strcasecmp(val
, "false"))
3732 value
->value
.boolean
= 0;
3734 parse_warn(cfile
, "expecting true or false");
3736 skip_to_semi(cfile
);
3740 parse_warn (cfile
, "expecting a constant value.");
3742 skip_to_semi (cfile
);
3749 /* address-range-declaration :== ip-address ip-address SEMI
3750 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3752 void parse_address_range (cfile
, group
, type
, inpool
, lpchain
)
3753 struct parse
*cfile
;
3754 struct group
*group
;
3756 struct pool
*inpool
;
3757 struct lease
**lpchain
;
3759 struct iaddr low
, high
, net
;
3760 unsigned char addr
[4];
3761 unsigned len
= sizeof addr
;
3762 enum dhcp_token token
;
3765 struct subnet
*subnet
;
3766 struct shared_network
*share
;
3768 isc_result_t status
;
3770 if ((token
= peek_token (&val
,
3771 (unsigned *)0, cfile
)) == DYNAMIC_BOOTP
) {
3772 skip_token(&val
, (unsigned *)0, cfile
);
3776 /* Get the bottom address in the range... */
3777 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3779 memcpy (low
.iabuf
, addr
, len
);
3782 /* Only one address? */
3783 token
= peek_token (&val
, (unsigned *)0, cfile
);
3787 /* Get the top address in the range... */
3788 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3790 memcpy (high
.iabuf
, addr
, len
);
3794 token
= next_token (&val
, (unsigned *)0, cfile
);
3795 if (token
!= SEMI
) {
3796 parse_warn (cfile
, "semicolon expected.");
3797 skip_to_semi (cfile
);
3801 if (type
== SUBNET_DECL
) {
3802 subnet
= group
-> subnet
;
3803 share
= subnet
-> shared_network
;
3805 share
= group
-> shared_network
;
3806 for (subnet
= share
-> subnets
;
3807 subnet
; subnet
= subnet
-> next_sibling
) {
3808 net
= subnet_number (low
, subnet
-> netmask
);
3809 if (addr_eq (net
, subnet
-> net
))
3813 parse_warn (cfile
, "address range not on network %s",
3814 group
-> shared_network
-> name
);
3815 log_error ("Be sure to place pool statement after %s",
3816 "related subnet declarations.");
3822 struct pool
*last
= (struct pool
*)0;
3824 /* If we're permitting dynamic bootp for this range,
3825 then look for a pool with an empty prohibit list and
3826 a permit list with one entry that permits all clients. */
3827 for (pool
= share
-> pools
; pool
; pool
= pool
-> next
) {
3828 if ((!dynamic
&& !pool
-> permit_list
&&
3829 pool
-> prohibit_list
&&
3830 !pool
-> prohibit_list
-> next
&&
3831 (pool
-> prohibit_list
-> type
==
3832 permit_dynamic_bootp_clients
)) ||
3833 (dynamic
&& !pool
-> prohibit_list
&&
3834 pool
-> permit_list
&&
3835 !pool
-> permit_list
-> next
&&
3836 (pool
-> permit_list
-> type
==
3837 permit_all_clients
))) {
3843 /* If we didn't get a pool, make one. */
3846 status
= pool_allocate (&pool
, MDL
);
3847 if (status
!= ISC_R_SUCCESS
)
3848 log_fatal ("no memory for ad-hoc pool: %s",
3849 isc_result_totext (status
));
3850 p
= new_permit (MDL
);
3852 log_fatal ("no memory for ad-hoc permit.");
3854 /* Dynamic pools permit all clients. Otherwise
3855 we prohibit BOOTP clients. */
3857 p
-> type
= permit_all_clients
;
3858 pool
-> permit_list
= p
;
3860 p
-> type
= permit_dynamic_bootp_clients
;
3861 pool
-> prohibit_list
= p
;
3865 pool_reference (&last
-> next
, pool
, MDL
);
3867 pool_reference (&share
-> pools
, pool
, MDL
);
3868 shared_network_reference (&pool
-> shared_network
,
3870 if (!clone_group (&pool
-> group
, share
-> group
, MDL
))
3871 log_fatal ("no memory for anon pool group.");
3873 pool
= (struct pool
*)0;
3875 pool_reference (&pool
, last
, MDL
);
3877 pool_reference (&pool
, share
-> pools
, MDL
);
3880 pool
= (struct pool
*)0;
3881 pool_reference (&pool
, inpool
, MDL
);
3884 #if defined (FAILOVER_PROTOCOL)
3885 if (pool
-> failover_peer
&& dynamic
) {
3886 /* Doctor, do you think I'm overly sensitive
3887 about getting bug reports I can't fix? */
3888 parse_warn (cfile
, "dynamic-bootp flag is %s",
3889 "not permitted for address");
3890 log_error ("range declarations where there is a failover");
3891 log_error ("peer in scope. If you wish to declare an");
3892 log_error ("address range from which dynamic bootp leases");
3893 log_error ("can be allocated, please declare it within a");
3894 log_error ("pool declaration that also contains the \"no");
3895 log_error ("failover\" statement. The failover protocol");
3896 log_error ("itself does not permit dynamic bootp - this");
3897 log_error ("is not a limitation specific to the ISC DHCP");
3898 log_error ("server. Please don't ask me to defend this");
3899 log_error ("until you have read and really tried %s",
3901 log_error ("the failover protocol specification.");
3903 /* We don't actually bomb at this point - instead,
3904 we let parse_lease_file notice the error and
3905 bomb at that point - it's easier. */
3907 #endif /* FAILOVER_PROTOCOL */
3909 /* Create the new address range... */
3910 new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
);
3911 pool_dereference (&pool
, MDL
);
3916 add_ipv6_pool_to_subnet(struct subnet
*subnet
, u_int16_t type
,
3917 struct iaddr
*lo_addr
, int bits
, int units
,
3918 struct ipv6_pond
*pond
) {
3919 struct ipv6_pool
*pool
;
3920 struct in6_addr tmp_in6_addr
;
3922 struct ipv6_pool
**tmp
;
3927 if (lo_addr
->len
!= sizeof(tmp_in6_addr
)) {
3928 log_fatal("Internal error: Attempt to add non-IPv6 address "
3929 "to IPv6 shared network.");
3931 memcpy(&tmp_in6_addr
, lo_addr
->iabuf
, sizeof(tmp_in6_addr
));
3933 if (ipv6_pool_allocate(&pool
, type
, &tmp_in6_addr
,
3934 bits
, units
, MDL
) != ISC_R_SUCCESS
) {
3935 log_fatal("Out of memory");
3939 * Add to our global IPv6 pool set.
3941 if (add_ipv6_pool(pool
) != ISC_R_SUCCESS
) {
3942 log_fatal ("Out of memory");
3946 * Link the pool to its network.
3948 pool
->subnet
= NULL
;
3949 subnet_reference(&pool
->subnet
, subnet
, MDL
);
3950 pool
->shared_network
= NULL
;
3951 shared_network_reference(&pool
->shared_network
,
3952 subnet
->shared_network
, MDL
);
3953 pool
->ipv6_pond
= NULL
;
3954 ipv6_pond_reference(&pool
->ipv6_pond
, pond
, MDL
);
3957 * Increase our array size for ipv6_pools in the pond
3959 if (pond
->ipv6_pools
== NULL
) {
3963 while (pond
->ipv6_pools
[num_pools
] != NULL
) {
3967 tmp
= dmalloc(sizeof(struct ipv6_pool
*) * (num_pools
+ 2), MDL
);
3969 log_fatal("Out of memory");
3971 if (num_pools
> 0) {
3972 memcpy(tmp
, pond
->ipv6_pools
,
3973 sizeof(struct ipv6_pool
*) * num_pools
);
3975 if (pond
->ipv6_pools
!= NULL
) {
3976 dfree(pond
->ipv6_pools
, MDL
);
3978 pond
->ipv6_pools
= tmp
;
3981 * Record this pool in our array of pools for this shared network.
3983 ipv6_pool_reference(&pond
->ipv6_pools
[num_pools
], pool
, MDL
);
3984 pond
->ipv6_pools
[num_pools
+1] = NULL
;
3986 /* Update the number of elements in the pond. Conveniently
3987 * we have the total size of the block in bits and the amount
3988 * we would allocate per element in units. For an address units
3989 * will always be 128, for a prefix it will be something else.
3991 * We need to make sure the number of elements isn't too large
3992 * to track. If so, we flag it to avoid wasting time with log
3993 * threshold logic. We also emit a log stating that log-threshold
3994 * will be disabled for the shared-network but that's done
3995 * elsewhere via report_log_threshold().
3999 /* Only bother if we aren't already flagged as jumbo */
4000 if (pond
->jumbo_range
== 0) {
4001 if ((units
- bits
) > (sizeof(isc_uint64_t
) * 8)) {
4002 pond
->jumbo_range
= 1;
4003 pond
->num_total
= POND_TRACK_MAX
;
4006 isc_uint64_t space_left
4007 = POND_TRACK_MAX
- pond
->num_total
;
4009 = (isc_uint64_t
)(1) << (units
- bits
);
4011 if (addon
> space_left
) {
4012 pond
->jumbo_range
= 1;
4013 pond
->num_total
= POND_TRACK_MAX
;
4015 pond
->num_total
+= addon
;
4023 * \brief Find or create a default pond
4025 * Find or create an ipv6_pond on which to attach the ipv6_pools. We
4026 * check the shared network to see if there is a general purpose
4027 * entry - this will have an empty prohibit list and a permit list
4028 * with a single entry that permits all clients. If the shared
4029 * network doesn't have one of them create it and attach it to
4030 * the shared network and the return argument.
4032 * This function is used when we have a range6 or prefix6 statement
4033 * inside a subnet6 statement but outside of a pool6 statement.
4034 * This routine constructs the missing ipv6_pond structure so
4036 * shared_network -> ipv6_pond -> ipv6_pool
4038 * \param[in] group = a pointer to the group structure from which
4039 * we can find the subnet and shared netowrk
4041 * \param[out] ret_pond = a pointer to space for the pointer to
4042 * the structure to return
4048 add_ipv6_pond_to_network(struct group
*group
,
4049 struct ipv6_pond
**ret_pond
) {
4051 struct ipv6_pond
*pond
= NULL
, *last
= NULL
;
4053 isc_result_t status
;
4054 struct shared_network
*shared
= group
->subnet
->shared_network
;
4056 for (pond
= shared
->ipv6_pond
; pond
; pond
= pond
->next
) {
4057 if ((pond
->group
->statements
== group
->statements
) &&
4058 (pond
->prohibit_list
== NULL
) &&
4059 (pond
->permit_list
!= NULL
) &&
4060 (pond
->permit_list
->next
== NULL
) &&
4061 (pond
->permit_list
->type
== permit_all_clients
)) {
4062 ipv6_pond_reference(ret_pond
, pond
, MDL
);
4068 /* no pond available, make one */
4069 status
= ipv6_pond_allocate(&pond
, MDL
);
4070 if (status
!= ISC_R_SUCCESS
)
4071 log_fatal ("no memory for ad-hoc ipv6 pond: %s",
4072 isc_result_totext (status
));
4073 p
= new_permit (MDL
);
4075 log_fatal ("no memory for ad-hoc ipv6 permit.");
4077 /* we permit all clients */
4078 p
->type
= permit_all_clients
;
4079 pond
->permit_list
= p
;
4081 /* and attach the pond to the return argument and the shared network */
4082 ipv6_pond_reference(ret_pond
, pond
, MDL
);
4084 if (shared
->ipv6_pond
)
4085 ipv6_pond_reference(&last
->next
, pond
, MDL
);
4087 ipv6_pond_reference(&shared
->ipv6_pond
, pond
, MDL
);
4089 shared_network_reference(&pond
->shared_network
, shared
, MDL
);
4090 if (!clone_group (&pond
->group
, group
, MDL
))
4091 log_fatal ("no memory for anon pool group.");
4093 ipv6_pond_dereference(&pond
, MDL
);
4098 /* address-range6-declaration :== ip-address6 ip-address6 SEMI
4099 | ip-address6 SLASH number SEMI
4100 | ip-address6 [SLASH number] TEMPORARY SEMI */
4103 parse_address_range6(struct parse
*cfile
,
4104 struct group
*group
,
4105 struct ipv6_pond
*inpond
) {
4106 struct iaddr lo
, hi
;
4108 enum dhcp_token token
;
4110 struct iaddrcidrnetlist
*nets
, net
;
4111 struct iaddrcidrnetlist
*p
;
4112 u_int16_t type
= D6O_IA_NA
;
4113 struct ipv6_pond
*pond
= NULL
;
4115 if (local_family
!= AF_INET6
) {
4116 parse_warn(cfile
, "range6 statement is only supported "
4118 skip_to_semi(cfile
);
4122 /* This is enforced by the caller, this is just a sanity check. */
4123 if (group
->subnet
== NULL
)
4124 log_fatal("Impossible condition at %s:%d.", MDL
);
4127 * Read starting address.
4129 if (!parse_ip6_addr(cfile
, &lo
)) {
4133 /* Make sure starting address is within the subnet */
4134 if (!addr_eq(group
->subnet
->net
,
4135 subnet_number(lo
, group
->subnet
->netmask
))) {
4136 parse_warn(cfile
, "range6 start address is outside the subnet");
4137 skip_to_semi(cfile
);
4142 * zero out the net entry in case we use it
4144 memset(&net
, 0, sizeof(net
));
4145 net
.cidrnet
.lo_addr
= lo
;
4148 * See if we we're using range or CIDR notation or TEMPORARY
4150 token
= peek_token(&val
, NULL
, cfile
);
4151 if (token
== SLASH
) {
4153 * '/' means CIDR notation, so read the bits we want.
4155 skip_token(NULL
, NULL
, cfile
);
4156 token
= next_token(&val
, NULL
, cfile
);
4157 if (token
!= NUMBER
) {
4158 parse_warn(cfile
, "expecting number");
4159 skip_to_semi(cfile
);
4162 net
.cidrnet
.bits
= atoi(val
);
4163 bits
= net
.cidrnet
.bits
;
4164 if ((bits
< 0) || (bits
> 128)) {
4165 parse_warn(cfile
, "networks have 0 to 128 bits");
4166 skip_to_semi(cfile
);
4169 if (bits
< group
->subnet
->prefix_len
) {
4171 "network mask smaller than subnet mask");
4172 skip_to_semi(cfile
);
4175 if (!is_cidr_mask_valid(&net
.cidrnet
.lo_addr
, bits
)) {
4176 parse_warn(cfile
, "network mask too short");
4177 skip_to_semi(cfile
);
4181 * can be temporary (RFC 4941 like)
4183 token
= peek_token(&val
, NULL
, cfile
);
4184 if (token
== TEMPORARY
) {
4186 parse_warn(cfile
, "temporary mask too short");
4188 parse_warn(cfile
, "temporary singleton?");
4189 skip_token(NULL
, NULL
, cfile
);
4195 } else if (token
== TEMPORARY
) {
4197 * temporary (RFC 4941)
4200 skip_token(NULL
, NULL
, cfile
);
4201 net
.cidrnet
.bits
= 64;
4202 if (!is_cidr_mask_valid(&net
.cidrnet
.lo_addr
,
4203 net
.cidrnet
.bits
)) {
4204 parse_warn(cfile
, "network mask too short");
4205 skip_to_semi(cfile
);
4213 * No '/', so we are looking for the end address of
4216 if (!parse_ip6_addr(cfile
, &hi
)) {
4220 /* Make sure ending address is within the subnet */
4221 if (!addr_eq(group
->subnet
->net
,
4222 subnet_number(hi
, group
->subnet
->netmask
))) {
4224 "range6 end address is outside the subnet");
4225 skip_to_semi(cfile
);
4230 * Convert our range to a set of CIDR networks.
4233 if (range2cidr(&nets
, &lo
, &hi
) != ISC_R_SUCCESS
) {
4234 log_fatal("Error converting range to CIDR networks");
4240 * See if we have a pond for this set of pools.
4241 * If the caller supplied one we use it, otherwise
4242 * check the shared network
4245 if (inpond
!= NULL
) {
4246 ipv6_pond_reference(&pond
, inpond
, MDL
);
4248 add_ipv6_pond_to_network(group
, &pond
);
4251 /* Now that we have a pond add the nets we have parsed */
4252 for (p
=nets
; p
!= NULL
; p
=p
->next
) {
4253 add_ipv6_pool_to_subnet(group
->subnet
, type
,
4254 &p
->cidrnet
.lo_addr
,
4255 p
->cidrnet
.bits
, 128, pond
);
4258 /* if we allocated a list free it now */
4260 free_iaddrcidrnetlist(&nets
);
4262 ipv6_pond_dereference(&pond
, MDL
);
4264 token
= next_token(NULL
, NULL
, cfile
);
4265 if (token
!= SEMI
) {
4266 parse_warn(cfile
, "semicolon expected.");
4267 skip_to_semi(cfile
);
4272 /* prefix6-declaration :== ip-address6 ip-address6 SLASH number SEMI */
4275 parse_prefix6(struct parse
*cfile
,
4276 struct group
*group
,
4277 struct ipv6_pond
*inpond
) {
4278 struct iaddr lo
, hi
;
4280 enum dhcp_token token
;
4282 struct iaddrcidrnetlist
*nets
;
4283 struct iaddrcidrnetlist
*p
;
4284 struct ipv6_pond
*pond
= NULL
;
4286 if (local_family
!= AF_INET6
) {
4287 parse_warn(cfile
, "prefix6 statement is only supported "
4289 skip_to_semi(cfile
);
4293 /* This is enforced by the caller, so it's just a sanity check. */
4294 if (group
->subnet
== NULL
)
4295 log_fatal("Impossible condition at %s:%d.", MDL
);
4298 * Read starting and ending address.
4300 if (!parse_ip6_addr(cfile
, &lo
)) {
4305 /* Prefixes are not required to be within the subnet, but I'm not
4306 * entirely sure that we won't want to revive this code as a warning
4307 * in the future so I'm ifdeffing it
4310 /* Make sure starting prefix is within the subnet */
4311 if (!addr_eq(group
->subnet
->net
,
4312 subnet_number(lo
, group
->subnet
->netmask
))) {
4313 parse_warn(cfile
, "prefix6 start prefix"
4314 " is outside the subnet");
4315 skip_to_semi(cfile
);
4320 if (!parse_ip6_addr(cfile
, &hi
)) {
4325 /* Prefixes are not required to be within the subnet, but I'm not
4326 * entirely sure that we won't want to revive this code as a warning
4327 * in the future so I'm ifdeffing it
4330 /* Make sure ending prefix is within the subnet */
4331 if (!addr_eq(group
->subnet
->net
,
4332 subnet_number(hi
, group
->subnet
->netmask
))) {
4333 parse_warn(cfile
, "prefix6 end prefix"
4334 " is outside the subnet");
4335 skip_to_semi(cfile
);
4341 * Next is '/' number ';'.
4343 token
= next_token(NULL
, NULL
, cfile
);
4344 if (token
!= SLASH
) {
4345 parse_warn(cfile
, "expecting '/'");
4347 skip_to_semi(cfile
);
4350 token
= next_token(&val
, NULL
, cfile
);
4351 if (token
!= NUMBER
) {
4352 parse_warn(cfile
, "expecting number");
4354 skip_to_semi(cfile
);
4358 if ((bits
<= 0) || (bits
>= 128)) {
4359 parse_warn(cfile
, "networks have 0 to 128 bits (exclusive)");
4364 /* Prefixes are not required to be within the subnet, but I'm not
4365 * entirely sure that we won't want to revive this code as a warning
4366 * in the future so I'm ifdeffing it
4369 if (bits
< group
->subnet
->prefix_len
) {
4370 parse_warn(cfile
, "network mask smaller than subnet mask");
4371 skip_to_semi(cfile
);
4376 if (!is_cidr_mask_valid(&lo
, bits
) ||
4377 !is_cidr_mask_valid(&hi
, bits
)) {
4378 parse_warn(cfile
, "network mask too short");
4379 skip_to_semi(cfile
);
4382 token
= next_token(NULL
, NULL
, cfile
);
4383 if (token
!= SEMI
) {
4384 parse_warn(cfile
, "semicolon expected.");
4385 skip_to_semi(cfile
);
4390 * Convert our range to a set of CIDR networks.
4393 if (range2cidr(&nets
, &lo
, &hi
) != ISC_R_SUCCESS
) {
4394 log_fatal("Error converting prefix to CIDR");
4398 * See if we have a pond for this set of pools.
4399 * If the caller supplied one we use it, otherwise
4400 * check the shared network
4403 if (inpond
!= NULL
) {
4404 ipv6_pond_reference(&pond
, inpond
, MDL
);
4406 add_ipv6_pond_to_network(group
, &pond
);
4409 for (p
= nets
; p
!= NULL
; p
= p
->next
) {
4410 /* Normalize and check. */
4411 if (p
->cidrnet
.bits
== 128) {
4412 p
->cidrnet
.bits
= bits
;
4414 if (p
->cidrnet
.bits
> bits
) {
4415 parse_warn(cfile
, "impossible mask length");
4418 add_ipv6_pool_to_subnet(group
->subnet
, D6O_IA_PD
,
4419 &p
->cidrnet
.lo_addr
,
4420 p
->cidrnet
.bits
, bits
, pond
);
4423 free_iaddrcidrnetlist(&nets
);
4426 /* fixed-prefix6 :== ip6-address SLASH number SEMI */
4429 parse_fixed_prefix6(struct parse
*cfile
, struct host_decl
*host_decl
) {
4430 struct iaddrcidrnetlist
*ia
, **h
;
4431 enum dhcp_token token
;
4435 * Get the head of the fixed-prefix list.
4437 h
= &host_decl
->fixed_prefix
;
4442 while (*h
!= NULL
) {
4447 * Allocate a new iaddrcidrnetlist structure.
4449 ia
= dmalloc(sizeof(*ia
), MDL
);
4451 log_fatal("Out of memory");
4457 if (!parse_ip6_addr(cfile
, &ia
->cidrnet
.lo_addr
)) {
4461 token
= next_token(NULL
, NULL
, cfile
);
4462 if (token
!= SLASH
) {
4464 parse_warn(cfile
, "expecting '/'");
4466 skip_to_semi(cfile
);
4469 token
= next_token(&val
, NULL
, cfile
);
4470 if (token
!= NUMBER
) {
4472 parse_warn(cfile
, "expecting number");
4474 skip_to_semi(cfile
);
4477 token
= next_token(NULL
, NULL
, cfile
);
4478 if (token
!= SEMI
) {
4480 parse_warn(cfile
, "semicolon expected.");
4481 skip_to_semi(cfile
);
4488 ia
->cidrnet
.bits
= atoi(val
);
4489 if ((ia
->cidrnet
.bits
< 0) || (ia
->cidrnet
.bits
> 128)) {
4491 parse_warn(cfile
, "networks have 0 to 128 bits");
4494 if (!is_cidr_mask_valid(&ia
->cidrnet
.lo_addr
, ia
->cidrnet
.bits
)) {
4496 parse_warn(cfile
, "network mask too short");
4509 * \brief Parse a pool6 statement
4511 * Pool statements are used to group declarations and permit & deny information
4512 * with a specific address range. They must be declared within a shared network
4513 * or subnet and there may be multiple pools withing a shared network or subnet.
4514 * Each pool may have a different set of permit or deny options.
4516 * \param[in] cfile = the configuration file being parsed
4517 * \param[in] group = the group structure for this pool
4518 * \param[in] type = the type of the enclosing statement. This must be
4519 * SUBNET_DECL for this function.
4522 * void - This function either parses the statement and updates the structures
4523 * or it generates an error message and possible halts the program if
4524 * it encounters a problem.
4526 void parse_pool6_statement (cfile
, group
, type
)
4527 struct parse
*cfile
;
4528 struct group
*group
;
4531 enum dhcp_token token
;
4534 struct ipv6_pond
*pond
, **p
;
4535 int declaration
= 0;
4536 isc_result_t status
;
4539 status
= ipv6_pond_allocate(&pond
, MDL
);
4540 if (status
!= ISC_R_SUCCESS
)
4541 log_fatal("no memory for pool6: %s",
4542 isc_result_totext (status
));
4544 if (type
== SUBNET_DECL
)
4545 shared_network_reference(&pond
->shared_network
,
4546 group
->subnet
->shared_network
,
4549 parse_warn(cfile
, "pool6s are only valid inside "
4550 "subnet statements.");
4551 ipv6_pond_dereference(&pond
, MDL
);
4552 skip_to_semi(cfile
);
4556 if (clone_group(&pond
->group
, group
, MDL
) == 0)
4557 log_fatal("can't clone pool6 group.");
4559 if (parse_lbrace(cfile
) == 0) {
4560 ipv6_pond_dereference(&pond
, MDL
);
4565 token
= peek_token(&val
, NULL
, cfile
);
4568 skip_token(NULL
, NULL
, cfile
);
4569 parse_address_range6(cfile
, group
, pond
);
4573 skip_token(NULL
, NULL
, cfile
);
4574 parse_prefix6(cfile
, group
, pond
);
4578 skip_token(NULL
, NULL
, cfile
);
4579 get_permit(cfile
, &pond
->permit_list
, 1,
4580 &pond
->valid_from
, &pond
->valid_until
);
4584 skip_token(NULL
, NULL
, cfile
);
4585 get_permit(cfile
, &pond
->prohibit_list
, 0,
4586 &pond
->valid_from
, &pond
->valid_until
);
4590 skip_token(&val
, NULL
, cfile
);
4596 * We can get to END_OF_FILE if, for instance,
4597 * the parse_statement() reads all available tokens
4598 * and leaves us at the end.
4600 parse_warn(cfile
, "unexpected end of file");
4604 declaration
= parse_statement(cfile
, pond
->group
,
4612 * A possible optimization is to see if this pond can be merged into
4613 * an already existing pond. But I'll pass on that for now as we need
4614 * to repoint the leases to the other pond which is annoying. SAR
4618 * Add this pond to the list (will need updating if we add the
4622 p
= &pond
->shared_network
->ipv6_pond
;
4623 for (; *p
; p
= &((*p
)->next
))
4625 ipv6_pond_reference(p
, pond
, MDL
);
4627 /* Don't allow a pool6 declaration with no addresses or
4628 prefixes, since it is probably a configuration error. */
4629 if (pond
->ipv6_pools
== NULL
) {
4630 parse_warn (cfile
, "Pool6 declaration with no %s.",
4631 "address range6 or prefix6");
4632 log_error ("Pool6 declarations must always contain at least");
4633 log_error ("one range6 or prefix6 statement.");
4637 ipv6_pond_dereference(&pond
, MDL
);
4644 /* allow-deny-keyword :== BOOTP
4647 | UNKNOWN_CLIENTS */
4649 int parse_allow_deny (oc
, cfile
, flag
)
4650 struct option_cache
**oc
;
4651 struct parse
*cfile
;
4654 enum dhcp_token token
;
4656 unsigned char rf
= flag
;
4658 struct option
*option
= NULL
;
4659 struct expression
*data
= (struct expression
*)0;
4662 if (!make_const_data (&data
, &rf
, 1, 0, 1, MDL
))
4665 token
= next_token (&val
, (unsigned *)0, cfile
);
4668 code
= SV_ALLOW_BOOTP
;
4672 code
= SV_ALLOW_BOOTING
;
4676 code
= SV_DYNAMIC_BOOTP
;
4679 case UNKNOWN_CLIENTS
:
4680 code
= SV_BOOT_UNKNOWN_CLIENTS
;
4684 code
= SV_DUPLICATES
;
4691 case CLIENT_UPDATES
:
4692 code
= SV_CLIENT_UPDATES
;
4696 code
= SV_LEASEQUERY
;
4700 parse_warn (cfile
, "expecting allow/deny key");
4701 skip_to_semi (cfile
);
4702 expression_dereference (&data
, MDL
);
4705 /* Reference on option is passed to option cache. */
4706 if (!option_code_hash_lookup(&option
, server_universe
.code_hash
,
4708 log_fatal("Unable to find server option %u (%s:%d).",
4710 status
= option_cache(oc
, NULL
, data
, option
, MDL
);
4711 expression_dereference (&data
, MDL
);
4717 parse_ia_na_declaration(struct parse
*cfile
) {
4718 #if !defined(DHCPv6)
4719 parse_warn(cfile
, "No DHCPv6 support.");
4720 skip_to_semi(cfile
);
4721 #else /* defined(DHCPv6) */
4722 enum dhcp_token token
;
4723 struct ia_xx
*ia
= NULL
;
4725 struct ia_xx
*old_ia
;
4728 binding_state_t state
;
4732 struct iasubopt
*iaaddr
;
4733 struct ipv6_pool
*pool
;
4734 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
4735 isc_boolean_t newbinding
;
4736 struct binding_scope
*scope
= NULL
;
4737 struct binding
*bnd
;
4738 struct binding_value
*nv
= NULL
;
4739 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
4742 if (local_family
!= AF_INET6
) {
4743 parse_warn(cfile
, "IA_NA is only supported in DHCPv6 mode.");
4744 skip_to_semi(cfile
);
4748 if (!parse_iaid_duid(cfile
, &ia
, &iaid
, MDL
)) {
4752 ia
->ia_type
= D6O_IA_NA
;
4754 token
= next_token(&val
, NULL
, cfile
);
4755 if (token
!= LBRACE
) {
4756 parse_warn(cfile
, "corrupt lease file; expecting left brace");
4757 skip_to_semi(cfile
);
4762 token
= next_token(&val
, NULL
, cfile
);
4763 if (token
== RBRACE
) break;
4765 if (token
== CLTT
) {
4766 ia
->cltt
= parse_date (cfile
);
4770 if (token
!= IAADDR
) {
4771 parse_warn(cfile
, "corrupt lease file; "
4772 "expecting IAADDR or right brace");
4773 skip_to_semi(cfile
);
4777 if (!parse_ip6_addr(cfile
, &iaddr
)) {
4778 parse_warn(cfile
, "corrupt lease file; "
4779 "expecting IPv6 address");
4780 skip_to_semi(cfile
);
4784 token
= next_token(&val
, NULL
, cfile
);
4785 if (token
!= LBRACE
) {
4786 parse_warn(cfile
, "corrupt lease file; "
4787 "expecting left brace");
4788 skip_to_semi(cfile
);
4796 token
= next_token(&val
, NULL
, cfile
);
4797 if (token
== RBRACE
) break;
4801 /* We hit the end of file and don't know
4802 * what parts of the lease we may be missing
4803 * don't try to salvage the lease
4805 parse_warn(cfile
, "corrupt lease file; "
4806 "unexpected end of file");
4809 /* Lease binding state. */
4811 token
= next_token(&val
, NULL
, cfile
);
4812 if (token
!= STATE
) {
4813 parse_warn(cfile
, "corrupt lease file; "
4815 skip_to_semi(cfile
);
4818 token
= next_token(&val
, NULL
, cfile
);
4820 case TOKEN_ABANDONED
:
4821 state
= FTS_ABANDONED
;
4830 state
= FTS_EXPIRED
;
4832 case TOKEN_RELEASED
:
4833 state
= FTS_RELEASED
;
4841 skip_to_semi(cfile
);
4845 token
= next_token(&val
, NULL
, cfile
);
4846 if (token
!= SEMI
) {
4847 parse_warn(cfile
, "corrupt lease file; "
4853 /* Lease preferred lifetime. */
4854 case PREFERRED_LIFE
:
4855 token
= next_token(&val
, NULL
, cfile
);
4856 if (token
!= NUMBER
) {
4857 parse_warn(cfile
, "%s is not a valid "
4860 skip_to_semi(cfile
);
4863 prefer
= atoi (val
);
4866 * Currently we peek for the semi-colon to
4867 * allow processing of older lease files that
4868 * don't have the semi-colon. Eventually we
4869 * should remove the peeking code.
4871 token
= peek_token(&val
, NULL
, cfile
);
4872 if (token
== SEMI
) {
4873 skip_token(&val
, NULL
, cfile
);
4876 "corrupt lease file; "
4877 "expecting semicolon.");
4881 /* Lease valid lifetime. */
4883 token
= next_token(&val
, NULL
, cfile
);
4884 if (token
!= NUMBER
) {
4885 parse_warn(cfile
, "%s is not a valid "
4888 skip_to_semi(cfile
);
4894 * Currently we peek for the semi-colon to
4895 * allow processing of older lease files that
4896 * don't have the semi-colon. Eventually we
4897 * should remove the peeking code.
4899 token
= peek_token(&val
, NULL
, cfile
);
4900 if (token
== SEMI
) {
4901 skip_token(&val
, NULL
, cfile
);
4904 "corrupt lease file; "
4905 "expecting semicolon.");
4909 /* Lease expiration time. */
4911 end_time
= parse_date(cfile
);
4914 /* Lease binding scopes. */
4916 token
= next_token(&val
, NULL
, cfile
);
4917 if ((token
!= NAME
) &&
4918 (token
!= NUMBER_OR_NAME
)) {
4919 parse_warn(cfile
, "%s is not a valid "
4922 skip_to_semi(cfile
);
4927 bnd
= find_binding(scope
, val
);
4929 if (!binding_scope_allocate(&scope
,
4931 log_fatal("Out of memory for "
4940 bnd
= dmalloc(sizeof(*bnd
),
4943 log_fatal("No memory for "
4947 bnd
->name
= dmalloc(strlen(val
) + 1,
4949 if (bnd
->name
== NULL
) {
4950 log_fatal("No memory for "
4953 strcpy(bnd
->name
, val
);
4955 newbinding
= ISC_TRUE
;
4957 newbinding
= ISC_FALSE
;
4960 if (!binding_value_allocate(&nv
, MDL
)) {
4961 log_fatal("no memory for binding "
4965 token
= next_token(NULL
, NULL
, cfile
);
4966 if (token
!= EQUAL
) {
4967 parse_warn(cfile
, "expecting '=' in "
4972 if (!parse_binding_value(cfile
, nv
)) {
4974 binding_value_dereference(&nv
, MDL
);
4975 binding_scope_dereference(&scope
, MDL
);
4980 binding_value_reference(&bnd
->value
,
4982 bnd
->next
= scope
->bindings
;
4983 scope
->bindings
= bnd
;
4985 binding_value_dereference(&bnd
->value
,
4987 binding_value_reference(&bnd
->value
,
4991 binding_value_dereference(&nv
, MDL
);
4998 * Depending on the user config we may
4999 * have one or two on statements. We
5000 * need to save information about both
5001 * of them until we allocate the
5002 * iasubopt to hold them.
5004 if (on_star
[0] == NULL
) {
5005 if (!parse_on_statement (&on_star
[0],
5012 skip_to_rbrace (cfile
, 1);
5016 if (!parse_on_statement (&on_star
[1],
5023 skip_to_rbrace (cfile
, 1);
5031 parse_warn(cfile
, "corrupt lease file; "
5032 "expecting ia_na contents, "
5034 skip_to_semi(cfile
);
5039 if (state
== FTS_LAST
+1) {
5040 parse_warn(cfile
, "corrupt lease file; "
5041 "missing state in iaaddr");
5044 if (end_time
== -1) {
5045 parse_warn(cfile
, "corrupt lease file; "
5046 "missing end time in iaaddr");
5051 if (iasubopt_allocate(&iaaddr
, MDL
) != ISC_R_SUCCESS
) {
5052 log_fatal("Out of memory.");
5054 memcpy(&iaaddr
->addr
, iaddr
.iabuf
, sizeof(iaaddr
->addr
));
5056 iaaddr
->state
= state
;
5057 iaaddr
->prefer
= prefer
;
5058 iaaddr
->valid
= valid
;
5059 if (iaaddr
->state
== FTS_RELEASED
)
5060 iaaddr
->hard_lifetime_end_time
= end_time
;
5062 if (scope
!= NULL
) {
5063 binding_scope_reference(&iaaddr
->scope
, scope
, MDL
);
5064 binding_scope_dereference(&scope
, MDL
);
5068 * Check on both on statements. Because of how we write the
5069 * lease file we know which is which if we have two but it's
5070 * easier to write the code to be independent. We do assume
5071 * that the statements won't overlap.
5074 (i
< 2) && on_star
[i
] != NULL
;
5076 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
5077 on_star
[i
]->data
.on
.statements
) {
5078 executable_statement_reference
5079 (&iaaddr
->on_star
.on_expiry
,
5080 on_star
[i
]->data
.on
.statements
, MDL
);
5082 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
5083 on_star
[i
]->data
.on
.statements
) {
5084 executable_statement_reference
5085 (&iaaddr
->on_star
.on_release
,
5086 on_star
[i
]->data
.on
.statements
, MDL
);
5088 executable_statement_dereference (&on_star
[i
], MDL
);
5091 /* find the pool this address is in */
5093 if (find_ipv6_pool(&pool
, D6O_IA_NA
,
5094 &iaaddr
->addr
) != ISC_R_SUCCESS
) {
5095 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5096 addr_buf
, sizeof(addr_buf
));
5097 log_error("No pool found for IA_NA address %s",
5099 iasubopt_dereference(&iaaddr
, MDL
);
5103 /* remove old information */
5104 if (cleanup_lease6(ia_na_active
, pool
,
5105 iaaddr
, ia
) != ISC_R_SUCCESS
) {
5106 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5107 addr_buf
, sizeof(addr_buf
));
5108 parse_warn(cfile
, "duplicate na lease for address %s",
5113 * if we like the lease we add it to our various structues
5114 * otherwise we leave it and it will get cleaned when we
5115 * do the iasubopt_dereference.
5117 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
5118 ia_add_iasubopt(ia
, iaaddr
, MDL
);
5119 ia_reference(&iaaddr
->ia
, ia
, MDL
);
5120 add_lease6(pool
, iaaddr
, end_time
);
5123 iasubopt_dereference(&iaaddr
, MDL
);
5124 ipv6_pool_dereference(&pool
, MDL
);
5128 * If we have an existing record for this IA_NA, remove it.
5131 if (ia_hash_lookup(&old_ia
, ia_na_active
,
5132 (unsigned char *)ia
->iaid_duid
.data
,
5133 ia
->iaid_duid
.len
, MDL
)) {
5134 ia_hash_delete(ia_na_active
,
5135 (unsigned char *)ia
->iaid_duid
.data
,
5136 ia
->iaid_duid
.len
, MDL
);
5137 ia_dereference(&old_ia
, MDL
);
5141 * If we have addresses, add this, otherwise don't bother.
5143 if (ia
->num_iasubopt
> 0) {
5144 ia_hash_add(ia_na_active
,
5145 (unsigned char *)ia
->iaid_duid
.data
,
5146 ia
->iaid_duid
.len
, ia
, MDL
);
5148 ia_dereference(&ia
, MDL
);
5149 #endif /* defined(DHCPv6) */
5153 parse_ia_ta_declaration(struct parse
*cfile
) {
5154 #if !defined(DHCPv6)
5155 parse_warn(cfile
, "No DHCPv6 support.");
5156 skip_to_semi(cfile
);
5157 #else /* defined(DHCPv6) */
5158 enum dhcp_token token
;
5159 struct ia_xx
*ia
= NULL
;
5161 struct ia_xx
*old_ia
;
5164 binding_state_t state
;
5168 struct iasubopt
*iaaddr
;
5169 struct ipv6_pool
*pool
;
5170 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5171 isc_boolean_t newbinding
;
5172 struct binding_scope
*scope
= NULL
;
5173 struct binding
*bnd
;
5174 struct binding_value
*nv
= NULL
;
5175 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
5178 if (local_family
!= AF_INET6
) {
5179 parse_warn(cfile
, "IA_TA is only supported in DHCPv6 mode.");
5180 skip_to_semi(cfile
);
5184 if (!parse_iaid_duid(cfile
, &ia
, &iaid
, MDL
)) {
5188 ia
->ia_type
= D6O_IA_TA
;
5190 token
= next_token(&val
, NULL
, cfile
);
5191 if (token
!= LBRACE
) {
5192 parse_warn(cfile
, "corrupt lease file; expecting left brace");
5193 skip_to_semi(cfile
);
5198 token
= next_token(&val
, NULL
, cfile
);
5199 if (token
== RBRACE
) break;
5201 if (token
== CLTT
) {
5202 ia
->cltt
= parse_date (cfile
);
5206 if (token
!= IAADDR
) {
5207 parse_warn(cfile
, "corrupt lease file; "
5208 "expecting IAADDR or right brace");
5209 skip_to_semi(cfile
);
5213 if (!parse_ip6_addr(cfile
, &iaddr
)) {
5214 parse_warn(cfile
, "corrupt lease file; "
5215 "expecting IPv6 address");
5216 skip_to_semi(cfile
);
5220 token
= next_token(&val
, NULL
, cfile
);
5221 if (token
!= LBRACE
) {
5222 parse_warn(cfile
, "corrupt lease file; "
5223 "expecting left brace");
5224 skip_to_semi(cfile
);
5232 token
= next_token(&val
, NULL
, cfile
);
5233 if (token
== RBRACE
) break;
5237 /* We hit the end of file and don't know
5238 * what parts of the lease we may be missing
5239 * don't try to salvage the lease
5241 parse_warn(cfile
, "corrupt lease file; "
5242 "unexpected end of file");
5245 /* Lease binding state. */
5247 token
= next_token(&val
, NULL
, cfile
);
5248 if (token
!= STATE
) {
5249 parse_warn(cfile
, "corrupt lease file; "
5251 skip_to_semi(cfile
);
5254 token
= next_token(&val
, NULL
, cfile
);
5256 case TOKEN_ABANDONED
:
5257 state
= FTS_ABANDONED
;
5266 state
= FTS_EXPIRED
;
5268 case TOKEN_RELEASED
:
5269 state
= FTS_RELEASED
;
5277 skip_to_semi(cfile
);
5281 token
= next_token(&val
, NULL
, cfile
);
5282 if (token
!= SEMI
) {
5283 parse_warn(cfile
, "corrupt lease file; "
5289 /* Lease preferred lifetime. */
5290 case PREFERRED_LIFE
:
5291 token
= next_token(&val
, NULL
, cfile
);
5292 if (token
!= NUMBER
) {
5293 parse_warn(cfile
, "%s is not a valid "
5296 skip_to_semi(cfile
);
5299 prefer
= atoi (val
);
5302 * Currently we peek for the semi-colon to
5303 * allow processing of older lease files that
5304 * don't have the semi-colon. Eventually we
5305 * should remove the peeking code.
5307 token
= peek_token(&val
, NULL
, cfile
);
5308 if (token
== SEMI
) {
5309 skip_token(&val
, NULL
, cfile
);
5312 "corrupt lease file; "
5313 "expecting semicolon.");
5317 /* Lease valid lifetime. */
5319 token
= next_token(&val
, NULL
, cfile
);
5320 if (token
!= NUMBER
) {
5321 parse_warn(cfile
, "%s is not a valid "
5324 skip_to_semi(cfile
);
5330 * Currently we peek for the semi-colon to
5331 * allow processing of older lease files that
5332 * don't have the semi-colon. Eventually we
5333 * should remove the peeking code.
5335 token
= peek_token(&val
, NULL
, cfile
);
5336 if (token
== SEMI
) {
5337 skip_token(&val
, NULL
, cfile
);
5340 "corrupt lease file; "
5341 "expecting semicolon.");
5345 /* Lease expiration time. */
5347 end_time
= parse_date(cfile
);
5350 /* Lease binding scopes. */
5352 token
= next_token(&val
, NULL
, cfile
);
5353 if ((token
!= NAME
) &&
5354 (token
!= NUMBER_OR_NAME
)) {
5355 parse_warn(cfile
, "%s is not a valid "
5358 skip_to_semi(cfile
);
5363 bnd
= find_binding(scope
, val
);
5365 if (!binding_scope_allocate(&scope
,
5367 log_fatal("Out of memory for "
5376 bnd
= dmalloc(sizeof(*bnd
),
5379 log_fatal("No memory for "
5383 bnd
->name
= dmalloc(strlen(val
) + 1,
5385 if (bnd
->name
== NULL
) {
5386 log_fatal("No memory for "
5389 strcpy(bnd
->name
, val
);
5391 newbinding
= ISC_TRUE
;
5393 newbinding
= ISC_FALSE
;
5396 if (!binding_value_allocate(&nv
, MDL
)) {
5397 log_fatal("no memory for binding "
5401 token
= next_token(NULL
, NULL
, cfile
);
5402 if (token
!= EQUAL
) {
5403 parse_warn(cfile
, "expecting '=' in "
5408 if (!parse_binding_value(cfile
, nv
)) {
5410 binding_value_dereference(&nv
, MDL
);
5411 binding_scope_dereference(&scope
, MDL
);
5416 binding_value_reference(&bnd
->value
,
5418 bnd
->next
= scope
->bindings
;
5419 scope
->bindings
= bnd
;
5421 binding_value_dereference(&bnd
->value
,
5423 binding_value_reference(&bnd
->value
,
5427 binding_value_dereference(&nv
, MDL
);
5434 * Depending on the user config we may
5435 * have one or two on statements. We
5436 * need to save information about both
5437 * of them until we allocate the
5438 * iasubopt to hold them.
5440 if (on_star
[0] == NULL
) {
5441 if (!parse_on_statement (&on_star
[0],
5448 skip_to_rbrace (cfile
, 1);
5452 if (!parse_on_statement (&on_star
[1],
5459 skip_to_rbrace (cfile
, 1);
5467 parse_warn(cfile
, "corrupt lease file; "
5468 "expecting ia_ta contents, "
5470 skip_to_semi(cfile
);
5475 if (state
== FTS_LAST
+1) {
5476 parse_warn(cfile
, "corrupt lease file; "
5477 "missing state in iaaddr");
5480 if (end_time
== -1) {
5481 parse_warn(cfile
, "corrupt lease file; "
5482 "missing end time in iaaddr");
5487 if (iasubopt_allocate(&iaaddr
, MDL
) != ISC_R_SUCCESS
) {
5488 log_fatal("Out of memory.");
5490 memcpy(&iaaddr
->addr
, iaddr
.iabuf
, sizeof(iaaddr
->addr
));
5492 iaaddr
->state
= state
;
5493 iaaddr
->prefer
= prefer
;
5494 iaaddr
->valid
= valid
;
5495 if (iaaddr
->state
== FTS_RELEASED
)
5496 iaaddr
->hard_lifetime_end_time
= end_time
;
5498 if (scope
!= NULL
) {
5499 binding_scope_reference(&iaaddr
->scope
, scope
, MDL
);
5500 binding_scope_dereference(&scope
, MDL
);
5504 * Check on both on statements. Because of how we write the
5505 * lease file we know which is which if we have two but it's
5506 * easier to write the code to be independent. We do assume
5507 * that the statements won't overlap.
5510 (i
< 2) && on_star
[i
] != NULL
;
5512 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
5513 on_star
[i
]->data
.on
.statements
) {
5514 executable_statement_reference
5515 (&iaaddr
->on_star
.on_expiry
,
5516 on_star
[i
]->data
.on
.statements
, MDL
);
5518 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
5519 on_star
[i
]->data
.on
.statements
) {
5520 executable_statement_reference
5521 (&iaaddr
->on_star
.on_release
,
5522 on_star
[i
]->data
.on
.statements
, MDL
);
5524 executable_statement_dereference (&on_star
[i
], MDL
);
5527 /* find the pool this address is in */
5529 if (find_ipv6_pool(&pool
, D6O_IA_TA
,
5530 &iaaddr
->addr
) != ISC_R_SUCCESS
) {
5531 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5532 addr_buf
, sizeof(addr_buf
));
5533 log_error("No pool found for IA_TA address %s",
5535 iasubopt_dereference(&iaaddr
, MDL
);
5539 /* remove old information */
5540 if (cleanup_lease6(ia_ta_active
, pool
,
5541 iaaddr
, ia
) != ISC_R_SUCCESS
) {
5542 inet_ntop(AF_INET6
, &iaaddr
->addr
,
5543 addr_buf
, sizeof(addr_buf
));
5544 parse_warn(cfile
, "duplicate ta lease for address %s",
5549 * if we like the lease we add it to our various structues
5550 * otherwise we leave it and it will get cleaned when we
5551 * do the iasubopt_dereference.
5553 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
5554 ia_add_iasubopt(ia
, iaaddr
, MDL
);
5555 ia_reference(&iaaddr
->ia
, ia
, MDL
);
5556 add_lease6(pool
, iaaddr
, end_time
);
5559 ipv6_pool_dereference(&pool
, MDL
);
5560 iasubopt_dereference(&iaaddr
, MDL
);
5564 * If we have an existing record for this IA_TA, remove it.
5567 if (ia_hash_lookup(&old_ia
, ia_ta_active
,
5568 (unsigned char *)ia
->iaid_duid
.data
,
5569 ia
->iaid_duid
.len
, MDL
)) {
5570 ia_hash_delete(ia_ta_active
,
5571 (unsigned char *)ia
->iaid_duid
.data
,
5572 ia
->iaid_duid
.len
, MDL
);
5573 ia_dereference(&old_ia
, MDL
);
5577 * If we have addresses, add this, otherwise don't bother.
5579 if (ia
->num_iasubopt
> 0) {
5580 ia_hash_add(ia_ta_active
,
5581 (unsigned char *)ia
->iaid_duid
.data
,
5582 ia
->iaid_duid
.len
, ia
, MDL
);
5584 ia_dereference(&ia
, MDL
);
5585 #endif /* defined(DHCPv6) */
5589 parse_ia_pd_declaration(struct parse
*cfile
) {
5590 #if !defined(DHCPv6)
5591 parse_warn(cfile
, "No DHCPv6 support.");
5592 skip_to_semi(cfile
);
5593 #else /* defined(DHCPv6) */
5594 enum dhcp_token token
;
5595 struct ia_xx
*ia
= NULL
;
5597 struct ia_xx
*old_ia
;
5601 binding_state_t state
;
5605 struct iasubopt
*iapref
;
5606 struct ipv6_pool
*pool
;
5607 char addr_buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
5608 isc_boolean_t newbinding
;
5609 struct binding_scope
*scope
= NULL
;
5610 struct binding
*bnd
;
5611 struct binding_value
*nv
= NULL
;
5612 struct executable_statement
*on_star
[2] = {NULL
, NULL
};
5615 if (local_family
!= AF_INET6
) {
5616 parse_warn(cfile
, "IA_PD is only supported in DHCPv6 mode.");
5617 skip_to_semi(cfile
);
5621 if (!parse_iaid_duid(cfile
, &ia
, &iaid
, MDL
)) {
5625 ia
->ia_type
= D6O_IA_PD
;
5627 token
= next_token(&val
, NULL
, cfile
);
5628 if (token
!= LBRACE
) {
5629 parse_warn(cfile
, "corrupt lease file; expecting left brace");
5630 skip_to_semi(cfile
);
5635 token
= next_token(&val
, NULL
, cfile
);
5636 if (token
== RBRACE
) break;
5638 if (token
== CLTT
) {
5639 ia
->cltt
= parse_date (cfile
);
5643 if (token
!= IAPREFIX
) {
5644 parse_warn(cfile
, "corrupt lease file; expecting "
5645 "IAPREFIX or right brace");
5646 skip_to_semi(cfile
);
5650 if (!parse_ip6_prefix(cfile
, &iaddr
, &plen
)) {
5651 parse_warn(cfile
, "corrupt lease file; "
5652 "expecting IPv6 prefix");
5653 skip_to_semi(cfile
);
5657 token
= next_token(&val
, NULL
, cfile
);
5658 if (token
!= LBRACE
) {
5659 parse_warn(cfile
, "corrupt lease file; "
5660 "expecting left brace");
5661 skip_to_semi(cfile
);
5669 token
= next_token(&val
, NULL
, cfile
);
5670 if (token
== RBRACE
) break;
5674 /* We hit the end of file and don't know
5675 * what parts of the lease we may be missing
5676 * don't try to salvage the lease
5678 parse_warn(cfile
, "corrupt lease file; "
5679 "unexpected end of file");
5682 /* Prefix binding state. */
5684 token
= next_token(&val
, NULL
, cfile
);
5685 if (token
!= STATE
) {
5686 parse_warn(cfile
, "corrupt lease file; "
5688 skip_to_semi(cfile
);
5691 token
= next_token(&val
, NULL
, cfile
);
5693 case TOKEN_ABANDONED
:
5694 state
= FTS_ABANDONED
;
5703 state
= FTS_EXPIRED
;
5705 case TOKEN_RELEASED
:
5706 state
= FTS_RELEASED
;
5714 skip_to_semi(cfile
);
5718 token
= next_token(&val
, NULL
, cfile
);
5719 if (token
!= SEMI
) {
5720 parse_warn(cfile
, "corrupt lease file; "
5726 /* Lease preferred lifetime. */
5727 case PREFERRED_LIFE
:
5728 token
= next_token(&val
, NULL
, cfile
);
5729 if (token
!= NUMBER
) {
5730 parse_warn(cfile
, "%s is not a valid "
5733 skip_to_semi(cfile
);
5736 prefer
= atoi (val
);
5739 * Currently we peek for the semi-colon to
5740 * allow processing of older lease files that
5741 * don't have the semi-colon. Eventually we
5742 * should remove the peeking code.
5744 token
= peek_token(&val
, NULL
, cfile
);
5745 if (token
== SEMI
) {
5746 skip_token(&val
, NULL
, cfile
);
5749 "corrupt lease file; "
5750 "expecting semicolon.");
5754 /* Lease valid lifetime. */
5756 token
= next_token(&val
, NULL
, cfile
);
5757 if (token
!= NUMBER
) {
5758 parse_warn(cfile
, "%s is not a valid "
5761 skip_to_semi(cfile
);
5767 * Currently we peek for the semi-colon to
5768 * allow processing of older lease files that
5769 * don't have the semi-colon. Eventually we
5770 * should remove the peeking code.
5772 token
= peek_token(&val
, NULL
, cfile
);
5773 if (token
== SEMI
) {
5774 skip_token(&val
, NULL
, cfile
);
5777 "corrupt lease file; "
5778 "expecting semicolon.");
5782 /* Prefix expiration time. */
5784 end_time
= parse_date(cfile
);
5787 /* Prefix binding scopes. */
5789 token
= next_token(&val
, NULL
, cfile
);
5790 if ((token
!= NAME
) &&
5791 (token
!= NUMBER_OR_NAME
)) {
5792 parse_warn(cfile
, "%s is not a valid "
5795 skip_to_semi(cfile
);
5800 bnd
= find_binding(scope
, val
);
5802 if (!binding_scope_allocate(&scope
,
5804 log_fatal("Out of memory for "
5813 bnd
= dmalloc(sizeof(*bnd
),
5816 log_fatal("No memory for "
5820 bnd
->name
= dmalloc(strlen(val
) + 1,
5822 if (bnd
->name
== NULL
) {
5823 log_fatal("No memory for "
5826 strcpy(bnd
->name
, val
);
5828 newbinding
= ISC_TRUE
;
5830 newbinding
= ISC_FALSE
;
5833 if (!binding_value_allocate(&nv
, MDL
)) {
5834 log_fatal("no memory for binding "
5838 token
= next_token(NULL
, NULL
, cfile
);
5839 if (token
!= EQUAL
) {
5840 parse_warn(cfile
, "expecting '=' in "
5845 if (!parse_binding_value(cfile
, nv
)) {
5847 binding_value_dereference(&nv
, MDL
);
5848 binding_scope_dereference(&scope
, MDL
);
5853 binding_value_reference(&bnd
->value
,
5855 bnd
->next
= scope
->bindings
;
5856 scope
->bindings
= bnd
;
5858 binding_value_dereference(&bnd
->value
,
5860 binding_value_reference(&bnd
->value
,
5864 binding_value_dereference(&nv
, MDL
);
5871 * Depending on the user config we may
5872 * have one or two on statements. We
5873 * need to save information about both
5874 * of them until we allocate the
5875 * iasubopt to hold them.
5877 if (on_star
[0] == NULL
) {
5878 if (!parse_on_statement (&on_star
[0],
5885 skip_to_rbrace (cfile
, 1);
5889 if (!parse_on_statement (&on_star
[1],
5896 skip_to_rbrace (cfile
, 1);
5904 parse_warn(cfile
, "corrupt lease file; "
5905 "expecting ia_pd contents, "
5907 skip_to_semi(cfile
);
5912 if (state
== FTS_LAST
+1) {
5913 parse_warn(cfile
, "corrupt lease file; "
5914 "missing state in iaprefix");
5917 if (end_time
== -1) {
5918 parse_warn(cfile
, "corrupt lease file; "
5919 "missing end time in iaprefix");
5924 if (iasubopt_allocate(&iapref
, MDL
) != ISC_R_SUCCESS
) {
5925 log_fatal("Out of memory.");
5927 memcpy(&iapref
->addr
, iaddr
.iabuf
, sizeof(iapref
->addr
));
5928 iapref
->plen
= plen
;
5929 iapref
->state
= state
;
5930 iapref
->prefer
= prefer
;
5931 iapref
->valid
= valid
;
5932 if (iapref
->state
== FTS_RELEASED
)
5933 iapref
->hard_lifetime_end_time
= end_time
;
5935 if (scope
!= NULL
) {
5936 binding_scope_reference(&iapref
->scope
, scope
, MDL
);
5937 binding_scope_dereference(&scope
, MDL
);
5941 * Check on both on statements. Because of how we write the
5942 * lease file we know which is which if we have two but it's
5943 * easier to write the code to be independent. We do assume
5944 * that the statements won't overlap.
5947 (i
< 2) && on_star
[i
] != NULL
;
5949 if ((on_star
[i
]->data
.on
.evtypes
& ON_EXPIRY
) &&
5950 on_star
[i
]->data
.on
.statements
) {
5951 executable_statement_reference
5952 (&iapref
->on_star
.on_expiry
,
5953 on_star
[i
]->data
.on
.statements
, MDL
);
5955 if ((on_star
[i
]->data
.on
.evtypes
& ON_RELEASE
) &&
5956 on_star
[i
]->data
.on
.statements
) {
5957 executable_statement_reference
5958 (&iapref
->on_star
.on_release
,
5959 on_star
[i
]->data
.on
.statements
, MDL
);
5961 executable_statement_dereference (&on_star
[i
], MDL
);
5964 /* find the pool this address is in */
5966 if (find_ipv6_pool(&pool
, D6O_IA_PD
,
5967 &iapref
->addr
) != ISC_R_SUCCESS
) {
5968 inet_ntop(AF_INET6
, &iapref
->addr
,
5969 addr_buf
, sizeof(addr_buf
));
5970 log_error("No pool found for prefix %s", addr_buf
);
5971 iasubopt_dereference(&iapref
, MDL
);
5975 /* remove old information */
5976 if (cleanup_lease6(ia_pd_active
, pool
,
5977 iapref
, ia
) != ISC_R_SUCCESS
) {
5978 inet_ntop(AF_INET6
, &iapref
->addr
,
5979 addr_buf
, sizeof(addr_buf
));
5980 parse_warn(cfile
, "duplicate pd lease for address %s",
5985 * if we like the lease we add it to our various structues
5986 * otherwise we leave it and it will get cleaned when we
5987 * do the iasubopt_dereference.
5989 if ((state
== FTS_ACTIVE
) || (state
== FTS_ABANDONED
)) {
5990 ia_add_iasubopt(ia
, iapref
, MDL
);
5991 ia_reference(&iapref
->ia
, ia
, MDL
);
5992 add_lease6(pool
, iapref
, end_time
);
5995 ipv6_pool_dereference(&pool
, MDL
);
5996 iasubopt_dereference(&iapref
, MDL
);
6000 * If we have an existing record for this IA_PD, remove it.
6003 if (ia_hash_lookup(&old_ia
, ia_pd_active
,
6004 (unsigned char *)ia
->iaid_duid
.data
,
6005 ia
->iaid_duid
.len
, MDL
)) {
6006 ia_hash_delete(ia_pd_active
,
6007 (unsigned char *)ia
->iaid_duid
.data
,
6008 ia
->iaid_duid
.len
, MDL
);
6009 ia_dereference(&old_ia
, MDL
);
6013 * If we have prefixes, add this, otherwise don't bother.
6015 if (ia
->num_iasubopt
> 0) {
6016 ia_hash_add(ia_pd_active
,
6017 (unsigned char *)ia
->iaid_duid
.data
,
6018 ia
->iaid_duid
.len
, ia
, MDL
);
6020 ia_dereference(&ia
, MDL
);
6021 #endif /* defined(DHCPv6) */
6026 * When we parse a server-duid statement in a lease file, we are
6027 * looking at the saved server DUID from a previous run. In this case
6028 * we expect it to be followed by the binary representation of the
6029 * DUID stored in a string:
6031 * server-duid "\000\001\000\001\015\221\034JRT\000\0224Y";
6033 * OR as a hex string of digits:
6035 * server-duid 00:01:00:01:1e:68:b3:db:0a:00:27:00:00:02;
6038 parse_server_duid(struct parse
*cfile
) {
6039 struct data_string duid
;
6040 unsigned char bytes
[128]; /* Maximum valid DUID is 128 */
6043 len
= parse_X(cfile
, bytes
, sizeof(bytes
));
6045 parse_warn(cfile
, "Invalid duid contents");
6046 skip_to_semi(cfile
);
6050 memset(&duid
, 0x0, sizeof(duid
));
6051 if (!buffer_allocate(&duid
.buffer
, len
, MDL
)) {
6052 log_fatal("parse_server_duid: out of memory");
6055 memcpy(duid
.buffer
->data
, bytes
, len
);
6057 duid
.data
= duid
.buffer
->data
;
6059 set_server_duid(&duid
);
6060 data_string_forget(&duid
, MDL
);
6066 * When we parse a server-duid statement in a config file, we will
6067 * have the type of the server DUID to generate, and possibly the
6068 * actual value defined.
6071 * server-duid llt ethernet|ieee802|fddi 213982198 00:16:6F:49:7D:9B;
6073 * server-duid ll ethernet|ieee802|fddi 00:16:6F:49:7D:9B;
6074 * server-duid en 2495 "enterprise-specific-identifier-1234";
6077 parse_server_duid_conf(struct parse
*cfile
) {
6078 enum dhcp_token token
;
6081 u_int32_t enterprise_number
;
6083 struct data_string ll_addr
;
6085 struct data_string duid
;
6089 * Consume the SERVER_DUID token.
6091 skip_token(NULL
, NULL
, cfile
);
6094 * Obtain the DUID type.
6096 token
= next_token(&val
, NULL
, cfile
);
6099 * Enterprise is the easiest - enterprise number and raw data
6104 * Get enterprise number and identifier.
6106 token
= next_token(&val
, NULL
, cfile
);
6107 if (token
!= NUMBER
) {
6108 parse_warn(cfile
, "enterprise number expected");
6109 skip_to_semi(cfile
);
6112 enterprise_number
= atoi(val
);
6114 token
= next_token(&val
, &len
, cfile
);
6115 if (token
!= STRING
) {
6116 parse_warn(cfile
, "identifier expected");
6117 skip_to_semi(cfile
);
6124 memset(&duid
, 0, sizeof(duid
));
6125 duid
.len
= 2 + 4 + len
;
6126 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6127 log_fatal("Out of memory storing DUID");
6129 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6130 putUShort(duid
.buffer
->data
, DUID_EN
);
6131 putULong(duid
.buffer
->data
+ 2, enterprise_number
);
6132 memcpy(duid
.buffer
->data
+ 6, val
, len
);
6134 set_server_duid(&duid
);
6135 data_string_forget(&duid
, MDL
);
6139 * Next easiest is the link-layer DUID. It consists only of
6140 * the LL directive, or optionally the specific value to use.
6142 * If we have LL only, then we set the type. If we have the
6143 * value, then we set the actual DUID.
6145 else if (token
== LL
) {
6146 if (peek_token(NULL
, NULL
, cfile
) == SEMI
) {
6147 set_server_duid_type(DUID_LL
);
6150 * Get our hardware type and address.
6152 token
= next_token(NULL
, NULL
, cfile
);
6155 ll_type
= HTYPE_ETHER
;
6158 ll_type
= HTYPE_IEEE802
;
6161 ll_type
= HTYPE_FDDI
;
6164 parse_warn(cfile
, "hardware type expected");
6165 skip_to_semi(cfile
);
6168 memset(&ll_addr
, 0, sizeof(ll_addr
));
6169 if (!parse_cshl(&ll_addr
, cfile
)) {
6176 memset(&duid
, 0, sizeof(duid
));
6177 duid
.len
= 2 + 2 + ll_addr
.len
;
6178 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6179 log_fatal("Out of memory storing DUID");
6181 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6182 putUShort(duid
.buffer
->data
, DUID_LL
);
6183 putUShort(duid
.buffer
->data
+ 2, ll_type
);
6184 memcpy(duid
.buffer
->data
+ 4,
6185 ll_addr
.data
, ll_addr
.len
);
6187 set_server_duid(&duid
);
6188 data_string_forget(&duid
, MDL
);
6189 data_string_forget(&ll_addr
, MDL
);
6194 * Finally the link-layer DUID plus time. It consists only of
6195 * the LLT directive, or optionally the specific value to use.
6197 * If we have LLT only, then we set the type. If we have the
6198 * value, then we set the actual DUID.
6200 else if (token
== LLT
) {
6201 if (peek_token(NULL
, NULL
, cfile
) == SEMI
) {
6202 set_server_duid_type(DUID_LLT
);
6205 * Get our hardware type, timestamp, and address.
6207 token
= next_token(NULL
, NULL
, cfile
);
6210 ll_type
= HTYPE_ETHER
;
6213 ll_type
= HTYPE_IEEE802
;
6216 ll_type
= HTYPE_FDDI
;
6219 parse_warn(cfile
, "hardware type expected");
6220 skip_to_semi(cfile
);
6224 token
= next_token(&val
, NULL
, cfile
);
6225 if (token
!= NUMBER
) {
6226 parse_warn(cfile
, "timestamp expected");
6227 skip_to_semi(cfile
);
6230 llt_time
= atoi(val
);
6232 memset(&ll_addr
, 0, sizeof(ll_addr
));
6233 if (!parse_cshl(&ll_addr
, cfile
)) {
6240 memset(&duid
, 0, sizeof(duid
));
6241 duid
.len
= 2 + 2 + 4 + ll_addr
.len
;
6242 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6243 log_fatal("Out of memory storing DUID");
6245 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6246 putUShort(duid
.buffer
->data
, DUID_LLT
);
6247 putUShort(duid
.buffer
->data
+ 2, ll_type
);
6248 putULong(duid
.buffer
->data
+ 4, llt_time
);
6249 memcpy(duid
.buffer
->data
+ 8,
6250 ll_addr
.data
, ll_addr
.len
);
6252 set_server_duid(&duid
);
6253 data_string_forget(&duid
, MDL
);
6254 data_string_forget(&ll_addr
, MDL
);
6259 * If users want they can use a number for DUID types.
6260 * This is useful for supporting future, not-yet-defined
6263 * In this case, they have to put in the complete value.
6265 * This also works for existing DUID types of course.
6267 else if (token
== NUMBER
) {
6268 duid_type_num
= atoi(val
);
6270 token
= next_token(&val
, &len
, cfile
);
6271 if (token
!= STRING
) {
6272 parse_warn(cfile
, "identifier expected");
6273 skip_to_semi(cfile
);
6280 memset(&duid
, 0, sizeof(duid
));
6282 if (!buffer_allocate(&duid
.buffer
, duid
.len
, MDL
)) {
6283 log_fatal("Out of memory storing DUID");
6285 duid
.data
= (unsigned char *)duid
.buffer
->data
;
6286 putUShort(duid
.buffer
->data
, duid_type_num
);
6287 memcpy(duid
.buffer
->data
+ 2, val
, len
);
6289 set_server_duid(&duid
);
6290 data_string_forget(&duid
, MDL
);
6294 * Anything else is an error.
6297 parse_warn(cfile
, "DUID type of LLT, EN, or LL expected");
6298 skip_to_semi(cfile
);
6303 * Finally consume our trailing semicolon.
6305 token
= next_token(NULL
, NULL
, cfile
);
6306 if (token
!= SEMI
) {
6307 parse_warn(cfile
, "semicolon expected");
6308 skip_to_semi(cfile
);
6313 * \brief Creates a byte-order corrected uint32 from a buffer
6315 * This function creates an integer value from a buffer, converting from
6316 * the byte order specified by authoring-byte-order to the current server's
6317 * byte order if they are different. The conversion works in either direction.
6319 * If the parameter, authoring-byte-order hasn't yet been encountered we will
6320 * emit a warning and then default the byte order to match the current server's
6321 * byte order (i.e. no conversion will done).
6323 * \param source buffer containing the "raw" four byte data
6324 * \return uint32_t containing the corrected value
6326 uint32_t parse_byte_order_uint32(const void *source
) {
6329 /* use memcpy to avoid any alignment monkey business */
6330 memcpy(&value
, source
, 4);
6332 if (authoring_byte_order
== 0) {
6333 log_error ("WARNING: "
6334 "authoring-byte-order not in the lease file.\n"
6335 "Assuming file byte order matches this server.\n");
6336 authoring_byte_order
= DHCP_BYTE_ORDER
;
6339 if (authoring_byte_order
!= DHCP_BYTE_ORDER
) {
6340 value
= (((value
>> 24) & 0xff) | // move byte 3 to byte 0
6341 ((value
<< 8) & 0xff0000) | // move byte 1 to byte 2
6342 ((value
>> 8) & 0xff00) | // move byte 2 to byte 1
6343 ((value
<< 24) & 0xff000000)); // byte 0 to byte 3
6349 /* !brief Parses an iaid/duid string into an iaid and struct ia
6351 * Given a string containing the iaid-duid value read from the file,
6352 * and using the format specified by input lease-id-format, convert
6353 * it into an IAID value and an ia_xx struct.
6355 * \param cfile - file being parsed
6356 * \param ia - pointer in which to store the allocated ia_xx struct
6357 * \param iaid - pointer in which to return the IAID value
6358 * \param file - source file name of invocation
6359 * \param line - line numbe of invocation
6361 * \return 0 if parsing fails, non-zero otherwise
6364 parse_iaid_duid(struct parse
* cfile
, struct ia_xx
** ia
, u_int32_t
*iaid
,
6365 const char* file
, int line
) {
6366 unsigned char bytes
[132]; /* Maximum valid IAID-DUID is 132 */
6370 log_error("parse_iaid_duid: ia ptr cannot be null");
6375 len
= parse_X(cfile
, bytes
, sizeof(bytes
));
6377 parse_warn(cfile
, "corrupt lease file; "
6378 "iaid+ia_xx string too short");
6379 skip_to_semi(cfile
);
6383 /* Extract the IAID from the front */
6384 *iaid
= parse_byte_order_uint32(bytes
);
6386 /* Instantiate the ia_xx */
6387 if (ia_allocate(ia
, *iaid
, (const char*)bytes
+ 4, len
- 4, file
, line
)
6389 log_fatal("parse_iaid_duid:Out of memory.");