3 Server-specific in-memory database support. */
6 * Copyright (c) 2011-2015 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2004-2009 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1996-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
31 #include "omapip/hash.h"
33 struct subnet
*subnets
;
34 struct shared_network
*shared_networks
;
35 host_hash_t
*host_hw_addr_hash
;
36 host_hash_t
*host_uid_hash
;
37 host_hash_t
*host_name_hash
;
38 lease_id_hash_t
*lease_uid_hash
;
39 lease_ip_hash_t
*lease_ip_addr_hash
;
40 lease_id_hash_t
*lease_hw_addr_hash
;
43 * We allow users to specify any option as a host identifier.
45 * Any host is uniquely identified by the combination of
46 * option type & option data.
48 * We expect people will only use a few types of options as host
49 * identifier. Because of this, we store a list with an entry for
50 * each option type. Each of these has a hash table, which contains
51 * hash of the option data.
53 * For v6 we also include a relay count - this specifies which
54 * relay to check for the requested option. As each different
55 * value of relays creates a new instance admins should use the
56 * same value across each option for all host-identifers.
57 * A value of 0 indicates that we aren't doing relay options
58 * and should simply look in the current option list.
60 typedef struct host_id_info
{
61 struct option
*option
;
62 host_hash_t
*values_hash
;
64 struct host_id_info
*next
;
67 static host_id_info_t
*host_id_info
= NULL
;
69 int numclasseswritten
;
71 omapi_object_type_t
*dhcp_type_host
;
73 isc_result_t
enter_class(cd
, dynamicp
, commit
)
78 if (!collections
-> classes
) {
79 /* A subclass with no parent is invalid. */
81 return DHCP_R_INVALIDARG
;
83 class_reference (&collections
-> classes
, cd
, MDL
);
84 } else if (cd
->name
!= NULL
) { /* regular class */
87 if (find_class(&c
, cd
->name
, MDL
) != ISC_R_NOTFOUND
) {
88 class_dereference(&c
, MDL
);
93 for (c
= collections
-> classes
;
94 c
-> nic
; c
= c
-> nic
)
96 class_reference (&c
-> nic
, cd
, MDL
);
99 if (dynamicp
&& commit
) {
100 const char *name
= cd
->name
;
103 name
= cd
->superclass
->name
;
106 write_named_billing_class ((const unsigned char *)name
, 0, cd
);
107 if (!commit_leases ())
108 return ISC_R_IOERROR
;
111 return ISC_R_SUCCESS
;
115 /* Variable to check if we're starting the server. The server will init as
116 * starting - but just to be safe start out as false to avoid triggering new
118 * XXX: There is actually a server_startup state...which is never entered...
122 static int server_starting
= 0;
124 static int find_uid_statement (struct executable_statement
*esp
,
127 struct executable_statement
**evp
= vp
;
129 if (esp
-> op
== supersede_option_statement
&&
130 esp
-> data
.option
&&
131 (esp
-> data
.option
-> option
-> universe
==
133 (esp
-> data
.option
-> option
-> code
==
134 DHO_DHCP_CLIENT_IDENTIFIER
)) {
136 log_error ("dhcp client identifier may not be %s",
137 "specified conditionally.");
138 } else if (!(*evp
)) {
139 executable_statement_reference (evp
, esp
, MDL
);
142 log_error ("only one dhcp client identifier may be %s",
150 static host_id_info_t
*
151 find_host_id_info(unsigned int option_code
, int relays
) {
154 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
155 if ((p
->option
->code
== option_code
) &&
156 (p
->relays
== relays
)) {
166 print_host(const void *name
, unsigned len
, void *value
) {
168 printf("--------------\n");
169 printf("name:'%s'\n", print_hex_1(len
, name
, 60));
170 printf("len:%d\n", len
);
171 h
= (struct host_decl
*)value
;
172 printf("host @%p is '%s'\n", h
, h
->name
);
173 return ISC_R_SUCCESS
;
177 hash_print_hosts(struct hash_table
*h
) {
178 hash_foreach(h
, print_host
);
179 printf("--------------\n");
184 change_host_uid(struct host_decl
*host
, const char *uid
, int len
) {
185 /* XXX: should consolidate this type of code throughout */
186 if (host_uid_hash
== NULL
) {
187 if (!host_new_hash(&host_uid_hash
, HOST_HASH_SIZE
, MDL
)) {
188 log_fatal("Can't allocate host/uid hash");
193 * Remove the old entry, if one exists.
195 if (host
->client_identifier
.data
!= NULL
) {
196 host_hash_delete(host_uid_hash
,
197 host
->client_identifier
.data
,
198 host
->client_identifier
.len
,
200 data_string_forget(&host
->client_identifier
, MDL
);
206 memset(&host
->client_identifier
, 0, sizeof(host
->client_identifier
));
207 host
->client_identifier
.len
= len
;
208 if (!buffer_allocate(&host
->client_identifier
.buffer
, len
, MDL
)) {
209 log_fatal("Can't allocate uid buffer");
211 host
->client_identifier
.data
= host
->client_identifier
.buffer
->data
;
212 memcpy((char *)host
->client_identifier
.data
, uid
, len
);
217 host_hash_add(host_uid_hash
, host
->client_identifier
.data
,
218 host
->client_identifier
.len
, host
, MDL
);
221 isc_result_t
enter_host (hd
, dynamicp
, commit
)
222 struct host_decl
*hd
;
226 struct host_decl
*hp
= (struct host_decl
*)0;
227 struct host_decl
*np
= (struct host_decl
*)0;
228 struct executable_statement
*esp
;
229 host_id_info_t
*h_id_info
;
231 if (!host_name_hash
) {
232 if (!host_new_hash(&host_name_hash
, HOST_HASH_SIZE
, MDL
))
233 log_fatal ("Can't allocate host name hash");
234 host_hash_add (host_name_hash
,
235 (unsigned char *)hd
-> name
,
236 strlen (hd
-> name
), hd
, MDL
);
238 host_hash_lookup (&hp
, host_name_hash
,
239 (unsigned char *)hd
-> name
,
240 strlen (hd
-> name
), MDL
);
242 /* If it's deleted, we can supersede it. */
243 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
244 host_hash_delete (host_name_hash
,
245 (unsigned char *)hd
-> name
,
246 strlen (hd
-> name
), MDL
);
247 /* If the old entry wasn't dynamic, then we
248 always have to keep the deletion. */
249 if (hp
-> flags
& HOST_DECL_STATIC
) {
250 hd
-> flags
|= HOST_DECL_STATIC
;
252 host_dereference (&hp
, MDL
);
255 /* If we are updating an existing host declaration, we
256 can just delete it and add it again. */
257 if (hp
&& hp
== hd
) {
258 host_dereference (&hp
, MDL
);
260 if (!write_host (hd
))
261 return ISC_R_IOERROR
;
262 hd
-> flags
&= ~HOST_DECL_DELETED
;
265 /* If there isn't already a host decl matching this
266 address, add it to the hash table. */
268 host_hash_add (host_name_hash
,
269 (unsigned char *)hd
-> name
,
270 strlen (hd
-> name
), hd
, MDL
);
272 /* XXX actually, we have to delete the old one
273 XXX carefully and replace it. Not done yet. */
274 host_dereference (&hp
, MDL
);
280 host_dereference (&hd
-> n_ipaddr
, MDL
);
283 hd
-> type
= dhcp_type_host
;
285 if (hd
-> interface
.hlen
) {
286 if (!host_hw_addr_hash
) {
287 if (!host_new_hash(&host_hw_addr_hash
,
288 HOST_HASH_SIZE
, MDL
))
289 log_fatal ("Can't allocate host/hw hash");
291 /* If there isn't already a host decl matching this
292 address, add it to the hash table. */
293 host_hash_lookup (&hp
, host_hw_addr_hash
,
294 hd
-> interface
.hbuf
,
295 hd
-> interface
.hlen
, MDL
);
298 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
299 hd
-> interface
.hlen
, hd
, MDL
);
301 /* If there was already a host declaration for
302 this hardware address, add this one to the
304 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
306 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
307 host_dereference (&hp
, MDL
);
311 /* See if there's a statement that sets the client identifier.
312 This is a kludge - the client identifier really shouldn't be
313 set with an executable statement. */
315 if (executable_statement_foreach (hd
->group
->statements
,
316 find_uid_statement
, &esp
, 0)) {
317 (void) evaluate_option_cache (&hd
->client_identifier
,
318 NULL
, NULL
, NULL
, NULL
, NULL
,
320 esp
->data
.option
, MDL
);
323 /* If we got a client identifier, hash this entry by
324 client identifier. */
325 if (hd
-> client_identifier
.len
) {
326 /* If there's no uid hash, make one; otherwise, see if
327 there's already an entry in the hash for this host. */
328 if (!host_uid_hash
) {
329 if (!host_new_hash(&host_uid_hash
,
330 HOST_HASH_SIZE
, MDL
))
331 log_fatal ("Can't allocate host/uid hash");
333 host_hash_add (host_uid_hash
,
334 hd
-> client_identifier
.data
,
335 hd
-> client_identifier
.len
,
338 /* If there's already a host declaration for this
339 client identifier, add this one to the end of the
340 list. Otherwise, add it to the hash table. */
341 if (host_hash_lookup (&hp
, host_uid_hash
,
342 hd
-> client_identifier
.data
,
343 hd
-> client_identifier
.len
,
345 /* Don't link it in twice... */
347 for (np
= hp
; np
-> n_ipaddr
;
348 np
= np
-> n_ipaddr
) {
353 host_reference (&np
-> n_ipaddr
,
356 host_dereference (&hp
, MDL
);
358 host_hash_add (host_uid_hash
,
359 hd
-> client_identifier
.data
,
360 hd
-> client_identifier
.len
,
368 * If we use an option as our host identifier, record it here.
370 if (hd
->host_id_option
!= NULL
) {
372 * Look for the host identifier information for this option,
373 * and create a new entry if there is none.
375 h_id_info
= find_host_id_info(hd
->host_id_option
->code
,
377 if (h_id_info
== NULL
) {
378 h_id_info
= dmalloc(sizeof(*h_id_info
), MDL
);
379 if (h_id_info
== NULL
) {
380 log_fatal("No memory for host-identifier "
381 "option information.");
383 option_reference(&h_id_info
->option
,
384 hd
->host_id_option
, MDL
);
385 if (!host_new_hash(&h_id_info
->values_hash
,
386 HOST_HASH_SIZE
, MDL
)) {
387 log_fatal("No memory for host-identifier "
390 h_id_info
->relays
= hd
->relays
;
391 h_id_info
->next
= host_id_info
;
392 host_id_info
= h_id_info
;
395 if (host_hash_lookup(&hp
, h_id_info
->values_hash
,
396 hd
->host_id
.data
, hd
->host_id
.len
, MDL
)) {
398 * If this option is already present, then add
399 * this host to the list in n_ipaddr, unless
400 * we have already done so previously.
402 * XXXSK: This seems scary to me, but I don't
403 * fully understand how these are used.
404 * Shouldn't there be multiple lists, or
405 * maybe we should just forbid duplicates?
409 while (np
->n_ipaddr
!= NULL
) {
413 host_reference(&np
->n_ipaddr
, hd
, MDL
);
416 host_dereference(&hp
, MDL
);
418 host_hash_add(h_id_info
->values_hash
,
425 if (dynamicp
&& commit
) {
426 if (!write_host (hd
))
427 return ISC_R_IOERROR
;
428 if (!commit_leases ())
429 return ISC_R_IOERROR
;
432 return ISC_R_SUCCESS
;
436 isc_result_t
delete_class (cp
, commit
)
440 cp
->flags
|= CLASS_DECL_DELETED
;
442 /* do the write first as we won't be leaving it in any data
443 structures, unlike the host objects */
446 write_named_billing_class ((unsigned char *)cp
->name
, 0, cp
);
447 if (!commit_leases ())
448 return ISC_R_IOERROR
;
452 * If this is a subclass remove it from the class's hash table
454 if (cp
->superclass
) {
455 class_hash_delete(cp
->superclass
->hash
,
456 (const char *)cp
->hash_string
.data
,
461 /* remove from collections */
464 return ISC_R_SUCCESS
;
468 isc_result_t
delete_host (hd
, commit
)
469 struct host_decl
*hd
;
472 struct host_decl
*hp
= (struct host_decl
*)0;
473 struct host_decl
*np
= (struct host_decl
*)0;
474 struct host_decl
*foo
;
475 int hw_head
= 0, uid_head
= 1;
477 /* Don't need to do it twice. */
478 if (hd
-> flags
& HOST_DECL_DELETED
)
479 return ISC_R_SUCCESS
;
481 /* But we do need to do it once! :') */
482 hd
-> flags
|= HOST_DECL_DELETED
;
484 if (hd
-> interface
.hlen
) {
485 if (host_hw_addr_hash
) {
486 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
487 hd
-> interface
.hbuf
,
488 hd
-> interface
.hlen
, MDL
)) {
490 host_hash_delete (host_hw_addr_hash
,
491 hd
-> interface
.hbuf
,
492 hd
-> interface
.hlen
, MDL
);
495 np
= (struct host_decl
*)0;
496 foo
= (struct host_decl
*)0;
497 host_reference (&foo
, hp
, MDL
);
502 host_dereference (&np
, MDL
);
503 host_reference (&np
, foo
, MDL
);
504 host_dereference (&foo
, MDL
);
506 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
510 host_dereference (&np
-> n_ipaddr
, MDL
);
512 host_reference (&np
-> n_ipaddr
,
513 hd
-> n_ipaddr
, MDL
);
514 host_dereference (&foo
, MDL
);
517 host_dereference (&np
, MDL
);
519 host_dereference (&hp
, MDL
);
524 /* If we got a client identifier, hash this entry by
525 client identifier. */
526 if (hd
-> client_identifier
.len
) {
528 if (host_hash_lookup (&hp
, host_uid_hash
,
529 hd
-> client_identifier
.data
,
530 hd
-> client_identifier
.len
, MDL
)) {
532 host_hash_delete (host_uid_hash
,
533 hd
-> client_identifier
.data
,
534 hd
-> client_identifier
.len
, MDL
);
537 np
= (struct host_decl
*)0;
538 foo
= (struct host_decl
*)0;
539 host_reference (&foo
, hp
, MDL
);
544 host_dereference (&np
, MDL
);
545 host_reference (&np
, foo
, MDL
);
546 host_dereference (&foo
, MDL
);
548 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
552 host_dereference (&np
-> n_ipaddr
, MDL
);
554 host_reference (&np
-> n_ipaddr
,
555 hd
-> n_ipaddr
, MDL
);
556 host_dereference (&foo
, MDL
);
559 host_dereference (&np
, MDL
);
561 host_dereference (&hp
, MDL
);
566 if (hd
->host_id_option
!= NULL
) {
567 option_dereference(&hd
->host_id_option
, MDL
);
568 data_string_forget(&hd
->host_id
, MDL
);
571 if (hd
-> n_ipaddr
) {
572 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
575 hd
-> n_ipaddr
-> client_identifier
.data
,
576 hd
-> n_ipaddr
-> client_identifier
.len
,
577 hd
-> n_ipaddr
, MDL
);
579 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
580 host_hash_add (host_hw_addr_hash
,
581 hd
-> n_ipaddr
-> interface
.hbuf
,
582 hd
-> n_ipaddr
-> interface
.hlen
,
583 hd
-> n_ipaddr
, MDL
);
585 host_dereference (&hd
-> n_ipaddr
, MDL
);
588 if (host_name_hash
) {
589 if (host_hash_lookup (&hp
, host_name_hash
,
590 (unsigned char *)hd
-> name
,
591 strlen (hd
-> name
), MDL
)) {
592 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
593 host_hash_delete (host_name_hash
,
594 (unsigned char *)hd
-> name
,
595 strlen (hd
-> name
), MDL
);
597 host_dereference (&hp
, MDL
);
602 if (!write_host (hd
))
603 return ISC_R_IOERROR
;
604 if (!commit_leases ())
605 return ISC_R_IOERROR
;
607 return ISC_R_SUCCESS
;
610 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
611 const unsigned char *haddr
, unsigned hlen
,
612 const char *file
, int line
)
615 #if defined(LDAP_CONFIGURATION)
618 if ((ret
= find_haddr_in_ldap (hp
, htype
, hlen
, haddr
, file
, line
)))
624 memcpy (&h
.hbuf
[1], haddr
, hlen
);
626 return host_hash_lookup (hp
, host_hw_addr_hash
,
627 h
.hbuf
, h
.hlen
, file
, line
);
630 int find_hosts_by_uid (struct host_decl
**hp
,
631 const unsigned char *data
, unsigned len
,
632 const char *file
, int line
)
634 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
638 find_hosts_by_option(struct host_decl
**hp
,
639 struct packet
*packet
,
640 struct option_state
*opt_state
,
641 const char *file
, int line
) {
643 struct option_cache
*oc
;
644 struct data_string data
;
646 struct packet
*relay_packet
;
647 struct option_state
*relay_state
;
649 #if defined(LDAP_CONFIGURATION)
650 if ((found
= find_client_in_ldap (hp
, packet
, opt_state
, file
, line
)))
654 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
655 relay_packet
= packet
;
656 relay_state
= opt_state
;
658 /* If this option block is for a relay (relays != 0)
659 * and we are processing the main options and not
660 * options from the IA (packet->options == opt_state)
661 * try to find the proper relay
663 if ((p
->relays
!= 0) && (packet
->options
== opt_state
)) {
666 (relay_packet
->dhcpv6_container_packet
!= NULL
)) {
668 relay_packet
->dhcpv6_container_packet
;
671 /* We wanted a specific relay but were
672 * unable to find it */
673 if ((p
->relays
<= MAX_V6RELAY_HOPS
) && (i
!= 0))
676 relay_state
= relay_packet
->options
;
679 oc
= lookup_option(p
->option
->universe
,
680 relay_state
, p
->option
->code
);
682 memset(&data
, 0, sizeof(data
));
684 if (!evaluate_option_cache(&data
, relay_packet
, NULL
,
685 NULL
, relay_state
, NULL
,
688 log_error("Error evaluating option cache");
692 found
= host_hash_lookup(hp
, p
->values_hash
,
696 data_string_forget(&data
, MDL
);
706 /* More than one host_decl can be returned by find_hosts_by_haddr or
707 find_hosts_by_uid, and each host_decl can have multiple addresses.
708 Loop through the list of hosts, and then for each host, through the
709 list of addresses, looking for an address that's in the same shared
710 network as the one specified. Store the matching address through
711 the addr pointer, update the host pointer to point at the host_decl
712 that matched, and return the subnet that matched. */
714 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
715 struct iaddr
*addr
, struct shared_network
*share
)
718 struct iaddr ip_address
;
719 struct host_decl
*hp
;
720 struct data_string fixed_addr
;
722 memset (&fixed_addr
, 0, sizeof fixed_addr
);
724 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
725 if (!hp
-> fixed_addr
)
727 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
729 (struct client_state
*)0,
730 (struct option_state
*)0,
731 (struct option_state
*)0,
733 hp
-> fixed_addr
, MDL
))
735 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
737 memcpy (ip_address
.iabuf
,
738 fixed_addr
.data
+ i
, 4);
739 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
740 struct host_decl
*tmp
= (struct host_decl
*)0;
742 /* This is probably not necessary, but
743 just in case *host is the only reference
744 to that host declaration, make a temporary
745 reference so that dereferencing it doesn't
746 dereference hp out from under us. */
747 host_reference (&tmp
, *host
, MDL
);
748 host_dereference (host
, MDL
);
749 host_reference (host
, hp
, MDL
);
750 host_dereference (&tmp
, MDL
);
751 data_string_forget (&fixed_addr
, MDL
);
755 data_string_forget (&fixed_addr
, MDL
);
760 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
762 struct iaddr low
, high
;
763 struct subnet
*subnet
;
765 struct lease
**lpchain
;
767 #if defined(COMPACT_LEASES)
768 struct lease
*address_range
;
771 unsigned min
, max
, i
, num_addrs
;
772 char lowbuf
[16], highbuf
[16], netbuf
[16];
773 struct shared_network
*share
= subnet
-> shared_network
;
774 struct lease
*lt
= (struct lease
*)0;
775 #if !defined(COMPACT_LEASES)
779 /* All subnets should have attached shared network structures. */
781 strcpy (netbuf
, piaddr (subnet
-> net
));
782 log_fatal ("No shared network for network %s (%s)",
783 netbuf
, piaddr (subnet
-> netmask
));
786 /* Initialize the hash table if it hasn't been done yet. */
787 if (!lease_uid_hash
) {
788 if (!lease_id_new_hash(&lease_uid_hash
, LEASE_HASH_SIZE
, MDL
))
789 log_fatal ("Can't allocate lease/uid hash");
791 if (!lease_ip_addr_hash
) {
792 if (!lease_ip_new_hash(&lease_ip_addr_hash
, LEASE_HASH_SIZE
,
794 log_fatal ("Can't allocate lease/ip hash");
796 if (!lease_hw_addr_hash
) {
797 if (!lease_id_new_hash(&lease_hw_addr_hash
, LEASE_HASH_SIZE
,
799 log_fatal ("Can't allocate lease/hw hash");
802 /* Make sure that high and low addresses are in this subnet. */
803 if (!addr_eq(subnet
->net
, subnet_number(low
, subnet
->netmask
))) {
804 strcpy(lowbuf
, piaddr(low
));
805 strcpy(netbuf
, piaddr(subnet
->net
));
806 log_fatal("bad range, address %s not in subnet %s netmask %s",
807 lowbuf
, netbuf
, piaddr(subnet
->netmask
));
810 if (!addr_eq(subnet
->net
, subnet_number(high
, subnet
->netmask
))) {
811 strcpy(highbuf
, piaddr(high
));
812 strcpy(netbuf
, piaddr(subnet
->net
));
813 log_fatal("bad range, address %s not in subnet %s netmask %s",
814 highbuf
, netbuf
, piaddr(subnet
->netmask
));
817 /* Get the high and low host addresses... */
818 max
= host_addr (high
, subnet
-> netmask
);
819 min
= host_addr (low
, subnet
-> netmask
);
821 /* Allow range to be specified high-to-low as well as low-to-high. */
824 min
= host_addr (high
, subnet
-> netmask
);
827 /* get the number of addresses we want, and add it to the pool info
828 * this value is only for use when setting up lease chains and will
829 * be overwritten when expire_all_pools is run
831 num_addrs
= max
- min
+ 1;
832 #if defined (BINARY_LEASES)
833 pool
->lease_count
+= num_addrs
;
836 /* Get a lease structure for each address in the range. */
837 #if defined (COMPACT_LEASES)
838 s
= (num_addrs
+ 1) * sizeof (struct lease
);
839 /* Check unsigned overflow in new_leases().
840 With 304 byte lease structure (x64_86), this happens at
841 range 10.0.0.0 10.215.148.52; */
842 if (((s
% sizeof (struct lease
)) != 0) ||
843 ((s
/ sizeof (struct lease
)) != (num_addrs
+ 1))) {
844 strcpy (lowbuf
, piaddr (low
));
845 strcpy (highbuf
, piaddr (high
));
846 parse_warn (cfile
, "%s-%s is an overly large address range.",
848 log_fatal ("Memory overflow.");
850 address_range
= new_leases (num_addrs
, MDL
);
851 if (!address_range
) {
852 strcpy (lowbuf
, piaddr (low
));
853 strcpy (highbuf
, piaddr (high
));
854 log_fatal ("No memory for address range %s-%s.",
859 /* Fill out the lease structures with some minimal information. */
860 for (i
= 0; i
< num_addrs
; i
++) {
861 struct lease
*lp
= (struct lease
*)0;
862 #if defined (COMPACT_LEASES)
863 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
865 0, sizeof (struct lease
), MDL
);
866 lease_reference (&lp
, &address_range
[i
], MDL
);
868 status
= lease_allocate (&lp
, MDL
);
869 if (status
!= ISC_R_SUCCESS
)
870 log_fatal ("No memory for lease %s: %s",
871 piaddr (ip_addr (subnet
-> net
,
874 isc_result_totext (status
));
876 lp
->ip_addr
= ip_addr(subnet
->net
, subnet
->netmask
, i
+ min
);
877 lp
->starts
= MIN_TIME
;
879 subnet_reference(&lp
->subnet
, subnet
, MDL
);
880 pool_reference(&lp
->pool
, pool
, MDL
);
881 lp
->binding_state
= FTS_FREE
;
882 lp
->next_binding_state
= FTS_FREE
;
883 lp
->rewind_binding_state
= FTS_FREE
;
886 /* Remember the lease in the IP address hash. */
887 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
890 "lease %s is declared twice!",
891 piaddr (lp
-> ip_addr
));
893 pool_reference (<
-> pool
, pool
, MDL
);
894 lease_dereference (<
, MDL
);
896 lease_ip_hash_add(lease_ip_addr_hash
,
897 lp
->ip_addr
.iabuf
, lp
->ip_addr
.len
,
899 /* Put the lease on the chain for the caller. */
902 lease_reference (&lp
-> next
, *lpchain
, MDL
);
903 lease_dereference (lpchain
, MDL
);
905 lease_reference (lpchain
, lp
, MDL
);
907 lease_dereference (&lp
, MDL
);
911 int find_subnet (struct subnet
**sp
,
912 struct iaddr addr
, const char *file
, int line
)
916 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
917 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
918 if (subnet_reference (sp
, rv
,
919 file
, line
) != ISC_R_SUCCESS
)
927 int find_grouped_subnet (struct subnet
**sp
,
928 struct shared_network
*share
, struct iaddr addr
,
929 const char *file
, int line
)
933 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
934 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
935 if (subnet_reference (sp
, rv
,
936 file
, line
) != ISC_R_SUCCESS
)
944 /* XXX: could speed up if everyone had a prefix length */
946 subnet_inner_than(const struct subnet
*subnet
,
947 const struct subnet
*scan
,
949 if (addr_eq(subnet_number(subnet
->net
, scan
->netmask
), scan
->net
) ||
950 addr_eq(subnet_number(scan
->net
, subnet
->netmask
), subnet
->net
)) {
951 char n1buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
953 for (i
= 0; i
< 128; i
++)
954 if (subnet
->netmask
.iabuf
[3 - (i
>> 3)]
957 for (j
= 0; j
< 128; j
++)
958 if (scan
->netmask
.iabuf
[3 - (j
>> 3)] &
962 strcpy(n1buf
, piaddr(subnet
->net
));
963 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
965 piaddr(scan
->net
), 32 - j
);
973 /* Enter a new subnet into the subnet list. */
974 void enter_subnet (subnet
)
975 struct subnet
*subnet
;
977 struct subnet
*scan
= (struct subnet
*)0;
978 struct subnet
*next
= (struct subnet
*)0;
979 struct subnet
*prev
= (struct subnet
*)0;
981 /* Check for duplicates... */
983 subnet_reference (&next
, subnets
, MDL
);
985 subnet_reference (&scan
, next
, MDL
);
986 subnet_dereference (&next
, MDL
);
988 /* When we find a conflict, make sure that the
989 subnet with the narrowest subnet mask comes
991 if (subnet_inner_than (subnet
, scan
, 1)) {
993 if (prev
-> next_subnet
)
994 subnet_dereference (&prev
-> next_subnet
, MDL
);
995 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
996 subnet_dereference (&prev
, MDL
);
998 subnet_dereference (&subnets
, MDL
);
999 subnet_reference (&subnets
, subnet
, MDL
);
1001 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
1002 subnet_dereference (&scan
, MDL
);
1005 subnet_reference (&prev
, scan
, MDL
);
1006 subnet_dereference (&scan
, MDL
);
1009 subnet_dereference (&prev
, MDL
);
1011 /* XXX use the BSD radix tree code instead of a linked list. */
1013 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
1014 subnet_dereference (&subnets
, MDL
);
1016 subnet_reference (&subnets
, subnet
, MDL
);
1019 /* Enter a new shared network into the shared network list. */
1021 void enter_shared_network (share
)
1022 struct shared_network
*share
;
1024 if (shared_networks
) {
1025 shared_network_reference (&share
-> next
,
1026 shared_networks
, MDL
);
1027 shared_network_dereference (&shared_networks
, MDL
);
1029 shared_network_reference (&shared_networks
, share
, MDL
);
1032 void new_shared_network_interface (cfile
, share
, name
)
1033 struct parse
*cfile
;
1034 struct shared_network
*share
;
1037 struct interface_info
*ip
;
1038 isc_result_t status
;
1040 if (share
-> interface
) {
1042 "A subnet or shared network can't be connected %s",
1043 "to two interfaces.");
1047 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
1048 if (!strcmp (ip
-> name
, name
))
1051 status
= interface_allocate (&ip
, MDL
);
1052 if (status
!= ISC_R_SUCCESS
)
1053 log_fatal ("new_shared_network_interface %s: %s",
1054 name
, isc_result_totext (status
));
1055 if (strlen (name
) > sizeof ip
-> name
) {
1056 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
1057 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
1059 strcpy (ip
-> name
, name
);
1061 interface_reference (&ip
-> next
, interfaces
, MDL
);
1062 interface_dereference (&interfaces
, MDL
);
1064 interface_reference (&interfaces
, ip
, MDL
);
1065 ip
-> flags
= INTERFACE_REQUESTED
;
1066 /* XXX this is a reference loop. */
1067 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
1068 interface_reference (&share
-> interface
, ip
, MDL
);
1072 /* Enter a lease into the system. This is called by the parser each
1073 time it reads in a new lease. If the subnet for that lease has
1074 already been read in (usually the case), just update that lease;
1075 otherwise, allocate temporary storage for the lease and keep it around
1076 until we're done reading in the config file. */
1078 void enter_lease (lease
)
1079 struct lease
*lease
;
1081 struct lease
*comp
= (struct lease
*)0;
1083 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
1084 if (!comp
-> pool
) {
1085 log_error ("undeclared lease found in database: %s",
1086 piaddr (lease
-> ip_addr
));
1088 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
1091 subnet_reference (&lease
-> subnet
,
1092 comp
-> subnet
, MDL
);
1093 lease_ip_hash_delete(lease_ip_addr_hash
,
1094 lease
->ip_addr
.iabuf
, lease
->ip_addr
.len
,
1096 lease_dereference (&comp
, MDL
);
1099 /* The only way a lease can get here without a subnet is if it's in
1100 the lease file, but not in the dhcpd.conf file. In this case, we
1101 *should* keep it around until it's expired, but never reallocate it
1102 or renew it. Currently, to maintain consistency, we are not doing
1104 XXX fix this so that the lease is kept around until it expires.
1105 XXX this will be important in IPv6 with addresses that become
1106 XXX non-renewable as a result of a renumbering event. */
1108 if (!lease
-> subnet
) {
1109 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
1112 lease_ip_hash_add(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
1113 lease
->ip_addr
.len
, lease
, MDL
);
1116 /* Replace the data in an existing lease with the data in a new lease;
1117 adjust hash tables to suit, and insertion sort the lease into the
1118 list of leases by expiry time so that we can always find the oldest
1121 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
, from_pool
)
1122 struct lease
*comp
, *lease
;
1128 LEASE_STRUCT_PTR lq
;
1130 #if defined (FAILOVER_PROTOCOL)
1131 int do_pool_check
= 0;
1133 /* We must commit leases before sending updates regarding them
1134 to failover peers. It is, therefore, an error to set pimmediate
1136 if (pimmediate
&& !commit
)
1140 /* If there is no sample lease, just do the move. */
1144 /* Static leases are not currently kept in the database... */
1145 if (lease
-> flags
& STATIC_LEASE
)
1148 /* If the existing lease hasn't expired and has a different
1149 unique identifier or, if it doesn't have a unique
1150 identifier, a different hardware address, then the two
1151 leases are in conflict. If the existing lease has a uid
1152 and the new one doesn't, but they both have the same
1153 hardware address, and dynamic bootp is allowed on this
1154 lease, then we allow that, in case a dynamic BOOTP lease is
1155 requested *after* a DHCP lease has been assigned. */
1157 if (lease
-> binding_state
!= FTS_ABANDONED
&&
1158 lease
-> next_binding_state
!= FTS_ABANDONED
&&
1159 comp
-> binding_state
== FTS_ACTIVE
&&
1160 (((comp
-> uid
&& lease
-> uid
) &&
1161 (comp
-> uid_len
!= lease
-> uid_len
||
1162 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
1164 ((comp
-> hardware_addr
.hlen
!=
1165 lease
-> hardware_addr
.hlen
) ||
1166 memcmp (comp
-> hardware_addr
.hbuf
,
1167 lease
-> hardware_addr
.hbuf
,
1168 comp
-> hardware_addr
.hlen
))))) {
1169 log_error ("Lease conflict at %s",
1170 piaddr (comp
-> ip_addr
));
1173 /* If there's a Unique ID, dissociate it from the hash
1174 table and free it if necessary. */
1176 uid_hash_delete(comp
);
1177 if (comp
->uid
!= comp
->uid_buf
) {
1178 dfree(comp
->uid
, MDL
);
1182 comp
-> uid
= (unsigned char *)0;
1185 /* If there's a hardware address, remove the lease from its
1186 * old position in the hash bucket's ordered list.
1188 if (comp
->hardware_addr
.hlen
)
1189 hw_hash_delete(comp
);
1191 /* If the lease has been billed to a class, remove the billing. */
1192 if (comp
-> billing_class
!= lease
-> billing_class
) {
1193 if (comp
->billing_class
)
1195 if (lease
-> billing_class
)
1196 bill_class (comp
, lease
-> billing_class
);
1199 /* Copy the data files, but not the linkages. */
1200 comp
-> starts
= lease
-> starts
;
1202 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
1203 memcpy (comp
-> uid_buf
,
1204 lease
-> uid
, lease
-> uid_len
);
1205 comp
-> uid
= &comp
-> uid_buf
[0];
1206 comp
-> uid_max
= sizeof comp
-> uid_buf
;
1207 comp
-> uid_len
= lease
-> uid_len
;
1208 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
1209 comp
-> uid
= lease
-> uid
;
1210 comp
-> uid_max
= lease
-> uid_max
;
1211 lease
-> uid
= (unsigned char *)0;
1212 lease
-> uid_max
= 0;
1213 comp
-> uid_len
= lease
-> uid_len
;
1214 lease
-> uid_len
= 0;
1216 log_fatal ("corrupt lease uid."); /* XXX */
1219 comp
-> uid
= (unsigned char *)0;
1220 comp
-> uid_len
= comp
-> uid_max
= 0;
1223 host_dereference (&comp
-> host
, MDL
);
1224 host_reference (&comp
-> host
, lease
-> host
, MDL
);
1225 comp
-> hardware_addr
= lease
-> hardware_addr
;
1226 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
1227 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
1229 binding_scope_dereference (&comp
-> scope
, MDL
);
1230 if (lease
-> scope
) {
1231 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
1232 binding_scope_dereference (&lease
-> scope
, MDL
);
1235 if (comp
-> agent_options
)
1236 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
1237 if (lease
-> agent_options
) {
1238 /* Only retain the agent options if the lease is still
1239 affirmatively associated with a client. */
1240 if (lease
-> next_binding_state
== FTS_ACTIVE
||
1241 lease
-> next_binding_state
== FTS_EXPIRED
)
1242 option_chain_head_reference (&comp
-> agent_options
,
1243 lease
-> agent_options
,
1245 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
1248 /* Record the hostname information in the lease. */
1249 if (comp
-> client_hostname
)
1250 dfree (comp
-> client_hostname
, MDL
);
1251 comp
-> client_hostname
= lease
-> client_hostname
;
1252 lease
-> client_hostname
= (char *)0;
1254 if (lease
->on_star
.on_expiry
) {
1255 if (comp
->on_star
.on_expiry
)
1256 executable_statement_dereference
1257 (&comp
->on_star
.on_expiry
, MDL
);
1258 executable_statement_reference (&comp
->on_star
.on_expiry
,
1259 lease
->on_star
.on_expiry
,
1262 if (lease
->on_star
.on_commit
) {
1263 if (comp
->on_star
.on_commit
)
1264 executable_statement_dereference
1265 (&comp
->on_star
.on_commit
, MDL
);
1266 executable_statement_reference (&comp
->on_star
.on_commit
,
1267 lease
->on_star
.on_commit
,
1270 if (lease
->on_star
.on_release
) {
1271 if (comp
->on_star
.on_release
)
1272 executable_statement_dereference
1273 (&comp
->on_star
.on_release
, MDL
);
1274 executable_statement_reference (&comp
->on_star
.on_release
,
1275 lease
->on_star
.on_release
,
1279 /* Record the lease in the uid hash if necessary. */
1283 /* Record it in the hardware address hash if necessary. */
1284 if (comp
->hardware_addr
.hlen
)
1287 comp
->cltt
= lease
->cltt
;
1288 #if defined (FAILOVER_PROTOCOL)
1289 comp
->tstp
= lease
->tstp
;
1290 comp
->tsfp
= lease
->tsfp
;
1291 comp
->atsfp
= lease
->atsfp
;
1292 #endif /* FAILOVER_PROTOCOL */
1293 comp
->ends
= lease
->ends
;
1294 comp
->next_binding_state
= lease
->next_binding_state
;
1297 * If we have a control block pointer copy it in.
1298 * We don't zero out an older ponter as it is still
1299 * in use. We shouldn't need to overwrite an
1300 * old pointer with a new one as the old transaction
1301 * should have been cancelled before getting here.
1303 if (lease
->ddns_cb
!= NULL
)
1304 comp
->ddns_cb
= lease
->ddns_cb
;
1307 #if defined (FAILOVER_PROTOCOL)
1309 * Atsfp should be cleared upon any state change that implies
1310 * propagation whether supersede_lease was given a copy lease
1311 * structure or not (often from the pool_timer()).
1315 #endif /* FAILOVER_PROTOCOL */
1317 if (!comp
-> pool
) {
1318 log_error ("Supersede_lease: lease %s with no pool.",
1319 piaddr (comp
-> ip_addr
));
1323 /* Figure out which queue it's on. */
1324 switch (comp
-> binding_state
) {
1326 if (comp
->flags
& RESERVED_LEASE
)
1327 lq
= &comp
->pool
->reserved
;
1329 lq
= &comp
->pool
->free
;
1330 comp
->pool
->free_leases
--;
1333 #if defined(FAILOVER_PROTOCOL)
1339 lq
= &comp
-> pool
-> active
;
1345 lq
= &comp
-> pool
-> expired
;
1349 lq
= &comp
-> pool
-> abandoned
;
1353 if (comp
->flags
& RESERVED_LEASE
)
1354 lq
= &comp
->pool
->reserved
;
1356 lq
= &comp
->pool
->backup
;
1357 comp
->pool
->backup_leases
--;
1360 #if defined(FAILOVER_PROTOCOL)
1366 log_error ("Lease with bogus binding state: %d",
1367 comp
-> binding_state
);
1368 #if defined (BINDING_STATE_DEBUG)
1374 /* Remove the lease from its current place in its current
1376 LEASE_REMOVEP(lq
, comp
);
1378 /* Make the state transition. */
1379 if (commit
|| !pimmediate
)
1380 make_binding_state_transition (comp
);
1382 /* Put the lease back on the appropriate queue. If the lease
1383 is corrupt (as detected by lease_enqueue), don't go any farther. */
1384 if (!lease_enqueue (comp
))
1387 /* If this is the next lease that will timeout on the pool,
1388 zap the old timeout and set the timeout on this pool to the
1389 time that the lease's next event will happen.
1391 We do not actually set the timeout unless commit is true -
1392 we don't want to thrash the timer queue when reading the
1393 lease database. Instead, the database code calls the
1394 expiry event on each pool after reading in the lease file,
1395 and the expiry code sets the timer if there's anything left
1396 to expire after it's run any outstanding expiry events on
1398 if ((commit
|| !pimmediate
) &&
1399 comp
-> sort_time
!= MIN_TIME
&&
1400 comp
-> sort_time
> cur_time
&&
1401 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1402 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1403 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1404 tv
. tv_sec
= comp
-> pool
-> next_event_time
;
1407 pool_timer
, comp
-> pool
,
1408 (tvref_t
)pool_reference
,
1409 (tvunref_t
)pool_dereference
);
1413 #if defined(FAILOVER_PROTOCOL)
1415 * If commit and propogate are set, then we can save a
1416 * possible fsync later in BNDUPD socket transmission by
1417 * stepping the rewind state forward to the new state, in
1418 * case it has changed. This is only worth doing if the
1419 * failover connection is currently connected, as in this
1420 * case it is likely we will be transmitting to the peer very
1423 if (propogate
&& (comp
->pool
->failover_peer
!= NULL
) &&
1424 ((comp
->pool
->failover_peer
->service_state
==
1426 (comp
->pool
->failover_peer
->service_state
==
1428 comp
->rewind_binding_state
= comp
->binding_state
;
1431 if (!write_lease (comp
))
1433 if ((server_starting
& SS_NOSYNC
) == 0) {
1434 if (!commit_leases ())
1439 #if defined (FAILOVER_PROTOCOL)
1441 comp
-> desired_binding_state
= comp
-> binding_state
;
1442 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1445 if (do_pool_check
&& comp
->pool
->failover_peer
)
1446 dhcp_failover_pool_check(comp
->pool
);
1449 /* If the current binding state has already expired and we haven't
1450 * been called from pool_timer, do an expiry event right now.
1452 /* XXX At some point we should optimize this so that we don't
1453 XXX write the lease twice, but this is a safe way to fix the
1454 XXX problem for 3.0 (I hope!). */
1455 if ((from_pool
== 0) &&
1456 (commit
|| !pimmediate
) &&
1457 (comp
->sort_time
< cur_time
) &&
1458 (comp
->next_binding_state
!= comp
->binding_state
))
1459 pool_timer(comp
->pool
);
1464 void make_binding_state_transition (struct lease
*lease
)
1467 #if defined (FAILOVER_PROTOCOL)
1468 dhcp_failover_state_t
*peer
;
1470 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1471 peer
= lease
-> pool
-> failover_peer
;
1473 peer
= (dhcp_failover_state_t
*)0;
1476 /* If the lease was active and is now no longer active, but isn't
1477 released, then it just expired, so do the expiry event. */
1478 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1480 #if defined (FAILOVER_PROTOCOL)
1482 (lease
->binding_state
== FTS_EXPIRED
||
1483 lease
->binding_state
== FTS_ACTIVE
) &&
1484 (lease
->next_binding_state
== FTS_FREE
||
1485 lease
->next_binding_state
== FTS_BACKUP
)) ||
1488 lease
-> binding_state
== FTS_ACTIVE
&&
1489 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1490 #if defined (NSUPDATE)
1491 (void) ddns_removals(lease
, NULL
, NULL
, ISC_TRUE
);
1493 if (lease
->on_star
.on_expiry
) {
1494 execute_statements(NULL
, NULL
, lease
,
1497 lease
->on_star
.on_expiry
,
1499 if (lease
->on_star
.on_expiry
)
1500 executable_statement_dereference
1501 (&lease
->on_star
.on_expiry
, MDL
);
1504 /* No sense releasing a lease after it's expired. */
1505 if (lease
->on_star
.on_release
)
1506 executable_statement_dereference
1507 (&lease
->on_star
.on_release
, MDL
);
1508 /* Get rid of client-specific bindings that are only
1509 correct when the lease is active. */
1510 if (lease
->billing_class
)
1511 unbill_class(lease
);
1512 if (lease
-> agent_options
)
1513 option_chain_head_dereference (&lease
-> agent_options
,
1515 if (lease
-> client_hostname
) {
1516 dfree (lease
-> client_hostname
, MDL
);
1517 lease
-> client_hostname
= (char *)0;
1520 host_dereference (&lease
-> host
, MDL
);
1522 /* Send the expiry time to the peer. */
1523 lease
-> tstp
= lease
-> ends
;
1526 /* If the lease was active and is now released, do the release
1528 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1530 #if defined (FAILOVER_PROTOCOL)
1532 lease
-> binding_state
== FTS_RELEASED
&&
1533 (lease
-> next_binding_state
== FTS_FREE
||
1534 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1537 lease
-> binding_state
== FTS_ACTIVE
&&
1538 lease
-> next_binding_state
== FTS_RELEASED
))) {
1539 #if defined (NSUPDATE)
1541 * Note: ddns_removals() is also iterated when the lease
1542 * enters state 'released' in 'release_lease()'. The below
1543 * is caught when a peer receives a BNDUPD from a failover
1544 * peer; it may not have received the client's release (it
1545 * may have been offline).
1547 * We could remove the call from release_lease() because
1548 * it will also catch here on the originating server after the
1549 * peer acknowledges the state change. However, there could
1550 * be many hours inbetween, and in this case we /know/ the
1551 * client is no longer using the lease when we receive the
1552 * release message. This is not true of expiry, where the
1553 * peer may have extended the lease.
1555 (void) ddns_removals(lease
, NULL
, NULL
, ISC_TRUE
);
1557 if (lease
->on_star
.on_release
) {
1558 execute_statements(NULL
, NULL
, lease
,
1561 lease
->on_star
.on_release
,
1563 executable_statement_dereference
1564 (&lease
->on_star
.on_release
, MDL
);
1567 /* A released lease can't expire. */
1568 if (lease
->on_star
.on_expiry
)
1569 executable_statement_dereference
1570 (&lease
->on_star
.on_expiry
, MDL
);
1572 /* Get rid of client-specific bindings that are only
1573 correct when the lease is active. */
1574 if (lease
->billing_class
)
1575 unbill_class(lease
);
1576 if (lease
-> agent_options
)
1577 option_chain_head_dereference (&lease
-> agent_options
,
1579 if (lease
-> client_hostname
) {
1580 dfree (lease
-> client_hostname
, MDL
);
1581 lease
-> client_hostname
= (char *)0;
1584 host_dereference (&lease
-> host
, MDL
);
1586 /* Send the release time (should be == cur_time) to the
1588 lease
-> tstp
= lease
-> ends
;
1591 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1592 log_debug ("lease %s moves from %s to %s",
1593 piaddr (lease
-> ip_addr
),
1594 binding_state_print (lease
-> binding_state
),
1595 binding_state_print (lease
-> next_binding_state
));
1598 lease
-> binding_state
= lease
-> next_binding_state
;
1599 switch (lease
-> binding_state
) {
1601 #if defined (FAILOVER_PROTOCOL)
1602 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1603 lease
-> next_binding_state
= FTS_EXPIRED
;
1606 lease
-> next_binding_state
= FTS_FREE
;
1613 lease
->next_binding_state
= FTS_FREE
;
1614 #if defined(FAILOVER_PROTOCOL)
1615 /* If we are not in partner_down, leases don't go from
1616 EXPIRED to FREE on a timeout - only on an update.
1617 If we're in partner_down, they expire at mclt past
1618 the time we entered partner_down. */
1619 if ((lease
->pool
!= NULL
) &&
1620 (lease
->pool
->failover_peer
!= NULL
) &&
1621 (lease
->pool
->failover_peer
->me
.state
== partner_down
))
1623 (lease
->pool
->failover_peer
->me
.stos
+
1624 lease
->pool
->failover_peer
->mclt
);
1625 #endif /* FAILOVER_PROTOCOL */
1630 lease
-> next_binding_state
= lease
-> binding_state
;
1633 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1634 log_debug ("lease %s: next binding state %s",
1635 piaddr (lease
-> ip_addr
),
1636 binding_state_print (lease
-> next_binding_state
));
1640 /* Copy the contents of one lease into another, correctly maintaining
1641 reference counts. */
1642 int lease_copy (struct lease
**lp
,
1643 struct lease
*lease
, const char *file
, int line
)
1645 struct lease
*lt
= (struct lease
*)0;
1646 isc_result_t status
;
1648 status
= lease_allocate (<
, MDL
);
1649 if (status
!= ISC_R_SUCCESS
)
1652 lt
-> ip_addr
= lease
-> ip_addr
;
1653 lt
-> starts
= lease
-> starts
;
1654 lt
-> ends
= lease
-> ends
;
1655 lt
-> uid_len
= lease
-> uid_len
;
1656 lt
-> uid_max
= lease
-> uid_max
;
1657 if (lease
-> uid
== lease
-> uid_buf
) {
1658 lt
-> uid
= lt
-> uid_buf
;
1659 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1660 } else if (!lease
-> uid_max
) {
1661 lt
-> uid
= (unsigned char *)0;
1663 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1665 lease_dereference (<
, MDL
);
1668 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1670 if (lease
-> client_hostname
) {
1671 lt
-> client_hostname
=
1672 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1673 if (!lt
-> client_hostname
) {
1674 lease_dereference (<
, MDL
);
1677 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1680 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1681 if (lease
-> agent_options
)
1682 option_chain_head_reference (<
-> agent_options
,
1683 lease
-> agent_options
, MDL
);
1684 host_reference (<
-> host
, lease
-> host
, file
, line
);
1685 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1686 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1687 class_reference (<
-> billing_class
,
1688 lease
-> billing_class
, file
, line
);
1689 lt
-> hardware_addr
= lease
-> hardware_addr
;
1690 if (lease
->on_star
.on_expiry
)
1691 executable_statement_reference (<
->on_star
.on_expiry
,
1692 lease
->on_star
.on_expiry
,
1694 if (lease
->on_star
.on_commit
)
1695 executable_statement_reference (<
->on_star
.on_commit
,
1696 lease
->on_star
.on_commit
,
1698 if (lease
->on_star
.on_release
)
1699 executable_statement_reference (<
->on_star
.on_release
,
1700 lease
->on_star
.on_release
,
1702 lt
->flags
= lease
->flags
;
1703 lt
->tstp
= lease
->tstp
;
1704 lt
->tsfp
= lease
->tsfp
;
1705 lt
->atsfp
= lease
->atsfp
;
1706 lt
->cltt
= lease
-> cltt
;
1707 lt
->binding_state
= lease
->binding_state
;
1708 lt
->next_binding_state
= lease
->next_binding_state
;
1709 lt
->rewind_binding_state
= lease
->rewind_binding_state
;
1710 status
= lease_reference(lp
, lt
, file
, line
);
1711 lease_dereference(<
, MDL
);
1712 return status
== ISC_R_SUCCESS
;
1715 /* Release the specified lease and re-hash it as appropriate. */
1716 void release_lease (lease
, packet
)
1717 struct lease
*lease
;
1718 struct packet
*packet
;
1720 /* If there are statements to execute when the lease is
1721 released, execute them. */
1722 #if defined (NSUPDATE)
1723 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1725 if (lease
->on_star
.on_release
) {
1726 execute_statements (NULL
, packet
, lease
,
1727 NULL
, packet
->options
,
1728 NULL
, &lease
->scope
,
1729 lease
->on_star
.on_release
, NULL
);
1730 if (lease
->on_star
.on_release
)
1731 executable_statement_dereference
1732 (&lease
->on_star
.on_release
, MDL
);
1735 /* We do either the on_release or the on_expiry events, but
1736 not both (it's possible that they could be the same,
1738 if (lease
->on_star
.on_expiry
)
1739 executable_statement_dereference
1740 (&lease
->on_star
.on_expiry
, MDL
);
1742 if (lease
-> binding_state
!= FTS_FREE
&&
1743 lease
-> binding_state
!= FTS_BACKUP
&&
1744 lease
-> binding_state
!= FTS_RELEASED
&&
1745 lease
-> binding_state
!= FTS_EXPIRED
&&
1746 lease
-> binding_state
!= FTS_RESET
) {
1747 if (lease
->on_star
.on_commit
)
1748 executable_statement_dereference
1749 (&lease
->on_star
.on_commit
, MDL
);
1751 /* Blow away any bindings. */
1753 binding_scope_dereference (&lease
-> scope
, MDL
);
1755 /* Set sort times to the present. */
1756 lease
-> ends
= cur_time
;
1757 /* Lower layers of muckery set tstp to ->ends. But we send
1758 * protocol messages before this. So it is best to set
1761 lease
->tstp
= cur_time
;
1762 #if defined (FAILOVER_PROTOCOL)
1763 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1764 dhcp_failover_state_t
*peer
= NULL
;
1766 if (lease
->pool
!= NULL
)
1767 peer
= lease
->pool
->failover_peer
;
1769 if ((peer
->service_state
== not_cooperating
) &&
1770 (((peer
->i_am
== primary
) &&
1771 (lease
->rewind_binding_state
== FTS_FREE
)) ||
1772 ((peer
->i_am
== secondary
) &&
1773 (lease
->rewind_binding_state
== FTS_BACKUP
)))) {
1774 lease
->next_binding_state
=
1775 lease
->rewind_binding_state
;
1777 lease
-> next_binding_state
= FTS_RELEASED
;
1779 lease
-> next_binding_state
= FTS_FREE
;
1782 lease
-> next_binding_state
= FTS_FREE
;
1784 supersede_lease(lease
, NULL
, 1, 1, 1, 0);
1788 /* Abandon the specified lease (set its timeout to infinity and its
1789 particulars to zero, and re-hash it as appropriate. */
1791 void abandon_lease (lease
, message
)
1792 struct lease
*lease
;
1793 const char *message
;
1795 struct lease
*lt
= (struct lease
*)0;
1796 #if defined (NSUPDATE)
1797 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1800 if (!lease_copy (<
, lease
, MDL
))
1804 binding_scope_dereference(<
->scope
, MDL
);
1806 lt
-> ends
= cur_time
; /* XXX */
1807 lt
-> next_binding_state
= FTS_ABANDONED
;
1809 log_error ("Abandoning IP address %s: %s",
1810 piaddr (lease
-> ip_addr
), message
);
1811 lt
-> hardware_addr
.hlen
= 0;
1812 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1813 dfree (lt
-> uid
, MDL
);
1814 lt
-> uid
= (unsigned char *)0;
1817 supersede_lease (lease
, lt
, 1, 1, 1, 0);
1818 lease_dereference (<
, MDL
);
1823 * This doesn't appear to be in use for anything anymore.
1824 * I'm ifdeffing it now and if there are no complaints in
1825 * the future it will be removed.
1829 /* Abandon the specified lease (set its timeout to infinity and its
1830 particulars to zero, and re-hash it as appropriate. */
1832 void dissociate_lease (lease
)
1833 struct lease
*lease
;
1835 struct lease
*lt
= (struct lease
*)0;
1836 #if defined (NSUPDATE)
1837 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1840 if (!lease_copy (<
, lease
, MDL
))
1843 #if defined (FAILOVER_PROTOCOL)
1844 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1845 lt
-> next_binding_state
= FTS_RESET
;
1847 lt
-> next_binding_state
= FTS_FREE
;
1850 lt
-> next_binding_state
= FTS_FREE
;
1852 lt
-> ends
= cur_time
; /* XXX */
1853 lt
-> hardware_addr
.hlen
= 0;
1854 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1855 dfree (lt
-> uid
, MDL
);
1856 lt
-> uid
= (unsigned char *)0;
1859 supersede_lease (lease
, lt
, 1, 1, 1, 0);
1860 lease_dereference (<
, MDL
);
1864 /* Timer called when a lease in a particular pool expires. */
1865 void pool_timer (vpool
)
1869 struct lease
*next
= NULL
;
1870 struct lease
*lease
= NULL
;
1871 struct lease
*ltemp
= NULL
;
1872 #define FREE_LEASES 0
1873 #define ACTIVE_LEASES 1
1874 #define EXPIRED_LEASES 2
1875 #define ABANDONED_LEASES 3
1876 #define BACKUP_LEASES 4
1877 #define RESERVED_LEASES 5
1878 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
1879 TIME next_expiry
= MAX_TIME
;
1883 pool
= (struct pool
*)vpool
;
1885 lptr
[FREE_LEASES
] = &pool
->free
;
1886 lptr
[ACTIVE_LEASES
] = &pool
->active
;
1887 lptr
[EXPIRED_LEASES
] = &pool
->expired
;
1888 lptr
[ABANDONED_LEASES
] = &pool
->abandoned
;
1889 lptr
[BACKUP_LEASES
] = &pool
->backup
;
1890 lptr
[RESERVED_LEASES
] = &pool
->reserved
;
1892 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
1893 /* If there's nothing on the queue, skip it. */
1894 if (!(LEASE_NOT_EMPTYP(lptr
[i
])))
1897 #if defined (FAILOVER_PROTOCOL)
1898 if (pool
->failover_peer
&&
1899 pool
->failover_peer
->me
.state
!= partner_down
) {
1901 * Normally the secondary doesn't initiate expiration
1902 * events (unless in partner-down), but rather relies
1903 * on the primary to expire the lease. However, when
1904 * disconnected from its peer, the server is allowed to
1905 * rewind a lease to the previous state that the peer
1906 * would have recorded it. This means there may be
1907 * opportunities for active->free or active->backup
1908 * expirations while out of contact.
1910 * Q: Should we limit this expiration to
1911 * comms-interrupt rather than not-normal?
1913 if ((i
== ACTIVE_LEASES
) &&
1914 (pool
->failover_peer
->i_am
== secondary
) &&
1915 (pool
->failover_peer
->me
.state
== normal
))
1918 /* Leases in an expired state don't move to
1919 free because of a timeout unless we're in
1921 if (i
== EXPIRED_LEASES
)
1925 lease_reference(&lease
, LEASE_GET_FIRSTP(lptr
[i
]), MDL
);
1928 /* Remember the next lease in the list. */
1930 lease_dereference(&next
, MDL
);
1931 ltemp
= LEASE_GET_NEXTP(lptr
[i
], lease
);
1933 lease_reference(&next
, ltemp
, MDL
);
1935 /* If we've run out of things to expire on this list,
1937 if (lease
->sort_time
> cur_time
) {
1938 if (lease
->sort_time
< next_expiry
)
1939 next_expiry
= lease
->sort_time
;
1943 /* If there is a pending state change, and
1944 this lease has gotten to the time when the
1945 state change should happen, just call
1946 supersede_lease on it to make the change
1948 if (lease
->next_binding_state
!= lease
->binding_state
)
1950 #if defined(FAILOVER_PROTOCOL)
1951 dhcp_failover_state_t
*peer
= NULL
;
1953 if (lease
->pool
!= NULL
)
1954 peer
= lease
->pool
->failover_peer
;
1956 /* Can we rewind the lease to a free state? */
1958 peer
->service_state
== not_cooperating
&&
1959 lease
->next_binding_state
== FTS_EXPIRED
&&
1960 ((peer
->i_am
== primary
&&
1961 lease
->rewind_binding_state
== FTS_FREE
)
1963 (peer
->i_am
== secondary
&&
1964 lease
->rewind_binding_state
==
1966 lease
->next_binding_state
=
1967 lease
->rewind_binding_state
;
1969 supersede_lease(lease
, NULL
, 1, 1, 1, 1);
1972 lease_dereference(&lease
, MDL
);
1974 lease_reference(&lease
, next
, MDL
);
1977 lease_dereference(&next
, MDL
);
1979 lease_dereference(&lease
, MDL
);
1982 /* If we found something to expire and its expiration time
1983 * is either less than the current expiration time or the
1984 * current expiration time is already expired update the
1987 if ((next_expiry
!= MAX_TIME
) &&
1988 ((pool
->next_event_time
> next_expiry
) ||
1989 (pool
->next_event_time
<= cur_time
))) {
1990 pool
->next_event_time
= next_expiry
;
1991 tv
.tv_sec
= pool
->next_event_time
;
1993 add_timeout (&tv
, pool_timer
, pool
,
1994 (tvref_t
)pool_reference
,
1995 (tvunref_t
)pool_dereference
);
1997 pool
->next_event_time
= MIN_TIME
;
2001 /* Locate the lease associated with a given IP address... */
2003 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
2004 const char *file
, int line
)
2006 return lease_ip_hash_lookup(lp
, lease_ip_addr_hash
, addr
.iabuf
,
2007 addr
.len
, file
, line
);
2010 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
2011 unsigned len
, const char *file
, int line
)
2015 return lease_id_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
2018 int find_lease_by_hw_addr (struct lease
**lp
,
2019 const unsigned char *hwaddr
, unsigned hwlen
,
2020 const char *file
, int line
)
2026 * If it's an infiniband address don't bother
2027 * as we don't have a useful address to hash.
2029 if ((hwlen
== 1) && (hwaddr
[0] == HTYPE_INFINIBAND
))
2032 return (lease_id_hash_lookup(lp
, lease_hw_addr_hash
, hwaddr
, hwlen
,
2036 /* If the lease is preferred over the candidate, return truth. The
2037 * 'cand' and 'lease' names are retained to read more clearly against
2038 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
2039 * to those two functions).
2041 * 1) ACTIVE leases are preferred. The active lease with
2042 * the longest lifetime is preferred over shortest.
2043 * 2) "transitional states" are next, this time with the
2045 * 3) free/backup/etc states are next, again with CLTT. In truth we
2046 * should never see reset leases for this.
2047 * 4) Abandoned leases are always dead last.
2049 static isc_boolean_t
2050 client_lease_preferred(struct lease
*cand
, struct lease
*lease
)
2052 if (cand
->binding_state
== FTS_ACTIVE
) {
2053 if (lease
->binding_state
== FTS_ACTIVE
&&
2054 lease
->ends
>= cand
->ends
)
2056 } else if (cand
->binding_state
== FTS_EXPIRED
||
2057 cand
->binding_state
== FTS_RELEASED
) {
2058 if (lease
->binding_state
== FTS_ACTIVE
)
2061 if ((lease
->binding_state
== FTS_EXPIRED
||
2062 lease
->binding_state
== FTS_RELEASED
) &&
2063 lease
->cltt
>= cand
->cltt
)
2065 } else if (cand
->binding_state
!= FTS_ABANDONED
) {
2066 if (lease
->binding_state
== FTS_ACTIVE
||
2067 lease
->binding_state
== FTS_EXPIRED
||
2068 lease
->binding_state
== FTS_RELEASED
)
2071 if (lease
->binding_state
!= FTS_ABANDONED
&&
2072 lease
->cltt
>= cand
->cltt
)
2074 } else /* (cand->binding_state == FTS_ABANDONED) */ {
2075 if (lease
->binding_state
!= FTS_ABANDONED
||
2076 lease
->cltt
>= cand
->cltt
)
2083 /* Add the specified lease to the uid hash. */
2085 uid_hash_add(struct lease
*lease
)
2087 struct lease
*head
= NULL
;
2088 struct lease
*cand
= NULL
;
2089 struct lease
*prev
= NULL
;
2090 struct lease
*next
= NULL
;
2092 /* If it's not in the hash, just add it. */
2093 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
2094 lease_id_hash_add(lease_uid_hash
, lease
->uid
, lease
->uid_len
,
2097 /* Otherwise, insert it into the list in order of its
2098 * preference for "resuming allocation to the client."
2100 * Because we don't have control of the hash bucket index
2101 * directly, we have to remove and re-insert the client
2102 * id into the hash if we're inserting onto the head.
2104 lease_reference(&cand
, head
, MDL
);
2105 while (cand
!= NULL
) {
2106 if (client_lease_preferred(cand
, lease
))
2110 lease_dereference(&prev
, MDL
);
2111 lease_reference(&prev
, cand
, MDL
);
2113 if (cand
->n_uid
!= NULL
)
2114 lease_reference(&next
, cand
->n_uid
, MDL
);
2116 lease_dereference(&cand
, MDL
);
2119 lease_reference(&cand
, next
, MDL
);
2120 lease_dereference(&next
, MDL
);
2124 /* If we want to insert 'before cand', and prev is NULL,
2125 * then it was the head of the list. Assume that position.
2128 lease_reference(&lease
->n_uid
, head
, MDL
);
2129 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2130 lease
->uid_len
, MDL
);
2131 lease_id_hash_add(lease_uid_hash
, lease
->uid
,
2132 lease
->uid_len
, lease
, MDL
);
2133 } else /* (prev != NULL) */ {
2134 if(prev
->n_uid
!= NULL
) {
2135 lease_reference(&lease
->n_uid
, prev
->n_uid
,
2137 lease_dereference(&prev
->n_uid
, MDL
);
2139 lease_reference(&prev
->n_uid
, lease
, MDL
);
2141 lease_dereference(&prev
, MDL
);
2145 lease_dereference(&cand
, MDL
);
2146 lease_dereference(&head
, MDL
);
2150 /* Delete the specified lease from the uid hash. */
2152 void uid_hash_delete (lease
)
2153 struct lease
*lease
;
2155 struct lease
*head
= (struct lease
*)0;
2158 /* If it's not in the hash, we have no work to do. */
2159 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
2161 lease_dereference (&lease
-> n_uid
, MDL
);
2165 /* If the lease we're freeing is at the head of the list,
2166 remove the hash table entry and add a new one with the
2167 next lease on the list (if there is one). */
2168 if (head
== lease
) {
2169 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2170 lease
->uid_len
, MDL
);
2171 if (lease
-> n_uid
) {
2172 lease_id_hash_add(lease_uid_hash
, lease
->n_uid
->uid
,
2173 lease
->n_uid
->uid_len
, lease
->n_uid
,
2175 lease_dereference (&lease
-> n_uid
, MDL
);
2178 /* Otherwise, look for the lease in the list of leases
2179 attached to the hash table entry, and remove it if
2181 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
2182 if (scan
-> n_uid
== lease
) {
2183 lease_dereference (&scan
-> n_uid
, MDL
);
2184 if (lease
-> n_uid
) {
2185 lease_reference (&scan
-> n_uid
,
2186 lease
-> n_uid
, MDL
);
2187 lease_dereference (&lease
-> n_uid
,
2194 lease_dereference (&head
, MDL
);
2197 /* Add the specified lease to the hardware address hash. */
2198 /* We don't add leases with infiniband addresses to the
2199 * hash as there isn't any address to hash on. */
2202 hw_hash_add(struct lease
*lease
)
2204 struct lease
*head
= NULL
;
2205 struct lease
*cand
= NULL
;
2206 struct lease
*prev
= NULL
;
2207 struct lease
*next
= NULL
;
2210 * If it's an infiniband address don't bother
2211 * as we don't have a useful address to hash.
2213 if ((lease
->hardware_addr
.hlen
== 1) &&
2214 (lease
->hardware_addr
.hbuf
[0] == HTYPE_INFINIBAND
))
2217 /* If it's not in the hash, just add it. */
2218 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2219 lease
-> hardware_addr
.hlen
, MDL
))
2220 lease_id_hash_add(lease_hw_addr_hash
,
2221 lease
->hardware_addr
.hbuf
,
2222 lease
->hardware_addr
.hlen
, lease
, MDL
);
2224 /* Otherwise, insert it into the list in order of its
2225 * preference for "resuming allocation to the client."
2227 * Because we don't have control of the hash bucket index
2228 * directly, we have to remove and re-insert the client
2229 * id into the hash if we're inserting onto the head.
2231 lease_reference(&cand
, head
, MDL
);
2232 while (cand
!= NULL
) {
2233 if (client_lease_preferred(cand
, lease
))
2237 lease_dereference(&prev
, MDL
);
2238 lease_reference(&prev
, cand
, MDL
);
2240 if (cand
->n_hw
!= NULL
)
2241 lease_reference(&next
, cand
->n_hw
, MDL
);
2243 lease_dereference(&cand
, MDL
);
2246 lease_reference(&cand
, next
, MDL
);
2247 lease_dereference(&next
, MDL
);
2251 /* If we want to insert 'before cand', and prev is NULL,
2252 * then it was the head of the list. Assume that position.
2255 lease_reference(&lease
->n_hw
, head
, MDL
);
2256 lease_id_hash_delete(lease_hw_addr_hash
,
2257 lease
->hardware_addr
.hbuf
,
2258 lease
->hardware_addr
.hlen
, MDL
);
2259 lease_id_hash_add(lease_hw_addr_hash
,
2260 lease
->hardware_addr
.hbuf
,
2261 lease
->hardware_addr
.hlen
,
2263 } else /* (prev != NULL) */ {
2264 if(prev
->n_hw
!= NULL
) {
2265 lease_reference(&lease
->n_hw
, prev
->n_hw
,
2267 lease_dereference(&prev
->n_hw
, MDL
);
2269 lease_reference(&prev
->n_hw
, lease
, MDL
);
2271 lease_dereference(&prev
, MDL
);
2275 lease_dereference(&cand
, MDL
);
2276 lease_dereference(&head
, MDL
);
2280 /* Delete the specified lease from the hardware address hash. */
2282 void hw_hash_delete (lease
)
2283 struct lease
*lease
;
2285 struct lease
*head
= (struct lease
*)0;
2286 struct lease
*next
= (struct lease
*)0;
2289 * If it's an infiniband address don't bother
2290 * as we don't have a useful address to hash.
2292 if ((lease
->hardware_addr
.hlen
== 1) &&
2293 (lease
->hardware_addr
.hbuf
[0] == HTYPE_INFINIBAND
))
2296 /* If it's not in the hash, we have no work to do. */
2297 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2298 lease
-> hardware_addr
.hlen
, MDL
)) {
2300 lease_dereference (&lease
-> n_hw
, MDL
);
2304 /* If the lease we're freeing is at the head of the list,
2305 remove the hash table entry and add a new one with the
2306 next lease on the list (if there is one). */
2307 if (head
== lease
) {
2308 lease_id_hash_delete(lease_hw_addr_hash
,
2309 lease
->hardware_addr
.hbuf
,
2310 lease
->hardware_addr
.hlen
, MDL
);
2312 lease_id_hash_add(lease_hw_addr_hash
,
2313 lease
->n_hw
->hardware_addr
.hbuf
,
2314 lease
->n_hw
->hardware_addr
.hlen
,
2316 lease_dereference(&lease
->n_hw
, MDL
);
2319 /* Otherwise, look for the lease in the list of leases
2320 attached to the hash table entry, and remove it if
2322 while (head
-> n_hw
) {
2323 if (head
-> n_hw
== lease
) {
2324 lease_dereference (&head
-> n_hw
, MDL
);
2325 if (lease
-> n_hw
) {
2326 lease_reference (&head
-> n_hw
,
2327 lease
-> n_hw
, MDL
);
2328 lease_dereference (&lease
-> n_hw
,
2333 lease_reference (&next
, head
-> n_hw
, MDL
);
2334 lease_dereference (&head
, MDL
);
2335 lease_reference (&head
, next
, MDL
);
2336 lease_dereference (&next
, MDL
);
2340 lease_dereference (&head
, MDL
);
2343 /* Write v4 leases to permanent storage. */
2344 int write_leases4(void) {
2346 struct shared_network
*s
;
2348 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2349 int num_written
= 0, i
;
2351 /* Write all the leases. */
2352 for (s
= shared_networks
; s
; s
= s
->next
) {
2353 for (p
= s
->pools
; p
; p
= p
->next
) {
2354 lptr
[FREE_LEASES
] = &p
->free
;
2355 lptr
[ACTIVE_LEASES
] = &p
->active
;
2356 lptr
[EXPIRED_LEASES
] = &p
->expired
;
2357 lptr
[ABANDONED_LEASES
] = &p
->abandoned
;
2358 lptr
[BACKUP_LEASES
] = &p
->backup
;
2359 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2361 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2362 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2364 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2365 #if !defined (DEBUG_DUMP_ALL_LEASES)
2366 if (l
->hardware_addr
.hlen
!= 0 || l
->uid_len
!= 0 ||
2367 l
->tsfp
!= 0 || l
->binding_state
!= FTS_FREE
)
2370 if (write_lease(l
) == 0)
2379 log_info ("Wrote %d leases to leases file.", num_written
);
2383 /* Write all interesting leases to permanent storage. */
2387 struct host_decl
*hp
;
2388 struct group_object
*gp
;
2389 struct hash_bucket
*hb
;
2391 struct collection
*colp
;
2395 /* write all the dynamically-created class declarations. */
2396 if (collections
->classes
) {
2397 numclasseswritten
= 0;
2398 for (colp
= collections
; colp
; colp
= colp
->next
) {
2399 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
2400 write_named_billing_class(
2401 (unsigned char *)cp
->name
,
2406 /* XXXJAB this number doesn't include subclasses... */
2407 log_info ("Wrote %d class decls to leases file.",
2412 /* Write all the dynamically-created group declarations. */
2413 if (group_name_hash
) {
2415 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
2416 for (hb
= group_name_hash
-> buckets
[i
];
2417 hb
; hb
= hb
-> next
) {
2418 gp
= (struct group_object
*)hb
-> value
;
2419 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
2420 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
2421 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
2422 if (!write_group (gp
))
2428 log_info ("Wrote %d group decls to leases file.", num_written
);
2431 /* Write all the deleted host declarations. */
2432 if (host_name_hash
) {
2434 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2435 for (hb
= host_name_hash
-> buckets
[i
];
2436 hb
; hb
= hb
-> next
) {
2437 hp
= (struct host_decl
*)hb
-> value
;
2438 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
2439 (hp
-> flags
& HOST_DECL_DELETED
))) {
2440 if (!write_host (hp
))
2446 log_info ("Wrote %d deleted host decls to leases file.",
2450 /* Write all the new, dynamic host declarations. */
2451 if (host_name_hash
) {
2453 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2454 for (hb
= host_name_hash
-> buckets
[i
];
2455 hb
; hb
= hb
-> next
) {
2456 hp
= (struct host_decl
*)hb
-> value
;
2457 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
2458 if (!write_host (hp
))
2463 log_info ("Wrote %d new dynamic host decls to leases file.",
2467 #if defined (FAILOVER_PROTOCOL)
2468 /* Write all the failover states. */
2469 if (!dhcp_failover_write_all_states ())
2473 switch (local_family
) {
2475 if (write_leases4() == 0)
2480 if (write_leases6() == 0)
2486 if (commit_leases() == 0)
2491 #if !defined (BINARY_LEASES)
2492 /* Unlink all the leases in the queue. */
2493 void lease_remove_all(struct lease
**lq
) {
2494 struct lease
*lp
, *ln
= NULL
;
2500 /* We simply derefernce the first item in the list. When
2501 * it's reference counter goes to zero it will be cleaned
2502 * and the reference counter
2504 * Get a pointer to the first item in the list and then
2505 * drop the reference from the queue pointer
2507 lease_reference(&lp
, *lq
, MDL
);
2508 lease_dereference(lq
, MDL
);
2511 /* if we have a next save a pointer to it and unlink it */
2513 lease_reference(&ln
, lp
->next
, MDL
);
2514 lease_dereference(&lp
->next
, MDL
);
2517 /* get rid of what we currently have */
2518 lease_dereference(&lp
, MDL
);
2520 /* move the next to the current and loop */
2523 } while (lp
!= NULL
);
2527 * This routine walks through a given lease queue (lq) looking
2528 * for comp. If it doesn't find the lease it is a fatal error
2529 * as it should be on the given queue. Once we find the lease
2530 * we can remove it from this list.
2532 void lease_remove(struct lease
**lq
, struct lease
*comp
)
2534 struct lease
*prev
, *lp
;
2537 for (lp
= *lq
; lp
!= NULL
; lp
= lp
->next
) {
2544 log_fatal("Lease with binding state %s not on its queue.",
2545 (comp
->binding_state
< 1 ||
2546 comp
->binding_state
> FTS_LAST
)
2548 : binding_state_names
[comp
->binding_state
- 1]);
2552 lease_dereference(&prev
->next
, MDL
);
2554 lease_reference(&prev
->next
, comp
->next
, MDL
);
2555 lease_dereference (&comp
->next
, MDL
);
2558 lease_dereference(lq
, MDL
);
2560 lease_reference(lq
, comp
->next
, MDL
);
2561 lease_dereference(&comp
->next
, MDL
);
2566 /* This routine inserts comp into lq in a sorted fashion.
2567 * The sort key is comp->sort_time, smaller values are
2568 * placed earlier in the list.
2570 void lease_insert(struct lease
**lq
, struct lease
*comp
)
2572 struct lease
*prev
, *lp
;
2573 static struct lease
**last_lq
= NULL
;
2574 static struct lease
*last_insert_point
= NULL
;
2576 /* This only works during server startup: during runtime, the last
2577 * lease may be dequeued in between calls. If the queue is the same
2578 * as was used previously, and the lease structure isn't (this is not
2579 * a re-queue), use that as a starting point for the insertion-sort.
2581 if ((server_starting
& SS_QFOLLOW
) && (lq
== last_lq
) &&
2582 (comp
!= last_insert_point
) &&
2583 (last_insert_point
->sort_time
<= comp
->sort_time
)) {
2584 prev
= last_insert_point
;
2591 /* Insertion sort the lease onto the appropriate queue. */
2592 for (; lp
!= NULL
; lp
= lp
->next
) {
2593 if (lp
->sort_time
>= comp
->sort_time
)
2600 lease_reference(&comp
->next
, prev
->next
, MDL
);
2601 lease_dereference(&prev
->next
, MDL
);
2603 lease_reference(&prev
->next
, comp
, MDL
);
2606 lease_reference (&comp
->next
, *lq
, MDL
);
2607 lease_dereference(lq
, MDL
);
2609 lease_reference(lq
, comp
, MDL
);
2611 last_insert_point
= comp
;
2618 /* In addition to placing this lease upon a lease queue depending on its
2619 * state, it also keeps track of the number of FREE and BACKUP leases in
2620 * existence, and sets the sort_time on the lease.
2622 * Sort_time is used in pool_timer() to determine when the lease will
2623 * bubble to the top of the list and be supersede_lease()'d into its next
2624 * state (possibly, if all goes well). Example, ACTIVE leases move to
2625 * EXPIRED state when the 'ends' value is reached, so that is its sort
2626 * time. Most queues are sorted by 'ends', since it is generally best
2627 * practice to re-use the oldest lease, to reduce address collision
2630 int lease_enqueue (struct lease
*comp
)
2632 LEASE_STRUCT_PTR lq
;
2634 /* No queue to put it on? */
2638 /* Figure out which queue it's going to. */
2639 switch (comp
-> binding_state
) {
2641 if (comp
->flags
& RESERVED_LEASE
) {
2642 lq
= &comp
->pool
->reserved
;
2644 lq
= &comp
->pool
->free
;
2645 comp
->pool
->free_leases
++;
2647 comp
-> sort_time
= comp
-> ends
;
2651 lq
= &comp
-> pool
-> active
;
2652 comp
-> sort_time
= comp
-> ends
;
2658 lq
= &comp
-> pool
-> expired
;
2659 #if defined(FAILOVER_PROTOCOL)
2660 /* In partner_down, tsfp is the time at which the lease
2661 * may be reallocated (stos+mclt). We can do that with
2662 * lease_mine_to_reallocate() anywhere between tsfp and
2663 * ends. But we prefer to wait until ends before doing it
2664 * automatically (choose the greater of the two). Note
2665 * that 'ends' is usually a historic timestamp in the
2666 * case of expired leases, is really only in the future
2667 * on released leases, and if we know a lease to be released
2668 * the peer might still know it to be active...in which case
2669 * it's possible the peer has renewed this lease, so avoid
2672 if (comp
->pool
->failover_peer
&&
2673 comp
->pool
->failover_peer
->me
.state
== partner_down
)
2674 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
2675 comp
->tsfp
: comp
->ends
;
2678 comp
->sort_time
= comp
->ends
;
2683 lq
= &comp
-> pool
-> abandoned
;
2684 comp
-> sort_time
= comp
-> ends
;
2688 if (comp
->flags
& RESERVED_LEASE
) {
2689 lq
= &comp
->pool
->reserved
;
2691 lq
= &comp
->pool
->backup
;
2692 comp
->pool
->backup_leases
++;
2694 comp
-> sort_time
= comp
-> ends
;
2698 log_error ("Lease with bogus binding state: %d",
2699 comp
-> binding_state
);
2700 #if defined (BINDING_STATE_DEBUG)
2706 LEASE_INSERTP(lq
, comp
);
2711 /* For a given lease, sort it onto the right list in its pool and put it
2712 in each appropriate hash, understanding that it's already by definition
2713 in lease_ip_addr_hash. */
2716 lease_instantiate(const void *key
, unsigned len
, void *object
)
2718 struct lease
*lease
= object
;
2719 struct class *class;
2720 /* XXX If the lease doesn't have a pool at this point, it's an
2721 XXX orphan, which we *should* keep around until it expires,
2722 XXX but which right now we just forget. */
2723 if (!lease
-> pool
) {
2724 lease_ip_hash_delete(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
2725 lease
->ip_addr
.len
, MDL
);
2726 return ISC_R_SUCCESS
;
2729 #if defined (FAILOVER_PROTOCOL)
2730 /* If the lease is in FTS_BACKUP but there is no peer, then the
2731 * pool must have been formerly configured for failover and
2732 * is now configured as standalone. This means we need to
2733 * move the lease to FTS_FREE to make it available. */
2734 if ((lease
->binding_state
== FTS_BACKUP
) &&
2735 (lease
->pool
->failover_peer
== NULL
)) {
2737 /* We aren't compiled for failover, so just move to FTS_FREE */
2738 if (lease
->binding_state
== FTS_BACKUP
) {
2740 lease
->binding_state
= FTS_FREE
;
2741 lease
->next_binding_state
= FTS_FREE
;
2742 lease
->rewind_binding_state
= FTS_FREE
;
2745 /* Put the lease on the right queue. Failure to queue is probably
2746 * due to a bogus binding state. In such a case, we claim success,
2747 * so that later leases in a hash_foreach are processed, but we
2748 * return early as we really don't want hw address hash entries or
2749 * other cruft to surround such a bogus entry.
2751 if (!lease_enqueue(lease
))
2752 return ISC_R_SUCCESS
;
2754 /* Record the lease in the uid hash if possible. */
2756 uid_hash_add (lease
);
2759 /* Record it in the hardware address hash if possible. */
2760 if (lease
-> hardware_addr
.hlen
) {
2761 hw_hash_add (lease
);
2764 /* If the lease has a billing class, set up the billing. */
2765 if (lease
-> billing_class
) {
2766 class = (struct class *)0;
2767 class_reference (&class, lease
-> billing_class
, MDL
);
2768 class_dereference (&lease
-> billing_class
, MDL
);
2769 /* If the lease is available for allocation, the billing
2770 is invalid, so we don't keep it. */
2771 if (lease
-> binding_state
== FTS_ACTIVE
||
2772 lease
-> binding_state
== FTS_EXPIRED
||
2773 lease
-> binding_state
== FTS_RELEASED
||
2774 lease
-> binding_state
== FTS_RESET
)
2775 bill_class (lease
, class);
2776 class_dereference (&class, MDL
);
2778 return ISC_R_SUCCESS
;
2781 /* Run expiry events on every pool. This is called on startup so that
2782 any expiry events that occurred after the server stopped and before it
2783 was restarted can be run. At the same time, if failover support is
2784 compiled in, we compute the balance of leases for the pool. */
2786 void expire_all_pools ()
2788 struct shared_network
*s
;
2792 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2794 /* Indicate that we are in the startup phase */
2795 server_starting
= SS_NOSYNC
| SS_QFOLLOW
;
2797 #if defined (BINARY_LEASES)
2798 /* set up the growth factors for the binary leases.
2799 * We use 100% for free, 50% for active and backup
2800 * 20% for expired, abandoned and reserved
2801 * but no less than 100, 50, and 20.
2803 for (s
= shared_networks
; s
; s
= s
-> next
) {
2804 for (p
= s
-> pools
; p
!= NULL
; p
= p
-> next
) {
2805 size_t num_f
= 100, num_a
= 50, num_e
= 20;
2806 if (p
->lease_count
> 100) {
2807 num_f
= p
->lease_count
;
2811 lc_init_growth(&p
->free
, num_f
);
2812 lc_init_growth(&p
->active
, num_a
);
2813 lc_init_growth(&p
->expired
, num_a
);
2814 lc_init_growth(&p
->abandoned
, num_e
);
2815 lc_init_growth(&p
->backup
, num_e
);
2816 lc_init_growth(&p
->reserved
, num_e
);
2821 /* First, go over the hash list and actually put all the leases
2822 on the appropriate lists. */
2823 lease_ip_hash_foreach(lease_ip_addr_hash
, lease_instantiate
);
2825 /* Loop through each pool in each shared network and call the
2826 * expiry routine on the pool. It is no longer safe to follow
2827 * the queue insertion point, as expiration of a lease can move
2828 * it between queues (and this may be the lease that function
2831 server_starting
&= ~SS_QFOLLOW
;
2832 for (s
= shared_networks
; s
; s
= s
-> next
) {
2833 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2836 p
-> lease_count
= 0;
2837 p
-> free_leases
= 0;
2838 p
-> backup_leases
= 0;
2840 lptr
[FREE_LEASES
] = &p
-> free
;
2841 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2842 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2843 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2844 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2845 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2847 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2848 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2850 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2852 if (l
-> ends
<= cur_time
) {
2853 if (l
->binding_state
== FTS_FREE
) {
2854 if (i
== FREE_LEASES
)
2856 else if (i
!= RESERVED_LEASES
)
2857 log_fatal("Impossible case "
2859 } else if (l
->binding_state
== FTS_BACKUP
) {
2860 if (i
== BACKUP_LEASES
)
2862 else if (i
!= RESERVED_LEASES
)
2863 log_fatal("Impossible case "
2867 #if defined (FAILOVER_PROTOCOL)
2868 if (p
-> failover_peer
&&
2869 l
-> tstp
> l
-> atsfp
&&
2870 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2871 l
-> desired_binding_state
= l
-> binding_state
;
2872 dhcp_failover_queue_update (l
, 1);
2880 /* turn off startup phase */
2881 server_starting
= 0;
2884 void dump_subnets ()
2887 struct shared_network
*s
;
2890 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2893 log_info ("Subnets:");
2894 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2895 log_debug (" Subnet %s", piaddr (n
-> net
));
2896 log_debug (" netmask %s",
2897 piaddr (n
-> netmask
));
2899 log_info ("Shared networks:");
2900 for (s
= shared_networks
; s
; s
= s
-> next
) {
2901 log_info (" %s", s
-> name
);
2902 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2903 lptr
[FREE_LEASES
] = &p
-> free
;
2904 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2905 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2906 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2907 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2908 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2910 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2911 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2913 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2921 HASH_FUNCTIONS(lease_ip
, const unsigned char *, struct lease
, lease_ip_hash_t
,
2922 lease_reference
, lease_dereference
, do_ip4_hash
)
2923 HASH_FUNCTIONS(lease_id
, const unsigned char *, struct lease
, lease_id_hash_t
,
2924 lease_reference
, lease_dereference
, do_id_hash
)
2925 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2926 host_reference
, host_dereference
, do_string_hash
)
2927 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2928 class_reference
, class_dereference
, do_string_hash
)
2930 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2931 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2932 extern struct hash_table
*dns_zone_hash
;
2933 extern struct interface_info
**interface_vector
;
2934 extern int interface_count
;
2935 dhcp_control_object_t
*dhcp_control_object
;
2936 extern struct hash_table
*auth_key_hash
;
2937 struct hash_table
*universe_hash
;
2938 struct universe
**universes
;
2939 int universe_count
, universe_max
;
2944 #if defined (COMPACT_LEASES)
2945 extern struct lease
*lease_hunks
;
2948 void free_everything(void)
2950 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2951 struct shared_network
*nc
= (struct shared_network
*)0,
2952 *nn
= (struct shared_network
*)0;
2953 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2954 struct lease
*lc
= NULL
, *ln
= NULL
, *ltemp
= NULL
;
2955 struct interface_info
*ic
= (struct interface_info
*)0,
2956 *in
= (struct interface_info
*)0;
2957 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2958 struct collection
*lp
;
2961 /* Get rid of all the hash tables. */
2962 if (host_hw_addr_hash
)
2963 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2964 host_hw_addr_hash
= 0;
2966 host_free_hash_table (&host_uid_hash
, MDL
);
2969 lease_id_free_hash_table (&lease_uid_hash
, MDL
);
2971 if (lease_ip_addr_hash
)
2972 lease_ip_free_hash_table (&lease_ip_addr_hash
, MDL
);
2973 lease_ip_addr_hash
= 0;
2974 if (lease_hw_addr_hash
)
2975 lease_id_free_hash_table (&lease_hw_addr_hash
, MDL
);
2976 lease_hw_addr_hash
= 0;
2978 host_free_hash_table (&host_name_hash
, MDL
);
2981 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2984 while (host_id_info
!= NULL
) {
2985 host_id_info_t
*tmp
;
2986 option_dereference(&host_id_info
->option
, MDL
);
2987 host_free_hash_table(&host_id_info
->values_hash
, MDL
);
2988 tmp
= host_id_info
->next
;
2989 dfree(host_id_info
, MDL
);
2994 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2998 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
3001 for (lp
= collections
; lp
; lp
= lp
-> next
) {
3002 if (lp
-> classes
) {
3003 class_reference (&cn
, lp
-> classes
, MDL
);
3006 class_reference (&cc
, cn
, MDL
);
3007 class_dereference (&cn
, MDL
);
3010 class_reference (&cn
, cc
-> nic
, MDL
);
3011 class_dereference (&cc
-> nic
, MDL
);
3013 group_dereference (&cc
-> group
, MDL
);
3015 class_free_hash_table (&cc
-> hash
, MDL
);
3016 cc
-> hash
= (struct hash_table
*)0;
3018 class_dereference (&cc
, MDL
);
3020 class_dereference (&lp
-> classes
, MDL
);
3024 if (interface_vector
) {
3025 for (i
= 0; i
< interface_count
; i
++) {
3026 if (interface_vector
[i
])
3027 interface_dereference (&interface_vector
[i
], MDL
);
3029 dfree (interface_vector
, MDL
);
3030 interface_vector
= 0;
3034 interface_reference (&in
, interfaces
, MDL
);
3037 interface_reference (&ic
, in
, MDL
);
3038 interface_dereference (&in
, MDL
);
3041 interface_reference (&in
, ic
-> next
, MDL
);
3042 interface_dereference (&ic
-> next
, MDL
);
3044 omapi_unregister_io_object ((omapi_object_t
*)ic
);
3045 if (ic
-> shared_network
) {
3046 if (ic
-> shared_network
-> interface
)
3047 interface_dereference
3048 (&ic
-> shared_network
-> interface
, MDL
);
3049 shared_network_dereference (&ic
-> shared_network
, MDL
);
3051 interface_dereference (&ic
, MDL
);
3053 interface_dereference (&interfaces
, MDL
);
3056 /* Subnets are complicated because of the extra links. */
3058 subnet_reference (&sn
, subnets
, MDL
);
3061 subnet_reference (&sc
, sn
, MDL
);
3062 subnet_dereference (&sn
, MDL
);
3064 if (sc
-> next_subnet
) {
3065 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
3066 subnet_dereference (&sc
-> next_subnet
, MDL
);
3068 if (sc
-> next_sibling
)
3069 subnet_dereference (&sc
-> next_sibling
, MDL
);
3070 if (sc
-> shared_network
)
3071 shared_network_dereference (&sc
-> shared_network
, MDL
);
3072 group_dereference (&sc
-> group
, MDL
);
3073 if (sc
-> interface
)
3074 interface_dereference (&sc
-> interface
, MDL
);
3075 subnet_dereference (&sc
, MDL
);
3077 subnet_dereference (&subnets
, MDL
);
3080 /* So are shared networks. */
3081 /* XXX: this doesn't work presently, but i'm ok just filtering
3082 * it out of the noise (you get a bigger spike on the real leaks).
3083 * It would be good to fix this, but it is not a "real bug," so not
3084 * today. This hack is incomplete, it doesn't trim out sub-values.
3086 if (shared_networks
) {
3087 shared_network_dereference (&shared_networks
, MDL
);
3088 /* This is the old method (tries to free memory twice, broken) */
3090 shared_network_reference (&nn
, shared_networks
, MDL
);
3093 shared_network_reference (&nc
, nn
, MDL
);
3094 shared_network_dereference (&nn
, MDL
);
3097 shared_network_reference (&nn
, nc
-> next
, MDL
);
3098 shared_network_dereference (&nc
-> next
, MDL
);
3103 pool_reference (&pn
, nc
-> pools
, MDL
);
3105 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
3108 pool_reference (&pc
, pn
, MDL
);
3109 pool_dereference (&pn
, MDL
);
3112 pool_reference (&pn
, pc
-> next
, MDL
);
3113 pool_dereference (&pc
-> next
, MDL
);
3116 lptr
[FREE_LEASES
] = &pc
-> free
;
3117 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
3118 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
3119 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
3120 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
3121 lptr
[RESERVED_LEASES
] = &pc
->reserved
;
3123 /* As (sigh) are leases. */
3124 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
3125 if (LEASE_NOT_EMPTYP(lptr
[i
])) {
3126 lease_reference(&ln
, LEASE_GET_FIRSTP(lptr
[i
]), MDL
);
3128 /* save a pointer to the current lease */
3129 lease_reference (&lc
, ln
, MDL
);
3130 lease_dereference (&ln
, MDL
);
3132 /* get the next lease if there is one */
3133 ltemp
= LEASE_GET_NEXTP(lptr
[i
], lc
);
3134 if (ltemp
!= NULL
) {
3135 lease_reference(&ln
, ltemp
, MDL
);
3138 /* remove the current lease from the queue */
3139 LEASE_REMOVEP(lptr
[i
], lc
);
3141 if (lc
-> billing_class
)
3142 class_dereference (&lc
-> billing_class
,
3145 free_lease_state (lc
-> state
, MDL
);
3146 lc
-> state
= (struct lease_state
*)0;
3148 lease_dereference (&lc
-> n_hw
, MDL
);
3150 lease_dereference (&lc
-> n_uid
, MDL
);
3151 lease_dereference (&lc
, MDL
);
3156 group_dereference (&pc
-> group
, MDL
);
3157 if (pc
-> shared_network
)
3158 shared_network_dereference (&pc
-> shared_network
,
3160 pool_dereference (&pc
, MDL
);
3162 pool_dereference (&nc
-> pools
, MDL
);
3164 /* Because of a circular reference, we need to nuke this
3166 group_dereference (&nc
-> group
, MDL
);
3167 shared_network_dereference (&nc
, MDL
);
3169 shared_network_dereference (&shared_networks
, MDL
);
3172 cancel_all_timeouts ();
3173 relinquish_timeouts ();
3174 #if defined(DELAYED_ACK)
3175 relinquish_ackqueue();
3178 group_dereference (&root_group
, MDL
);
3179 executable_statement_dereference (&default_classification_rules
, MDL
);
3181 shutdown_state
= shutdown_drop_omapi_connections
;
3182 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3183 shutdown_state
= shutdown_listeners
;
3184 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3185 shutdown_state
= shutdown_dhcp
;
3186 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3188 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
3190 universe_free_hash_table (&universe_hash
, MDL
);
3191 for (i
= 0; i
< universe_count
; i
++) {
3198 if (universes
[i
]) {
3199 if (universes
[i
]->name_hash
)
3200 option_name_free_hash_table(
3201 &universes
[i
]->name_hash
,
3203 if (universes
[i
]->code_hash
)
3204 option_code_free_hash_table(
3205 &universes
[i
]->code_hash
,
3208 if (universes
[i
] -> name
> (char *)&end
) {
3209 foo
.c
= universes
[i
] -> name
;
3212 if (universes
[i
] > (struct universe
*)&end
)
3213 dfree (universes
[i
], MDL
);
3217 dfree (universes
, MDL
);
3219 relinquish_free_lease_states ();
3220 relinquish_free_pairs ();
3221 relinquish_free_expressions ();
3222 relinquish_free_binding_values ();
3223 relinquish_free_option_caches ();
3224 relinquish_free_packets ();
3225 #if defined(COMPACT_LEASES)
3226 relinquish_lease_hunks ();
3228 relinquish_hash_bucket_hunks ();
3229 omapi_type_relinquish ();
3231 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */