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$ 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
)
82 ttype
= trace_readleases_type
;
84 ttype
= trace_readconf_type
;
86 /* If we're in playback, we need to snarf the contents of the
87 named file out of the playback file rather than trying to
89 if (trace_playback ()) {
92 status
= trace_get_file (ttype
, filename
, &tflen
, &dbuf
);
93 if (status
!= ISC_R_SUCCESS
)
97 /* What we get back is filename\0contents, where contents is
98 terminated just by the length. So we figure out the length
99 of the filename, and subtract that and the NUL from the
100 total length to get the length of the contents of the file.
101 We make fbuf a pointer to the contents of the file, and
102 leave dbuf as it is so we can free it later. */
103 tflen
= strlen (dbuf
);
104 ulen
= ulen
- tflen
- 1;
105 fbuf
= dbuf
+ tflen
+ 1;
110 if ((file
= open (filename
, O_RDONLY
)) < 0) {
112 log_error ("Can't open lease database %s: %m --",
114 log_error (" check for failed database %s!",
116 log_error ("Please read the dhcpd.leases manual%s",
118 log_fatal ("don't know what to do about this.");
120 log_fatal ("Can't open %s: %m", filename
);
124 cfile
= (struct parse
*)0;
125 #if defined (TRACING)
126 flen
= lseek (file
, (off_t
)0, SEEK_END
);
129 log_fatal ("Can't lseek on %s: %m", filename
);
131 if (lseek (file
, (off_t
)0, SEEK_SET
) < 0)
133 /* Can't handle files greater than 2^31-1. */
134 if (flen
> 0x7FFFFFFFUL
)
135 log_fatal ("%s: file is too long to buffer.", filename
);
138 /* Allocate a buffer that will be what's written to the tracefile,
139 and also will be what we parse from. */
140 tflen
= strlen (filename
);
141 dbuf
= dmalloc (ulen
+ tflen
+ 1, MDL
);
143 log_fatal ("No memory for %s (%d bytes)",
146 /* Copy the name into the beginning, nul-terminated. */
147 strcpy (dbuf
, filename
);
149 /* Load the file in after the NUL. */
150 fbuf
= dbuf
+ tflen
+ 1;
151 result
= read (file
, fbuf
, ulen
);
153 log_fatal ("Can't read in %s: %m", filename
);
155 log_fatal ("%s: short read of %d bytes instead of %d.",
156 filename
, ulen
, result
);
159 /* If we're recording, write out the filename and file contents. */
161 trace_write_packet (ttype
, ulen
+ tflen
+ 1, dbuf
, MDL
);
162 new_parse (&cfile
, -1, fbuf
, ulen
, filename
, 0); /* XXX */
164 new_parse (&cfile
, file
, (char *)0, 0, filename
, 0);
168 status
= lease_file_subparse (cfile
);
170 status
= conf_file_subparse (cfile
, group
, group_type
);
172 #if defined (TRACING)
178 #if defined (TRACING)
179 void trace_conf_input (trace_type_t
*ttype
, unsigned len
, char *data
)
184 struct parse
*cfile
= (struct parse
*)0;
185 static int postconf_initialized
;
186 static int leaseconf_initialized
;
188 /* Do what's done above, except that we don't have to read in the
189 data, because it's already been read for us. */
190 tflen
= strlen (data
);
191 flen
= len
- tflen
- 1;
192 fbuf
= data
+ tflen
+ 1;
194 /* If we're recording, write out the filename and file contents. */
196 trace_write_packet (ttype
, len
, data
, MDL
);
197 new_parse (&cfile
, -1, fbuf
, flen
, data
, 0);
198 if (ttype
== trace_readleases_type
)
199 lease_file_subparse (cfile
);
201 conf_file_subparse (cfile
, root_group
, ROOT_GROUP
);
204 /* Postconfiguration needs to be done after the config file
206 if (!postconf_initialized
&& ttype
== trace_readconf_type
) {
207 postconf_initialization (0);
208 postconf_initialized
= 1;
211 if (!leaseconf_initialized
&& ttype
== trace_readleases_type
) {
213 leaseconf_initialized
= 1;
218 void trace_conf_stop (trace_type_t
*ttype
) { }
221 /* conf-file :== parameters declarations END_OF_FILE
222 parameters :== <nil> | parameter | parameters parameter
223 declarations :== <nil> | declaration | declarations declaration */
225 isc_result_t
conf_file_subparse (struct parse
*cfile
, struct group
*group
,
229 enum dhcp_token token
;
234 token
= peek_token (&val
, (unsigned *)0, cfile
);
235 if (token
== END_OF_FILE
)
237 declaration
= parse_statement (cfile
, group
, group_type
,
238 (struct host_decl
*)0,
241 token
= next_token (&val
, (unsigned *)0, cfile
);
243 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
247 /* lease-file :== lease-declarations END_OF_FILE
248 lease-statments :== <nil>
250 | lease-declarations lease-declaration */
252 isc_result_t
lease_file_subparse (struct parse
*cfile
)
255 enum dhcp_token token
;
259 token
= next_token (&val
, (unsigned *)0, cfile
);
260 if (token
== END_OF_FILE
)
262 if (token
== LEASE
) {
263 struct lease
*lease
= (struct lease
*)0;
264 if (parse_lease_declaration (&lease
, cfile
)) {
266 lease_dereference (&lease
, MDL
);
269 "possibly corrupt lease file");
270 } else if (token
== HOST
) {
271 parse_host_declaration (cfile
, root_group
);
272 } else if (token
== GROUP
) {
273 parse_group_declaration (cfile
, root_group
);
274 #if defined (FAILOVER_PROTOCOL)
275 } else if (token
== FAILOVER
) {
276 parse_failover_state_declaration
277 (cfile
, (dhcp_failover_state_t
*)0);
280 log_error ("Corrupt lease file - possible data loss!");
281 skip_to_semi (cfile
);
286 status
= cfile
-> warnings_occurred
? ISC_R_BADPARSE
: ISC_R_SUCCESS
;
290 /* statement :== parameter | declaration
292 parameter :== timestamp
293 | DEFAULT_LEASE_TIME lease_time
294 | MAX_LEASE_TIME lease_time
295 | DYNAMIC_BOOTP_LEASE_CUTOFF date
296 | DYNAMIC_BOOTP_LEASE_LENGTH lease_time
297 | BOOT_UNKNOWN_CLIENTS boolean
298 | ONE_LEASE_PER_CLIENT boolean
299 | GET_LEASE_HOSTNAMES boolean
300 | USE_HOST_DECL_NAME boolean
301 | NEXT_SERVER ip-addr-or-hostname SEMI
303 | SERVER-IDENTIFIER ip-addr-or-hostname SEMI
304 | FILENAME string-parameter
305 | SERVER_NAME string-parameter
307 | fixed-address-parameter
308 | ALLOW allow-deny-keyword
309 | DENY allow-deny-keyword
310 | USE_LEASE_ADDR_FOR_DEFAULT_ROUTE boolean
314 declaration :== host-declaration
316 | shared-network-declaration
318 | VENDOR_CLASS class-declaration
319 | USER_CLASS class-declaration
320 | RANGE address-range-declaration */
322 int parse_statement (cfile
, group
, type
, host_decl
, declaration
)
326 struct host_decl
*host_decl
;
329 enum dhcp_token token
;
331 struct shared_network
*share
;
333 struct expression
*expr
;
334 struct data_string data
;
335 struct hardware hardware
;
336 struct executable_statement
*et
, *ep
;
337 struct option
*option
;
338 struct option_cache
*cache
;
340 struct data_string key_id
;
344 token
= peek_token (&val
, (unsigned *)0, cfile
);
348 next_token (&val
, (unsigned *)0, cfile
);
349 token
= next_token (&val
, (unsigned *)0, cfile
);
350 if (token
!= STRING
) {
351 parse_warn (cfile
, "filename string expected.");
352 skip_to_semi (cfile
);
354 status
= read_conf_file (val
, group
, type
, 0);
355 if (status
!= ISC_R_SUCCESS
)
356 parse_warn (cfile
, "%s: bad parse.", val
);
362 next_token (&val
, (unsigned *)0, cfile
);
363 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
364 parse_host_declaration (cfile
, group
);
367 "host declarations not allowed here.");
368 skip_to_semi (cfile
);
373 next_token (&val
, (unsigned *)0, cfile
);
374 if (type
!= HOST_DECL
&& type
!= CLASS_DECL
)
375 parse_group_declaration (cfile
, group
);
378 "group declarations not allowed here.");
379 skip_to_semi (cfile
);
384 next_token (&val
, (unsigned *)0, cfile
);
385 parsed_time
= parse_timestamp (cfile
);
389 next_token (&val
, (unsigned *)0, cfile
);
390 if (type
== SHARED_NET_DECL
||
392 type
== SUBNET_DECL
||
393 type
== CLASS_DECL
) {
394 parse_warn (cfile
, "shared-network parameters not %s.",
396 skip_to_semi (cfile
);
400 parse_shared_net_declaration (cfile
, group
);
404 next_token (&val
, (unsigned *)0, cfile
);
405 if (type
== HOST_DECL
|| type
== SUBNET_DECL
||
406 type
== CLASS_DECL
) {
408 "subnet declarations not allowed here.");
409 skip_to_semi (cfile
);
413 /* If we're in a subnet declaration, just do the parse. */
414 if (group
-> shared_network
) {
415 parse_subnet_declaration (cfile
,
416 group
-> shared_network
);
420 /* Otherwise, cons up a fake shared network structure
421 and populate it with the lone subnet... */
423 share
= (struct shared_network
*)0;
424 status
= shared_network_allocate (&share
, MDL
);
425 if (status
!= ISC_R_SUCCESS
)
426 log_fatal ("Can't allocate shared subnet: %s",
427 isc_result_totext (status
));
428 if (!clone_group (&share
-> group
, group
, MDL
))
429 log_fatal ("Can't allocate group for shared net");
430 shared_network_reference (&share
-> group
-> shared_network
,
433 parse_subnet_declaration (cfile
, share
);
435 /* share -> subnets is the subnet we just parsed. */
436 if (share
-> subnets
) {
437 interface_reference (&share
-> interface
,
438 share
-> subnets
-> interface
,
441 /* Make the shared network name from network number. */
442 n
= piaddrmask (share
-> subnets
-> net
,
443 share
-> subnets
-> netmask
, MDL
);
446 /* Copy the authoritative parameter from the subnet,
447 since there is no opportunity to declare it here. */
448 share
-> group
-> authoritative
=
449 share
-> subnets
-> group
-> authoritative
;
450 enter_shared_network (share
);
452 shared_network_dereference (&share
, MDL
);
456 next_token (&val
, (unsigned *)0, cfile
);
457 if (type
== CLASS_DECL
) {
459 "class declarations not allowed here.");
460 skip_to_semi (cfile
);
463 parse_class_declaration ((struct class **)0, cfile
, group
, 0);
467 next_token (&val
, (unsigned *)0, cfile
);
468 if (type
== CLASS_DECL
) {
470 "class declarations not allowed here.");
471 skip_to_semi (cfile
);
474 parse_class_declaration ((struct class **)0, cfile
, group
, 1);
478 next_token (&val
, (unsigned *)0, cfile
);
479 if (type
== CLASS_DECL
) {
481 "class declarations not allowed here.");
482 skip_to_semi (cfile
);
485 parse_class_declaration ((struct class **)0, cfile
, group
, 2);
489 next_token (&val
, (unsigned *)0, cfile
);
490 if (type
== CLASS_DECL
) {
492 "class declarations not allowed here.");
493 skip_to_semi (cfile
);
496 parse_class_declaration ((struct class **)0, cfile
, group
, 3);
500 next_token (&val
, (unsigned *)0, cfile
);
501 memset (&hardware
, 0, sizeof hardware
);
502 parse_hardware_param (cfile
, &hardware
);
504 host_decl
-> interface
= hardware
;
506 parse_warn (cfile
, "hardware address parameter %s",
507 "not allowed here.");
511 next_token (&val
, (unsigned *)0, cfile
);
512 cache
= (struct option_cache
*)0;
513 if (parse_fixed_addr_param (&cache
, cfile
)) {
515 if (host_decl
-> fixed_addr
) {
516 option_cache_dereference (&cache
, MDL
);
518 "Only one fixed address%s",
519 " declaration per host.");
521 host_decl
-> fixed_addr
= cache
;
525 "fixed-address parameter not %s",
527 option_cache_dereference (&cache
, MDL
);
533 next_token (&val
, (unsigned *)0, cfile
);
534 if (type
!= SUBNET_DECL
&& type
!= SHARED_NET_DECL
) {
535 parse_warn (cfile
, "pool declared outside of network");
537 if (type
== POOL_DECL
) {
538 parse_warn (cfile
, "pool declared within pool.");
540 parse_pool_statement (cfile
, group
, type
);
544 next_token (&val
, (unsigned *)0, cfile
);
545 if (type
!= SUBNET_DECL
|| !group
-> subnet
) {
547 "range declaration not allowed here.");
548 skip_to_semi (cfile
);
551 parse_address_range (cfile
, group
, type
, (struct pool
*)0,
556 token
= next_token (&val
, (unsigned *)0, cfile
);
557 token
= next_token (&val
, (unsigned *)0, cfile
);
560 group
-> authoritative
= 0;
563 parse_warn (cfile
, "expecting assertion");
564 skip_to_semi (cfile
);
569 token
= next_token (&val
, (unsigned *)0, cfile
);
570 group
-> authoritative
= 1;
572 if (type
== HOST_DECL
)
573 parse_warn (cfile
, "authority makes no sense here.");
577 /* "server-identifier" is a special hack, equivalent to
578 "option dhcp-server-identifier". */
579 case SERVER_IDENTIFIER
:
580 option
= dhcp_universe
.options
[DHO_DHCP_SERVER_IDENTIFIER
];
581 token
= next_token (&val
, (unsigned *)0, cfile
);
585 token
= next_token (&val
, (unsigned *)0, cfile
);
586 token
= peek_token (&val
, (unsigned *)0, cfile
);
587 if (token
== SPACE
) {
588 if (type
!= ROOT_GROUP
) {
590 "option space definitions %s",
591 "may not be scoped.");
592 skip_to_semi (cfile
);
595 parse_option_space_decl (cfile
);
600 option
= parse_option_name (cfile
, 1, &known
);
602 token
= peek_token (&val
, (unsigned *)0, cfile
);
604 if (type
!= ROOT_GROUP
) {
606 "option definitions%s",
607 " may not be scoped.");
608 skip_to_semi (cfile
);
609 free_option (option
, MDL
);
612 next_token (&val
, (unsigned *)0, cfile
);
613 if (!parse_option_code_definition (cfile
,
615 free_option (option
, MDL
);
619 /* If this wasn't an option code definition, don't
620 allow an unknown option. */
622 parse_warn (cfile
, "unknown option %s.%s",
623 option
-> universe
-> name
,
625 skip_to_semi (cfile
);
626 free_option (option
, MDL
);
631 et
= (struct executable_statement
*)0;
632 if (!parse_option_statement
633 (&et
, cfile
, 1, option
,
634 supersede_option_statement
))
636 goto insert_statement
;
643 if (type
!= ROOT_GROUP
&& type
!= SHARED_NET_DECL
) {
644 parse_warn (cfile
, "failover peers may only be %s",
645 "defined in shared-network");
646 log_error ("declarations and the outer scope.");
647 skip_to_semi (cfile
);
650 token
= next_token (&val
, (unsigned *)0, cfile
);
651 #if defined (FAILOVER_PROTOCOL)
652 parse_failover_peer (cfile
, group
, type
);
654 parse_warn (cfile
, "No failover support.");
655 skip_to_semi (cfile
);
660 et
= (struct executable_statement
*)0;
662 if (!parse_executable_statement (&et
, cfile
, &lose
,
667 "expecting a declaration");
670 "expecting a parameter %s",
672 skip_to_semi (cfile
);
679 if (group
-> statements
) {
682 /* If this set of statements is only referenced
683 by this group, just add the current statement
684 to the end of the chain. */
685 for (ep
= group
-> statements
; ep
-> next
;
687 if (ep
-> refcnt
> 1) /* XXX */
690 executable_statement_reference (&ep
-> next
,
692 executable_statement_dereference (&et
, MDL
);
696 /* Otherwise, make a parent chain, and put the
697 current group statements first and the new
698 statement in the next pointer. */
699 ep
= (struct executable_statement
*)0;
700 if (!executable_statement_allocate (&ep
, MDL
))
701 log_fatal ("No memory for statements.");
702 ep
-> op
= statements_statement
;
703 executable_statement_reference (&ep
-> data
.statements
,
706 executable_statement_reference (&ep
-> next
, et
, MDL
);
707 executable_statement_dereference (&group
-> statements
,
709 executable_statement_reference (&group
-> statements
,
711 executable_statement_dereference (&ep
, MDL
);
713 executable_statement_reference (&group
-> statements
,
716 executable_statement_dereference (&et
, MDL
);
723 #if defined (FAILOVER_PROTOCOL)
724 void parse_failover_peer (cfile
, group
, type
)
729 enum dhcp_token token
;
731 dhcp_failover_state_t
*peer
;
736 unsigned hba_len
= sizeof hba
;
738 struct expression
*expr
;
740 dhcp_failover_config_t
*cp
;
742 token
= next_token (&val
, (unsigned *)0, cfile
);
744 parse_warn (cfile
, "expecting \"peer\"");
745 skip_to_semi (cfile
);
749 token
= next_token (&val
, (unsigned *)0, cfile
);
750 if (is_identifier (token
) || token
== STRING
) {
751 name
= dmalloc (strlen (val
) + 1, MDL
);
753 log_fatal ("no memory for peer name %s", name
);
756 parse_warn (cfile
, "expecting failover peer name.");
757 skip_to_semi (cfile
);
761 /* See if there's a peer declaration by this name. */
762 peer
= (dhcp_failover_state_t
*)0;
763 find_failover_peer (&peer
, name
, MDL
);
765 token
= next_token (&val
, (unsigned *)0, cfile
);
768 if (type
!= SHARED_NET_DECL
)
769 parse_warn (cfile
, "failover peer reference not %s",
770 "in shared-network declaration");
773 parse_warn (cfile
, "reference to unknown%s%s",
774 " failover peer ", name
);
777 dhcp_failover_state_reference
778 (&group
-> shared_network
-> failover_peer
,
781 dhcp_failover_state_dereference (&peer
, MDL
);
783 } else if (token
== STATE
) {
785 parse_warn (cfile
, "state declaration for unknown%s%s",
786 " failover peer ", name
);
789 parse_failover_state_declaration (cfile
, peer
);
790 dhcp_failover_state_dereference (&peer
, MDL
);
792 } else if (token
!= LBRACE
) {
793 parse_warn (cfile
, "expecting left brace");
794 skip_to_semi (cfile
);
797 /* Make sure this isn't a redeclaration. */
799 parse_warn (cfile
, "redeclaration of failover peer %s", name
);
800 skip_to_rbrace (cfile
, 1);
801 dhcp_failover_state_dereference (&peer
, MDL
);
805 status
= dhcp_failover_state_allocate (&peer
, MDL
);
806 if (status
!= ISC_R_SUCCESS
)
807 log_fatal ("Can't allocate failover peer %s: %s",
808 name
, isc_result_totext (status
));
816 token
= next_token (&val
, (unsigned *)0, cfile
);
822 peer
-> i_am
= primary
;
826 peer
-> i_am
= secondary
;
829 "secondary may not define %s",
830 "load balance settings.");
834 cp
= &peer
-> partner
;
838 expr
= (struct expression
*)0;
839 if (!parse_ip_addr_or_hostname (&expr
, cfile
, 0)) {
840 skip_to_rbrace (cfile
, 1);
841 dhcp_failover_state_dereference (&peer
, MDL
);
844 option_cache (&cp
-> address
,
845 (struct data_string
*)0, expr
,
846 (struct option
*)0, MDL
);
847 expression_dereference (&expr
, MDL
);
851 token
= next_token (&val
, (unsigned *)0, cfile
);
852 if (token
!= NUMBER
) {
853 parse_warn (cfile
, "expecting number");
854 skip_to_rbrace (cfile
, 1);
856 cp
-> port
= atoi (val
);
859 case MAX_RESPONSE_DELAY
:
860 tp
= &cp
-> max_response_delay
;
862 token
= next_token (&val
, (unsigned *)0, cfile
);
863 if (token
!= NUMBER
) {
864 parse_warn (cfile
, "expecting number.");
865 skip_to_rbrace (cfile
, 1);
866 dhcp_failover_state_dereference (&peer
, MDL
);
872 case MAX_UNACKED_UPDATES
:
873 tp
= &cp
-> max_flying_updates
;
882 if (peer
-> i_am
== secondary
)
884 "secondary may not define %s",
885 "load balance settings.");
886 if (!parse_numeric_aggregate (cfile
, hba
, &hba_len
,
888 skip_to_rbrace (cfile
, 1);
889 dhcp_failover_state_dereference (&peer
, MDL
);
894 "HBA must be exactly 32 bytes.");
899 peer
-> hba
= dmalloc (32, MDL
);
901 dfree (peer
-> name
, MDL
);
904 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");
916 skip_to_rbrace (cfile
, 1);
917 dhcp_failover_state_dereference (&peer
, MDL
);
922 parse_warn (cfile
, "split must be < 256");
924 memset (hba
, 0, sizeof hba
);
925 for (i
= 0; i
< split
; i
++) {
927 hba
[i
/ 8] |= (1 << (i
& 7));
934 token
= next_token (&val
, (unsigned *)0, cfile
);
935 if (token
!= BALANCE
) {
936 parse_warn (cfile
, "expecting 'balance'");
938 skip_to_rbrace (cfile
, 1);
941 token
= next_token (&val
, (unsigned *)0, cfile
);
942 if (token
!= TOKEN_MAX
) {
943 parse_warn (cfile
, "expecting 'max'");
946 token
= next_token (&val
, (unsigned *)0, cfile
);
947 if (token
!= SECONDS
) {
948 parse_warn (cfile
, "expecting 'secs'");
951 token
= next_token (&val
, (unsigned *)0, cfile
);
952 if (token
!= NUMBER
) {
953 parse_warn (cfile
, "expecting number");
956 peer
-> load_balance_max_secs
= atoi (val
);
961 "invalid statement in peer declaration");
962 skip_to_rbrace (cfile
, 1);
963 dhcp_failover_state_dereference (&peer
, MDL
);
966 if (token
!= RBRACE
&& !parse_semi (cfile
)) {
967 skip_to_rbrace (cfile
, 1);
968 dhcp_failover_state_dereference (&peer
, MDL
);
971 } while (token
!= RBRACE
);
973 /* me.address can be null; the failover link initiate code tries to
974 * derive a reasonable address to use.
976 if (!peer
-> partner
.address
)
977 parse_warn (cfile
, "peer address may not be omitted");
979 /* XXX - when/if we get a port number assigned, just set as default */
980 if (!peer
-> me
.port
)
981 parse_warn (cfile
, "local port may not be omitted");
982 if (!peer
-> partner
.port
)
983 parse_warn (cfile
, "peer port may not be omitted");
985 if (peer
-> i_am
== primary
) {
988 "primary failover server must have hba or split.");
989 } else if (!peer
-> mclt
) {
991 "primary failover server must have mclt.");
994 if (!peer
-> me
.max_flying_updates
) {
995 peer
-> me
.max_flying_updates
= 100;
997 if (!peer
-> me
.max_response_delay
) {
998 peer
-> me
.max_response_delay
= 60;
1001 if (type
== SHARED_NET_DECL
) {
1002 group
-> shared_network
-> failover_peer
= peer
;
1005 /* Set the initial state. */
1006 if (peer
-> i_am
== primary
) {
1007 peer
-> me
.state
= recover
;
1008 peer
-> me
.stos
= cur_time
;
1009 peer
-> partner
.state
= unknown_state
;
1010 peer
-> partner
.stos
= cur_time
;
1012 peer
-> me
.state
= recover
;
1013 peer
-> me
.stos
= cur_time
;
1014 peer
-> partner
.state
= unknown_state
;
1015 peer
-> partner
.stos
= cur_time
;
1018 status
= enter_failover_peer (peer
);
1019 if (status
!= ISC_R_SUCCESS
)
1020 parse_warn (cfile
, "failover peer %s: %s",
1021 peer
-> name
, isc_result_totext (status
));
1022 dhcp_failover_state_dereference (&peer
, MDL
);
1025 void parse_failover_state_declaration (struct parse
*cfile
,
1026 dhcp_failover_state_t
*peer
)
1028 enum dhcp_token token
;
1031 dhcp_failover_state_t
*state
;
1032 dhcp_failover_config_t
*cp
;
1035 token
= next_token (&val
, (unsigned *)0, cfile
);
1036 if (token
!= PEER
) {
1037 parse_warn (cfile
, "expecting \"peer\"");
1038 skip_to_semi (cfile
);
1042 token
= next_token (&val
, (unsigned *)0, cfile
);
1043 if (is_identifier (token
) || token
== STRING
) {
1044 name
= dmalloc (strlen (val
) + 1, MDL
);
1046 log_fatal ("failover peer name %s: no memory",
1050 parse_warn (cfile
, "expecting failover peer name.");
1051 skip_to_semi (cfile
);
1055 /* See if there's a peer declaration by this name. */
1056 state
= (dhcp_failover_state_t
*)0;
1057 find_failover_peer (&state
, name
, MDL
);
1059 parse_warn (cfile
, "unknown failover peer: %s", name
);
1060 skip_to_semi (cfile
);
1064 token
= next_token (&val
, (unsigned *)0, cfile
);
1065 if (token
!= STATE
) {
1066 parse_warn (cfile
, "expecting 'state'");
1068 skip_to_semi (cfile
);
1072 state
= (dhcp_failover_state_t
*)0;
1073 dhcp_failover_state_reference (&state
, peer
, MDL
);
1075 token
= next_token (&val
, (unsigned *)0, cfile
);
1076 if (token
!= LBRACE
) {
1077 parse_warn (cfile
, "expecting left brace");
1079 skip_to_semi (cfile
);
1080 dhcp_failover_state_dereference (&state
, MDL
);
1084 token
= next_token (&val
, (unsigned *)0, cfile
);
1091 token
= next_token (&val
, (unsigned *)0, cfile
);
1092 if (token
!= STATE
) {
1093 parse_warn (cfile
, "expecting 'state'");
1096 parse_failover_state (cfile
,
1097 &cp
-> state
, &cp
-> stos
);
1101 cp
= &state
-> partner
;
1105 if (state
-> i_am
== primary
) {
1107 "mclt not valid for primary");
1110 token
= next_token (&val
, (unsigned *)0, cfile
);
1111 if (token
!= NUMBER
) {
1112 parse_warn (cfile
, "expecting a number.");
1115 state
-> mclt
= atoi (val
);
1120 parse_warn (cfile
, "expecting state setting.");
1122 skip_to_rbrace (cfile
, 1);
1123 dhcp_failover_state_dereference (&state
, MDL
);
1126 } while (token
!= RBRACE
);
1127 dhcp_failover_state_dereference (&state
, MDL
);
1130 void parse_failover_state (cfile
, state
, stos
)
1131 struct parse
*cfile
;
1132 enum failover_state
*state
;
1135 enum dhcp_token token
;
1137 enum failover_state state_in
;
1140 token
= next_token (&val
, (unsigned *)0, cfile
);
1143 state_in
= unknown_state
;
1147 state_in
= partner_down
;
1154 case COMMUNICATIONS_INTERRUPTED
:
1155 state_in
= communications_interrupted
;
1158 case RESOLUTION_INTERRUPTED
:
1159 state_in
= resolution_interrupted
;
1162 case POTENTIAL_CONFLICT
:
1163 state_in
= potential_conflict
;
1171 state_in
= recover_wait
;
1175 state_in
= recover_done
;
1179 state_in
= shut_down
;
1191 parse_warn (cfile
, "unknown failover state");
1192 skip_to_semi (cfile
);
1196 token
= next_token (&val
, (unsigned *)0, cfile
);
1197 if (token
== SEMI
) {
1201 parse_warn (cfile
, "expecting \"at\"");
1202 skip_to_semi (cfile
);
1206 stos_in
= parse_date (cfile
);
1211 /* Now that we've apparently gotten a clean parse, we
1212 can trust that this is a state that was fully committed to
1213 disk, so we can install it. */
1217 #endif /* defined (FAILOVER_PROTOCOL) */
1219 /* Permit_list_match returns 1 if every element of the permit list in lhs
1220 also appears in rhs. Note that this doesn't by itself mean that the
1221 two lists are equal - to check for equality, permit_list_match has to
1222 return 1 with (list1, list2) and with (list2, list1). */
1224 int permit_list_match (struct permit
*lhs
, struct permit
*rhs
)
1226 struct permit
*plp
, *prp
;
1233 for (plp
= lhs
; plp
; plp
= plp
-> next
) {
1235 for (prp
= rhs
; prp
; prp
= prp
-> next
) {
1236 if (prp
-> type
== plp
-> type
&&
1237 (prp
-> type
!= permit_class
||
1238 prp
-> class == plp
-> class)) {
1249 void parse_pool_statement (cfile
, group
, type
)
1250 struct parse
*cfile
;
1251 struct group
*group
;
1254 enum dhcp_token token
;
1257 struct pool
*pool
, **p
, *pp
;
1258 struct permit
*permit
;
1259 struct permit
**permit_head
;
1260 int declaration
= 0;
1261 isc_result_t status
;
1262 struct lease
*lpchain
= (struct lease
*)0, *lp
;
1264 pool
= (struct pool
*)0;
1265 status
= pool_allocate (&pool
, MDL
);
1266 if (status
!= ISC_R_SUCCESS
)
1267 log_fatal ("no memory for pool: %s",
1268 isc_result_totext (status
));
1270 if (type
== SUBNET_DECL
)
1271 shared_network_reference (&pool
-> shared_network
,
1272 group
-> subnet
-> shared_network
,
1275 shared_network_reference (&pool
-> shared_network
,
1276 group
-> shared_network
, MDL
);
1278 if (!clone_group (&pool
-> group
, pool
-> shared_network
-> group
, MDL
))
1279 log_fatal ("can't clone pool group.");
1281 #if defined (FAILOVER_PROTOCOL)
1282 /* Inherit the failover peer from the shared network. */
1283 if (pool
-> shared_network
-> failover_peer
)
1284 dhcp_failover_state_reference
1285 (&pool
-> failover_peer
,
1286 pool
-> shared_network
-> failover_peer
, MDL
);
1289 if (!parse_lbrace (cfile
)) {
1290 pool_dereference (&pool
, MDL
);
1295 token
= peek_token (&val
, (unsigned *)0, cfile
);
1298 next_token (&val
, (unsigned *)0, cfile
);
1299 token
= next_token (&val
, (unsigned *)0, cfile
);
1300 if (token
!= FAILOVER
||
1301 (token
= next_token (&val
, (unsigned *)0,
1304 "expecting \"failover peer\".");
1305 skip_to_semi (cfile
);
1308 #if defined (FAILOVER_PROTOCOL)
1309 if (pool
-> failover_peer
)
1310 dhcp_failover_state_dereference
1311 (&pool
-> failover_peer
, MDL
);
1315 #if defined (FAILOVER_PROTOCOL)
1317 next_token (&val
, (unsigned *)0, cfile
);
1318 token
= next_token (&val
, (unsigned *)0, cfile
);
1319 if (token
!= PEER
) {
1320 parse_warn (cfile
, "expecting 'peer'.");
1321 skip_to_semi (cfile
);
1324 token
= next_token (&val
, (unsigned *)0, cfile
);
1325 if (token
!= STRING
) {
1326 parse_warn (cfile
, "expecting string.");
1327 skip_to_semi (cfile
);
1330 if (pool
-> failover_peer
)
1331 dhcp_failover_state_dereference
1332 (&pool
-> failover_peer
, MDL
);
1333 status
= find_failover_peer (&pool
-> failover_peer
,
1335 if (status
!= ISC_R_SUCCESS
)
1337 "failover peer %s: %s", val
,
1338 isc_result_totext (status
));
1340 pool
-> failover_peer
-> pool_count
++;
1346 next_token (&val
, (unsigned *)0, cfile
);
1347 parse_address_range (cfile
, group
, type
,
1351 permit_head
= &pool
-> permit_list
;
1353 permit
= new_permit (MDL
);
1355 log_fatal ("no memory for permit");
1356 next_token (&val
, (unsigned *)0, cfile
);
1357 token
= next_token (&val
, (unsigned *)0, cfile
);
1360 permit
-> type
= permit_unknown_clients
;
1362 if (next_token (&val
, (unsigned *)0,
1363 cfile
) != CLIENTS
) {
1365 "expecting \"clients\"");
1366 skip_to_semi (cfile
);
1367 free_permit (permit
, MDL
);
1373 permit
-> type
= permit_known_clients
;
1376 case UNKNOWN_CLIENTS
:
1377 permit
-> type
= permit_unknown_clients
;
1381 permit
-> type
= permit_known_clients
;
1385 permit
-> type
= permit_authenticated_clients
;
1388 case UNAUTHENTICATED
:
1390 permit_unauthenticated_clients
;
1394 permit
-> type
= permit_all_clients
;
1399 permit
-> type
= permit_dynamic_bootp_clients
;
1400 if (next_token (&val
, (unsigned *)0,
1401 cfile
) != TOKEN_BOOTP
) {
1403 "expecting \"bootp\"");
1404 skip_to_semi (cfile
);
1405 free_permit (permit
, MDL
);
1411 if (next_token (&val
, (unsigned *)0,
1413 parse_warn (cfile
, "expecting \"of\"");
1414 skip_to_semi (cfile
);
1415 free_permit (permit
, MDL
);
1418 if (next_token (&val
, (unsigned *)0,
1421 "expecting class name.");
1422 skip_to_semi (cfile
);
1423 free_permit (permit
, MDL
);
1426 permit
-> type
= permit_class
;
1427 permit
-> class = (struct class *)0;
1428 find_class (&permit
-> class, val
, MDL
);
1429 if (!permit
-> class)
1431 "no such class: %s", val
);
1435 parse_warn (cfile
, "expecting permit type.");
1436 skip_to_semi (cfile
);
1439 while (*permit_head
)
1440 permit_head
= &((*permit_head
) -> next
);
1441 *permit_head
= permit
;
1446 permit_head
= &pool
-> prohibit_list
;
1450 next_token (&val
, (unsigned *)0, cfile
);
1455 declaration
= parse_statement (cfile
, pool
-> group
,
1457 (struct host_decl
*)0,
1463 #if defined (FAILOVER_PROTOCOL)
1464 /* We can't do failover on a pool that supports dynamic bootp,
1465 because BOOTP doesn't support leases, and failover absolutely
1466 depends on lease timing. */
1467 if (pool
-> failover_peer
) {
1468 /* This search order matches the search orders later in
1469 * execution - deny first, if not denied, check permit
1470 * list. A dynamic bootp client may be known or unknown,
1471 * it may belong to a member of a class, but it definitely
1472 * will not be authenticated since that requires DHCP
1473 * to work. So a dynamic bootp client is definitely not
1474 * an authenticated client, and we can't say for sure about
1477 * So we nag the user.
1479 for (permit
= pool
-> prohibit_list
; permit
;
1480 permit
= permit
-> next
) {
1481 if (permit
-> type
== permit_dynamic_bootp_clients
||
1482 permit
-> type
== permit_unauthenticated_clients
||
1483 permit
-> type
== permit_all_clients
)
1487 permit
= pool
-> permit_list
;
1491 permit_authenticated_clients
) {
1493 "pools with failover peers %s",
1494 "may not permit dynamic bootp.");
1495 log_error ("Either write a \"%s\" %s",
1497 "statement and use disjoint");
1498 log_error ("pools, or%s (%s) %s",
1499 " don't permit dynamic bootp",
1500 "\"deny dynamic bootp clients;\"",
1502 log_error ("This is a protocol,%s %s",
1503 " limitation, not an ISC DHCP",
1505 log_error ("please don't request an %s",
1506 "enhancement or ask why this is.");
1511 permit
= permit
-> next
;
1515 #endif /* FAILOVER_PROTOCOL */
1517 /* See if there's already a pool into which we can merge this one. */
1518 for (pp
= pool
-> shared_network
-> pools
; pp
; pp
= pp
-> next
) {
1521 if (pp
-> group
-> statements
!= pool
-> group
-> statements
)
1523 #if defined (FAILOVER_PROTOCOL)
1524 if (pool
-> failover_peer
!= pp
-> failover_peer
)
1527 if (!permit_list_match (pp
-> permit_list
,
1528 pool
-> permit_list
) ||
1529 !permit_list_match (pool
-> permit_list
,
1530 pp
-> permit_list
) ||
1531 !permit_list_match (pp
-> prohibit_list
,
1532 pool
-> prohibit_list
) ||
1533 !permit_list_match (pool
-> prohibit_list
,
1534 pp
-> prohibit_list
))
1537 /* Okay, we can merge these two pools. All we have to
1538 do is fix up the leases, which all point to their pool. */
1539 for (lp
= lpchain
; lp
; lp
= lp
-> next
) {
1540 pool_dereference (&lp
-> pool
, MDL
);
1541 pool_reference (&lp
-> pool
, pp
, MDL
);
1546 /* If we didn't succeed in merging this pool into another, put
1549 p
= &pool
-> shared_network
-> pools
;
1550 for (; *p
; p
= &((*p
) -> next
))
1552 pool_reference (p
, pool
, MDL
);
1555 /* Don't allow a pool declaration with no addresses, since it is
1556 probably a configuration error. */
1558 parse_warn (cfile
, "Pool declaration with no address range.");
1559 log_error ("Pool declarations must always contain at least");
1560 log_error ("one range statement.");
1563 /* Dereference the lease chain. */
1564 lp
= (struct lease
*)0;
1566 lease_reference (&lp
, lpchain
, MDL
);
1567 lease_dereference (&lpchain
, MDL
);
1569 lease_reference (&lpchain
, lp
-> next
, MDL
);
1570 lease_dereference (&lp
-> next
, MDL
);
1571 lease_dereference (&lp
, MDL
);
1574 pool_dereference (&pool
, MDL
);
1577 /* boolean :== ON SEMI | OFF SEMI | TRUE SEMI | FALSE SEMI */
1579 int parse_boolean (cfile
)
1580 struct parse
*cfile
;
1582 enum dhcp_token token
;
1586 token
= next_token (&val
, (unsigned *)0, cfile
);
1587 if (!strcasecmp (val
, "true")
1588 || !strcasecmp (val
, "on"))
1590 else if (!strcasecmp (val
, "false")
1591 || !strcasecmp (val
, "off"))
1595 "boolean value (true/false/on/off) expected");
1596 skip_to_semi (cfile
);
1603 /* Expect a left brace; if there isn't one, skip over the rest of the
1604 statement and return zero; otherwise, return 1. */
1606 int parse_lbrace (cfile
)
1607 struct parse
*cfile
;
1609 enum dhcp_token token
;
1612 token
= next_token (&val
, (unsigned *)0, cfile
);
1613 if (token
!= LBRACE
) {
1614 parse_warn (cfile
, "expecting left brace.");
1615 skip_to_semi (cfile
);
1622 /* host-declaration :== hostname RBRACE parameters declarations LBRACE */
1624 void parse_host_declaration (cfile
, group
)
1625 struct parse
*cfile
;
1626 struct group
*group
;
1629 enum dhcp_token token
;
1630 struct host_decl
*host
;
1632 int declaration
= 0;
1635 isc_result_t status
;
1637 name
= parse_host_name (cfile
);
1639 parse_warn (cfile
, "expecting a name for host declaration.");
1640 skip_to_semi (cfile
);
1644 host
= (struct host_decl
*)0;
1645 status
= host_allocate (&host
, MDL
);
1646 if (status
!= ISC_R_SUCCESS
)
1647 log_fatal ("can't allocate host decl struct %s: %s",
1648 name
, isc_result_totext (status
));
1649 host
-> name
= name
;
1650 if (!clone_group (&host
-> group
, group
, MDL
)) {
1651 log_fatal ("can't clone group for host %s", name
);
1653 host_dereference (&host
, MDL
);
1657 if (!parse_lbrace (cfile
))
1661 token
= peek_token (&val
, (unsigned *)0, cfile
);
1662 if (token
== RBRACE
) {
1663 token
= next_token (&val
, (unsigned *)0, cfile
);
1666 if (token
== END_OF_FILE
) {
1667 token
= next_token (&val
, (unsigned *)0, cfile
);
1668 parse_warn (cfile
, "unexpected end of file");
1671 /* If the host declaration was created by the server,
1672 remember to save it. */
1673 if (token
== DYNAMIC
) {
1675 token
= next_token (&val
, (unsigned *)0, cfile
);
1676 if (!parse_semi (cfile
))
1680 /* If the host declaration was created by the server,
1681 remember to save it. */
1682 if (token
== TOKEN_DELETED
) {
1684 token
= next_token (&val
, (unsigned *)0, cfile
);
1685 if (!parse_semi (cfile
))
1690 if (token
== GROUP
) {
1691 struct group_object
*go
;
1692 token
= next_token (&val
, (unsigned *)0, cfile
);
1693 token
= next_token (&val
, (unsigned *)0, cfile
);
1694 if (token
!= STRING
&& !is_identifier (token
)) {
1696 "expecting string or identifier.");
1697 skip_to_rbrace (cfile
, 1);
1700 go
= (struct group_object
*)0;
1701 if (!group_hash_lookup (&go
, group_name_hash
,
1702 val
, strlen (val
), MDL
)) {
1703 parse_warn (cfile
, "unknown group %s in host %s",
1706 if (host
-> named_group
)
1707 group_object_dereference
1708 (&host
-> named_group
, MDL
);
1709 group_object_reference (&host
-> named_group
,
1711 group_object_dereference (&go
, MDL
);
1713 if (!parse_semi (cfile
))
1720 unsigned char *t
= 0;
1723 token
= next_token (&val
, (unsigned *)0, cfile
);
1724 data_string_forget (&host
-> client_identifier
, MDL
);
1726 /* See if it's a string or a cshl. */
1727 token
= peek_token (&val
, (unsigned *)0, cfile
);
1728 if (token
== STRING
) {
1729 token
= next_token (&val
, &len
, cfile
);
1731 host
-> client_identifier
.terminated
= 1;
1734 t
= parse_numeric_aggregate
1736 (unsigned char *)0, &len
, ':', 16, 8);
1739 "expecting hex list.");
1740 skip_to_semi (cfile
);
1742 s
= (const char *)t
;
1744 if (!buffer_allocate
1745 (&host
-> client_identifier
.buffer
,
1746 len
+ host
-> client_identifier
.terminated
, MDL
))
1747 log_fatal ("no memory for uid for host %s.",
1749 host
-> client_identifier
.data
=
1750 host
-> client_identifier
.buffer
-> data
;
1751 host
-> client_identifier
.len
= len
;
1752 memcpy (host
-> client_identifier
.buffer
-> data
, s
,
1753 len
+ host
-> client_identifier
.terminated
);
1757 if (!parse_semi (cfile
))
1761 declaration
= parse_statement (cfile
, host
-> group
,
1767 struct host_decl
*hp
= (struct host_decl
*)0;
1768 if (host_hash_lookup (&hp
, host_name_hash
,
1769 (unsigned char *)host
-> name
,
1770 strlen (host
-> name
), MDL
)) {
1771 delete_host (hp
, 0);
1772 host_dereference (&hp
, MDL
);
1775 if (host
-> named_group
&& host
-> named_group
-> group
) {
1776 if (host
-> group
-> statements
||
1777 (host
-> group
-> authoritative
!=
1778 host
-> named_group
-> group
-> authoritative
)) {
1779 if (host
-> group
-> next
)
1780 group_dereference (&host
-> group
-> next
,
1782 group_reference (&host
-> group
-> next
,
1783 host
-> named_group
-> group
,
1786 group_dereference (&host
-> group
, MDL
);
1787 group_reference (&host
-> group
,
1788 host
-> named_group
-> group
,
1794 host
-> flags
|= HOST_DECL_DYNAMIC
;
1796 host
-> flags
|= HOST_DECL_STATIC
;
1798 status
= enter_host (host
, dynamicp
, 0);
1799 if (status
!= ISC_R_SUCCESS
)
1800 parse_warn (cfile
, "host %s: %s", host
-> name
,
1801 isc_result_totext (status
));
1803 host_dereference (&host
, MDL
);
1806 /* class-declaration :== STRING LBRACE parameters declarations RBRACE
1809 int parse_class_declaration (cp
, cfile
, group
, type
)
1811 struct parse
*cfile
;
1812 struct group
*group
;
1816 enum dhcp_token token
;
1817 struct class *class = (struct class *)0, *pc
= (struct class *)0;
1818 int declaration
= 0;
1820 struct data_string data
;
1823 struct executable_statement
*stmt
= (struct executable_statement
*)0;
1824 struct expression
*expr
;
1826 isc_result_t status
= ISC_R_FAILURE
;
1828 token
= next_token (&val
, (unsigned *)0, cfile
);
1829 if (token
!= STRING
) {
1830 parse_warn (cfile
, "Expecting class name");
1831 skip_to_semi (cfile
);
1835 /* See if there's already a class with the specified name. */
1836 find_class (&pc
, val
, MDL
);
1838 /* If this isn't a subclass, we're updating an existing class. */
1839 if (pc
&& type
!= 0 && type
!= 1 && type
!= 3) {
1840 class_reference (&class, pc
, MDL
);
1842 class_dereference (&pc
, MDL
);
1845 /* If this _is_ a subclass, there _must_ be a class with the
1847 if (!pc
&& (type
== 0 || type
== 1 || type
== 3)) {
1848 parse_warn (cfile
, "no class named %s", val
);
1849 skip_to_semi (cfile
);
1853 /* The old vendor-class and user-class declarations had an implicit
1854 match. We don't do the implicit match anymore. Instead, for
1855 backward compatibility, we have an implicit-vendor-class and an
1856 implicit-user-class. vendor-class and user-class declarations
1857 are turned into subclasses of the implicit classes, and the
1858 submatch expression of the implicit classes extracts the contents of
1859 the vendor class or user class. */
1860 if (type
== 0 || type
== 1) {
1861 data
.len
= strlen (val
);
1862 data
.buffer
= (struct buffer
*)0;
1863 if (!buffer_allocate (&data
.buffer
, data
.len
+ 1, MDL
))
1864 log_fatal ("no memory for class name.");
1865 data
.data
= &data
.buffer
-> data
[0];
1866 data
.terminated
= 1;
1868 tname
= type
? "implicit-vendor-class" : "implicit-user-class";
1869 } else if (type
== 2) {
1872 tname
= (const char *)0;
1876 name
= dmalloc (strlen (tname
) + 1, MDL
);
1878 log_fatal ("No memory for class name %s.", tname
);
1883 /* If this is a straight subclass, parse the hash string. */
1885 token
= peek_token (&val
, (unsigned *)0, cfile
);
1886 if (token
== STRING
) {
1887 token
= next_token (&val
, &data
.len
, cfile
);
1888 data
.buffer
= (struct buffer
*)0;
1889 if (!buffer_allocate (&data
.buffer
,
1890 data
.len
+ 1, MDL
)) {
1892 class_dereference (&pc
, MDL
);
1896 data
.terminated
= 1;
1897 data
.data
= &data
.buffer
-> data
[0];
1898 memcpy ((char *)data
.buffer
-> data
, val
,
1900 } else if (token
== NUMBER_OR_NAME
|| token
== NUMBER
) {
1901 memset (&data
, 0, sizeof data
);
1902 if (!parse_cshl (&data
, cfile
)) {
1903 class_dereference (&pc
, MDL
);
1907 parse_warn (cfile
, "Expecting string or hex list.");
1909 class_dereference (&pc
, MDL
);
1914 /* See if there's already a class in the hash table matching the
1916 if (type
== 0 || type
== 1 || type
== 3)
1917 class_hash_lookup (&class, pc
-> hash
,
1918 (const char *)data
.data
, data
.len
, MDL
);
1920 /* If we didn't find an existing class, allocate a new one. */
1922 /* Allocate the class structure... */
1923 status
= class_allocate (&class, MDL
);
1925 group_reference (&class -> group
, pc
-> group
, MDL
);
1926 class_reference (&class -> superclass
, pc
, MDL
);
1927 class -> lease_limit
= pc
-> lease_limit
;
1928 if (class -> lease_limit
) {
1929 class -> billed_leases
=
1930 dmalloc (class -> lease_limit
*
1931 sizeof (struct lease
*), MDL
);
1932 if (!class -> billed_leases
)
1933 log_fatal ("no memory for billing");
1934 memset (class -> billed_leases
, 0,
1935 (class -> lease_limit
*
1936 sizeof class -> billed_leases
));
1938 data_string_copy (&class -> hash_string
, &data
, MDL
);
1940 !class_new_hash (&pc
-> hash
, 0, MDL
))
1941 log_fatal ("No memory for subclass hash.");
1942 class_hash_add (pc
-> hash
,
1943 (const char *)class -> hash_string
.data
,
1944 class -> hash_string
.len
,
1945 (void *)class, MDL
);
1947 if (!clone_group (&class -> group
, group
, MDL
))
1948 log_fatal ("no memory to clone class group.");
1951 /* If this is an implicit vendor or user class, add a
1952 statement that causes the vendor or user class ID to
1953 be sent back in the reply. */
1954 if (type
== 0 || type
== 1) {
1955 stmt
= (struct executable_statement
*)0;
1956 if (!executable_statement_allocate (&stmt
, MDL
))
1957 log_fatal ("no memory for class statement.");
1958 stmt
-> op
= supersede_option_statement
;
1959 if (option_cache_allocate (&stmt
-> data
.option
,
1961 stmt
-> data
.option
-> data
= data
;
1962 stmt
-> data
.option
-> option
=
1963 dhcp_universe
.options
1965 ? DHO_VENDOR_CLASS_IDENTIFIER
1968 class -> statements
= stmt
;
1971 /* Save the name, if there is one. */
1972 class -> name
= name
;
1975 if (type
== 0 || type
== 1 || type
== 3)
1976 data_string_forget (&data
, MDL
);
1978 /* Spawned classes don't have to have their own settings. */
1979 if (class -> superclass
) {
1980 token
= peek_token (&val
, (unsigned *)0, cfile
);
1981 if (token
== SEMI
) {
1982 next_token (&val
, (unsigned *)0, cfile
);
1984 status
= class_reference (cp
, class, MDL
);
1985 class_dereference (&class, MDL
);
1987 class_dereference (&pc
, MDL
);
1988 return cp
? (status
== ISC_R_SUCCESS
) : 1;
1990 /* Give the subclass its own group. */
1991 if (!clone_group (&class -> group
, class -> group
, MDL
))
1992 log_fatal ("can't clone class group.");
1996 if (!parse_lbrace (cfile
)) {
1997 class_dereference (&class, MDL
);
1999 class_dereference (&pc
, MDL
);
2004 token
= peek_token (&val
, (unsigned *)0, cfile
);
2005 if (token
== RBRACE
) {
2006 token
= next_token (&val
, (unsigned *)0, cfile
);
2008 } else if (token
== END_OF_FILE
) {
2009 token
= next_token (&val
, (unsigned *)0, cfile
);
2010 parse_warn (cfile
, "unexpected end of file");
2012 } else if (token
== MATCH
) {
2015 "invalid match in subclass.");
2016 skip_to_semi (cfile
);
2019 token
= next_token (&val
, (unsigned *)0, cfile
);
2020 token
= peek_token (&val
, (unsigned *)0, cfile
);
2023 if (class -> expr
) {
2024 parse_warn (cfile
, "can't override match.");
2025 skip_to_semi (cfile
);
2028 token
= next_token (&val
, (unsigned *)0, cfile
);
2029 if (!parse_boolean_expression (&class -> expr
, cfile
,
2033 "expecting boolean expr.");
2034 skip_to_semi (cfile
);
2037 #if defined (DEBUG_EXPRESSION_PARSE)
2038 print_expression ("class match",
2043 } else if (token
== SPAWN
) {
2046 "invalid spawn in subclass.");
2047 skip_to_semi (cfile
);
2050 token
= next_token (&val
, (unsigned *)0, cfile
);
2051 class -> spawning
= 1;
2052 token
= next_token (&val
, (unsigned *)0, cfile
);
2053 if (token
!= WITH
) {
2055 "expecting with after spawn");
2056 skip_to_semi (cfile
);
2060 if (class -> submatch
) {
2062 "can't override existing %s.",
2064 skip_to_semi (cfile
);
2067 if (!parse_data_expression (&class -> submatch
,
2071 "expecting data expr.");
2072 skip_to_semi (cfile
);
2075 #if defined (DEBUG_EXPRESSION_PARSE)
2076 print_expression ("class submatch",
2081 } else if (token
== LEASE
) {
2082 next_token (&val
, (unsigned *)0, cfile
);
2083 token
= next_token (&val
, (unsigned *)0, cfile
);
2084 if (token
!= LIMIT
) {
2085 parse_warn (cfile
, "expecting \"limit\"");
2087 skip_to_semi (cfile
);
2090 token
= next_token (&val
, (unsigned *)0, cfile
);
2091 if (token
!= NUMBER
) {
2092 parse_warn (cfile
, "expecting a number");
2094 skip_to_semi (cfile
);
2097 class -> lease_limit
= atoi (val
);
2098 class -> billed_leases
=
2099 dmalloc (class -> lease_limit
*
2100 sizeof (struct lease
*), MDL
);
2101 if (!class -> billed_leases
)
2102 log_fatal ("no memory for billed leases.");
2103 memset (class -> billed_leases
, 0,
2104 (class -> lease_limit
*
2105 sizeof class -> billed_leases
));
2106 have_billing_classes
= 1;
2109 declaration
= parse_statement (cfile
, class -> group
,
2111 (struct host_decl
*)0,
2115 if (type
== 2 && new) {
2116 if (!collections
-> classes
)
2117 class_reference (&collections
-> classes
, class, MDL
);
2120 for (c
= collections
-> classes
;
2121 c
-> nic
; c
= c
-> nic
)
2123 class_reference (&c
-> nic
, class, MDL
);
2127 status
= class_reference (cp
, class, MDL
);
2128 class_dereference (&class, MDL
);
2130 class_dereference (&pc
, MDL
);
2131 return cp
? (status
== ISC_R_SUCCESS
) : 1;
2134 /* shared-network-declaration :==
2135 hostname LBRACE declarations parameters RBRACE */
2137 void parse_shared_net_declaration (cfile
, group
)
2138 struct parse
*cfile
;
2139 struct group
*group
;
2142 enum dhcp_token token
;
2143 struct shared_network
*share
;
2145 int declaration
= 0;
2146 isc_result_t status
;
2148 share
= (struct shared_network
*)0;
2149 status
= shared_network_allocate (&share
, MDL
);
2150 if (status
!= ISC_R_SUCCESS
)
2151 log_fatal ("Can't allocate shared subnet: %s",
2152 isc_result_totext (status
));
2153 clone_group (&share
-> group
, group
, MDL
);
2154 shared_network_reference (&share
-> group
-> shared_network
,
2157 /* Get the name of the shared network... */
2158 token
= peek_token (&val
, (unsigned *)0, cfile
);
2159 if (token
== STRING
) {
2160 token
= next_token (&val
, (unsigned *)0, cfile
);
2163 parse_warn (cfile
, "zero-length shared network name");
2164 val
= "<no-name-given>";
2166 name
= dmalloc (strlen (val
) + 1, MDL
);
2168 log_fatal ("no memory for shared network name");
2171 name
= parse_host_name (cfile
);
2174 "expecting a name for shared-network");
2175 skip_to_semi (cfile
);
2176 shared_network_dereference (&share
, MDL
);
2180 share
-> name
= name
;
2182 if (!parse_lbrace (cfile
)) {
2183 shared_network_dereference (&share
, MDL
);
2188 token
= peek_token (&val
, (unsigned *)0, cfile
);
2189 if (token
== RBRACE
) {
2190 token
= next_token (&val
, (unsigned *)0, cfile
);
2191 if (!share
-> subnets
)
2193 "empty shared-network decl");
2195 enter_shared_network (share
);
2196 shared_network_dereference (&share
, MDL
);
2198 } else if (token
== END_OF_FILE
) {
2199 token
= next_token (&val
, (unsigned *)0, cfile
);
2200 parse_warn (cfile
, "unexpected end of file");
2202 } else if (token
== INTERFACE
) {
2203 token
= next_token (&val
, (unsigned *)0, cfile
);
2204 token
= next_token (&val
, (unsigned *)0, cfile
);
2205 new_shared_network_interface (cfile
, share
, val
);
2206 if (!parse_semi (cfile
))
2211 declaration
= parse_statement (cfile
, share
-> group
,
2213 (struct host_decl
*)0,
2216 shared_network_dereference (&share
, MDL
);
2219 /* subnet-declaration :==
2220 net NETMASK netmask RBRACE parameters declarations LBRACE */
2222 void parse_subnet_declaration (cfile
, share
)
2223 struct parse
*cfile
;
2224 struct shared_network
*share
;
2227 enum dhcp_token token
;
2228 struct subnet
*subnet
, *t
, *u
;
2230 unsigned char addr
[4];
2231 unsigned len
= sizeof addr
;
2232 int declaration
= 0;
2233 struct interface_info
*ip
;
2234 isc_result_t status
;
2236 subnet
= (struct subnet
*)0;
2237 status
= subnet_allocate (&subnet
, MDL
);
2238 if (status
!= ISC_R_SUCCESS
)
2239 log_fatal ("Allocation of new subnet failed: %s",
2240 isc_result_totext (status
));
2241 shared_network_reference (&subnet
-> shared_network
, share
, MDL
);
2242 if (!clone_group (&subnet
-> group
, share
-> group
, MDL
))
2243 log_fatal ("allocation of group for new subnet failed.");
2244 subnet_reference (&subnet
-> group
-> subnet
, subnet
, MDL
);
2246 /* Get the network number... */
2247 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2248 subnet_dereference (&subnet
, MDL
);
2251 memcpy (iaddr
.iabuf
, addr
, len
);
2253 subnet
-> net
= iaddr
;
2255 token
= next_token (&val
, (unsigned *)0, cfile
);
2256 if (token
!= NETMASK
) {
2257 parse_warn (cfile
, "Expecting netmask");
2258 skip_to_semi (cfile
);
2262 /* Get the netmask... */
2263 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2264 subnet_dereference (&subnet
, MDL
);
2267 memcpy (iaddr
.iabuf
, addr
, len
);
2269 subnet
-> netmask
= iaddr
;
2271 /* Validate the network number/netmask pair. */
2272 if (host_addr (subnet
-> net
, subnet
-> netmask
)) {
2275 maskstr
= strdup (piaddr (subnet
-> netmask
));
2277 "subnet %s netmask %s: bad subnet number/mask combination.",
2278 piaddr (subnet
-> net
), maskstr
);
2280 subnet_dereference (&subnet
, MDL
);
2281 skip_to_semi (cfile
);
2285 enter_subnet (subnet
);
2287 if (!parse_lbrace (cfile
)) {
2288 subnet_dereference (&subnet
, MDL
);
2293 token
= peek_token (&val
, (unsigned *)0, cfile
);
2294 if (token
== RBRACE
) {
2295 token
= next_token (&val
, (unsigned *)0, cfile
);
2297 } else if (token
== END_OF_FILE
) {
2298 token
= next_token (&val
, (unsigned *)0, cfile
);
2299 parse_warn (cfile
, "unexpected end of file");
2301 } else if (token
== INTERFACE
) {
2302 token
= next_token (&val
, (unsigned *)0, cfile
);
2303 token
= next_token (&val
, (unsigned *)0, cfile
);
2304 new_shared_network_interface (cfile
, share
, val
);
2305 if (!parse_semi (cfile
))
2309 declaration
= parse_statement (cfile
, subnet
-> group
,
2311 (struct host_decl
*)0,
2315 /* Add the subnet to the list of subnets in this shared net. */
2316 if (!share
-> subnets
)
2317 subnet_reference (&share
-> subnets
, subnet
, MDL
);
2319 u
= (struct subnet
*)0;
2320 for (t
= share
-> subnets
;
2321 t
-> next_sibling
; t
= t
-> next_sibling
) {
2322 if (subnet_inner_than (subnet
, t
, 0)) {
2323 subnet_reference (&subnet
-> next_sibling
,
2326 subnet_dereference (&u
-> next_sibling
,
2328 subnet_reference (&u
-> next_sibling
,
2331 subnet_dereference (&share
-> subnets
,
2333 subnet_reference (&share
-> subnets
,
2336 subnet_dereference (&subnet
, MDL
);
2341 subnet_reference (&t
-> next_sibling
, subnet
, MDL
);
2343 subnet_dereference (&subnet
, MDL
);
2346 /* group-declaration :== RBRACE parameters declarations LBRACE */
2348 void parse_group_declaration (cfile
, group
)
2349 struct parse
*cfile
;
2350 struct group
*group
;
2353 enum dhcp_token token
;
2355 int declaration
= 0;
2356 struct group_object
*t
;
2357 isc_result_t status
;
2363 g
= (struct group
*)0;
2364 if (!clone_group (&g
, group
, MDL
))
2365 log_fatal ("no memory for explicit group.");
2367 token
= peek_token (&val
, (unsigned *)0, cfile
);
2368 if (is_identifier (token
) || token
== STRING
) {
2369 next_token (&val
, (unsigned *)0, cfile
);
2371 name
= dmalloc (strlen (val
) + 1, MDL
);
2373 log_fatal ("no memory for group decl name %s", val
);
2377 if (!parse_lbrace (cfile
)) {
2378 group_dereference (&g
, MDL
);
2383 token
= peek_token (&val
, (unsigned *)0, cfile
);
2384 if (token
== RBRACE
) {
2385 token
= next_token (&val
, (unsigned *)0, cfile
);
2387 } else if (token
== END_OF_FILE
) {
2388 token
= next_token (&val
, (unsigned *)0, cfile
);
2389 parse_warn (cfile
, "unexpected end of file");
2391 } else if (token
== TOKEN_DELETED
) {
2392 token
= next_token (&val
, (unsigned *)0, cfile
);
2395 } else if (token
== DYNAMIC
) {
2396 token
= next_token (&val
, (unsigned *)0, cfile
);
2399 } else if (token
== _STATIC
) {
2400 token
= next_token (&val
, (unsigned *)0, cfile
);
2404 declaration
= parse_statement (cfile
, g
, GROUP_DECL
,
2405 (struct host_decl
*)0,
2411 if (group_name_hash
) {
2412 t
= (struct group_object
*)0;
2413 if (group_hash_lookup (&t
, group_name_hash
,
2415 strlen (name
), MDL
)) {
2416 delete_group (t
, 0);
2420 t
= (struct group_object
*)0;
2421 status
= group_object_allocate (&t
, MDL
);
2422 if (status
!= ISC_R_SUCCESS
)
2423 log_fatal ("no memory for group decl %s: %s",
2424 val
, isc_result_totext (status
));
2425 group_reference (&t
-> group
, g
, MDL
);
2427 t
-> flags
= ((staticp
? GROUP_OBJECT_STATIC
: 0) |
2428 (dynamicp
? GROUP_OBJECT_DYNAMIC
: 0) |
2429 (deletedp
? GROUP_OBJECT_DELETED
: 0));
2430 supersede_group (t
, 0);
2433 group_object_dereference (&t
, MDL
);
2437 /* fixed-addr-parameter :== ip-addrs-or-hostnames SEMI
2438 ip-addrs-or-hostnames :== ip-addr-or-hostname
2439 | ip-addrs-or-hostnames ip-addr-or-hostname */
2441 int parse_fixed_addr_param (oc
, cfile
)
2442 struct option_cache
**oc
;
2443 struct parse
*cfile
;
2446 enum dhcp_token token
;
2447 struct expression
*expr
= (struct expression
*)0;
2448 struct expression
*tmp
, *new;
2452 tmp
= (struct expression
*)0;
2453 if (parse_ip_addr_or_hostname (&tmp
, cfile
, 1)) {
2455 new = (struct expression
*)0;
2456 status
= make_concat (&new, expr
, tmp
);
2457 expression_dereference (&expr
, MDL
);
2458 expression_dereference (&tmp
, MDL
);
2466 expression_dereference (&expr
, MDL
);
2469 token
= peek_token (&val
, (unsigned *)0, cfile
);
2471 token
= next_token (&val
, (unsigned *)0, cfile
);
2472 } while (token
== COMMA
);
2474 if (!parse_semi (cfile
)) {
2476 expression_dereference (&expr
, MDL
);
2479 status
= option_cache (oc
, (struct data_string
*)0, expr
,
2480 (struct option
*)0, MDL
);
2481 expression_dereference (&expr
, MDL
);
2485 /* timestamp :== date
2487 Timestamps are actually not used in dhcpd.conf, which is a static file,
2488 but rather in the database file and the journal file. (Okay, actually
2489 they're not even used there yet). */
2491 TIME
parse_timestamp (cfile
)
2492 struct parse
*cfile
;
2496 rv
= parse_date (cfile
);
2500 /* lease_declaration :== LEASE ip_address LBRACE lease_parameters RBRACE
2502 lease_parameters :== <nil>
2504 | lease_parameters lease_parameter
2506 lease_parameter :== STARTS date
2509 | HARDWARE hardware-parameter
2510 | UID hex_numbers SEMI
2511 | HOSTNAME hostname SEMI
2512 | CLIENT_HOSTNAME hostname SEMI
2513 | CLASS identifier SEMI
2514 | DYNAMIC_BOOTP SEMI */
2516 int parse_lease_declaration (struct lease
**lp
, struct parse
*cfile
)
2519 enum dhcp_token token
;
2520 unsigned char addr
[4];
2521 unsigned len
= sizeof addr
;
2525 struct lease
*lease
;
2526 struct executable_statement
*on
;
2527 struct expression
*exp
;
2528 struct data_string ds
;
2532 int noequal
, newbinding
;
2533 struct binding
*binding
;
2534 isc_result_t status
;
2535 struct option_cache
*oc
;
2537 binding_state_t new_state
;
2538 unsigned buflen
= 0;
2539 struct class *class;
2541 lease
= (struct lease
*)0;
2542 status
= lease_allocate (&lease
, MDL
);
2543 if (status
!= ISC_R_SUCCESS
)
2546 /* Get the address for which the lease has been issued. */
2547 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8)) {
2548 lease_dereference (&lease
, MDL
);
2551 memcpy (lease
-> ip_addr
.iabuf
, addr
, len
);
2552 lease
-> ip_addr
.len
= len
;
2554 if (!parse_lbrace (cfile
)) {
2555 lease_dereference (&lease
, MDL
);
2560 token
= next_token (&val
, (unsigned *)0, cfile
);
2561 if (token
== RBRACE
)
2563 else if (token
== END_OF_FILE
) {
2564 parse_warn (cfile
, "unexpected end of file");
2567 strncpy (tbuf
, val
, sizeof tbuf
);
2568 tbuf
[(sizeof tbuf
) - 1] = 0;
2570 /* Parse any of the times associated with the lease. */
2578 t
= parse_date (cfile
);
2582 lease
-> starts
= t
;
2592 lease
-> timestamp
= t
;
2610 default: /* for gcc, we'll never get here. */
2611 log_fatal ("Impossible error at %s:%d.", MDL
);
2616 /* Colon-seperated hexadecimal octets... */
2619 token
= peek_token (&val
, (unsigned *)0, cfile
);
2620 if (token
== STRING
) {
2621 unsigned char *tuid
;
2622 token
= next_token (&val
, &buflen
, cfile
);
2623 if (buflen
< sizeof lease
-> uid_buf
) {
2624 tuid
= lease
-> uid_buf
;
2626 sizeof lease
-> uid_buf
;
2628 tuid
= ((unsigned char *)
2629 dmalloc (buflen
, MDL
));
2631 log_error ("no space for uid");
2632 lease_dereference (&lease
,
2636 lease
-> uid_max
= buflen
;
2638 lease
-> uid_len
= buflen
;
2639 memcpy (tuid
, val
, lease
-> uid_len
);
2640 lease
-> uid
= tuid
;
2643 lease
-> uid
= (parse_numeric_aggregate
2644 (cfile
, (unsigned char *)0,
2645 &buflen
, ':', 16, 8));
2646 if (!lease
-> uid
) {
2647 lease_dereference (&lease
, MDL
);
2650 lease
-> uid_len
= buflen
;
2651 lease
-> uid_max
= buflen
;
2652 if (lease
-> uid_len
== 0) {
2653 lease
-> uid
= (unsigned char *)0;
2654 parse_warn (cfile
, "zero-length uid");
2661 if (!lease
-> uid
) {
2662 log_fatal ("No memory for lease uid");
2668 token
= next_token (&val
, (unsigned *)0, cfile
);
2669 if (!is_identifier (token
)) {
2671 skip_to_rbrace (cfile
, 1);
2672 lease_dereference (&lease
, MDL
);
2676 /* for now, we aren't using this. */
2681 parse_hardware_param (cfile
,
2682 &lease
-> hardware_addr
);
2687 lease
-> flags
|= BOOTP_LEASE
;
2691 case TOKEN_ABANDONED
:
2693 lease
-> binding_state
= FTS_ABANDONED
;
2694 lease
-> next_binding_state
= FTS_ABANDONED
;
2700 token
= next_token (&val
, (unsigned *)0, cfile
);
2701 if (token
!= BINDING
) {
2702 parse_warn (cfile
, "expecting 'binding'");
2703 skip_to_semi (cfile
);
2706 goto do_binding_state
;
2712 token
= next_token (&val
, (unsigned *)0, cfile
);
2713 if (token
!= STATE
) {
2714 parse_warn (cfile
, "expecting 'state'");
2715 skip_to_semi (cfile
);
2718 token
= next_token (&val
, (unsigned *)0, cfile
);
2720 case TOKEN_ABANDONED
:
2721 new_state
= FTS_ABANDONED
;
2724 new_state
= FTS_FREE
;
2727 new_state
= FTS_ACTIVE
;
2730 new_state
= FTS_EXPIRED
;
2732 case TOKEN_RELEASED
:
2733 new_state
= FTS_RELEASED
;
2736 new_state
= FTS_RESET
;
2739 new_state
= FTS_BACKUP
;
2741 case TOKEN_RESERVED
:
2742 new_state
= FTS_ACTIVE
;
2745 new_state
= FTS_ACTIVE
;
2746 lease
-> flags
|= BOOTP_LEASE
;
2750 "%s: expecting a binding state.",
2752 skip_to_semi (cfile
);
2756 if (seenbit
== 256) {
2757 lease
-> binding_state
= new_state
;
2759 /* If no next binding state is specified, it's
2760 the same as the current state. */
2761 if (!(seenmask
& 128))
2762 lease
-> next_binding_state
= new_state
;
2764 lease
-> next_binding_state
= new_state
;
2769 case CLIENT_HOSTNAME
:
2771 token
= peek_token (&val
, (unsigned *)0, cfile
);
2772 if (token
== STRING
) {
2773 if (!parse_string (cfile
,
2774 &lease
-> client_hostname
,
2776 lease_dereference (&lease
, MDL
);
2780 lease
-> client_hostname
=
2781 parse_host_name (cfile
);
2782 if (lease
-> client_hostname
)
2786 "expecting a hostname.");
2787 skip_to_semi (cfile
);
2788 lease_dereference (&lease
, MDL
);
2796 class = (struct class *)0;
2797 token
= next_token (&val
, (unsigned *)0, cfile
);
2798 if (token
== CLASS
) {
2799 token
= next_token (&val
,
2800 (unsigned *)0, cfile
);
2801 if (token
!= STRING
) {
2802 parse_warn (cfile
, "expecting string");
2804 skip_to_semi (cfile
);
2808 if (lease
-> billing_class
)
2809 class_dereference (&lease
-> billing_class
,
2811 find_class (&class, val
, MDL
);
2814 "unknown class %s", val
);
2816 } else if (token
== SUBCLASS
) {
2817 if (lease
-> billing_class
)
2818 class_dereference (&lease
-> billing_class
,
2820 parse_class_declaration
2822 cfile
, (struct group
*)0, 3);
2824 parse_warn (cfile
, "expecting \"class\"");
2826 skip_to_semi (cfile
);
2829 class_reference (&lease
-> billing_class
,
2831 class_dereference (&class, MDL
);
2836 on
= (struct executable_statement
*)0;
2838 if (!parse_on_statement (&on
, cfile
, &lose
)) {
2839 skip_to_rbrace (cfile
, 1);
2840 lease_dereference (&lease
, MDL
);
2844 if ((on
-> data
.on
.evtypes
& ON_EXPIRY
) &&
2845 on
-> data
.on
.statements
) {
2847 executable_statement_reference
2848 (&lease
-> on_expiry
,
2849 on
-> data
.on
.statements
, MDL
);
2851 if ((on
-> data
.on
.evtypes
& ON_RELEASE
) &&
2852 on
-> data
.on
.statements
) {
2854 executable_statement_reference
2855 (&lease
-> on_release
,
2856 on
-> data
.on
.statements
, MDL
);
2858 executable_statement_dereference (&on
, MDL
);
2865 oc
= (struct option_cache
*)0;
2866 if (parse_option_decl (&oc
, cfile
)) {
2867 if (oc
-> option
-> universe
!=
2870 "agent option expected.");
2871 option_cache_dereference (&oc
, MDL
);
2874 if (!lease
-> agent_options
&&
2875 !(option_chain_head_allocate
2876 (&lease
-> agent_options
, MDL
))) {
2877 log_error ("no memory to stash agent option");
2880 for (p
= &lease
-> agent_options
-> first
;
2881 *p
; p
= &((*p
) -> cdr
))
2884 option_cache_reference (((struct option_cache
**)
2885 &((*p
) -> car
)), oc
, MDL
);
2886 option_cache_dereference (&oc
, MDL
);
2893 token
= next_token (&val
, (unsigned *)0, cfile
);
2894 if (token
!= NAME
&& token
!= NUMBER_OR_NAME
) {
2896 "%s can't be a variable name",
2899 skip_to_semi (cfile
);
2900 lease_dereference (&lease
, MDL
);
2907 binding
= find_binding (lease
-> scope
, val
);
2909 binding
= (struct binding
*)0;
2911 if (!lease
-> scope
)
2912 if (!(binding_scope_allocate
2913 (&lease
-> scope
, MDL
)))
2914 log_fatal ("no memory for scope");
2915 binding
= dmalloc (sizeof *binding
, MDL
);
2917 log_fatal ("No memory for lease %s.",
2919 memset (binding
, 0, sizeof *binding
);
2921 dmalloc (strlen (val
) + 1, MDL
);
2922 if (!binding
-> name
)
2923 log_fatal ("No memory for binding %s.",
2925 strcpy (binding
-> name
, val
);
2928 if (binding
-> value
)
2929 binding_value_dereference (&binding
-> value
,
2934 if (!binding_value_allocate (&binding
-> value
, MDL
))
2935 log_fatal ("no memory for binding value.");
2938 token
= next_token (&val
, (unsigned *)0, cfile
);
2939 if (token
!= EQUAL
) {
2941 "expecting '=' in set statement.");
2946 token
= peek_token (&val
, (unsigned *)0, cfile
);
2947 if (token
== STRING
) {
2948 unsigned char *tuid
;
2949 token
= next_token (&val
, &buflen
, cfile
);
2950 binding
-> value
-> type
= binding_data
;
2951 binding
-> value
-> value
.data
.len
= buflen
;
2952 if (!(buffer_allocate
2953 (&binding
-> value
-> value
.data
.buffer
,
2955 log_fatal ("No memory for binding.");
2957 (binding
-> value
->
2958 value
.data
.buffer
-> data
),
2960 binding
-> value
-> value
.data
.data
=
2961 binding
-> value
-> value
.data
.buffer
-> data
;
2962 binding
-> value
-> value
.data
.terminated
= 1;
2963 } else if (token
== NUMBER_OR_NAME
) {
2964 binding
-> value
-> type
= binding_data
;
2966 (parse_numeric_aggregate
2967 (cfile
, (unsigned char *)0,
2968 &binding
-> value
-> value
.data
.len
,
2971 binding_value_dereference
2972 (&binding
-> value
, MDL
);
2973 lease_dereference (&lease
, MDL
);
2976 if (binding
-> value
-> value
.data
.len
) {
2977 if (!(buffer_allocate
2978 (&binding
-> value
-> value
.data
.buffer
,
2979 binding
-> value
-> value
.data
.len
+ 1,
2981 log_fatal ("No memory for binding.");
2982 memcpy ((binding
-> value
->
2983 value
.data
.buffer
-> data
), s
,
2984 binding
-> value
-> value
.data
.len
);
2986 binding
-> value
-> value
.data
.data
=
2987 binding
-> value
-> value
.data
.buffer
-> data
;
2989 } else if (token
== PERCENT
) {
2990 token
= next_token (&val
, (unsigned *)0, cfile
);
2991 token
= next_token (&val
, (unsigned *)0, cfile
);
2992 if (token
!= NUMBER
) {
2994 "expecting decimal number.");
2996 skip_to_semi (cfile
);
2997 binding_value_dereference
2998 (&binding
-> value
, MDL
);
2999 lease_dereference (&lease
, MDL
);
3002 binding
-> value
-> type
= binding_numeric
;
3003 binding
-> value
-> value
.intval
= atol (val
);
3004 } else if (token
== NAME
) {
3005 token
= next_token (&val
,
3006 (unsigned *)0, cfile
);
3007 binding
-> value
-> type
= binding_boolean
;
3008 if (!strcasecmp (val
, "true"))
3009 binding
-> value
-> value
.boolean
= 1;
3010 else if (!strcasecmp (val
, "false"))
3011 binding
-> value
-> value
.boolean
= 0;
3017 "expecting a constant value.");
3018 skip_to_semi (cfile
);
3019 binding_value_dereference (&binding
-> value
,
3021 lease_dereference (&lease
, MDL
);
3026 binding
-> next
= lease
-> scope
-> bindings
;
3027 lease
-> scope
-> bindings
= binding
;
3033 if (!strcasecmp (val
, "ddns-fwd-name")) {
3037 } else if (!strcasecmp (val
, "ddns-rev-name")) {
3042 skip_to_semi (cfile
);
3044 lease_dereference (&lease
, MDL
);
3048 if (seenmask
& seenbit
) {
3050 "Too many %s parameters in lease %s\n",
3051 tbuf
, piaddr (lease
-> ip_addr
));
3053 seenmask
|= seenbit
;
3057 /* If no binding state is specified, make one up. */
3058 if (!(seenmask
& 256)) {
3059 if (lease
-> ends
> cur_time
||
3060 lease
-> on_expiry
|| lease
-> on_release
)
3061 lease
-> binding_state
= FTS_ACTIVE
;
3062 #if defined (FAILOVER_PROTOCOL)
3063 else if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3064 lease
-> binding_state
= FTS_EXPIRED
;
3067 lease
-> binding_state
= FTS_FREE
;
3068 if (lease
-> binding_state
== FTS_ACTIVE
) {
3069 #if defined (FAILOVER_PROTOCOL)
3070 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
3071 lease
-> next_binding_state
= FTS_EXPIRED
;
3074 lease
-> next_binding_state
= FTS_FREE
;
3076 lease
-> next_binding_state
= lease
-> binding_state
;
3079 if (!(seenmask
& 65536))
3080 lease
-> tstp
= lease
-> ends
;
3082 lease_reference (lp
, lease
, MDL
);
3083 lease_dereference (&lease
, MDL
);
3087 /* address-range-declaration :== ip-address ip-address SEMI
3088 | DYNAMIC_BOOTP ip-address ip-address SEMI */
3090 void parse_address_range (cfile
, group
, type
, inpool
, lpchain
)
3091 struct parse
*cfile
;
3092 struct group
*group
;
3094 struct pool
*inpool
;
3095 struct lease
**lpchain
;
3097 struct iaddr low
, high
, net
;
3098 unsigned char addr
[4];
3099 unsigned len
= sizeof addr
;
3100 enum dhcp_token token
;
3103 struct subnet
*subnet
;
3104 struct shared_network
*share
;
3107 isc_result_t status
;
3109 if ((token
= peek_token (&val
,
3110 (unsigned *)0, cfile
)) == DYNAMIC_BOOTP
) {
3111 token
= next_token (&val
, (unsigned *)0, cfile
);
3115 /* Get the bottom address in the range... */
3116 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3118 memcpy (low
.iabuf
, addr
, len
);
3121 /* Only one address? */
3122 token
= peek_token (&val
, (unsigned *)0, cfile
);
3126 /* Get the top address in the range... */
3127 if (!parse_numeric_aggregate (cfile
, addr
, &len
, DOT
, 10, 8))
3129 memcpy (high
.iabuf
, addr
, len
);
3133 token
= next_token (&val
, (unsigned *)0, cfile
);
3134 if (token
!= SEMI
) {
3135 parse_warn (cfile
, "semicolon expected.");
3136 skip_to_semi (cfile
);
3140 if (type
== SUBNET_DECL
) {
3141 subnet
= group
-> subnet
;
3142 share
= subnet
-> shared_network
;
3144 share
= group
-> shared_network
;
3145 for (subnet
= share
-> subnets
;
3146 subnet
; subnet
= subnet
-> next_sibling
) {
3147 net
= subnet_number (low
, subnet
-> netmask
);
3148 if (addr_eq (net
, subnet
-> net
))
3152 parse_warn (cfile
, "address range not on network %s",
3153 group
-> shared_network
-> name
);
3154 log_error ("Be sure to place pool statement after %s",
3155 "related subnet declarations.");
3161 struct pool
*last
= (struct pool
*)0;
3163 /* If we're permitting dynamic bootp for this range,
3164 then look for a pool with an empty prohibit list and
3165 a permit list with one entry that permits all clients. */
3166 for (pool
= share
-> pools
; pool
; pool
= pool
-> next
) {
3167 if ((!dynamic
&& !pool
-> permit_list
&&
3168 pool
-> prohibit_list
&&
3169 !pool
-> prohibit_list
-> next
&&
3170 (pool
-> prohibit_list
-> type
==
3171 permit_dynamic_bootp_clients
)) ||
3172 (dynamic
&& !pool
-> prohibit_list
&&
3173 pool
-> permit_list
&&
3174 !pool
-> permit_list
-> next
&&
3175 (pool
-> permit_list
-> type
==
3176 permit_all_clients
))) {
3182 /* If we didn't get a pool, make one. */
3185 status
= pool_allocate (&pool
, MDL
);
3186 if (status
!= ISC_R_SUCCESS
)
3187 log_fatal ("no memory for ad-hoc pool: %s",
3188 isc_result_totext (status
));
3189 p
= new_permit (MDL
);
3191 log_fatal ("no memory for ad-hoc permit.");
3193 /* Dynamic pools permit all clients. Otherwise
3194 we prohibit BOOTP clients. */
3196 p
-> type
= permit_all_clients
;
3197 pool
-> permit_list
= p
;
3199 p
-> type
= permit_dynamic_bootp_clients
;
3200 pool
-> prohibit_list
= p
;
3204 pool_reference (&last
-> next
, pool
, MDL
);
3206 pool_reference (&share
-> pools
, pool
, MDL
);
3207 shared_network_reference (&pool
-> shared_network
,
3209 if (!clone_group (&pool
-> group
, share
-> group
, MDL
))
3210 log_fatal ("no memory for anon pool group.");
3212 pool
= (struct pool
*)0;
3214 pool_reference (&pool
, last
, MDL
);
3216 pool_reference (&pool
, share
-> pools
, MDL
);
3219 pool
= (struct pool
*)0;
3220 pool_reference (&pool
, inpool
, MDL
);
3223 #if defined (FAILOVER_PROTOCOL)
3224 if (pool
-> failover_peer
&& dynamic
) {
3225 /* Doctor, do you think I'm overly sensitive
3226 about getting bug reports I can't fix? */
3227 parse_warn (cfile
, "dynamic-bootp flag is %s",
3228 "not permitted for address");
3229 log_error ("range declarations where there is a failover");
3230 log_error ("peer in scope. If you wish to declare an");
3231 log_error ("address range from which dynamic bootp leases");
3232 log_error ("can be allocated, please declare it within a");
3233 log_error ("pool declaration that also contains the \"no");
3234 log_error ("failover\" statement. The failover protocol");
3235 log_error ("itself does not permit dynamic bootp - this");
3236 log_error ("is not a limitation specific to the ISC DHCP");
3237 log_error ("server. Please don't ask me to defend this");
3238 log_error ("until you have read and really tried %s",
3240 log_error ("the failover protocol specification.");
3242 /* We don't actually bomb at this point - instead,
3243 we let parse_lease_file notice the error and
3244 bomb at that point - it's easier. */
3246 #endif /* FAILOVER_PROTOCOL */
3248 /* Create the new address range... */
3249 new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
);
3250 pool_dereference (&pool
, MDL
);
3253 /* allow-deny-keyword :== BOOTP
3256 | UNKNOWN_CLIENTS */
3258 int parse_allow_deny (oc
, cfile
, flag
)
3259 struct option_cache
**oc
;
3260 struct parse
*cfile
;
3263 enum dhcp_token token
;
3265 unsigned char rf
= flag
;
3266 struct expression
*data
= (struct expression
*)0;
3269 if (!make_const_data (&data
, &rf
, 1, 0, 1, MDL
))
3272 token
= next_token (&val
, (unsigned *)0, cfile
);
3275 status
= option_cache (oc
, (struct data_string
*)0, data
,
3276 &server_options
[SV_ALLOW_BOOTP
], MDL
);
3280 status
= option_cache (oc
, (struct data_string
*)0, data
,
3281 &server_options
[SV_ALLOW_BOOTING
],
3286 status
= option_cache (oc
, (struct data_string
*)0, data
,
3287 &server_options
[SV_DYNAMIC_BOOTP
],
3291 case UNKNOWN_CLIENTS
:
3292 status
= (option_cache
3293 (oc
, (struct data_string
*)0, data
,
3294 &server_options
[SV_BOOT_UNKNOWN_CLIENTS
], MDL
));
3298 status
= option_cache (oc
, (struct data_string
*)0, data
,
3299 &server_options
[SV_DUPLICATES
], MDL
);
3303 status
= option_cache (oc
, (struct data_string
*)0, data
,
3304 &server_options
[SV_DECLINES
], MDL
);
3307 case CLIENT_UPDATES
:
3308 status
= option_cache (oc
, (struct data_string
*)0, data
,
3309 &server_options
[SV_CLIENT_UPDATES
],
3314 parse_warn (cfile
, "expecting allow/deny key");
3315 skip_to_semi (cfile
);
3318 expression_dereference (&data
, MDL
);