3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2016 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
25 * https://www.isc.org/
30 #include "omapip/hash.h"
32 struct subnet
*subnets
;
33 struct shared_network
*shared_networks
;
34 host_hash_t
*host_hw_addr_hash
;
35 host_hash_t
*host_uid_hash
;
36 host_hash_t
*host_name_hash
;
37 lease_id_hash_t
*lease_uid_hash
;
38 lease_ip_hash_t
*lease_ip_addr_hash
;
39 lease_id_hash_t
*lease_hw_addr_hash
;
42 * We allow users to specify any option as a host identifier.
44 * Any host is uniquely identified by the combination of
45 * option type & option data.
47 * We expect people will only use a few types of options as host
48 * identifier. Because of this, we store a list with an entry for
49 * each option type. Each of these has a hash table, which contains
50 * hash of the option data.
52 * For v6 we also include a relay count - this specifies which
53 * relay to check for the requested option. As each different
54 * value of relays creates a new instance admins should use the
55 * same value across each option for all host-identifers.
56 * A value of 0 indicates that we aren't doing relay options
57 * and should simply look in the current option list.
59 typedef struct host_id_info
{
60 struct option
*option
;
61 host_hash_t
*values_hash
;
63 struct host_id_info
*next
;
66 static host_id_info_t
*host_id_info
= NULL
;
68 int numclasseswritten
;
70 omapi_object_type_t
*dhcp_type_host
;
72 isc_result_t
enter_class(cd
, dynamicp
, commit
)
77 if (!collections
-> classes
) {
78 /* A subclass with no parent is invalid. */
80 return DHCP_R_INVALIDARG
;
82 class_reference (&collections
-> classes
, cd
, MDL
);
83 } else if (cd
->name
!= NULL
) { /* regular class */
86 if (find_class(&c
, cd
->name
, MDL
) != ISC_R_NOTFOUND
) {
87 class_dereference(&c
, MDL
);
92 for (c
= collections
-> classes
;
93 c
-> nic
; c
= c
-> nic
)
95 class_reference (&c
-> nic
, cd
, MDL
);
98 if (dynamicp
&& commit
) {
99 const char *name
= cd
->name
;
102 name
= cd
->superclass
->name
;
105 write_named_billing_class ((const unsigned char *)name
, 0, cd
);
106 if (!commit_leases ())
107 return ISC_R_IOERROR
;
110 return ISC_R_SUCCESS
;
114 /* Variable to check if we're starting the server. The server will init as
115 * starting - but just to be safe start out as false to avoid triggering new
117 * XXX: There is actually a server_startup state...which is never entered...
121 static int server_starting
= 0;
123 static int find_uid_statement (struct executable_statement
*esp
,
126 struct executable_statement
**evp
= vp
;
128 if (esp
-> op
== supersede_option_statement
&&
129 esp
-> data
.option
&&
130 (esp
-> data
.option
-> option
-> universe
==
132 (esp
-> data
.option
-> option
-> code
==
133 DHO_DHCP_CLIENT_IDENTIFIER
)) {
135 log_error ("dhcp client identifier may not be %s",
136 "specified conditionally.");
137 } else if (!(*evp
)) {
138 executable_statement_reference (evp
, esp
, MDL
);
141 log_error ("only one dhcp client identifier may be %s",
149 static host_id_info_t
*
150 find_host_id_info(unsigned int option_code
, int relays
) {
153 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
154 if ((p
->option
->code
== option_code
) &&
155 (p
->relays
== relays
)) {
165 print_host(const void *name
, unsigned len
, void *value
) {
167 printf("--------------\n");
168 printf("name:'%s'\n", print_hex_1(len
, name
, 60));
169 printf("len:%d\n", len
);
170 h
= (struct host_decl
*)value
;
171 printf("host @%p is '%s'\n", h
, h
->name
);
172 return ISC_R_SUCCESS
;
176 hash_print_hosts(struct hash_table
*h
) {
177 hash_foreach(h
, print_host
);
178 printf("--------------\n");
183 change_host_uid(struct host_decl
*host
, const char *uid
, int len
) {
184 /* XXX: should consolidate this type of code throughout */
185 if (host_uid_hash
== NULL
) {
186 if (!host_new_hash(&host_uid_hash
, HOST_HASH_SIZE
, MDL
)) {
187 log_fatal("Can't allocate host/uid hash");
192 * Remove the old entry, if one exists.
194 if (host
->client_identifier
.data
!= NULL
) {
195 host_hash_delete(host_uid_hash
,
196 host
->client_identifier
.data
,
197 host
->client_identifier
.len
,
199 data_string_forget(&host
->client_identifier
, MDL
);
205 memset(&host
->client_identifier
, 0, sizeof(host
->client_identifier
));
206 host
->client_identifier
.len
= len
;
207 if (!buffer_allocate(&host
->client_identifier
.buffer
, len
, MDL
)) {
208 log_fatal("Can't allocate uid buffer");
210 host
->client_identifier
.data
= host
->client_identifier
.buffer
->data
;
211 memcpy((char *)host
->client_identifier
.data
, uid
, len
);
216 host_hash_add(host_uid_hash
, host
->client_identifier
.data
,
217 host
->client_identifier
.len
, host
, MDL
);
220 isc_result_t
enter_host (hd
, dynamicp
, commit
)
221 struct host_decl
*hd
;
225 struct host_decl
*hp
= (struct host_decl
*)0;
226 struct host_decl
*np
= (struct host_decl
*)0;
227 struct executable_statement
*esp
;
228 host_id_info_t
*h_id_info
;
230 if (!host_name_hash
) {
231 if (!host_new_hash(&host_name_hash
, HOST_HASH_SIZE
, MDL
))
232 log_fatal ("Can't allocate host name hash");
233 host_hash_add (host_name_hash
,
234 (unsigned char *)hd
-> name
,
235 strlen (hd
-> name
), hd
, MDL
);
237 host_hash_lookup (&hp
, host_name_hash
,
238 (unsigned char *)hd
-> name
,
239 strlen (hd
-> name
), MDL
);
241 /* If it's deleted, we can supersede it. */
242 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
243 host_hash_delete (host_name_hash
,
244 (unsigned char *)hd
-> name
,
245 strlen (hd
-> name
), MDL
);
246 /* If the old entry wasn't dynamic, then we
247 always have to keep the deletion. */
248 if (hp
-> flags
& HOST_DECL_STATIC
) {
249 hd
-> flags
|= HOST_DECL_STATIC
;
251 host_dereference (&hp
, MDL
);
254 /* If we are updating an existing host declaration, we
255 can just delete it and add it again. */
256 if (hp
&& hp
== hd
) {
257 host_dereference (&hp
, MDL
);
259 if (!write_host (hd
))
260 return ISC_R_IOERROR
;
261 hd
-> flags
&= ~HOST_DECL_DELETED
;
264 /* If there isn't already a host decl matching this
265 address, add it to the hash table. */
267 host_hash_add (host_name_hash
,
268 (unsigned char *)hd
-> name
,
269 strlen (hd
-> name
), hd
, MDL
);
271 /* XXX actually, we have to delete the old one
272 XXX carefully and replace it. Not done yet. */
273 host_dereference (&hp
, MDL
);
279 host_dereference (&hd
-> n_ipaddr
, MDL
);
282 hd
-> type
= dhcp_type_host
;
284 if (hd
-> interface
.hlen
) {
285 if (!host_hw_addr_hash
) {
286 if (!host_new_hash(&host_hw_addr_hash
,
287 HOST_HASH_SIZE
, MDL
))
288 log_fatal ("Can't allocate host/hw hash");
290 /* If there isn't already a host decl matching this
291 address, add it to the hash table. */
292 host_hash_lookup (&hp
, host_hw_addr_hash
,
293 hd
-> interface
.hbuf
,
294 hd
-> interface
.hlen
, MDL
);
297 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
298 hd
-> interface
.hlen
, hd
, MDL
);
300 /* If there was already a host declaration for
301 this hardware address, add this one to the
303 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
305 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
306 host_dereference (&hp
, MDL
);
310 /* See if there's a statement that sets the client identifier.
311 This is a kludge - the client identifier really shouldn't be
312 set with an executable statement. */
314 if (executable_statement_foreach (hd
->group
->statements
,
315 find_uid_statement
, &esp
, 0)) {
316 (void) evaluate_option_cache (&hd
->client_identifier
,
317 NULL
, NULL
, NULL
, NULL
, NULL
,
319 esp
->data
.option
, MDL
);
322 /* If we got a client identifier, hash this entry by
323 client identifier. */
324 if (hd
-> client_identifier
.len
) {
325 /* If there's no uid hash, make one; otherwise, see if
326 there's already an entry in the hash for this host. */
327 if (!host_uid_hash
) {
328 if (!host_new_hash(&host_uid_hash
,
329 HOST_HASH_SIZE
, MDL
))
330 log_fatal ("Can't allocate host/uid hash");
332 host_hash_add (host_uid_hash
,
333 hd
-> client_identifier
.data
,
334 hd
-> client_identifier
.len
,
337 /* If there's already a host declaration for this
338 client identifier, add this one to the end of the
339 list. Otherwise, add it to the hash table. */
340 if (host_hash_lookup (&hp
, host_uid_hash
,
341 hd
-> client_identifier
.data
,
342 hd
-> client_identifier
.len
,
344 /* Don't link it in twice... */
346 for (np
= hp
; np
-> n_ipaddr
;
347 np
= np
-> n_ipaddr
) {
352 host_reference (&np
-> n_ipaddr
,
355 host_dereference (&hp
, MDL
);
357 host_hash_add (host_uid_hash
,
358 hd
-> client_identifier
.data
,
359 hd
-> client_identifier
.len
,
367 * If we use an option as our host identifier, record it here.
369 if (hd
->host_id_option
!= NULL
) {
371 * Look for the host identifier information for this option,
372 * and create a new entry if there is none.
374 h_id_info
= find_host_id_info(hd
->host_id_option
->code
,
376 if (h_id_info
== NULL
) {
377 h_id_info
= dmalloc(sizeof(*h_id_info
), MDL
);
378 if (h_id_info
== NULL
) {
379 log_fatal("No memory for host-identifier "
380 "option information.");
382 option_reference(&h_id_info
->option
,
383 hd
->host_id_option
, MDL
);
384 if (!host_new_hash(&h_id_info
->values_hash
,
385 HOST_HASH_SIZE
, MDL
)) {
386 log_fatal("No memory for host-identifier "
389 h_id_info
->relays
= hd
->relays
;
390 h_id_info
->next
= host_id_info
;
391 host_id_info
= h_id_info
;
394 if (host_hash_lookup(&hp
, h_id_info
->values_hash
,
395 hd
->host_id
.data
, hd
->host_id
.len
, MDL
)) {
397 * If this option is already present, then add
398 * this host to the list in n_ipaddr, unless
399 * we have already done so previously.
401 * XXXSK: This seems scary to me, but I don't
402 * fully understand how these are used.
403 * Shouldn't there be multiple lists, or
404 * maybe we should just forbid duplicates?
408 while (np
->n_ipaddr
!= NULL
) {
412 host_reference(&np
->n_ipaddr
, hd
, MDL
);
415 host_dereference(&hp
, MDL
);
417 host_hash_add(h_id_info
->values_hash
,
424 if (dynamicp
&& commit
) {
425 if (!write_host (hd
))
426 return ISC_R_IOERROR
;
427 if (!commit_leases ())
428 return ISC_R_IOERROR
;
431 return ISC_R_SUCCESS
;
435 isc_result_t
delete_class (cp
, commit
)
439 cp
->flags
|= CLASS_DECL_DELETED
;
441 /* do the write first as we won't be leaving it in any data
442 structures, unlike the host objects */
445 write_named_billing_class ((unsigned char *)cp
->name
, 0, cp
);
446 if (!commit_leases ())
447 return ISC_R_IOERROR
;
451 * If this is a subclass remove it from the class's hash table
453 if (cp
->superclass
) {
454 class_hash_delete(cp
->superclass
->hash
,
455 (const char *)cp
->hash_string
.data
,
460 /* remove from collections */
463 return ISC_R_SUCCESS
;
467 isc_result_t
delete_host (hd
, commit
)
468 struct host_decl
*hd
;
471 struct host_decl
*hp
= (struct host_decl
*)0;
472 struct host_decl
*np
= (struct host_decl
*)0;
473 struct host_decl
*foo
;
474 int hw_head
= 0, uid_head
= 1;
476 /* Don't need to do it twice. */
477 if (hd
-> flags
& HOST_DECL_DELETED
)
478 return ISC_R_SUCCESS
;
480 /* But we do need to do it once! :') */
481 hd
-> flags
|= HOST_DECL_DELETED
;
483 if (hd
-> interface
.hlen
) {
484 if (host_hw_addr_hash
) {
485 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
486 hd
-> interface
.hbuf
,
487 hd
-> interface
.hlen
, MDL
)) {
489 host_hash_delete (host_hw_addr_hash
,
490 hd
-> interface
.hbuf
,
491 hd
-> interface
.hlen
, MDL
);
494 np
= (struct host_decl
*)0;
495 foo
= (struct host_decl
*)0;
496 host_reference (&foo
, hp
, MDL
);
501 host_dereference (&np
, MDL
);
502 host_reference (&np
, foo
, MDL
);
503 host_dereference (&foo
, MDL
);
505 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
509 host_dereference (&np
-> n_ipaddr
, MDL
);
511 host_reference (&np
-> n_ipaddr
,
512 hd
-> n_ipaddr
, MDL
);
513 host_dereference (&foo
, MDL
);
516 host_dereference (&np
, MDL
);
518 host_dereference (&hp
, MDL
);
523 /* If we got a client identifier, hash this entry by
524 client identifier. */
525 if (hd
-> client_identifier
.len
) {
527 if (host_hash_lookup (&hp
, host_uid_hash
,
528 hd
-> client_identifier
.data
,
529 hd
-> client_identifier
.len
, MDL
)) {
531 host_hash_delete (host_uid_hash
,
532 hd
-> client_identifier
.data
,
533 hd
-> client_identifier
.len
, MDL
);
536 np
= (struct host_decl
*)0;
537 foo
= (struct host_decl
*)0;
538 host_reference (&foo
, hp
, MDL
);
543 host_dereference (&np
, MDL
);
544 host_reference (&np
, foo
, MDL
);
545 host_dereference (&foo
, MDL
);
547 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
551 host_dereference (&np
-> n_ipaddr
, MDL
);
553 host_reference (&np
-> n_ipaddr
,
554 hd
-> n_ipaddr
, MDL
);
555 host_dereference (&foo
, MDL
);
558 host_dereference (&np
, MDL
);
560 host_dereference (&hp
, MDL
);
565 if (hd
->host_id_option
!= NULL
) {
566 option_dereference(&hd
->host_id_option
, MDL
);
567 data_string_forget(&hd
->host_id
, MDL
);
570 if (hd
-> n_ipaddr
) {
571 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
574 hd
-> n_ipaddr
-> client_identifier
.data
,
575 hd
-> n_ipaddr
-> client_identifier
.len
,
576 hd
-> n_ipaddr
, MDL
);
578 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
579 host_hash_add (host_hw_addr_hash
,
580 hd
-> n_ipaddr
-> interface
.hbuf
,
581 hd
-> n_ipaddr
-> interface
.hlen
,
582 hd
-> n_ipaddr
, MDL
);
584 host_dereference (&hd
-> n_ipaddr
, MDL
);
587 if (host_name_hash
) {
588 if (host_hash_lookup (&hp
, host_name_hash
,
589 (unsigned char *)hd
-> name
,
590 strlen (hd
-> name
), MDL
)) {
591 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
592 host_hash_delete (host_name_hash
,
593 (unsigned char *)hd
-> name
,
594 strlen (hd
-> name
), MDL
);
596 host_dereference (&hp
, MDL
);
601 if (!write_host (hd
))
602 return ISC_R_IOERROR
;
603 if (!commit_leases ())
604 return ISC_R_IOERROR
;
606 return ISC_R_SUCCESS
;
609 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
610 const unsigned char *haddr
, unsigned hlen
,
611 const char *file
, int line
)
614 #if defined(LDAP_CONFIGURATION)
617 if ((ret
= find_haddr_in_ldap (hp
, htype
, hlen
, haddr
, file
, line
)))
623 memcpy (&h
.hbuf
[1], haddr
, hlen
);
625 return host_hash_lookup (hp
, host_hw_addr_hash
,
626 h
.hbuf
, h
.hlen
, file
, line
);
629 int find_hosts_by_uid (struct host_decl
**hp
,
630 const unsigned char *data
, unsigned len
,
631 const char *file
, int line
)
633 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
637 find_hosts_by_option(struct host_decl
**hp
,
638 struct packet
*packet
,
639 struct option_state
*opt_state
,
640 const char *file
, int line
) {
642 struct option_cache
*oc
;
643 struct data_string data
;
645 struct packet
*relay_packet
;
646 struct option_state
*relay_state
;
648 #if defined(LDAP_CONFIGURATION)
649 if ((found
= find_client_in_ldap (hp
, packet
, opt_state
, file
, line
)))
653 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
654 relay_packet
= packet
;
655 relay_state
= opt_state
;
657 /* If this option block is for a relay (relays != 0)
658 * and we are processing the main options and not
659 * options from the IA (packet->options == opt_state)
660 * try to find the proper relay
662 if ((p
->relays
!= 0) && (packet
->options
== opt_state
)) {
665 (relay_packet
->dhcpv6_container_packet
!= NULL
)) {
667 relay_packet
->dhcpv6_container_packet
;
670 /* We wanted a specific relay but were
671 * unable to find it */
672 if ((p
->relays
<= MAX_V6RELAY_HOPS
) && (i
!= 0))
675 relay_state
= relay_packet
->options
;
678 oc
= lookup_option(p
->option
->universe
,
679 relay_state
, p
->option
->code
);
681 memset(&data
, 0, sizeof(data
));
683 if (!evaluate_option_cache(&data
, relay_packet
, NULL
,
684 NULL
, relay_state
, NULL
,
687 log_error("Error evaluating option cache");
691 found
= host_hash_lookup(hp
, p
->values_hash
,
695 data_string_forget(&data
, MDL
);
705 /* More than one host_decl can be returned by find_hosts_by_haddr or
706 find_hosts_by_uid, and each host_decl can have multiple addresses.
707 Loop through the list of hosts, and then for each host, through the
708 list of addresses, looking for an address that's in the same shared
709 network as the one specified. Store the matching address through
710 the addr pointer, update the host pointer to point at the host_decl
711 that matched, and return the subnet that matched. */
713 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
714 struct iaddr
*addr
, struct shared_network
*share
)
717 struct iaddr ip_address
;
718 struct host_decl
*hp
;
719 struct data_string fixed_addr
;
721 memset (&fixed_addr
, 0, sizeof fixed_addr
);
723 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
724 if (!hp
-> fixed_addr
)
726 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
728 (struct client_state
*)0,
729 (struct option_state
*)0,
730 (struct option_state
*)0,
732 hp
-> fixed_addr
, MDL
))
734 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
736 memcpy (ip_address
.iabuf
,
737 fixed_addr
.data
+ i
, 4);
738 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
739 struct host_decl
*tmp
= (struct host_decl
*)0;
741 /* This is probably not necessary, but
742 just in case *host is the only reference
743 to that host declaration, make a temporary
744 reference so that dereferencing it doesn't
745 dereference hp out from under us. */
746 host_reference (&tmp
, *host
, MDL
);
747 host_dereference (host
, MDL
);
748 host_reference (host
, hp
, MDL
);
749 host_dereference (&tmp
, MDL
);
750 data_string_forget (&fixed_addr
, MDL
);
754 data_string_forget (&fixed_addr
, MDL
);
759 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
761 struct iaddr low
, high
;
762 struct subnet
*subnet
;
764 struct lease
**lpchain
;
766 #if defined(COMPACT_LEASES)
767 struct lease
*address_range
;
770 unsigned min
, max
, i
, num_addrs
;
771 char lowbuf
[16], highbuf
[16], netbuf
[16];
772 struct shared_network
*share
= subnet
-> shared_network
;
773 struct lease
*lt
= (struct lease
*)0;
774 #if !defined(COMPACT_LEASES)
778 /* All subnets should have attached shared network structures. */
780 strcpy (netbuf
, piaddr (subnet
-> net
));
781 log_fatal ("No shared network for network %s (%s)",
782 netbuf
, piaddr (subnet
-> netmask
));
785 /* Initialize the hash table if it hasn't been done yet. */
786 if (!lease_uid_hash
) {
787 if (!lease_id_new_hash(&lease_uid_hash
, LEASE_HASH_SIZE
, MDL
))
788 log_fatal ("Can't allocate lease/uid hash");
790 if (!lease_ip_addr_hash
) {
791 if (!lease_ip_new_hash(&lease_ip_addr_hash
, LEASE_HASH_SIZE
,
793 log_fatal ("Can't allocate lease/ip hash");
795 if (!lease_hw_addr_hash
) {
796 if (!lease_id_new_hash(&lease_hw_addr_hash
, LEASE_HASH_SIZE
,
798 log_fatal ("Can't allocate lease/hw hash");
801 /* Make sure that high and low addresses are in this subnet. */
802 if (!addr_eq(subnet
->net
, subnet_number(low
, subnet
->netmask
))) {
803 strcpy(lowbuf
, piaddr(low
));
804 strcpy(netbuf
, piaddr(subnet
->net
));
805 log_fatal("bad range, address %s not in subnet %s netmask %s",
806 lowbuf
, netbuf
, piaddr(subnet
->netmask
));
809 if (!addr_eq(subnet
->net
, subnet_number(high
, subnet
->netmask
))) {
810 strcpy(highbuf
, piaddr(high
));
811 strcpy(netbuf
, piaddr(subnet
->net
));
812 log_fatal("bad range, address %s not in subnet %s netmask %s",
813 highbuf
, netbuf
, piaddr(subnet
->netmask
));
816 /* Get the high and low host addresses... */
817 max
= host_addr (high
, subnet
-> netmask
);
818 min
= host_addr (low
, subnet
-> netmask
);
820 /* Allow range to be specified high-to-low as well as low-to-high. */
823 min
= host_addr (high
, subnet
-> netmask
);
826 /* get the number of addresses we want, and add it to the pool info
827 * this value is only for use when setting up lease chains and will
828 * be overwritten when expire_all_pools is run
830 num_addrs
= max
- min
+ 1;
831 #if defined (BINARY_LEASES)
832 pool
->lease_count
+= num_addrs
;
835 /* Get a lease structure for each address in the range. */
836 #if defined (COMPACT_LEASES)
837 s
= (num_addrs
+ 1) * sizeof (struct lease
);
838 /* Check unsigned overflow in new_leases().
839 With 304 byte lease structure (x64_86), this happens at
840 range 10.0.0.0 10.215.148.52; */
841 if (((s
% sizeof (struct lease
)) != 0) ||
842 ((s
/ sizeof (struct lease
)) != (num_addrs
+ 1))) {
843 strcpy (lowbuf
, piaddr (low
));
844 strcpy (highbuf
, piaddr (high
));
845 parse_warn (cfile
, "%s-%s is an overly large address range.",
847 log_fatal ("Memory overflow.");
849 address_range
= new_leases (num_addrs
, MDL
);
850 if (!address_range
) {
851 strcpy (lowbuf
, piaddr (low
));
852 strcpy (highbuf
, piaddr (high
));
853 log_fatal ("No memory for address range %s-%s.",
858 /* Fill out the lease structures with some minimal information. */
859 for (i
= 0; i
< num_addrs
; i
++) {
860 struct lease
*lp
= (struct lease
*)0;
861 #if defined (COMPACT_LEASES)
862 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
864 0, sizeof (struct lease
), MDL
);
865 lease_reference (&lp
, &address_range
[i
], MDL
);
867 status
= lease_allocate (&lp
, MDL
);
868 if (status
!= ISC_R_SUCCESS
)
869 log_fatal ("No memory for lease %s: %s",
870 piaddr (ip_addr (subnet
-> net
,
873 isc_result_totext (status
));
875 lp
->ip_addr
= ip_addr(subnet
->net
, subnet
->netmask
, i
+ min
);
876 lp
->starts
= MIN_TIME
;
878 subnet_reference(&lp
->subnet
, subnet
, MDL
);
879 pool_reference(&lp
->pool
, pool
, MDL
);
880 lp
->binding_state
= FTS_FREE
;
881 lp
->next_binding_state
= FTS_FREE
;
882 lp
->rewind_binding_state
= FTS_FREE
;
885 /* Remember the lease in the IP address hash. */
886 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
889 "lease %s is declared twice!",
890 piaddr (lp
-> ip_addr
));
892 pool_reference (<
-> pool
, pool
, MDL
);
893 lease_dereference (<
, MDL
);
895 lease_ip_hash_add(lease_ip_addr_hash
,
896 lp
->ip_addr
.iabuf
, lp
->ip_addr
.len
,
898 /* Put the lease on the chain for the caller. */
901 lease_reference (&lp
-> next
, *lpchain
, MDL
);
902 lease_dereference (lpchain
, MDL
);
904 lease_reference (lpchain
, lp
, MDL
);
906 lease_dereference (&lp
, MDL
);
910 int find_subnet (struct subnet
**sp
,
911 struct iaddr addr
, const char *file
, int line
)
915 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
917 if (addr
.len
!= rv
->netmask
.len
)
920 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
921 if (subnet_reference (sp
, rv
,
922 file
, line
) != ISC_R_SUCCESS
)
930 int find_grouped_subnet (struct subnet
**sp
,
931 struct shared_network
*share
, struct iaddr addr
,
932 const char *file
, int line
)
936 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
938 if (addr
.len
!= rv
->netmask
.len
)
941 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
942 if (subnet_reference (sp
, rv
,
943 file
, line
) != ISC_R_SUCCESS
)
951 /* XXX: could speed up if everyone had a prefix length */
953 subnet_inner_than(const struct subnet
*subnet
,
954 const struct subnet
*scan
,
957 if (subnet
->net
.len
!= scan
->net
.len
)
960 if (addr_eq(subnet_number(subnet
->net
, scan
->netmask
), scan
->net
) ||
961 addr_eq(subnet_number(scan
->net
, subnet
->netmask
), subnet
->net
)) {
962 char n1buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
964 for (i
= 0; i
< 128; i
++)
965 if (subnet
->netmask
.iabuf
[3 - (i
>> 3)]
968 for (j
= 0; j
< 128; j
++)
969 if (scan
->netmask
.iabuf
[3 - (j
>> 3)] &
973 strcpy(n1buf
, piaddr(subnet
->net
));
974 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
976 piaddr(scan
->net
), 32 - j
);
984 /* Enter a new subnet into the subnet list. */
985 void enter_subnet (subnet
)
986 struct subnet
*subnet
;
988 struct subnet
*scan
= (struct subnet
*)0;
989 struct subnet
*next
= (struct subnet
*)0;
990 struct subnet
*prev
= (struct subnet
*)0;
992 /* Check for duplicates... */
994 subnet_reference (&next
, subnets
, MDL
);
996 subnet_reference (&scan
, next
, MDL
);
997 subnet_dereference (&next
, MDL
);
999 /* When we find a conflict, make sure that the
1000 subnet with the narrowest subnet mask comes
1002 if (subnet_inner_than (subnet
, scan
, 1)) {
1004 if (prev
-> next_subnet
)
1005 subnet_dereference (&prev
-> next_subnet
, MDL
);
1006 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
1007 subnet_dereference (&prev
, MDL
);
1009 subnet_dereference (&subnets
, MDL
);
1010 subnet_reference (&subnets
, subnet
, MDL
);
1012 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
1013 subnet_dereference (&scan
, MDL
);
1016 subnet_reference (&prev
, scan
, MDL
);
1017 subnet_dereference (&scan
, MDL
);
1020 subnet_dereference (&prev
, MDL
);
1022 /* XXX use the BSD radix tree code instead of a linked list. */
1024 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
1025 subnet_dereference (&subnets
, MDL
);
1027 subnet_reference (&subnets
, subnet
, MDL
);
1030 /* Enter a new shared network into the shared network list. */
1032 void enter_shared_network (share
)
1033 struct shared_network
*share
;
1035 if (shared_networks
) {
1036 shared_network_reference (&share
-> next
,
1037 shared_networks
, MDL
);
1038 shared_network_dereference (&shared_networks
, MDL
);
1040 shared_network_reference (&shared_networks
, share
, MDL
);
1043 void new_shared_network_interface (cfile
, share
, name
)
1044 struct parse
*cfile
;
1045 struct shared_network
*share
;
1048 struct interface_info
*ip
;
1049 isc_result_t status
;
1051 if (share
-> interface
) {
1053 "A subnet or shared network can't be connected %s",
1054 "to two interfaces.");
1058 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
1059 if (!strcmp (ip
-> name
, name
))
1062 status
= interface_allocate (&ip
, MDL
);
1063 if (status
!= ISC_R_SUCCESS
)
1064 log_fatal ("new_shared_network_interface %s: %s",
1065 name
, isc_result_totext (status
));
1066 if (strlen (name
) > sizeof ip
-> name
) {
1067 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
1068 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
1070 strcpy (ip
-> name
, name
);
1072 interface_reference (&ip
-> next
, interfaces
, MDL
);
1073 interface_dereference (&interfaces
, MDL
);
1075 interface_reference (&interfaces
, ip
, MDL
);
1076 ip
-> flags
= INTERFACE_REQUESTED
;
1077 /* XXX this is a reference loop. */
1078 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
1079 interface_reference (&share
-> interface
, ip
, MDL
);
1083 /* Enter a lease into the system. This is called by the parser each
1084 time it reads in a new lease. If the subnet for that lease has
1085 already been read in (usually the case), just update that lease;
1086 otherwise, allocate temporary storage for the lease and keep it around
1087 until we're done reading in the config file. */
1089 void enter_lease (lease
)
1090 struct lease
*lease
;
1092 struct lease
*comp
= (struct lease
*)0;
1094 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
1095 if (!comp
-> pool
) {
1096 log_error ("undeclared lease found in database: %s",
1097 piaddr (lease
-> ip_addr
));
1099 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
1102 subnet_reference (&lease
-> subnet
,
1103 comp
-> subnet
, MDL
);
1104 lease_ip_hash_delete(lease_ip_addr_hash
,
1105 lease
->ip_addr
.iabuf
, lease
->ip_addr
.len
,
1107 lease_dereference (&comp
, MDL
);
1110 /* The only way a lease can get here without a subnet is if it's in
1111 the lease file, but not in the dhcpd.conf file. In this case, we
1112 *should* keep it around until it's expired, but never reallocate it
1113 or renew it. Currently, to maintain consistency, we are not doing
1115 XXX fix this so that the lease is kept around until it expires.
1116 XXX this will be important in IPv6 with addresses that become
1117 XXX non-renewable as a result of a renumbering event. */
1119 if (!lease
-> subnet
) {
1120 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
1123 lease_ip_hash_add(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
1124 lease
->ip_addr
.len
, lease
, MDL
);
1127 /* Replace the data in an existing lease with the data in a new lease;
1128 adjust hash tables to suit, and insertion sort the lease into the
1129 list of leases by expiry time so that we can always find the oldest
1132 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
, from_pool
)
1133 struct lease
*comp
, *lease
;
1139 LEASE_STRUCT_PTR lq
;
1141 #if defined (FAILOVER_PROTOCOL)
1142 int do_pool_check
= 0;
1144 /* We must commit leases before sending updates regarding them
1145 to failover peers. It is, therefore, an error to set pimmediate
1147 if (pimmediate
&& !commit
)
1150 /* If there is no sample lease, just do the move. */
1154 /* Static leases are not currently kept in the database... */
1155 if (lease
-> flags
& STATIC_LEASE
)
1158 /* If the existing lease hasn't expired and has a different
1159 unique identifier or, if it doesn't have a unique
1160 identifier, a different hardware address, then the two
1161 leases are in conflict. If the existing lease has a uid
1162 and the new one doesn't, but they both have the same
1163 hardware address, and dynamic bootp is allowed on this
1164 lease, then we allow that, in case a dynamic BOOTP lease is
1165 requested *after* a DHCP lease has been assigned. */
1167 if (lease
-> binding_state
!= FTS_ABANDONED
&&
1168 lease
-> next_binding_state
!= FTS_ABANDONED
&&
1169 comp
-> binding_state
== FTS_ACTIVE
&&
1170 (((comp
-> uid
&& lease
-> uid
) &&
1171 (comp
-> uid_len
!= lease
-> uid_len
||
1172 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
1174 ((comp
-> hardware_addr
.hlen
!=
1175 lease
-> hardware_addr
.hlen
) ||
1176 memcmp (comp
-> hardware_addr
.hbuf
,
1177 lease
-> hardware_addr
.hbuf
,
1178 comp
-> hardware_addr
.hlen
))))) {
1179 log_error ("Lease conflict at %s",
1180 piaddr (comp
-> ip_addr
));
1183 /* If there's a Unique ID, dissociate it from the hash
1184 table and free it if necessary. */
1186 uid_hash_delete(comp
);
1187 if (comp
->uid
!= comp
->uid_buf
) {
1188 dfree(comp
->uid
, MDL
);
1192 comp
-> uid
= (unsigned char *)0;
1195 /* If there's a hardware address, remove the lease from its
1196 * old position in the hash bucket's ordered list.
1198 if (comp
->hardware_addr
.hlen
)
1199 hw_hash_delete(comp
);
1201 /* If the lease has been billed to a class, remove the billing. */
1202 if (comp
-> billing_class
!= lease
-> billing_class
) {
1203 if (comp
->billing_class
)
1205 if (lease
-> billing_class
)
1206 bill_class (comp
, lease
-> billing_class
);
1209 /* Copy the data files, but not the linkages. */
1210 comp
-> starts
= lease
-> starts
;
1212 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
1213 memcpy (comp
-> uid_buf
,
1214 lease
-> uid
, lease
-> uid_len
);
1215 comp
-> uid
= &comp
-> uid_buf
[0];
1216 comp
-> uid_max
= sizeof comp
-> uid_buf
;
1217 comp
-> uid_len
= lease
-> uid_len
;
1218 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
1219 comp
-> uid
= lease
-> uid
;
1220 comp
-> uid_max
= lease
-> uid_max
;
1221 lease
-> uid
= (unsigned char *)0;
1222 lease
-> uid_max
= 0;
1223 comp
-> uid_len
= lease
-> uid_len
;
1224 lease
-> uid_len
= 0;
1226 log_fatal ("corrupt lease uid."); /* XXX */
1229 comp
-> uid
= (unsigned char *)0;
1230 comp
-> uid_len
= comp
-> uid_max
= 0;
1233 host_dereference (&comp
-> host
, MDL
);
1234 host_reference (&comp
-> host
, lease
-> host
, MDL
);
1235 comp
-> hardware_addr
= lease
-> hardware_addr
;
1237 binding_scope_dereference (&comp
-> scope
, MDL
);
1238 if (lease
-> scope
) {
1239 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
1240 binding_scope_dereference (&lease
-> scope
, MDL
);
1243 if (comp
-> agent_options
)
1244 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
1245 if (lease
-> agent_options
) {
1246 /* Only retain the agent options if the lease is still
1247 affirmatively associated with a client. */
1248 if (lease
-> next_binding_state
== FTS_ACTIVE
||
1249 lease
-> next_binding_state
== FTS_EXPIRED
)
1250 option_chain_head_reference (&comp
-> agent_options
,
1251 lease
-> agent_options
,
1253 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
1256 /* Record the hostname information in the lease. */
1257 if (comp
-> client_hostname
)
1258 dfree (comp
-> client_hostname
, MDL
);
1259 comp
-> client_hostname
= lease
-> client_hostname
;
1260 lease
-> client_hostname
= (char *)0;
1262 if (lease
->on_star
.on_expiry
) {
1263 if (comp
->on_star
.on_expiry
)
1264 executable_statement_dereference
1265 (&comp
->on_star
.on_expiry
, MDL
);
1266 executable_statement_reference (&comp
->on_star
.on_expiry
,
1267 lease
->on_star
.on_expiry
,
1270 if (lease
->on_star
.on_commit
) {
1271 if (comp
->on_star
.on_commit
)
1272 executable_statement_dereference
1273 (&comp
->on_star
.on_commit
, MDL
);
1274 executable_statement_reference (&comp
->on_star
.on_commit
,
1275 lease
->on_star
.on_commit
,
1278 if (lease
->on_star
.on_release
) {
1279 if (comp
->on_star
.on_release
)
1280 executable_statement_dereference
1281 (&comp
->on_star
.on_release
, MDL
);
1282 executable_statement_reference (&comp
->on_star
.on_release
,
1283 lease
->on_star
.on_release
,
1287 /* Record the lease in the uid hash if necessary. */
1291 /* Record it in the hardware address hash if necessary. */
1292 if (comp
->hardware_addr
.hlen
)
1295 comp
->cltt
= lease
->cltt
;
1296 #if defined (FAILOVER_PROTOCOL)
1297 comp
->tstp
= lease
->tstp
;
1298 comp
->tsfp
= lease
->tsfp
;
1299 comp
->atsfp
= lease
->atsfp
;
1300 #endif /* FAILOVER_PROTOCOL */
1301 comp
->ends
= lease
->ends
;
1302 comp
->next_binding_state
= lease
->next_binding_state
;
1305 * If we have a control block pointer copy it in.
1306 * We don't zero out an older ponter as it is still
1307 * in use. We shouldn't need to overwrite an
1308 * old pointer with a new one as the old transaction
1309 * should have been cancelled before getting here.
1311 if (lease
->ddns_cb
!= NULL
)
1312 comp
->ddns_cb
= lease
->ddns_cb
;
1315 #if defined (FAILOVER_PROTOCOL)
1317 * Atsfp should be cleared upon any state change that implies
1318 * propagation whether supersede_lease was given a copy lease
1319 * structure or not (often from the pool_timer()).
1323 #endif /* FAILOVER_PROTOCOL */
1325 if (!comp
-> pool
) {
1326 log_error ("Supersede_lease: lease %s with no pool.",
1327 piaddr (comp
-> ip_addr
));
1331 /* Figure out which queue it's on. */
1332 switch (comp
-> binding_state
) {
1334 if (comp
->flags
& RESERVED_LEASE
)
1335 lq
= &comp
->pool
->reserved
;
1337 lq
= &comp
->pool
->free
;
1338 comp
->pool
->free_leases
--;
1341 #if defined(FAILOVER_PROTOCOL)
1347 lq
= &comp
-> pool
-> active
;
1353 lq
= &comp
-> pool
-> expired
;
1357 lq
= &comp
-> pool
-> abandoned
;
1361 if (comp
->flags
& RESERVED_LEASE
)
1362 lq
= &comp
->pool
->reserved
;
1364 lq
= &comp
->pool
->backup
;
1365 comp
->pool
->backup_leases
--;
1368 #if defined(FAILOVER_PROTOCOL)
1374 log_error ("Lease with bogus binding state: %d",
1375 comp
-> binding_state
);
1376 #if defined (BINDING_STATE_DEBUG)
1382 /* Remove the lease from its current place in its current
1384 LEASE_REMOVEP(lq
, comp
);
1386 /* Now that we've done the flag-affected queue removal
1387 * we can update the new lease's flags, if there's an
1390 comp
->flags
= ((lease
->flags
& ~PERSISTENT_FLAGS
) |
1391 (comp
->flags
& ~EPHEMERAL_FLAGS
));
1394 /* Make the state transition. */
1395 if (commit
|| !pimmediate
)
1396 make_binding_state_transition (comp
);
1398 /* Put the lease back on the appropriate queue. If the lease
1399 is corrupt (as detected by lease_enqueue), don't go any farther. */
1400 if (!lease_enqueue (comp
))
1403 /* If this is the next lease that will timeout on the pool,
1404 zap the old timeout and set the timeout on this pool to the
1405 time that the lease's next event will happen.
1407 We do not actually set the timeout unless commit is true -
1408 we don't want to thrash the timer queue when reading the
1409 lease database. Instead, the database code calls the
1410 expiry event on each pool after reading in the lease file,
1411 and the expiry code sets the timer if there's anything left
1412 to expire after it's run any outstanding expiry events on
1414 if ((commit
|| !pimmediate
) &&
1415 comp
-> sort_time
!= MIN_TIME
&&
1416 comp
-> sort_time
> cur_time
&&
1417 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1418 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1419 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1420 tv
. tv_sec
= comp
-> pool
-> next_event_time
;
1423 pool_timer
, comp
-> pool
,
1424 (tvref_t
)pool_reference
,
1425 (tvunref_t
)pool_dereference
);
1429 #if defined(FAILOVER_PROTOCOL)
1431 * If commit and propogate are set, then we can save a
1432 * possible fsync later in BNDUPD socket transmission by
1433 * stepping the rewind state forward to the new state, in
1434 * case it has changed. This is only worth doing if the
1435 * failover connection is currently connected, as in this
1436 * case it is likely we will be transmitting to the peer very
1439 if (propogate
&& (comp
->pool
->failover_peer
!= NULL
) &&
1440 ((comp
->pool
->failover_peer
->service_state
==
1442 (comp
->pool
->failover_peer
->service_state
==
1444 comp
->rewind_binding_state
= comp
->binding_state
;
1447 if (!write_lease (comp
))
1449 if ((server_starting
& SS_NOSYNC
) == 0) {
1450 if (!commit_leases ())
1455 #if defined (FAILOVER_PROTOCOL)
1457 comp
-> desired_binding_state
= comp
-> binding_state
;
1458 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1461 if (do_pool_check
&& comp
->pool
->failover_peer
)
1462 dhcp_failover_pool_check(comp
->pool
);
1465 /* If the current binding state has already expired and we haven't
1466 * been called from pool_timer, do an expiry event right now.
1468 /* XXX At some point we should optimize this so that we don't
1469 XXX write the lease twice, but this is a safe way to fix the
1470 XXX problem for 3.0 (I hope!). */
1471 if ((from_pool
== 0) &&
1472 (commit
|| !pimmediate
) &&
1473 (comp
->sort_time
< cur_time
) &&
1474 (comp
->next_binding_state
!= comp
->binding_state
))
1475 pool_timer(comp
->pool
);
1480 void make_binding_state_transition (struct lease
*lease
)
1483 #if defined (FAILOVER_PROTOCOL)
1484 dhcp_failover_state_t
*peer
;
1486 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1487 peer
= lease
-> pool
-> failover_peer
;
1489 peer
= (dhcp_failover_state_t
*)0;
1492 /* If the lease was active and is now no longer active, but isn't
1493 released, then it just expired, so do the expiry event. */
1494 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1496 #if defined (FAILOVER_PROTOCOL)
1498 (lease
->binding_state
== FTS_EXPIRED
||
1499 lease
->binding_state
== FTS_ACTIVE
) &&
1500 (lease
->next_binding_state
== FTS_FREE
||
1501 lease
->next_binding_state
== FTS_BACKUP
)) ||
1504 lease
-> binding_state
== FTS_ACTIVE
&&
1505 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1506 #if defined (NSUPDATE)
1507 (void) ddns_removals(lease
, NULL
, NULL
, ISC_TRUE
);
1509 if (lease
->on_star
.on_expiry
) {
1510 execute_statements(NULL
, NULL
, lease
,
1513 lease
->on_star
.on_expiry
,
1515 if (lease
->on_star
.on_expiry
)
1516 executable_statement_dereference
1517 (&lease
->on_star
.on_expiry
, MDL
);
1520 /* No sense releasing a lease after it's expired. */
1521 if (lease
->on_star
.on_release
)
1522 executable_statement_dereference
1523 (&lease
->on_star
.on_release
, MDL
);
1524 /* Get rid of client-specific bindings that are only
1525 correct when the lease is active. */
1526 if (lease
->billing_class
)
1527 unbill_class(lease
);
1528 if (lease
-> agent_options
)
1529 option_chain_head_dereference (&lease
-> agent_options
,
1531 if (lease
-> client_hostname
) {
1532 dfree (lease
-> client_hostname
, MDL
);
1533 lease
-> client_hostname
= (char *)0;
1536 host_dereference (&lease
-> host
, MDL
);
1538 /* Send the expiry time to the peer. */
1539 lease
-> tstp
= lease
-> ends
;
1542 /* If the lease was active and is now released, do the release
1544 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1546 #if defined (FAILOVER_PROTOCOL)
1548 lease
-> binding_state
== FTS_RELEASED
&&
1549 (lease
-> next_binding_state
== FTS_FREE
||
1550 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1553 lease
-> binding_state
== FTS_ACTIVE
&&
1554 lease
-> next_binding_state
== FTS_RELEASED
))) {
1555 #if defined (NSUPDATE)
1557 * Note: ddns_removals() is also iterated when the lease
1558 * enters state 'released' in 'release_lease()'. The below
1559 * is caught when a peer receives a BNDUPD from a failover
1560 * peer; it may not have received the client's release (it
1561 * may have been offline).
1563 * We could remove the call from release_lease() because
1564 * it will also catch here on the originating server after the
1565 * peer acknowledges the state change. However, there could
1566 * be many hours inbetween, and in this case we /know/ the
1567 * client is no longer using the lease when we receive the
1568 * release message. This is not true of expiry, where the
1569 * peer may have extended the lease.
1571 (void) ddns_removals(lease
, NULL
, NULL
, ISC_TRUE
);
1573 if (lease
->on_star
.on_release
) {
1574 execute_statements(NULL
, NULL
, lease
,
1577 lease
->on_star
.on_release
,
1579 executable_statement_dereference
1580 (&lease
->on_star
.on_release
, MDL
);
1583 /* A released lease can't expire. */
1584 if (lease
->on_star
.on_expiry
)
1585 executable_statement_dereference
1586 (&lease
->on_star
.on_expiry
, MDL
);
1588 /* Get rid of client-specific bindings that are only
1589 correct when the lease is active. */
1590 if (lease
->billing_class
)
1591 unbill_class(lease
);
1592 if (lease
-> agent_options
)
1593 option_chain_head_dereference (&lease
-> agent_options
,
1595 if (lease
-> client_hostname
) {
1596 dfree (lease
-> client_hostname
, MDL
);
1597 lease
-> client_hostname
= (char *)0;
1600 host_dereference (&lease
-> host
, MDL
);
1602 /* Send the release time (should be == cur_time) to the
1604 lease
-> tstp
= lease
-> ends
;
1607 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1608 log_debug ("lease %s moves from %s to %s",
1609 piaddr (lease
-> ip_addr
),
1610 binding_state_print (lease
-> binding_state
),
1611 binding_state_print (lease
-> next_binding_state
));
1614 lease
-> binding_state
= lease
-> next_binding_state
;
1615 switch (lease
-> binding_state
) {
1617 #if defined (FAILOVER_PROTOCOL)
1618 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1619 lease
-> next_binding_state
= FTS_EXPIRED
;
1622 lease
-> next_binding_state
= FTS_FREE
;
1629 lease
->next_binding_state
= FTS_FREE
;
1630 #if defined(FAILOVER_PROTOCOL)
1631 /* If we are not in partner_down, leases don't go from
1632 EXPIRED to FREE on a timeout - only on an update.
1633 If we're in partner_down, they expire at mclt past
1634 the time we entered partner_down. */
1635 if ((lease
->pool
!= NULL
) &&
1636 (lease
->pool
->failover_peer
!= NULL
) &&
1637 (lease
->pool
->failover_peer
->me
.state
== partner_down
))
1639 (lease
->pool
->failover_peer
->me
.stos
+
1640 lease
->pool
->failover_peer
->mclt
);
1641 #endif /* FAILOVER_PROTOCOL */
1646 lease
-> next_binding_state
= lease
-> binding_state
;
1649 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1650 log_debug ("lease %s: next binding state %s",
1651 piaddr (lease
-> ip_addr
),
1652 binding_state_print (lease
-> next_binding_state
));
1656 /* Copy the contents of one lease into another, correctly maintaining
1657 reference counts. */
1658 int lease_copy (struct lease
**lp
,
1659 struct lease
*lease
, const char *file
, int line
)
1661 struct lease
*lt
= (struct lease
*)0;
1662 isc_result_t status
;
1664 status
= lease_allocate (<
, MDL
);
1665 if (status
!= ISC_R_SUCCESS
)
1668 lt
-> ip_addr
= lease
-> ip_addr
;
1669 lt
-> starts
= lease
-> starts
;
1670 lt
-> ends
= lease
-> ends
;
1671 lt
-> uid_len
= lease
-> uid_len
;
1672 lt
-> uid_max
= lease
-> uid_max
;
1673 if (lease
-> uid
== lease
-> uid_buf
) {
1674 lt
-> uid
= lt
-> uid_buf
;
1675 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1676 } else if (!lease
-> uid_max
) {
1677 lt
-> uid
= (unsigned char *)0;
1679 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1681 lease_dereference (<
, MDL
);
1684 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1686 if (lease
-> client_hostname
) {
1687 lt
-> client_hostname
=
1688 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1689 if (!lt
-> client_hostname
) {
1690 lease_dereference (<
, MDL
);
1693 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1696 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1697 if (lease
-> agent_options
)
1698 option_chain_head_reference (<
-> agent_options
,
1699 lease
-> agent_options
, MDL
);
1700 host_reference (<
-> host
, lease
-> host
, file
, line
);
1701 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1702 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1703 class_reference (<
-> billing_class
,
1704 lease
-> billing_class
, file
, line
);
1705 lt
-> hardware_addr
= lease
-> hardware_addr
;
1706 if (lease
->on_star
.on_expiry
)
1707 executable_statement_reference (<
->on_star
.on_expiry
,
1708 lease
->on_star
.on_expiry
,
1710 if (lease
->on_star
.on_commit
)
1711 executable_statement_reference (<
->on_star
.on_commit
,
1712 lease
->on_star
.on_commit
,
1714 if (lease
->on_star
.on_release
)
1715 executable_statement_reference (<
->on_star
.on_release
,
1716 lease
->on_star
.on_release
,
1718 lt
->flags
= lease
->flags
;
1719 lt
->tstp
= lease
->tstp
;
1720 lt
->tsfp
= lease
->tsfp
;
1721 lt
->atsfp
= lease
->atsfp
;
1722 lt
->cltt
= lease
-> cltt
;
1723 lt
->binding_state
= lease
->binding_state
;
1724 lt
->next_binding_state
= lease
->next_binding_state
;
1725 lt
->rewind_binding_state
= lease
->rewind_binding_state
;
1726 status
= lease_reference(lp
, lt
, file
, line
);
1727 lease_dereference(<
, MDL
);
1728 return status
== ISC_R_SUCCESS
;
1731 /* Release the specified lease and re-hash it as appropriate. */
1732 void release_lease (lease
, packet
)
1733 struct lease
*lease
;
1734 struct packet
*packet
;
1736 /* If there are statements to execute when the lease is
1737 released, execute them. */
1738 #if defined (NSUPDATE)
1739 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1741 if (lease
->on_star
.on_release
) {
1742 execute_statements (NULL
, packet
, lease
,
1743 NULL
, packet
->options
,
1744 NULL
, &lease
->scope
,
1745 lease
->on_star
.on_release
, NULL
);
1746 if (lease
->on_star
.on_release
)
1747 executable_statement_dereference
1748 (&lease
->on_star
.on_release
, MDL
);
1751 /* We do either the on_release or the on_expiry events, but
1752 not both (it's possible that they could be the same,
1754 if (lease
->on_star
.on_expiry
)
1755 executable_statement_dereference
1756 (&lease
->on_star
.on_expiry
, MDL
);
1758 if (lease
-> binding_state
!= FTS_FREE
&&
1759 lease
-> binding_state
!= FTS_BACKUP
&&
1760 lease
-> binding_state
!= FTS_RELEASED
&&
1761 lease
-> binding_state
!= FTS_EXPIRED
&&
1762 lease
-> binding_state
!= FTS_RESET
) {
1763 if (lease
->on_star
.on_commit
)
1764 executable_statement_dereference
1765 (&lease
->on_star
.on_commit
, MDL
);
1767 /* Blow away any bindings. */
1769 binding_scope_dereference (&lease
-> scope
, MDL
);
1771 /* Set sort times to the present. */
1772 lease
-> ends
= cur_time
;
1773 /* Lower layers of muckery set tstp to ->ends. But we send
1774 * protocol messages before this. So it is best to set
1777 lease
->tstp
= cur_time
;
1778 #if defined (FAILOVER_PROTOCOL)
1779 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1780 dhcp_failover_state_t
*peer
= NULL
;
1782 if (lease
->pool
!= NULL
)
1783 peer
= lease
->pool
->failover_peer
;
1785 if ((peer
->service_state
== not_cooperating
) &&
1786 (((peer
->i_am
== primary
) &&
1787 (lease
->rewind_binding_state
== FTS_FREE
)) ||
1788 ((peer
->i_am
== secondary
) &&
1789 (lease
->rewind_binding_state
== FTS_BACKUP
)))) {
1790 lease
->next_binding_state
=
1791 lease
->rewind_binding_state
;
1793 lease
-> next_binding_state
= FTS_RELEASED
;
1795 lease
-> next_binding_state
= FTS_FREE
;
1798 lease
-> next_binding_state
= FTS_FREE
;
1800 supersede_lease(lease
, NULL
, 1, 1, 1, 0);
1804 /* Abandon the specified lease (set its timeout to infinity and its
1805 particulars to zero, and re-hash it as appropriate. */
1807 void abandon_lease (lease
, message
)
1808 struct lease
*lease
;
1809 const char *message
;
1811 struct lease
*lt
= NULL
;
1812 #if defined (NSUPDATE)
1813 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1816 if (!lease_copy(<
, lease
, MDL
)) {
1821 binding_scope_dereference(<
->scope
, MDL
);
1824 /* Calculate the abandone expiry time. If it wraps,
1825 * use the maximum expiry time. */
1826 lt
->ends
= cur_time
+ abandon_lease_time
;
1827 if (lt
->ends
< cur_time
|| lt
->ends
> MAX_TIME
) {
1828 lt
->ends
= MAX_TIME
;
1831 lt
->next_binding_state
= FTS_ABANDONED
;
1833 log_error ("Abandoning IP address %s: %s", piaddr(lease
->ip_addr
),
1835 lt
->hardware_addr
.hlen
= 0;
1836 if (lt
->uid
&& lt
->uid
!= lt
->uid_buf
) {
1837 dfree(lt
->uid
, MDL
);
1843 supersede_lease(lease
, lt
, 1, 1, 1, 0);
1844 lease_dereference(<
, MDL
);
1849 * This doesn't appear to be in use for anything anymore.
1850 * I'm ifdeffing it now and if there are no complaints in
1851 * the future it will be removed.
1855 /* Abandon the specified lease (set its timeout to infinity and its
1856 particulars to zero, and re-hash it as appropriate. */
1858 void dissociate_lease (lease
)
1859 struct lease
*lease
;
1861 struct lease
*lt
= (struct lease
*)0;
1862 #if defined (NSUPDATE)
1863 (void) ddns_removals(lease
, NULL
, NULL
, ISC_FALSE
);
1866 if (!lease_copy (<
, lease
, MDL
))
1869 #if defined (FAILOVER_PROTOCOL)
1870 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1871 lt
-> next_binding_state
= FTS_RESET
;
1873 lt
-> next_binding_state
= FTS_FREE
;
1876 lt
-> next_binding_state
= FTS_FREE
;
1878 lt
-> ends
= cur_time
; /* XXX */
1879 lt
-> hardware_addr
.hlen
= 0;
1880 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1881 dfree (lt
-> uid
, MDL
);
1882 lt
-> uid
= (unsigned char *)0;
1885 supersede_lease (lease
, lt
, 1, 1, 1, 0);
1886 lease_dereference (<
, MDL
);
1890 /* Timer called when a lease in a particular pool expires. */
1891 void pool_timer (vpool
)
1895 struct lease
*next
= NULL
;
1896 struct lease
*lease
= NULL
;
1897 struct lease
*ltemp
= NULL
;
1898 #define FREE_LEASES 0
1899 #define ACTIVE_LEASES 1
1900 #define EXPIRED_LEASES 2
1901 #define ABANDONED_LEASES 3
1902 #define BACKUP_LEASES 4
1903 #define RESERVED_LEASES 5
1904 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
1905 TIME next_expiry
= MAX_TIME
;
1909 pool
= (struct pool
*)vpool
;
1911 lptr
[FREE_LEASES
] = &pool
->free
;
1912 lptr
[ACTIVE_LEASES
] = &pool
->active
;
1913 lptr
[EXPIRED_LEASES
] = &pool
->expired
;
1914 lptr
[ABANDONED_LEASES
] = &pool
->abandoned
;
1915 lptr
[BACKUP_LEASES
] = &pool
->backup
;
1916 lptr
[RESERVED_LEASES
] = &pool
->reserved
;
1918 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
1919 /* If there's nothing on the queue, skip it. */
1920 if (!(LEASE_NOT_EMPTYP(lptr
[i
])))
1923 #if defined (FAILOVER_PROTOCOL)
1924 if (pool
->failover_peer
&&
1925 pool
->failover_peer
->me
.state
!= partner_down
) {
1927 * Normally the secondary doesn't initiate expiration
1928 * events (unless in partner-down), but rather relies
1929 * on the primary to expire the lease. However, when
1930 * disconnected from its peer, the server is allowed to
1931 * rewind a lease to the previous state that the peer
1932 * would have recorded it. This means there may be
1933 * opportunities for active->free or active->backup
1934 * expirations while out of contact.
1936 * Q: Should we limit this expiration to
1937 * comms-interrupt rather than not-normal?
1939 if ((i
== ACTIVE_LEASES
) &&
1940 (pool
->failover_peer
->i_am
== secondary
) &&
1941 (pool
->failover_peer
->me
.state
== normal
))
1944 /* Leases in an expired state don't move to
1945 free because of a timeout unless we're in
1947 if (i
== EXPIRED_LEASES
)
1951 lease_reference(&lease
, LEASE_GET_FIRSTP(lptr
[i
]), MDL
);
1954 /* Remember the next lease in the list. */
1956 lease_dereference(&next
, MDL
);
1957 ltemp
= LEASE_GET_NEXTP(lptr
[i
], lease
);
1959 lease_reference(&next
, ltemp
, MDL
);
1961 /* If we've run out of things to expire on this list,
1963 if (lease
->sort_time
> cur_time
) {
1964 if (lease
->sort_time
< next_expiry
)
1965 next_expiry
= lease
->sort_time
;
1969 /* If there is a pending state change, and
1970 this lease has gotten to the time when the
1971 state change should happen, just call
1972 supersede_lease on it to make the change
1974 if (lease
->next_binding_state
!= lease
->binding_state
)
1976 #if defined(FAILOVER_PROTOCOL)
1977 dhcp_failover_state_t
*peer
= NULL
;
1979 if (lease
->pool
!= NULL
)
1980 peer
= lease
->pool
->failover_peer
;
1982 /* Can we rewind the lease to a free state? */
1984 peer
->service_state
== not_cooperating
&&
1985 lease
->next_binding_state
== FTS_EXPIRED
&&
1986 ((peer
->i_am
== primary
&&
1987 lease
->rewind_binding_state
== FTS_FREE
)
1989 (peer
->i_am
== secondary
&&
1990 lease
->rewind_binding_state
==
1992 lease
->next_binding_state
=
1993 lease
->rewind_binding_state
;
1995 supersede_lease(lease
, NULL
, 1, 1, 1, 1);
1998 lease_dereference(&lease
, MDL
);
2000 lease_reference(&lease
, next
, MDL
);
2003 lease_dereference(&next
, MDL
);
2005 lease_dereference(&lease
, MDL
);
2008 /* If we found something to expire and its expiration time
2009 * is either less than the current expiration time or the
2010 * current expiration time is already expired update the
2013 if ((next_expiry
!= MAX_TIME
) &&
2014 ((pool
->next_event_time
> next_expiry
) ||
2015 (pool
->next_event_time
<= cur_time
))) {
2016 pool
->next_event_time
= next_expiry
;
2017 tv
.tv_sec
= pool
->next_event_time
;
2019 add_timeout (&tv
, pool_timer
, pool
,
2020 (tvref_t
)pool_reference
,
2021 (tvunref_t
)pool_dereference
);
2023 pool
->next_event_time
= MIN_TIME
;
2027 /* Locate the lease associated with a given IP address... */
2029 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
2030 const char *file
, int line
)
2032 return lease_ip_hash_lookup(lp
, lease_ip_addr_hash
, addr
.iabuf
,
2033 addr
.len
, file
, line
);
2036 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
2037 unsigned len
, const char *file
, int line
)
2041 return lease_id_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
2044 int find_lease_by_hw_addr (struct lease
**lp
,
2045 const unsigned char *hwaddr
, unsigned hwlen
,
2046 const char *file
, int line
)
2052 * If it's an infiniband address don't bother
2053 * as we don't have a useful address to hash.
2055 if ((hwlen
== 1) && (hwaddr
[0] == HTYPE_INFINIBAND
))
2058 return (lease_id_hash_lookup(lp
, lease_hw_addr_hash
, hwaddr
, hwlen
,
2062 /* If the lease is preferred over the candidate, return truth. The
2063 * 'cand' and 'lease' names are retained to read more clearly against
2064 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
2065 * to those two functions).
2067 * 1) ACTIVE leases are preferred. The active lease with
2068 * the longest lifetime is preferred over shortest.
2069 * 2) "transitional states" are next, this time with the
2071 * 3) free/backup/etc states are next, again with CLTT. In truth we
2072 * should never see reset leases for this.
2073 * 4) Abandoned leases are always dead last.
2075 static isc_boolean_t
2076 client_lease_preferred(struct lease
*cand
, struct lease
*lease
)
2078 if (cand
->binding_state
== FTS_ACTIVE
) {
2079 if (lease
->binding_state
== FTS_ACTIVE
&&
2080 lease
->ends
>= cand
->ends
)
2082 } else if (cand
->binding_state
== FTS_EXPIRED
||
2083 cand
->binding_state
== FTS_RELEASED
) {
2084 if (lease
->binding_state
== FTS_ACTIVE
)
2087 if ((lease
->binding_state
== FTS_EXPIRED
||
2088 lease
->binding_state
== FTS_RELEASED
) &&
2089 lease
->cltt
>= cand
->cltt
)
2091 } else if (cand
->binding_state
!= FTS_ABANDONED
) {
2092 if (lease
->binding_state
== FTS_ACTIVE
||
2093 lease
->binding_state
== FTS_EXPIRED
||
2094 lease
->binding_state
== FTS_RELEASED
)
2097 if (lease
->binding_state
!= FTS_ABANDONED
&&
2098 lease
->cltt
>= cand
->cltt
)
2100 } else /* (cand->binding_state == FTS_ABANDONED) */ {
2101 if (lease
->binding_state
!= FTS_ABANDONED
||
2102 lease
->cltt
>= cand
->cltt
)
2109 /* Add the specified lease to the uid hash. */
2111 uid_hash_add(struct lease
*lease
)
2113 struct lease
*head
= NULL
;
2114 struct lease
*cand
= NULL
;
2115 struct lease
*prev
= NULL
;
2116 struct lease
*next
= NULL
;
2118 /* If it's not in the hash, just add it. */
2119 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
2120 lease_id_hash_add(lease_uid_hash
, lease
->uid
, lease
->uid_len
,
2123 /* Otherwise, insert it into the list in order of its
2124 * preference for "resuming allocation to the client."
2126 * Because we don't have control of the hash bucket index
2127 * directly, we have to remove and re-insert the client
2128 * id into the hash if we're inserting onto the head.
2130 lease_reference(&cand
, head
, MDL
);
2131 while (cand
!= NULL
) {
2132 if (client_lease_preferred(cand
, lease
))
2136 lease_dereference(&prev
, MDL
);
2137 lease_reference(&prev
, cand
, MDL
);
2139 if (cand
->n_uid
!= NULL
)
2140 lease_reference(&next
, cand
->n_uid
, MDL
);
2142 lease_dereference(&cand
, MDL
);
2145 lease_reference(&cand
, next
, MDL
);
2146 lease_dereference(&next
, MDL
);
2150 /* If we want to insert 'before cand', and prev is NULL,
2151 * then it was the head of the list. Assume that position.
2154 lease_reference(&lease
->n_uid
, head
, MDL
);
2155 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2156 lease
->uid_len
, MDL
);
2157 lease_id_hash_add(lease_uid_hash
, lease
->uid
,
2158 lease
->uid_len
, lease
, MDL
);
2159 } else /* (prev != NULL) */ {
2160 if(prev
->n_uid
!= NULL
) {
2161 lease_reference(&lease
->n_uid
, prev
->n_uid
,
2163 lease_dereference(&prev
->n_uid
, MDL
);
2165 lease_reference(&prev
->n_uid
, lease
, MDL
);
2167 lease_dereference(&prev
, MDL
);
2171 lease_dereference(&cand
, MDL
);
2172 lease_dereference(&head
, MDL
);
2176 /* Delete the specified lease from the uid hash. */
2178 void uid_hash_delete (lease
)
2179 struct lease
*lease
;
2181 struct lease
*head
= (struct lease
*)0;
2184 /* If it's not in the hash, we have no work to do. */
2185 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
2187 lease_dereference (&lease
-> n_uid
, MDL
);
2191 /* If the lease we're freeing is at the head of the list,
2192 remove the hash table entry and add a new one with the
2193 next lease on the list (if there is one). */
2194 if (head
== lease
) {
2195 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2196 lease
->uid_len
, MDL
);
2197 if (lease
-> n_uid
) {
2198 lease_id_hash_add(lease_uid_hash
, lease
->n_uid
->uid
,
2199 lease
->n_uid
->uid_len
, lease
->n_uid
,
2201 lease_dereference (&lease
-> n_uid
, MDL
);
2204 /* Otherwise, look for the lease in the list of leases
2205 attached to the hash table entry, and remove it if
2207 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
2208 if (scan
-> n_uid
== lease
) {
2209 lease_dereference (&scan
-> n_uid
, MDL
);
2210 if (lease
-> n_uid
) {
2211 lease_reference (&scan
-> n_uid
,
2212 lease
-> n_uid
, MDL
);
2213 lease_dereference (&lease
-> n_uid
,
2220 lease_dereference (&head
, MDL
);
2223 /* Add the specified lease to the hardware address hash. */
2224 /* We don't add leases with infiniband addresses to the
2225 * hash as there isn't any address to hash on. */
2228 hw_hash_add(struct lease
*lease
)
2230 struct lease
*head
= NULL
;
2231 struct lease
*cand
= NULL
;
2232 struct lease
*prev
= NULL
;
2233 struct lease
*next
= NULL
;
2236 * If it's an infiniband address don't bother
2237 * as we don't have a useful address to hash.
2239 if ((lease
->hardware_addr
.hlen
== 1) &&
2240 (lease
->hardware_addr
.hbuf
[0] == HTYPE_INFINIBAND
))
2243 /* If it's not in the hash, just add it. */
2244 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2245 lease
-> hardware_addr
.hlen
, MDL
))
2246 lease_id_hash_add(lease_hw_addr_hash
,
2247 lease
->hardware_addr
.hbuf
,
2248 lease
->hardware_addr
.hlen
, lease
, MDL
);
2250 /* Otherwise, insert it into the list in order of its
2251 * preference for "resuming allocation to the client."
2253 * Because we don't have control of the hash bucket index
2254 * directly, we have to remove and re-insert the client
2255 * id into the hash if we're inserting onto the head.
2257 lease_reference(&cand
, head
, MDL
);
2258 while (cand
!= NULL
) {
2259 if (client_lease_preferred(cand
, lease
))
2263 lease_dereference(&prev
, MDL
);
2264 lease_reference(&prev
, cand
, MDL
);
2266 if (cand
->n_hw
!= NULL
)
2267 lease_reference(&next
, cand
->n_hw
, MDL
);
2269 lease_dereference(&cand
, MDL
);
2272 lease_reference(&cand
, next
, MDL
);
2273 lease_dereference(&next
, MDL
);
2277 /* If we want to insert 'before cand', and prev is NULL,
2278 * then it was the head of the list. Assume that position.
2281 lease_reference(&lease
->n_hw
, head
, MDL
);
2282 lease_id_hash_delete(lease_hw_addr_hash
,
2283 lease
->hardware_addr
.hbuf
,
2284 lease
->hardware_addr
.hlen
, MDL
);
2285 lease_id_hash_add(lease_hw_addr_hash
,
2286 lease
->hardware_addr
.hbuf
,
2287 lease
->hardware_addr
.hlen
,
2289 } else /* (prev != NULL) */ {
2290 if(prev
->n_hw
!= NULL
) {
2291 lease_reference(&lease
->n_hw
, prev
->n_hw
,
2293 lease_dereference(&prev
->n_hw
, MDL
);
2295 lease_reference(&prev
->n_hw
, lease
, MDL
);
2297 lease_dereference(&prev
, MDL
);
2301 lease_dereference(&cand
, MDL
);
2302 lease_dereference(&head
, MDL
);
2306 /* Delete the specified lease from the hardware address hash. */
2308 void hw_hash_delete (lease
)
2309 struct lease
*lease
;
2311 struct lease
*head
= (struct lease
*)0;
2312 struct lease
*next
= (struct lease
*)0;
2315 * If it's an infiniband address don't bother
2316 * as we don't have a useful address to hash.
2318 if ((lease
->hardware_addr
.hlen
== 1) &&
2319 (lease
->hardware_addr
.hbuf
[0] == HTYPE_INFINIBAND
))
2322 /* If it's not in the hash, we have no work to do. */
2323 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2324 lease
-> hardware_addr
.hlen
, MDL
)) {
2326 lease_dereference (&lease
-> n_hw
, MDL
);
2330 /* If the lease we're freeing is at the head of the list,
2331 remove the hash table entry and add a new one with the
2332 next lease on the list (if there is one). */
2333 if (head
== lease
) {
2334 lease_id_hash_delete(lease_hw_addr_hash
,
2335 lease
->hardware_addr
.hbuf
,
2336 lease
->hardware_addr
.hlen
, MDL
);
2338 lease_id_hash_add(lease_hw_addr_hash
,
2339 lease
->n_hw
->hardware_addr
.hbuf
,
2340 lease
->n_hw
->hardware_addr
.hlen
,
2342 lease_dereference(&lease
->n_hw
, MDL
);
2345 /* Otherwise, look for the lease in the list of leases
2346 attached to the hash table entry, and remove it if
2348 while (head
-> n_hw
) {
2349 if (head
-> n_hw
== lease
) {
2350 lease_dereference (&head
-> n_hw
, MDL
);
2351 if (lease
-> n_hw
) {
2352 lease_reference (&head
-> n_hw
,
2353 lease
-> n_hw
, MDL
);
2354 lease_dereference (&lease
-> n_hw
,
2359 lease_reference (&next
, head
-> n_hw
, MDL
);
2360 lease_dereference (&head
, MDL
);
2361 lease_reference (&head
, next
, MDL
);
2362 lease_dereference (&next
, MDL
);
2366 lease_dereference (&head
, MDL
);
2369 /* Write v4 leases to permanent storage. */
2370 int write_leases4(void) {
2372 struct shared_network
*s
;
2374 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2375 int num_written
= 0, i
;
2377 /* Write all the leases. */
2378 for (s
= shared_networks
; s
; s
= s
->next
) {
2379 for (p
= s
->pools
; p
; p
= p
->next
) {
2380 lptr
[FREE_LEASES
] = &p
->free
;
2381 lptr
[ACTIVE_LEASES
] = &p
->active
;
2382 lptr
[EXPIRED_LEASES
] = &p
->expired
;
2383 lptr
[ABANDONED_LEASES
] = &p
->abandoned
;
2384 lptr
[BACKUP_LEASES
] = &p
->backup
;
2385 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2387 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2388 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2390 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2391 #if !defined (DEBUG_DUMP_ALL_LEASES)
2392 if (l
->hardware_addr
.hlen
!= 0 || l
->uid_len
!= 0 ||
2393 l
->tsfp
!= 0 || l
->binding_state
!= FTS_FREE
)
2396 if (write_lease(l
) == 0)
2405 log_info ("Wrote %d leases to leases file.", num_written
);
2409 /* Write all interesting leases to permanent storage. */
2413 struct host_decl
*hp
;
2414 struct group_object
*gp
;
2415 struct hash_bucket
*hb
;
2417 struct collection
*colp
;
2421 /* write all the dynamically-created class declarations. */
2422 if (collections
->classes
) {
2423 numclasseswritten
= 0;
2424 for (colp
= collections
; colp
; colp
= colp
->next
) {
2425 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
2426 write_named_billing_class(
2427 (unsigned char *)cp
->name
,
2432 /* XXXJAB this number doesn't include subclasses... */
2433 log_info ("Wrote %d class decls to leases file.",
2438 /* Write all the dynamically-created group declarations. */
2439 if (group_name_hash
) {
2441 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
2442 for (hb
= group_name_hash
-> buckets
[i
];
2443 hb
; hb
= hb
-> next
) {
2444 gp
= (struct group_object
*)hb
-> value
;
2445 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
2446 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
2447 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
2448 if (!write_group (gp
))
2454 log_info ("Wrote %d group decls to leases file.", num_written
);
2457 /* Write all the deleted host declarations. */
2458 if (host_name_hash
) {
2460 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2461 for (hb
= host_name_hash
-> buckets
[i
];
2462 hb
; hb
= hb
-> next
) {
2463 hp
= (struct host_decl
*)hb
-> value
;
2464 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
2465 (hp
-> flags
& HOST_DECL_DELETED
))) {
2466 if (!write_host (hp
))
2472 log_info ("Wrote %d deleted host decls to leases file.",
2476 /* Write all the new, dynamic host declarations. */
2477 if (host_name_hash
) {
2479 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2480 for (hb
= host_name_hash
-> buckets
[i
];
2481 hb
; hb
= hb
-> next
) {
2482 hp
= (struct host_decl
*)hb
-> value
;
2483 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
2484 if (!write_host (hp
))
2489 log_info ("Wrote %d new dynamic host decls to leases file.",
2493 #if defined (FAILOVER_PROTOCOL)
2494 /* Write all the failover states. */
2495 if (!dhcp_failover_write_all_states ())
2499 switch (local_family
) {
2501 if (write_leases4() == 0)
2506 if (write_leases6() == 0)
2512 if (commit_leases() == 0)
2517 #if !defined (BINARY_LEASES)
2518 /* Unlink all the leases in the queue. */
2519 void lease_remove_all(struct lease
**lq
) {
2520 struct lease
*lp
, *ln
= NULL
;
2526 /* We simply derefernce the first item in the list. When
2527 * it's reference counter goes to zero it will be cleaned
2528 * and the reference counter
2530 * Get a pointer to the first item in the list and then
2531 * drop the reference from the queue pointer
2533 lease_reference(&lp
, *lq
, MDL
);
2534 lease_dereference(lq
, MDL
);
2537 /* if we have a next save a pointer to it and unlink it */
2539 lease_reference(&ln
, lp
->next
, MDL
);
2540 lease_dereference(&lp
->next
, MDL
);
2543 /* get rid of what we currently have */
2544 lease_dereference(&lp
, MDL
);
2546 /* move the next to the current and loop */
2549 } while (lp
!= NULL
);
2553 * This routine walks through a given lease queue (lq) looking
2554 * for comp. If it doesn't find the lease it is a fatal error
2555 * as it should be on the given queue. Once we find the lease
2556 * we can remove it from this list.
2558 void lease_remove(struct lease
**lq
, struct lease
*comp
)
2560 struct lease
*prev
, *lp
;
2563 for (lp
= *lq
; lp
!= NULL
; lp
= lp
->next
) {
2570 log_fatal("Lease with binding state %s not on its queue.",
2571 (comp
->binding_state
< 1 ||
2572 comp
->binding_state
> FTS_LAST
)
2574 : binding_state_names
[comp
->binding_state
- 1]);
2578 lease_dereference(&prev
->next
, MDL
);
2580 lease_reference(&prev
->next
, comp
->next
, MDL
);
2581 lease_dereference (&comp
->next
, MDL
);
2584 lease_dereference(lq
, MDL
);
2586 lease_reference(lq
, comp
->next
, MDL
);
2587 lease_dereference(&comp
->next
, MDL
);
2592 /* This routine inserts comp into lq in a sorted fashion.
2593 * The sort key is comp->sort_time, smaller values are
2594 * placed earlier in the list.
2596 void lease_insert(struct lease
**lq
, struct lease
*comp
)
2598 struct lease
*prev
, *lp
;
2599 static struct lease
**last_lq
= NULL
;
2600 static struct lease
*last_insert_point
= NULL
;
2602 /* This only works during server startup: during runtime, the last
2603 * lease may be dequeued in between calls. If the queue is the same
2604 * as was used previously, and the lease structure isn't (this is not
2605 * a re-queue), use that as a starting point for the insertion-sort.
2607 if ((server_starting
& SS_QFOLLOW
) && (lq
== last_lq
) &&
2608 (comp
!= last_insert_point
) &&
2609 (last_insert_point
->sort_time
<= comp
->sort_time
)) {
2610 prev
= last_insert_point
;
2617 /* Insertion sort the lease onto the appropriate queue. */
2618 for (; lp
!= NULL
; lp
= lp
->next
) {
2619 if (lp
->sort_time
>= comp
->sort_time
)
2626 lease_reference(&comp
->next
, prev
->next
, MDL
);
2627 lease_dereference(&prev
->next
, MDL
);
2629 lease_reference(&prev
->next
, comp
, MDL
);
2632 lease_reference (&comp
->next
, *lq
, MDL
);
2633 lease_dereference(lq
, MDL
);
2635 lease_reference(lq
, comp
, MDL
);
2637 last_insert_point
= comp
;
2644 /* In addition to placing this lease upon a lease queue depending on its
2645 * state, it also keeps track of the number of FREE and BACKUP leases in
2646 * existence, and sets the sort_time on the lease.
2648 * Sort_time is used in pool_timer() to determine when the lease will
2649 * bubble to the top of the list and be supersede_lease()'d into its next
2650 * state (possibly, if all goes well). Example, ACTIVE leases move to
2651 * EXPIRED state when the 'ends' value is reached, so that is its sort
2652 * time. Most queues are sorted by 'ends', since it is generally best
2653 * practice to re-use the oldest lease, to reduce address collision
2656 int lease_enqueue (struct lease
*comp
)
2658 LEASE_STRUCT_PTR lq
;
2660 /* No queue to put it on? */
2664 /* Figure out which queue it's going to. */
2665 switch (comp
-> binding_state
) {
2667 if (comp
->flags
& RESERVED_LEASE
) {
2668 lq
= &comp
->pool
->reserved
;
2670 lq
= &comp
->pool
->free
;
2671 comp
->pool
->free_leases
++;
2673 comp
-> sort_time
= comp
-> ends
;
2677 lq
= &comp
-> pool
-> active
;
2678 comp
-> sort_time
= comp
-> ends
;
2684 lq
= &comp
-> pool
-> expired
;
2685 #if defined(FAILOVER_PROTOCOL)
2686 /* In partner_down, tsfp is the time at which the lease
2687 * may be reallocated (stos+mclt). We can do that with
2688 * lease_mine_to_reallocate() anywhere between tsfp and
2689 * ends. But we prefer to wait until ends before doing it
2690 * automatically (choose the greater of the two). Note
2691 * that 'ends' is usually a historic timestamp in the
2692 * case of expired leases, is really only in the future
2693 * on released leases, and if we know a lease to be released
2694 * the peer might still know it to be active...in which case
2695 * it's possible the peer has renewed this lease, so avoid
2698 if (comp
->pool
->failover_peer
&&
2699 comp
->pool
->failover_peer
->me
.state
== partner_down
)
2700 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
2701 comp
->tsfp
: comp
->ends
;
2704 comp
->sort_time
= comp
->ends
;
2709 lq
= &comp
-> pool
-> abandoned
;
2710 comp
-> sort_time
= comp
-> ends
;
2714 if (comp
->flags
& RESERVED_LEASE
) {
2715 lq
= &comp
->pool
->reserved
;
2717 lq
= &comp
->pool
->backup
;
2718 comp
->pool
->backup_leases
++;
2720 comp
-> sort_time
= comp
-> ends
;
2724 log_error ("Lease with bogus binding state: %d",
2725 comp
-> binding_state
);
2726 #if defined (BINDING_STATE_DEBUG)
2732 LEASE_INSERTP(lq
, comp
);
2737 /* For a given lease, sort it onto the right list in its pool and put it
2738 in each appropriate hash, understanding that it's already by definition
2739 in lease_ip_addr_hash. */
2742 lease_instantiate(const void *key
, unsigned len
, void *object
)
2744 struct lease
*lease
= object
;
2745 struct class *class;
2746 /* XXX If the lease doesn't have a pool at this point, it's an
2747 XXX orphan, which we *should* keep around until it expires,
2748 XXX but which right now we just forget. */
2749 if (!lease
-> pool
) {
2750 lease_ip_hash_delete(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
2751 lease
->ip_addr
.len
, MDL
);
2752 return ISC_R_SUCCESS
;
2755 #if defined (FAILOVER_PROTOCOL)
2756 /* If the lease is in FTS_BACKUP but there is no peer, then the
2757 * pool must have been formerly configured for failover and
2758 * is now configured as standalone. This means we need to
2759 * move the lease to FTS_FREE to make it available. */
2760 if ((lease
->binding_state
== FTS_BACKUP
) &&
2761 (lease
->pool
->failover_peer
== NULL
)) {
2763 /* We aren't compiled for failover, so just move to FTS_FREE */
2764 if (lease
->binding_state
== FTS_BACKUP
) {
2766 lease
->binding_state
= FTS_FREE
;
2767 lease
->next_binding_state
= FTS_FREE
;
2768 lease
->rewind_binding_state
= FTS_FREE
;
2771 /* Put the lease on the right queue. Failure to queue is probably
2772 * due to a bogus binding state. In such a case, we claim success,
2773 * so that later leases in a hash_foreach are processed, but we
2774 * return early as we really don't want hw address hash entries or
2775 * other cruft to surround such a bogus entry.
2777 if (!lease_enqueue(lease
))
2778 return ISC_R_SUCCESS
;
2780 /* Record the lease in the uid hash if possible. */
2782 uid_hash_add (lease
);
2785 /* Record it in the hardware address hash if possible. */
2786 if (lease
-> hardware_addr
.hlen
) {
2787 hw_hash_add (lease
);
2790 /* If the lease has a billing class, set up the billing. */
2791 if (lease
-> billing_class
) {
2792 class = (struct class *)0;
2793 class_reference (&class, lease
-> billing_class
, MDL
);
2794 class_dereference (&lease
-> billing_class
, MDL
);
2795 /* If the lease is available for allocation, the billing
2796 is invalid, so we don't keep it. */
2797 if (lease
-> binding_state
== FTS_ACTIVE
||
2798 lease
-> binding_state
== FTS_EXPIRED
||
2799 lease
-> binding_state
== FTS_RELEASED
||
2800 lease
-> binding_state
== FTS_RESET
)
2801 bill_class (lease
, class);
2802 class_dereference (&class, MDL
);
2804 return ISC_R_SUCCESS
;
2807 /* Run expiry events on every pool. This is called on startup so that
2808 any expiry events that occurred after the server stopped and before it
2809 was restarted can be run. At the same time, if failover support is
2810 compiled in, we compute the balance of leases for the pool. */
2812 void expire_all_pools ()
2814 struct shared_network
*s
;
2818 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2820 /* Indicate that we are in the startup phase */
2821 server_starting
= SS_NOSYNC
| SS_QFOLLOW
;
2823 #if defined (BINARY_LEASES)
2824 /* set up the growth factors for the binary leases.
2825 * We use 100% for free, 50% for active and backup
2826 * 20% for expired, abandoned and reserved
2827 * but no less than 100, 50, and 20.
2829 for (s
= shared_networks
; s
; s
= s
-> next
) {
2830 for (p
= s
-> pools
; p
!= NULL
; p
= p
-> next
) {
2831 size_t num_f
= 100, num_a
= 50, num_e
= 20;
2832 if (p
->lease_count
> 100) {
2833 num_f
= p
->lease_count
;
2837 lc_init_growth(&p
->free
, num_f
);
2838 lc_init_growth(&p
->active
, num_a
);
2839 lc_init_growth(&p
->expired
, num_a
);
2840 lc_init_growth(&p
->abandoned
, num_e
);
2841 lc_init_growth(&p
->backup
, num_e
);
2842 lc_init_growth(&p
->reserved
, num_e
);
2847 /* First, go over the hash list and actually put all the leases
2848 on the appropriate lists. */
2849 lease_ip_hash_foreach(lease_ip_addr_hash
, lease_instantiate
);
2851 /* Loop through each pool in each shared network and call the
2852 * expiry routine on the pool. It is no longer safe to follow
2853 * the queue insertion point, as expiration of a lease can move
2854 * it between queues (and this may be the lease that function
2857 server_starting
&= ~SS_QFOLLOW
;
2858 for (s
= shared_networks
; s
; s
= s
-> next
) {
2859 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2862 p
-> lease_count
= 0;
2863 p
-> free_leases
= 0;
2864 p
-> backup_leases
= 0;
2866 lptr
[FREE_LEASES
] = &p
-> free
;
2867 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2868 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2869 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2870 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2871 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2873 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2874 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2876 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2878 if (l
-> ends
<= cur_time
) {
2879 if (l
->binding_state
== FTS_FREE
) {
2880 if (i
== FREE_LEASES
)
2882 else if (i
!= RESERVED_LEASES
)
2883 log_fatal("Impossible case "
2885 } else if (l
->binding_state
== FTS_BACKUP
) {
2886 if (i
== BACKUP_LEASES
)
2888 else if (i
!= RESERVED_LEASES
)
2889 log_fatal("Impossible case "
2893 #if defined (FAILOVER_PROTOCOL)
2894 if (p
-> failover_peer
&&
2895 l
-> tstp
> l
-> atsfp
&&
2896 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2897 l
-> desired_binding_state
= l
-> binding_state
;
2898 dhcp_failover_queue_update (l
, 1);
2906 /* turn off startup phase */
2907 server_starting
= 0;
2910 void dump_subnets ()
2913 struct shared_network
*s
;
2916 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
2919 log_info ("Subnets:");
2920 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2921 log_debug (" Subnet %s", piaddr (n
-> net
));
2922 log_debug (" netmask %s",
2923 piaddr (n
-> netmask
));
2925 log_info ("Shared networks:");
2926 for (s
= shared_networks
; s
; s
= s
-> next
) {
2927 log_info (" %s", s
-> name
);
2928 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2929 lptr
[FREE_LEASES
] = &p
-> free
;
2930 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2931 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2932 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2933 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2934 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2936 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2937 for (l
= LEASE_GET_FIRSTP(lptr
[i
]);
2939 l
= LEASE_GET_NEXTP(lptr
[i
], l
)) {
2947 HASH_FUNCTIONS(lease_ip
, const unsigned char *, struct lease
, lease_ip_hash_t
,
2948 lease_reference
, lease_dereference
, do_ip4_hash
)
2949 HASH_FUNCTIONS(lease_id
, const unsigned char *, struct lease
, lease_id_hash_t
,
2950 lease_reference
, lease_dereference
, do_id_hash
)
2951 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2952 host_reference
, host_dereference
, do_string_hash
)
2953 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2954 class_reference
, class_dereference
, do_string_hash
)
2956 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2957 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2958 extern struct hash_table
*dns_zone_hash
;
2959 extern struct interface_info
**interface_vector
;
2960 extern int interface_count
;
2961 dhcp_control_object_t
*dhcp_control_object
;
2962 extern struct hash_table
*auth_key_hash
;
2963 struct hash_table
*universe_hash
;
2964 struct universe
**universes
;
2965 int universe_count
, universe_max
;
2970 #if defined (COMPACT_LEASES)
2971 extern struct lease
*lease_hunks
;
2974 void free_everything(void)
2976 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2977 struct shared_network
*nc
= (struct shared_network
*)0,
2978 *nn
= (struct shared_network
*)0;
2979 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2980 struct lease
*lc
= NULL
, *ln
= NULL
, *ltemp
= NULL
;
2981 struct interface_info
*ic
= (struct interface_info
*)0,
2982 *in
= (struct interface_info
*)0;
2983 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2984 struct collection
*lp
;
2987 /* Get rid of all the hash tables. */
2988 if (host_hw_addr_hash
)
2989 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2990 host_hw_addr_hash
= 0;
2992 host_free_hash_table (&host_uid_hash
, MDL
);
2995 lease_id_free_hash_table (&lease_uid_hash
, MDL
);
2997 if (lease_ip_addr_hash
)
2998 lease_ip_free_hash_table (&lease_ip_addr_hash
, MDL
);
2999 lease_ip_addr_hash
= 0;
3000 if (lease_hw_addr_hash
)
3001 lease_id_free_hash_table (&lease_hw_addr_hash
, MDL
);
3002 lease_hw_addr_hash
= 0;
3004 host_free_hash_table (&host_name_hash
, MDL
);
3007 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
3010 while (host_id_info
!= NULL
) {
3011 host_id_info_t
*tmp
;
3012 option_dereference(&host_id_info
->option
, MDL
);
3013 host_free_hash_table(&host_id_info
->values_hash
, MDL
);
3014 tmp
= host_id_info
->next
;
3015 dfree(host_id_info
, MDL
);
3020 auth_key_free_hash_table (&auth_key_hash
, MDL
);
3024 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
3027 for (lp
= collections
; lp
; lp
= lp
-> next
) {
3028 if (lp
-> classes
) {
3029 class_reference (&cn
, lp
-> classes
, MDL
);
3032 class_reference (&cc
, cn
, MDL
);
3033 class_dereference (&cn
, MDL
);
3036 class_reference (&cn
, cc
-> nic
, MDL
);
3037 class_dereference (&cc
-> nic
, MDL
);
3039 group_dereference (&cc
-> group
, MDL
);
3041 class_free_hash_table (&cc
-> hash
, MDL
);
3042 cc
-> hash
= (struct hash_table
*)0;
3044 class_dereference (&cc
, MDL
);
3046 class_dereference (&lp
-> classes
, MDL
);
3050 if (interface_vector
) {
3051 for (i
= 0; i
< interface_count
; i
++) {
3052 if (interface_vector
[i
])
3053 interface_dereference (&interface_vector
[i
], MDL
);
3055 dfree (interface_vector
, MDL
);
3056 interface_vector
= 0;
3060 interface_reference (&in
, interfaces
, MDL
);
3063 interface_reference (&ic
, in
, MDL
);
3064 interface_dereference (&in
, MDL
);
3067 interface_reference (&in
, ic
-> next
, MDL
);
3068 interface_dereference (&ic
-> next
, MDL
);
3070 omapi_unregister_io_object ((omapi_object_t
*)ic
);
3071 if (ic
-> shared_network
) {
3072 if (ic
-> shared_network
-> interface
)
3073 interface_dereference
3074 (&ic
-> shared_network
-> interface
, MDL
);
3075 shared_network_dereference (&ic
-> shared_network
, MDL
);
3077 interface_dereference (&ic
, MDL
);
3079 interface_dereference (&interfaces
, MDL
);
3082 /* Subnets are complicated because of the extra links. */
3084 subnet_reference (&sn
, subnets
, MDL
);
3087 subnet_reference (&sc
, sn
, MDL
);
3088 subnet_dereference (&sn
, MDL
);
3090 if (sc
-> next_subnet
) {
3091 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
3092 subnet_dereference (&sc
-> next_subnet
, MDL
);
3094 if (sc
-> next_sibling
)
3095 subnet_dereference (&sc
-> next_sibling
, MDL
);
3096 if (sc
-> shared_network
)
3097 shared_network_dereference (&sc
-> shared_network
, MDL
);
3098 group_dereference (&sc
-> group
, MDL
);
3099 if (sc
-> interface
)
3100 interface_dereference (&sc
-> interface
, MDL
);
3101 subnet_dereference (&sc
, MDL
);
3103 subnet_dereference (&subnets
, MDL
);
3106 /* So are shared networks. */
3107 /* XXX: this doesn't work presently, but i'm ok just filtering
3108 * it out of the noise (you get a bigger spike on the real leaks).
3109 * It would be good to fix this, but it is not a "real bug," so not
3110 * today. This hack is incomplete, it doesn't trim out sub-values.
3112 if (shared_networks
) {
3113 shared_network_dereference (&shared_networks
, MDL
);
3114 /* This is the old method (tries to free memory twice, broken) */
3116 shared_network_reference (&nn
, shared_networks
, MDL
);
3119 shared_network_reference (&nc
, nn
, MDL
);
3120 shared_network_dereference (&nn
, MDL
);
3123 shared_network_reference (&nn
, nc
-> next
, MDL
);
3124 shared_network_dereference (&nc
-> next
, MDL
);
3129 pool_reference (&pn
, nc
-> pools
, MDL
);
3131 LEASE_STRUCT_PTR lptr
[RESERVED_LEASES
+1];
3134 pool_reference (&pc
, pn
, MDL
);
3135 pool_dereference (&pn
, MDL
);
3138 pool_reference (&pn
, pc
-> next
, MDL
);
3139 pool_dereference (&pc
-> next
, MDL
);
3142 lptr
[FREE_LEASES
] = &pc
-> free
;
3143 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
3144 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
3145 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
3146 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
3147 lptr
[RESERVED_LEASES
] = &pc
->reserved
;
3149 /* As (sigh) are leases. */
3150 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
3151 if (LEASE_NOT_EMPTYP(lptr
[i
])) {
3152 lease_reference(&ln
, LEASE_GET_FIRSTP(lptr
[i
]), MDL
);
3154 /* save a pointer to the current lease */
3155 lease_reference (&lc
, ln
, MDL
);
3156 lease_dereference (&ln
, MDL
);
3158 /* get the next lease if there is one */
3159 ltemp
= LEASE_GET_NEXTP(lptr
[i
], lc
);
3160 if (ltemp
!= NULL
) {
3161 lease_reference(&ln
, ltemp
, MDL
);
3164 /* remove the current lease from the queue */
3165 LEASE_REMOVEP(lptr
[i
], lc
);
3167 if (lc
-> billing_class
)
3168 class_dereference (&lc
-> billing_class
,
3171 free_lease_state (lc
-> state
, MDL
);
3172 lc
-> state
= (struct lease_state
*)0;
3174 lease_dereference (&lc
-> n_hw
, MDL
);
3176 lease_dereference (&lc
-> n_uid
, MDL
);
3177 lease_dereference (&lc
, MDL
);
3182 group_dereference (&pc
-> group
, MDL
);
3183 if (pc
-> shared_network
)
3184 shared_network_dereference (&pc
-> shared_network
,
3186 pool_dereference (&pc
, MDL
);
3188 pool_dereference (&nc
-> pools
, MDL
);
3190 /* Because of a circular reference, we need to nuke this
3192 group_dereference (&nc
-> group
, MDL
);
3193 shared_network_dereference (&nc
, MDL
);
3195 shared_network_dereference (&shared_networks
, MDL
);
3198 cancel_all_timeouts ();
3199 relinquish_timeouts ();
3200 #if defined(DELAYED_ACK)
3201 relinquish_ackqueue();
3204 group_dereference (&root_group
, MDL
);
3205 executable_statement_dereference (&default_classification_rules
, MDL
);
3207 shutdown_state
= shutdown_drop_omapi_connections
;
3208 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3209 shutdown_state
= shutdown_listeners
;
3210 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3211 shutdown_state
= shutdown_dhcp
;
3212 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
3214 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
3216 universe_free_hash_table (&universe_hash
, MDL
);
3217 for (i
= 0; i
< universe_count
; i
++) {
3224 if (universes
[i
]) {
3225 if (universes
[i
]->name_hash
)
3226 option_name_free_hash_table(
3227 &universes
[i
]->name_hash
,
3229 if (universes
[i
]->code_hash
)
3230 option_code_free_hash_table(
3231 &universes
[i
]->code_hash
,
3234 if (universes
[i
] -> name
> (char *)&end
) {
3235 foo
.c
= universes
[i
] -> name
;
3238 if (universes
[i
] > (struct universe
*)&end
)
3239 dfree (universes
[i
], MDL
);
3243 dfree (universes
, MDL
);
3245 relinquish_free_lease_states ();
3246 relinquish_free_pairs ();
3247 relinquish_free_expressions ();
3248 relinquish_free_binding_values ();
3249 relinquish_free_option_caches ();
3250 relinquish_free_packets ();
3251 #if defined(COMPACT_LEASES)
3252 relinquish_lease_hunks ();
3254 relinquish_hash_bucket_hunks ();
3255 omapi_type_relinquish ();
3257 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */