3 Parser for dhcpd config file... */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1995-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id: confpars.c,v 1.10 2006/12/26 00:08:44 alc Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
42 static TIME parsed_time
;
45 trace_type_t
*trace_readconf_type
;
46 trace_type_t
*trace_readleases_type
;
48 void parse_trace_setup ()
50 trace_readconf_type
= trace_type_register ("readconf", (void *)0,
52 trace_conf_stop
, MDL
);
53 trace_readleases_type
= trace_type_register ("readleases", (void *)0,
55 trace_conf_stop
, MDL
);
59 /* conf-file :== parameters declarations END_OF_FILE
60 parameters :== <nil> | parameter | parameters parameter
61 declarations :== <nil> | declaration | declarations declaration */
63 isc_result_t
readconf ()
65 return read_conf_file (path_dhcpd_conf
, root_group
, ROOT_GROUP
, 0);
68 isc_result_t
read_conf_file (const char *filename
, struct group
*group
,
69 int group_type
, int leasep
)
83 ttype
= trace_readleases_type
;
85 ttype
= trace_readconf_type
;
87 /* If we're in playback, we need to snarf the contents of the
88 named file out of the playback file rather than trying to
90 if (trace_playback ()) {
93 status
= trace_get_file (ttype
, filename
, &tflen
, &dbuf
);
94 if (status
!= ISC_R_SUCCESS
)
98 /* What we get back is filename\0contents, where contents is
99 terminated just by the length. So we figure out the length
100 of the filename, and subtract that and the NUL from the
101 total length to get the length of the contents of the file.
102 We make fbuf a pointer to the contents of the file, and
103 leave dbuf as it is so we can free it later. */
104 tflen
= strlen (dbuf
);
105 ulen
= ulen
- tflen
- 1;
106 fbuf
= dbuf
+ tflen
+ 1;
111 if ((file
= open (filename
, O_RDONLY
)) < 0) {
113 log_error ("Can't open lease database %s: %m --",
115 log_error (" check for failed database %s!",
117 log_error ("Please read the dhcpd.leases manual%s",
119 log_fatal ("don't know what to do about this.");
121 log_fatal ("Can't open %s: %m", filename
);
125 cfile
= (struct parse
*)0;
126 #if defined (TRACING)
127 flen
= lseek (file
, (off_t
)0, SEEK_END
);
130 log_fatal ("Can't lseek on %s: %m", filename
);
132 if (lseek (file
, (off_t
)0, SEEK_SET
) < 0)
134 /* Can't handle files greater than 2^31-1. */
135 if (flen
> 0x7FFFFFFFUL
)
136 log_fatal ("%s: file is too long to buffer.", filename
);
139 /* Allocate a buffer that will be what's written to the tracefile,
140 and also will be what we parse from. */
141 tflen
= strlen (filename
);
142 dbuf
= dmalloc (ulen
+ tflen
+ 1, MDL
);
144 log_fatal ("No memory for %s (%d bytes)",
147 /* Copy the name into the beginning, nul-terminated. */
148 strcpy (dbuf
, filename
);
150 /* Load the file in after the NUL. */
151 fbuf
= dbuf
+ tflen
+ 1;
152 result
= read (file
, fbuf
, ulen
);
154 log_fatal ("Can't read in %s: %m", filename
);
156 log_fatal ("%s: short read of %d bytes instead of %d.",
157 filename
, ulen
, result
);
160 /* If we're recording, write out the filename and file contents. */
162 trace_write_packet (ttype
, ulen
+ tflen
+ 1, dbuf
, MDL
);
163 new_parse (&cfile
, -1, fbuf
, ulen
, filename
, 0); /* XXX */
165 new_parse (&cfile
, file
, (char *)0, 0, filename
, 0);
169 status
= lease_file_subparse (cfile
);
171 status
= conf_file_subparse (cfile
, group
, group_type
);
173 #if defined (TRACING)
179 #if defined (TRACING)
180 void trace_conf_input (trace_type_t
*ttype
, unsigned len
, char *data
)
185 struct parse
*cfile
= (struct parse
*)0;
186 static int postconf_initialized
;
187 static int leaseconf_initialized
;
189 /* Do what's done above, except that we don't have to read in the
190 data, because it's already been read for us. */
191 tflen
= strlen (data
);
192 flen
= len
- tflen
- 1;
193 fbuf
= data
+ tflen
+ 1;
195 /* If we're recording, write out the filename and file contents. */
197 trace_write_packet (ttype
, len
, data
, MDL
);
198 new_parse (&cfile
, -1, fbuf
, flen
, data
, 0);
199 if (ttype
== trace_readleases_type
)
200 lease_file_subparse (cfile
);
202 conf_file_subparse (cfile
, root_group
, ROOT_GROUP
);
205 /* Postconfiguration needs to be done after the config file
207 if (!postconf_initialized
&& ttype
== trace_readconf_type
) {
208 postconf_initialization (0);
209 postconf_initialized
= 1;
212 if (!leaseconf_initialized
&& ttype
== trace_readleases_type
) {
214 leaseconf_initialized
= 1;
219 void trace_conf_stop (trace_type_t
*ttype
) { }
222 /* conf-file :== parameters declarations END_OF_FILE
223 parameters :== <nil> | parameter | parameters parameter
224 declarations :== <nil> | declaration | declarations declaration */
226 isc_result_t
conf_file_subparse (struct parse
*cfile
, struct group
*group
,
230 enum dhcp_token token
;
235 token
= peek_token (&val
, (unsigned *)0, cfile
);
236 if (token
== END_OF_FILE
)
238 declaration
= parse_statement (cfile
, group
, group_type
,
239 (struct host_decl
*)0,
242 token
= next_token (&val
, (unsigned *)0, cfile
);
244 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
248 /* lease-file :== lease-declarations END_OF_FILE
249 lease-statments :== <nil>
251 | lease-declarations lease-declaration */
253 isc_result_t
lease_file_subparse (struct parse
*cfile
)
256 enum dhcp_token token
;
260 token
= next_token (&val
, (unsigned *)0, cfile
);
261 if (token
== END_OF_FILE
)
263 if (token
== LEASE
) {
264 struct lease
*lease
= (struct lease
*)0;
265 if (parse_lease_declaration (&lease
, cfile
)) {
267 lease_dereference (&lease
, MDL
);
270 "possibly corrupt lease file");
271 } else if (token
== HOST
) {
272 parse_host_declaration (cfile
, root_group
);
273 } else if (token
== GROUP
) {
274 parse_group_declaration (cfile
, root_group
);
275 #if defined (FAILOVER_PROTOCOL)
276 } else if (token
== FAILOVER
) {
277 parse_failover_state_declaration
278 (cfile
, (dhcp_failover_state_t
*)0);
281 log_error ("Corrupt lease file - possible data loss!");
282 skip_to_semi (cfile
);
287 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
291 /* statement :== parameter | declaration
293 parameter :== timestamp
294 | DEFAULT_LEASE_TIME lease_time
295 | MAX_LEASE_TIME lease_time
296 | DYNAMIC_BOOTP_LEASE_CUTOFF date
297 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
298 | BOOT_UNKNOWN_CLIENTS boolean
299 | ONE_LEASE_PER_CLIENT boolean
300 | GET_LEASE_HOSTNAMES boolean
301 | USE_HOST_DECL_NAME boolean
302 | NEXT_SERVER ip-addr-or-hostname SEMI
304 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
305 | FILENAME string-parameter
306 | SERVER_NAME string-parameter
308 | fixed-address-parameter
309 | ALLOW allow-deny-keyword
310 | DENY allow-deny-keyword
311 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
315 declaration :== host-declaration
317 | shared-network-declaration
319 | VENDOR_CLASS class-declaration
320 | USER_CLASS class-declaration
321 | RANGE address-range-declaration */
323 int parse_statement (cfile
, group
, type
, host_decl
, declaration
)
327 struct host_decl
*host_decl
;
330 enum dhcp_token token
;
332 struct shared_network
*share
;
334 struct hardware hardware
;
335 struct executable_statement
*et
, *ep
;
336 struct option
*option
;
337 struct option_cache
*cache
;
342 token
= peek_token (&val
, (unsigned *)0, cfile
);
346 next_token (&val
, (unsigned *)0, cfile
);
347 token
= next_token (&val
, (unsigned *)0, cfile
);
348 if (token
!= STRING
) {
349 parse_warn (cfile
, "filename string expected.");
350 skip_to_semi (cfile
);
352 status
= read_conf_file (val
, group
, type
, 0);
353 if (status
!= ISC_R_SUCCESS
)
354 parse_warn (cfile
, "%s: bad parse.", val
);
360 next_token (&val
, (unsigned *)0, cfile
);
361 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
362 parse_host_declaration (cfile
, group
);
365 "host declarations not allowed here.");
366 skip_to_semi (cfile
);
371 next_token (&val
, (unsigned *)0, cfile
);
372 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
373 parse_group_declaration (cfile
, group
);
376 "group declarations not allowed here.");
377 skip_to_semi (cfile
);
382 next_token (&val
, (unsigned *)0, cfile
);
383 parsed_time
= parse_timestamp (cfile
);
387 next_token (&val
, (unsigned *)0, cfile
);
388 if (type
== SHARED_NET_DECL
||
390 type
== SUBNET_DECL
||
391 type
== CLASS_DECL
) {
392 parse_warn (cfile
, "shared-network parameters not %s.",
394 skip_to_semi (cfile
);
398 parse_shared_net_declaration (cfile
, group
);
402 next_token (&val
, (unsigned *)0, cfile
);
403 if (type
== HOST_DECL
|| type
== SUBNET_DECL
||
404 type
== CLASS_DECL
) {
406 "subnet declarations not allowed here.");
407 skip_to_semi (cfile
);
411 /* If we're in a subnet declaration, just do the parse. */
412 if (group
-> shared_network
) {
413 parse_subnet_declaration (cfile
,
414 group
-> shared_network
);
418 /* Otherwise, cons up a fake shared network structure
419 and populate it with the lone subnet... */
421 share
= (struct shared_network
*)0;
422 status
= shared_network_allocate (&share
, MDL
);
423 if (status
!= ISC_R_SUCCESS
)
424 log_fatal ("Can't allocate shared subnet: %s",
425 isc_result_totext (status
));
426 if (!clone_group (&share
-> group
, group
, MDL
))
427 log_fatal ("Can't allocate group for shared net");
428 shared_network_reference (&share
-> group
-> shared_network
,
431 parse_subnet_declaration (cfile
, share
);
433 /* share -> subnets is the subnet we just parsed. */
434 if (share
-> subnets
) {
435 interface_reference (&share
-> interface
,
436 share
-> subnets
-> interface
,
439 /* Make the shared network name from network number. */
440 n
= piaddrmask (share
-> subnets
-> net
,
441 share
-> subnets
-> netmask
, MDL
);
444 /* Copy the authoritative parameter from the subnet,
445 since there is no opportunity to declare it here. */
446 share
-> group
-> authoritative
=
447 share
-> subnets
-> group
-> authoritative
;
448 enter_shared_network (share
);
450 shared_network_dereference (&share
, MDL
);
454 next_token (&val
, (unsigned *)0, cfile
);
455 if (type
== CLASS_DECL
) {
457 "class declarations not allowed here.");
458 skip_to_semi (cfile
);
461 parse_class_declaration ((struct class **)0, cfile
, group
, 0);
465 next_token (&val
, (unsigned *)0, cfile
);
466 if (type
== CLASS_DECL
) {
468 "class declarations not allowed here.");
469 skip_to_semi (cfile
);
472 parse_class_declaration ((struct class **)0, cfile
, group
, 1);
476 next_token (&val
, (unsigned *)0, cfile
);
477 if (type
== CLASS_DECL
) {
479 "class declarations not allowed here.");
480 skip_to_semi (cfile
);
483 parse_class_declaration ((struct class **)0, cfile
, group
, 2);
487 next_token (&val
, (unsigned *)0, cfile
);
488 if (type
== CLASS_DECL
) {
490 "class declarations not allowed here.");
491 skip_to_semi (cfile
);
494 parse_class_declaration ((struct class **)0, cfile
, group
, 3);
498 next_token (&val
, (unsigned *)0, cfile
);
499 memset (&hardware
, 0, sizeof hardware
);
500 parse_hardware_param (cfile
, &hardware
);
502 host_decl
-> interface
= hardware
;
504 parse_warn (cfile
, "hardware address parameter %s",
505 "not allowed here.");
509 next_token (&val
, (unsigned *)0, cfile
);
510 cache
= (struct option_cache
*)0;
511 if (parse_fixed_addr_param (&cache
, cfile
)) {
513 if (host_decl
-> fixed_addr
) {
514 option_cache_dereference (&cache
, MDL
);
516 "Only one fixed address%s",
517 " declaration per host.");
519 host_decl
-> fixed_addr
= cache
;
523 "fixed-address parameter not %s",
525 option_cache_dereference (&cache
, MDL
);
531 next_token (&val
, (unsigned *)0, cfile
);
532 if (type
!= SUBNET_DECL
&& type
!= SHARED_NET_DECL
) {
533 parse_warn (cfile
, "pool declared outside of network");
535 if (type
== POOL_DECL
) {
536 parse_warn (cfile
, "pool declared within pool.");
538 parse_pool_statement (cfile
, group
, type
);
542 next_token (&val
, (unsigned *)0, cfile
);
543 if (type
!= SUBNET_DECL
|| !group
-> subnet
) {
545 "range declaration not allowed here.");
546 skip_to_semi (cfile
);
549 parse_address_range (cfile
, group
, type
, (struct pool
*)0,
554 token
= next_token (&val
, (unsigned *)0, cfile
);
555 token
= next_token (&val
, (unsigned *)0, cfile
);
558 group
-> authoritative
= 0;
561 parse_warn (cfile
, "expecting assertion");
562 skip_to_semi (cfile
);
567 token
= next_token (&val
, (unsigned *)0, cfile
);
568 group
-> authoritative
= 1;
570 if (type
== HOST_DECL
)
571 parse_warn (cfile
, "authority makes no sense here.");
575 /* "server-identifier" is a special hack, equivalent to
576 "option dhcp-server-identifier". */
577 case SERVER_IDENTIFIER
:
578 option
= dhcp_universe
.options
[DHO_DHCP_SERVER_IDENTIFIER
];
579 token
= next_token (&val
, (unsigned *)0, cfile
);
583 token
= next_token (&val
, (unsigned *)0, cfile
);
584 token
= peek_token (&val
, (unsigned *)0, cfile
);
585 if (token
== SPACE
) {
586 if (type
!= ROOT_GROUP
) {
588 "option space definitions %s",
589 "may not be scoped.");
590 skip_to_semi (cfile
);
593 parse_option_space_decl (cfile
);
598 option
= parse_option_name (cfile
, 1, &known
);
600 token
= peek_token (&val
, (unsigned *)0, cfile
);
602 if (type
!= ROOT_GROUP
) {
604 "option definitions%s",
605 " may not be scoped.");
606 skip_to_semi (cfile
);
607 free_option (option
, MDL
);
610 next_token (&val
, (unsigned *)0, cfile
);
611 if (!parse_option_code_definition (cfile
,
613 free_option (option
, MDL
);
617 /* If this wasn't an option code definition, don't
618 allow an unknown option. */
620 parse_warn (cfile
, "unknown option %s.%s",
621 option
-> universe
-> name
,
623 skip_to_semi (cfile
);
624 free_option (option
, MDL
);
629 et
= (struct executable_statement
*)0;
630 if (!parse_option_statement
631 (&et
, cfile
, 1, option
,
632 supersede_option_statement
))
634 goto insert_statement
;
641 if (type
!= ROOT_GROUP
&& type
!= SHARED_NET_DECL
) {
642 parse_warn (cfile
, "failover peers may only be %s",
643 "defined in shared-network");
644 log_error ("declarations and the outer scope.");
645 skip_to_semi (cfile
);
648 token
= next_token (&val
, (unsigned *)0, cfile
);
649 #if defined (FAILOVER_PROTOCOL)
650 parse_failover_peer (cfile
, group
, type
);
652 parse_warn (cfile
, "No failover support.");
653 skip_to_semi (cfile
);
658 et
= (struct executable_statement
*)0;
660 if (!parse_executable_statement (&et
, cfile
, &lose
,
665 "expecting a declaration");
668 "expecting a parameter %s",
670 skip_to_semi (cfile
);
677 if (group
-> statements
) {
680 /* If this set of statements is only referenced
681 by this group, just add the current statement
682 to the end of the chain. */
683 for (ep
= group
-> statements
; ep
-> next
;
685 if (ep
-> refcnt
> 1) /* XXX */
688 executable_statement_reference (&ep
-> next
,
690 executable_statement_dereference (&et
, MDL
);
694 /* Otherwise, make a parent chain, and put the
695 current group statements first and the new
696 statement in the next pointer. */
697 ep
= (struct executable_statement
*)0;
698 if (!executable_statement_allocate (&ep
, MDL
))
699 log_fatal ("No memory for statements.");
700 ep
-> op
= statements_statement
;
701 executable_statement_reference (&ep
-> data
.statements
,
704 executable_statement_reference (&ep
-> next
, et
, MDL
);
705 executable_statement_dereference (&group
-> statements
,
707 executable_statement_reference (&group
-> statements
,
709 executable_statement_dereference (&ep
, MDL
);
711 executable_statement_reference (&group
-> statements
,
714 executable_statement_dereference (&et
, MDL
);
721 #if defined (FAILOVER_PROTOCOL)
722 void parse_failover_peer (cfile
, group
, type
)
727 enum dhcp_token token
;
729 dhcp_failover_state_t
*peer
;
734 unsigned hba_len
= sizeof hba
;
736 struct expression
*expr
;
738 dhcp_failover_config_t
*cp
;
740 token
= next_token (&val
, (unsigned *)0, cfile
);
742 parse_warn (cfile
, "expecting \"peer\"");
743 skip_to_semi (cfile
);
747 token
= next_token (&val
, (unsigned *)0, cfile
);
748 if (is_identifier (token
) || token
== STRING
) {
749 name
= dmalloc (strlen (val
) + 1, MDL
);
751 log_fatal ("no memory for peer name %s", name
);
754 parse_warn (cfile
, "expecting failover peer name.");
755 skip_to_semi (cfile
);
759 /* See if there's a peer declaration by this name. */
760 peer
= (dhcp_failover_state_t
*)0;
761 find_failover_peer (&peer
, name
, MDL
);
763 token
= next_token (&val
, (unsigned *)0, cfile
);
766 if (type
!= SHARED_NET_DECL
)
767 parse_warn (cfile
, "failover peer reference not %s",
768 "in shared-network declaration");
771 parse_warn (cfile
, "reference to unknown%s%s",
772 " failover peer ", name
);
775 dhcp_failover_state_reference
776 (&group
-> shared_network
-> failover_peer
,
779 dhcp_failover_state_dereference (&peer
, MDL
);
781 } else if (token
== STATE
) {
783 parse_warn (cfile
, "state declaration for unknown%s%s",
784 " failover peer ", name
);
787 parse_failover_state_declaration (cfile
, peer
);
788 dhcp_failover_state_dereference (&peer
, MDL
);
790 } else if (token
!= LBRACE
) {
791 parse_warn (cfile
, "expecting left brace");
792 skip_to_semi (cfile
);
795 /* Make sure this isn't a redeclaration. */
797 parse_warn (cfile
, "redeclaration of failover peer %s", name
);
798 skip_to_rbrace (cfile
, 1);
799 dhcp_failover_state_dereference (&peer
, MDL
);
803 status
= dhcp_failover_state_allocate (&peer
, MDL
);
804 if (status
!= ISC_R_SUCCESS
)
805 log_fatal ("Can't allocate failover peer %s: %s",
806 name
, isc_result_totext (status
));
814 token
= next_token (&val
, (unsigned *)0, cfile
);
820 peer
-> i_am
= primary
;
824 peer
-> i_am
= secondary
;
827 "secondary may not define %s",
828 "load balance settings.");
832 cp
= &peer
-> partner
;
836 expr
= (struct expression
*)0;
837 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
838 skip_to_rbrace (cfile
, 1);
839 dhcp_failover_state_dereference (&peer
, MDL
);
842 option_cache (&cp
-> address
,
843 (struct data_string
*)0, expr
,
844 (struct option
*)0, MDL
);
845 expression_dereference (&expr
, MDL
);
849 token
= next_token (&val
, (unsigned *)0, cfile
);
850 if (token
!= NUMBER
) {
851 parse_warn (cfile
, "expecting number");
852 skip_to_rbrace (cfile
, 1);
854 cp
-> port
= atoi (val
);
857 case MAX_RESPONSE_DELAY
:
858 tp
= &cp
-> max_response_delay
;
860 token
= next_token (&val
, (unsigned *)0, cfile
);
861 if (token
!= NUMBER
) {
862 parse_warn (cfile
, "expecting number.");
863 skip_to_rbrace (cfile
, 1);
864 dhcp_failover_state_dereference (&peer
, MDL
);
870 case MAX_UNACKED_UPDATES
:
871 tp
= &cp
-> max_flying_updates
;
880 if (peer
-> i_am
== secondary
)
882 "secondary may not define %s",
883 "load balance settings.");
884 if (!parse_numeric_aggregate (cfile
, hba
, &hba_len
,
886 skip_to_rbrace (cfile
, 1);
887 dhcp_failover_state_dereference (&peer
, MDL
);
892 "HBA must be exactly 32 bytes.");
897 peer
-> hba
= dmalloc (32, MDL
);
899 dfree (peer
-> name
, MDL
);
901 log_fatal ("parse failover peer: no memory");
903 memcpy (peer
-> hba
, hba
, 32);
908 token
= next_token (&val
, (unsigned *)0, cfile
);
909 if (peer
-> i_am
== secondary
)
911 "secondary may not define %s",
912 "load balance settings.");
913 if (token
!= NUMBER
) {
914 parse_warn (cfile
, "expecting number");
915 skip_to_rbrace (cfile
, 1);
916 dhcp_failover_state_dereference (&peer
, MDL
);
921 parse_warn (cfile
, "split must be < 256");
923 memset (hba
, 0, sizeof hba
);
924 for (i
= 0; i
< split
; i
++) {
926 hba
[i
/ 8] |= (1 << (i
& 7));
933 token
= next_token (&val
, (unsigned *)0, cfile
);
934 if (token
!= BALANCE
) {
935 parse_warn (cfile
, "expecting 'balance'");
937 skip_to_rbrace (cfile
, 1);
940 token
= next_token (&val
, (unsigned *)0, cfile
);
941 if (token
!= TOKEN_MAX
) {
942 parse_warn (cfile
, "expecting 'max'");
945 token
= next_token (&val
, (unsigned *)0, cfile
);
946 if (token
!= SECONDS
) {
947 parse_warn (cfile
, "expecting 'secs'");
950 token
= next_token (&val
, (unsigned *)0, cfile
);
951 if (token
!= NUMBER
) {
952 parse_warn (cfile
, "expecting number");
955 peer
-> load_balance_max_secs
= atoi (val
);
960 "invalid statement in peer declaration");
961 skip_to_rbrace (cfile
, 1);
962 dhcp_failover_state_dereference (&peer
, MDL
);
965 if (token
!= RBRACE
&& !parse_semi (cfile
)) {
966 skip_to_rbrace (cfile
, 1);
967 dhcp_failover_state_dereference (&peer
, MDL
);
970 } while (token
!= RBRACE
);
972 /* me.address can be null; the failover link initiate code tries to
973 * derive a reasonable address to use.
975 if (!peer
-> partner
.address
)
976 parse_warn (cfile
, "peer address may not be omitted");
978 /* XXX - when/if we get a port number assigned, just set as default */
979 if (!peer
-> me
.port
)
980 parse_warn (cfile
, "local port may not be omitted");
981 if (!peer
-> partner
.port
)
982 parse_warn (cfile
, "peer port may not be omitted");
984 if (peer
-> i_am
== primary
) {
987 "primary failover server must have hba or split.");
988 } else if (!peer
-> mclt
) {
990 "primary failover server must have mclt.");
993 if (!peer
-> me
.max_flying_updates
) {
994 peer
-> me
.max_flying_updates
= 100;
996 if (!peer
-> me
.max_response_delay
) {
997 peer
-> me
.max_response_delay
= 60;
1000 if (type
== SHARED_NET_DECL
) {
1001 group
-> shared_network
-> failover_peer
= peer
;
1004 /* Set the initial state. */
1005 if (peer
-> i_am
== primary
) {
1006 peer
-> me
.state
= recover
;
1007 peer
-> me
.stos
= cur_time
;
1008 peer
-> partner
.state
= unknown_state
;
1009 peer
-> partner
.stos
= cur_time
;
1011 peer
-> me
.state
= recover
;
1012 peer
-> me
.stos
= cur_time
;
1013 peer
-> partner
.state
= unknown_state
;
1014 peer
-> partner
.stos
= cur_time
;
1017 status
= enter_failover_peer (peer
);
1018 if (status
!= ISC_R_SUCCESS
)
1019 parse_warn (cfile
, "failover peer %s: %s",
1020 peer
-> name
, isc_result_totext (status
));
1021 dhcp_failover_state_dereference (&peer
, MDL
);
1024 void parse_failover_state_declaration (struct parse
*cfile
,
1025 dhcp_failover_state_t
*peer
)
1027 enum dhcp_token token
;
1030 dhcp_failover_state_t
*state
;
1031 dhcp_failover_config_t
*cp
;
1034 token
= next_token (&val
, (unsigned *)0, cfile
);
1035 if (token
!= PEER
) {
1036 parse_warn (cfile
, "expecting \"peer\"");
1037 skip_to_semi (cfile
);
1041 token
= next_token (&val
, (unsigned *)0, cfile
);
1042 if (is_identifier (token
) || token
== STRING
) {
1043 name
= dmalloc (strlen (val
) + 1, MDL
);
1045 log_fatal ("failover peer name %s: no memory",
1049 parse_warn (cfile
, "expecting failover peer name.");
1050 skip_to_semi (cfile
);
1054 /* See if there's a peer declaration by this name. */
1055 state
= (dhcp_failover_state_t
*)0;
1056 find_failover_peer (&state
, name
, MDL
);
1058 parse_warn (cfile
, "unknown failover peer: %s", name
);
1059 skip_to_semi (cfile
);
1063 token
= next_token (&val
, (unsigned *)0, cfile
);
1064 if (token
!= STATE
) {
1065 parse_warn (cfile
, "expecting 'state'");
1067 skip_to_semi (cfile
);
1071 state
= (dhcp_failover_state_t
*)0;
1072 dhcp_failover_state_reference (&state
, peer
, MDL
);
1074 token
= next_token (&val
, (unsigned *)0, cfile
);
1075 if (token
!= LBRACE
) {
1076 parse_warn (cfile
, "expecting left brace");
1078 skip_to_semi (cfile
);
1079 dhcp_failover_state_dereference (&state
, MDL
);
1083 token
= next_token (&val
, (unsigned *)0, cfile
);
1090 token
= next_token (&val
, (unsigned *)0, cfile
);
1091 if (token
!= STATE
) {
1092 parse_warn (cfile
, "expecting 'state'");
1095 parse_failover_state (cfile
,
1096 &cp
-> state
, &cp
-> stos
);
1100 cp
= &state
-> partner
;
1104 if (state
-> i_am
== primary
) {
1106 "mclt not valid for primary");
1109 token
= next_token (&val
, (unsigned *)0, cfile
);
1110 if (token
!= NUMBER
) {
1111 parse_warn (cfile
, "expecting a number.");
1114 state
-> mclt
= atoi (val
);
1119 parse_warn (cfile
, "expecting state setting.");
1121 skip_to_rbrace (cfile
, 1);
1122 dhcp_failover_state_dereference (&state
, MDL
);
1125 } while (token
!= RBRACE
);
1126 dhcp_failover_state_dereference (&state
, MDL
);
1129 void parse_failover_state (cfile
, state
, stos
)
1130 struct parse
*cfile
;
1131 enum failover_state
*state
;
1134 enum dhcp_token token
;
1136 enum failover_state state_in
;
1139 token
= next_token (&val
, (unsigned *)0, cfile
);
1142 state_in
= unknown_state
;
1146 state_in
= partner_down
;
1153 case COMMUNICATIONS_INTERRUPTED
:
1154 state_in
= communications_interrupted
;
1157 case RESOLUTION_INTERRUPTED
:
1158 state_in
= resolution_interrupted
;
1161 case POTENTIAL_CONFLICT
:
1162 state_in
= potential_conflict
;
1170 state_in
= recover_wait
;
1174 state_in
= recover_done
;
1178 state_in
= shut_down
;
1190 parse_warn (cfile
, "unknown failover state");
1191 skip_to_semi (cfile
);
1195 token
= next_token (&val
, (unsigned *)0, cfile
);
1196 if (token
== SEMI
) {
1200 parse_warn (cfile
, "expecting \"at\"");
1201 skip_to_semi (cfile
);
1205 stos_in
= parse_date (cfile
);
1210 /* Now that we've apparently gotten a clean parse, we
1211 can trust that this is a state that was fully committed to
1212 disk, so we can install it. */
1216 #endif /* defined (FAILOVER_PROTOCOL) */
1218 /* Permit_list_match returns 1 if every element of the permit list in lhs
1219 also appears in rhs. Note that this doesn't by itself mean that the
1220 two lists are equal - to check for equality, permit_list_match has to
1221 return 1 with (list1, list2) and with (list2, list1). */
1223 int permit_list_match (struct permit
*lhs
, struct permit
*rhs
)
1225 struct permit
*plp
, *prp
;
1232 for (plp
= lhs
; plp
; plp
= plp
-> next
) {
1234 for (prp
= rhs
; prp
; prp
= prp
-> next
) {
1235 if (prp
-> type
== plp
-> type
&&
1236 (prp
-> type
!= permit_class
||
1237 prp
-> class == plp
-> class)) {
1248 void parse_pool_statement (cfile
, group
, type
)
1249 struct parse
*cfile
;
1250 struct group
*group
;
1253 enum dhcp_token token
;
1256 struct pool
*pool
, **p
, *pp
;
1257 struct permit
*permit
;
1258 struct permit
**permit_head
;
1259 int declaration
= 0;
1260 isc_result_t status
;
1261 struct lease
*lpchain
= (struct lease
*)0, *lp
;
1263 pool
= (struct pool
*)0;
1264 status
= pool_allocate (&pool
, MDL
);
1265 if (status
!= ISC_R_SUCCESS
)
1266 log_fatal ("no memory for pool: %s",
1267 isc_result_totext (status
));
1269 if (type
== SUBNET_DECL
)
1270 shared_network_reference (&pool
-> shared_network
,
1271 group
-> subnet
-> shared_network
,
1274 shared_network_reference (&pool
-> shared_network
,
1275 group
-> shared_network
, MDL
);
1277 if (!clone_group (&pool
-> group
, pool
-> shared_network
-> group
, MDL
))
1278 log_fatal ("can't clone pool group.");
1280 #if defined (FAILOVER_PROTOCOL)
1281 /* Inherit the failover peer from the shared network. */
1282 if (pool
-> shared_network
-> failover_peer
)
1283 dhcp_failover_state_reference
1284 (&pool
-> failover_peer
,
1285 pool
-> shared_network
-> failover_peer
, MDL
);
1288 if (!parse_lbrace (cfile
)) {
1289 pool_dereference (&pool
, MDL
);
1294 token
= peek_token (&val
, (unsigned *)0, cfile
);
1297 next_token (&val
, (unsigned *)0, cfile
);
1298 token
= next_token (&val
, (unsigned *)0, cfile
);
1299 if (token
!= FAILOVER
||
1300 (token
= next_token (&val
, (unsigned *)0,
1303 "expecting \"failover peer\".");
1304 skip_to_semi (cfile
);
1307 #if defined (FAILOVER_PROTOCOL)
1308 if (pool
-> failover_peer
)
1309 dhcp_failover_state_dereference
1310 (&pool
-> failover_peer
, MDL
);
1314 #if defined (FAILOVER_PROTOCOL)
1316 next_token (&val
, (unsigned *)0, cfile
);
1317 token
= next_token (&val
, (unsigned *)0, cfile
);
1318 if (token
!= PEER
) {
1319 parse_warn (cfile
, "expecting 'peer'.");
1320 skip_to_semi (cfile
);
1323 token
= next_token (&val
, (unsigned *)0, cfile
);
1324 if (token
!= STRING
) {
1325 parse_warn (cfile
, "expecting string.");
1326 skip_to_semi (cfile
);
1329 if (pool
-> failover_peer
)
1330 dhcp_failover_state_dereference
1331 (&pool
-> failover_peer
, MDL
);
1332 status
= find_failover_peer (&pool
-> failover_peer
,
1334 if (status
!= ISC_R_SUCCESS
)
1336 "failover peer %s: %s", val
,
1337 isc_result_totext (status
));
1339 pool
-> failover_peer
-> pool_count
++;
1345 next_token (&val
, (unsigned *)0, cfile
);
1346 parse_address_range (cfile
, group
, type
,
1350 permit_head
= &pool
-> permit_list
;
1352 permit
= new_permit (MDL
);
1354 log_fatal ("no memory for permit");
1355 next_token (&val
, (unsigned *)0, cfile
);
1356 token
= next_token (&val
, (unsigned *)0, cfile
);
1359 permit
-> type
= permit_unknown_clients
;
1361 if (next_token (&val
, (unsigned *)0,
1362 cfile
) != CLIENTS
) {
1364 "expecting \"clients\"");
1365 skip_to_semi (cfile
);
1366 free_permit (permit
, MDL
);
1372 permit
-> type
= permit_known_clients
;
1375 case UNKNOWN_CLIENTS
:
1376 permit
-> type
= permit_unknown_clients
;
1380 permit
-> type
= permit_known_clients
;
1384 permit
-> type
= permit_authenticated_clients
;
1387 case UNAUTHENTICATED
:
1389 permit_unauthenticated_clients
;
1393 permit
-> type
= permit_all_clients
;
1398 permit
-> type
= permit_dynamic_bootp_clients
;
1399 if (next_token (&val
, (unsigned *)0,
1400 cfile
) != TOKEN_BOOTP
) {
1402 "expecting \"bootp\"");
1403 skip_to_semi (cfile
);
1404 free_permit (permit
, MDL
);
1410 if (next_token (&val
, (unsigned *)0,
1412 parse_warn (cfile
, "expecting \"of\"");
1413 skip_to_semi (cfile
);
1414 free_permit (permit
, MDL
);
1417 if (next_token (&val
, (unsigned *)0,
1420 "expecting class name.");
1421 skip_to_semi (cfile
);
1422 free_permit (permit
, MDL
);
1425 permit
-> type
= permit_class
;
1426 permit
-> class = (struct class *)0;
1427 find_class (&permit
-> class, val
, MDL
);
1428 if (!permit
-> class)
1430 "no such class: %s", val
);
1434 parse_warn (cfile
, "expecting permit type.");
1435 skip_to_semi (cfile
);
1438 while (*permit_head
)
1439 permit_head
= &((*permit_head
) -> next
);
1440 *permit_head
= permit
;
1445 permit_head
= &pool
-> prohibit_list
;
1449 next_token (&val
, (unsigned *)0, cfile
);
1454 declaration
= parse_statement (cfile
, pool
-> group
,
1456 (struct host_decl
*)0,
1462 #if defined (FAILOVER_PROTOCOL)
1463 /* We can't do failover on a pool that supports dynamic bootp,
1464 because BOOTP doesn't support leases, and failover absolutely
1465 depends on lease timing. */
1466 if (pool
-> failover_peer
) {
1467 /* This search order matches the search orders later in
1468 * execution - deny first, if not denied, check permit
1469 * list. A dynamic bootp client may be known or unknown,
1470 * it may belong to a member of a class, but it definitely
1471 * will not be authenticated since that requires DHCP
1472 * to work. So a dynamic bootp client is definitely not
1473 * an authenticated client, and we can't say for sure about
1476 * So we nag the user.
1478 for (permit
= pool
-> prohibit_list
; permit
;
1479 permit
= permit
-> next
) {
1480 if (permit
-> type
== permit_dynamic_bootp_clients
||
1481 permit
-> type
== permit_unauthenticated_clients
||
1482 permit
-> type
== permit_all_clients
)
1486 permit
= pool
-> permit_list
;
1490 permit_authenticated_clients
) {
1492 "pools with failover peers %s",
1493 "may not permit dynamic bootp.");
1494 log_error ("Either write a \"%s\" %s",
1496 "statement and use disjoint");
1497 log_error ("pools, or%s (%s) %s",
1498 " don't permit dynamic bootp",
1499 "\"deny dynamic bootp clients;\"",
1501 log_error ("This is a protocol,%s %s",
1502 " limitation, not an ISC DHCP",
1504 log_error ("please don't request an %s",
1505 "enhancement or ask why this is.");
1510 permit
= permit
-> next
;
1514 #endif /* FAILOVER_PROTOCOL */
1516 /* See if there's already a pool into which we can merge this one. */
1517 for (pp
= pool
-> shared_network
-> pools
; pp
; pp
= pp
-> next
) {
1519 if (pp
-> group
-> statements
!= pool
-> group
-> statements
)
1521 #if defined (FAILOVER_PROTOCOL)
1522 if (pool
-> failover_peer
!= pp
-> failover_peer
)
1525 if (!permit_list_match (pp
-> permit_list
,
1526 pool
-> permit_list
) ||
1527 !permit_list_match (pool
-> permit_list
,
1528 pp
-> permit_list
) ||
1529 !permit_list_match (pp
-> prohibit_list
,
1530 pool
-> prohibit_list
) ||
1531 !permit_list_match (pool
-> prohibit_list
,
1532 pp
-> prohibit_list
))
1535 /* Okay, we can merge these two pools. All we have to
1536 do is fix up the leases, which all point to their pool. */
1537 for (lp
= lpchain
; lp
; lp
= lp
-> next
) {
1538 pool_dereference (&lp
-> pool
, MDL
);
1539 pool_reference (&lp
-> pool
, pp
, MDL
);
1544 /* If we didn't succeed in merging this pool into another, put
1547 p
= &pool
-> shared_network
-> pools
;
1548 for (; *p
; p
= &((*p
) -> next
))
1550 pool_reference (p
, pool
, MDL
);
1553 /* Don't allow a pool declaration with no addresses, since it is
1554 probably a configuration error. */
1556 parse_warn (cfile
, "Pool declaration with no address range.");
1557 log_error ("Pool declarations must always contain at least");
1558 log_error ("one range statement.");
1561 /* Dereference the lease chain. */
1562 lp
= (struct lease
*)0;
1564 lease_reference (&lp
, lpchain
, MDL
);
1565 lease_dereference (&lpchain
, MDL
);
1567 lease_reference (&lpchain
, lp
-> next
, MDL
);
1568 lease_dereference (&lp
-> next
, MDL
);
1569 lease_dereference (&lp
, MDL
);
1572 pool_dereference (&pool
, MDL
);
1575 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1577 int parse_boolean (cfile
)
1578 struct parse
*cfile
;
1580 enum dhcp_token token
;
1584 token
= next_token (&val
, (unsigned *)0, cfile
);
1585 if (!strcasecmp (val
, "true")
1586 || !strcasecmp (val
, "on"))
1588 else if (!strcasecmp (val
, "false")
1589 || !strcasecmp (val
, "off"))
1593 "boolean value (true/false/on/off) expected");
1594 skip_to_semi (cfile
);
1601 /* Expect a left brace; if there isn't one, skip over the rest of the
1602 statement and return zero; otherwise, return 1. */
1604 int parse_lbrace (cfile
)
1605 struct parse
*cfile
;
1607 enum dhcp_token token
;
1610 token
= next_token (&val
, (unsigned *)0, cfile
);
1611 if (token
!= LBRACE
) {
1612 parse_warn (cfile
, "expecting left brace.");
1613 skip_to_semi (cfile
);
1620 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1622 void parse_host_declaration (cfile
, group
)
1623 struct parse
*cfile
;
1624 struct group
*group
;
1627 enum dhcp_token token
;
1628 struct host_decl
*host
;
1630 int declaration
= 0;
1633 isc_result_t status
;
1635 name
= parse_host_name (cfile
);
1637 parse_warn (cfile
, "expecting a name for host declaration.");
1638 skip_to_semi (cfile
);
1642 host
= (struct host_decl
*)0;
1643 status
= host_allocate (&host
, MDL
);
1644 if (status
!= ISC_R_SUCCESS
)
1645 log_fatal ("can't allocate host decl struct %s: %s",
1646 name
, isc_result_totext (status
));
1647 host
-> name
= name
;
1648 if (!clone_group (&host
-> group
, group
, MDL
)) {
1649 log_fatal ("can't clone group for host %s", name
);
1651 host_dereference (&host
, MDL
);
1655 if (!parse_lbrace (cfile
))
1659 token
= peek_token (&val
, (unsigned *)0, cfile
);
1660 if (token
== RBRACE
) {
1661 token
= next_token (&val
, (unsigned *)0, cfile
);
1664 if (token
== END_OF_FILE
) {
1665 token
= next_token (&val
, (unsigned *)0, cfile
);
1666 parse_warn (cfile
, "unexpected end of file");
1669 /* If the host declaration was created by the server,
1670 remember to save it. */
1671 if (token
== DYNAMIC
) {
1673 token
= next_token (&val
, (unsigned *)0, cfile
);
1674 if (!parse_semi (cfile
))
1678 /* If the host declaration was created by the server,
1679 remember to save it. */
1680 if (token
== TOKEN_DELETED
) {
1682 token
= next_token (&val
, (unsigned *)0, cfile
);
1683 if (!parse_semi (cfile
))
1688 if (token
== GROUP
) {
1689 struct group_object
*go
;
1690 token
= next_token (&val
, (unsigned *)0, cfile
);
1691 token
= next_token (&val
, (unsigned *)0, cfile
);
1692 if (token
!= STRING
&& !is_identifier (token
)) {
1694 "expecting string or identifier.");
1695 skip_to_rbrace (cfile
, 1);
1698 go
= (struct group_object
*)0;
1699 if (!group_hash_lookup (&go
, group_name_hash
,
1700 val
, strlen (val
), MDL
)) {
1701 parse_warn (cfile
, "unknown group %s in host %s",
1704 if (host
-> named_group
)
1705 group_object_dereference
1706 (&host
-> named_group
, MDL
);
1707 group_object_reference (&host
-> named_group
,
1709 group_object_dereference (&go
, MDL
);
1711 if (!parse_semi (cfile
))
1718 unsigned char *t
= 0;
1721 token
= next_token (&val
, (unsigned *)0, cfile
);
1722 data_string_forget (&host
-> client_identifier
, MDL
);
1724 /* See if it's a string or a cshl. */
1725 token
= peek_token (&val
, (unsigned *)0, cfile
);
1726 if (token
== STRING
) {
1727 token
= next_token (&val
, &len
, cfile
);
1729 host
-> client_identifier
.terminated
= 1;
1732 t
= parse_numeric_aggregate
1734 (unsigned char *)0, &len
, ':', 16, 8);
1737 "expecting hex list.");
1738 skip_to_semi (cfile
);
1740 s
= (const char *)t
;
1742 if (!buffer_allocate
1743 (&host
-> client_identifier
.buffer
,
1744 len
+ host
-> client_identifier
.terminated
, MDL
))
1745 log_fatal ("no memory for uid for host %s.",
1747 host
-> client_identifier
.data
=
1748 host
-> client_identifier
.buffer
-> data
;
1749 host
-> client_identifier
.len
= len
;
1750 memcpy (host
-> client_identifier
.buffer
-> data
, s
,
1751 len
+ host
-> client_identifier
.terminated
);
1755 if (!parse_semi (cfile
))
1759 declaration
= parse_statement (cfile
, host
-> group
,
1765 struct host_decl
*hp
= (struct host_decl
*)0;
1766 if (host_hash_lookup (&hp
, host_name_hash
,
1767 (unsigned char *)host
-> name
,
1768 strlen (host
-> name
), MDL
)) {
1769 delete_host (hp
, 0);
1770 host_dereference (&hp
, MDL
);
1773 if (host
-> named_group
&& host
-> named_group
-> group
) {
1774 if (host
-> group
-> statements
||
1775 (host
-> group
-> authoritative
!=
1776 host
-> named_group
-> group
-> authoritative
)) {
1777 if (host
-> group
-> next
)
1778 group_dereference (&host
-> group
-> next
,
1780 group_reference (&host
-> group
-> next
,
1781 host
-> named_group
-> group
,
1784 group_dereference (&host
-> group
, MDL
);
1785 group_reference (&host
-> group
,
1786 host
-> named_group
-> group
,
1792 host
-> flags
|= HOST_DECL_DYNAMIC
;
1794 host
-> flags
|= HOST_DECL_STATIC
;
1796 status
= enter_host (host
, dynamicp
, 0);
1797 if (status
!= ISC_R_SUCCESS
)
1798 parse_warn (cfile
, "host %s: %s", host
-> name
,
1799 isc_result_totext (status
));
1801 host_dereference (&host
, MDL
);
1804 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
1807 int parse_class_declaration (cp
, cfile
, group
, type
)
1809 struct parse
*cfile
;
1810 struct group
*group
;
1814 enum dhcp_token token
;
1815 struct class *class = (struct class *)0, *pc
= (struct class *)0;
1816 int declaration
= 0;
1818 struct data_string data
;
1821 struct executable_statement
*stmt
= (struct executable_statement
*)0;
1822 struct expression
*expr
;
1824 isc_result_t status
= ISC_R_FAILURE
;
1826 token
= next_token (&val
, (unsigned *)0, cfile
);
1827 if (token
!= STRING
) {
1828 parse_warn (cfile
, "Expecting class name");
1829 skip_to_semi (cfile
);
1833 /* See if there's already a class with the specified name. */
1834 find_class (&pc
, val
, MDL
);
1836 /* If this isn't a subclass, we're updating an existing class. */
1837 if (pc
&& type
!= 0 && type
!= 1 && type
!= 3) {
1838 class_reference (&class, pc
, MDL
);
1840 class_dereference (&pc
, MDL
);
1843 /* If this _is_ a subclass, there _must_ be a class with the
1845 if (!pc
&& (type
== 0 || type
== 1 || type
== 3)) {
1846 parse_warn (cfile
, "no class named %s", val
);
1847 skip_to_semi (cfile
);
1851 /* The old vendor-class and user-class declarations had an implicit
1852 match. We don't do the implicit match anymore. Instead, for
1853 backward compatibility, we have an implicit-vendor-class and an
1854 implicit-user-class. vendor-class and user-class declarations
1855 are turned into subclasses of the implicit classes, and the
1856 submatch expression of the implicit classes extracts the contents of
1857 the vendor class or user class. */
1858 if (type
== 0 || type
== 1) {
1859 data
.len
= strlen (val
);
1860 data
.buffer
= (struct buffer
*)0;
1861 if (!buffer_allocate (&data
.buffer
, data
.len
+ 1, MDL
))
1862 log_fatal ("no memory for class name.");
1863 data
.data
= &data
.buffer
-> data
[0];
1864 data
.terminated
= 1;
1866 tname
= type
? "implicit-vendor-class" : "implicit-user-class";
1867 } else if (type
== 2) {
1870 tname
= (const char *)0;
1874 name
= dmalloc (strlen (tname
) + 1, MDL
);
1876 log_fatal ("No memory for class name %s.", tname
);
1881 /* If this is a straight subclass, parse the hash string. */
1883 token
= peek_token (&val
, (unsigned *)0, cfile
);
1884 if (token
== STRING
) {
1885 token
= next_token (&val
, &data
.len
, cfile
);
1886 data
.buffer
= (struct buffer
*)0;
1887 if (!buffer_allocate (&data
.buffer
,
1888 data
.len
+ 1, MDL
)) {
1890 class_dereference (&pc
, MDL
);
1894 data
.terminated
= 1;
1895 data
.data
= &data
.buffer
-> data
[0];
1896 memcpy ((char *)data
.buffer
-> data
, val
,
1898 } else if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
1899 memset (&data
, 0, sizeof data
);
1900 if (!parse_cshl (&data
, cfile
)) {
1901 class_dereference (&pc
, MDL
);
1905 parse_warn (cfile
, "Expecting string or hex list.");
1907 class_dereference (&pc
, MDL
);
1912 /* See if there's already a class in the hash table matching the
1914 if (type
== 0 || type
== 1 || type
== 3)
1915 class_hash_lookup (&class, pc
-> hash
,
1916 (const char *)data
.data
, data
.len
, MDL
);
1918 /* If we didn't find an existing class, allocate a new one. */
1920 /* Allocate the class structure... */
1921 status
= class_allocate (&class, MDL
);
1923 group_reference (&class -> group
, pc
-> group
, MDL
);
1924 class_reference (&class -> superclass
, pc
, MDL
);
1925 class -> lease_limit
= pc
-> lease_limit
;
1926 if (class -> lease_limit
) {
1927 class -> billed_leases
=
1928 dmalloc (class -> lease_limit
*
1929 sizeof (struct lease
*), MDL
);
1930 if (!class -> billed_leases
)
1931 log_fatal ("no memory for billing");
1932 memset (class -> billed_leases
, 0,
1933 (class -> lease_limit
*
1934 sizeof class -> billed_leases
));
1936 data_string_copy (&class -> hash_string
, &data
, MDL
);
1938 !class_new_hash (&pc
-> hash
, 0, MDL
))
1939 log_fatal ("No memory for subclass hash.");
1940 class_hash_add (pc
-> hash
,
1941 (const char *)class -> hash_string
.data
,
1942 class -> hash_string
.len
,
1943 (void *)class, MDL
);
1945 if (!clone_group (&class -> group
, group
, MDL
))
1946 log_fatal ("no memory to clone class group.");
1949 /* If this is an implicit vendor or user class, add a
1950 statement that causes the vendor or user class ID to
1951 be sent back in the reply. */
1952 if (type
== 0 || type
== 1) {
1953 stmt
= (struct executable_statement
*)0;
1954 if (!executable_statement_allocate (&stmt
, MDL
))
1955 log_fatal ("no memory for class statement.");
1956 stmt
-> op
= supersede_option_statement
;
1957 if (option_cache_allocate (&stmt
-> data
.option
,
1959 stmt
-> data
.option
-> data
= data
;
1960 stmt
-> data
.option
-> option
=
1961 dhcp_universe
.options
1963 ? DHO_VENDOR_CLASS_IDENTIFIER
1966 class -> statements
= stmt
;
1969 /* Save the name, if there is one. */
1970 class -> name
= name
;
1973 if (type
== 0 || type
== 1 || type
== 3)
1974 data_string_forget (&data
, MDL
);
1976 /* Spawned classes don't have to have their own settings. */
1977 if (class -> superclass
) {
1978 token
= peek_token (&val
, (unsigned *)0, cfile
);
1979 if (token
== SEMI
) {
1980 next_token (&val
, (unsigned *)0, cfile
);
1982 status
= class_reference (cp
, class, MDL
);
1983 class_dereference (&class, MDL
);
1985 class_dereference (&pc
, MDL
);
1986 return cp
? (status
== ISC_R_SUCCESS
) : 1;
1988 /* Give the subclass its own group. */
1989 if (!clone_group (&class -> group
, class -> group
, MDL
))
1990 log_fatal ("can't clone class group.");
1994 if (!parse_lbrace (cfile
)) {
1995 class_dereference (&class, MDL
);
1997 class_dereference (&pc
, MDL
);
2002 token
= peek_token (&val
, (unsigned *)0, cfile
);
2003 if (token
== RBRACE
) {
2004 token
= next_token (&val
, (unsigned *)0, cfile
);
2006 } else if (token
== END_OF_FILE
) {
2007 token
= next_token (&val
, (unsigned *)0, cfile
);
2008 parse_warn (cfile
, "unexpected end of file");
2010 } else if (token
== MATCH
) {
2013 "invalid match in subclass.");
2014 skip_to_semi (cfile
);
2017 token
= next_token (&val
, (unsigned *)0, cfile
);
2018 token
= peek_token (&val
, (unsigned *)0, cfile
);
2021 if (class -> expr
) {
2022 parse_warn (cfile
, "can't override match.");
2023 skip_to_semi (cfile
);
2026 token
= next_token (&val
, (unsigned *)0, cfile
);
2027 if (!parse_boolean_expression (&class -> expr
, cfile
,
2031 "expecting boolean expr.");
2032 skip_to_semi (cfile
);
2035 #if defined (DEBUG_EXPRESSION_PARSE)
2036 print_expression ("class match",
2041 } else if (token
== SPAWN
) {
2044 "invalid spawn in subclass.");
2045 skip_to_semi (cfile
);
2048 token
= next_token (&val
, (unsigned *)0, cfile
);
2049 class -> spawning
= 1;
2050 token
= next_token (&val
, (unsigned *)0, cfile
);
2051 if (token
!= WITH
) {
2053 "expecting with after spawn");
2054 skip_to_semi (cfile
);
2058 if (class -> submatch
) {
2060 "can't override existing %s.",
2062 skip_to_semi (cfile
);
2065 if (!parse_data_expression (&class -> submatch
,
2069 "expecting data expr.");
2070 skip_to_semi (cfile
);
2073 #if defined (DEBUG_EXPRESSION_PARSE)
2074 print_expression ("class submatch",
2079 } else if (token
== LEASE
) {
2080 next_token (&val
, (unsigned *)0, cfile
);
2081 token
= next_token (&val
, (unsigned *)0, cfile
);
2082 if (token
!= LIMIT
) {
2083 parse_warn (cfile
, "expecting \"limit\"");
2085 skip_to_semi (cfile
);
2088 token
= next_token (&val
, (unsigned *)0, cfile
);
2089 if (token
!= NUMBER
) {
2090 parse_warn (cfile
, "expecting a number");
2092 skip_to_semi (cfile
);
2095 class -> lease_limit
= atoi (val
);
2096 class -> billed_leases
=
2097 dmalloc (class -> lease_limit
*
2098 sizeof (struct lease
*), MDL
);
2099 if (!class -> billed_leases
)
2100 log_fatal ("no memory for billed leases.");
2101 memset (class -> billed_leases
, 0,
2102 (class -> lease_limit
*
2103 sizeof class -> billed_leases
));
2104 have_billing_classes
= 1;
2107 declaration
= parse_statement (cfile
, class -> group
,
2109 (struct host_decl
*)0,
2113 if (type
== 2 && new) {
2114 if (!collections
-> classes
)
2115 class_reference (&collections
-> classes
, class, MDL
);
2118 for (c
= collections
-> classes
;
2119 c
-> nic
; c
= c
-> nic
)
2121 class_reference (&c
-> nic
, class, MDL
);
2125 status
= class_reference (cp
, class, MDL
);
2126 class_dereference (&class, MDL
);
2128 class_dereference (&pc
, MDL
);
2129 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2132 /* shared-network-declaration :==
2133 hostname LBRACE declarations parameters RBRACE */
2135 void parse_shared_net_declaration (cfile
, group
)
2136 struct parse
*cfile
;
2137 struct group
*group
;
2140 enum dhcp_token token
;
2141 struct shared_network
*share
;
2143 int declaration
= 0;
2144 isc_result_t status
;
2146 share
= (struct shared_network
*)0;
2147 status
= shared_network_allocate (&share
, MDL
);
2148 if (status
!= ISC_R_SUCCESS
)
2149 log_fatal ("Can't allocate shared subnet: %s",
2150 isc_result_totext (status
));
2151 clone_group (&share
-> group
, group
, MDL
);
2152 shared_network_reference (&share
-> group
-> shared_network
,
2155 /* Get the name of the shared network... */
2156 token
= peek_token (&val
, (unsigned *)0, cfile
);
2157 if (token
== STRING
) {
2158 token
= next_token (&val
, (unsigned *)0, cfile
);
2161 parse_warn (cfile
, "zero-length shared network name");
2162 val
= "<no-name-given>";
2164 name
= dmalloc (strlen (val
) + 1, MDL
);
2166 log_fatal ("no memory for shared network name");
2169 name
= parse_host_name (cfile
);
2172 "expecting a name for shared-network");
2173 skip_to_semi (cfile
);
2174 shared_network_dereference (&share
, MDL
);
2178 share
-> name
= name
;
2180 if (!parse_lbrace (cfile
)) {
2181 shared_network_dereference (&share
, MDL
);
2186 token
= peek_token (&val
, (unsigned *)0, cfile
);
2187 if (token
== RBRACE
) {
2188 token
= next_token (&val
, (unsigned *)0, cfile
);
2189 if (!share
-> subnets
)
2191 "empty shared-network decl");
2193 enter_shared_network (share
);
2194 shared_network_dereference (&share
, MDL
);
2196 } else if (token
== END_OF_FILE
) {
2197 token
= next_token (&val
, (unsigned *)0, cfile
);
2198 parse_warn (cfile
, "unexpected end of file");
2200 } else if (token
== INTERFACE
) {
2201 token
= next_token (&val
, (unsigned *)0, cfile
);
2202 token
= next_token (&val
, (unsigned *)0, cfile
);
2203 new_shared_network_interface (cfile
, share
, val
);
2204 if (!parse_semi (cfile
))
2209 declaration
= parse_statement (cfile
, share
-> group
,
2211 (struct host_decl
*)0,
2214 shared_network_dereference (&share
, MDL
);
2217 /* subnet-declaration :==
2218 net NETMASK netmask RBRACE parameters declarations LBRACE */
2220 void parse_subnet_declaration (cfile
, share
)
2221 struct parse
*cfile
;
2222 struct shared_network
*share
;
2225 enum dhcp_token token
;
2226 struct subnet
*subnet
, *t
, *u
;
2228 unsigned char addr
[4];
2229 unsigned len
= sizeof addr
;
2230 int declaration
= 0;
2231 isc_result_t status
;
2233 subnet
= (struct subnet
*)0;
2234 status
= subnet_allocate (&subnet
, MDL
);
2235 if (status
!= ISC_R_SUCCESS
)
2236 log_fatal ("Allocation of new subnet failed: %s",
2237 isc_result_totext (status
));
2238 shared_network_reference (&subnet
-> shared_network
, share
, MDL
);
2239 if (!clone_group (&subnet
-> group
, share
-> group
, MDL
))
2240 log_fatal ("allocation of group for new subnet failed.");
2241 subnet_reference (&subnet
-> group
-> subnet
, subnet
, MDL
);
2243 /* Get the network number... */
2244 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2245 subnet_dereference (&subnet
, MDL
);
2248 memcpy (iaddr
.iabuf
, addr
, len
);
2250 subnet
-> net
= iaddr
;
2252 token
= next_token (&val
, (unsigned *)0, cfile
);
2253 if (token
!= NETMASK
) {
2254 parse_warn (cfile
, "Expecting netmask");
2255 skip_to_semi (cfile
);
2259 /* Get the netmask... */
2260 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2261 subnet_dereference (&subnet
, MDL
);
2264 memcpy (iaddr
.iabuf
, addr
, len
);
2266 subnet
-> netmask
= iaddr
;
2268 /* Validate the network number/netmask pair. */
2269 if (host_addr (subnet
-> net
, subnet
-> netmask
)) {
2272 maskstr
= strdup (piaddr (subnet
-> netmask
));
2274 "subnet %s netmask %s: bad subnet number/mask combination.",
2275 piaddr (subnet
-> net
), maskstr
);
2277 subnet_dereference (&subnet
, MDL
);
2278 skip_to_semi (cfile
);
2282 enter_subnet (subnet
);
2284 if (!parse_lbrace (cfile
)) {
2285 subnet_dereference (&subnet
, MDL
);
2290 token
= peek_token (&val
, (unsigned *)0, cfile
);
2291 if (token
== RBRACE
) {
2292 token
= next_token (&val
, (unsigned *)0, cfile
);
2294 } else if (token
== END_OF_FILE
) {
2295 token
= next_token (&val
, (unsigned *)0, cfile
);
2296 parse_warn (cfile
, "unexpected end of file");
2298 } else if (token
== INTERFACE
) {
2299 token
= next_token (&val
, (unsigned *)0, cfile
);
2300 token
= next_token (&val
, (unsigned *)0, cfile
);
2301 new_shared_network_interface (cfile
, share
, val
);
2302 if (!parse_semi (cfile
))
2306 declaration
= parse_statement (cfile
, subnet
-> group
,
2308 (struct host_decl
*)0,
2312 /* Add the subnet to the list of subnets in this shared net. */
2313 if (!share
-> subnets
)
2314 subnet_reference (&share
-> subnets
, subnet
, MDL
);
2316 u
= (struct subnet
*)0;
2317 for (t
= share
-> subnets
;
2318 t
-> next_sibling
; t
= t
-> next_sibling
) {
2319 if (subnet_inner_than (subnet
, t
, 0)) {
2320 subnet_reference (&subnet
-> next_sibling
,
2323 subnet_dereference (&u
-> next_sibling
,
2325 subnet_reference (&u
-> next_sibling
,
2328 subnet_dereference (&share
-> subnets
,
2330 subnet_reference (&share
-> subnets
,
2333 subnet_dereference (&subnet
, MDL
);
2338 subnet_reference (&t
-> next_sibling
, subnet
, MDL
);
2340 subnet_dereference (&subnet
, MDL
);
2343 /* group-declaration :== RBRACE parameters declarations LBRACE */
2345 void parse_group_declaration (cfile
, group
)
2346 struct parse
*cfile
;
2347 struct group
*group
;
2350 enum dhcp_token token
;
2352 int declaration
= 0;
2353 struct group_object
*t
= NULL
;
2354 isc_result_t status
;
2360 g
= (struct group
*)0;
2361 if (!clone_group (&g
, group
, MDL
))
2362 log_fatal ("no memory for explicit group.");
2364 token
= peek_token (&val
, (unsigned *)0, cfile
);
2365 if (is_identifier (token
) || token
== STRING
) {
2366 next_token (&val
, (unsigned *)0, cfile
);
2368 name
= dmalloc (strlen (val
) + 1, MDL
);
2370 log_fatal ("no memory for group decl name %s", val
);
2374 if (!parse_lbrace (cfile
)) {
2375 group_dereference (&g
, MDL
);
2380 token
= peek_token (&val
, (unsigned *)0, cfile
);
2381 if (token
== RBRACE
) {
2382 token
= next_token (&val
, (unsigned *)0, cfile
);
2384 } else if (token
== END_OF_FILE
) {
2385 token
= next_token (&val
, (unsigned *)0, cfile
);
2386 parse_warn (cfile
, "unexpected end of file");
2388 } else if (token
== TOKEN_DELETED
) {
2389 token
= next_token (&val
, (unsigned *)0, cfile
);
2392 } else if (token
== DYNAMIC
) {
2393 token
= next_token (&val
, (unsigned *)0, cfile
);
2396 } else if (token
== STATIC
) {
2397 token
= next_token (&val
, (unsigned *)0, cfile
);
2401 declaration
= parse_statement (cfile
, g
, GROUP_DECL
,
2402 (struct host_decl
*)0,
2408 if (group_name_hash
) {
2409 t
= (struct group_object
*)0;
2410 if (group_hash_lookup (&t
, group_name_hash
,
2412 strlen (name
), MDL
)) {
2413 delete_group (t
, 0);
2417 t
= (struct group_object
*)0;
2418 status
= group_object_allocate (&t
, MDL
);
2419 if (status
!= ISC_R_SUCCESS
)
2420 log_fatal ("no memory for group decl %s: %s",
2421 val
, isc_result_totext (status
));
2422 group_reference (&t
-> group
, g
, MDL
);
2424 t
-> flags
= ((staticp
? GROUP_OBJECT_STATIC
: 0) |
2425 (dynamicp
? GROUP_OBJECT_DYNAMIC
: 0) |
2426 (deletedp
? GROUP_OBJECT_DELETED
: 0));
2427 supersede_group (t
, 0);
2430 group_object_dereference (&t
, MDL
);
2434 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2435 ip-addrs-or-hostnames :== ip-addr-or-hostname
2436 | ip-addrs-or-hostnames ip-addr-or-hostname */
2438 int parse_fixed_addr_param (oc
, cfile
)
2439 struct option_cache
**oc
;
2440 struct parse
*cfile
;
2443 enum dhcp_token token
;
2444 struct expression
*expr
= (struct expression
*)0;
2445 struct expression
*tmp
, *new;
2449 tmp
= (struct expression
*)0;
2450 if (parse_ip_addr_or_hostname (&tmp
, cfile
, 1)) {
2452 new = (struct expression
*)0;
2453 status
= make_concat (&new, expr
, tmp
);
2454 expression_dereference (&expr
, MDL
);
2455 expression_dereference (&tmp
, MDL
);
2463 expression_dereference (&expr
, MDL
);
2466 token
= peek_token (&val
, (unsigned *)0, cfile
);
2468 token
= next_token (&val
, (unsigned *)0, cfile
);
2469 } while (token
== COMMA
);
2471 if (!parse_semi (cfile
)) {
2473 expression_dereference (&expr
, MDL
);
2476 status
= option_cache (oc
, (struct data_string
*)0, expr
,
2477 (struct option
*)0, MDL
);
2478 expression_dereference (&expr
, MDL
);
2482 /* timestamp :== date
2484 Timestamps are actually not used in dhcpd.conf, which is a static file,
2485 but rather in the database file and the journal file. (Okay, actually
2486 they're not even used there yet). */
2488 TIME
parse_timestamp (cfile
)
2489 struct parse
*cfile
;
2493 rv
= parse_date (cfile
);
2497 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2499 lease_parameters :== <nil>
2501 | lease_parameters lease_parameter
2503 lease_parameter :== STARTS date
2506 | HARDWARE hardware-parameter
2507 | UID hex_numbers SEMI
2508 | HOSTNAME hostname SEMI
2509 | CLIENT_HOSTNAME hostname SEMI
2510 | CLASS identifier SEMI
2511 | DYNAMIC_BOOTP SEMI */
2513 int parse_lease_declaration (struct lease
**lp
, struct parse
*cfile
)
2516 enum dhcp_token token
;
2517 unsigned char addr
[4];
2518 unsigned len
= sizeof addr
;
2522 struct lease
*lease
;
2523 struct executable_statement
*on
;
2527 int noequal
, newbinding
;
2528 struct binding
*binding
;
2529 isc_result_t status
;
2530 struct option_cache
*oc
;
2532 binding_state_t new_state
;
2533 unsigned buflen
= 0;
2534 struct class *class;
2536 seenbit
= 0; /* XXXGCC -Wuninitialized */
2537 newbinding
= 0; /* XXXGCC -Wuninitialized */
2538 new_state
= 0; /* XXXGCC -Wuninitialized */
2540 lease
= (struct lease
*)0;
2541 status
= lease_allocate (&lease
, MDL
);
2542 if (status
!= ISC_R_SUCCESS
)
2545 /* Get the address for which the lease has been issued. */
2546 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2547 lease_dereference (&lease
, MDL
);
2550 memcpy (lease
-> ip_addr
.iabuf
, addr
, len
);
2551 lease
-> ip_addr
.len
= len
;
2553 if (!parse_lbrace (cfile
)) {
2554 lease_dereference (&lease
, MDL
);
2559 token
= next_token (&val
, (unsigned *)0, cfile
);
2560 if (token
== RBRACE
)
2562 else if (token
== END_OF_FILE
) {
2563 parse_warn (cfile
, "unexpected end of file");
2566 strncpy (tbuf
, val
, sizeof tbuf
);
2567 tbuf
[(sizeof tbuf
) - 1] = 0;
2569 /* Parse any of the times associated with the lease. */
2577 t
= parse_date (cfile
);
2581 lease
-> starts
= t
;
2591 lease
-> timestamp
= t
;
2609 default: /* for gcc, we'll never get here. */
2610 log_fatal ("Impossible error at %s:%d.", MDL
);
2615 /* Colon-seperated hexadecimal octets... */
2618 token
= peek_token (&val
, (unsigned *)0, cfile
);
2619 if (token
== STRING
) {
2620 unsigned char *tuid
;
2621 token
= next_token (&val
, &buflen
, cfile
);
2622 if (buflen
< sizeof lease
-> uid_buf
) {
2623 tuid
= lease
-> uid_buf
;
2625 sizeof lease
-> uid_buf
;
2627 tuid
= ((unsigned char *)
2628 dmalloc (buflen
, MDL
));
2630 log_error ("no space for uid");
2631 lease_dereference (&lease
,
2635 lease
-> uid_max
= buflen
;
2637 lease
-> uid_len
= buflen
;
2638 memcpy (tuid
, val
, lease
-> uid_len
);
2639 lease
-> uid
= tuid
;
2642 lease
-> uid
= (parse_numeric_aggregate
2643 (cfile
, (unsigned char *)0,
2644 &buflen
, ':', 16, 8));
2645 if (!lease
-> uid
) {
2646 lease_dereference (&lease
, MDL
);
2649 lease
-> uid_len
= buflen
;
2650 lease
-> uid_max
= buflen
;
2651 if (lease
-> uid_len
== 0) {
2652 lease
-> uid
= (unsigned char *)0;
2653 parse_warn (cfile
, "zero-length uid");
2660 if (!lease
-> uid
) {
2661 log_fatal ("No memory for lease uid");
2667 token
= next_token (&val
, (unsigned *)0, cfile
);
2668 if (!is_identifier (token
)) {
2670 skip_to_rbrace (cfile
, 1);
2671 lease_dereference (&lease
, MDL
);
2675 /* for now, we aren't using this. */
2680 parse_hardware_param (cfile
,
2681 &lease
-> hardware_addr
);
2686 lease
-> flags
|= BOOTP_LEASE
;
2690 case TOKEN_ABANDONED
:
2692 lease
-> binding_state
= FTS_ABANDONED
;
2693 lease
-> next_binding_state
= FTS_ABANDONED
;
2699 token
= next_token (&val
, (unsigned *)0, cfile
);
2700 if (token
!= BINDING
) {
2701 parse_warn (cfile
, "expecting 'binding'");
2702 skip_to_semi (cfile
);
2705 goto do_binding_state
;
2711 token
= next_token (&val
, (unsigned *)0, cfile
);
2712 if (token
!= STATE
) {
2713 parse_warn (cfile
, "expecting 'state'");
2714 skip_to_semi (cfile
);
2717 token
= next_token (&val
, (unsigned *)0, cfile
);
2719 case TOKEN_ABANDONED
:
2720 new_state
= FTS_ABANDONED
;
2723 new_state
= FTS_FREE
;
2726 new_state
= FTS_ACTIVE
;
2729 new_state
= FTS_EXPIRED
;
2731 case TOKEN_RELEASED
:
2732 new_state
= FTS_RELEASED
;
2735 new_state
= FTS_RESET
;
2738 new_state
= FTS_BACKUP
;
2740 case TOKEN_RESERVED
:
2741 new_state
= FTS_ACTIVE
;
2744 new_state
= FTS_ACTIVE
;
2745 lease
-> flags
|= BOOTP_LEASE
;
2749 "%s: expecting a binding state.",
2751 skip_to_semi (cfile
);
2755 if (seenbit
== 256) {
2756 lease
-> binding_state
= new_state
;
2758 /* If no next binding state is specified, it's
2759 the same as the current state. */
2760 if (!(seenmask
& 128))
2761 lease
-> next_binding_state
= new_state
;
2763 lease
-> next_binding_state
= new_state
;
2768 case CLIENT_HOSTNAME
:
2770 token
= peek_token (&val
, (unsigned *)0, cfile
);
2771 if (token
== STRING
) {
2772 if (!parse_string (cfile
,
2773 &lease
-> client_hostname
,
2775 lease_dereference (&lease
, MDL
);
2779 lease
-> client_hostname
=
2780 parse_host_name (cfile
);
2781 if (lease
-> client_hostname
)
2785 "expecting a hostname.");
2786 skip_to_semi (cfile
);
2787 lease_dereference (&lease
, MDL
);
2795 class = (struct class *)0;
2796 token
= next_token (&val
, (unsigned *)0, cfile
);
2797 if (token
== CLASS
) {
2798 token
= next_token (&val
,
2799 (unsigned *)0, cfile
);
2800 if (token
!= STRING
) {
2801 parse_warn (cfile
, "expecting string");
2803 skip_to_semi (cfile
);
2807 if (lease
-> billing_class
)
2808 class_dereference (&lease
-> billing_class
,
2810 find_class (&class, val
, MDL
);
2813 "unknown class %s", val
);
2815 } else if (token
== SUBCLASS
) {
2816 if (lease
-> billing_class
)
2817 class_dereference (&lease
-> billing_class
,
2819 parse_class_declaration
2821 cfile
, (struct group
*)0, 3);
2823 parse_warn (cfile
, "expecting \"class\"");
2825 skip_to_semi (cfile
);
2828 class_reference (&lease
-> billing_class
,
2830 class_dereference (&class, MDL
);
2835 on
= (struct executable_statement
*)0;
2837 if (!parse_on_statement (&on
, cfile
, &lose
)) {
2838 skip_to_rbrace (cfile
, 1);
2839 lease_dereference (&lease
, MDL
);
2843 if ((on
-> data
.on
.evtypes
& ON_EXPIRY
) &&
2844 on
-> data
.on
.statements
) {
2846 executable_statement_reference
2847 (&lease
-> on_expiry
,
2848 on
-> data
.on
.statements
, MDL
);
2850 if ((on
-> data
.on
.evtypes
& ON_RELEASE
) &&
2851 on
-> data
.on
.statements
) {
2853 executable_statement_reference
2854 (&lease
-> on_release
,
2855 on
-> data
.on
.statements
, MDL
);
2857 executable_statement_dereference (&on
, MDL
);
2864 oc
= (struct option_cache
*)0;
2865 if (parse_option_decl (&oc
, cfile
)) {
2866 if (oc
-> option
-> universe
!=
2869 "agent option expected.");
2870 option_cache_dereference (&oc
, MDL
);
2873 if (!lease
-> agent_options
&&
2874 !(option_chain_head_allocate
2875 (&lease
-> agent_options
, MDL
))) {
2876 log_error ("no memory to stash agent option");
2879 for (p
= &lease
-> agent_options
-> first
;
2880 *p
; p
= &((*p
) -> cdr
))
2883 option_cache_reference (((struct option_cache
**)
2884 &((*p
) -> car
)), oc
, MDL
);
2885 option_cache_dereference (&oc
, MDL
);
2892 token
= next_token (&val
, (unsigned *)0, cfile
);
2893 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2895 "%s can't be a variable name",
2898 skip_to_semi (cfile
);
2899 lease_dereference (&lease
, MDL
);
2906 binding
= find_binding (lease
-> scope
, val
);
2908 binding
= (struct binding
*)0;
2910 if (!lease
-> scope
)
2911 if (!(binding_scope_allocate
2912 (&lease
-> scope
, MDL
)))
2913 log_fatal ("no memory for scope");
2914 binding
= dmalloc (sizeof *binding
, MDL
);
2916 log_fatal ("No memory for lease %s.",
2918 memset (binding
, 0, sizeof *binding
);
2920 dmalloc (strlen (val
) + 1, MDL
);
2921 if (!binding
-> name
)
2922 log_fatal ("No memory for binding %s.",
2924 strcpy (binding
-> name
, val
);
2927 if (binding
-> value
)
2928 binding_value_dereference (&binding
-> value
,
2933 if (!binding_value_allocate (&binding
-> value
, MDL
))
2934 log_fatal ("no memory for binding value.");
2937 token
= next_token (&val
, (unsigned *)0, cfile
);
2938 if (token
!= EQUAL
) {
2940 "expecting '=' in set statement.");
2945 token
= peek_token (&val
, (unsigned *)0, cfile
);
2946 if (token
== STRING
) {
2947 token
= next_token (&val
, &buflen
, cfile
);
2948 binding
-> value
-> type
= binding_data
;
2949 binding
-> value
-> value
.data
.len
= buflen
;
2950 if (!(buffer_allocate
2951 (&binding
-> value
-> value
.data
.buffer
,
2953 log_fatal ("No memory for binding.");
2955 (binding
-> value
->
2956 value
.data
.buffer
-> data
),
2958 binding
-> value
-> value
.data
.data
=
2959 binding
-> value
-> value
.data
.buffer
-> data
;
2960 binding
-> value
-> value
.data
.terminated
= 1;
2961 } else if (token
== NUMBER_OR_NAME
) {
2962 binding
-> value
-> type
= binding_data
;
2964 (parse_numeric_aggregate
2965 (cfile
, (unsigned char *)0,
2966 &binding
-> value
-> value
.data
.len
,
2969 binding_value_dereference
2970 (&binding
-> value
, MDL
);
2971 lease_dereference (&lease
, MDL
);
2974 if (binding
-> value
-> value
.data
.len
) {
2975 if (!(buffer_allocate
2976 (&binding
-> value
-> value
.data
.buffer
,
2977 binding
-> value
-> value
.data
.len
+ 1,
2979 log_fatal ("No memory for binding.");
2980 memcpy ((binding
-> value
->
2981 value
.data
.buffer
-> data
), s
,
2982 binding
-> value
-> value
.data
.len
);
2984 binding
-> value
-> value
.data
.data
=
2985 binding
-> value
-> value
.data
.buffer
-> data
;
2987 } else if (token
== PERCENT
) {
2988 token
= next_token (&val
, (unsigned *)0, cfile
);
2989 token
= next_token (&val
, (unsigned *)0, cfile
);
2990 if (token
!= NUMBER
) {
2992 "expecting decimal number.");
2994 skip_to_semi (cfile
);
2995 binding_value_dereference
2996 (&binding
-> value
, MDL
);
2997 lease_dereference (&lease
, MDL
);
3000 binding
-> value
-> type
= binding_numeric
;
3001 binding
-> value
-> value
.intval
= atol (val
);
3002 } else if (token
== NAME
) {
3003 token
= next_token (&val
,
3004 (unsigned *)0, cfile
);
3005 binding
-> value
-> type
= binding_boolean
;
3006 if (!strcasecmp (val
, "true"))
3007 binding
-> value
-> value
.boolean
= 1;
3008 else if (!strcasecmp (val
, "false"))
3009 binding
-> value
-> value
.boolean
= 0;
3015 "expecting a constant value.");
3016 skip_to_semi (cfile
);
3017 binding_value_dereference (&binding
-> value
,
3019 lease_dereference (&lease
, MDL
);
3024 binding
-> next
= lease
-> scope
-> bindings
;
3025 lease
-> scope
-> bindings
= binding
;
3031 if (!strcasecmp (val
, "ddns-fwd-name")) {
3035 } else if (!strcasecmp (val
, "ddns-rev-name")) {
3040 skip_to_semi (cfile
);
3042 lease_dereference (&lease
, MDL
);
3046 if (seenmask
& seenbit
) {
3048 "Too many %s parameters in lease %s\n",
3049 tbuf
, piaddr (lease
-> ip_addr
));
3051 seenmask
|= seenbit
;
3055 /* If no binding state is specified, make one up. */
3056 if (!(seenmask
& 256)) {
3057 if (lease
-> ends
> cur_time
||
3058 lease
-> on_expiry
|| lease
-> on_release
)
3059 lease
-> binding_state
= FTS_ACTIVE
;
3060 #if defined (FAILOVER_PROTOCOL)
3061 else if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3062 lease
-> binding_state
= FTS_EXPIRED
;
3065 lease
-> binding_state
= FTS_FREE
;
3066 if (lease
-> binding_state
== FTS_ACTIVE
) {
3067 #if defined (FAILOVER_PROTOCOL)
3068 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3069 lease
-> next_binding_state
= FTS_EXPIRED
;
3072 lease
-> next_binding_state
= FTS_FREE
;
3074 lease
-> next_binding_state
= lease
-> binding_state
;
3077 if (!(seenmask
& 65536))
3078 lease
-> tstp
= lease
-> ends
;
3080 lease_reference (lp
, lease
, MDL
);
3081 lease_dereference (&lease
, MDL
);
3085 /* address-range-declaration :== ip-address ip-address SEMI
3086 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3088 void parse_address_range (cfile
, group
, type
, inpool
, lpchain
)
3089 struct parse
*cfile
;
3090 struct group
*group
;
3092 struct pool
*inpool
;
3093 struct lease
**lpchain
;
3095 struct iaddr low
, high
, net
;
3096 unsigned char addr
[4];
3097 unsigned len
= sizeof addr
;
3098 enum dhcp_token token
;
3101 struct subnet
*subnet
;
3102 struct shared_network
*share
;
3104 isc_result_t status
;
3106 if ((token
= peek_token (&val
,
3107 (unsigned *)0, cfile
)) == DYNAMIC_BOOTP
) {
3108 token
= next_token (&val
, (unsigned *)0, cfile
);
3112 /* Get the bottom address in the range... */
3113 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3115 memcpy (low
.iabuf
, addr
, len
);
3118 /* Only one address? */
3119 token
= peek_token (&val
, (unsigned *)0, cfile
);
3123 /* Get the top address in the range... */
3124 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3126 memcpy (high
.iabuf
, addr
, len
);
3130 token
= next_token (&val
, (unsigned *)0, cfile
);
3131 if (token
!= SEMI
) {
3132 parse_warn (cfile
, "semicolon expected.");
3133 skip_to_semi (cfile
);
3137 if (type
== SUBNET_DECL
) {
3138 subnet
= group
-> subnet
;
3139 share
= subnet
-> shared_network
;
3141 share
= group
-> shared_network
;
3142 for (subnet
= share
-> subnets
;
3143 subnet
; subnet
= subnet
-> next_sibling
) {
3144 net
= subnet_number (low
, subnet
-> netmask
);
3145 if (addr_eq (net
, subnet
-> net
))
3149 parse_warn (cfile
, "address range not on network %s",
3150 group
-> shared_network
-> name
);
3151 log_error ("Be sure to place pool statement after %s",
3152 "related subnet declarations.");
3158 struct pool
*last
= (struct pool
*)0;
3160 /* If we're permitting dynamic bootp for this range,
3161 then look for a pool with an empty prohibit list and
3162 a permit list with one entry that permits all clients. */
3163 for (pool
= share
-> pools
; pool
; pool
= pool
-> next
) {
3164 if ((!dynamic
&& !pool
-> permit_list
&&
3165 pool
-> prohibit_list
&&
3166 !pool
-> prohibit_list
-> next
&&
3167 (pool
-> prohibit_list
-> type
==
3168 permit_dynamic_bootp_clients
)) ||
3169 (dynamic
&& !pool
-> prohibit_list
&&
3170 pool
-> permit_list
&&
3171 !pool
-> permit_list
-> next
&&
3172 (pool
-> permit_list
-> type
==
3173 permit_all_clients
))) {
3179 /* If we didn't get a pool, make one. */
3182 status
= pool_allocate (&pool
, MDL
);
3183 if (status
!= ISC_R_SUCCESS
)
3184 log_fatal ("no memory for ad-hoc pool: %s",
3185 isc_result_totext (status
));
3186 p
= new_permit (MDL
);
3188 log_fatal ("no memory for ad-hoc permit.");
3190 /* Dynamic pools permit all clients. Otherwise
3191 we prohibit BOOTP clients. */
3193 p
-> type
= permit_all_clients
;
3194 pool
-> permit_list
= p
;
3196 p
-> type
= permit_dynamic_bootp_clients
;
3197 pool
-> prohibit_list
= p
;
3201 pool_reference (&last
-> next
, pool
, MDL
);
3203 pool_reference (&share
-> pools
, pool
, MDL
);
3204 shared_network_reference (&pool
-> shared_network
,
3206 if (!clone_group (&pool
-> group
, share
-> group
, MDL
))
3207 log_fatal ("no memory for anon pool group.");
3209 pool
= (struct pool
*)0;
3211 pool_reference (&pool
, last
, MDL
);
3213 pool_reference (&pool
, share
-> pools
, MDL
);
3216 pool
= (struct pool
*)0;
3217 pool_reference (&pool
, inpool
, MDL
);
3220 #if defined (FAILOVER_PROTOCOL)
3221 if (pool
-> failover_peer
&& dynamic
) {
3222 /* Doctor, do you think I'm overly sensitive
3223 about getting bug reports I can't fix? */
3224 parse_warn (cfile
, "dynamic-bootp flag is %s",
3225 "not permitted for address");
3226 log_error ("range declarations where there is a failover");
3227 log_error ("peer in scope. If you wish to declare an");
3228 log_error ("address range from which dynamic bootp leases");
3229 log_error ("can be allocated, please declare it within a");
3230 log_error ("pool declaration that also contains the \"no");
3231 log_error ("failover\" statement. The failover protocol");
3232 log_error ("itself does not permit dynamic bootp - this");
3233 log_error ("is not a limitation specific to the ISC DHCP");
3234 log_error ("server. Please don't ask me to defend this");
3235 log_error ("until you have read and really tried %s",
3237 log_error ("the failover protocol specification.");
3239 /* We don't actually bomb at this point - instead,
3240 we let parse_lease_file notice the error and
3241 bomb at that point - it's easier. */
3243 #endif /* FAILOVER_PROTOCOL */
3245 /* Create the new address range... */
3246 new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
);
3247 pool_dereference (&pool
, MDL
);
3250 /* allow-deny-keyword :== BOOTP
3253 | UNKNOWN_CLIENTS */
3255 int parse_allow_deny (oc
, cfile
, flag
)
3256 struct option_cache
**oc
;
3257 struct parse
*cfile
;
3260 enum dhcp_token token
;
3262 unsigned char rf
= flag
;
3263 struct expression
*data
= (struct expression
*)0;
3266 if (!make_const_data (&data
, &rf
, 1, 0, 1, MDL
))
3269 token
= next_token (&val
, (unsigned *)0, cfile
);
3272 status
= option_cache (oc
, (struct data_string
*)0, data
,
3273 &server_options
[SV_ALLOW_BOOTP
], MDL
);
3277 status
= option_cache (oc
, (struct data_string
*)0, data
,
3278 &server_options
[SV_ALLOW_BOOTING
],
3283 status
= option_cache (oc
, (struct data_string
*)0, data
,
3284 &server_options
[SV_DYNAMIC_BOOTP
],
3288 case UNKNOWN_CLIENTS
:
3289 status
= (option_cache
3290 (oc
, (struct data_string
*)0, data
,
3291 &server_options
[SV_BOOT_UNKNOWN_CLIENTS
], MDL
));
3295 status
= option_cache (oc
, (struct data_string
*)0, data
,
3296 &server_options
[SV_DUPLICATES
], MDL
);
3300 status
= option_cache (oc
, (struct data_string
*)0, data
,
3301 &server_options
[SV_DECLINES
], MDL
);
3304 case CLIENT_UPDATES
:
3305 status
= option_cache (oc
, (struct data_string
*)0, data
,
3306 &server_options
[SV_CLIENT_UPDATES
],
3311 parse_warn (cfile
, "expecting allow/deny key");
3312 skip_to_semi (cfile
);
3315 expression_dereference (&data
, MDL
);