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$ 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 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
))
1408 binding_scope_dereference(<
->scope
, MDL
);
1410 lt
-> ends
= cur_time
; /* XXX */
1411 lt
-> next_binding_state
= FTS_ABANDONED
;
1413 log_error ("Abandoning IP address %s: %s",
1414 piaddr (lease
-> ip_addr
), message
);
1415 lt
-> hardware_addr
.hlen
= 0;
1416 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1417 dfree (lt
-> uid
, MDL
);
1418 lt
-> uid
= (unsigned char *)0;
1421 supersede_lease (lease
, lt
, 1, 1, 1);
1422 lease_dereference (<
, MDL
);
1425 /* Abandon the specified lease (set its timeout to infinity and its
1426 particulars to zero, and re-hash it as appropriate. */
1428 void dissociate_lease (lease
)
1429 struct lease
*lease
;
1431 struct lease
*lt
= (struct lease
*)0;
1433 if (!lease_copy (<
, lease
, MDL
))
1436 #if defined (FAILOVER_PROTOCOL)
1437 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1438 lt
-> next_binding_state
= FTS_RESET
;
1440 lt
-> next_binding_state
= FTS_FREE
;
1443 lt
-> next_binding_state
= FTS_FREE
;
1445 lt
-> ends
= cur_time
; /* XXX */
1446 lt
-> hardware_addr
.hlen
= 0;
1447 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1448 dfree (lt
-> uid
, MDL
);
1449 lt
-> uid
= (unsigned char *)0;
1452 supersede_lease (lease
, lt
, 1, 1, 1);
1453 lease_dereference (<
, MDL
);
1456 /* Timer called when a lease in a particular pool expires. */
1457 void pool_timer (vpool
)
1461 struct lease
*lt
= (struct lease
*)0;
1462 struct lease
*next
= (struct lease
*)0;
1463 struct lease
*lease
= (struct lease
*)0;
1464 struct lease
**lptr
[5];
1465 TIME next_expiry
= MAX_TIME
;
1468 pool
= (struct pool
*)vpool
;
1470 #define FREE_LEASES 0
1471 lptr
[FREE_LEASES
] = &pool
-> free
;
1472 #define ACTIVE_LEASES 1
1473 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1474 #define EXPIRED_LEASES 2
1475 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1476 #define ABANDONED_LEASES 3
1477 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1478 #define BACKUP_LEASES 4
1479 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1481 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1482 /* If there's nothing on the queue, skip it. */
1486 #if defined (FAILOVER_PROTOCOL)
1487 if (pool
-> failover_peer
&&
1488 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1489 /* The secondary can't remove a lease from the
1490 active state except in partner_down. */
1491 if (i
== ACTIVE_LEASES
&&
1492 pool
-> failover_peer
-> i_am
== secondary
)
1494 /* Leases in an expired state don't move to
1495 free because of a timeout unless we're in
1497 if (i
== EXPIRED_LEASES
)
1501 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1504 /* Remember the next lease in the list. */
1506 lease_dereference (&next
, MDL
);
1508 lease_reference (&next
, lease
-> next
, MDL
);
1510 /* If we've run out of things to expire on this list,
1512 if (lease
-> sort_time
> cur_time
) {
1513 if (lease
-> sort_time
< next_expiry
)
1514 next_expiry
= lease
-> sort_time
;
1518 /* If there is a pending state change, and
1519 this lease has gotten to the time when the
1520 state change should happen, just call
1521 supersede_lease on it to make the change
1523 if (lease
-> next_binding_state
!=
1524 lease
-> binding_state
)
1525 supersede_lease (lease
,
1526 (struct lease
*)0, 1, 1, 1);
1528 lease_dereference (&lease
, MDL
);
1530 lease_reference (&lease
, next
, MDL
);
1533 lease_dereference (&next
, MDL
);
1535 lease_dereference (&lease
, MDL
);
1537 if (next_expiry
!= MAX_TIME
) {
1538 pool
-> next_event_time
= next_expiry
;
1539 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1540 (tvref_t
)pool_reference
,
1541 (tvunref_t
)pool_dereference
);
1543 pool
-> next_event_time
= MIN_TIME
;
1547 /* Locate the lease associated with a given IP address... */
1549 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1550 const char *file
, int line
)
1552 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1553 addr
.iabuf
, addr
.len
, file
, line
);
1556 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1557 unsigned len
, const char *file
, int line
)
1561 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1564 int find_lease_by_hw_addr (struct lease
**lp
,
1565 const unsigned char *hwaddr
, unsigned hwlen
,
1566 const char *file
, int line
)
1570 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1571 hwaddr
, hwlen
, file
, line
);
1574 /* Add the specified lease to the uid hash. */
1576 void uid_hash_add (lease
)
1577 struct lease
*lease
;
1579 struct lease
*head
= (struct lease
*)0;
1580 struct lease
*next
= (struct lease
*)0;
1583 /* If it's not in the hash, just add it. */
1584 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1585 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1586 lease
-> uid_len
, lease
, MDL
);
1588 /* Otherwise, attach it to the end of the list. */
1589 while (head
-> n_uid
) {
1590 lease_reference (&next
, head
-> n_uid
, MDL
);
1591 lease_dereference (&head
, MDL
);
1592 lease_reference (&head
, next
, MDL
);
1593 lease_dereference (&next
, MDL
);
1595 lease_reference (&head
-> n_uid
, lease
, MDL
);
1596 lease_dereference (&head
, MDL
);
1600 /* Delete the specified lease from the uid hash. */
1602 void uid_hash_delete (lease
)
1603 struct lease
*lease
;
1605 struct lease
*head
= (struct lease
*)0;
1608 /* If it's not in the hash, we have no work to do. */
1609 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1611 lease_dereference (&lease
-> n_uid
, MDL
);
1615 /* If the lease we're freeing is at the head of the list,
1616 remove the hash table entry and add a new one with the
1617 next lease on the list (if there is one). */
1618 if (head
== lease
) {
1619 lease_hash_delete (lease_uid_hash
,
1620 lease
-> uid
, lease
-> uid_len
, MDL
);
1621 if (lease
-> n_uid
) {
1622 lease_hash_add (lease_uid_hash
,
1623 lease
-> n_uid
-> uid
,
1624 lease
-> n_uid
-> uid_len
,
1625 lease
-> n_uid
, MDL
);
1626 lease_dereference (&lease
-> n_uid
, MDL
);
1629 /* Otherwise, look for the lease in the list of leases
1630 attached to the hash table entry, and remove it if
1632 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1633 if (scan
-> n_uid
== lease
) {
1634 lease_dereference (&scan
-> n_uid
, MDL
);
1635 if (lease
-> n_uid
) {
1636 lease_reference (&scan
-> n_uid
,
1637 lease
-> n_uid
, MDL
);
1638 lease_dereference (&lease
-> n_uid
,
1645 lease_dereference (&head
, MDL
);
1648 /* Add the specified lease to the hardware address hash. */
1650 void hw_hash_add (lease
)
1651 struct lease
*lease
;
1653 struct lease
*head
= (struct lease
*)0;
1654 struct lease
*next
= (struct lease
*)0;
1656 /* If it's not in the hash, just add it. */
1657 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1658 lease
-> hardware_addr
.hlen
, MDL
))
1659 lease_hash_add (lease_hw_addr_hash
,
1660 lease
-> hardware_addr
.hbuf
,
1661 lease
-> hardware_addr
.hlen
,
1664 /* Otherwise, attach it to the end of the list. */
1665 while (head
-> n_hw
) {
1666 lease_reference (&next
, head
-> n_hw
, MDL
);
1667 lease_dereference (&head
, MDL
);
1668 lease_reference (&head
, next
, MDL
);
1669 lease_dereference (&next
, MDL
);
1672 lease_reference (&head
-> n_hw
, lease
, MDL
);
1673 lease_dereference (&head
, MDL
);
1677 /* Delete the specified lease from the hardware address hash. */
1679 void hw_hash_delete (lease
)
1680 struct lease
*lease
;
1682 struct lease
*head
= (struct lease
*)0;
1683 struct lease
*next
= (struct lease
*)0;
1685 /* If it's not in the hash, we have no work to do. */
1686 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1687 lease
-> hardware_addr
.hlen
, MDL
)) {
1689 lease_dereference (&lease
-> n_hw
, MDL
);
1693 /* If the lease we're freeing is at the head of the list,
1694 remove the hash table entry and add a new one with the
1695 next lease on the list (if there is one). */
1696 if (head
== lease
) {
1697 lease_hash_delete (lease_hw_addr_hash
,
1698 lease
-> hardware_addr
.hbuf
,
1699 lease
-> hardware_addr
.hlen
, MDL
);
1700 if (lease
-> n_hw
) {
1701 lease_hash_add (lease_hw_addr_hash
,
1702 lease
-> n_hw
-> hardware_addr
.hbuf
,
1703 lease
-> n_hw
-> hardware_addr
.hlen
,
1704 lease
-> n_hw
, MDL
);
1705 lease_dereference (&lease
-> n_hw
, MDL
);
1708 /* Otherwise, look for the lease in the list of leases
1709 attached to the hash table entry, and remove it if
1711 while (head
-> n_hw
) {
1712 if (head
-> n_hw
== lease
) {
1713 lease_dereference (&head
-> n_hw
, MDL
);
1714 if (lease
-> n_hw
) {
1715 lease_reference (&head
-> n_hw
,
1716 lease
-> n_hw
, MDL
);
1717 lease_dereference (&lease
-> n_hw
,
1722 lease_reference (&next
, head
-> n_hw
, MDL
);
1723 lease_dereference (&head
, MDL
);
1724 lease_reference (&head
, next
, MDL
);
1725 lease_dereference (&next
, MDL
);
1729 lease_dereference (&head
, MDL
);
1732 /* Write all interesting leases to permanent storage. */
1737 struct shared_network
*s
;
1739 struct host_decl
*hp
;
1740 struct group_object
*gp
;
1741 struct hash_bucket
*hb
;
1744 struct lease
**lptr
[5];
1746 /* Write all the dynamically-created group declarations. */
1747 if (group_name_hash
) {
1749 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1750 for (hb
= group_name_hash
-> buckets
[i
];
1751 hb
; hb
= hb
-> next
) {
1752 gp
= (struct group_object
*)hb
-> value
;
1753 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1754 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1755 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1756 if (!write_group (gp
))
1762 log_info ("Wrote %d group decls to leases file.", num_written
);
1765 /* Write all the deleted host declarations. */
1766 if (host_name_hash
) {
1768 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1769 for (hb
= host_name_hash
-> buckets
[i
];
1770 hb
; hb
= hb
-> next
) {
1771 hp
= (struct host_decl
*)hb
-> value
;
1772 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1773 (hp
-> flags
& HOST_DECL_DELETED
))) {
1774 if (!write_host (hp
))
1780 log_info ("Wrote %d deleted host decls to leases file.",
1784 /* Write all the new, dynamic host declarations. */
1785 if (host_name_hash
) {
1787 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1788 for (hb
= host_name_hash
-> buckets
[i
];
1789 hb
; hb
= hb
-> next
) {
1790 hp
= (struct host_decl
*)hb
-> value
;
1791 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1792 if (!write_host (hp
))
1797 log_info ("Wrote %d new dynamic host decls to leases file.",
1801 #if defined (FAILOVER_PROTOCOL)
1802 /* Write all the failover states. */
1803 if (!dhcp_failover_write_all_states ())
1807 /* Write all the leases. */
1809 for (s
= shared_networks
; s
; s
= s
-> next
) {
1810 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1811 lptr
[FREE_LEASES
] = &p
-> free
;
1812 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1813 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1814 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1815 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1817 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1818 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1819 #if !defined (DEBUG_DUMP_ALL_LEASES)
1820 if (l
-> hardware_addr
.hlen
||
1822 (l
-> binding_state
!= FTS_FREE
))
1825 if (!write_lease (l
))
1833 log_info ("Wrote %d leases to leases file.", num_written
);
1834 if (!commit_leases ())
1839 int lease_enqueue (struct lease
*comp
)
1841 struct lease
**lq
, *prev
, *lp
;
1843 /* No queue to put it on? */
1847 /* Figure out which queue it's going to. */
1848 switch (comp
-> binding_state
) {
1850 lq
= &comp
-> pool
-> free
;
1851 comp
-> pool
-> free_leases
++;
1852 comp
-> sort_time
= comp
-> ends
;
1856 lq
= &comp
-> pool
-> active
;
1857 comp
-> sort_time
= comp
-> ends
;
1863 lq
= &comp
-> pool
-> expired
;
1864 comp
-> sort_time
= comp
-> ends
;
1869 lq
= &comp
-> pool
-> abandoned
;
1870 comp
-> sort_time
= comp
-> ends
;
1874 lq
= &comp
-> pool
-> backup
;
1875 comp
-> pool
-> backup_leases
++;
1876 comp
-> sort_time
= comp
-> ends
;
1880 log_error ("Lease with bogus binding state: %d",
1881 comp
-> binding_state
);
1882 #if defined (BINDING_STATE_DEBUG)
1888 /* Insertion sort the lease onto the appropriate queue. */
1889 prev
= (struct lease
*)0;
1890 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1891 if (lp
-> sort_time
>= comp
-> sort_time
)
1897 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1898 lease_dereference (&prev
-> next
, MDL
);
1900 lease_reference (&prev
-> next
, comp
, MDL
);
1903 lease_reference (&comp
-> next
, *lq
, MDL
);
1904 lease_dereference (lq
, MDL
);
1906 lease_reference (lq
, comp
, MDL
);
1911 /* For a given lease, sort it onto the right list in its pool and put it
1912 in each appropriate hash, understanding that it's already by definition
1913 in lease_ip_addr_hash. */
1915 void lease_instantiate (const unsigned char *val
, unsigned len
,
1916 struct lease
*lease
)
1918 struct class *class;
1919 /* XXX If the lease doesn't have a pool at this point, it's an
1920 XXX orphan, which we *should* keep around until it expires,
1921 XXX but which right now we just forget. */
1922 if (!lease
-> pool
) {
1923 lease_hash_delete (lease_ip_addr_hash
,
1924 lease
-> ip_addr
.iabuf
,
1925 lease
-> ip_addr
.len
, MDL
);
1929 /* Put the lease on the right queue. */
1930 lease_enqueue (lease
);
1932 /* Record the lease in the uid hash if possible. */
1934 uid_hash_add (lease
);
1937 /* Record it in the hardware address hash if possible. */
1938 if (lease
-> hardware_addr
.hlen
) {
1939 hw_hash_add (lease
);
1942 /* If the lease has a billing class, set up the billing. */
1943 if (lease
-> billing_class
) {
1944 class = (struct class *)0;
1945 class_reference (&class, lease
-> billing_class
, MDL
);
1946 class_dereference (&lease
-> billing_class
, MDL
);
1947 /* If the lease is available for allocation, the billing
1948 is invalid, so we don't keep it. */
1949 if (lease
-> binding_state
== FTS_ACTIVE
||
1950 lease
-> binding_state
== FTS_EXPIRED
||
1951 lease
-> binding_state
== FTS_RELEASED
||
1952 lease
-> binding_state
== FTS_RESET
)
1953 bill_class (lease
, class);
1954 class_dereference (&class, MDL
);
1959 /* Run expiry events on every pool. This is called on startup so that
1960 any expiry events that occurred after the server stopped and before it
1961 was restarted can be run. At the same time, if failover support is
1962 compiled in, we compute the balance of leases for the pool. */
1964 void expire_all_pools ()
1966 struct shared_network
*s
;
1968 struct hash_bucket
*hb
;
1971 struct lease
**lptr
[5];
1973 /* First, go over the hash list and actually put all the leases
1974 on the appropriate lists. */
1975 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1977 /* Loop through each pool in each shared network and call the
1978 expiry routine on the pool. */
1979 for (s
= shared_networks
; s
; s
= s
-> next
) {
1980 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1983 p
-> lease_count
= 0;
1984 p
-> free_leases
= 0;
1985 p
-> backup_leases
= 0;
1987 lptr
[FREE_LEASES
] = &p
-> free
;
1988 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1989 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1990 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1991 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1993 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1994 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1996 if (l
-> ends
<= cur_time
) {
1997 if (l
-> binding_state
== FTS_FREE
)
1999 else if (l
-> binding_state
== FTS_BACKUP
)
2000 p
-> backup_leases
++;
2002 #if defined (FAILOVER_PROTOCOL)
2003 if (p
-> failover_peer
&&
2004 l
-> tstp
> l
-> tsfp
&&
2005 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2006 l
-> desired_binding_state
= l
-> binding_state
;
2007 dhcp_failover_queue_update (l
, 1);
2016 void dump_subnets ()
2019 struct shared_network
*s
;
2022 struct lease
**lptr
[5];
2025 log_info ("Subnets:");
2026 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2027 log_debug (" Subnet %s", piaddr (n
-> net
));
2028 log_debug (" netmask %s",
2029 piaddr (n
-> netmask
));
2031 log_info ("Shared networks:");
2032 for (s
= shared_networks
; s
; s
= s
-> next
) {
2033 log_info (" %s", s
-> name
);
2034 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2035 lptr
[FREE_LEASES
] = &p
-> free
;
2036 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2037 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2038 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2039 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2041 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2042 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2050 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
, lease_hash_t
,
2051 lease_reference
, lease_dereference
)
2052 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2053 host_reference
, host_dereference
)
2054 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2055 class_reference
, class_dereference
)
2057 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2058 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2059 extern struct hash_table
*dns_zone_hash
;
2060 extern struct interface_info
**interface_vector
;
2061 extern int interface_count
;
2062 dhcp_control_object_t
*dhcp_control_object
;
2063 extern struct hash_table
*auth_key_hash
;
2064 struct hash_table
*universe_hash
;
2065 struct universe
**universes
;
2066 int universe_count
, universe_max
;
2071 #if defined (COMPACT_LEASES)
2072 extern struct lease
*lease_hunks
;
2075 void free_everything ()
2077 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2078 struct shared_network
*nc
= (struct shared_network
*)0,
2079 *nn
= (struct shared_network
*)0;
2080 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2081 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2082 struct interface_info
*ic
= (struct interface_info
*)0,
2083 *in
= (struct interface_info
*)0;
2084 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2085 struct collection
*lp
;
2086 void *st
= (shared_networks
2087 ? (shared_networks
-> next
2088 ? shared_networks
-> next
-> next
: 0) : 0);
2092 /* Get rid of all the hash tables. */
2093 if (host_hw_addr_hash
)
2094 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2095 host_hw_addr_hash
= 0;
2097 host_free_hash_table (&host_uid_hash
, MDL
);
2100 lease_free_hash_table (&lease_uid_hash
, MDL
);
2102 if (lease_ip_addr_hash
)
2103 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2104 lease_ip_addr_hash
= 0;
2105 if (lease_hw_addr_hash
)
2106 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2107 lease_hw_addr_hash
= 0;
2109 host_free_hash_table (&host_name_hash
, MDL
);
2112 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2116 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2120 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2123 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2124 if (lp
-> classes
) {
2125 class_reference (&cn
, lp
-> classes
, MDL
);
2128 class_reference (&cc
, cn
, MDL
);
2129 class_dereference (&cn
, MDL
);
2132 class_reference (&cn
, cc
-> nic
, MDL
);
2133 class_dereference (&cc
-> nic
, MDL
);
2135 group_dereference (&cc
-> group
, MDL
);
2137 class_free_hash_table (&cc
-> hash
, MDL
);
2138 cc
-> hash
= (struct hash_table
*)0;
2140 class_dereference (&cc
, MDL
);
2142 class_dereference (&lp
-> classes
, MDL
);
2146 if (interface_vector
) {
2147 for (i
= 0; i
< interface_count
; i
++) {
2148 if (interface_vector
[i
])
2149 interface_dereference (&interface_vector
[i
], MDL
);
2151 dfree (interface_vector
, MDL
);
2152 interface_vector
= 0;
2156 interface_reference (&in
, interfaces
, MDL
);
2159 interface_reference (&ic
, in
, MDL
);
2160 interface_dereference (&in
, MDL
);
2163 interface_reference (&in
, ic
-> next
, MDL
);
2164 interface_dereference (&ic
-> next
, MDL
);
2166 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2167 if (ic
-> shared_network
) {
2168 if (ic
-> shared_network
-> interface
)
2169 interface_dereference
2170 (&ic
-> shared_network
-> interface
, MDL
);
2171 shared_network_dereference (&ic
-> shared_network
, MDL
);
2173 interface_dereference (&ic
, MDL
);
2175 interface_dereference (&interfaces
, MDL
);
2178 /* Subnets are complicated because of the extra links. */
2180 subnet_reference (&sn
, subnets
, MDL
);
2183 subnet_reference (&sc
, sn
, MDL
);
2184 subnet_dereference (&sn
, MDL
);
2186 if (sc
-> next_subnet
) {
2187 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2188 subnet_dereference (&sc
-> next_subnet
, MDL
);
2190 if (sc
-> next_sibling
)
2191 subnet_dereference (&sc
-> next_sibling
, MDL
);
2192 if (sc
-> shared_network
)
2193 shared_network_dereference (&sc
-> shared_network
, MDL
);
2194 group_dereference (&sc
-> group
, MDL
);
2195 if (sc
-> interface
)
2196 interface_dereference (&sc
-> interface
, MDL
);
2197 subnet_dereference (&sc
, MDL
);
2199 subnet_dereference (&subnets
, MDL
);
2202 /* So are shared networks. */
2203 if (shared_networks
) {
2204 shared_network_reference (&nn
, shared_networks
, MDL
);
2207 shared_network_reference (&nc
, nn
, MDL
);
2208 shared_network_dereference (&nn
, MDL
);
2211 shared_network_reference (&nn
, nc
-> next
, MDL
);
2212 shared_network_dereference (&nc
-> next
, MDL
);
2217 pool_reference (&pn
, nc
-> pools
, MDL
);
2219 struct lease
**lptr
[5];
2222 pool_reference (&pc
, pn
, MDL
);
2223 pool_dereference (&pn
, MDL
);
2226 pool_reference (&pn
, pc
-> next
, MDL
);
2227 pool_dereference (&pc
-> next
, MDL
);
2230 lptr
[FREE_LEASES
] = &pc
-> free
;
2231 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2232 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2233 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2234 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2236 /* As (sigh) are leases. */
2237 for (i
= 0; i
< 5; i
++) {
2239 lease_reference (&ln
, *lptr
[i
], MDL
);
2242 lease_reference (&lc
, ln
, MDL
);
2243 lease_dereference (&ln
, MDL
);
2246 lease_reference (&ln
, lc
-> next
, MDL
);
2247 lease_dereference (&lc
-> next
, MDL
);
2249 if (lc
-> billing_class
)
2250 class_dereference (&lc
-> billing_class
,
2253 free_lease_state (lc
-> state
, MDL
);
2254 lc
-> state
= (struct lease_state
*)0;
2256 lease_dereference (&lc
-> n_hw
, MDL
);
2258 lease_dereference (&lc
-> n_uid
, MDL
);
2259 lease_dereference (&lc
, MDL
);
2261 lease_dereference (lptr
[i
], MDL
);
2265 group_dereference (&pc
-> group
, MDL
);
2266 if (pc
-> shared_network
)
2267 shared_network_dereference (&pc
-> shared_network
,
2269 pool_dereference (&pc
, MDL
);
2271 pool_dereference (&nc
-> pools
, MDL
);
2273 /* Because of a circular reference, we need to nuke this
2275 group_dereference (&nc
-> group
, MDL
);
2276 shared_network_dereference (&nc
, MDL
);
2278 shared_network_dereference (&shared_networks
, MDL
);
2281 cancel_all_timeouts ();
2282 relinquish_timeouts ();
2284 group_dereference (&root_group
, MDL
);
2285 executable_statement_dereference (&default_classification_rules
, MDL
);
2287 shutdown_state
= shutdown_drop_omapi_connections
;
2288 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2289 shutdown_state
= shutdown_listeners
;
2290 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2291 shutdown_state
= shutdown_dhcp
;
2292 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2294 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2296 universe_free_hash_table (&universe_hash
, MDL
);
2297 for (i
= 0; i
< universe_count
; i
++) {
2302 if (universes
[i
]) {
2303 if (universes
[i
] -> hash
)
2304 option_free_hash_table (&universes
[i
] -> hash
,
2307 if (universes
[i
] -> name
> (char *)&end
) {
2308 foo
.c
= universes
[i
] -> name
;
2311 if (universes
[i
] > (struct universe
*)&end
)
2312 dfree (universes
[i
], MDL
);
2316 dfree (universes
, MDL
);
2318 relinquish_free_lease_states ();
2319 relinquish_free_pairs ();
2320 relinquish_free_expressions ();
2321 relinquish_free_binding_values ();
2322 relinquish_free_option_caches ();
2323 relinquish_free_packets ();
2324 relinquish_lease_hunks ();
2325 relinquish_hash_bucket_hunks ();
2326 omapi_type_relinquish ();
2328 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */