3 Server-specific in-memory database support. */
6 * Copyright (c) 1996-2000 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
45 static char copyright
[] =
46 "$Id: mdb.c,v 1.68 2001/05/17 19:04:08 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
51 struct subnet
*subnets
;
52 struct shared_network
*shared_networks
;
53 struct hash_table
*host_hw_addr_hash
;
54 struct hash_table
*host_uid_hash
;
55 struct hash_table
*lease_uid_hash
;
56 struct hash_table
*lease_ip_addr_hash
;
57 struct hash_table
*lease_hw_addr_hash
;
58 struct hash_table
*host_name_hash
;
60 omapi_object_type_t
*dhcp_type_host
;
62 isc_result_t
enter_host (hd
, dynamicp
, commit
)
67 struct host_decl
*hp
= (struct host_decl
*)0;
68 struct host_decl
*np
= (struct host_decl
*)0;
69 struct executable_statement
*esp
;
71 if (!host_name_hash
) {
73 new_hash ((hash_reference
)host_reference
,
74 (hash_dereference
)host_dereference
, 0);
76 log_fatal ("Can't allocate host name hash");
77 host_hash_add (host_name_hash
,
78 (unsigned char *)hd
-> name
,
79 strlen (hd
-> name
), hd
, MDL
);
81 host_hash_lookup (&hp
, host_name_hash
,
82 (unsigned char *)hd
-> name
,
83 strlen (hd
-> name
), MDL
);
85 /* If it's deleted, we can supersede it. */
86 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
87 host_hash_delete (host_name_hash
,
88 (unsigned char *)hd
-> name
,
89 strlen (hd
-> name
), MDL
);
90 /* If the old entry wasn't dynamic, then we
91 always have to keep the deletion. */
92 if (!hp
-> flags
& HOST_DECL_DYNAMIC
)
93 hd
-> flags
|= HOST_DECL_STATIC
;
96 /* If there isn't already a host decl matching this
97 address, add it to the hash table. */
99 host_hash_add (host_name_hash
,
100 (unsigned char *)hd
-> name
,
101 strlen (hd
-> name
), hd
, MDL
);
103 /* XXX actually, we have to delete the old one
104 XXX carefully and replace it. Not done yet. */
105 host_dereference (&hp
, MDL
);
111 host_dereference (&hd
-> n_ipaddr
, MDL
);
114 hd
-> type
= dhcp_type_host
;
116 if (hd
-> interface
.hlen
) {
117 if (!host_hw_addr_hash
) {
119 new_hash ((hash_reference
)host_reference
,
120 (hash_dereference
)host_dereference
,
122 if (!host_hw_addr_hash
)
123 log_fatal ("Can't allocate host/hw hash");
125 /* If there isn't already a host decl matching this
126 address, add it to the hash table. */
127 host_hash_lookup (&hp
, host_hw_addr_hash
,
128 hd
-> interface
.hbuf
,
129 hd
-> interface
.hlen
, MDL
);
132 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
133 hd
-> interface
.hlen
, hd
, MDL
);
135 /* If there was already a host declaration for
136 this hardware address, add this one to the
138 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
140 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
141 host_dereference (&hp
, MDL
);
145 /* See if there's a statement that sets the client identifier.
146 This is a kludge - the client identifier really shouldn't be
147 set with an executable statement. */
148 for (esp
= hd
-> group
-> statements
; esp
; esp
= esp
-> next
) {
149 if (esp
-> op
== supersede_option_statement
&&
150 esp
-> data
.option
&&
151 (esp
-> data
.option
-> option
-> universe
==
153 (esp
-> data
.option
-> option
-> code
==
154 DHO_DHCP_CLIENT_IDENTIFIER
)) {
155 evaluate_option_cache
156 (&hd
-> client_identifier
, (struct packet
*)0,
157 (struct lease
*)0, (struct client_state
*)0,
158 (struct option_state
*)0,
159 (struct option_state
*)0, &global_scope
,
160 esp
-> data
.option
, MDL
);
165 /* If we got a client identifier, hash this entry by
166 client identifier. */
167 if (hd
-> client_identifier
.len
) {
168 /* If there's no uid hash, make one; otherwise, see if
169 there's already an entry in the hash for this host. */
170 if (!host_uid_hash
) {
172 new_hash ((hash_reference
)host_reference
,
173 (hash_dereference
)host_dereference
,
176 log_fatal ("Can't allocate host/uid hash");
178 host_hash_add (host_uid_hash
,
179 hd
-> client_identifier
.data
,
180 hd
-> client_identifier
.len
,
183 /* If there's already a host declaration for this
184 client identifier, add this one to the end of the
185 list. Otherwise, add it to the hash table. */
186 if (host_hash_lookup (&hp
, host_uid_hash
,
187 hd
-> client_identifier
.data
,
188 hd
-> client_identifier
.len
,
190 /* Don't link it in twice... */
192 for (np
= hp
; np
-> n_ipaddr
;
193 np
= np
-> n_ipaddr
) {
198 host_reference (&np
-> n_ipaddr
,
201 host_dereference (&hp
, MDL
);
203 host_hash_add (host_uid_hash
,
204 hd
-> client_identifier
.data
,
205 hd
-> client_identifier
.len
,
211 if (dynamicp
&& commit
) {
212 if (!write_host (hd
))
213 return ISC_R_IOERROR
;
214 if (!commit_leases ())
215 return ISC_R_IOERROR
;
218 return ISC_R_SUCCESS
;
221 isc_result_t
delete_host (hd
, commit
)
222 struct host_decl
*hd
;
225 struct host_decl
*hp
= (struct host_decl
*)0;
226 struct host_decl
*np
= (struct host_decl
*)0;
227 struct host_decl
*foo
;
228 struct executable_statement
*esp
;
229 int hw_head
= 0, uid_head
= 1;
231 /* Don't need to do it twice. */
232 if (hd
-> flags
& HOST_DECL_DELETED
)
233 return ISC_R_SUCCESS
;
235 /* But we do need to do it once! :') */
236 hd
-> flags
|= HOST_DECL_DELETED
;
238 if (hd
-> interface
.hlen
) {
239 if (host_hw_addr_hash
) {
240 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
241 hd
-> interface
.hbuf
,
242 hd
-> interface
.hlen
, MDL
)) {
244 host_hash_delete (host_hw_addr_hash
,
245 hd
-> interface
.hbuf
,
246 hd
-> interface
.hlen
, MDL
);
249 np
= (struct host_decl
*)0;
250 foo
= (struct host_decl
*)0;
251 host_reference (&foo
, hp
, MDL
);
255 host_reference (&np
, foo
, MDL
);
256 host_dereference (&foo
, MDL
);
258 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
262 host_dereference (&np
-> n_ipaddr
, MDL
);
264 host_reference (&np
-> n_ipaddr
,
265 hd
-> n_ipaddr
, MDL
);
266 host_dereference (&foo
, MDL
);
269 host_dereference (&np
, MDL
);
271 host_dereference (&hp
, MDL
);
276 /* If we got a client identifier, hash this entry by
277 client identifier. */
278 if (hd
-> client_identifier
.len
) {
280 if (host_hash_lookup (&hp
, host_uid_hash
,
281 hd
-> client_identifier
.data
,
282 hd
-> client_identifier
.len
, MDL
)) {
284 host_hash_delete (host_uid_hash
,
285 hd
-> client_identifier
.data
,
286 hd
-> client_identifier
.len
, MDL
);
289 np
= (struct host_decl
*)0;
290 foo
= (struct host_decl
*)0;
291 host_reference (&foo
, hp
, MDL
);
295 host_reference (&np
, foo
, MDL
);
296 host_dereference (&foo
, MDL
);
298 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
302 host_dereference (&np
-> n_ipaddr
, MDL
);
304 host_reference (&np
-> n_ipaddr
,
305 hd
-> n_ipaddr
, MDL
);
306 host_dereference (&foo
, MDL
);
309 host_dereference (&np
, MDL
);
311 host_dereference (&hp
, MDL
);
316 if (hd
-> n_ipaddr
) {
317 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
320 hd
-> n_ipaddr
-> client_identifier
.data
,
321 hd
-> n_ipaddr
-> client_identifier
.len
,
322 hd
-> n_ipaddr
, MDL
);
324 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
325 host_hash_add (host_hw_addr_hash
,
326 hd
-> n_ipaddr
-> interface
.hbuf
,
327 hd
-> n_ipaddr
-> interface
.hlen
,
328 hd
-> n_ipaddr
, MDL
);
330 host_dereference (&hd
-> n_ipaddr
, MDL
);
333 if (host_name_hash
) {
334 if (host_hash_lookup (&hp
, host_name_hash
,
335 (unsigned char *)hd
-> name
,
336 strlen (hd
-> name
), MDL
)) {
337 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
338 host_hash_delete (host_name_hash
,
339 (unsigned char *)hd
-> name
,
340 strlen (hd
-> name
), MDL
);
342 host_dereference (&hp
, MDL
);
347 if (!write_host (hd
))
348 return ISC_R_IOERROR
;
349 if (!commit_leases ())
350 return ISC_R_IOERROR
;
352 return ISC_R_SUCCESS
;
355 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
356 const unsigned char *haddr
, unsigned hlen
,
357 const char *file
, int line
)
359 struct host_decl
*foo
;
364 memcpy (&h
.hbuf
[1], haddr
, hlen
);
366 return host_hash_lookup (hp
, host_hw_addr_hash
,
367 h
.hbuf
, h
.hlen
, file
, line
);
370 int find_hosts_by_uid (struct host_decl
**hp
,
371 const unsigned char *data
, unsigned len
,
372 const char *file
, int line
)
374 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
377 /* More than one host_decl can be returned by find_hosts_by_haddr or
378 find_hosts_by_uid, and each host_decl can have multiple addresses.
379 Loop through the list of hosts, and then for each host, through the
380 list of addresses, looking for an address that's in the same shared
381 network as the one specified. Store the matching address through
382 the addr pointer, update the host pointer to point at the host_decl
383 that matched, and return the subnet that matched. */
385 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
386 struct iaddr
*addr
, struct shared_network
*share
)
389 struct subnet
*subnet
;
390 struct iaddr ip_address
;
391 struct host_decl
*hp
;
392 struct data_string fixed_addr
;
394 memset (&fixed_addr
, 0, sizeof fixed_addr
);
396 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
397 if (!hp
-> fixed_addr
)
399 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
401 (struct client_state
*)0,
402 (struct option_state
*)0,
403 (struct option_state
*)0,
405 hp
-> fixed_addr
, MDL
))
407 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
409 memcpy (ip_address
.iabuf
,
410 fixed_addr
.data
+ i
, 4);
411 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
412 struct host_decl
*tmp
= (struct host_decl
*)0;
414 /* This is probably not necessary, but
415 just in case *host is the only reference
416 to that host declaration, make a temporary
417 reference so that dereferencing it doesn't
418 dereference hp out from under us. */
419 host_reference (&tmp
, *host
, MDL
);
420 host_dereference (host
, MDL
);
421 host_reference (host
, hp
, MDL
);
422 host_dereference (&tmp
, MDL
);
423 data_string_forget (&fixed_addr
, MDL
);
427 data_string_forget (&fixed_addr
, MDL
);
432 void new_address_range (low
, high
, subnet
, pool
)
433 struct iaddr low
, high
;
434 struct subnet
*subnet
;
437 struct lease
*address_range
, *lp
, *plp
;
439 unsigned min
, max
, i
;
440 char lowbuf
[16], highbuf
[16], netbuf
[16];
441 struct shared_network
*share
= subnet
-> shared_network
;
443 struct lease
*lt
= (struct lease
*)0;
445 /* All subnets should have attached shared network structures. */
447 strcpy (netbuf
, piaddr (subnet
-> net
));
448 log_fatal ("No shared network for network %s (%s)",
449 netbuf
, piaddr (subnet
-> netmask
));
452 /* Initialize the hash table if it hasn't been done yet. */
453 if (!lease_uid_hash
) {
455 new_hash ((hash_reference
)lease_reference
,
456 (hash_dereference
)lease_dereference
, 0);
458 log_fatal ("Can't allocate lease/uid hash");
460 if (!lease_ip_addr_hash
) {
462 new_hash ((hash_reference
)lease_reference
,
463 (hash_dereference
)lease_dereference
, 0);
465 log_fatal ("Can't allocate lease/ip hash");
467 if (!lease_hw_addr_hash
) {
469 new_hash ((hash_reference
)lease_reference
,
470 (hash_dereference
)lease_dereference
, 0);
472 log_fatal ("Can't allocate lease/hw hash");
475 /* Make sure that high and low addresses are in same subnet. */
476 net
= subnet_number (low
, subnet
-> netmask
);
477 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
478 strcpy (lowbuf
, piaddr (low
));
479 strcpy (highbuf
, piaddr (high
));
480 strcpy (netbuf
, piaddr (subnet
-> netmask
));
481 log_fatal ("Address range %s to %s, netmask %s spans %s!",
482 lowbuf
, highbuf
, netbuf
, "multiple subnets");
485 /* Make sure that the addresses are on the correct subnet. */
486 if (!addr_eq (net
, subnet
-> net
)) {
487 strcpy (lowbuf
, piaddr (low
));
488 strcpy (highbuf
, piaddr (high
));
489 strcpy (netbuf
, piaddr (subnet
-> netmask
));
490 log_fatal ("Address range %s to %s not on net %s/%s!",
491 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
494 /* Get the high and low host addresses... */
495 max
= host_addr (high
, subnet
-> netmask
);
496 min
= host_addr (low
, subnet
-> netmask
);
498 /* Allow range to be specified high-to-low as well as low-to-high. */
501 min
= host_addr (high
, subnet
-> netmask
);
504 /* Get a lease structure for each address in the range. */
505 #if defined (COMPACT_LEASES)
506 address_range
= new_leases (max
- min
+ 1, MDL
);
507 if (!address_range
) {
508 strcpy (lowbuf
, piaddr (low
));
509 strcpy (highbuf
, piaddr (high
));
510 log_fatal ("No memory for address range %s-%s.",
515 /* Fill out the lease structures with some minimal information. */
516 for (i
= 0; i
< max
- min
+ 1; i
++) {
517 struct lease
*lp
= (struct lease
*)0;
518 #if defined (COMPACT_LEASES)
519 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
521 0, sizeof (struct lease
), MDL
);
522 lease_reference (&lp
, &address_range
[i
], MDL
);
524 status
= lease_allocate (&lp
, MDL
);
525 if (status
!= ISC_R_SUCCESS
)
526 log_fatal ("No memory for lease %s: %s",
527 piaddr (ip_addr (subnet
-> net
,
530 isc_result_totext (status
));
532 lp
-> ip_addr
= ip_addr (subnet
-> net
,
533 subnet
-> netmask
, i
+ min
);
534 lp
-> starts
= lp
-> timestamp
= MIN_TIME
;
535 lp
-> ends
= MIN_TIME
;
536 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
537 pool_reference (&lp
-> pool
, pool
, MDL
);
538 lp
-> binding_state
= FTS_FREE
;
539 lp
-> next_binding_state
= FTS_FREE
;
542 /* Remember the lease in the IP address hash. */
543 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
545 log_error ("duplicate entries for lease %s",
546 piaddr (lp
-> ip_addr
));
548 pool_reference (<
-> pool
, pool
, MDL
);
549 lease_dereference (<
, MDL
);
551 lease_hash_add (lease_ip_addr_hash
,
553 lp
-> ip_addr
.len
, lp
, MDL
);
554 lease_dereference (&lp
, MDL
);
559 #if defined (COMPACT_LEASES)
560 struct lease
*free_leases
;
562 /* If we are allocating leases in aggregations, there's really no way
563 to free one, although perhaps we can maintain a free list. */
565 isc_result_t
dhcp_lease_free (omapi_object_t
*lo
,
566 const char *file
, int line
)
569 if (lo
-> type
!= dhcp_type_lease
)
570 return ISC_R_INVALIDARG
;
571 lease
= (struct lease
*)lo
;
572 lease
-> next
= free_leases
;
574 return ISC_R_SUCCESS
;
577 isc_result_t
dhcp_lease_get (omapi_object_t
**lp
,
578 const char *file
, int line
)
580 struct lease
**lease
= (struct lease
**)lp
;
585 free_leases
= lt
-> next
;
587 return ISC_R_SUCCESS
;
589 return ISC_R_NOMEMORY
;
593 int find_subnet (struct subnet
**sp
,
594 struct iaddr addr
, const char *file
, int line
)
598 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
599 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
600 if (subnet_reference (sp
, rv
,
601 file
, line
) != ISC_R_SUCCESS
)
609 int find_grouped_subnet (struct subnet
**sp
,
610 struct shared_network
*share
, struct iaddr addr
,
611 const char *file
, int line
)
615 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
616 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
617 if (subnet_reference (sp
, rv
,
618 file
, line
) != ISC_R_SUCCESS
)
626 int subnet_inner_than (subnet
, scan
, warnp
)
627 struct subnet
*subnet
, *scan
;
630 if (addr_eq (subnet_number (subnet
-> net
, scan
-> netmask
),
632 addr_eq (subnet_number (scan
-> net
, subnet
-> netmask
),
636 for (i
= 0; i
< 32; i
++)
637 if (subnet
-> netmask
.iabuf
[3 - (i
>> 3)]
640 for (j
= 0; j
< 32; j
++)
641 if (scan
-> netmask
.iabuf
[3 - (j
>> 3)] &
644 strcpy (n1buf
, piaddr (subnet
-> net
));
646 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
647 "Warning: ", n1buf
, 32 - i
,
648 piaddr (scan
-> net
), 32 - j
);
655 /* Enter a new subnet into the subnet list. */
656 void enter_subnet (subnet
)
657 struct subnet
*subnet
;
659 struct subnet
*scan
, *prev
= (struct subnet
*)0;
661 /* Check for duplicates... */
662 for (scan
= subnets
; scan
; scan
= scan
-> next_subnet
) {
663 /* When we find a conflict, make sure that the
664 subnet with the narrowest subnet mask comes
666 if (subnet_inner_than (subnet
, scan
, 1)) {
668 subnet_reference (&prev
-> next_subnet
,
671 subnet_reference (&subnets
, subnet
, MDL
);
672 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
678 /* XXX use the BSD radix tree code instead of a linked list. */
679 subnet
-> next_subnet
= subnets
;
683 /* Enter a new shared network into the shared network list. */
685 void enter_shared_network (share
)
686 struct shared_network
*share
;
688 if (shared_networks
) {
689 shared_network_reference (&share
-> next
,
690 shared_networks
, MDL
);
691 shared_network_dereference (&shared_networks
, MDL
);
693 shared_network_reference (&shared_networks
, share
, MDL
);
696 void new_shared_network_interface (cfile
, share
, name
)
698 struct shared_network
*share
;
701 struct interface_info
*ip
;
704 if (share
-> interface
) {
706 "A subnet or shared network can't be connected %s",
707 "to two interfaces.");
711 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
712 if (!strcmp (ip
-> name
, name
))
715 status
= interface_allocate (&ip
, MDL
);
716 if (status
!= ISC_R_SUCCESS
)
717 log_fatal ("new_shared_network_interface %s: %s",
718 name
, isc_result_totext (status
));
719 if (strlen (name
) > sizeof ip
-> name
) {
720 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
721 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
723 strcpy (ip
-> name
, name
);
725 interface_reference (&ip
-> next
, interfaces
, MDL
);
726 interface_dereference (&interfaces
, MDL
);
728 interface_reference (&interfaces
, ip
, MDL
);
729 ip
-> flags
= INTERFACE_REQUESTED
;
730 /* XXX this is a reference loop. */
731 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
732 interface_reference (&share
-> interface
, ip
, MDL
);
736 /* Enter a lease into the system. This is called by the parser each
737 time it reads in a new lease. If the subnet for that lease has
738 already been read in (usually the case), just update that lease;
739 otherwise, allocate temporary storage for the lease and keep it around
740 until we're done reading in the config file. */
742 void enter_lease (lease
)
745 struct lease
*comp
= (struct lease
*)0;
748 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
750 log_error ("undeclared lease found in database: %s",
751 piaddr (lease
-> ip_addr
));
753 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
756 subnet_reference (&lease
-> subnet
,
757 comp
-> subnet
, MDL
);
758 lease_hash_delete (lease_ip_addr_hash
,
759 lease
-> ip_addr
.iabuf
,
760 lease
-> ip_addr
.len
, MDL
);
761 lease_dereference (&comp
, MDL
);
764 /* The only way a lease can get here without a subnet is if it's in
765 the lease file, but not in the dhcpd.conf file. In this case, we
766 *should* keep it around until it's expired, but never reallocate it
767 or renew it. Currently, to maintain consistency, we are not doing
769 XXX fix this so that the lease is kept around until it expires.
770 XXX this will be important in IPv6 with addresses that become
771 XXX non-renewable as a result of a renumbering event. */
773 if (!lease
-> subnet
) {
774 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
777 lease_hash_add (lease_ip_addr_hash
,
778 lease
-> ip_addr
.iabuf
,
779 lease
-> ip_addr
.len
, lease
, MDL
);
782 /* Replace the data in an existing lease with the data in a new lease;
783 adjust hash tables to suit, and insertion sort the lease into the
784 list of leases by expiry time so that we can always find the oldest
787 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
788 struct lease
*comp
, *lease
;
794 int enter_hwaddr
= 0;
795 struct lease
*lp
, **lq
, *prev
;
798 #if defined (FAILOVER_PROTOCOL)
799 /* We must commit leases before sending updates regarding them
800 to failover peers. It is, therefore, an error to set pimmediate
802 if (pimmediate
&& !commit
)
806 /* If there is no sample lease, just do the move. */
810 /* Static leases are not currently kept in the database... */
811 if (lease
-> flags
& STATIC_LEASE
)
814 /* If the existing lease hasn't expired and has a different
815 unique identifier or, if it doesn't have a unique
816 identifier, a different hardware address, then the two
817 leases are in conflict. If the existing lease has a uid
818 and the new one doesn't, but they both have the same
819 hardware address, and dynamic bootp is allowed on this
820 lease, then we allow that, in case a dynamic BOOTP lease is
821 requested *after* a DHCP lease has been assigned. */
823 if (lease
-> binding_state
!= FTS_ABANDONED
&&
824 lease
-> next_binding_state
!= FTS_ABANDONED
&&
825 (comp
-> binding_state
== FTS_ACTIVE
||
826 comp
-> binding_state
== FTS_RESERVED
||
827 comp
-> binding_state
== FTS_BOOTP
) &&
828 (((comp
-> uid
&& lease
-> uid
) &&
829 (comp
-> uid_len
!= lease
-> uid_len
||
830 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
832 ((comp
-> hardware_addr
.hlen
!=
833 lease
-> hardware_addr
.hlen
) ||
834 memcmp (comp
-> hardware_addr
.hbuf
,
835 lease
-> hardware_addr
.hbuf
,
836 comp
-> hardware_addr
.hlen
))))) {
837 log_error ("Lease conflict at %s",
838 piaddr (comp
-> ip_addr
));
842 /* If there's a Unique ID, dissociate it from the hash
843 table and free it if necessary. */
845 uid_hash_delete (comp
);
847 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
848 dfree (comp
-> uid
, MDL
);
852 comp
-> uid
= (unsigned char *)0;
856 if (comp
-> hardware_addr
.hlen
&&
857 ((comp
-> hardware_addr
.hlen
!=
858 lease
-> hardware_addr
.hlen
) ||
859 memcmp (comp
-> hardware_addr
.hbuf
,
860 lease
-> hardware_addr
.hbuf
,
861 comp
-> hardware_addr
.hlen
))) {
862 hw_hash_delete (comp
);
864 } else if (!comp
-> hardware_addr
.hlen
)
867 /* If the lease has been billed to a class, remove the billing. */
868 if (comp
-> billing_class
!= lease
-> billing_class
) {
869 if (comp
-> billing_class
)
870 unbill_class (comp
, comp
-> billing_class
);
871 if (lease
-> billing_class
)
872 bill_class (comp
, lease
-> billing_class
);
875 /* Copy the data files, but not the linkages. */
876 comp
-> starts
= lease
-> starts
;
878 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
879 memcpy (comp
-> uid_buf
,
880 lease
-> uid
, lease
-> uid_len
);
881 comp
-> uid
= &comp
-> uid_buf
[0];
882 comp
-> uid_max
= sizeof comp
-> uid_buf
;
883 comp
-> uid_len
= lease
-> uid_len
;
884 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
885 comp
-> uid
= lease
-> uid
;
886 comp
-> uid_max
= lease
-> uid_max
;
887 lease
-> uid
= (unsigned char *)0;
888 lease
-> uid_max
= 0;
889 comp
-> uid_len
= lease
-> uid_len
;
890 lease
-> uid_len
= 0;
892 log_fatal ("corrupt lease uid."); /* XXX */
895 comp
-> uid
= (unsigned char *)0;
896 comp
-> uid_len
= comp
-> uid_max
= 0;
899 host_dereference (&comp
-> host
, MDL
);
900 host_reference (&comp
-> host
, lease
-> host
, MDL
);
901 comp
-> hardware_addr
= lease
-> hardware_addr
;
902 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
903 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
905 binding_scope_dereference (&comp
-> scope
, MDL
);
906 if (lease
-> scope
) {
907 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
908 binding_scope_dereference (&lease
-> scope
, MDL
);
911 if (comp
-> agent_options
)
912 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
913 if (lease
-> agent_options
) {
914 /* Only retain the agent options if the lease is still
915 affirmatively associated with a client. */
916 if (lease
-> next_binding_state
== FTS_ACTIVE
||
917 lease
-> next_binding_state
== FTS_EXPIRED
||
918 lease
-> next_binding_state
== FTS_RESERVED
||
919 lease
-> next_binding_state
== FTS_BOOTP
)
920 option_chain_head_reference (&comp
-> agent_options
,
921 lease
-> agent_options
,
923 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
926 /* Record the hostname information in the lease. */
927 if (comp
-> client_hostname
)
928 dfree (comp
-> client_hostname
, MDL
);
929 comp
-> client_hostname
= lease
-> client_hostname
;
930 lease
-> client_hostname
= (char *)0;
932 if (lease
-> on_expiry
) {
933 if (comp
-> on_expiry
)
934 executable_statement_dereference (&comp
-> on_expiry
,
936 executable_statement_reference (&comp
-> on_expiry
,
940 if (lease
-> on_commit
) {
941 if (comp
-> on_commit
)
942 executable_statement_dereference (&comp
-> on_commit
,
944 executable_statement_reference (&comp
-> on_commit
,
948 if (lease
-> on_release
) {
949 if (comp
-> on_release
)
950 executable_statement_dereference (&comp
-> on_release
,
952 executable_statement_reference (&comp
-> on_release
,
953 lease
-> on_release
, MDL
);
956 /* Record the lease in the uid hash if necessary. */
957 if (enter_uid
&& comp
-> uid
) {
961 /* Record it in the hardware address hash if necessary. */
962 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
966 #if defined (FAILOVER_PROTOCOL)
967 comp
-> cltt
= lease
-> cltt
;
968 comp
-> tstp
= lease
-> tstp
;
969 comp
-> tsfp
= lease
-> tsfp
;
970 #endif /* FAILOVER_PROTOCOL */
971 comp
-> ends
= lease
-> ends
;
972 comp
-> next_binding_state
= lease
-> next_binding_state
;
976 log_error ("Supersede_lease: lease %s with no pool.",
977 piaddr (comp
-> ip_addr
));
981 /* Figure out which queue it's on. */
982 switch (comp
-> binding_state
) {
984 lq
= &comp
-> pool
-> free
;
985 comp
-> pool
-> free_leases
--;
991 lq
= &comp
-> pool
-> active
;
997 lq
= &comp
-> pool
-> expired
;
1001 lq
= &comp
-> pool
-> abandoned
;
1005 lq
= &comp
-> pool
-> backup
;
1006 comp
-> pool
-> backup_leases
--;
1010 log_error ("Lease with bogus binding state: %d",
1011 comp
-> binding_state
);
1012 #if defined (BINDING_STATE_DEBUG)
1018 /* Remove the lease from its current place in its current
1020 prev
= (struct lease
*)0;
1021 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1028 log_error ("Lease with binding state %s not on its queue.",
1029 (comp
-> binding_state
< 1 &&
1030 comp
-> binding_state
< FTS_BOOTP
)
1032 : binding_state_names
[comp
-> binding_state
- 1]);
1037 lease_dereference (&prev
-> next
, MDL
);
1039 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1040 lease_dereference (&comp
-> next
, MDL
);
1043 lease_dereference (lq
, MDL
);
1045 lease_reference (lq
, comp
-> next
, MDL
);
1046 lease_dereference (&comp
-> next
, MDL
);
1050 /* Make the state transition. */
1051 if (commit
|| !pimmediate
)
1052 make_binding_state_transition (comp
);
1054 /* Put the lease back on the appropriate queue. If the lease
1055 is corrupt (as detected by lease_enqueue), don't go any farther. */
1056 if (!lease_enqueue (comp
))
1059 /* If this is the next lease that will timeout on the pool,
1060 zap the old timeout and set the timeout on this pool to the
1061 time that the lease's next event will happen.
1063 We do not actually set the timeout unless commit is true -
1064 we don't want to thrash the timer queue when reading the
1065 lease database. Instead, the database code calls the
1066 expiry event on each pool after reading in the lease file,
1067 and the expiry code sets the timer if there's anything left
1068 to expire after it's run any outstanding expiry events on
1070 if ((commit
|| !pimmediate
) &&
1071 comp
-> sort_time
!= MIN_TIME
&&
1072 comp
-> sort_time
> cur_time
&&
1073 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1074 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1075 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1076 add_timeout (comp
-> pool
-> next_event_time
,
1077 pool_timer
, comp
-> pool
,
1078 (tvref_t
)pool_reference
,
1079 (tvunref_t
)pool_dereference
);
1083 if (!write_lease (comp
))
1085 if (!commit_leases ())
1089 #if defined (FAILOVER_PROTOCOL)
1091 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1099 void make_binding_state_transition (struct lease
*lease
)
1101 #if defined (FAILOVER_PROTOCOL)
1102 dhcp_failover_state_t
*peer
;
1104 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1105 peer
= lease
-> pool
-> failover_peer
;
1107 peer
= (dhcp_failover_state_t
*)0;
1110 /* If the lease was active and is now no longer active, but isn't
1111 released, then it just expired, so do the expiry event. */
1112 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1114 #if defined (FAILOVER_PROTOCOL)
1116 lease
-> binding_state
== FTS_EXPIRED
&&
1117 (lease
-> next_binding_state
== FTS_FREE
||
1118 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1121 (lease
-> binding_state
== FTS_ACTIVE
||
1122 lease
-> binding_state
== FTS_BOOTP
||
1123 lease
-> binding_state
== FTS_RESERVED
) &&
1124 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1125 #if defined (NSUPDATE)
1126 ddns_removals (lease
);
1128 if (lease
-> on_expiry
) {
1129 execute_statements ((struct binding_value
**)0,
1130 (struct packet
*)0, lease
,
1131 (struct client_state
*)0,
1132 (struct option_state
*)0,
1133 (struct option_state
*)0, /* XXX */
1135 lease
-> on_expiry
);
1136 if (lease
-> on_expiry
)
1137 executable_statement_dereference
1138 (&lease
-> on_expiry
, MDL
);
1141 /* No sense releasing a lease after it's expired. */
1142 if (lease
-> on_release
)
1143 executable_statement_dereference (&lease
-> on_release
,
1145 if (lease
-> billing_class
)
1146 unbill_class (lease
, lease
-> billing_class
);
1148 /* Send the expiry time to the peer. */
1149 lease
-> tstp
= lease
-> ends
;
1152 /* If the lease was active and is now released, do the release
1154 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1156 #if defined (FAILOVER_PROTOCOL)
1158 lease
-> binding_state
== FTS_RELEASED
&&
1159 (lease
-> next_binding_state
== FTS_FREE
||
1160 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1163 (lease
-> binding_state
== FTS_ACTIVE
||
1164 lease
-> binding_state
== FTS_BOOTP
||
1165 lease
-> binding_state
== FTS_RESERVED
) &&
1166 lease
-> next_binding_state
== FTS_RELEASED
))) {
1167 #if defined (NSUPDATE)
1168 ddns_removals (lease
);
1170 if (lease
-> on_release
) {
1171 execute_statements ((struct binding_value
**)0,
1172 (struct packet
*)0, lease
,
1173 (struct client_state
*)0,
1174 (struct option_state
*)0,
1175 (struct option_state
*)0, /* XXX */
1177 lease
-> on_release
);
1178 executable_statement_dereference (&lease
-> on_release
,
1182 /* A released lease can't expire. */
1183 if (lease
-> on_expiry
)
1184 executable_statement_dereference (&lease
-> on_expiry
,
1187 if (lease
-> billing_class
)
1188 unbill_class (lease
, lease
-> billing_class
);
1190 /* Send the release time (should be == cur_time) to the
1192 lease
-> tstp
= lease
-> ends
;
1195 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1196 log_debug ("lease %s moves from %s to %s",
1197 piaddr (lease
-> ip_addr
),
1198 binding_state_print (lease
-> binding_state
),
1199 binding_state_print (lease
-> next_binding_state
));
1202 lease
-> binding_state
= lease
-> next_binding_state
;
1203 switch (lease
-> binding_state
) {
1206 #if defined (FAILOVER_PROTOCOL)
1207 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1208 lease
-> next_binding_state
= FTS_EXPIRED
;
1211 lease
-> next_binding_state
= FTS_FREE
;
1218 lease
-> next_binding_state
= FTS_FREE
;
1219 /* If we are not in partner_down, leases don't go from
1220 EXPIRED to FREE on a timeout - only on an update.
1221 If we're in partner_down, they expire at mclt past
1222 the time we entered partner_down. */
1223 if (lease
-> pool
-> failover_peer
&&
1224 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1226 (lease
-> pool
-> failover_peer
-> me
.stos
+
1227 lease
-> pool
-> failover_peer
-> mclt
);
1233 lease
-> next_binding_state
= lease
-> binding_state
;
1236 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1237 log_debug ("lease %s: next binding state %s",
1238 piaddr (lease
-> ip_addr
),
1239 binding_state_print (lease
-> next_binding_state
));
1244 /* Copy the contents of one lease into another, correctly maintaining
1245 reference counts. */
1246 int lease_copy (struct lease
**lp
,
1247 struct lease
*lease
, const char *file
, int line
)
1249 struct lease
*lt
= (struct lease
*)0;
1250 isc_result_t status
;
1252 status
= lease_allocate (<
, MDL
);
1253 if (status
!= ISC_R_SUCCESS
)
1256 lt
-> ip_addr
= lease
-> ip_addr
;
1257 lt
-> starts
= lease
-> starts
;
1258 lt
-> ends
= lease
-> ends
;
1259 lt
-> timestamp
= lease
-> timestamp
;
1260 lt
-> uid_len
= lease
-> uid_len
;
1261 lt
-> uid_max
= lease
-> uid_max
;
1262 if (lease
-> uid
== lease
-> uid_buf
) {
1263 lt
-> uid
= lt
-> uid_buf
;
1264 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1265 } else if (!lease
-> uid_max
) {
1266 lt
-> uid
= (unsigned char *)0;
1268 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1270 lease_dereference (<
, MDL
);
1273 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1275 if (lease
-> client_hostname
) {
1276 lt
-> client_hostname
=
1277 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1278 if (!lt
-> client_hostname
) {
1279 lease_dereference (<
, MDL
);
1282 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1285 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1286 if (lease
-> agent_options
)
1287 option_chain_head_reference (<
-> agent_options
,
1288 lease
-> agent_options
, MDL
);
1289 host_reference (<
-> host
, lease
-> host
, file
, line
);
1290 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1291 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1292 class_reference (<
-> billing_class
,
1293 lease
-> billing_class
, file
, line
);
1294 lt
-> hardware_addr
= lease
-> hardware_addr
;
1295 if (lease
-> on_expiry
)
1296 executable_statement_reference (<
-> on_expiry
,
1299 if (lease
-> on_commit
)
1300 executable_statement_reference (<
-> on_commit
,
1303 if (lease
-> on_release
)
1304 executable_statement_reference (<
-> on_release
,
1305 lease
-> on_release
,
1307 lt
-> flags
= lease
-> flags
;
1308 lt
-> tstp
= lease
-> tstp
;
1309 lt
-> tsfp
= lease
-> tsfp
;
1310 lt
-> cltt
= lease
-> cltt
;
1311 lt
-> binding_state
= lease
-> binding_state
;
1312 lt
-> next_binding_state
= lease
-> next_binding_state
;
1313 status
= lease_reference (lp
, lt
, file
, line
);
1314 lease_dereference (<
, MDL
);
1315 return status
== ISC_R_SUCCESS
;
1318 /* Release the specified lease and re-hash it as appropriate. */
1319 void release_lease (lease
, packet
)
1320 struct lease
*lease
;
1321 struct packet
*packet
;
1323 /* If there are statements to execute when the lease is
1324 released, execute them. */
1325 #if defined (NSUPDATE)
1326 ddns_removals (lease
);
1328 if (lease
-> on_release
) {
1329 execute_statements ((struct binding_value
**)0,
1330 packet
, lease
, (struct client_state
*)0,
1332 (struct option_state
*)0, /* XXX */
1333 &lease
-> scope
, lease
-> on_release
);
1334 if (lease
-> on_release
)
1335 executable_statement_dereference (&lease
-> on_release
,
1339 /* We do either the on_release or the on_expiry events, but
1340 not both (it's possible that they could be the same,
1342 if (lease
-> on_expiry
)
1343 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1345 if (lease
-> binding_state
!= FTS_FREE
&&
1346 lease
-> binding_state
!= FTS_BACKUP
&&
1347 lease
-> binding_state
!= FTS_RELEASED
&&
1348 lease
-> binding_state
!= FTS_EXPIRED
&&
1349 lease
-> binding_state
!= FTS_RESET
) {
1350 if (lease
-> on_commit
)
1351 executable_statement_dereference (&lease
-> on_commit
,
1354 /* Blow away any bindings. */
1356 binding_scope_dereference (&lease
-> scope
, MDL
);
1357 lease
-> ends
= cur_time
;
1358 #if defined (FAILOVER_PROTOCOL)
1359 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1360 lease
-> next_binding_state
= FTS_RELEASED
;
1362 lease
-> next_binding_state
= FTS_FREE
;
1365 lease
-> next_binding_state
= FTS_FREE
;
1367 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1371 /* Abandon the specified lease (set its timeout to infinity and its
1372 particulars to zero, and re-hash it as appropriate. */
1374 void abandon_lease (lease
, message
)
1375 struct lease
*lease
;
1376 const char *message
;
1378 struct lease
*lt
= (struct lease
*)0;
1380 if (!lease_copy (<
, lease
, MDL
))
1383 lt
-> ends
= cur_time
; /* XXX */
1384 lt
-> next_binding_state
= FTS_ABANDONED
;
1386 log_error ("Abandoning IP address %s: %s",
1387 piaddr (lease
-> ip_addr
), message
);
1388 lt
-> hardware_addr
.hlen
= 0;
1389 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1390 dfree (lt
-> uid
, MDL
);
1391 lt
-> uid
= (unsigned char *)0;
1394 supersede_lease (lease
, lt
, 1, 1, 1);
1395 lease_dereference (<
, MDL
);
1398 /* Abandon the specified lease (set its timeout to infinity and its
1399 particulars to zero, and re-hash it as appropriate. */
1401 void dissociate_lease (lease
)
1402 struct lease
*lease
;
1404 struct lease
*lt
= (struct lease
*)0;
1406 if (!lease_copy (<
, lease
, MDL
))
1409 #if defined (FAILOVER_PROTOCOL)
1410 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1411 lt
-> next_binding_state
= FTS_RESET
;
1413 lt
-> next_binding_state
= FTS_FREE
;
1416 lt
-> next_binding_state
= FTS_FREE
;
1418 lt
-> ends
= cur_time
; /* XXX */
1419 lt
-> hardware_addr
.hlen
= 0;
1420 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1421 dfree (lt
-> uid
, MDL
);
1422 lt
-> uid
= (unsigned char *)0;
1425 supersede_lease (lease
, lt
, 1, 1, 1);
1426 lease_dereference (<
, MDL
);
1429 /* Timer called when a lease in a particular pool expires. */
1430 void pool_timer (vpool
)
1434 struct lease
*lt
= (struct lease
*)0;
1435 struct lease
*next
= (struct lease
*)0;
1436 struct lease
*lease
= (struct lease
*)0;
1437 struct lease
**lptr
[5];
1438 TIME next_expiry
= MAX_TIME
;
1441 pool
= (struct pool
*)vpool
;
1443 #define FREE_LEASES 0
1444 lptr
[FREE_LEASES
] = &pool
-> free
;
1445 #define ACTIVE_LEASES 1
1446 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1447 #define EXPIRED_LEASES 2
1448 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1449 #define ABANDONED_LEASES 3
1450 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1451 #define BACKUP_LEASES 4
1452 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1454 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1455 /* If there's nothing on the queue, skip it. */
1459 #if defined (FAILOVER_PROTOCOL)
1460 if (pool
-> failover_peer
&&
1461 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1462 /* The secondary can't remove a lease from the
1463 active state except in partner_down. */
1464 if (i
== ACTIVE_LEASES
&&
1465 pool
-> failover_peer
-> i_am
== secondary
)
1467 /* Leases in an expired state don't move to
1468 free because of a timeout unless we're in
1470 if (i
== EXPIRED_LEASES
)
1474 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1477 /* Remember the next lease in the list. */
1479 lease_dereference (&next
, MDL
);
1481 lease_reference (&next
, lease
-> next
, MDL
);
1483 /* If we've run out of things to expire on this list,
1485 if (lease
-> sort_time
> cur_time
) {
1486 if (lease
-> sort_time
< next_expiry
)
1487 next_expiry
= lease
-> sort_time
;
1491 /* If there is a pending state change, and
1492 this lease has gotten to the time when the
1493 state change should happen, just call
1494 supersede_lease on it to make the change
1496 if (lease
-> next_binding_state
!=
1497 lease
-> binding_state
)
1498 supersede_lease (lease
,
1499 (struct lease
*)0, 1, 1, 1);
1501 lease_dereference (&lease
, MDL
);
1503 lease_reference (&lease
, next
, MDL
);
1506 lease_dereference (&next
, MDL
);
1508 lease_dereference (&lease
, MDL
);
1510 if (next_expiry
!= MAX_TIME
) {
1511 pool
-> next_event_time
= next_expiry
;
1512 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1513 (tvref_t
)pool_reference
,
1514 (tvunref_t
)pool_dereference
);
1516 pool
-> next_event_time
= MIN_TIME
;
1520 /* Locate the lease associated with a given IP address... */
1522 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1523 const char *file
, int line
)
1525 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1526 addr
.iabuf
, addr
.len
, file
, line
);
1529 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1530 unsigned len
, const char *file
, int line
)
1534 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1537 int find_lease_by_hw_addr (struct lease
**lp
,
1538 const unsigned char *hwaddr
, unsigned hwlen
,
1539 const char *file
, int line
)
1543 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1544 hwaddr
, hwlen
, file
, line
);
1547 /* Add the specified lease to the uid hash. */
1549 void uid_hash_add (lease
)
1550 struct lease
*lease
;
1552 struct lease
*head
= (struct lease
*)0;
1553 struct lease
*next
= (struct lease
*)0;
1556 /* If it's not in the hash, just add it. */
1557 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1558 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1559 lease
-> uid_len
, lease
, MDL
);
1561 /* Otherwise, attach it to the end of the list. */
1562 while (head
-> n_uid
) {
1563 lease_reference (&next
, head
-> n_uid
, MDL
);
1564 lease_dereference (&head
, MDL
);
1565 lease_reference (&head
, next
, MDL
);
1566 lease_dereference (&next
, MDL
);
1568 lease_reference (&head
-> n_uid
, lease
, MDL
);
1569 lease_dereference (&head
, MDL
);
1573 /* Delete the specified lease from the uid hash. */
1575 void uid_hash_delete (lease
)
1576 struct lease
*lease
;
1578 struct lease
*head
= (struct lease
*)0;
1581 /* If it's not in the hash, we have no work to do. */
1582 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1584 lease_dereference (&lease
-> n_uid
, MDL
);
1588 /* If the lease we're freeing is at the head of the list,
1589 remove the hash table entry and add a new one with the
1590 next lease on the list (if there is one). */
1591 if (head
== lease
) {
1592 lease_hash_delete (lease_uid_hash
,
1593 lease
-> uid
, lease
-> uid_len
, MDL
);
1594 if (lease
-> n_uid
) {
1595 lease_hash_add (lease_uid_hash
,
1596 lease
-> n_uid
-> uid
,
1597 lease
-> n_uid
-> uid_len
,
1598 lease
-> n_uid
, MDL
);
1599 lease_dereference (&lease
-> n_uid
, MDL
);
1602 /* Otherwise, look for the lease in the list of leases
1603 attached to the hash table entry, and remove it if
1605 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1606 if (scan
-> n_uid
== lease
) {
1607 lease_dereference (&scan
-> n_uid
, MDL
);
1608 if (lease
-> n_uid
) {
1609 lease_reference (&scan
-> n_uid
,
1610 lease
-> n_uid
, MDL
);
1611 lease_dereference (&lease
-> n_uid
,
1618 lease_dereference (&head
, MDL
);
1621 /* Add the specified lease to the hardware address hash. */
1623 void hw_hash_add (lease
)
1624 struct lease
*lease
;
1626 struct lease
*head
= (struct lease
*)0;
1627 struct lease
*next
= (struct lease
*)0;
1629 /* If it's not in the hash, just add it. */
1630 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1631 lease
-> hardware_addr
.hlen
, MDL
))
1632 lease_hash_add (lease_hw_addr_hash
,
1633 lease
-> hardware_addr
.hbuf
,
1634 lease
-> hardware_addr
.hlen
,
1637 /* Otherwise, attach it to the end of the list. */
1638 while (head
-> n_hw
) {
1639 lease_reference (&next
, head
-> n_hw
, MDL
);
1640 lease_dereference (&head
, MDL
);
1641 lease_reference (&head
, next
, MDL
);
1642 lease_dereference (&next
, MDL
);
1645 lease_reference (&head
-> n_hw
, lease
, MDL
);
1646 lease_dereference (&head
, MDL
);
1650 /* Delete the specified lease from the hardware address hash. */
1652 void hw_hash_delete (lease
)
1653 struct lease
*lease
;
1655 struct lease
*head
= (struct lease
*)0;
1656 struct lease
*next
= (struct lease
*)0;
1658 /* If it's not in the hash, we have no work to do. */
1659 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1660 lease
-> hardware_addr
.hlen
, MDL
)) {
1662 lease_dereference (&lease
-> n_hw
, MDL
);
1666 /* If the lease we're freeing is at the head of the list,
1667 remove the hash table entry and add a new one with the
1668 next lease on the list (if there is one). */
1669 if (head
== lease
) {
1670 lease_hash_delete (lease_hw_addr_hash
,
1671 lease
-> hardware_addr
.hbuf
,
1672 lease
-> hardware_addr
.hlen
, MDL
);
1673 if (lease
-> n_hw
) {
1674 lease_hash_add (lease_hw_addr_hash
,
1675 lease
-> n_hw
-> hardware_addr
.hbuf
,
1676 lease
-> n_hw
-> hardware_addr
.hlen
,
1677 lease
-> n_hw
, MDL
);
1678 lease_dereference (&lease
-> n_hw
, MDL
);
1681 /* Otherwise, look for the lease in the list of leases
1682 attached to the hash table entry, and remove it if
1684 while (head
-> n_hw
) {
1685 if (head
-> n_hw
== lease
) {
1686 lease_dereference (&head
-> n_hw
, MDL
);
1687 if (lease
-> n_hw
) {
1688 lease_reference (&head
-> n_hw
,
1689 lease
-> n_hw
, MDL
);
1690 lease_dereference (&lease
-> n_hw
,
1695 lease_reference (&next
, head
-> n_hw
, MDL
);
1696 lease_dereference (&head
, MDL
);
1697 lease_reference (&head
, next
, MDL
);
1698 lease_dereference (&next
, MDL
);
1702 lease_dereference (&head
, MDL
);
1705 /* Write all interesting leases to permanent storage. */
1707 void write_leases ()
1710 struct shared_network
*s
;
1712 struct host_decl
*hp
;
1713 struct group_object
*gp
;
1714 struct hash_bucket
*hb
;
1717 struct lease
**lptr
[5];
1719 /* Write all the dynamically-created group declarations. */
1720 if (group_name_hash
) {
1722 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1723 for (hb
= group_name_hash
-> buckets
[i
];
1724 hb
; hb
= hb
-> next
) {
1725 gp
= (struct group_object
*)hb
-> value
;
1726 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1727 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1728 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1734 log_info ("Wrote %d group decls to leases file.", num_written
);
1737 /* Write all the deleted host declarations. */
1738 if (host_name_hash
) {
1740 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1741 for (hb
= host_name_hash
-> buckets
[i
];
1742 hb
; hb
= hb
-> next
) {
1743 hp
= (struct host_decl
*)hb
-> value
;
1744 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1745 (hp
-> flags
& HOST_DECL_DELETED
))) {
1751 log_info ("Wrote %d deleted host decls to leases file.",
1755 /* Write all the new, dynamic host declarations. */
1756 if (host_name_hash
) {
1758 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1759 for (hb
= host_name_hash
-> buckets
[i
];
1760 hb
; hb
= hb
-> next
) {
1761 hp
= (struct host_decl
*)hb
-> value
;
1762 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1768 log_info ("Wrote %d new dynamic host decls to leases file.",
1772 #if defined (FAILOVER_PROTOCOL)
1773 /* Write all the failover states. */
1774 dhcp_failover_write_all_states ();
1777 /* Write all the leases. */
1779 for (s
= shared_networks
; s
; s
= s
-> next
) {
1780 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1781 lptr
[FREE_LEASES
] = &p
-> free
;
1782 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1783 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1784 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1785 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1787 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1788 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1789 if (l
-> hardware_addr
.hlen
||
1791 (l
-> binding_state
!= FTS_FREE
)) {
1792 if (!write_lease (l
))
1793 log_fatal ("Can't rewrite lease database");
1800 log_info ("Wrote %d leases to leases file.", num_written
);
1801 if (!commit_leases ())
1802 log_fatal ("Can't commit leases to new database: %m");
1805 int lease_enqueue (struct lease
*comp
)
1807 struct lease
**lq
, *prev
, *lp
;
1809 /* No queue to put it on? */
1813 /* Figure out which queue it's going to. */
1814 switch (comp
-> binding_state
) {
1816 lq
= &comp
-> pool
-> free
;
1817 comp
-> pool
-> free_leases
++;
1818 comp
-> sort_time
= comp
-> ends
;
1824 lq
= &comp
-> pool
-> active
;
1825 comp
-> sort_time
= comp
-> ends
;
1831 lq
= &comp
-> pool
-> expired
;
1832 comp
-> sort_time
= comp
-> ends
;
1837 lq
= &comp
-> pool
-> abandoned
;
1838 comp
-> sort_time
= comp
-> ends
;
1842 lq
= &comp
-> pool
-> backup
;
1843 comp
-> pool
-> backup_leases
++;
1844 comp
-> sort_time
= comp
-> ends
;
1848 log_error ("Lease with bogus binding state: %d",
1849 comp
-> binding_state
);
1850 #if defined (BINDING_STATE_DEBUG)
1856 /* Insertion sort the lease onto the appropriate queue. */
1857 prev
= (struct lease
*)0;
1858 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1859 if (lp
-> sort_time
>= comp
-> sort_time
)
1865 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1866 lease_dereference (&prev
-> next
, MDL
);
1868 lease_reference (&prev
-> next
, comp
, MDL
);
1871 lease_reference (&comp
-> next
, *lq
, MDL
);
1872 lease_dereference (lq
, MDL
);
1874 lease_reference (lq
, comp
, MDL
);
1879 /* For a given lease, sort it onto the right list in its pool and put it
1880 in each appropriate hash, understanding that it's already by definition
1881 in lease_ip_addr_hash. */
1883 void lease_instantiate (const unsigned char *val
, unsigned len
,
1884 struct lease
*lease
)
1886 struct class *class;
1887 /* XXX If the lease doesn't have a pool at this point, it's an
1888 XXX orphan, which we *should* keep around until it expires,
1889 XXX but which right now we just forget. */
1890 if (!lease
-> pool
) {
1891 lease_hash_delete (lease_ip_addr_hash
,
1892 lease
-> ip_addr
.iabuf
,
1893 lease
-> ip_addr
.len
, MDL
);
1897 /* Put the lease on the right queue. */
1898 lease_enqueue (lease
);
1900 /* Record the lease in the uid hash if possible. */
1902 uid_hash_add (lease
);
1905 /* Record it in the hardware address hash if possible. */
1906 if (lease
-> hardware_addr
.hlen
) {
1907 hw_hash_add (lease
);
1910 /* If the lease has a billing class, set up the billing. */
1911 if (lease
-> billing_class
) {
1912 class = (struct class *)0;
1913 class_reference (&class, lease
-> billing_class
, MDL
);
1914 class_dereference (&lease
-> billing_class
, MDL
);
1915 /* If the lease is available for allocation, the billing
1916 is invalid, so we don't keep it. */
1917 if (lease
-> binding_state
== FTS_ACTIVE
||
1918 lease
-> binding_state
== FTS_EXPIRED
||
1919 lease
-> binding_state
== FTS_RELEASED
||
1920 lease
-> binding_state
== FTS_RESET
||
1921 lease
-> binding_state
== FTS_RESERVED
||
1922 lease
-> binding_state
== FTS_BOOTP
)
1923 bill_class (lease
, class);
1924 class_dereference (&class, MDL
);
1929 /* Run expiry events on every pool. This is called on startup so that
1930 any expiry events that occurred after the server stopped and before it
1931 was restarted can be run. At the same time, if failover support is
1932 compiled in, we compute the balance of leases for the pool. */
1934 void expire_all_pools ()
1936 struct shared_network
*s
;
1938 struct hash_bucket
*hb
;
1941 struct lease
**lptr
[5];
1943 /* First, go over the hash list and actually put all the leases
1944 on the appropriate lists. */
1945 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1947 /* Loop through each pool in each shared network and call the
1948 expiry routine on the pool. */
1949 for (s
= shared_networks
; s
; s
= s
-> next
) {
1950 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1953 p
-> lease_count
= 0;
1954 p
-> free_leases
= 0;
1955 p
-> backup_leases
= 0;
1957 lptr
[FREE_LEASES
] = &p
-> free
;
1958 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1959 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1960 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1961 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1963 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1964 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1966 if (l
-> ends
<= cur_time
) {
1967 if (l
-> binding_state
== FTS_FREE
)
1969 else if (l
-> binding_state
== FTS_BACKUP
)
1970 p
-> backup_leases
++;
1972 #if defined (FAILOVER_PROTOCOL)
1973 if (p
-> failover_peer
&&
1974 l
-> tstp
> l
-> tsfp
&&
1975 !(l
-> flags
& ON_UPDATE_QUEUE
))
1976 dhcp_failover_queue_update (l
, 1);
1984 void dump_subnets ()
1987 struct shared_network
*s
;
1990 struct lease
**lptr
[5];
1993 log_info ("Subnets:");
1994 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
1995 log_debug (" Subnet %s", piaddr (n
-> net
));
1996 log_debug (" netmask %s",
1997 piaddr (n
-> netmask
));
1999 log_info ("Shared networks:");
2000 for (s
= shared_networks
; s
; s
= s
-> next
) {
2001 log_info (" %s", s
-> name
);
2002 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2003 lptr
[FREE_LEASES
] = &p
-> free
;
2004 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2005 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2006 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2007 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2009 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2010 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2018 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
)
2019 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
)
2020 HASH_FUNCTIONS (class, const char *, struct class)