3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2006 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.74 2006/02/24 23:16:32 dhankins Exp $ Copyright (c) 2004-2006 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 int numclasseswritten
;
54 omapi_object_type_t
*dhcp_type_host
;
56 isc_result_t
enter_class(cd
, dynamicp
, commit
)
61 if (!collections
-> classes
) {
62 /* A subclass with no parent is invalid. */
64 return ISC_R_INVALIDARG
;
66 class_reference (&collections
-> classes
, cd
, MDL
);
67 } else if (cd
->name
!= NULL
) { /* regular class */
70 if (find_class(&c
, cd
->name
, MDL
) != ISC_R_NOTFOUND
) {
71 class_dereference(&c
, MDL
);
76 for (c
= collections
-> classes
;
77 c
-> nic
; c
= c
-> nic
)
79 class_reference (&c
-> nic
, cd
, MDL
);
82 if (dynamicp
&& commit
) {
83 const char *name
= cd
->name
;
86 name
= cd
->superclass
->name
;
89 write_named_billing_class (name
, 0, cd
);
90 if (!commit_leases ())
98 static int find_uid_statement (struct executable_statement
*esp
,
101 struct executable_statement
**evp
= vp
;
103 if (esp
-> op
== supersede_option_statement
&&
104 esp
-> data
.option
&&
105 (esp
-> data
.option
-> option
-> universe
==
107 (esp
-> data
.option
-> option
-> code
==
108 DHO_DHCP_CLIENT_IDENTIFIER
)) {
110 log_error ("dhcp client identifier may not be %s",
111 "specified conditionally.");
112 } else if (!(*evp
)) {
113 executable_statement_reference (evp
, esp
, MDL
);
116 log_error ("only one dhcp client identifier may be %s",
123 isc_result_t
enter_host (hd
, dynamicp
, commit
)
124 struct host_decl
*hd
;
128 struct host_decl
*hp
= (struct host_decl
*)0;
129 struct host_decl
*np
= (struct host_decl
*)0;
130 struct executable_statement
*esp
;
132 if (!host_name_hash
) {
133 if (!host_new_hash (&host_name_hash
, 0, MDL
))
134 log_fatal ("Can't allocate host name hash");
135 host_hash_add (host_name_hash
,
136 (unsigned char *)hd
-> name
,
137 strlen (hd
-> name
), hd
, MDL
);
139 host_hash_lookup (&hp
, host_name_hash
,
140 (unsigned char *)hd
-> name
,
141 strlen (hd
-> name
), MDL
);
143 /* If it's deleted, we can supersede it. */
144 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
145 host_hash_delete (host_name_hash
,
146 (unsigned char *)hd
-> name
,
147 strlen (hd
-> name
), MDL
);
148 /* If the old entry wasn't dynamic, then we
149 always have to keep the deletion. */
150 if (hp
-> flags
& HOST_DECL_STATIC
) {
151 hd
-> flags
|= HOST_DECL_STATIC
;
153 host_dereference (&hp
, MDL
);
156 /* If we are updating an existing host declaration, we
157 can just delete it and add it again. */
158 if (hp
&& hp
== hd
) {
159 host_dereference (&hp
, MDL
);
161 if (!write_host (hd
))
162 return ISC_R_IOERROR
;
163 hd
-> flags
&= ~HOST_DECL_DELETED
;
166 /* If there isn't already a host decl matching this
167 address, add it to the hash table. */
169 host_hash_add (host_name_hash
,
170 (unsigned char *)hd
-> name
,
171 strlen (hd
-> name
), hd
, MDL
);
173 /* XXX actually, we have to delete the old one
174 XXX carefully and replace it. Not done yet. */
175 host_dereference (&hp
, MDL
);
181 host_dereference (&hd
-> n_ipaddr
, MDL
);
184 hd
-> type
= dhcp_type_host
;
186 if (hd
-> interface
.hlen
) {
187 if (!host_hw_addr_hash
) {
188 if (!host_new_hash (&host_hw_addr_hash
, 0, MDL
))
189 log_fatal ("Can't allocate host/hw hash");
191 /* If there isn't already a host decl matching this
192 address, add it to the hash table. */
193 host_hash_lookup (&hp
, host_hw_addr_hash
,
194 hd
-> interface
.hbuf
,
195 hd
-> interface
.hlen
, MDL
);
198 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
199 hd
-> interface
.hlen
, hd
, MDL
);
201 /* If there was already a host declaration for
202 this hardware address, add this one to the
204 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
206 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
207 host_dereference (&hp
, MDL
);
211 /* See if there's a statement that sets the client identifier.
212 This is a kludge - the client identifier really shouldn't be
213 set with an executable statement. */
214 esp
= (struct executable_statement
*)0;
215 if (executable_statement_foreach (hd
-> group
-> statements
,
216 find_uid_statement
, &esp
, 0)) {
217 evaluate_option_cache (&hd
-> client_identifier
,
220 (struct client_state
*)0,
221 (struct option_state
*)0,
222 (struct option_state
*)0, &global_scope
,
223 esp
-> data
.option
, MDL
);
226 /* If we got a client identifier, hash this entry by
227 client identifier. */
228 if (hd
-> client_identifier
.len
) {
229 /* If there's no uid hash, make one; otherwise, see if
230 there's already an entry in the hash for this host. */
231 if (!host_uid_hash
) {
232 if (!host_new_hash (&host_uid_hash
, 0, MDL
))
233 log_fatal ("Can't allocate host/uid hash");
235 host_hash_add (host_uid_hash
,
236 hd
-> client_identifier
.data
,
237 hd
-> client_identifier
.len
,
240 /* If there's already a host declaration for this
241 client identifier, add this one to the end of the
242 list. Otherwise, add it to the hash table. */
243 if (host_hash_lookup (&hp
, host_uid_hash
,
244 hd
-> client_identifier
.data
,
245 hd
-> client_identifier
.len
,
247 /* Don't link it in twice... */
249 for (np
= hp
; np
-> n_ipaddr
;
250 np
= np
-> n_ipaddr
) {
255 host_reference (&np
-> n_ipaddr
,
258 host_dereference (&hp
, MDL
);
260 host_hash_add (host_uid_hash
,
261 hd
-> client_identifier
.data
,
262 hd
-> client_identifier
.len
,
268 if (dynamicp
&& commit
) {
269 if (!write_host (hd
))
270 return ISC_R_IOERROR
;
271 if (!commit_leases ())
272 return ISC_R_IOERROR
;
275 return ISC_R_SUCCESS
;
279 isc_result_t
delete_class (cp
, commit
)
283 cp
->flags
|= CLASS_DECL_DELETED
;
285 /* do the write first as we won't be leaving it in any data
286 structures, unlike the host objects */
289 write_named_billing_class (cp
->name
, 0, cp
);
290 if (!commit_leases ())
291 return ISC_R_IOERROR
;
294 unlink_class(&cp
); /* remove from collections */
296 class_dereference(&cp
, MDL
);
298 return ISC_R_SUCCESS
;
302 isc_result_t
delete_host (hd
, commit
)
303 struct host_decl
*hd
;
306 struct host_decl
*hp
= (struct host_decl
*)0;
307 struct host_decl
*np
= (struct host_decl
*)0;
308 struct host_decl
*foo
;
309 struct executable_statement
*esp
;
310 int hw_head
= 0, uid_head
= 1;
312 /* Don't need to do it twice. */
313 if (hd
-> flags
& HOST_DECL_DELETED
)
314 return ISC_R_SUCCESS
;
316 /* But we do need to do it once! :') */
317 hd
-> flags
|= HOST_DECL_DELETED
;
319 if (hd
-> interface
.hlen
) {
320 if (host_hw_addr_hash
) {
321 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
322 hd
-> interface
.hbuf
,
323 hd
-> interface
.hlen
, MDL
)) {
325 host_hash_delete (host_hw_addr_hash
,
326 hd
-> interface
.hbuf
,
327 hd
-> interface
.hlen
, MDL
);
330 np
= (struct host_decl
*)0;
331 foo
= (struct host_decl
*)0;
332 host_reference (&foo
, hp
, MDL
);
337 host_dereference (&np
, MDL
);
338 host_reference (&np
, foo
, MDL
);
339 host_dereference (&foo
, MDL
);
341 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
345 host_dereference (&np
-> n_ipaddr
, MDL
);
347 host_reference (&np
-> n_ipaddr
,
348 hd
-> n_ipaddr
, MDL
);
349 host_dereference (&foo
, MDL
);
352 host_dereference (&np
, MDL
);
354 host_dereference (&hp
, MDL
);
359 /* If we got a client identifier, hash this entry by
360 client identifier. */
361 if (hd
-> client_identifier
.len
) {
363 if (host_hash_lookup (&hp
, host_uid_hash
,
364 hd
-> client_identifier
.data
,
365 hd
-> client_identifier
.len
, MDL
)) {
367 host_hash_delete (host_uid_hash
,
368 hd
-> client_identifier
.data
,
369 hd
-> client_identifier
.len
, MDL
);
372 np
= (struct host_decl
*)0;
373 foo
= (struct host_decl
*)0;
374 host_reference (&foo
, hp
, MDL
);
379 host_dereference (&np
, MDL
);
380 host_reference (&np
, foo
, MDL
);
381 host_dereference (&foo
, MDL
);
383 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
387 host_dereference (&np
-> n_ipaddr
, MDL
);
389 host_reference (&np
-> n_ipaddr
,
390 hd
-> n_ipaddr
, MDL
);
391 host_dereference (&foo
, MDL
);
394 host_dereference (&np
, MDL
);
396 host_dereference (&hp
, MDL
);
401 if (hd
-> n_ipaddr
) {
402 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
405 hd
-> n_ipaddr
-> client_identifier
.data
,
406 hd
-> n_ipaddr
-> client_identifier
.len
,
407 hd
-> n_ipaddr
, MDL
);
409 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
410 host_hash_add (host_hw_addr_hash
,
411 hd
-> n_ipaddr
-> interface
.hbuf
,
412 hd
-> n_ipaddr
-> interface
.hlen
,
413 hd
-> n_ipaddr
, MDL
);
415 host_dereference (&hd
-> n_ipaddr
, MDL
);
418 if (host_name_hash
) {
419 if (host_hash_lookup (&hp
, host_name_hash
,
420 (unsigned char *)hd
-> name
,
421 strlen (hd
-> name
), MDL
)) {
422 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
423 host_hash_delete (host_name_hash
,
424 (unsigned char *)hd
-> name
,
425 strlen (hd
-> name
), MDL
);
427 host_dereference (&hp
, MDL
);
432 if (!write_host (hd
))
433 return ISC_R_IOERROR
;
434 if (!commit_leases ())
435 return ISC_R_IOERROR
;
437 return ISC_R_SUCCESS
;
440 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
441 const unsigned char *haddr
, unsigned hlen
,
442 const char *file
, int line
)
444 struct host_decl
*foo
;
449 memcpy (&h
.hbuf
[1], haddr
, hlen
);
451 return host_hash_lookup (hp
, host_hw_addr_hash
,
452 h
.hbuf
, h
.hlen
, file
, line
);
455 int find_hosts_by_uid (struct host_decl
**hp
,
456 const unsigned char *data
, unsigned len
,
457 const char *file
, int line
)
459 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
462 /* More than one host_decl can be returned by find_hosts_by_haddr or
463 find_hosts_by_uid, and each host_decl can have multiple addresses.
464 Loop through the list of hosts, and then for each host, through the
465 list of addresses, looking for an address that's in the same shared
466 network as the one specified. Store the matching address through
467 the addr pointer, update the host pointer to point at the host_decl
468 that matched, and return the subnet that matched. */
470 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
471 struct iaddr
*addr
, struct shared_network
*share
)
474 struct subnet
*subnet
;
475 struct iaddr ip_address
;
476 struct host_decl
*hp
;
477 struct data_string fixed_addr
;
479 memset (&fixed_addr
, 0, sizeof fixed_addr
);
481 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
482 if (!hp
-> fixed_addr
)
484 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
486 (struct client_state
*)0,
487 (struct option_state
*)0,
488 (struct option_state
*)0,
490 hp
-> fixed_addr
, MDL
))
492 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
494 memcpy (ip_address
.iabuf
,
495 fixed_addr
.data
+ i
, 4);
496 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
497 struct host_decl
*tmp
= (struct host_decl
*)0;
499 /* This is probably not necessary, but
500 just in case *host is the only reference
501 to that host declaration, make a temporary
502 reference so that dereferencing it doesn't
503 dereference hp out from under us. */
504 host_reference (&tmp
, *host
, MDL
);
505 host_dereference (host
, MDL
);
506 host_reference (host
, hp
, MDL
);
507 host_dereference (&tmp
, MDL
);
508 data_string_forget (&fixed_addr
, MDL
);
512 data_string_forget (&fixed_addr
, MDL
);
517 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
519 struct iaddr low
, high
;
520 struct subnet
*subnet
;
522 struct lease
**lpchain
;
524 struct lease
*address_range
, *lp
, *plp
;
526 unsigned min
, max
, i
;
527 char lowbuf
[16], highbuf
[16], netbuf
[16];
528 struct shared_network
*share
= subnet
-> shared_network
;
530 struct lease
*lt
= (struct lease
*)0;
532 /* All subnets should have attached shared network structures. */
534 strcpy (netbuf
, piaddr (subnet
-> net
));
535 log_fatal ("No shared network for network %s (%s)",
536 netbuf
, piaddr (subnet
-> netmask
));
539 /* Initialize the hash table if it hasn't been done yet. */
540 if (!lease_uid_hash
) {
541 if (!lease_new_hash (&lease_uid_hash
, 0, MDL
))
542 log_fatal ("Can't allocate lease/uid hash");
544 if (!lease_ip_addr_hash
) {
545 if (!lease_new_hash (&lease_ip_addr_hash
, 0, MDL
))
546 log_fatal ("Can't allocate lease/ip hash");
548 if (!lease_hw_addr_hash
) {
549 if (!lease_new_hash (&lease_hw_addr_hash
, 0, MDL
))
550 log_fatal ("Can't allocate lease/hw hash");
553 /* Make sure that high and low addresses are in same subnet. */
554 net
= subnet_number (low
, subnet
-> netmask
);
555 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
556 strcpy (lowbuf
, piaddr (low
));
557 strcpy (highbuf
, piaddr (high
));
558 strcpy (netbuf
, piaddr (subnet
-> netmask
));
559 log_fatal ("Address range %s to %s, netmask %s spans %s!",
560 lowbuf
, highbuf
, netbuf
, "multiple subnets");
563 /* Make sure that the addresses are on the correct subnet. */
564 if (!addr_eq (net
, subnet
-> net
)) {
565 strcpy (lowbuf
, piaddr (low
));
566 strcpy (highbuf
, piaddr (high
));
567 strcpy (netbuf
, piaddr (subnet
-> netmask
));
568 log_fatal ("Address range %s to %s not on net %s/%s!",
569 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
572 /* Get the high and low host addresses... */
573 max
= host_addr (high
, subnet
-> netmask
);
574 min
= host_addr (low
, subnet
-> netmask
);
576 /* Allow range to be specified high-to-low as well as low-to-high. */
579 min
= host_addr (high
, subnet
-> netmask
);
582 /* Get a lease structure for each address in the range. */
583 #if defined (COMPACT_LEASES)
584 address_range
= new_leases (max
- min
+ 1, MDL
);
585 if (!address_range
) {
586 strcpy (lowbuf
, piaddr (low
));
587 strcpy (highbuf
, piaddr (high
));
588 log_fatal ("No memory for address range %s-%s.",
593 /* Fill out the lease structures with some minimal information. */
594 for (i
= 0; i
< max
- min
+ 1; i
++) {
595 struct lease
*lp
= (struct lease
*)0;
596 #if defined (COMPACT_LEASES)
597 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
599 0, sizeof (struct lease
), MDL
);
600 lease_reference (&lp
, &address_range
[i
], MDL
);
602 status
= lease_allocate (&lp
, MDL
);
603 if (status
!= ISC_R_SUCCESS
)
604 log_fatal ("No memory for lease %s: %s",
605 piaddr (ip_addr (subnet
-> net
,
608 isc_result_totext (status
));
610 lp
-> ip_addr
= ip_addr (subnet
-> net
,
611 subnet
-> netmask
, i
+ min
);
612 lp
-> starts
= lp
-> timestamp
= MIN_TIME
;
613 lp
-> ends
= MIN_TIME
;
614 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
615 pool_reference (&lp
-> pool
, pool
, MDL
);
616 lp
-> binding_state
= FTS_FREE
;
617 lp
-> next_binding_state
= FTS_FREE
;
620 /* Remember the lease in the IP address hash. */
621 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
624 "lease %s is declared twice!",
625 piaddr (lp
-> ip_addr
));
627 pool_reference (<
-> pool
, pool
, MDL
);
628 lease_dereference (<
, MDL
);
630 lease_hash_add (lease_ip_addr_hash
,
632 lp
-> ip_addr
.len
, lp
, MDL
);
633 /* Put the lease on the chain for the caller. */
636 lease_reference (&lp
-> next
, *lpchain
, MDL
);
637 lease_dereference (lpchain
, MDL
);
639 lease_reference (lpchain
, lp
, MDL
);
641 lease_dereference (&lp
, MDL
);
645 int find_subnet (struct subnet
**sp
,
646 struct iaddr addr
, const char *file
, int line
)
650 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
651 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
652 if (subnet_reference (sp
, rv
,
653 file
, line
) != ISC_R_SUCCESS
)
661 int find_grouped_subnet (struct subnet
**sp
,
662 struct shared_network
*share
, struct iaddr addr
,
663 const char *file
, int line
)
667 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
668 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
669 if (subnet_reference (sp
, rv
,
670 file
, line
) != ISC_R_SUCCESS
)
678 int subnet_inner_than (subnet
, scan
, warnp
)
679 struct subnet
*subnet
, *scan
;
682 if (addr_eq (subnet_number (subnet
-> net
, scan
-> netmask
),
684 addr_eq (subnet_number (scan
-> net
, subnet
-> netmask
),
688 for (i
= 0; i
< 32; i
++)
689 if (subnet
-> netmask
.iabuf
[3 - (i
>> 3)]
692 for (j
= 0; j
< 32; j
++)
693 if (scan
-> netmask
.iabuf
[3 - (j
>> 3)] &
696 strcpy (n1buf
, piaddr (subnet
-> net
));
698 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
699 "Warning: ", n1buf
, 32 - i
,
700 piaddr (scan
-> net
), 32 - j
);
707 /* Enter a new subnet into the subnet list. */
708 void enter_subnet (subnet
)
709 struct subnet
*subnet
;
711 struct subnet
*scan
= (struct subnet
*)0;
712 struct subnet
*next
= (struct subnet
*)0;
713 struct subnet
*prev
= (struct subnet
*)0;
715 /* Check for duplicates... */
717 subnet_reference (&next
, subnets
, MDL
);
719 subnet_reference (&scan
, next
, MDL
);
720 subnet_dereference (&next
, MDL
);
722 /* When we find a conflict, make sure that the
723 subnet with the narrowest subnet mask comes
725 if (subnet_inner_than (subnet
, scan
, 1)) {
727 if (prev
-> next_subnet
)
728 subnet_dereference (&prev
-> next_subnet
, MDL
);
729 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
730 subnet_dereference (&prev
, MDL
);
732 subnet_dereference (&subnets
, MDL
);
733 subnet_reference (&subnets
, subnet
, MDL
);
735 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
736 subnet_dereference (&scan
, MDL
);
739 subnet_reference (&prev
, scan
, MDL
);
740 subnet_dereference (&scan
, MDL
);
743 subnet_dereference (&prev
, MDL
);
745 /* XXX use the BSD radix tree code instead of a linked list. */
747 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
748 subnet_dereference (&subnets
, MDL
);
750 subnet_reference (&subnets
, subnet
, MDL
);
753 /* Enter a new shared network into the shared network list. */
755 void enter_shared_network (share
)
756 struct shared_network
*share
;
758 if (shared_networks
) {
759 shared_network_reference (&share
-> next
,
760 shared_networks
, MDL
);
761 shared_network_dereference (&shared_networks
, MDL
);
763 shared_network_reference (&shared_networks
, share
, MDL
);
766 void new_shared_network_interface (cfile
, share
, name
)
768 struct shared_network
*share
;
771 struct interface_info
*ip
;
774 if (share
-> interface
) {
776 "A subnet or shared network can't be connected %s",
777 "to two interfaces.");
781 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
782 if (!strcmp (ip
-> name
, name
))
785 status
= interface_allocate (&ip
, MDL
);
786 if (status
!= ISC_R_SUCCESS
)
787 log_fatal ("new_shared_network_interface %s: %s",
788 name
, isc_result_totext (status
));
789 if (strlen (name
) > sizeof ip
-> name
) {
790 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
791 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
793 strcpy (ip
-> name
, name
);
795 interface_reference (&ip
-> next
, interfaces
, MDL
);
796 interface_dereference (&interfaces
, MDL
);
798 interface_reference (&interfaces
, ip
, MDL
);
799 ip
-> flags
= INTERFACE_REQUESTED
;
800 /* XXX this is a reference loop. */
801 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
802 interface_reference (&share
-> interface
, ip
, MDL
);
806 /* Enter a lease into the system. This is called by the parser each
807 time it reads in a new lease. If the subnet for that lease has
808 already been read in (usually the case), just update that lease;
809 otherwise, allocate temporary storage for the lease and keep it around
810 until we're done reading in the config file. */
812 void enter_lease (lease
)
815 struct lease
*comp
= (struct lease
*)0;
818 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
820 log_error ("undeclared lease found in database: %s",
821 piaddr (lease
-> ip_addr
));
823 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
826 subnet_reference (&lease
-> subnet
,
827 comp
-> subnet
, MDL
);
828 lease_hash_delete (lease_ip_addr_hash
,
829 lease
-> ip_addr
.iabuf
,
830 lease
-> ip_addr
.len
, MDL
);
831 lease_dereference (&comp
, MDL
);
834 /* The only way a lease can get here without a subnet is if it's in
835 the lease file, but not in the dhcpd.conf file. In this case, we
836 *should* keep it around until it's expired, but never reallocate it
837 or renew it. Currently, to maintain consistency, we are not doing
839 XXX fix this so that the lease is kept around until it expires.
840 XXX this will be important in IPv6 with addresses that become
841 XXX non-renewable as a result of a renumbering event. */
843 if (!lease
-> subnet
) {
844 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
847 lease_hash_add (lease_ip_addr_hash
,
848 lease
-> ip_addr
.iabuf
,
849 lease
-> ip_addr
.len
, lease
, MDL
);
852 /* Replace the data in an existing lease with the data in a new lease;
853 adjust hash tables to suit, and insertion sort the lease into the
854 list of leases by expiry time so that we can always find the oldest
857 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
858 struct lease
*comp
, *lease
;
864 int enter_hwaddr
= 0;
865 struct lease
*lp
, **lq
, *prev
;
868 #if defined (FAILOVER_PROTOCOL)
869 /* We must commit leases before sending updates regarding them
870 to failover peers. It is, therefore, an error to set pimmediate
872 if (pimmediate
&& !commit
)
876 /* If there is no sample lease, just do the move. */
880 /* Static leases are not currently kept in the database... */
881 if (lease
-> flags
& STATIC_LEASE
)
884 /* If the existing lease hasn't expired and has a different
885 unique identifier or, if it doesn't have a unique
886 identifier, a different hardware address, then the two
887 leases are in conflict. If the existing lease has a uid
888 and the new one doesn't, but they both have the same
889 hardware address, and dynamic bootp is allowed on this
890 lease, then we allow that, in case a dynamic BOOTP lease is
891 requested *after* a DHCP lease has been assigned. */
893 if (lease
-> binding_state
!= FTS_ABANDONED
&&
894 lease
-> next_binding_state
!= FTS_ABANDONED
&&
895 (comp
-> binding_state
== FTS_ACTIVE
||
896 comp
-> binding_state
== FTS_RESERVED
||
897 comp
-> binding_state
== FTS_BOOTP
) &&
898 (((comp
-> uid
&& lease
-> uid
) &&
899 (comp
-> uid_len
!= lease
-> uid_len
||
900 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
902 ((comp
-> hardware_addr
.hlen
!=
903 lease
-> hardware_addr
.hlen
) ||
904 memcmp (comp
-> hardware_addr
.hbuf
,
905 lease
-> hardware_addr
.hbuf
,
906 comp
-> hardware_addr
.hlen
))))) {
907 log_error ("Lease conflict at %s",
908 piaddr (comp
-> ip_addr
));
911 /* If there's a Unique ID, dissociate it from the hash
912 table and free it if necessary. */
914 uid_hash_delete (comp
);
916 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
917 dfree (comp
-> uid
, MDL
);
921 comp
-> uid
= (unsigned char *)0;
925 if (comp
-> hardware_addr
.hlen
&&
926 ((comp
-> hardware_addr
.hlen
!=
927 lease
-> hardware_addr
.hlen
) ||
928 memcmp (comp
-> hardware_addr
.hbuf
,
929 lease
-> hardware_addr
.hbuf
,
930 comp
-> hardware_addr
.hlen
))) {
931 hw_hash_delete (comp
);
933 } else if (!comp
-> hardware_addr
.hlen
)
936 /* If the lease has been billed to a class, remove the billing. */
937 if (comp
-> billing_class
!= lease
-> billing_class
) {
938 if (comp
-> billing_class
)
939 unbill_class (comp
, comp
-> billing_class
);
940 if (lease
-> billing_class
)
941 bill_class (comp
, lease
-> billing_class
);
944 /* Copy the data files, but not the linkages. */
945 comp
-> starts
= lease
-> starts
;
947 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
948 memcpy (comp
-> uid_buf
,
949 lease
-> uid
, lease
-> uid_len
);
950 comp
-> uid
= &comp
-> uid_buf
[0];
951 comp
-> uid_max
= sizeof comp
-> uid_buf
;
952 comp
-> uid_len
= lease
-> uid_len
;
953 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
954 comp
-> uid
= lease
-> uid
;
955 comp
-> uid_max
= lease
-> uid_max
;
956 lease
-> uid
= (unsigned char *)0;
957 lease
-> uid_max
= 0;
958 comp
-> uid_len
= lease
-> uid_len
;
959 lease
-> uid_len
= 0;
961 log_fatal ("corrupt lease uid."); /* XXX */
964 comp
-> uid
= (unsigned char *)0;
965 comp
-> uid_len
= comp
-> uid_max
= 0;
968 host_dereference (&comp
-> host
, MDL
);
969 host_reference (&comp
-> host
, lease
-> host
, MDL
);
970 comp
-> hardware_addr
= lease
-> hardware_addr
;
971 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
972 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
974 binding_scope_dereference (&comp
-> scope
, MDL
);
975 if (lease
-> scope
) {
976 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
977 binding_scope_dereference (&lease
-> scope
, MDL
);
980 if (comp
-> agent_options
)
981 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
982 if (lease
-> agent_options
) {
983 /* Only retain the agent options if the lease is still
984 affirmatively associated with a client. */
985 if (lease
-> next_binding_state
== FTS_ACTIVE
||
986 lease
-> next_binding_state
== FTS_EXPIRED
)
987 option_chain_head_reference (&comp
-> agent_options
,
988 lease
-> agent_options
,
990 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
993 /* Record the hostname information in the lease. */
994 if (comp
-> client_hostname
)
995 dfree (comp
-> client_hostname
, MDL
);
996 comp
-> client_hostname
= lease
-> client_hostname
;
997 lease
-> client_hostname
= (char *)0;
999 if (lease
-> on_expiry
) {
1000 if (comp
-> on_expiry
)
1001 executable_statement_dereference (&comp
-> on_expiry
,
1003 executable_statement_reference (&comp
-> on_expiry
,
1007 if (lease
-> on_commit
) {
1008 if (comp
-> on_commit
)
1009 executable_statement_dereference (&comp
-> on_commit
,
1011 executable_statement_reference (&comp
-> on_commit
,
1015 if (lease
-> on_release
) {
1016 if (comp
-> on_release
)
1017 executable_statement_dereference (&comp
-> on_release
,
1019 executable_statement_reference (&comp
-> on_release
,
1020 lease
-> on_release
, MDL
);
1023 /* Record the lease in the uid hash if necessary. */
1024 if (enter_uid
&& comp
-> uid
) {
1025 uid_hash_add (comp
);
1028 /* Record it in the hardware address hash if necessary. */
1029 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
1033 #if defined (FAILOVER_PROTOCOL)
1034 comp
->cltt
= lease
->cltt
;
1035 comp
->tstp
= lease
->tstp
;
1036 comp
->tsfp
= lease
->tsfp
;
1037 comp
->atsfp
= lease
->atsfp
;
1038 #endif /* FAILOVER_PROTOCOL */
1039 comp
->ends
= lease
->ends
;
1040 comp
->next_binding_state
= lease
->next_binding_state
;
1043 #if defined (FAILOVER_PROTOCOL)
1044 /* Atsfp should be cleared upon any state change that implies
1045 * propogation wether supersede_lease was given a copy lease
1046 * structure or not (often from the pool_timer()).
1050 #endif /* FAILOVER_PROTOCOL */
1052 if (!comp
-> pool
) {
1053 log_error ("Supersede_lease: lease %s with no pool.",
1054 piaddr (comp
-> ip_addr
));
1058 /* Figure out which queue it's on. */
1059 switch (comp
-> binding_state
) {
1061 lq
= &comp
-> pool
-> free
;
1062 comp
-> pool
-> free_leases
--;
1066 lq
= &comp
-> pool
-> active
;
1072 lq
= &comp
-> pool
-> expired
;
1076 lq
= &comp
-> pool
-> abandoned
;
1080 lq
= &comp
-> pool
-> backup
;
1081 comp
-> pool
-> backup_leases
--;
1085 log_error ("Lease with bogus binding state: %d",
1086 comp
-> binding_state
);
1087 #if defined (BINDING_STATE_DEBUG)
1093 /* Remove the lease from its current place in its current
1095 /* XXX this is horrid. */
1096 prev
= (struct lease
*)0;
1097 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1104 log_error ("Lease with binding state %s not on its queue.",
1105 (comp
-> binding_state
< 1 ||
1106 comp
-> binding_state
> FTS_LAST
)
1108 : binding_state_names
[comp
-> binding_state
- 1]);
1113 lease_dereference (&prev
-> next
, MDL
);
1115 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1116 lease_dereference (&comp
-> next
, MDL
);
1119 lease_dereference (lq
, MDL
);
1121 lease_reference (lq
, comp
-> next
, MDL
);
1122 lease_dereference (&comp
-> next
, MDL
);
1126 /* Make the state transition. */
1127 if (commit
|| !pimmediate
)
1128 make_binding_state_transition (comp
);
1130 /* Put the lease back on the appropriate queue. If the lease
1131 is corrupt (as detected by lease_enqueue), don't go any farther. */
1132 if (!lease_enqueue (comp
))
1135 /* If this is the next lease that will timeout on the pool,
1136 zap the old timeout and set the timeout on this pool to the
1137 time that the lease's next event will happen.
1139 We do not actually set the timeout unless commit is true -
1140 we don't want to thrash the timer queue when reading the
1141 lease database. Instead, the database code calls the
1142 expiry event on each pool after reading in the lease file,
1143 and the expiry code sets the timer if there's anything left
1144 to expire after it's run any outstanding expiry events on
1146 if ((commit
|| !pimmediate
) &&
1147 comp
-> sort_time
!= MIN_TIME
&&
1148 comp
-> sort_time
> cur_time
&&
1149 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1150 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1151 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1152 add_timeout (comp
-> pool
-> next_event_time
,
1153 pool_timer
, comp
-> pool
,
1154 (tvref_t
)pool_reference
,
1155 (tvunref_t
)pool_dereference
);
1159 if (!write_lease (comp
))
1161 if (!commit_leases ())
1165 #if defined (FAILOVER_PROTOCOL)
1167 comp
-> desired_binding_state
= comp
-> binding_state
;
1168 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1173 /* If the current binding state has already expired, do an
1174 expiry event right now. */
1175 /* XXX At some point we should optimize this so that we don't
1176 XXX write the lease twice, but this is a safe way to fix the
1177 XXX problem for 3.0 (I hope!). */
1178 if ((commit
|| !pimmediate
) &&
1179 comp
-> sort_time
< cur_time
&&
1180 comp
-> next_binding_state
!= comp
-> binding_state
)
1181 pool_timer (comp
-> pool
);
1186 void make_binding_state_transition (struct lease
*lease
)
1188 #if defined (FAILOVER_PROTOCOL)
1189 dhcp_failover_state_t
*peer
;
1191 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1192 peer
= lease
-> pool
-> failover_peer
;
1194 peer
= (dhcp_failover_state_t
*)0;
1197 /* If the lease was active and is now no longer active, but isn't
1198 released, then it just expired, so do the expiry event. */
1199 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1201 #if defined (FAILOVER_PROTOCOL)
1203 (lease
-> binding_state
== FTS_EXPIRED
||
1204 (peer
-> i_am
== secondary
&&
1205 lease
-> binding_state
== FTS_ACTIVE
)) &&
1206 (lease
-> next_binding_state
== FTS_FREE
||
1207 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1210 lease
-> binding_state
== FTS_ACTIVE
&&
1211 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1212 #if defined (NSUPDATE)
1213 ddns_removals (lease
);
1215 if (lease
-> on_expiry
) {
1216 execute_statements ((struct binding_value
**)0,
1217 (struct packet
*)0, lease
,
1218 (struct client_state
*)0,
1219 (struct option_state
*)0,
1220 (struct option_state
*)0, /* XXX */
1222 lease
-> on_expiry
);
1223 if (lease
-> on_expiry
)
1224 executable_statement_dereference
1225 (&lease
-> on_expiry
, MDL
);
1228 /* No sense releasing a lease after it's expired. */
1229 if (lease
-> on_release
)
1230 executable_statement_dereference (&lease
-> on_release
,
1232 /* Get rid of client-specific bindings that are only
1233 correct when the lease is active. */
1234 if (lease
-> billing_class
)
1235 unbill_class (lease
, lease
-> billing_class
);
1236 if (lease
-> agent_options
)
1237 option_chain_head_dereference (&lease
-> agent_options
,
1239 if (lease
-> client_hostname
) {
1240 dfree (lease
-> client_hostname
, MDL
);
1241 lease
-> client_hostname
= (char *)0;
1244 host_dereference (&lease
-> host
, MDL
);
1246 /* Send the expiry time to the peer. */
1247 lease
-> tstp
= lease
-> ends
;
1250 /* If the lease was active and is now released, do the release
1252 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1254 #if defined (FAILOVER_PROTOCOL)
1256 lease
-> binding_state
== FTS_RELEASED
&&
1257 (lease
-> next_binding_state
== FTS_FREE
||
1258 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1261 lease
-> binding_state
== FTS_ACTIVE
&&
1262 lease
-> next_binding_state
== FTS_RELEASED
))) {
1263 #if defined (NSUPDATE)
1264 ddns_removals (lease
);
1266 if (lease
-> on_release
) {
1267 execute_statements ((struct binding_value
**)0,
1268 (struct packet
*)0, lease
,
1269 (struct client_state
*)0,
1270 (struct option_state
*)0,
1271 (struct option_state
*)0, /* XXX */
1273 lease
-> on_release
);
1274 executable_statement_dereference (&lease
-> on_release
,
1278 /* A released lease can't expire. */
1279 if (lease
-> on_expiry
)
1280 executable_statement_dereference (&lease
-> on_expiry
,
1283 /* Get rid of client-specific bindings that are only
1284 correct when the lease is active. */
1285 if (lease
-> billing_class
)
1286 unbill_class (lease
, lease
-> billing_class
);
1287 if (lease
-> agent_options
)
1288 option_chain_head_dereference (&lease
-> agent_options
,
1290 if (lease
-> client_hostname
) {
1291 dfree (lease
-> client_hostname
, MDL
);
1292 lease
-> client_hostname
= (char *)0;
1295 host_dereference (&lease
-> host
, MDL
);
1297 /* Send the release time (should be == cur_time) to the
1299 lease
-> tstp
= lease
-> ends
;
1302 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1303 log_debug ("lease %s moves from %s to %s",
1304 piaddr (lease
-> ip_addr
),
1305 binding_state_print (lease
-> binding_state
),
1306 binding_state_print (lease
-> next_binding_state
));
1309 lease
-> binding_state
= lease
-> next_binding_state
;
1310 switch (lease
-> binding_state
) {
1312 #if defined (FAILOVER_PROTOCOL)
1313 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1314 lease
-> next_binding_state
= FTS_EXPIRED
;
1317 lease
-> next_binding_state
= FTS_FREE
;
1324 lease
-> next_binding_state
= FTS_FREE
;
1325 /* If we are not in partner_down, leases don't go from
1326 EXPIRED to FREE on a timeout - only on an update.
1327 If we're in partner_down, they expire at mclt past
1328 the time we entered partner_down. */
1329 if (lease
-> pool
-> failover_peer
&&
1330 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1332 (lease
-> pool
-> failover_peer
-> me
.stos
+
1333 lease
-> pool
-> failover_peer
-> mclt
);
1338 lease
-> next_binding_state
= lease
-> binding_state
;
1341 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1342 log_debug ("lease %s: next binding state %s",
1343 piaddr (lease
-> ip_addr
),
1344 binding_state_print (lease
-> next_binding_state
));
1349 /* Copy the contents of one lease into another, correctly maintaining
1350 reference counts. */
1351 int lease_copy (struct lease
**lp
,
1352 struct lease
*lease
, const char *file
, int line
)
1354 struct lease
*lt
= (struct lease
*)0;
1355 isc_result_t status
;
1357 status
= lease_allocate (<
, MDL
);
1358 if (status
!= ISC_R_SUCCESS
)
1361 lt
-> ip_addr
= lease
-> ip_addr
;
1362 lt
-> starts
= lease
-> starts
;
1363 lt
-> ends
= lease
-> ends
;
1364 lt
-> timestamp
= lease
-> timestamp
;
1365 lt
-> uid_len
= lease
-> uid_len
;
1366 lt
-> uid_max
= lease
-> uid_max
;
1367 if (lease
-> uid
== lease
-> uid_buf
) {
1368 lt
-> uid
= lt
-> uid_buf
;
1369 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1370 } else if (!lease
-> uid_max
) {
1371 lt
-> uid
= (unsigned char *)0;
1373 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1375 lease_dereference (<
, MDL
);
1378 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1380 if (lease
-> client_hostname
) {
1381 lt
-> client_hostname
=
1382 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1383 if (!lt
-> client_hostname
) {
1384 lease_dereference (<
, MDL
);
1387 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1390 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1391 if (lease
-> agent_options
)
1392 option_chain_head_reference (<
-> agent_options
,
1393 lease
-> agent_options
, MDL
);
1394 host_reference (<
-> host
, lease
-> host
, file
, line
);
1395 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1396 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1397 class_reference (<
-> billing_class
,
1398 lease
-> billing_class
, file
, line
);
1399 lt
-> hardware_addr
= lease
-> hardware_addr
;
1400 if (lease
-> on_expiry
)
1401 executable_statement_reference (<
-> on_expiry
,
1404 if (lease
-> on_commit
)
1405 executable_statement_reference (<
-> on_commit
,
1408 if (lease
-> on_release
)
1409 executable_statement_reference (<
-> on_release
,
1410 lease
-> on_release
,
1412 lt
->flags
= lease
->flags
;
1413 lt
->tstp
= lease
->tstp
;
1414 lt
->tsfp
= lease
->tsfp
;
1415 lt
->atsfp
= lease
->atsfp
;
1416 lt
->cltt
= lease
-> cltt
;
1417 lt
->binding_state
= lease
->binding_state
;
1418 lt
->next_binding_state
= lease
->next_binding_state
;
1419 status
= lease_reference(lp
, lt
, file
, line
);
1420 lease_dereference(<
, MDL
);
1421 return status
== ISC_R_SUCCESS
;
1424 /* Release the specified lease and re-hash it as appropriate. */
1425 void release_lease (lease
, packet
)
1426 struct lease
*lease
;
1427 struct packet
*packet
;
1429 /* If there are statements to execute when the lease is
1430 released, execute them. */
1431 #if defined (NSUPDATE)
1432 ddns_removals (lease
);
1434 if (lease
-> on_release
) {
1435 execute_statements ((struct binding_value
**)0,
1436 packet
, lease
, (struct client_state
*)0,
1438 (struct option_state
*)0, /* XXX */
1439 &lease
-> scope
, lease
-> on_release
);
1440 if (lease
-> on_release
)
1441 executable_statement_dereference (&lease
-> on_release
,
1445 /* We do either the on_release or the on_expiry events, but
1446 not both (it's possible that they could be the same,
1448 if (lease
-> on_expiry
)
1449 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1451 if (lease
-> binding_state
!= FTS_FREE
&&
1452 lease
-> binding_state
!= FTS_BACKUP
&&
1453 lease
-> binding_state
!= FTS_RELEASED
&&
1454 lease
-> binding_state
!= FTS_EXPIRED
&&
1455 lease
-> binding_state
!= FTS_RESET
) {
1456 if (lease
-> on_commit
)
1457 executable_statement_dereference (&lease
-> on_commit
,
1460 /* Blow away any bindings. */
1462 binding_scope_dereference (&lease
-> scope
, MDL
);
1463 lease
-> ends
= cur_time
;
1464 #if defined (FAILOVER_PROTOCOL)
1465 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1466 lease
-> next_binding_state
= FTS_RELEASED
;
1468 lease
-> next_binding_state
= FTS_FREE
;
1471 lease
-> next_binding_state
= FTS_FREE
;
1473 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1477 /* Abandon the specified lease (set its timeout to infinity and its
1478 particulars to zero, and re-hash it as appropriate. */
1480 void abandon_lease (lease
, message
)
1481 struct lease
*lease
;
1482 const char *message
;
1484 struct lease
*lt
= (struct lease
*)0;
1486 if (!lease_copy (<
, lease
, MDL
))
1490 binding_scope_dereference(<
->scope
, MDL
);
1492 lt
-> ends
= cur_time
; /* XXX */
1493 lt
-> next_binding_state
= FTS_ABANDONED
;
1495 log_error ("Abandoning IP address %s: %s",
1496 piaddr (lease
-> ip_addr
), message
);
1497 lt
-> hardware_addr
.hlen
= 0;
1498 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1499 dfree (lt
-> uid
, MDL
);
1500 lt
-> uid
= (unsigned char *)0;
1503 supersede_lease (lease
, lt
, 1, 1, 1);
1504 lease_dereference (<
, MDL
);
1507 /* Abandon the specified lease (set its timeout to infinity and its
1508 particulars to zero, and re-hash it as appropriate. */
1510 void dissociate_lease (lease
)
1511 struct lease
*lease
;
1513 struct lease
*lt
= (struct lease
*)0;
1515 if (!lease_copy (<
, lease
, MDL
))
1518 #if defined (FAILOVER_PROTOCOL)
1519 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1520 lt
-> next_binding_state
= FTS_RESET
;
1522 lt
-> next_binding_state
= FTS_FREE
;
1525 lt
-> next_binding_state
= FTS_FREE
;
1527 lt
-> ends
= cur_time
; /* XXX */
1528 lt
-> hardware_addr
.hlen
= 0;
1529 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1530 dfree (lt
-> uid
, MDL
);
1531 lt
-> uid
= (unsigned char *)0;
1534 supersede_lease (lease
, lt
, 1, 1, 1);
1535 lease_dereference (<
, MDL
);
1538 /* Timer called when a lease in a particular pool expires. */
1539 void pool_timer (vpool
)
1543 struct lease
*lt
= (struct lease
*)0;
1544 struct lease
*next
= (struct lease
*)0;
1545 struct lease
*lease
= (struct lease
*)0;
1546 struct lease
**lptr
[5];
1547 TIME next_expiry
= MAX_TIME
;
1550 pool
= (struct pool
*)vpool
;
1552 #define FREE_LEASES 0
1553 lptr
[FREE_LEASES
] = &pool
-> free
;
1554 #define ACTIVE_LEASES 1
1555 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1556 #define EXPIRED_LEASES 2
1557 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1558 #define ABANDONED_LEASES 3
1559 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1560 #define BACKUP_LEASES 4
1561 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1563 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1564 /* If there's nothing on the queue, skip it. */
1568 #if defined (FAILOVER_PROTOCOL)
1569 if (pool
-> failover_peer
&&
1570 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1571 /* The secondary can't remove a lease from the
1572 active state except in partner_down. */
1573 if (i
== ACTIVE_LEASES
&&
1574 pool
-> failover_peer
-> i_am
== secondary
)
1576 /* Leases in an expired state don't move to
1577 free because of a timeout unless we're in
1579 if (i
== EXPIRED_LEASES
)
1583 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1586 /* Remember the next lease in the list. */
1588 lease_dereference (&next
, MDL
);
1590 lease_reference (&next
, lease
-> next
, MDL
);
1592 /* If we've run out of things to expire on this list,
1594 if (lease
-> sort_time
> cur_time
) {
1595 if (lease
-> sort_time
< next_expiry
)
1596 next_expiry
= lease
-> sort_time
;
1600 /* If there is a pending state change, and
1601 this lease has gotten to the time when the
1602 state change should happen, just call
1603 supersede_lease on it to make the change
1605 if (lease
-> next_binding_state
!=
1606 lease
-> binding_state
)
1607 supersede_lease (lease
,
1608 (struct lease
*)0, 1, 1, 1);
1610 lease_dereference (&lease
, MDL
);
1612 lease_reference (&lease
, next
, MDL
);
1615 lease_dereference (&next
, MDL
);
1617 lease_dereference (&lease
, MDL
);
1619 if (next_expiry
!= MAX_TIME
) {
1620 pool
-> next_event_time
= next_expiry
;
1621 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1622 (tvref_t
)pool_reference
,
1623 (tvunref_t
)pool_dereference
);
1625 pool
-> next_event_time
= MIN_TIME
;
1629 /* Locate the lease associated with a given IP address... */
1631 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1632 const char *file
, int line
)
1634 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1635 addr
.iabuf
, addr
.len
, file
, line
);
1638 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1639 unsigned len
, const char *file
, int line
)
1643 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1646 int find_lease_by_hw_addr (struct lease
**lp
,
1647 const unsigned char *hwaddr
, unsigned hwlen
,
1648 const char *file
, int line
)
1652 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1653 hwaddr
, hwlen
, file
, line
);
1656 /* Add the specified lease to the uid hash. */
1658 void uid_hash_add (lease
)
1659 struct lease
*lease
;
1661 struct lease
*head
= (struct lease
*)0;
1662 struct lease
*next
= (struct lease
*)0;
1665 /* If it's not in the hash, just add it. */
1666 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1667 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1668 lease
-> uid_len
, lease
, MDL
);
1670 /* Otherwise, attach it to the end of the list. */
1671 while (head
-> n_uid
) {
1672 lease_reference (&next
, head
-> n_uid
, MDL
);
1673 lease_dereference (&head
, MDL
);
1674 lease_reference (&head
, next
, MDL
);
1675 lease_dereference (&next
, MDL
);
1677 lease_reference (&head
-> n_uid
, lease
, MDL
);
1678 lease_dereference (&head
, MDL
);
1682 /* Delete the specified lease from the uid hash. */
1684 void uid_hash_delete (lease
)
1685 struct lease
*lease
;
1687 struct lease
*head
= (struct lease
*)0;
1690 /* If it's not in the hash, we have no work to do. */
1691 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1693 lease_dereference (&lease
-> n_uid
, MDL
);
1697 /* If the lease we're freeing is at the head of the list,
1698 remove the hash table entry and add a new one with the
1699 next lease on the list (if there is one). */
1700 if (head
== lease
) {
1701 lease_hash_delete (lease_uid_hash
,
1702 lease
-> uid
, lease
-> uid_len
, MDL
);
1703 if (lease
-> n_uid
) {
1704 lease_hash_add (lease_uid_hash
,
1705 lease
-> n_uid
-> uid
,
1706 lease
-> n_uid
-> uid_len
,
1707 lease
-> n_uid
, MDL
);
1708 lease_dereference (&lease
-> n_uid
, MDL
);
1711 /* Otherwise, look for the lease in the list of leases
1712 attached to the hash table entry, and remove it if
1714 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1715 if (scan
-> n_uid
== lease
) {
1716 lease_dereference (&scan
-> n_uid
, MDL
);
1717 if (lease
-> n_uid
) {
1718 lease_reference (&scan
-> n_uid
,
1719 lease
-> n_uid
, MDL
);
1720 lease_dereference (&lease
-> n_uid
,
1727 lease_dereference (&head
, MDL
);
1730 /* Add the specified lease to the hardware address hash. */
1732 void hw_hash_add (lease
)
1733 struct lease
*lease
;
1735 struct lease
*head
= (struct lease
*)0;
1736 struct lease
*next
= (struct lease
*)0;
1738 /* If it's not in the hash, just add it. */
1739 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1740 lease
-> hardware_addr
.hlen
, MDL
))
1741 lease_hash_add (lease_hw_addr_hash
,
1742 lease
-> hardware_addr
.hbuf
,
1743 lease
-> hardware_addr
.hlen
,
1746 /* Otherwise, attach it to the end of the list. */
1747 while (head
-> n_hw
) {
1748 lease_reference (&next
, head
-> n_hw
, MDL
);
1749 lease_dereference (&head
, MDL
);
1750 lease_reference (&head
, next
, MDL
);
1751 lease_dereference (&next
, MDL
);
1754 lease_reference (&head
-> n_hw
, lease
, MDL
);
1755 lease_dereference (&head
, MDL
);
1759 /* Delete the specified lease from the hardware address hash. */
1761 void hw_hash_delete (lease
)
1762 struct lease
*lease
;
1764 struct lease
*head
= (struct lease
*)0;
1765 struct lease
*next
= (struct lease
*)0;
1767 /* If it's not in the hash, we have no work to do. */
1768 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1769 lease
-> hardware_addr
.hlen
, MDL
)) {
1771 lease_dereference (&lease
-> n_hw
, MDL
);
1775 /* If the lease we're freeing is at the head of the list,
1776 remove the hash table entry and add a new one with the
1777 next lease on the list (if there is one). */
1778 if (head
== lease
) {
1779 lease_hash_delete (lease_hw_addr_hash
,
1780 lease
-> hardware_addr
.hbuf
,
1781 lease
-> hardware_addr
.hlen
, MDL
);
1782 if (lease
-> n_hw
) {
1783 lease_hash_add (lease_hw_addr_hash
,
1784 lease
-> n_hw
-> hardware_addr
.hbuf
,
1785 lease
-> n_hw
-> hardware_addr
.hlen
,
1786 lease
-> n_hw
, MDL
);
1787 lease_dereference (&lease
-> n_hw
, MDL
);
1790 /* Otherwise, look for the lease in the list of leases
1791 attached to the hash table entry, and remove it if
1793 while (head
-> n_hw
) {
1794 if (head
-> n_hw
== lease
) {
1795 lease_dereference (&head
-> n_hw
, MDL
);
1796 if (lease
-> n_hw
) {
1797 lease_reference (&head
-> n_hw
,
1798 lease
-> n_hw
, MDL
);
1799 lease_dereference (&lease
-> n_hw
,
1804 lease_reference (&next
, head
-> n_hw
, MDL
);
1805 lease_dereference (&head
, MDL
);
1806 lease_reference (&head
, next
, MDL
);
1807 lease_dereference (&next
, MDL
);
1811 lease_dereference (&head
, MDL
);
1814 /* Write all interesting leases to permanent storage. */
1819 struct shared_network
*s
;
1821 struct host_decl
*hp
;
1822 struct group_object
*gp
;
1823 struct hash_bucket
*hb
;
1825 struct collection
*colp
;
1828 struct lease
**lptr
[5];
1830 /* write all the dynamically-created class declarations. */
1831 if (collections
->classes
) {
1832 numclasseswritten
= 0;
1833 for (colp
= collections
; colp
; colp
= colp
->next
) {
1834 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
1835 write_named_billing_class(cp
->name
,
1840 /* XXXJAB this number doesn't include subclasses... */
1841 log_info ("Wrote %d class decls to leases file.",
1846 /* Write all the dynamically-created group declarations. */
1847 if (group_name_hash
) {
1849 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1850 for (hb
= group_name_hash
-> buckets
[i
];
1851 hb
; hb
= hb
-> next
) {
1852 gp
= (struct group_object
*)hb
-> value
;
1853 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1854 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1855 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1856 if (!write_group (gp
))
1862 log_info ("Wrote %d group decls to leases file.", num_written
);
1865 /* Write all the deleted host declarations. */
1866 if (host_name_hash
) {
1868 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1869 for (hb
= host_name_hash
-> buckets
[i
];
1870 hb
; hb
= hb
-> next
) {
1871 hp
= (struct host_decl
*)hb
-> value
;
1872 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1873 (hp
-> flags
& HOST_DECL_DELETED
))) {
1874 if (!write_host (hp
))
1880 log_info ("Wrote %d deleted host decls to leases file.",
1884 /* Write all the new, dynamic host declarations. */
1885 if (host_name_hash
) {
1887 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1888 for (hb
= host_name_hash
-> buckets
[i
];
1889 hb
; hb
= hb
-> next
) {
1890 hp
= (struct host_decl
*)hb
-> value
;
1891 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1892 if (!write_host (hp
))
1897 log_info ("Wrote %d new dynamic host decls to leases file.",
1901 #if defined (FAILOVER_PROTOCOL)
1902 /* Write all the failover states. */
1903 if (!dhcp_failover_write_all_states ())
1907 /* Write all the leases. */
1909 for (s
= shared_networks
; s
; s
= s
-> next
) {
1910 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1911 lptr
[FREE_LEASES
] = &p
-> free
;
1912 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1913 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1914 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1915 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1917 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1918 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1919 #if !defined (DEBUG_DUMP_ALL_LEASES)
1920 if (l
-> hardware_addr
.hlen
||
1922 (l
-> binding_state
!= FTS_FREE
))
1925 if (!write_lease (l
))
1933 log_info ("Wrote %d leases to leases file.", num_written
);
1934 if (!commit_leases ())
1939 /* In addition to placing this lease upon a lease queue depending on its
1940 * state, it also keeps track of the number of FREE and BACKUP leases in
1941 * existence, and sets the sort_time on the lease.
1943 * Sort_time is used in pool_timer() to determine when the lease will
1944 * bubble to the top of the list and be supersede_lease()'d into its next
1945 * state (possibly, if all goes well). Example, ACTIVE leases move to
1946 * EXPIRED state when the 'ends' value is reached, so that is its sort
1947 * time. Most queues are sorted by 'ends', since it is generally best
1948 * practice to re-use the oldest lease, to reduce address collision
1951 int lease_enqueue (struct lease
*comp
)
1953 struct lease
**lq
, *prev
, *lp
;
1955 /* No queue to put it on? */
1959 /* Figure out which queue it's going to. */
1960 switch (comp
-> binding_state
) {
1962 lq
= &comp
-> pool
-> free
;
1963 comp
-> pool
-> free_leases
++;
1964 comp
-> sort_time
= comp
-> ends
;
1968 lq
= &comp
-> pool
-> active
;
1969 comp
-> sort_time
= comp
-> ends
;
1975 lq
= &comp
-> pool
-> expired
;
1976 #if defined(FAILOVER_PROTOCOL)
1977 /* In partner_down, tsfp is the time at which the lease
1978 * may be reallocated (stos+mclt). We can do that with
1979 * lease_mine_to_reallocate() anywhere between tsfp and
1980 * ends. But we prefer to wait until ends before doing it
1981 * automatically (choose the greater of the two). Note
1982 * that 'ends' is usually a historic timestamp in the
1983 * case of expired leases, is really only in the future
1984 * on released leases, and if we know a lease to be released
1985 * the peer might still know it to be active...in which case
1986 * it's possible the peer has renewed this lease, so avoid
1989 if (comp
->pool
->failover_peer
&&
1990 comp
->pool
->failover_peer
->me
.state
== partner_down
)
1991 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
1992 comp
->tsfp
: comp
->ends
;
1995 comp
->sort_time
= comp
->ends
;
2000 lq
= &comp
-> pool
-> abandoned
;
2001 comp
-> sort_time
= comp
-> ends
;
2005 lq
= &comp
-> pool
-> backup
;
2006 comp
-> pool
-> backup_leases
++;
2007 comp
-> sort_time
= comp
-> ends
;
2011 log_error ("Lease with bogus binding state: %d",
2012 comp
-> binding_state
);
2013 #if defined (BINDING_STATE_DEBUG)
2019 /* Insertion sort the lease onto the appropriate queue. */
2020 prev
= (struct lease
*)0;
2021 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
2022 if (lp
-> sort_time
>= comp
-> sort_time
)
2028 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
2029 lease_dereference (&prev
-> next
, MDL
);
2031 lease_reference (&prev
-> next
, comp
, MDL
);
2034 lease_reference (&comp
-> next
, *lq
, MDL
);
2035 lease_dereference (lq
, MDL
);
2037 lease_reference (lq
, comp
, MDL
);
2042 /* For a given lease, sort it onto the right list in its pool and put it
2043 in each appropriate hash, understanding that it's already by definition
2044 in lease_ip_addr_hash. */
2047 lease_instantiate(const unsigned char *val
, unsigned len
, void *object
)
2049 struct lease
*lease
= object
;
2050 struct class *class;
2051 /* XXX If the lease doesn't have a pool at this point, it's an
2052 XXX orphan, which we *should* keep around until it expires,
2053 XXX but which right now we just forget. */
2054 if (!lease
-> pool
) {
2055 lease_hash_delete (lease_ip_addr_hash
,
2056 lease
-> ip_addr
.iabuf
,
2057 lease
-> ip_addr
.len
, MDL
);
2058 return ISC_R_SUCCESS
;
2061 /* Put the lease on the right queue. Failure to queue is probably
2062 * due to a bogus binding state. In such a case, we claim success,
2063 * so that later leases in a hash_foreach are processed, but we
2064 * return early as we really don't want hw address hash entries or
2065 * other cruft to surround such a bogus entry.
2067 if (!lease_enqueue(lease
))
2068 return ISC_R_SUCCESS
;
2070 /* Record the lease in the uid hash if possible. */
2072 uid_hash_add (lease
);
2075 /* Record it in the hardware address hash if possible. */
2076 if (lease
-> hardware_addr
.hlen
) {
2077 hw_hash_add (lease
);
2080 /* If the lease has a billing class, set up the billing. */
2081 if (lease
-> billing_class
) {
2082 class = (struct class *)0;
2083 class_reference (&class, lease
-> billing_class
, MDL
);
2084 class_dereference (&lease
-> billing_class
, MDL
);
2085 /* If the lease is available for allocation, the billing
2086 is invalid, so we don't keep it. */
2087 if (lease
-> binding_state
== FTS_ACTIVE
||
2088 lease
-> binding_state
== FTS_EXPIRED
||
2089 lease
-> binding_state
== FTS_RELEASED
||
2090 lease
-> binding_state
== FTS_RESET
)
2091 bill_class (lease
, class);
2092 class_dereference (&class, MDL
);
2094 return ISC_R_SUCCESS
;
2097 /* Run expiry events on every pool. This is called on startup so that
2098 any expiry events that occurred after the server stopped and before it
2099 was restarted can be run. At the same time, if failover support is
2100 compiled in, we compute the balance of leases for the pool. */
2102 void expire_all_pools ()
2104 struct shared_network
*s
;
2106 struct hash_bucket
*hb
;
2109 struct lease
**lptr
[5];
2111 /* First, go over the hash list and actually put all the leases
2112 on the appropriate lists. */
2113 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
2115 /* Loop through each pool in each shared network and call the
2116 expiry routine on the pool. */
2117 for (s
= shared_networks
; s
; s
= s
-> next
) {
2118 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2121 p
-> lease_count
= 0;
2122 p
-> free_leases
= 0;
2123 p
-> backup_leases
= 0;
2125 lptr
[FREE_LEASES
] = &p
-> free
;
2126 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2127 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2128 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2129 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2131 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2132 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2134 if (l
-> ends
<= cur_time
) {
2135 if (l
-> binding_state
== FTS_FREE
)
2137 else if (l
-> binding_state
== FTS_BACKUP
)
2138 p
-> backup_leases
++;
2140 #if defined (FAILOVER_PROTOCOL)
2141 if (p
-> failover_peer
&&
2142 l
-> tstp
> l
-> atsfp
&&
2143 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2144 l
-> desired_binding_state
= l
-> binding_state
;
2145 dhcp_failover_queue_update (l
, 1);
2154 void dump_subnets ()
2157 struct shared_network
*s
;
2160 struct lease
**lptr
[5];
2163 log_info ("Subnets:");
2164 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2165 log_debug (" Subnet %s", piaddr (n
-> net
));
2166 log_debug (" netmask %s",
2167 piaddr (n
-> netmask
));
2169 log_info ("Shared networks:");
2170 for (s
= shared_networks
; s
; s
= s
-> next
) {
2171 log_info (" %s", s
-> name
);
2172 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2173 lptr
[FREE_LEASES
] = &p
-> free
;
2174 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2175 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2176 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2177 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2179 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
2180 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2188 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
, lease_hash_t
,
2189 lease_reference
, lease_dereference
)
2190 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2191 host_reference
, host_dereference
)
2192 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2193 class_reference
, class_dereference
)
2195 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2196 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2197 extern struct hash_table
*dns_zone_hash
;
2198 extern struct interface_info
**interface_vector
;
2199 extern int interface_count
;
2200 dhcp_control_object_t
*dhcp_control_object
;
2201 extern struct hash_table
*auth_key_hash
;
2202 struct hash_table
*universe_hash
;
2203 struct universe
**universes
;
2204 int universe_count
, universe_max
;
2209 #if defined (COMPACT_LEASES)
2210 extern struct lease
*lease_hunks
;
2213 void free_everything ()
2215 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2216 struct shared_network
*nc
= (struct shared_network
*)0,
2217 *nn
= (struct shared_network
*)0;
2218 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2219 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2220 struct interface_info
*ic
= (struct interface_info
*)0,
2221 *in
= (struct interface_info
*)0;
2222 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2223 struct collection
*lp
;
2224 void *st
= (shared_networks
2225 ? (shared_networks
-> next
2226 ? shared_networks
-> next
-> next
: 0) : 0);
2230 /* Get rid of all the hash tables. */
2231 if (host_hw_addr_hash
)
2232 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2233 host_hw_addr_hash
= 0;
2235 host_free_hash_table (&host_uid_hash
, MDL
);
2238 lease_free_hash_table (&lease_uid_hash
, MDL
);
2240 if (lease_ip_addr_hash
)
2241 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2242 lease_ip_addr_hash
= 0;
2243 if (lease_hw_addr_hash
)
2244 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2245 lease_hw_addr_hash
= 0;
2247 host_free_hash_table (&host_name_hash
, MDL
);
2250 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2254 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2258 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2261 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2262 if (lp
-> classes
) {
2263 class_reference (&cn
, lp
-> classes
, MDL
);
2266 class_reference (&cc
, cn
, MDL
);
2267 class_dereference (&cn
, MDL
);
2270 class_reference (&cn
, cc
-> nic
, MDL
);
2271 class_dereference (&cc
-> nic
, MDL
);
2273 group_dereference (&cc
-> group
, MDL
);
2275 class_free_hash_table (&cc
-> hash
, MDL
);
2276 cc
-> hash
= (struct hash_table
*)0;
2278 class_dereference (&cc
, MDL
);
2280 class_dereference (&lp
-> classes
, MDL
);
2284 if (interface_vector
) {
2285 for (i
= 0; i
< interface_count
; i
++) {
2286 if (interface_vector
[i
])
2287 interface_dereference (&interface_vector
[i
], MDL
);
2289 dfree (interface_vector
, MDL
);
2290 interface_vector
= 0;
2294 interface_reference (&in
, interfaces
, MDL
);
2297 interface_reference (&ic
, in
, MDL
);
2298 interface_dereference (&in
, MDL
);
2301 interface_reference (&in
, ic
-> next
, MDL
);
2302 interface_dereference (&ic
-> next
, MDL
);
2304 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2305 if (ic
-> shared_network
) {
2306 if (ic
-> shared_network
-> interface
)
2307 interface_dereference
2308 (&ic
-> shared_network
-> interface
, MDL
);
2309 shared_network_dereference (&ic
-> shared_network
, MDL
);
2311 interface_dereference (&ic
, MDL
);
2313 interface_dereference (&interfaces
, MDL
);
2316 /* Subnets are complicated because of the extra links. */
2318 subnet_reference (&sn
, subnets
, MDL
);
2321 subnet_reference (&sc
, sn
, MDL
);
2322 subnet_dereference (&sn
, MDL
);
2324 if (sc
-> next_subnet
) {
2325 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2326 subnet_dereference (&sc
-> next_subnet
, MDL
);
2328 if (sc
-> next_sibling
)
2329 subnet_dereference (&sc
-> next_sibling
, MDL
);
2330 if (sc
-> shared_network
)
2331 shared_network_dereference (&sc
-> shared_network
, MDL
);
2332 group_dereference (&sc
-> group
, MDL
);
2333 if (sc
-> interface
)
2334 interface_dereference (&sc
-> interface
, MDL
);
2335 subnet_dereference (&sc
, MDL
);
2337 subnet_dereference (&subnets
, MDL
);
2340 /* So are shared networks. */
2341 if (shared_networks
) {
2342 shared_network_reference (&nn
, shared_networks
, MDL
);
2345 shared_network_reference (&nc
, nn
, MDL
);
2346 shared_network_dereference (&nn
, MDL
);
2349 shared_network_reference (&nn
, nc
-> next
, MDL
);
2350 shared_network_dereference (&nc
-> next
, MDL
);
2355 pool_reference (&pn
, nc
-> pools
, MDL
);
2357 struct lease
**lptr
[5];
2360 pool_reference (&pc
, pn
, MDL
);
2361 pool_dereference (&pn
, MDL
);
2364 pool_reference (&pn
, pc
-> next
, MDL
);
2365 pool_dereference (&pc
-> next
, MDL
);
2368 lptr
[FREE_LEASES
] = &pc
-> free
;
2369 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2370 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2371 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2372 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2374 /* As (sigh) are leases. */
2375 for (i
= 0; i
< 5; i
++) {
2377 lease_reference (&ln
, *lptr
[i
], MDL
);
2380 lease_reference (&lc
, ln
, MDL
);
2381 lease_dereference (&ln
, MDL
);
2384 lease_reference (&ln
, lc
-> next
, MDL
);
2385 lease_dereference (&lc
-> next
, MDL
);
2387 if (lc
-> billing_class
)
2388 class_dereference (&lc
-> billing_class
,
2391 free_lease_state (lc
-> state
, MDL
);
2392 lc
-> state
= (struct lease_state
*)0;
2394 lease_dereference (&lc
-> n_hw
, MDL
);
2396 lease_dereference (&lc
-> n_uid
, MDL
);
2397 lease_dereference (&lc
, MDL
);
2399 lease_dereference (lptr
[i
], MDL
);
2403 group_dereference (&pc
-> group
, MDL
);
2404 if (pc
-> shared_network
)
2405 shared_network_dereference (&pc
-> shared_network
,
2407 pool_dereference (&pc
, MDL
);
2409 pool_dereference (&nc
-> pools
, MDL
);
2411 /* Because of a circular reference, we need to nuke this
2413 group_dereference (&nc
-> group
, MDL
);
2414 shared_network_dereference (&nc
, MDL
);
2416 shared_network_dereference (&shared_networks
, MDL
);
2419 cancel_all_timeouts ();
2420 relinquish_timeouts ();
2422 group_dereference (&root_group
, MDL
);
2423 executable_statement_dereference (&default_classification_rules
, MDL
);
2425 shutdown_state
= shutdown_drop_omapi_connections
;
2426 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2427 shutdown_state
= shutdown_listeners
;
2428 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2429 shutdown_state
= shutdown_dhcp
;
2430 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2432 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2434 universe_free_hash_table (&universe_hash
, MDL
);
2435 for (i
= 0; i
< universe_count
; i
++) {
2440 if (universes
[i
]) {
2441 if (universes
[i
] -> hash
)
2442 option_free_hash_table (&universes
[i
] -> hash
,
2445 if (universes
[i
] -> name
> (char *)&end
) {
2446 foo
.c
= universes
[i
] -> name
;
2449 if (universes
[i
] > (struct universe
*)&end
)
2450 dfree (universes
[i
], MDL
);
2454 dfree (universes
, MDL
);
2456 relinquish_free_lease_states ();
2457 relinquish_free_pairs ();
2458 relinquish_free_expressions ();
2459 relinquish_free_binding_values ();
2460 relinquish_free_option_caches ();
2461 relinquish_free_packets ();
2462 relinquish_lease_hunks ();
2463 relinquish_hash_bucket_hunks ();
2464 omapi_type_relinquish ();
2466 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */