3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2005 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.4 2005/08/11 17:13:30 drochner Exp $ Copyright (c) 2004-2005 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 int hw_head
= 0, uid_head
= 1;
243 /* Don't need to do it twice. */
244 if (hd
-> flags
& HOST_DECL_DELETED
)
245 return ISC_R_SUCCESS
;
247 /* But we do need to do it once! :') */
248 hd
-> flags
|= HOST_DECL_DELETED
;
250 if (hd
-> interface
.hlen
) {
251 if (host_hw_addr_hash
) {
252 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
253 hd
-> interface
.hbuf
,
254 hd
-> interface
.hlen
, MDL
)) {
256 host_hash_delete (host_hw_addr_hash
,
257 hd
-> interface
.hbuf
,
258 hd
-> interface
.hlen
, MDL
);
261 np
= (struct host_decl
*)0;
262 foo
= (struct host_decl
*)0;
263 host_reference (&foo
, hp
, MDL
);
268 host_dereference (&np
, MDL
);
269 host_reference (&np
, foo
, MDL
);
270 host_dereference (&foo
, MDL
);
272 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
276 host_dereference (&np
-> n_ipaddr
, MDL
);
278 host_reference (&np
-> n_ipaddr
,
279 hd
-> n_ipaddr
, MDL
);
280 host_dereference (&foo
, MDL
);
283 host_dereference (&np
, MDL
);
285 host_dereference (&hp
, MDL
);
290 /* If we got a client identifier, hash this entry by
291 client identifier. */
292 if (hd
-> client_identifier
.len
) {
294 if (host_hash_lookup (&hp
, host_uid_hash
,
295 hd
-> client_identifier
.data
,
296 hd
-> client_identifier
.len
, MDL
)) {
298 host_hash_delete (host_uid_hash
,
299 hd
-> client_identifier
.data
,
300 hd
-> client_identifier
.len
, MDL
);
303 np
= (struct host_decl
*)0;
304 foo
= (struct host_decl
*)0;
305 host_reference (&foo
, hp
, MDL
);
310 host_dereference (&np
, MDL
);
311 host_reference (&np
, foo
, MDL
);
312 host_dereference (&foo
, MDL
);
314 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
318 host_dereference (&np
-> n_ipaddr
, MDL
);
320 host_reference (&np
-> n_ipaddr
,
321 hd
-> n_ipaddr
, MDL
);
322 host_dereference (&foo
, MDL
);
325 host_dereference (&np
, MDL
);
327 host_dereference (&hp
, MDL
);
332 if (hd
-> n_ipaddr
) {
333 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
336 hd
-> n_ipaddr
-> client_identifier
.data
,
337 hd
-> n_ipaddr
-> client_identifier
.len
,
338 hd
-> n_ipaddr
, MDL
);
340 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
341 host_hash_add (host_hw_addr_hash
,
342 hd
-> n_ipaddr
-> interface
.hbuf
,
343 hd
-> n_ipaddr
-> interface
.hlen
,
344 hd
-> n_ipaddr
, MDL
);
346 host_dereference (&hd
-> n_ipaddr
, MDL
);
349 if (host_name_hash
) {
350 if (host_hash_lookup (&hp
, host_name_hash
,
351 (unsigned char *)hd
-> name
,
352 strlen (hd
-> name
), MDL
)) {
353 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
354 host_hash_delete (host_name_hash
,
355 (unsigned char *)hd
-> name
,
356 strlen (hd
-> name
), MDL
);
358 host_dereference (&hp
, MDL
);
363 if (!write_host (hd
))
364 return ISC_R_IOERROR
;
365 if (!commit_leases ())
366 return ISC_R_IOERROR
;
368 return ISC_R_SUCCESS
;
371 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
372 const unsigned char *haddr
, unsigned hlen
,
373 const char *file
, int line
)
379 memcpy (&h
.hbuf
[1], haddr
, hlen
);
381 return host_hash_lookup (hp
, host_hw_addr_hash
,
382 h
.hbuf
, h
.hlen
, file
, line
);
385 int find_hosts_by_uid (struct host_decl
**hp
,
386 const unsigned char *data
, unsigned len
,
387 const char *file
, int line
)
389 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
392 /* More than one host_decl can be returned by find_hosts_by_haddr or
393 find_hosts_by_uid, and each host_decl can have multiple addresses.
394 Loop through the list of hosts, and then for each host, through the
395 list of addresses, looking for an address that's in the same shared
396 network as the one specified. Store the matching address through
397 the addr pointer, update the host pointer to point at the host_decl
398 that matched, and return the subnet that matched. */
400 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
401 struct iaddr
*addr
, struct shared_network
*share
)
404 struct iaddr ip_address
;
405 struct host_decl
*hp
;
406 struct data_string fixed_addr
;
408 memset (&fixed_addr
, 0, sizeof fixed_addr
);
410 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
411 if (!hp
-> fixed_addr
)
413 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
415 (struct client_state
*)0,
416 (struct option_state
*)0,
417 (struct option_state
*)0,
419 hp
-> fixed_addr
, MDL
))
421 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
423 memcpy (ip_address
.iabuf
,
424 fixed_addr
.data
+ i
, 4);
425 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
426 struct host_decl
*tmp
= (struct host_decl
*)0;
428 /* This is probably not necessary, but
429 just in case *host is the only reference
430 to that host declaration, make a temporary
431 reference so that dereferencing it doesn't
432 dereference hp out from under us. */
433 host_reference (&tmp
, *host
, MDL
);
434 host_dereference (host
, MDL
);
435 host_reference (host
, hp
, MDL
);
436 host_dereference (&tmp
, MDL
);
437 data_string_forget (&fixed_addr
, MDL
);
441 data_string_forget (&fixed_addr
, MDL
);
446 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
448 struct iaddr low
, high
;
449 struct subnet
*subnet
;
451 struct lease
**lpchain
;
453 struct lease
*address_range
;
455 unsigned min
, max
, i
;
456 char lowbuf
[16], highbuf
[16], netbuf
[16];
457 struct shared_network
*share
= subnet
-> shared_network
;
458 #if !defined (COMPACT_LEASES)
461 struct lease
*lt
= (struct lease
*)0;
463 /* All subnets should have attached shared network structures. */
465 strcpy (netbuf
, piaddr (subnet
-> net
));
466 log_fatal ("No shared network for network %s (%s)",
467 netbuf
, piaddr (subnet
-> netmask
));
470 /* Initialize the hash table if it hasn't been done yet. */
471 if (!lease_uid_hash
) {
472 if (!lease_new_hash (&lease_uid_hash
, 0, MDL
))
473 log_fatal ("Can't allocate lease/uid hash");
475 if (!lease_ip_addr_hash
) {
476 if (!lease_new_hash (&lease_ip_addr_hash
, 0, MDL
))
477 log_fatal ("Can't allocate lease/ip hash");
479 if (!lease_hw_addr_hash
) {
480 if (!lease_new_hash (&lease_hw_addr_hash
, 0, MDL
))
481 log_fatal ("Can't allocate lease/hw hash");
484 /* Make sure that high and low addresses are in same subnet. */
485 net
= subnet_number (low
, subnet
-> netmask
);
486 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
487 strcpy (lowbuf
, piaddr (low
));
488 strcpy (highbuf
, piaddr (high
));
489 strcpy (netbuf
, piaddr (subnet
-> netmask
));
490 log_fatal ("Address range %s to %s, netmask %s spans %s!",
491 lowbuf
, highbuf
, netbuf
, "multiple subnets");
494 /* Make sure that the addresses are on the correct subnet. */
495 if (!addr_eq (net
, subnet
-> net
)) {
496 strcpy (lowbuf
, piaddr (low
));
497 strcpy (highbuf
, piaddr (high
));
498 strcpy (netbuf
, piaddr (subnet
-> netmask
));
499 log_fatal ("Address range %s to %s not on net %s/%s!",
500 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
503 /* Get the high and low host addresses... */
504 max
= host_addr (high
, subnet
-> netmask
);
505 min
= host_addr (low
, subnet
-> netmask
);
507 /* Allow range to be specified high-to-low as well as low-to-high. */
510 min
= host_addr (high
, subnet
-> netmask
);
513 /* Get a lease structure for each address in the range. */
514 #if defined (COMPACT_LEASES)
515 address_range
= new_leases (max
- min
+ 1, MDL
);
516 if (!address_range
) {
517 strcpy (lowbuf
, piaddr (low
));
518 strcpy (highbuf
, piaddr (high
));
519 log_fatal ("No memory for address range %s-%s.",
524 /* Fill out the lease structures with some minimal information. */
525 for (i
= 0; i
< max
- min
+ 1; i
++) {
526 struct lease
*lp
= (struct lease
*)0;
527 #if defined (COMPACT_LEASES)
528 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
530 0, sizeof (struct lease
), MDL
);
531 lease_reference (&lp
, &address_range
[i
], MDL
);
533 status
= lease_allocate (&lp
, MDL
);
534 if (status
!= ISC_R_SUCCESS
)
535 log_fatal ("No memory for lease %s: %s",
536 piaddr (ip_addr (subnet
-> net
,
539 isc_result_totext (status
));
541 lp
-> ip_addr
= ip_addr (subnet
-> net
,
542 subnet
-> netmask
, i
+ min
);
543 lp
-> starts
= lp
-> timestamp
= MIN_TIME
;
544 lp
-> ends
= MIN_TIME
;
545 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
546 pool_reference (&lp
-> pool
, pool
, MDL
);
547 lp
-> binding_state
= FTS_FREE
;
548 lp
-> next_binding_state
= FTS_FREE
;
551 /* Remember the lease in the IP address hash. */
552 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
555 "lease %s is declared twice!",
556 piaddr (lp
-> ip_addr
));
558 pool_reference (<
-> pool
, pool
, MDL
);
559 lease_dereference (<
, MDL
);
561 lease_hash_add (lease_ip_addr_hash
,
563 lp
-> ip_addr
.len
, lp
, MDL
);
564 /* Put the lease on the chain for the caller. */
567 lease_reference (&lp
-> next
, *lpchain
, MDL
);
568 lease_dereference (lpchain
, MDL
);
570 lease_reference (lpchain
, lp
, MDL
);
572 lease_dereference (&lp
, MDL
);
576 int find_subnet (struct subnet
**sp
,
577 struct iaddr addr
, const char *file
, int line
)
581 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
582 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
583 if (subnet_reference (sp
, rv
,
584 file
, line
) != ISC_R_SUCCESS
)
592 int find_grouped_subnet (struct subnet
**sp
,
593 struct shared_network
*share
, struct iaddr addr
,
594 const char *file
, int line
)
598 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
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 subnet_inner_than (subnet
, scan
, warnp
)
610 struct subnet
*subnet
, *scan
;
613 if (addr_eq (subnet_number (subnet
-> net
, scan
-> netmask
),
615 addr_eq (subnet_number (scan
-> net
, subnet
-> netmask
),
619 for (i
= 0; i
< 32; i
++)
620 if (subnet
-> netmask
.iabuf
[3 - (i
>> 3)]
623 for (j
= 0; j
< 32; j
++)
624 if (scan
-> netmask
.iabuf
[3 - (j
>> 3)] &
627 strcpy (n1buf
, piaddr (subnet
-> net
));
629 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
630 "Warning: ", n1buf
, 32 - i
,
631 piaddr (scan
-> net
), 32 - j
);
638 /* Enter a new subnet into the subnet list. */
639 void enter_subnet (subnet
)
640 struct subnet
*subnet
;
642 struct subnet
*scan
= (struct subnet
*)0;
643 struct subnet
*next
= (struct subnet
*)0;
644 struct subnet
*prev
= (struct subnet
*)0;
646 /* Check for duplicates... */
648 subnet_reference (&next
, subnets
, MDL
);
650 subnet_reference (&scan
, next
, MDL
);
651 subnet_dereference (&next
, MDL
);
653 /* When we find a conflict, make sure that the
654 subnet with the narrowest subnet mask comes
656 if (subnet_inner_than (subnet
, scan
, 1)) {
658 if (prev
-> next_subnet
)
659 subnet_dereference (&prev
-> next_subnet
, MDL
);
660 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
661 subnet_dereference (&prev
, MDL
);
663 subnet_dereference (&subnets
, MDL
);
664 subnet_reference (&subnets
, subnet
, MDL
);
666 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
667 subnet_dereference (&scan
, MDL
);
670 subnet_reference (&prev
, scan
, MDL
);
671 subnet_dereference (&scan
, MDL
);
674 subnet_dereference (&prev
, MDL
);
676 /* XXX use the BSD radix tree code instead of a linked list. */
678 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
679 subnet_dereference (&subnets
, MDL
);
681 subnet_reference (&subnets
, subnet
, MDL
);
684 /* Enter a new shared network into the shared network list. */
686 void enter_shared_network (share
)
687 struct shared_network
*share
;
689 if (shared_networks
) {
690 shared_network_reference (&share
-> next
,
691 shared_networks
, MDL
);
692 shared_network_dereference (&shared_networks
, MDL
);
694 shared_network_reference (&shared_networks
, share
, MDL
);
697 void new_shared_network_interface (cfile
, share
, name
)
699 struct shared_network
*share
;
702 struct interface_info
*ip
;
705 if (share
-> interface
) {
707 "A subnet or shared network can't be connected %s",
708 "to two interfaces.");
712 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
713 if (!strcmp (ip
-> name
, name
))
716 status
= interface_allocate (&ip
, MDL
);
717 if (status
!= ISC_R_SUCCESS
)
718 log_fatal ("new_shared_network_interface %s: %s",
719 name
, isc_result_totext (status
));
720 if (strlen (name
) > sizeof ip
-> name
) {
721 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
722 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
724 strcpy (ip
-> name
, name
);
726 interface_reference (&ip
-> next
, interfaces
, MDL
);
727 interface_dereference (&interfaces
, MDL
);
729 interface_reference (&interfaces
, ip
, MDL
);
730 ip
-> flags
= INTERFACE_REQUESTED
;
731 /* XXX this is a reference loop. */
732 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
733 interface_reference (&share
-> interface
, ip
, MDL
);
737 /* Enter a lease into the system. This is called by the parser each
738 time it reads in a new lease. If the subnet for that lease has
739 already been read in (usually the case), just update that lease;
740 otherwise, allocate temporary storage for the lease and keep it around
741 until we're done reading in the config file. */
743 void enter_lease (lease
)
746 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
;
797 #if defined (FAILOVER_PROTOCOL)
798 /* We must commit leases before sending updates regarding them
799 to failover peers. It is, therefore, an error to set pimmediate
801 if (pimmediate
&& !commit
)
805 /* If there is no sample lease, just do the move. */
809 /* Static leases are not currently kept in the database... */
810 if (lease
-> flags
& STATIC_LEASE
)
813 /* If the existing lease hasn't expired and has a different
814 unique identifier or, if it doesn't have a unique
815 identifier, a different hardware address, then the two
816 leases are in conflict. If the existing lease has a uid
817 and the new one doesn't, but they both have the same
818 hardware address, and dynamic bootp is allowed on this
819 lease, then we allow that, in case a dynamic BOOTP lease is
820 requested *after* a DHCP lease has been assigned. */
822 if (lease
-> binding_state
!= FTS_ABANDONED
&&
823 lease
-> next_binding_state
!= FTS_ABANDONED
&&
824 comp
-> binding_state
== FTS_ACTIVE
&&
825 (((comp
-> uid
&& lease
-> uid
) &&
826 (comp
-> uid_len
!= lease
-> uid_len
||
827 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
829 ((comp
-> hardware_addr
.hlen
!=
830 lease
-> hardware_addr
.hlen
) ||
831 memcmp (comp
-> hardware_addr
.hbuf
,
832 lease
-> hardware_addr
.hbuf
,
833 comp
-> hardware_addr
.hlen
))))) {
834 log_error ("Lease conflict at %s",
835 piaddr (comp
-> ip_addr
));
838 /* If there's a Unique ID, dissociate it from the hash
839 table and free it if necessary. */
841 uid_hash_delete (comp
);
843 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
844 dfree (comp
-> uid
, MDL
);
848 comp
-> uid
= (unsigned char *)0;
852 if (comp
-> hardware_addr
.hlen
&&
853 ((comp
-> hardware_addr
.hlen
!=
854 lease
-> hardware_addr
.hlen
) ||
855 memcmp (comp
-> hardware_addr
.hbuf
,
856 lease
-> hardware_addr
.hbuf
,
857 comp
-> hardware_addr
.hlen
))) {
858 hw_hash_delete (comp
);
860 } else if (!comp
-> hardware_addr
.hlen
)
863 /* If the lease has been billed to a class, remove the billing. */
864 if (comp
-> billing_class
!= lease
-> billing_class
) {
865 if (comp
-> billing_class
)
866 unbill_class (comp
, comp
-> billing_class
);
867 if (lease
-> billing_class
)
868 bill_class (comp
, lease
-> billing_class
);
871 /* Copy the data files, but not the linkages. */
872 comp
-> starts
= lease
-> starts
;
874 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
875 memcpy (comp
-> uid_buf
,
876 lease
-> uid
, lease
-> uid_len
);
877 comp
-> uid
= &comp
-> uid_buf
[0];
878 comp
-> uid_max
= sizeof comp
-> uid_buf
;
879 comp
-> uid_len
= lease
-> uid_len
;
880 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
881 comp
-> uid
= lease
-> uid
;
882 comp
-> uid_max
= lease
-> uid_max
;
883 lease
-> uid
= (unsigned char *)0;
884 lease
-> uid_max
= 0;
885 comp
-> uid_len
= lease
-> uid_len
;
886 lease
-> uid_len
= 0;
888 log_fatal ("corrupt lease uid."); /* XXX */
891 comp
-> uid
= (unsigned char *)0;
892 comp
-> uid_len
= comp
-> uid_max
= 0;
895 host_dereference (&comp
-> host
, MDL
);
896 host_reference (&comp
-> host
, lease
-> host
, MDL
);
897 comp
-> hardware_addr
= lease
-> hardware_addr
;
898 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
899 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
901 binding_scope_dereference (&comp
-> scope
, MDL
);
902 if (lease
-> scope
) {
903 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
904 binding_scope_dereference (&lease
-> scope
, MDL
);
907 if (comp
-> agent_options
)
908 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
909 if (lease
-> agent_options
) {
910 /* Only retain the agent options if the lease is still
911 affirmatively associated with a client. */
912 if (lease
-> next_binding_state
== FTS_ACTIVE
||
913 lease
-> next_binding_state
== FTS_EXPIRED
)
914 option_chain_head_reference (&comp
-> agent_options
,
915 lease
-> agent_options
,
917 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
920 /* Record the hostname information in the lease. */
921 if (comp
-> client_hostname
)
922 dfree (comp
-> client_hostname
, MDL
);
923 comp
-> client_hostname
= lease
-> client_hostname
;
924 lease
-> client_hostname
= (char *)0;
926 if (lease
-> on_expiry
) {
927 if (comp
-> on_expiry
)
928 executable_statement_dereference (&comp
-> on_expiry
,
930 executable_statement_reference (&comp
-> on_expiry
,
934 if (lease
-> on_commit
) {
935 if (comp
-> on_commit
)
936 executable_statement_dereference (&comp
-> on_commit
,
938 executable_statement_reference (&comp
-> on_commit
,
942 if (lease
-> on_release
) {
943 if (comp
-> on_release
)
944 executable_statement_dereference (&comp
-> on_release
,
946 executable_statement_reference (&comp
-> on_release
,
947 lease
-> on_release
, MDL
);
950 /* Record the lease in the uid hash if necessary. */
951 if (enter_uid
&& comp
-> uid
) {
955 /* Record it in the hardware address hash if necessary. */
956 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
960 #if defined (FAILOVER_PROTOCOL)
961 comp
-> cltt
= lease
-> cltt
;
962 comp
-> tstp
= lease
-> tstp
;
963 comp
-> tsfp
= lease
-> tsfp
;
964 #endif /* FAILOVER_PROTOCOL */
965 comp
-> ends
= lease
-> ends
;
966 comp
-> next_binding_state
= lease
-> next_binding_state
;
970 log_error ("Supersede_lease: lease %s with no pool.",
971 piaddr (comp
-> ip_addr
));
975 /* Figure out which queue it's on. */
976 switch (comp
-> binding_state
) {
978 lq
= &comp
-> pool
-> free
;
979 comp
-> pool
-> free_leases
--;
983 lq
= &comp
-> pool
-> active
;
989 lq
= &comp
-> pool
-> expired
;
993 lq
= &comp
-> pool
-> abandoned
;
997 lq
= &comp
-> pool
-> backup
;
998 comp
-> pool
-> backup_leases
--;
1002 log_error ("Lease with bogus binding state: %d",
1003 comp
-> binding_state
);
1004 #if defined (BINDING_STATE_DEBUG)
1010 /* Remove the lease from its current place in its current
1012 prev
= (struct lease
*)0;
1013 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1020 log_error ("Lease with binding state %s not on its queue.",
1021 (comp
-> binding_state
< 1 ||
1022 comp
-> binding_state
> FTS_LAST
)
1024 : binding_state_names
[comp
-> binding_state
- 1]);
1029 lease_dereference (&prev
-> next
, MDL
);
1031 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1032 lease_dereference (&comp
-> next
, MDL
);
1035 lease_dereference (lq
, MDL
);
1037 lease_reference (lq
, comp
-> next
, MDL
);
1038 lease_dereference (&comp
-> next
, MDL
);
1042 /* Make the state transition. */
1043 if (commit
|| !pimmediate
)
1044 make_binding_state_transition (comp
);
1046 /* Put the lease back on the appropriate queue. If the lease
1047 is corrupt (as detected by lease_enqueue), don't go any farther. */
1048 if (!lease_enqueue (comp
))
1051 /* If this is the next lease that will timeout on the pool,
1052 zap the old timeout and set the timeout on this pool to the
1053 time that the lease's next event will happen.
1055 We do not actually set the timeout unless commit is true -
1056 we don't want to thrash the timer queue when reading the
1057 lease database. Instead, the database code calls the
1058 expiry event on each pool after reading in the lease file,
1059 and the expiry code sets the timer if there's anything left
1060 to expire after it's run any outstanding expiry events on
1062 if ((commit
|| !pimmediate
) &&
1063 comp
-> sort_time
!= MIN_TIME
&&
1064 comp
-> sort_time
> cur_time
&&
1065 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1066 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1067 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1068 add_timeout (comp
-> pool
-> next_event_time
,
1069 pool_timer
, comp
-> pool
,
1070 (tvref_t
)pool_reference
,
1071 (tvunref_t
)pool_dereference
);
1075 if (!write_lease (comp
))
1077 if (!commit_leases ())
1081 #if defined (FAILOVER_PROTOCOL)
1083 comp
-> desired_binding_state
= comp
-> binding_state
;
1084 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1089 /* If the current binding state has already expired, do an
1090 expiry event right now. */
1091 /* XXX At some point we should optimize this so that we don't
1092 XXX write the lease twice, but this is a safe way to fix the
1093 XXX problem for 3.0 (I hope!). */
1094 if ((commit
|| !pimmediate
) &&
1095 comp
-> sort_time
< cur_time
&&
1096 comp
-> next_binding_state
!= comp
-> binding_state
)
1097 pool_timer (comp
-> pool
);
1102 void make_binding_state_transition (struct lease
*lease
)
1104 #if defined (FAILOVER_PROTOCOL)
1105 dhcp_failover_state_t
*peer
;
1107 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1108 peer
= lease
-> pool
-> failover_peer
;
1110 peer
= (dhcp_failover_state_t
*)0;
1113 /* If the lease was active and is now no longer active, but isn't
1114 released, then it just expired, so do the expiry event. */
1115 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1117 #if defined (FAILOVER_PROTOCOL)
1119 (lease
-> binding_state
== FTS_EXPIRED
||
1120 (peer
-> i_am
== secondary
&&
1121 lease
-> binding_state
== FTS_ACTIVE
)) &&
1122 (lease
-> next_binding_state
== FTS_FREE
||
1123 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1126 lease
-> binding_state
== FTS_ACTIVE
&&
1127 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1128 #if defined (NSUPDATE)
1129 ddns_removals (lease
);
1131 if (lease
-> on_expiry
) {
1132 execute_statements ((struct binding_value
**)0,
1133 (struct packet
*)0, lease
,
1134 (struct client_state
*)0,
1135 (struct option_state
*)0,
1136 (struct option_state
*)0, /* XXX */
1138 lease
-> on_expiry
);
1139 if (lease
-> on_expiry
)
1140 executable_statement_dereference
1141 (&lease
-> on_expiry
, MDL
);
1144 /* No sense releasing a lease after it's expired. */
1145 if (lease
-> on_release
)
1146 executable_statement_dereference (&lease
-> on_release
,
1148 /* Get rid of client-specific bindings that are only
1149 correct when the lease is active. */
1150 if (lease
-> billing_class
)
1151 unbill_class (lease
, lease
-> billing_class
);
1152 if (lease
-> agent_options
)
1153 option_chain_head_dereference (&lease
-> agent_options
,
1155 if (lease
-> client_hostname
) {
1156 dfree (lease
-> client_hostname
, MDL
);
1157 lease
-> client_hostname
= (char *)0;
1160 host_dereference (&lease
-> host
, MDL
);
1162 /* Send the expiry time to the peer. */
1163 lease
-> tstp
= lease
-> ends
;
1166 /* If the lease was active and is now released, do the release
1168 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1170 #if defined (FAILOVER_PROTOCOL)
1172 lease
-> binding_state
== FTS_RELEASED
&&
1173 (lease
-> next_binding_state
== FTS_FREE
||
1174 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1177 lease
-> binding_state
== FTS_ACTIVE
&&
1178 lease
-> next_binding_state
== FTS_RELEASED
))) {
1179 #if defined (NSUPDATE)
1180 ddns_removals (lease
);
1182 if (lease
-> on_release
) {
1183 execute_statements ((struct binding_value
**)0,
1184 (struct packet
*)0, lease
,
1185 (struct client_state
*)0,
1186 (struct option_state
*)0,
1187 (struct option_state
*)0, /* XXX */
1189 lease
-> on_release
);
1190 executable_statement_dereference (&lease
-> on_release
,
1194 /* A released lease can't expire. */
1195 if (lease
-> on_expiry
)
1196 executable_statement_dereference (&lease
-> on_expiry
,
1199 /* Get rid of client-specific bindings that are only
1200 correct when the lease is active. */
1201 if (lease
-> billing_class
)
1202 unbill_class (lease
, lease
-> billing_class
);
1203 if (lease
-> agent_options
)
1204 option_chain_head_dereference (&lease
-> agent_options
,
1206 if (lease
-> client_hostname
) {
1207 dfree (lease
-> client_hostname
, MDL
);
1208 lease
-> client_hostname
= (char *)0;
1211 host_dereference (&lease
-> host
, MDL
);
1213 /* Send the release time (should be == cur_time) to the
1215 lease
-> tstp
= lease
-> ends
;
1218 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1219 log_debug ("lease %s moves from %s to %s",
1220 piaddr (lease
-> ip_addr
),
1221 binding_state_print (lease
-> binding_state
),
1222 binding_state_print (lease
-> next_binding_state
));
1225 lease
-> binding_state
= lease
-> next_binding_state
;
1226 switch (lease
-> binding_state
) {
1228 #if defined (FAILOVER_PROTOCOL)
1229 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1230 lease
-> next_binding_state
= FTS_EXPIRED
;
1233 lease
-> next_binding_state
= FTS_FREE
;
1240 lease
-> next_binding_state
= FTS_FREE
;
1241 /* If we are not in partner_down, leases don't go from
1242 EXPIRED to FREE on a timeout - only on an update.
1243 If we're in partner_down, they expire at mclt past
1244 the time we entered partner_down. */
1245 if (lease
-> pool
-> failover_peer
&&
1246 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1248 (lease
-> pool
-> failover_peer
-> me
.stos
+
1249 lease
-> pool
-> failover_peer
-> mclt
);
1254 lease
-> next_binding_state
= lease
-> binding_state
;
1257 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1258 log_debug ("lease %s: next binding state %s",
1259 piaddr (lease
-> ip_addr
),
1260 binding_state_print (lease
-> next_binding_state
));
1265 /* Copy the contents of one lease into another, correctly maintaining
1266 reference counts. */
1267 int lease_copy (struct lease
**lp
,
1268 struct lease
*lease
, const char *file
, int line
)
1270 struct lease
*lt
= (struct lease
*)0;
1271 isc_result_t status
;
1273 status
= lease_allocate (<
, MDL
);
1274 if (status
!= ISC_R_SUCCESS
)
1277 lt
-> ip_addr
= lease
-> ip_addr
;
1278 lt
-> starts
= lease
-> starts
;
1279 lt
-> ends
= lease
-> ends
;
1280 lt
-> timestamp
= lease
-> timestamp
;
1281 lt
-> uid_len
= lease
-> uid_len
;
1282 lt
-> uid_max
= lease
-> uid_max
;
1283 if (lease
-> uid
== lease
-> uid_buf
) {
1284 lt
-> uid
= lt
-> uid_buf
;
1285 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1286 } else if (!lease
-> uid_max
) {
1287 lt
-> uid
= (unsigned char *)0;
1289 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1291 lease_dereference (<
, MDL
);
1294 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1296 if (lease
-> client_hostname
) {
1297 lt
-> client_hostname
=
1298 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1299 if (!lt
-> client_hostname
) {
1300 lease_dereference (<
, MDL
);
1303 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1306 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1307 if (lease
-> agent_options
)
1308 option_chain_head_reference (<
-> agent_options
,
1309 lease
-> agent_options
, MDL
);
1310 host_reference (<
-> host
, lease
-> host
, file
, line
);
1311 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1312 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1313 class_reference (<
-> billing_class
,
1314 lease
-> billing_class
, file
, line
);
1315 lt
-> hardware_addr
= lease
-> hardware_addr
;
1316 if (lease
-> on_expiry
)
1317 executable_statement_reference (<
-> on_expiry
,
1320 if (lease
-> on_commit
)
1321 executable_statement_reference (<
-> on_commit
,
1324 if (lease
-> on_release
)
1325 executable_statement_reference (<
-> on_release
,
1326 lease
-> on_release
,
1328 lt
-> flags
= lease
-> flags
;
1329 lt
-> tstp
= lease
-> tstp
;
1330 lt
-> tsfp
= lease
-> tsfp
;
1331 lt
-> cltt
= lease
-> cltt
;
1332 lt
-> binding_state
= lease
-> binding_state
;
1333 lt
-> next_binding_state
= lease
-> next_binding_state
;
1334 status
= lease_reference (lp
, lt
, file
, line
);
1335 lease_dereference (<
, MDL
);
1336 return status
== ISC_R_SUCCESS
;
1339 /* Release the specified lease and re-hash it as appropriate. */
1340 void release_lease (lease
, packet
)
1341 struct lease
*lease
;
1342 struct packet
*packet
;
1344 /* If there are statements to execute when the lease is
1345 released, execute them. */
1346 #if defined (NSUPDATE)
1347 ddns_removals (lease
);
1349 if (lease
-> on_release
) {
1350 execute_statements ((struct binding_value
**)0,
1351 packet
, lease
, (struct client_state
*)0,
1353 (struct option_state
*)0, /* XXX */
1354 &lease
-> scope
, lease
-> on_release
);
1355 if (lease
-> on_release
)
1356 executable_statement_dereference (&lease
-> on_release
,
1360 /* We do either the on_release or the on_expiry events, but
1361 not both (it's possible that they could be the same,
1363 if (lease
-> on_expiry
)
1364 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1366 if (lease
-> binding_state
!= FTS_FREE
&&
1367 lease
-> binding_state
!= FTS_BACKUP
&&
1368 lease
-> binding_state
!= FTS_RELEASED
&&
1369 lease
-> binding_state
!= FTS_EXPIRED
&&
1370 lease
-> binding_state
!= FTS_RESET
) {
1371 if (lease
-> on_commit
)
1372 executable_statement_dereference (&lease
-> on_commit
,
1375 /* Blow away any bindings. */
1377 binding_scope_dereference (&lease
-> scope
, MDL
);
1378 lease
-> ends
= cur_time
;
1379 #if defined (FAILOVER_PROTOCOL)
1380 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1381 lease
-> next_binding_state
= FTS_RELEASED
;
1383 lease
-> next_binding_state
= FTS_FREE
;
1386 lease
-> next_binding_state
= FTS_FREE
;
1388 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1392 /* Abandon the specified lease (set its timeout to infinity and its
1393 particulars to zero, and re-hash it as appropriate. */
1395 void abandon_lease (lease
, message
)
1396 struct lease
*lease
;
1397 const char *message
;
1399 struct lease
*lt
= (struct lease
*)0;
1401 if (!lease_copy (<
, lease
, MDL
))
1405 binding_scope_dereference(<
->scope
, 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
*next
= (struct lease
*)0;
1459 struct lease
*lease
= (struct lease
*)0;
1460 struct lease
**lptr
[5];
1461 TIME next_expiry
= MAX_TIME
;
1464 pool
= (struct pool
*)vpool
;
1466 #define FREE_LEASES 0
1467 lptr
[FREE_LEASES
] = &pool
-> free
;
1468 #define ACTIVE_LEASES 1
1469 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1470 #define EXPIRED_LEASES 2
1471 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1472 #define ABANDONED_LEASES 3
1473 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1474 #define BACKUP_LEASES 4
1475 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1477 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1478 /* If there's nothing on the queue, skip it. */
1482 #if defined (FAILOVER_PROTOCOL)
1483 if (pool
-> failover_peer
&&
1484 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1485 /* The secondary can't remove a lease from the
1486 active state except in partner_down. */
1487 if (i
== ACTIVE_LEASES
&&
1488 pool
-> failover_peer
-> i_am
== secondary
)
1490 /* Leases in an expired state don't move to
1491 free because of a timeout unless we're in
1493 if (i
== EXPIRED_LEASES
)
1497 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1500 /* Remember the next lease in the list. */
1502 lease_dereference (&next
, MDL
);
1504 lease_reference (&next
, lease
-> next
, MDL
);
1506 /* If we've run out of things to expire on this list,
1508 if (lease
-> sort_time
> cur_time
) {
1509 if (lease
-> sort_time
< next_expiry
)
1510 next_expiry
= lease
-> sort_time
;
1514 /* If there is a pending state change, and
1515 this lease has gotten to the time when the
1516 state change should happen, just call
1517 supersede_lease on it to make the change
1519 if (lease
-> next_binding_state
!=
1520 lease
-> binding_state
)
1521 supersede_lease (lease
,
1522 (struct lease
*)0, 1, 1, 1);
1524 lease_dereference (&lease
, MDL
);
1526 lease_reference (&lease
, next
, MDL
);
1529 lease_dereference (&next
, MDL
);
1531 lease_dereference (&lease
, MDL
);
1533 if (next_expiry
!= MAX_TIME
) {
1534 pool
-> next_event_time
= next_expiry
;
1535 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1536 (tvref_t
)pool_reference
,
1537 (tvunref_t
)pool_dereference
);
1539 pool
-> next_event_time
= MIN_TIME
;
1543 /* Locate the lease associated with a given IP address... */
1545 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1546 const char *file
, int line
)
1548 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1549 addr
.iabuf
, addr
.len
, file
, line
);
1552 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1553 unsigned len
, const char *file
, int line
)
1557 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1560 int find_lease_by_hw_addr (struct lease
**lp
,
1561 const unsigned char *hwaddr
, unsigned hwlen
,
1562 const char *file
, int line
)
1566 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1567 hwaddr
, hwlen
, file
, line
);
1570 /* Add the specified lease to the uid hash. */
1572 void uid_hash_add (lease
)
1573 struct lease
*lease
;
1575 struct lease
*head
= (struct lease
*)0;
1576 struct lease
*next
= (struct lease
*)0;
1579 /* If it's not in the hash, just add it. */
1580 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1581 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1582 lease
-> uid_len
, lease
, MDL
);
1584 /* Otherwise, attach it to the end of the list. */
1585 while (head
-> n_uid
) {
1586 lease_reference (&next
, head
-> n_uid
, MDL
);
1587 lease_dereference (&head
, MDL
);
1588 lease_reference (&head
, next
, MDL
);
1589 lease_dereference (&next
, MDL
);
1591 lease_reference (&head
-> n_uid
, lease
, MDL
);
1592 lease_dereference (&head
, MDL
);
1596 /* Delete the specified lease from the uid hash. */
1598 void uid_hash_delete (lease
)
1599 struct lease
*lease
;
1601 struct lease
*head
= (struct lease
*)0;
1604 /* If it's not in the hash, we have no work to do. */
1605 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1607 lease_dereference (&lease
-> n_uid
, MDL
);
1611 /* If the lease we're freeing is at the head of the list,
1612 remove the hash table entry and add a new one with the
1613 next lease on the list (if there is one). */
1614 if (head
== lease
) {
1615 lease_hash_delete (lease_uid_hash
,
1616 lease
-> uid
, lease
-> uid_len
, MDL
);
1617 if (lease
-> n_uid
) {
1618 lease_hash_add (lease_uid_hash
,
1619 lease
-> n_uid
-> uid
,
1620 lease
-> n_uid
-> uid_len
,
1621 lease
-> n_uid
, MDL
);
1622 lease_dereference (&lease
-> n_uid
, MDL
);
1625 /* Otherwise, look for the lease in the list of leases
1626 attached to the hash table entry, and remove it if
1628 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1629 if (scan
-> n_uid
== lease
) {
1630 lease_dereference (&scan
-> n_uid
, MDL
);
1631 if (lease
-> n_uid
) {
1632 lease_reference (&scan
-> n_uid
,
1633 lease
-> n_uid
, MDL
);
1634 lease_dereference (&lease
-> n_uid
,
1641 lease_dereference (&head
, MDL
);
1644 /* Add the specified lease to the hardware address hash. */
1646 void hw_hash_add (lease
)
1647 struct lease
*lease
;
1649 struct lease
*head
= (struct lease
*)0;
1650 struct lease
*next
= (struct lease
*)0;
1652 /* If it's not in the hash, just add it. */
1653 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1654 lease
-> hardware_addr
.hlen
, MDL
))
1655 lease_hash_add (lease_hw_addr_hash
,
1656 lease
-> hardware_addr
.hbuf
,
1657 lease
-> hardware_addr
.hlen
,
1660 /* Otherwise, attach it to the end of the list. */
1661 while (head
-> n_hw
) {
1662 lease_reference (&next
, head
-> n_hw
, MDL
);
1663 lease_dereference (&head
, MDL
);
1664 lease_reference (&head
, next
, MDL
);
1665 lease_dereference (&next
, MDL
);
1668 lease_reference (&head
-> n_hw
, lease
, MDL
);
1669 lease_dereference (&head
, MDL
);
1673 /* Delete the specified lease from the hardware address hash. */
1675 void hw_hash_delete (lease
)
1676 struct lease
*lease
;
1678 struct lease
*head
= (struct lease
*)0;
1679 struct lease
*next
= (struct lease
*)0;
1681 /* If it's not in the hash, we have no work to do. */
1682 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1683 lease
-> hardware_addr
.hlen
, MDL
)) {
1685 lease_dereference (&lease
-> n_hw
, MDL
);
1689 /* If the lease we're freeing is at the head of the list,
1690 remove the hash table entry and add a new one with the
1691 next lease on the list (if there is one). */
1692 if (head
== lease
) {
1693 lease_hash_delete (lease_hw_addr_hash
,
1694 lease
-> hardware_addr
.hbuf
,
1695 lease
-> hardware_addr
.hlen
, MDL
);
1696 if (lease
-> n_hw
) {
1697 lease_hash_add (lease_hw_addr_hash
,
1698 lease
-> n_hw
-> hardware_addr
.hbuf
,
1699 lease
-> n_hw
-> hardware_addr
.hlen
,
1700 lease
-> n_hw
, MDL
);
1701 lease_dereference (&lease
-> n_hw
, MDL
);
1704 /* Otherwise, look for the lease in the list of leases
1705 attached to the hash table entry, and remove it if
1707 while (head
-> n_hw
) {
1708 if (head
-> n_hw
== lease
) {
1709 lease_dereference (&head
-> n_hw
, MDL
);
1710 if (lease
-> n_hw
) {
1711 lease_reference (&head
-> n_hw
,
1712 lease
-> n_hw
, MDL
);
1713 lease_dereference (&lease
-> n_hw
,
1718 lease_reference (&next
, head
-> n_hw
, MDL
);
1719 lease_dereference (&head
, MDL
);
1720 lease_reference (&head
, next
, MDL
);
1721 lease_dereference (&next
, MDL
);
1725 lease_dereference (&head
, MDL
);
1728 /* Write all interesting leases to permanent storage. */
1733 struct shared_network
*s
;
1735 struct host_decl
*hp
;
1736 struct group_object
*gp
;
1737 struct hash_bucket
*hb
;
1740 struct lease
**lptr
[5];
1742 /* Write all the dynamically-created group declarations. */
1743 if (group_name_hash
) {
1745 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1746 for (hb
= group_name_hash
-> buckets
[i
];
1747 hb
; hb
= hb
-> next
) {
1748 gp
= (struct group_object
*)hb
-> value
;
1749 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1750 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1751 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1752 if (!write_group (gp
))
1758 log_info ("Wrote %d group decls to leases file.", num_written
);
1761 /* Write all the deleted host declarations. */
1762 if (host_name_hash
) {
1764 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1765 for (hb
= host_name_hash
-> buckets
[i
];
1766 hb
; hb
= hb
-> next
) {
1767 hp
= (struct host_decl
*)hb
-> value
;
1768 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1769 (hp
-> flags
& HOST_DECL_DELETED
))) {
1770 if (!write_host (hp
))
1776 log_info ("Wrote %d deleted host decls to leases file.",
1780 /* Write all the new, dynamic host declarations. */
1781 if (host_name_hash
) {
1783 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1784 for (hb
= host_name_hash
-> buckets
[i
];
1785 hb
; hb
= hb
-> next
) {
1786 hp
= (struct host_decl
*)hb
-> value
;
1787 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1788 if (!write_host (hp
))
1793 log_info ("Wrote %d new dynamic host decls to leases file.",
1797 #if defined (FAILOVER_PROTOCOL)
1798 /* Write all the failover states. */
1799 if (!dhcp_failover_write_all_states ())
1803 /* Write all the leases. */
1805 for (s
= shared_networks
; s
; s
= s
-> next
) {
1806 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1807 lptr
[FREE_LEASES
] = &p
-> free
;
1808 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1809 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1810 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1811 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1813 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1814 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1815 #if !defined (DEBUG_DUMP_ALL_LEASES)
1816 if (l
-> hardware_addr
.hlen
||
1818 (l
-> binding_state
!= FTS_FREE
))
1821 if (!write_lease (l
))
1829 log_info ("Wrote %d leases to leases file.", num_written
);
1830 if (!commit_leases ())
1835 int lease_enqueue (struct lease
*comp
)
1837 struct lease
**lq
, *prev
, *lp
;
1839 /* No queue to put it on? */
1843 /* Figure out which queue it's going to. */
1844 switch (comp
-> binding_state
) {
1846 lq
= &comp
-> pool
-> free
;
1847 comp
-> pool
-> free_leases
++;
1848 comp
-> sort_time
= comp
-> ends
;
1852 lq
= &comp
-> pool
-> active
;
1853 comp
-> sort_time
= comp
-> ends
;
1859 lq
= &comp
-> pool
-> expired
;
1860 comp
-> sort_time
= comp
-> ends
;
1865 lq
= &comp
-> pool
-> abandoned
;
1866 comp
-> sort_time
= comp
-> ends
;
1870 lq
= &comp
-> pool
-> backup
;
1871 comp
-> pool
-> backup_leases
++;
1872 comp
-> sort_time
= comp
-> ends
;
1876 log_error ("Lease with bogus binding state: %d",
1877 comp
-> binding_state
);
1878 #if defined (BINDING_STATE_DEBUG)
1884 /* Insertion sort the lease onto the appropriate queue. */
1885 prev
= (struct lease
*)0;
1886 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1887 if (lp
-> sort_time
>= comp
-> sort_time
)
1893 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1894 lease_dereference (&prev
-> next
, MDL
);
1896 lease_reference (&prev
-> next
, comp
, MDL
);
1899 lease_reference (&comp
-> next
, *lq
, MDL
);
1900 lease_dereference (lq
, MDL
);
1902 lease_reference (lq
, comp
, MDL
);
1907 /* For a given lease, sort it onto the right list in its pool and put it
1908 in each appropriate hash, understanding that it's already by definition
1909 in lease_ip_addr_hash. */
1911 void lease_instantiate (const unsigned char *val
, unsigned len
,
1912 struct lease
*lease
)
1914 struct class *class;
1915 /* XXX If the lease doesn't have a pool at this point, it's an
1916 XXX orphan, which we *should* keep around until it expires,
1917 XXX but which right now we just forget. */
1918 if (!lease
-> pool
) {
1919 lease_hash_delete (lease_ip_addr_hash
,
1920 lease
-> ip_addr
.iabuf
,
1921 lease
-> ip_addr
.len
, MDL
);
1925 /* Put the lease on the right queue. */
1926 lease_enqueue (lease
);
1928 /* Record the lease in the uid hash if possible. */
1930 uid_hash_add (lease
);
1933 /* Record it in the hardware address hash if possible. */
1934 if (lease
-> hardware_addr
.hlen
) {
1935 hw_hash_add (lease
);
1938 /* If the lease has a billing class, set up the billing. */
1939 if (lease
-> billing_class
) {
1940 class = (struct class *)0;
1941 class_reference (&class, lease
-> billing_class
, MDL
);
1942 class_dereference (&lease
-> billing_class
, MDL
);
1943 /* If the lease is available for allocation, the billing
1944 is invalid, so we don't keep it. */
1945 if (lease
-> binding_state
== FTS_ACTIVE
||
1946 lease
-> binding_state
== FTS_EXPIRED
||
1947 lease
-> binding_state
== FTS_RELEASED
||
1948 lease
-> binding_state
== FTS_RESET
)
1949 bill_class (lease
, class);
1950 class_dereference (&class, MDL
);
1955 /* Run expiry events on every pool. This is called on startup so that
1956 any expiry events that occurred after the server stopped and before it
1957 was restarted can be run. At the same time, if failover support is
1958 compiled in, we compute the balance of leases for the pool. */
1960 void expire_all_pools ()
1962 struct shared_network
*s
;
1966 struct lease
**lptr
[5];
1968 /* First, go over the hash list and actually put all the leases
1969 on the appropriate lists. */
1970 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1972 /* Loop through each pool in each shared network and call the
1973 expiry routine on the pool. */
1974 for (s
= shared_networks
; s
; s
= s
-> next
) {
1975 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1978 p
-> lease_count
= 0;
1979 p
-> free_leases
= 0;
1980 p
-> backup_leases
= 0;
1982 lptr
[FREE_LEASES
] = &p
-> free
;
1983 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1984 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1985 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1986 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1988 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1989 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1991 if (l
-> ends
<= cur_time
) {
1992 if (l
-> binding_state
== FTS_FREE
)
1994 else if (l
-> binding_state
== FTS_BACKUP
)
1995 p
-> backup_leases
++;
1997 #if defined (FAILOVER_PROTOCOL)
1998 if (p
-> failover_peer
&&
1999 l
-> tstp
> l
-> tsfp
&&
2000 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2001 l
-> desired_binding_state
= l
-> binding_state
;
2002 dhcp_failover_queue_update (l
, 1);
2011 void dump_subnets ()
2014 struct shared_network
*s
;
2017 struct lease
**lptr
[5];
2020 log_info ("Subnets:");
2021 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2022 log_debug (" Subnet %s", piaddr (n
-> net
));
2023 log_debug (" netmask %s",
2024 piaddr (n
-> netmask
));
2026 log_info ("Shared networks:");
2027 for (s
= shared_networks
; s
; s
= s
-> next
) {
2028 log_info (" %s", s
-> name
);
2029 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2030 lptr
[FREE_LEASES
] = &p
-> free
;
2031 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2032 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2033 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2034 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2036 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2037 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2045 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
, lease_hash_t
,
2046 lease_reference
, lease_dereference
)
2047 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2048 host_reference
, host_dereference
)
2049 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2050 class_reference
, class_dereference
)
2052 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2053 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2054 extern struct hash_table
*dns_zone_hash
;
2055 extern struct interface_info
**interface_vector
;
2056 extern int interface_count
;
2057 dhcp_control_object_t
*dhcp_control_object
;
2058 extern struct hash_table
*auth_key_hash
;
2059 struct hash_table
*universe_hash
;
2060 struct universe
**universes
;
2061 int universe_count
, universe_max
;
2066 #if defined (COMPACT_LEASES)
2067 extern struct lease
*lease_hunks
;
2070 void free_everything ()
2072 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2073 struct shared_network
*nc
= (struct shared_network
*)0,
2074 *nn
= (struct shared_network
*)0;
2075 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2076 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2077 struct interface_info
*ic
= (struct interface_info
*)0,
2078 *in
= (struct interface_info
*)0;
2079 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2080 struct collection
*lp
;
2081 void *st
= (shared_networks
2082 ? (shared_networks
-> next
2083 ? shared_networks
-> next
-> next
: 0) : 0);
2087 /* Get rid of all the hash tables. */
2088 if (host_hw_addr_hash
)
2089 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2090 host_hw_addr_hash
= 0;
2092 host_free_hash_table (&host_uid_hash
, MDL
);
2095 lease_free_hash_table (&lease_uid_hash
, MDL
);
2097 if (lease_ip_addr_hash
)
2098 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2099 lease_ip_addr_hash
= 0;
2100 if (lease_hw_addr_hash
)
2101 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2102 lease_hw_addr_hash
= 0;
2104 host_free_hash_table (&host_name_hash
, MDL
);
2107 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2111 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2115 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2118 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2119 if (lp
-> classes
) {
2120 class_reference (&cn
, lp
-> classes
, MDL
);
2123 class_reference (&cc
, cn
, MDL
);
2124 class_dereference (&cn
, MDL
);
2127 class_reference (&cn
, cc
-> nic
, MDL
);
2128 class_dereference (&cc
-> nic
, MDL
);
2130 group_dereference (&cc
-> group
, MDL
);
2132 class_free_hash_table (&cc
-> hash
, MDL
);
2133 cc
-> hash
= (struct hash_table
*)0;
2135 class_dereference (&cc
, MDL
);
2137 class_dereference (&lp
-> classes
, MDL
);
2141 if (interface_vector
) {
2142 for (i
= 0; i
< interface_count
; i
++) {
2143 if (interface_vector
[i
])
2144 interface_dereference (&interface_vector
[i
], MDL
);
2146 dfree (interface_vector
, MDL
);
2147 interface_vector
= 0;
2151 interface_reference (&in
, interfaces
, MDL
);
2154 interface_reference (&ic
, in
, MDL
);
2155 interface_dereference (&in
, MDL
);
2158 interface_reference (&in
, ic
-> next
, MDL
);
2159 interface_dereference (&ic
-> next
, MDL
);
2161 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2162 if (ic
-> shared_network
) {
2163 if (ic
-> shared_network
-> interface
)
2164 interface_dereference
2165 (&ic
-> shared_network
-> interface
, MDL
);
2166 shared_network_dereference (&ic
-> shared_network
, MDL
);
2168 interface_dereference (&ic
, MDL
);
2170 interface_dereference (&interfaces
, MDL
);
2173 /* Subnets are complicated because of the extra links. */
2175 subnet_reference (&sn
, subnets
, MDL
);
2178 subnet_reference (&sc
, sn
, MDL
);
2179 subnet_dereference (&sn
, MDL
);
2181 if (sc
-> next_subnet
) {
2182 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2183 subnet_dereference (&sc
-> next_subnet
, MDL
);
2185 if (sc
-> next_sibling
)
2186 subnet_dereference (&sc
-> next_sibling
, MDL
);
2187 if (sc
-> shared_network
)
2188 shared_network_dereference (&sc
-> shared_network
, MDL
);
2189 group_dereference (&sc
-> group
, MDL
);
2190 if (sc
-> interface
)
2191 interface_dereference (&sc
-> interface
, MDL
);
2192 subnet_dereference (&sc
, MDL
);
2194 subnet_dereference (&subnets
, MDL
);
2197 /* So are shared networks. */
2198 if (shared_networks
) {
2199 shared_network_reference (&nn
, shared_networks
, MDL
);
2202 shared_network_reference (&nc
, nn
, MDL
);
2203 shared_network_dereference (&nn
, MDL
);
2206 shared_network_reference (&nn
, nc
-> next
, MDL
);
2207 shared_network_dereference (&nc
-> next
, MDL
);
2212 pool_reference (&pn
, nc
-> pools
, MDL
);
2214 struct lease
**lptr
[5];
2217 pool_reference (&pc
, pn
, MDL
);
2218 pool_dereference (&pn
, MDL
);
2221 pool_reference (&pn
, pc
-> next
, MDL
);
2222 pool_dereference (&pc
-> next
, MDL
);
2225 lptr
[FREE_LEASES
] = &pc
-> free
;
2226 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2227 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2228 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2229 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2231 /* As (sigh) are leases. */
2232 for (i
= 0; i
< 5; i
++) {
2234 lease_reference (&ln
, *lptr
[i
], MDL
);
2237 lease_reference (&lc
, ln
, MDL
);
2238 lease_dereference (&ln
, MDL
);
2241 lease_reference (&ln
, lc
-> next
, MDL
);
2242 lease_dereference (&lc
-> next
, MDL
);
2244 if (lc
-> billing_class
)
2245 class_dereference (&lc
-> billing_class
,
2248 free_lease_state (lc
-> state
, MDL
);
2249 lc
-> state
= (struct lease_state
*)0;
2251 lease_dereference (&lc
-> n_hw
, MDL
);
2253 lease_dereference (&lc
-> n_uid
, MDL
);
2254 lease_dereference (&lc
, MDL
);
2256 lease_dereference (lptr
[i
], MDL
);
2260 group_dereference (&pc
-> group
, MDL
);
2261 if (pc
-> shared_network
)
2262 shared_network_dereference (&pc
-> shared_network
,
2264 pool_dereference (&pc
, MDL
);
2266 pool_dereference (&nc
-> pools
, MDL
);
2268 /* Because of a circular reference, we need to nuke this
2270 group_dereference (&nc
-> group
, MDL
);
2271 shared_network_dereference (&nc
, MDL
);
2273 shared_network_dereference (&shared_networks
, MDL
);
2276 cancel_all_timeouts ();
2277 relinquish_timeouts ();
2279 group_dereference (&root_group
, MDL
);
2280 executable_statement_dereference (&default_classification_rules
, MDL
);
2282 shutdown_state
= shutdown_drop_omapi_connections
;
2283 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2284 shutdown_state
= shutdown_listeners
;
2285 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2286 shutdown_state
= shutdown_dhcp
;
2287 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2289 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2291 universe_free_hash_table (&universe_hash
, MDL
);
2292 for (i
= 0; i
< universe_count
; i
++) {
2297 if (universes
[i
]) {
2298 if (universes
[i
] -> hash
)
2299 option_free_hash_table (&universes
[i
] -> hash
,
2302 if (universes
[i
] -> name
> (char *)&end
) {
2303 foo
.c
= universes
[i
] -> name
;
2306 if (universes
[i
] > (struct universe
*)&end
)
2307 dfree (universes
[i
], MDL
);
2311 dfree (universes
, MDL
);
2313 relinquish_free_lease_states ();
2314 relinquish_free_pairs ();
2315 relinquish_free_expressions ();
2316 relinquish_free_binding_values ();
2317 relinquish_free_option_caches ();
2318 relinquish_free_packets ();
2319 relinquish_lease_hunks ();
2320 relinquish_hash_bucket_hunks ();
2321 omapi_type_relinquish ();
2323 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */