3 Server-specific in-memory database support. */
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-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: mdb.c,v 1.67.2.20 2004/09/01 20:19:44 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium. All rights reserved.\n";
41 #include "omapip/hash.h"
43 struct subnet
*subnets
;
44 struct shared_network
*shared_networks
;
45 host_hash_t
*host_hw_addr_hash
;
46 host_hash_t
*host_uid_hash
;
47 host_hash_t
*host_name_hash
;
48 lease_hash_t
*lease_uid_hash
;
49 lease_hash_t
*lease_ip_addr_hash
;
50 lease_hash_t
*lease_hw_addr_hash
;
52 omapi_object_type_t
*dhcp_type_host
;
54 static int find_uid_statement (struct executable_statement
*esp
,
57 struct executable_statement
**evp
= vp
;
59 if (esp
-> op
== supersede_option_statement
&&
61 (esp
-> data
.option
-> option
-> universe
==
63 (esp
-> data
.option
-> option
-> code
==
64 DHO_DHCP_CLIENT_IDENTIFIER
)) {
66 log_error ("dhcp client identifier may not be %s",
67 "specified conditionally.");
69 executable_statement_reference (evp
, esp
, MDL
);
72 log_error ("only one dhcp client identifier may be %s",
79 isc_result_t
enter_host (hd
, dynamicp
, commit
)
84 struct host_decl
*hp
= (struct host_decl
*)0;
85 struct host_decl
*np
= (struct host_decl
*)0;
86 struct executable_statement
*esp
;
88 if (!host_name_hash
) {
89 if (!host_new_hash (&host_name_hash
, 0, MDL
))
90 log_fatal ("Can't allocate host name hash");
91 host_hash_add (host_name_hash
,
92 (unsigned char *)hd
-> name
,
93 strlen (hd
-> name
), hd
, MDL
);
95 host_hash_lookup (&hp
, host_name_hash
,
96 (unsigned char *)hd
-> name
,
97 strlen (hd
-> name
), MDL
);
99 /* If it's deleted, we can supersede it. */
100 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
101 host_hash_delete (host_name_hash
,
102 (unsigned char *)hd
-> name
,
103 strlen (hd
-> name
), MDL
);
104 /* If the old entry wasn't dynamic, then we
105 always have to keep the deletion. */
106 if (hp
-> flags
& HOST_DECL_STATIC
) {
107 hd
-> flags
|= HOST_DECL_STATIC
;
109 host_dereference (&hp
, MDL
);
112 /* If we are updating an existing host declaration, we
113 can just delete it and add it again. */
114 if (hp
&& hp
== hd
) {
115 host_dereference (&hp
, MDL
);
117 if (!write_host (hd
))
118 return ISC_R_IOERROR
;
119 hd
-> flags
&= ~HOST_DECL_DELETED
;
122 /* If there isn't already a host decl matching this
123 address, add it to the hash table. */
125 host_hash_add (host_name_hash
,
126 (unsigned char *)hd
-> name
,
127 strlen (hd
-> name
), hd
, MDL
);
129 /* XXX actually, we have to delete the old one
130 XXX carefully and replace it. Not done yet. */
131 host_dereference (&hp
, MDL
);
137 host_dereference (&hd
-> n_ipaddr
, MDL
);
140 hd
-> type
= dhcp_type_host
;
142 if (hd
-> interface
.hlen
) {
143 if (!host_hw_addr_hash
) {
144 if (!host_new_hash (&host_hw_addr_hash
, 0, MDL
))
145 log_fatal ("Can't allocate host/hw hash");
147 /* If there isn't already a host decl matching this
148 address, add it to the hash table. */
149 host_hash_lookup (&hp
, host_hw_addr_hash
,
150 hd
-> interface
.hbuf
,
151 hd
-> interface
.hlen
, MDL
);
154 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
155 hd
-> interface
.hlen
, hd
, MDL
);
157 /* If there was already a host declaration for
158 this hardware address, add this one to the
160 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
162 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
163 host_dereference (&hp
, MDL
);
167 /* See if there's a statement that sets the client identifier.
168 This is a kludge - the client identifier really shouldn't be
169 set with an executable statement. */
170 esp
= (struct executable_statement
*)0;
171 if (executable_statement_foreach (hd
-> group
-> statements
,
172 find_uid_statement
, &esp
, 0)) {
173 evaluate_option_cache (&hd
-> client_identifier
,
176 (struct client_state
*)0,
177 (struct option_state
*)0,
178 (struct option_state
*)0, &global_scope
,
179 esp
-> data
.option
, MDL
);
182 /* If we got a client identifier, hash this entry by
183 client identifier. */
184 if (hd
-> client_identifier
.len
) {
185 /* If there's no uid hash, make one; otherwise, see if
186 there's already an entry in the hash for this host. */
187 if (!host_uid_hash
) {
188 if (!host_new_hash (&host_uid_hash
, 0, MDL
))
189 log_fatal ("Can't allocate host/uid hash");
191 host_hash_add (host_uid_hash
,
192 hd
-> client_identifier
.data
,
193 hd
-> client_identifier
.len
,
196 /* If there's already a host declaration for this
197 client identifier, add this one to the end of the
198 list. Otherwise, add it to the hash table. */
199 if (host_hash_lookup (&hp
, host_uid_hash
,
200 hd
-> client_identifier
.data
,
201 hd
-> client_identifier
.len
,
203 /* Don't link it in twice... */
205 for (np
= hp
; np
-> n_ipaddr
;
206 np
= np
-> n_ipaddr
) {
211 host_reference (&np
-> n_ipaddr
,
214 host_dereference (&hp
, MDL
);
216 host_hash_add (host_uid_hash
,
217 hd
-> client_identifier
.data
,
218 hd
-> client_identifier
.len
,
224 if (dynamicp
&& commit
) {
225 if (!write_host (hd
))
226 return ISC_R_IOERROR
;
227 if (!commit_leases ())
228 return ISC_R_IOERROR
;
231 return ISC_R_SUCCESS
;
234 isc_result_t
delete_host (hd
, commit
)
235 struct host_decl
*hd
;
238 struct host_decl
*hp
= (struct host_decl
*)0;
239 struct host_decl
*np
= (struct host_decl
*)0;
240 struct host_decl
*foo
;
241 struct executable_statement
*esp
;
242 int hw_head
= 0, uid_head
= 1;
244 /* Don't need to do it twice. */
245 if (hd
-> flags
& HOST_DECL_DELETED
)
246 return ISC_R_SUCCESS
;
248 /* But we do need to do it once! :') */
249 hd
-> flags
|= HOST_DECL_DELETED
;
251 if (hd
-> interface
.hlen
) {
252 if (host_hw_addr_hash
) {
253 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
254 hd
-> interface
.hbuf
,
255 hd
-> interface
.hlen
, MDL
)) {
257 host_hash_delete (host_hw_addr_hash
,
258 hd
-> interface
.hbuf
,
259 hd
-> interface
.hlen
, MDL
);
262 np
= (struct host_decl
*)0;
263 foo
= (struct host_decl
*)0;
264 host_reference (&foo
, hp
, MDL
);
269 host_dereference (&np
, MDL
);
270 host_reference (&np
, foo
, MDL
);
271 host_dereference (&foo
, MDL
);
273 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
277 host_dereference (&np
-> n_ipaddr
, MDL
);
279 host_reference (&np
-> n_ipaddr
,
280 hd
-> n_ipaddr
, MDL
);
281 host_dereference (&foo
, MDL
);
284 host_dereference (&np
, MDL
);
286 host_dereference (&hp
, MDL
);
291 /* If we got a client identifier, hash this entry by
292 client identifier. */
293 if (hd
-> client_identifier
.len
) {
295 if (host_hash_lookup (&hp
, host_uid_hash
,
296 hd
-> client_identifier
.data
,
297 hd
-> client_identifier
.len
, MDL
)) {
299 host_hash_delete (host_uid_hash
,
300 hd
-> client_identifier
.data
,
301 hd
-> client_identifier
.len
, MDL
);
304 np
= (struct host_decl
*)0;
305 foo
= (struct host_decl
*)0;
306 host_reference (&foo
, hp
, MDL
);
311 host_dereference (&np
, MDL
);
312 host_reference (&np
, foo
, MDL
);
313 host_dereference (&foo
, MDL
);
315 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
319 host_dereference (&np
-> n_ipaddr
, MDL
);
321 host_reference (&np
-> n_ipaddr
,
322 hd
-> n_ipaddr
, MDL
);
323 host_dereference (&foo
, MDL
);
326 host_dereference (&np
, MDL
);
328 host_dereference (&hp
, MDL
);
333 if (hd
-> n_ipaddr
) {
334 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
337 hd
-> n_ipaddr
-> client_identifier
.data
,
338 hd
-> n_ipaddr
-> client_identifier
.len
,
339 hd
-> n_ipaddr
, MDL
);
341 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
342 host_hash_add (host_hw_addr_hash
,
343 hd
-> n_ipaddr
-> interface
.hbuf
,
344 hd
-> n_ipaddr
-> interface
.hlen
,
345 hd
-> n_ipaddr
, MDL
);
347 host_dereference (&hd
-> n_ipaddr
, MDL
);
350 if (host_name_hash
) {
351 if (host_hash_lookup (&hp
, host_name_hash
,
352 (unsigned char *)hd
-> name
,
353 strlen (hd
-> name
), MDL
)) {
354 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
355 host_hash_delete (host_name_hash
,
356 (unsigned char *)hd
-> name
,
357 strlen (hd
-> name
), MDL
);
359 host_dereference (&hp
, MDL
);
364 if (!write_host (hd
))
365 return ISC_R_IOERROR
;
366 if (!commit_leases ())
367 return ISC_R_IOERROR
;
369 return ISC_R_SUCCESS
;
372 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
373 const unsigned char *haddr
, unsigned hlen
,
374 const char *file
, int line
)
376 struct host_decl
*foo
;
381 memcpy (&h
.hbuf
[1], haddr
, hlen
);
383 return host_hash_lookup (hp
, host_hw_addr_hash
,
384 h
.hbuf
, h
.hlen
, file
, line
);
387 int find_hosts_by_uid (struct host_decl
**hp
,
388 const unsigned char *data
, unsigned len
,
389 const char *file
, int line
)
391 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
394 /* More than one host_decl can be returned by find_hosts_by_haddr or
395 find_hosts_by_uid, and each host_decl can have multiple addresses.
396 Loop through the list of hosts, and then for each host, through the
397 list of addresses, looking for an address that's in the same shared
398 network as the one specified. Store the matching address through
399 the addr pointer, update the host pointer to point at the host_decl
400 that matched, and return the subnet that matched. */
402 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
403 struct iaddr
*addr
, struct shared_network
*share
)
406 struct subnet
*subnet
;
407 struct iaddr ip_address
;
408 struct host_decl
*hp
;
409 struct data_string fixed_addr
;
411 memset (&fixed_addr
, 0, sizeof fixed_addr
);
413 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
414 if (!hp
-> fixed_addr
)
416 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
418 (struct client_state
*)0,
419 (struct option_state
*)0,
420 (struct option_state
*)0,
422 hp
-> fixed_addr
, MDL
))
424 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
426 memcpy (ip_address
.iabuf
,
427 fixed_addr
.data
+ i
, 4);
428 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
429 struct host_decl
*tmp
= (struct host_decl
*)0;
431 /* This is probably not necessary, but
432 just in case *host is the only reference
433 to that host declaration, make a temporary
434 reference so that dereferencing it doesn't
435 dereference hp out from under us. */
436 host_reference (&tmp
, *host
, MDL
);
437 host_dereference (host
, MDL
);
438 host_reference (host
, hp
, MDL
);
439 host_dereference (&tmp
, MDL
);
440 data_string_forget (&fixed_addr
, MDL
);
444 data_string_forget (&fixed_addr
, MDL
);
449 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
451 struct iaddr low
, high
;
452 struct subnet
*subnet
;
454 struct lease
**lpchain
;
456 struct lease
*address_range
, *lp
, *plp
;
458 unsigned min
, max
, i
;
459 char lowbuf
[16], highbuf
[16], netbuf
[16];
460 struct shared_network
*share
= subnet
-> shared_network
;
462 struct lease
*lt
= (struct lease
*)0;
464 /* All subnets should have attached shared network structures. */
466 strcpy (netbuf
, piaddr (subnet
-> net
));
467 log_fatal ("No shared network for network %s (%s)",
468 netbuf
, piaddr (subnet
-> netmask
));
471 /* Initialize the hash table if it hasn't been done yet. */
472 if (!lease_uid_hash
) {
473 if (!lease_new_hash (&lease_uid_hash
, 0, MDL
))
474 log_fatal ("Can't allocate lease/uid hash");
476 if (!lease_ip_addr_hash
) {
477 if (!lease_new_hash (&lease_ip_addr_hash
, 0, MDL
))
478 log_fatal ("Can't allocate lease/ip hash");
480 if (!lease_hw_addr_hash
) {
481 if (!lease_new_hash (&lease_hw_addr_hash
, 0, MDL
))
482 log_fatal ("Can't allocate lease/hw hash");
485 /* Make sure that high and low addresses are in same subnet. */
486 net
= subnet_number (low
, subnet
-> netmask
);
487 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
488 strcpy (lowbuf
, piaddr (low
));
489 strcpy (highbuf
, piaddr (high
));
490 strcpy (netbuf
, piaddr (subnet
-> netmask
));
491 log_fatal ("Address range %s to %s, netmask %s spans %s!",
492 lowbuf
, highbuf
, netbuf
, "multiple subnets");
495 /* Make sure that the addresses are on the correct subnet. */
496 if (!addr_eq (net
, subnet
-> net
)) {
497 strcpy (lowbuf
, piaddr (low
));
498 strcpy (highbuf
, piaddr (high
));
499 strcpy (netbuf
, piaddr (subnet
-> netmask
));
500 log_fatal ("Address range %s to %s not on net %s/%s!",
501 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
504 /* Get the high and low host addresses... */
505 max
= host_addr (high
, subnet
-> netmask
);
506 min
= host_addr (low
, subnet
-> netmask
);
508 /* Allow range to be specified high-to-low as well as low-to-high. */
511 min
= host_addr (high
, subnet
-> netmask
);
514 /* Get a lease structure for each address in the range. */
515 #if defined (COMPACT_LEASES)
516 address_range
= new_leases (max
- min
+ 1, MDL
);
517 if (!address_range
) {
518 strcpy (lowbuf
, piaddr (low
));
519 strcpy (highbuf
, piaddr (high
));
520 log_fatal ("No memory for address range %s-%s.",
525 /* Fill out the lease structures with some minimal information. */
526 for (i
= 0; i
< max
- min
+ 1; i
++) {
527 struct lease
*lp
= (struct lease
*)0;
528 #if defined (COMPACT_LEASES)
529 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
531 0, sizeof (struct lease
), MDL
);
532 lease_reference (&lp
, &address_range
[i
], MDL
);
534 status
= lease_allocate (&lp
, MDL
);
535 if (status
!= ISC_R_SUCCESS
)
536 log_fatal ("No memory for lease %s: %s",
537 piaddr (ip_addr (subnet
-> net
,
540 isc_result_totext (status
));
542 lp
-> ip_addr
= ip_addr (subnet
-> net
,
543 subnet
-> netmask
, i
+ min
);
544 lp
-> starts
= lp
-> timestamp
= MIN_TIME
;
545 lp
-> ends
= MIN_TIME
;
546 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
547 pool_reference (&lp
-> pool
, pool
, MDL
);
548 lp
-> binding_state
= FTS_FREE
;
549 lp
-> next_binding_state
= FTS_FREE
;
552 /* Remember the lease in the IP address hash. */
553 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
556 "lease %s is declared twice!",
557 piaddr (lp
-> ip_addr
));
559 pool_reference (<
-> pool
, pool
, MDL
);
560 lease_dereference (<
, MDL
);
562 lease_hash_add (lease_ip_addr_hash
,
564 lp
-> ip_addr
.len
, lp
, MDL
);
565 /* Put the lease on the chain for the caller. */
568 lease_reference (&lp
-> next
, *lpchain
, MDL
);
569 lease_dereference (lpchain
, MDL
);
571 lease_reference (lpchain
, lp
, MDL
);
573 lease_dereference (&lp
, MDL
);
577 int find_subnet (struct subnet
**sp
,
578 struct iaddr addr
, const char *file
, int line
)
582 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
583 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
584 if (subnet_reference (sp
, rv
,
585 file
, line
) != ISC_R_SUCCESS
)
593 int find_grouped_subnet (struct subnet
**sp
,
594 struct shared_network
*share
, struct iaddr addr
,
595 const char *file
, int line
)
599 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
600 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
601 if (subnet_reference (sp
, rv
,
602 file
, line
) != ISC_R_SUCCESS
)
610 int subnet_inner_than (subnet
, scan
, warnp
)
611 struct subnet
*subnet
, *scan
;
614 if (addr_eq (subnet_number (subnet
-> net
, scan
-> netmask
),
616 addr_eq (subnet_number (scan
-> net
, subnet
-> netmask
),
620 for (i
= 0; i
< 32; i
++)
621 if (subnet
-> netmask
.iabuf
[3 - (i
>> 3)]
624 for (j
= 0; j
< 32; j
++)
625 if (scan
-> netmask
.iabuf
[3 - (j
>> 3)] &
628 strcpy (n1buf
, piaddr (subnet
-> net
));
630 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
631 "Warning: ", n1buf
, 32 - i
,
632 piaddr (scan
-> net
), 32 - j
);
639 /* Enter a new subnet into the subnet list. */
640 void enter_subnet (subnet
)
641 struct subnet
*subnet
;
643 struct subnet
*scan
= (struct subnet
*)0;
644 struct subnet
*next
= (struct subnet
*)0;
645 struct subnet
*prev
= (struct subnet
*)0;
647 /* Check for duplicates... */
649 subnet_reference (&next
, subnets
, MDL
);
651 subnet_reference (&scan
, next
, MDL
);
652 subnet_dereference (&next
, MDL
);
654 /* When we find a conflict, make sure that the
655 subnet with the narrowest subnet mask comes
657 if (subnet_inner_than (subnet
, scan
, 1)) {
659 if (prev
-> next_subnet
)
660 subnet_dereference (&prev
-> next_subnet
, MDL
);
661 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
662 subnet_dereference (&prev
, MDL
);
664 subnet_dereference (&subnets
, MDL
);
665 subnet_reference (&subnets
, subnet
, MDL
);
667 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
668 subnet_dereference (&scan
, MDL
);
671 subnet_reference (&prev
, scan
, MDL
);
672 subnet_dereference (&scan
, MDL
);
675 subnet_dereference (&prev
, MDL
);
677 /* XXX use the BSD radix tree code instead of a linked list. */
679 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
680 subnet_dereference (&subnets
, MDL
);
682 subnet_reference (&subnets
, subnet
, MDL
);
685 /* Enter a new shared network into the shared network list. */
687 void enter_shared_network (share
)
688 struct shared_network
*share
;
690 if (shared_networks
) {
691 shared_network_reference (&share
-> next
,
692 shared_networks
, MDL
);
693 shared_network_dereference (&shared_networks
, MDL
);
695 shared_network_reference (&shared_networks
, share
, MDL
);
698 void new_shared_network_interface (cfile
, share
, name
)
700 struct shared_network
*share
;
703 struct interface_info
*ip
;
706 if (share
-> interface
) {
708 "A subnet or shared network can't be connected %s",
709 "to two interfaces.");
713 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
714 if (!strcmp (ip
-> name
, name
))
717 status
= interface_allocate (&ip
, MDL
);
718 if (status
!= ISC_R_SUCCESS
)
719 log_fatal ("new_shared_network_interface %s: %s",
720 name
, isc_result_totext (status
));
721 if (strlen (name
) > sizeof ip
-> name
) {
722 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
723 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
725 strcpy (ip
-> name
, name
);
727 interface_reference (&ip
-> next
, interfaces
, MDL
);
728 interface_dereference (&interfaces
, MDL
);
730 interface_reference (&interfaces
, ip
, MDL
);
731 ip
-> flags
= INTERFACE_REQUESTED
;
732 /* XXX this is a reference loop. */
733 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
734 interface_reference (&share
-> interface
, ip
, MDL
);
738 /* Enter a lease into the system. This is called by the parser each
739 time it reads in a new lease. If the subnet for that lease has
740 already been read in (usually the case), just update that lease;
741 otherwise, allocate temporary storage for the lease and keep it around
742 until we're done reading in the config file. */
744 void enter_lease (lease
)
747 struct lease
*comp
= (struct lease
*)0;
750 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
752 log_error ("undeclared lease found in database: %s",
753 piaddr (lease
-> ip_addr
));
755 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
758 subnet_reference (&lease
-> subnet
,
759 comp
-> subnet
, MDL
);
760 lease_hash_delete (lease_ip_addr_hash
,
761 lease
-> ip_addr
.iabuf
,
762 lease
-> ip_addr
.len
, MDL
);
763 lease_dereference (&comp
, MDL
);
766 /* The only way a lease can get here without a subnet is if it's in
767 the lease file, but not in the dhcpd.conf file. In this case, we
768 *should* keep it around until it's expired, but never reallocate it
769 or renew it. Currently, to maintain consistency, we are not doing
771 XXX fix this so that the lease is kept around until it expires.
772 XXX this will be important in IPv6 with addresses that become
773 XXX non-renewable as a result of a renumbering event. */
775 if (!lease
-> subnet
) {
776 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
779 lease_hash_add (lease_ip_addr_hash
,
780 lease
-> ip_addr
.iabuf
,
781 lease
-> ip_addr
.len
, lease
, MDL
);
784 /* Replace the data in an existing lease with the data in a new lease;
785 adjust hash tables to suit, and insertion sort the lease into the
786 list of leases by expiry time so that we can always find the oldest
789 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
790 struct lease
*comp
, *lease
;
796 int enter_hwaddr
= 0;
797 struct lease
*lp
, **lq
, *prev
;
800 #if defined (FAILOVER_PROTOCOL)
801 /* We must commit leases before sending updates regarding them
802 to failover peers. It is, therefore, an error to set pimmediate
804 if (pimmediate
&& !commit
)
808 /* If there is no sample lease, just do the move. */
812 /* Static leases are not currently kept in the database... */
813 if (lease
-> flags
& STATIC_LEASE
)
816 /* If the existing lease hasn't expired and has a different
817 unique identifier or, if it doesn't have a unique
818 identifier, a different hardware address, then the two
819 leases are in conflict. If the existing lease has a uid
820 and the new one doesn't, but they both have the same
821 hardware address, and dynamic bootp is allowed on this
822 lease, then we allow that, in case a dynamic BOOTP lease is
823 requested *after* a DHCP lease has been assigned. */
825 if (lease
-> binding_state
!= FTS_ABANDONED
&&
826 lease
-> next_binding_state
!= FTS_ABANDONED
&&
827 comp
-> binding_state
== FTS_ACTIVE
&&
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
));
841 /* If there's a Unique ID, dissociate it from the hash
842 table and free it if necessary. */
844 uid_hash_delete (comp
);
846 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
847 dfree (comp
-> uid
, MDL
);
851 comp
-> uid
= (unsigned char *)0;
855 if (comp
-> hardware_addr
.hlen
&&
856 ((comp
-> hardware_addr
.hlen
!=
857 lease
-> hardware_addr
.hlen
) ||
858 memcmp (comp
-> hardware_addr
.hbuf
,
859 lease
-> hardware_addr
.hbuf
,
860 comp
-> hardware_addr
.hlen
))) {
861 hw_hash_delete (comp
);
863 } else if (!comp
-> hardware_addr
.hlen
)
866 /* If the lease has been billed to a class, remove the billing. */
867 if (comp
-> billing_class
!= lease
-> billing_class
) {
868 if (comp
-> billing_class
)
869 unbill_class (comp
, comp
-> billing_class
);
870 if (lease
-> billing_class
)
871 bill_class (comp
, lease
-> billing_class
);
874 /* Copy the data files, but not the linkages. */
875 comp
-> starts
= lease
-> starts
;
877 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
878 memcpy (comp
-> uid_buf
,
879 lease
-> uid
, lease
-> uid_len
);
880 comp
-> uid
= &comp
-> uid_buf
[0];
881 comp
-> uid_max
= sizeof comp
-> uid_buf
;
882 comp
-> uid_len
= lease
-> uid_len
;
883 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
884 comp
-> uid
= lease
-> uid
;
885 comp
-> uid_max
= lease
-> uid_max
;
886 lease
-> uid
= (unsigned char *)0;
887 lease
-> uid_max
= 0;
888 comp
-> uid_len
= lease
-> uid_len
;
889 lease
-> uid_len
= 0;
891 log_fatal ("corrupt lease uid."); /* XXX */
894 comp
-> uid
= (unsigned char *)0;
895 comp
-> uid_len
= comp
-> uid_max
= 0;
898 host_dereference (&comp
-> host
, MDL
);
899 host_reference (&comp
-> host
, lease
-> host
, MDL
);
900 comp
-> hardware_addr
= lease
-> hardware_addr
;
901 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
902 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
904 binding_scope_dereference (&comp
-> scope
, MDL
);
905 if (lease
-> scope
) {
906 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
907 binding_scope_dereference (&lease
-> scope
, MDL
);
910 if (comp
-> agent_options
)
911 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
912 if (lease
-> agent_options
) {
913 /* Only retain the agent options if the lease is still
914 affirmatively associated with a client. */
915 if (lease
-> next_binding_state
== FTS_ACTIVE
||
916 lease
-> next_binding_state
== FTS_EXPIRED
)
917 option_chain_head_reference (&comp
-> agent_options
,
918 lease
-> agent_options
,
920 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
923 /* Record the hostname information in the lease. */
924 if (comp
-> client_hostname
)
925 dfree (comp
-> client_hostname
, MDL
);
926 comp
-> client_hostname
= lease
-> client_hostname
;
927 lease
-> client_hostname
= (char *)0;
929 if (lease
-> on_expiry
) {
930 if (comp
-> on_expiry
)
931 executable_statement_dereference (&comp
-> on_expiry
,
933 executable_statement_reference (&comp
-> on_expiry
,
937 if (lease
-> on_commit
) {
938 if (comp
-> on_commit
)
939 executable_statement_dereference (&comp
-> on_commit
,
941 executable_statement_reference (&comp
-> on_commit
,
945 if (lease
-> on_release
) {
946 if (comp
-> on_release
)
947 executable_statement_dereference (&comp
-> on_release
,
949 executable_statement_reference (&comp
-> on_release
,
950 lease
-> on_release
, MDL
);
953 /* Record the lease in the uid hash if necessary. */
954 if (enter_uid
&& comp
-> uid
) {
958 /* Record it in the hardware address hash if necessary. */
959 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
963 #if defined (FAILOVER_PROTOCOL)
964 comp
-> cltt
= lease
-> cltt
;
965 comp
-> tstp
= lease
-> tstp
;
966 comp
-> tsfp
= lease
-> tsfp
;
967 #endif /* FAILOVER_PROTOCOL */
968 comp
-> ends
= lease
-> ends
;
969 comp
-> next_binding_state
= lease
-> next_binding_state
;
973 log_error ("Supersede_lease: lease %s with no pool.",
974 piaddr (comp
-> ip_addr
));
978 /* Figure out which queue it's on. */
979 switch (comp
-> binding_state
) {
981 lq
= &comp
-> pool
-> free
;
982 comp
-> pool
-> free_leases
--;
986 lq
= &comp
-> pool
-> active
;
992 lq
= &comp
-> pool
-> expired
;
996 lq
= &comp
-> pool
-> abandoned
;
1000 lq
= &comp
-> pool
-> backup
;
1001 comp
-> pool
-> backup_leases
--;
1005 log_error ("Lease with bogus binding state: %d",
1006 comp
-> binding_state
);
1007 #if defined (BINDING_STATE_DEBUG)
1013 /* Remove the lease from its current place in its current
1015 prev
= (struct lease
*)0;
1016 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1023 log_error ("Lease with binding state %s not on its queue.",
1024 (comp
-> binding_state
< 1 ||
1025 comp
-> binding_state
> FTS_LAST
)
1027 : binding_state_names
[comp
-> binding_state
- 1]);
1032 lease_dereference (&prev
-> next
, MDL
);
1034 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1035 lease_dereference (&comp
-> next
, MDL
);
1038 lease_dereference (lq
, MDL
);
1040 lease_reference (lq
, comp
-> next
, MDL
);
1041 lease_dereference (&comp
-> next
, MDL
);
1045 /* Make the state transition. */
1046 if (commit
|| !pimmediate
)
1047 make_binding_state_transition (comp
);
1049 /* Put the lease back on the appropriate queue. If the lease
1050 is corrupt (as detected by lease_enqueue), don't go any farther. */
1051 if (!lease_enqueue (comp
))
1054 /* If this is the next lease that will timeout on the pool,
1055 zap the old timeout and set the timeout on this pool to the
1056 time that the lease's next event will happen.
1058 We do not actually set the timeout unless commit is true -
1059 we don't want to thrash the timer queue when reading the
1060 lease database. Instead, the database code calls the
1061 expiry event on each pool after reading in the lease file,
1062 and the expiry code sets the timer if there's anything left
1063 to expire after it's run any outstanding expiry events on
1065 if ((commit
|| !pimmediate
) &&
1066 comp
-> sort_time
!= MIN_TIME
&&
1067 comp
-> sort_time
> cur_time
&&
1068 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1069 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1070 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1071 add_timeout (comp
-> pool
-> next_event_time
,
1072 pool_timer
, comp
-> pool
,
1073 (tvref_t
)pool_reference
,
1074 (tvunref_t
)pool_dereference
);
1078 if (!write_lease (comp
))
1080 if (!commit_leases ())
1084 #if defined (FAILOVER_PROTOCOL)
1086 comp
-> desired_binding_state
= comp
-> binding_state
;
1087 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1092 /* If the current binding state has already expired, do an
1093 expiry event right now. */
1094 /* XXX At some point we should optimize this so that we don't
1095 XXX write the lease twice, but this is a safe way to fix the
1096 XXX problem for 3.0 (I hope!). */
1097 if ((commit
|| !pimmediate
) &&
1098 comp
-> sort_time
< cur_time
&&
1099 comp
-> next_binding_state
!= comp
-> binding_state
)
1100 pool_timer (comp
-> pool
);
1105 void make_binding_state_transition (struct lease
*lease
)
1107 #if defined (FAILOVER_PROTOCOL)
1108 dhcp_failover_state_t
*peer
;
1110 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1111 peer
= lease
-> pool
-> failover_peer
;
1113 peer
= (dhcp_failover_state_t
*)0;
1116 /* If the lease was active and is now no longer active, but isn't
1117 released, then it just expired, so do the expiry event. */
1118 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1120 #if defined (FAILOVER_PROTOCOL)
1122 (lease
-> binding_state
== FTS_EXPIRED
||
1123 (peer
-> i_am
== secondary
&&
1124 lease
-> binding_state
== FTS_ACTIVE
)) &&
1125 (lease
-> next_binding_state
== FTS_FREE
||
1126 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1129 lease
-> binding_state
== FTS_ACTIVE
&&
1130 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1131 #if defined (NSUPDATE)
1132 ddns_removals (lease
);
1134 if (lease
-> on_expiry
) {
1135 execute_statements ((struct binding_value
**)0,
1136 (struct packet
*)0, lease
,
1137 (struct client_state
*)0,
1138 (struct option_state
*)0,
1139 (struct option_state
*)0, /* XXX */
1141 lease
-> on_expiry
);
1142 if (lease
-> on_expiry
)
1143 executable_statement_dereference
1144 (&lease
-> on_expiry
, MDL
);
1147 /* No sense releasing a lease after it's expired. */
1148 if (lease
-> on_release
)
1149 executable_statement_dereference (&lease
-> on_release
,
1151 /* Get rid of client-specific bindings that are only
1152 correct when the lease is active. */
1153 if (lease
-> billing_class
)
1154 unbill_class (lease
, lease
-> billing_class
);
1155 if (lease
-> agent_options
)
1156 option_chain_head_dereference (&lease
-> agent_options
,
1158 if (lease
-> client_hostname
) {
1159 dfree (lease
-> client_hostname
, MDL
);
1160 lease
-> client_hostname
= (char *)0;
1163 host_dereference (&lease
-> host
, MDL
);
1165 /* Send the expiry time to the peer. */
1166 lease
-> tstp
= lease
-> ends
;
1169 /* If the lease was active and is now released, do the release
1171 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1173 #if defined (FAILOVER_PROTOCOL)
1175 lease
-> binding_state
== FTS_RELEASED
&&
1176 (lease
-> next_binding_state
== FTS_FREE
||
1177 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1180 lease
-> binding_state
== FTS_ACTIVE
&&
1181 lease
-> next_binding_state
== FTS_RELEASED
))) {
1182 #if defined (NSUPDATE)
1183 ddns_removals (lease
);
1185 if (lease
-> on_release
) {
1186 execute_statements ((struct binding_value
**)0,
1187 (struct packet
*)0, lease
,
1188 (struct client_state
*)0,
1189 (struct option_state
*)0,
1190 (struct option_state
*)0, /* XXX */
1192 lease
-> on_release
);
1193 executable_statement_dereference (&lease
-> on_release
,
1197 /* A released lease can't expire. */
1198 if (lease
-> on_expiry
)
1199 executable_statement_dereference (&lease
-> on_expiry
,
1202 /* Get rid of client-specific bindings that are only
1203 correct when the lease is active. */
1204 if (lease
-> billing_class
)
1205 unbill_class (lease
, lease
-> billing_class
);
1206 if (lease
-> agent_options
)
1207 option_chain_head_dereference (&lease
-> agent_options
,
1209 if (lease
-> client_hostname
) {
1210 dfree (lease
-> client_hostname
, MDL
);
1211 lease
-> client_hostname
= (char *)0;
1214 host_dereference (&lease
-> host
, MDL
);
1216 /* Send the release time (should be == cur_time) to the
1218 lease
-> tstp
= lease
-> ends
;
1221 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1222 log_debug ("lease %s moves from %s to %s",
1223 piaddr (lease
-> ip_addr
),
1224 binding_state_print (lease
-> binding_state
),
1225 binding_state_print (lease
-> next_binding_state
));
1228 lease
-> binding_state
= lease
-> next_binding_state
;
1229 switch (lease
-> binding_state
) {
1231 #if defined (FAILOVER_PROTOCOL)
1232 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1233 lease
-> next_binding_state
= FTS_EXPIRED
;
1236 lease
-> next_binding_state
= FTS_FREE
;
1243 lease
-> next_binding_state
= FTS_FREE
;
1244 /* If we are not in partner_down, leases don't go from
1245 EXPIRED to FREE on a timeout - only on an update.
1246 If we're in partner_down, they expire at mclt past
1247 the time we entered partner_down. */
1248 if (lease
-> pool
-> failover_peer
&&
1249 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1251 (lease
-> pool
-> failover_peer
-> me
.stos
+
1252 lease
-> pool
-> failover_peer
-> mclt
);
1257 lease
-> next_binding_state
= lease
-> binding_state
;
1260 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1261 log_debug ("lease %s: next binding state %s",
1262 piaddr (lease
-> ip_addr
),
1263 binding_state_print (lease
-> next_binding_state
));
1268 /* Copy the contents of one lease into another, correctly maintaining
1269 reference counts. */
1270 int lease_copy (struct lease
**lp
,
1271 struct lease
*lease
, const char *file
, int line
)
1273 struct lease
*lt
= (struct lease
*)0;
1274 isc_result_t status
;
1276 status
= lease_allocate (<
, MDL
);
1277 if (status
!= ISC_R_SUCCESS
)
1280 lt
-> ip_addr
= lease
-> ip_addr
;
1281 lt
-> starts
= lease
-> starts
;
1282 lt
-> ends
= lease
-> ends
;
1283 lt
-> timestamp
= lease
-> timestamp
;
1284 lt
-> uid_len
= lease
-> uid_len
;
1285 lt
-> uid_max
= lease
-> uid_max
;
1286 if (lease
-> uid
== lease
-> uid_buf
) {
1287 lt
-> uid
= lt
-> uid_buf
;
1288 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1289 } else if (!lease
-> uid_max
) {
1290 lt
-> uid
= (unsigned char *)0;
1292 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1294 lease_dereference (<
, MDL
);
1297 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1299 if (lease
-> client_hostname
) {
1300 lt
-> client_hostname
=
1301 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1302 if (!lt
-> client_hostname
) {
1303 lease_dereference (<
, MDL
);
1306 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1309 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1310 if (lease
-> agent_options
)
1311 option_chain_head_reference (<
-> agent_options
,
1312 lease
-> agent_options
, MDL
);
1313 host_reference (<
-> host
, lease
-> host
, file
, line
);
1314 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1315 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1316 class_reference (<
-> billing_class
,
1317 lease
-> billing_class
, file
, line
);
1318 lt
-> hardware_addr
= lease
-> hardware_addr
;
1319 if (lease
-> on_expiry
)
1320 executable_statement_reference (<
-> on_expiry
,
1323 if (lease
-> on_commit
)
1324 executable_statement_reference (<
-> on_commit
,
1327 if (lease
-> on_release
)
1328 executable_statement_reference (<
-> on_release
,
1329 lease
-> on_release
,
1331 lt
-> flags
= lease
-> flags
;
1332 lt
-> tstp
= lease
-> tstp
;
1333 lt
-> tsfp
= lease
-> tsfp
;
1334 lt
-> cltt
= lease
-> cltt
;
1335 lt
-> binding_state
= lease
-> binding_state
;
1336 lt
-> next_binding_state
= lease
-> next_binding_state
;
1337 status
= lease_reference (lp
, lt
, file
, line
);
1338 lease_dereference (<
, MDL
);
1339 return status
== ISC_R_SUCCESS
;
1342 /* Release the specified lease and re-hash it as appropriate. */
1343 void release_lease (lease
, packet
)
1344 struct lease
*lease
;
1345 struct packet
*packet
;
1347 /* If there are statements to execute when the lease is
1348 released, execute them. */
1349 #if defined (NSUPDATE)
1350 ddns_removals (lease
);
1352 if (lease
-> on_release
) {
1353 execute_statements ((struct binding_value
**)0,
1354 packet
, lease
, (struct client_state
*)0,
1356 (struct option_state
*)0, /* XXX */
1357 &lease
-> scope
, lease
-> on_release
);
1358 if (lease
-> on_release
)
1359 executable_statement_dereference (&lease
-> on_release
,
1363 /* We do either the on_release or the on_expiry events, but
1364 not both (it's possible that they could be the same,
1366 if (lease
-> on_expiry
)
1367 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1369 if (lease
-> binding_state
!= FTS_FREE
&&
1370 lease
-> binding_state
!= FTS_BACKUP
&&
1371 lease
-> binding_state
!= FTS_RELEASED
&&
1372 lease
-> binding_state
!= FTS_EXPIRED
&&
1373 lease
-> binding_state
!= FTS_RESET
) {
1374 if (lease
-> on_commit
)
1375 executable_statement_dereference (&lease
-> on_commit
,
1378 /* Blow away any bindings. */
1380 binding_scope_dereference (&lease
-> scope
, MDL
);
1381 lease
-> ends
= cur_time
;
1382 #if defined (FAILOVER_PROTOCOL)
1383 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1384 lease
-> next_binding_state
= FTS_RELEASED
;
1386 lease
-> next_binding_state
= FTS_FREE
;
1389 lease
-> next_binding_state
= FTS_FREE
;
1391 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1395 /* Abandon the specified lease (set its timeout to infinity and its
1396 particulars to zero, and re-hash it as appropriate. */
1398 void abandon_lease (lease
, message
)
1399 struct lease
*lease
;
1400 const char *message
;
1402 struct lease
*lt
= (struct lease
*)0;
1404 if (!lease_copy (<
, lease
, MDL
))
1407 lt
-> ends
= cur_time
; /* XXX */
1408 lt
-> next_binding_state
= FTS_ABANDONED
;
1410 log_error ("Abandoning IP address %s: %s",
1411 piaddr (lease
-> ip_addr
), message
);
1412 lt
-> hardware_addr
.hlen
= 0;
1413 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1414 dfree (lt
-> uid
, MDL
);
1415 lt
-> uid
= (unsigned char *)0;
1418 supersede_lease (lease
, lt
, 1, 1, 1);
1419 lease_dereference (<
, MDL
);
1422 /* Abandon the specified lease (set its timeout to infinity and its
1423 particulars to zero, and re-hash it as appropriate. */
1425 void dissociate_lease (lease
)
1426 struct lease
*lease
;
1428 struct lease
*lt
= (struct lease
*)0;
1430 if (!lease_copy (<
, lease
, MDL
))
1433 #if defined (FAILOVER_PROTOCOL)
1434 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1435 lt
-> next_binding_state
= FTS_RESET
;
1437 lt
-> next_binding_state
= FTS_FREE
;
1440 lt
-> next_binding_state
= FTS_FREE
;
1442 lt
-> ends
= cur_time
; /* XXX */
1443 lt
-> hardware_addr
.hlen
= 0;
1444 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1445 dfree (lt
-> uid
, MDL
);
1446 lt
-> uid
= (unsigned char *)0;
1449 supersede_lease (lease
, lt
, 1, 1, 1);
1450 lease_dereference (<
, MDL
);
1453 /* Timer called when a lease in a particular pool expires. */
1454 void pool_timer (vpool
)
1458 struct lease
*lt
= (struct lease
*)0;
1459 struct lease
*next
= (struct lease
*)0;
1460 struct lease
*lease
= (struct lease
*)0;
1461 struct lease
**lptr
[5];
1462 TIME next_expiry
= MAX_TIME
;
1465 pool
= (struct pool
*)vpool
;
1467 #define FREE_LEASES 0
1468 lptr
[FREE_LEASES
] = &pool
-> free
;
1469 #define ACTIVE_LEASES 1
1470 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1471 #define EXPIRED_LEASES 2
1472 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1473 #define ABANDONED_LEASES 3
1474 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1475 #define BACKUP_LEASES 4
1476 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1478 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1479 /* If there's nothing on the queue, skip it. */
1483 #if defined (FAILOVER_PROTOCOL)
1484 if (pool
-> failover_peer
&&
1485 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1486 /* The secondary can't remove a lease from the
1487 active state except in partner_down. */
1488 if (i
== ACTIVE_LEASES
&&
1489 pool
-> failover_peer
-> i_am
== secondary
)
1491 /* Leases in an expired state don't move to
1492 free because of a timeout unless we're in
1494 if (i
== EXPIRED_LEASES
)
1498 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1501 /* Remember the next lease in the list. */
1503 lease_dereference (&next
, MDL
);
1505 lease_reference (&next
, lease
-> next
, MDL
);
1507 /* If we've run out of things to expire on this list,
1509 if (lease
-> sort_time
> cur_time
) {
1510 if (lease
-> sort_time
< next_expiry
)
1511 next_expiry
= lease
-> sort_time
;
1515 /* If there is a pending state change, and
1516 this lease has gotten to the time when the
1517 state change should happen, just call
1518 supersede_lease on it to make the change
1520 if (lease
-> next_binding_state
!=
1521 lease
-> binding_state
)
1522 supersede_lease (lease
,
1523 (struct lease
*)0, 1, 1, 1);
1525 lease_dereference (&lease
, MDL
);
1527 lease_reference (&lease
, next
, MDL
);
1530 lease_dereference (&next
, MDL
);
1532 lease_dereference (&lease
, MDL
);
1534 if (next_expiry
!= MAX_TIME
) {
1535 pool
-> next_event_time
= next_expiry
;
1536 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1537 (tvref_t
)pool_reference
,
1538 (tvunref_t
)pool_dereference
);
1540 pool
-> next_event_time
= MIN_TIME
;
1544 /* Locate the lease associated with a given IP address... */
1546 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1547 const char *file
, int line
)
1549 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1550 addr
.iabuf
, addr
.len
, file
, line
);
1553 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1554 unsigned len
, const char *file
, int line
)
1558 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1561 int find_lease_by_hw_addr (struct lease
**lp
,
1562 const unsigned char *hwaddr
, unsigned hwlen
,
1563 const char *file
, int line
)
1567 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1568 hwaddr
, hwlen
, file
, line
);
1571 /* Add the specified lease to the uid hash. */
1573 void uid_hash_add (lease
)
1574 struct lease
*lease
;
1576 struct lease
*head
= (struct lease
*)0;
1577 struct lease
*next
= (struct lease
*)0;
1580 /* If it's not in the hash, just add it. */
1581 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1582 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1583 lease
-> uid_len
, lease
, MDL
);
1585 /* Otherwise, attach it to the end of the list. */
1586 while (head
-> n_uid
) {
1587 lease_reference (&next
, head
-> n_uid
, MDL
);
1588 lease_dereference (&head
, MDL
);
1589 lease_reference (&head
, next
, MDL
);
1590 lease_dereference (&next
, MDL
);
1592 lease_reference (&head
-> n_uid
, lease
, MDL
);
1593 lease_dereference (&head
, MDL
);
1597 /* Delete the specified lease from the uid hash. */
1599 void uid_hash_delete (lease
)
1600 struct lease
*lease
;
1602 struct lease
*head
= (struct lease
*)0;
1605 /* If it's not in the hash, we have no work to do. */
1606 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1608 lease_dereference (&lease
-> n_uid
, MDL
);
1612 /* If the lease we're freeing is at the head of the list,
1613 remove the hash table entry and add a new one with the
1614 next lease on the list (if there is one). */
1615 if (head
== lease
) {
1616 lease_hash_delete (lease_uid_hash
,
1617 lease
-> uid
, lease
-> uid_len
, MDL
);
1618 if (lease
-> n_uid
) {
1619 lease_hash_add (lease_uid_hash
,
1620 lease
-> n_uid
-> uid
,
1621 lease
-> n_uid
-> uid_len
,
1622 lease
-> n_uid
, MDL
);
1623 lease_dereference (&lease
-> n_uid
, MDL
);
1626 /* Otherwise, look for the lease in the list of leases
1627 attached to the hash table entry, and remove it if
1629 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1630 if (scan
-> n_uid
== lease
) {
1631 lease_dereference (&scan
-> n_uid
, MDL
);
1632 if (lease
-> n_uid
) {
1633 lease_reference (&scan
-> n_uid
,
1634 lease
-> n_uid
, MDL
);
1635 lease_dereference (&lease
-> n_uid
,
1642 lease_dereference (&head
, MDL
);
1645 /* Add the specified lease to the hardware address hash. */
1647 void hw_hash_add (lease
)
1648 struct lease
*lease
;
1650 struct lease
*head
= (struct lease
*)0;
1651 struct lease
*next
= (struct lease
*)0;
1653 /* If it's not in the hash, just add it. */
1654 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1655 lease
-> hardware_addr
.hlen
, MDL
))
1656 lease_hash_add (lease_hw_addr_hash
,
1657 lease
-> hardware_addr
.hbuf
,
1658 lease
-> hardware_addr
.hlen
,
1661 /* Otherwise, attach it to the end of the list. */
1662 while (head
-> n_hw
) {
1663 lease_reference (&next
, head
-> n_hw
, MDL
);
1664 lease_dereference (&head
, MDL
);
1665 lease_reference (&head
, next
, MDL
);
1666 lease_dereference (&next
, MDL
);
1669 lease_reference (&head
-> n_hw
, lease
, MDL
);
1670 lease_dereference (&head
, MDL
);
1674 /* Delete the specified lease from the hardware address hash. */
1676 void hw_hash_delete (lease
)
1677 struct lease
*lease
;
1679 struct lease
*head
= (struct lease
*)0;
1680 struct lease
*next
= (struct lease
*)0;
1682 /* If it's not in the hash, we have no work to do. */
1683 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1684 lease
-> hardware_addr
.hlen
, MDL
)) {
1686 lease_dereference (&lease
-> n_hw
, MDL
);
1690 /* If the lease we're freeing is at the head of the list,
1691 remove the hash table entry and add a new one with the
1692 next lease on the list (if there is one). */
1693 if (head
== lease
) {
1694 lease_hash_delete (lease_hw_addr_hash
,
1695 lease
-> hardware_addr
.hbuf
,
1696 lease
-> hardware_addr
.hlen
, MDL
);
1697 if (lease
-> n_hw
) {
1698 lease_hash_add (lease_hw_addr_hash
,
1699 lease
-> n_hw
-> hardware_addr
.hbuf
,
1700 lease
-> n_hw
-> hardware_addr
.hlen
,
1701 lease
-> n_hw
, MDL
);
1702 lease_dereference (&lease
-> n_hw
, MDL
);
1705 /* Otherwise, look for the lease in the list of leases
1706 attached to the hash table entry, and remove it if
1708 while (head
-> n_hw
) {
1709 if (head
-> n_hw
== lease
) {
1710 lease_dereference (&head
-> n_hw
, MDL
);
1711 if (lease
-> n_hw
) {
1712 lease_reference (&head
-> n_hw
,
1713 lease
-> n_hw
, MDL
);
1714 lease_dereference (&lease
-> n_hw
,
1719 lease_reference (&next
, head
-> n_hw
, MDL
);
1720 lease_dereference (&head
, MDL
);
1721 lease_reference (&head
, next
, MDL
);
1722 lease_dereference (&next
, MDL
);
1726 lease_dereference (&head
, MDL
);
1729 /* Write all interesting leases to permanent storage. */
1734 struct shared_network
*s
;
1736 struct host_decl
*hp
;
1737 struct group_object
*gp
;
1738 struct hash_bucket
*hb
;
1741 struct lease
**lptr
[5];
1743 /* Write all the dynamically-created group declarations. */
1744 if (group_name_hash
) {
1746 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1747 for (hb
= group_name_hash
-> buckets
[i
];
1748 hb
; hb
= hb
-> next
) {
1749 gp
= (struct group_object
*)hb
-> value
;
1750 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1751 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1752 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1753 if (!write_group (gp
))
1759 log_info ("Wrote %d group decls to leases file.", num_written
);
1762 /* Write all the deleted host declarations. */
1763 if (host_name_hash
) {
1765 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1766 for (hb
= host_name_hash
-> buckets
[i
];
1767 hb
; hb
= hb
-> next
) {
1768 hp
= (struct host_decl
*)hb
-> value
;
1769 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1770 (hp
-> flags
& HOST_DECL_DELETED
))) {
1771 if (!write_host (hp
))
1777 log_info ("Wrote %d deleted host decls to leases file.",
1781 /* Write all the new, dynamic host declarations. */
1782 if (host_name_hash
) {
1784 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1785 for (hb
= host_name_hash
-> buckets
[i
];
1786 hb
; hb
= hb
-> next
) {
1787 hp
= (struct host_decl
*)hb
-> value
;
1788 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1789 if (!write_host (hp
))
1794 log_info ("Wrote %d new dynamic host decls to leases file.",
1798 #if defined (FAILOVER_PROTOCOL)
1799 /* Write all the failover states. */
1800 if (!dhcp_failover_write_all_states ())
1804 /* Write all the leases. */
1806 for (s
= shared_networks
; s
; s
= s
-> next
) {
1807 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1808 lptr
[FREE_LEASES
] = &p
-> free
;
1809 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1810 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1811 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1812 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1814 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1815 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1816 #if !defined (DEBUG_DUMP_ALL_LEASES)
1817 if (l
-> hardware_addr
.hlen
||
1819 (l
-> binding_state
!= FTS_FREE
))
1822 if (!write_lease (l
))
1830 log_info ("Wrote %d leases to leases file.", num_written
);
1831 if (!commit_leases ())
1836 int lease_enqueue (struct lease
*comp
)
1838 struct lease
**lq
, *prev
, *lp
;
1840 /* No queue to put it on? */
1844 /* Figure out which queue it's going to. */
1845 switch (comp
-> binding_state
) {
1847 lq
= &comp
-> pool
-> free
;
1848 comp
-> pool
-> free_leases
++;
1849 comp
-> sort_time
= comp
-> ends
;
1853 lq
= &comp
-> pool
-> active
;
1854 comp
-> sort_time
= comp
-> ends
;
1860 lq
= &comp
-> pool
-> expired
;
1861 comp
-> sort_time
= comp
-> ends
;
1866 lq
= &comp
-> pool
-> abandoned
;
1867 comp
-> sort_time
= comp
-> ends
;
1871 lq
= &comp
-> pool
-> backup
;
1872 comp
-> pool
-> backup_leases
++;
1873 comp
-> sort_time
= comp
-> ends
;
1877 log_error ("Lease with bogus binding state: %d",
1878 comp
-> binding_state
);
1879 #if defined (BINDING_STATE_DEBUG)
1885 /* Insertion sort the lease onto the appropriate queue. */
1886 prev
= (struct lease
*)0;
1887 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1888 if (lp
-> sort_time
>= comp
-> sort_time
)
1894 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1895 lease_dereference (&prev
-> next
, MDL
);
1897 lease_reference (&prev
-> next
, comp
, MDL
);
1900 lease_reference (&comp
-> next
, *lq
, MDL
);
1901 lease_dereference (lq
, MDL
);
1903 lease_reference (lq
, comp
, MDL
);
1908 /* For a given lease, sort it onto the right list in its pool and put it
1909 in each appropriate hash, understanding that it's already by definition
1910 in lease_ip_addr_hash. */
1912 void lease_instantiate (const unsigned char *val
, unsigned len
,
1913 struct lease
*lease
)
1915 struct class *class;
1916 /* XXX If the lease doesn't have a pool at this point, it's an
1917 XXX orphan, which we *should* keep around until it expires,
1918 XXX but which right now we just forget. */
1919 if (!lease
-> pool
) {
1920 lease_hash_delete (lease_ip_addr_hash
,
1921 lease
-> ip_addr
.iabuf
,
1922 lease
-> ip_addr
.len
, MDL
);
1926 /* Put the lease on the right queue. */
1927 lease_enqueue (lease
);
1929 /* Record the lease in the uid hash if possible. */
1931 uid_hash_add (lease
);
1934 /* Record it in the hardware address hash if possible. */
1935 if (lease
-> hardware_addr
.hlen
) {
1936 hw_hash_add (lease
);
1939 /* If the lease has a billing class, set up the billing. */
1940 if (lease
-> billing_class
) {
1941 class = (struct class *)0;
1942 class_reference (&class, lease
-> billing_class
, MDL
);
1943 class_dereference (&lease
-> billing_class
, MDL
);
1944 /* If the lease is available for allocation, the billing
1945 is invalid, so we don't keep it. */
1946 if (lease
-> binding_state
== FTS_ACTIVE
||
1947 lease
-> binding_state
== FTS_EXPIRED
||
1948 lease
-> binding_state
== FTS_RELEASED
||
1949 lease
-> binding_state
== FTS_RESET
)
1950 bill_class (lease
, class);
1951 class_dereference (&class, MDL
);
1956 /* Run expiry events on every pool. This is called on startup so that
1957 any expiry events that occurred after the server stopped and before it
1958 was restarted can be run. At the same time, if failover support is
1959 compiled in, we compute the balance of leases for the pool. */
1961 void expire_all_pools ()
1963 struct shared_network
*s
;
1965 struct hash_bucket
*hb
;
1968 struct lease
**lptr
[5];
1970 /* First, go over the hash list and actually put all the leases
1971 on the appropriate lists. */
1972 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1974 /* Loop through each pool in each shared network and call the
1975 expiry routine on the pool. */
1976 for (s
= shared_networks
; s
; s
= s
-> next
) {
1977 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1980 p
-> lease_count
= 0;
1981 p
-> free_leases
= 0;
1982 p
-> backup_leases
= 0;
1984 lptr
[FREE_LEASES
] = &p
-> free
;
1985 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1986 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1987 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1988 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1990 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1991 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1993 if (l
-> ends
<= cur_time
) {
1994 if (l
-> binding_state
== FTS_FREE
)
1996 else if (l
-> binding_state
== FTS_BACKUP
)
1997 p
-> backup_leases
++;
1999 #if defined (FAILOVER_PROTOCOL)
2000 if (p
-> failover_peer
&&
2001 l
-> tstp
> l
-> tsfp
&&
2002 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2003 l
-> desired_binding_state
= l
-> binding_state
;
2004 dhcp_failover_queue_update (l
, 1);
2013 void dump_subnets ()
2016 struct shared_network
*s
;
2019 struct lease
**lptr
[5];
2022 log_info ("Subnets:");
2023 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2024 log_debug (" Subnet %s", piaddr (n
-> net
));
2025 log_debug (" netmask %s",
2026 piaddr (n
-> netmask
));
2028 log_info ("Shared networks:");
2029 for (s
= shared_networks
; s
; s
= s
-> next
) {
2030 log_info (" %s", s
-> name
);
2031 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2032 lptr
[FREE_LEASES
] = &p
-> free
;
2033 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2034 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2035 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2036 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2038 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2039 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2047 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
, lease_hash_t
,
2048 lease_reference
, lease_dereference
)
2049 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2050 host_reference
, host_dereference
)
2051 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2052 class_reference
, class_dereference
)
2054 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2055 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2056 extern struct hash_table
*dns_zone_hash
;
2057 extern struct interface_info
**interface_vector
;
2058 extern int interface_count
;
2059 dhcp_control_object_t
*dhcp_control_object
;
2060 extern struct hash_table
*auth_key_hash
;
2061 struct hash_table
*universe_hash
;
2062 struct universe
**universes
;
2063 int universe_count
, universe_max
;
2068 #if defined (COMPACT_LEASES)
2069 extern struct lease
*lease_hunks
;
2072 void free_everything ()
2074 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2075 struct shared_network
*nc
= (struct shared_network
*)0,
2076 *nn
= (struct shared_network
*)0;
2077 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2078 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2079 struct interface_info
*ic
= (struct interface_info
*)0,
2080 *in
= (struct interface_info
*)0;
2081 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2082 struct collection
*lp
;
2083 void *st
= (shared_networks
2084 ? (shared_networks
-> next
2085 ? shared_networks
-> next
-> next
: 0) : 0);
2089 /* Get rid of all the hash tables. */
2090 if (host_hw_addr_hash
)
2091 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2092 host_hw_addr_hash
= 0;
2094 host_free_hash_table (&host_uid_hash
, MDL
);
2097 lease_free_hash_table (&lease_uid_hash
, MDL
);
2099 if (lease_ip_addr_hash
)
2100 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2101 lease_ip_addr_hash
= 0;
2102 if (lease_hw_addr_hash
)
2103 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2104 lease_hw_addr_hash
= 0;
2106 host_free_hash_table (&host_name_hash
, MDL
);
2109 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2113 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2117 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2120 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2121 if (lp
-> classes
) {
2122 class_reference (&cn
, lp
-> classes
, MDL
);
2125 class_reference (&cc
, cn
, MDL
);
2126 class_dereference (&cn
, MDL
);
2129 class_reference (&cn
, cc
-> nic
, MDL
);
2130 class_dereference (&cc
-> nic
, MDL
);
2132 group_dereference (&cc
-> group
, MDL
);
2134 class_free_hash_table (&cc
-> hash
, MDL
);
2135 cc
-> hash
= (struct hash_table
*)0;
2137 class_dereference (&cc
, MDL
);
2139 class_dereference (&lp
-> classes
, MDL
);
2143 if (interface_vector
) {
2144 for (i
= 0; i
< interface_count
; i
++) {
2145 if (interface_vector
[i
])
2146 interface_dereference (&interface_vector
[i
], MDL
);
2148 dfree (interface_vector
, MDL
);
2149 interface_vector
= 0;
2153 interface_reference (&in
, interfaces
, MDL
);
2156 interface_reference (&ic
, in
, MDL
);
2157 interface_dereference (&in
, MDL
);
2160 interface_reference (&in
, ic
-> next
, MDL
);
2161 interface_dereference (&ic
-> next
, MDL
);
2163 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2164 if (ic
-> shared_network
) {
2165 if (ic
-> shared_network
-> interface
)
2166 interface_dereference
2167 (&ic
-> shared_network
-> interface
, MDL
);
2168 shared_network_dereference (&ic
-> shared_network
, MDL
);
2170 interface_dereference (&ic
, MDL
);
2172 interface_dereference (&interfaces
, MDL
);
2175 /* Subnets are complicated because of the extra links. */
2177 subnet_reference (&sn
, subnets
, MDL
);
2180 subnet_reference (&sc
, sn
, MDL
);
2181 subnet_dereference (&sn
, MDL
);
2183 if (sc
-> next_subnet
) {
2184 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2185 subnet_dereference (&sc
-> next_subnet
, MDL
);
2187 if (sc
-> next_sibling
)
2188 subnet_dereference (&sc
-> next_sibling
, MDL
);
2189 if (sc
-> shared_network
)
2190 shared_network_dereference (&sc
-> shared_network
, MDL
);
2191 group_dereference (&sc
-> group
, MDL
);
2192 if (sc
-> interface
)
2193 interface_dereference (&sc
-> interface
, MDL
);
2194 subnet_dereference (&sc
, MDL
);
2196 subnet_dereference (&subnets
, MDL
);
2199 /* So are shared networks. */
2200 if (shared_networks
) {
2201 shared_network_reference (&nn
, shared_networks
, MDL
);
2204 shared_network_reference (&nc
, nn
, MDL
);
2205 shared_network_dereference (&nn
, MDL
);
2208 shared_network_reference (&nn
, nc
-> next
, MDL
);
2209 shared_network_dereference (&nc
-> next
, MDL
);
2214 pool_reference (&pn
, nc
-> pools
, MDL
);
2216 struct lease
**lptr
[5];
2219 pool_reference (&pc
, pn
, MDL
);
2220 pool_dereference (&pn
, MDL
);
2223 pool_reference (&pn
, pc
-> next
, MDL
);
2224 pool_dereference (&pc
-> next
, MDL
);
2227 lptr
[FREE_LEASES
] = &pc
-> free
;
2228 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2229 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2230 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2231 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2233 /* As (sigh) are leases. */
2234 for (i
= 0; i
< 5; i
++) {
2236 lease_reference (&ln
, *lptr
[i
], MDL
);
2239 lease_reference (&lc
, ln
, MDL
);
2240 lease_dereference (&ln
, MDL
);
2243 lease_reference (&ln
, lc
-> next
, MDL
);
2244 lease_dereference (&lc
-> next
, MDL
);
2246 if (lc
-> billing_class
)
2247 class_dereference (&lc
-> billing_class
,
2250 free_lease_state (lc
-> state
, MDL
);
2251 lc
-> state
= (struct lease_state
*)0;
2253 lease_dereference (&lc
-> n_hw
, MDL
);
2255 lease_dereference (&lc
-> n_uid
, MDL
);
2256 lease_dereference (&lc
, MDL
);
2258 lease_dereference (lptr
[i
], MDL
);
2262 group_dereference (&pc
-> group
, MDL
);
2263 if (pc
-> shared_network
)
2264 shared_network_dereference (&pc
-> shared_network
,
2266 pool_dereference (&pc
, MDL
);
2268 pool_dereference (&nc
-> pools
, MDL
);
2270 /* Because of a circular reference, we need to nuke this
2272 group_dereference (&nc
-> group
, MDL
);
2273 shared_network_dereference (&nc
, MDL
);
2275 shared_network_dereference (&shared_networks
, MDL
);
2278 cancel_all_timeouts ();
2279 relinquish_timeouts ();
2281 group_dereference (&root_group
, MDL
);
2282 executable_statement_dereference (&default_classification_rules
, MDL
);
2284 shutdown_state
= shutdown_drop_omapi_connections
;
2285 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2286 shutdown_state
= shutdown_listeners
;
2287 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2288 shutdown_state
= shutdown_dhcp
;
2289 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2291 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2293 universe_free_hash_table (&universe_hash
, MDL
);
2294 for (i
= 0; i
< universe_count
; i
++) {
2299 if (universes
[i
]) {
2300 if (universes
[i
] -> hash
)
2301 option_free_hash_table (&universes
[i
] -> hash
,
2304 if (universes
[i
] -> name
> (char *)&end
) {
2305 foo
.c
= universes
[i
] -> name
;
2308 if (universes
[i
] > (struct universe
*)&end
)
2309 dfree (universes
[i
], MDL
);
2313 dfree (universes
, MDL
);
2315 relinquish_free_lease_states ();
2316 relinquish_free_pairs ();
2317 relinquish_free_expressions ();
2318 relinquish_free_binding_values ();
2319 relinquish_free_option_caches ();
2320 relinquish_free_packets ();
2321 relinquish_lease_hunks ();
2322 relinquish_hash_bucket_hunks ();
2323 omapi_type_relinquish ();
2325 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */