3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2006 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
36 static char copyright
[] =
37 "$Id: mdb.c,v 1.90 2007/05/19 18:47:15 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
41 #include "omapip/hash.h"
43 struct subnet
*subnets
;
44 struct shared_network
*shared_networks
;
45 host_hash_t
*host_hw_addr_hash
;
46 host_hash_t
*host_uid_hash
;
47 host_hash_t
*host_name_hash
;
48 lease_id_hash_t
*lease_uid_hash
;
49 lease_ip_hash_t
*lease_ip_addr_hash
;
50 lease_id_hash_t
*lease_hw_addr_hash
;
53 * We allow users to specify any option as a host identifier.
55 * Any host is uniquely identified by the combination of
56 * option type & option data.
58 * We expect people will only use a few types of options as host
59 * identifier. Because of this, we store a list with an entry for
60 * each option type. Each of these has a hash table, which contains
61 * hash of the option data.
63 typedef struct host_id_info
{
64 struct option
*option
;
65 host_hash_t
*values_hash
;
66 struct host_id_info
*next
;
69 static host_id_info_t
*host_id_info
= NULL
;
71 int numclasseswritten
;
73 omapi_object_type_t
*dhcp_type_host
;
75 isc_result_t
enter_class(cd
, dynamicp
, commit
)
80 if (!collections
-> classes
) {
81 /* A subclass with no parent is invalid. */
83 return ISC_R_INVALIDARG
;
85 class_reference (&collections
-> classes
, cd
, MDL
);
86 } else if (cd
->name
!= NULL
) { /* regular class */
89 if (find_class(&c
, cd
->name
, MDL
) != ISC_R_NOTFOUND
) {
90 class_dereference(&c
, MDL
);
95 for (c
= collections
-> classes
;
96 c
-> nic
; c
= c
-> nic
)
98 class_reference (&c
-> nic
, cd
, MDL
);
101 if (dynamicp
&& commit
) {
102 const char *name
= cd
->name
;
105 name
= cd
->superclass
->name
;
108 write_named_billing_class ((const unsigned char *)name
, 0, cd
);
109 if (!commit_leases ())
110 return ISC_R_IOERROR
;
113 return ISC_R_SUCCESS
;
117 /* Variable to check if we're starting the server. The server will init as
118 * starting - but just to be safe start out as false to avoid triggering new
120 * XXX: There is actually a server_startup state...which is never entered...
124 static int server_starting
= 0;
126 static int find_uid_statement (struct executable_statement
*esp
,
129 struct executable_statement
**evp
= vp
;
131 if (esp
-> op
== supersede_option_statement
&&
132 esp
-> data
.option
&&
133 (esp
-> data
.option
-> option
-> universe
==
135 (esp
-> data
.option
-> option
-> code
==
136 DHO_DHCP_CLIENT_IDENTIFIER
)) {
138 log_error ("dhcp client identifier may not be %s",
139 "specified conditionally.");
140 } else if (!(*evp
)) {
141 executable_statement_reference (evp
, esp
, MDL
);
144 log_error ("only one dhcp client identifier may be %s",
152 static host_id_info_t
*
153 find_host_id_info(unsigned int option_code
) {
156 for (p
=host_id_info
; p
!= NULL
; p
= p
->next
) {
157 if (p
->option
->code
== option_code
) {
167 print_host(const void *name
, unsigned len
, void *value
) {
169 printf("--------------\n");
170 printf("name:'%s'\n", print_hex_1(len
, name
, 60));
171 printf("len:%d\n", len
);
172 h
= (struct host_decl
*)value
;
173 printf("host @%p is '%s'\n", h
, h
->name
);
174 return ISC_R_SUCCESS
;
178 hash_print_hosts(struct hash_table
*h
) {
179 hash_foreach(h
, print_host
);
180 printf("--------------\n");
185 change_host_uid(struct host_decl
*host
, const char *uid
, int len
) {
186 struct host_decl
*old_entry
;
188 /* XXX: should consolidate this type of code throughout */
189 if (host_uid_hash
== NULL
) {
190 if (!host_new_hash(&host_uid_hash
, HOST_HASH_SIZE
, MDL
)) {
191 log_fatal("Can't allocate host/uid hash");
196 * Remove the old entry, if one exists.
198 if (host
->client_identifier
.data
!= NULL
) {
199 host_hash_delete(host_uid_hash
,
200 host
->client_identifier
.data
,
201 host
->client_identifier
.len
,
203 data_string_forget(&host
->client_identifier
, MDL
);
209 memset(&host
->client_identifier
, 0, sizeof(host
->client_identifier
));
210 host
->client_identifier
.len
= len
;
211 if (!buffer_allocate(&host
->client_identifier
.buffer
, len
, MDL
)) {
212 log_fatal("Can't allocate uid buffer");
214 host
->client_identifier
.data
= host
->client_identifier
.buffer
->data
;
215 memcpy((char *)host
->client_identifier
.data
, uid
, len
);
220 host_hash_add(host_uid_hash
, host
->client_identifier
.data
,
221 host
->client_identifier
.len
, host
, MDL
);
224 isc_result_t
enter_host (hd
, dynamicp
, commit
)
225 struct host_decl
*hd
;
229 struct host_decl
*hp
= (struct host_decl
*)0;
230 struct host_decl
*np
= (struct host_decl
*)0;
231 struct executable_statement
*esp
;
232 host_id_info_t
*h_id_info
;
234 if (!host_name_hash
) {
235 if (!host_new_hash(&host_name_hash
, HOST_HASH_SIZE
, MDL
))
236 log_fatal ("Can't allocate host name hash");
237 host_hash_add (host_name_hash
,
238 (unsigned char *)hd
-> name
,
239 strlen (hd
-> name
), hd
, MDL
);
241 host_hash_lookup (&hp
, host_name_hash
,
242 (unsigned char *)hd
-> name
,
243 strlen (hd
-> name
), MDL
);
245 /* If it's deleted, we can supersede it. */
246 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
247 host_hash_delete (host_name_hash
,
248 (unsigned char *)hd
-> name
,
249 strlen (hd
-> name
), MDL
);
250 /* If the old entry wasn't dynamic, then we
251 always have to keep the deletion. */
252 if (hp
-> flags
& HOST_DECL_STATIC
) {
253 hd
-> flags
|= HOST_DECL_STATIC
;
255 host_dereference (&hp
, MDL
);
258 /* If we are updating an existing host declaration, we
259 can just delete it and add it again. */
260 if (hp
&& hp
== hd
) {
261 host_dereference (&hp
, MDL
);
263 if (!write_host (hd
))
264 return ISC_R_IOERROR
;
265 hd
-> flags
&= ~HOST_DECL_DELETED
;
268 /* If there isn't already a host decl matching this
269 address, add it to the hash table. */
271 host_hash_add (host_name_hash
,
272 (unsigned char *)hd
-> name
,
273 strlen (hd
-> name
), hd
, MDL
);
275 /* XXX actually, we have to delete the old one
276 XXX carefully and replace it. Not done yet. */
277 host_dereference (&hp
, MDL
);
283 host_dereference (&hd
-> n_ipaddr
, MDL
);
286 hd
-> type
= dhcp_type_host
;
288 if (hd
-> interface
.hlen
) {
289 if (!host_hw_addr_hash
) {
290 if (!host_new_hash(&host_hw_addr_hash
,
291 HOST_HASH_SIZE
, MDL
))
292 log_fatal ("Can't allocate host/hw hash");
294 /* If there isn't already a host decl matching this
295 address, add it to the hash table. */
296 host_hash_lookup (&hp
, host_hw_addr_hash
,
297 hd
-> interface
.hbuf
,
298 hd
-> interface
.hlen
, MDL
);
301 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
302 hd
-> interface
.hlen
, hd
, MDL
);
304 /* If there was already a host declaration for
305 this hardware address, add this one to the
307 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
309 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
310 host_dereference (&hp
, MDL
);
314 /* See if there's a statement that sets the client identifier.
315 This is a kludge - the client identifier really shouldn't be
316 set with an executable statement. */
317 esp
= (struct executable_statement
*)0;
318 if (executable_statement_foreach (hd
-> group
-> statements
,
319 find_uid_statement
, &esp
, 0)) {
320 evaluate_option_cache (&hd
-> client_identifier
,
323 (struct client_state
*)0,
324 (struct option_state
*)0,
325 (struct option_state
*)0, &global_scope
,
326 esp
-> data
.option
, MDL
);
329 /* If we got a client identifier, hash this entry by
330 client identifier. */
331 if (hd
-> client_identifier
.len
) {
332 /* If there's no uid hash, make one; otherwise, see if
333 there's already an entry in the hash for this host. */
334 if (!host_uid_hash
) {
335 if (!host_new_hash(&host_uid_hash
,
336 HOST_HASH_SIZE
, MDL
))
337 log_fatal ("Can't allocate host/uid hash");
339 host_hash_add (host_uid_hash
,
340 hd
-> client_identifier
.data
,
341 hd
-> client_identifier
.len
,
344 /* If there's already a host declaration for this
345 client identifier, add this one to the end of the
346 list. Otherwise, add it to the hash table. */
347 if (host_hash_lookup (&hp
, host_uid_hash
,
348 hd
-> client_identifier
.data
,
349 hd
-> client_identifier
.len
,
351 /* Don't link it in twice... */
353 for (np
= hp
; np
-> n_ipaddr
;
354 np
= np
-> n_ipaddr
) {
359 host_reference (&np
-> n_ipaddr
,
362 host_dereference (&hp
, MDL
);
364 host_hash_add (host_uid_hash
,
365 hd
-> client_identifier
.data
,
366 hd
-> client_identifier
.len
,
374 * If we use an option as our host identifier, record it here.
376 if (hd
->host_id_option
!= NULL
) {
378 * Look for the host identifier information for this option,
379 * and create a new entry if there is none.
381 h_id_info
= find_host_id_info(hd
->host_id_option
->code
);
382 if (h_id_info
== NULL
) {
383 h_id_info
= dmalloc(sizeof(*h_id_info
), MDL
);
384 if (h_id_info
== NULL
) {
385 log_fatal("No memory for host-identifier "
386 "option information.");
388 option_reference(&h_id_info
->option
,
389 hd
->host_id_option
, MDL
);
390 if (!host_new_hash(&h_id_info
->values_hash
,
391 HOST_HASH_SIZE
, MDL
)) {
392 log_fatal("No memory for host-identifer "
395 h_id_info
->next
= host_id_info
;
396 host_id_info
= h_id_info
;
399 if (host_hash_lookup(&hp
, h_id_info
->values_hash
,
400 hd
->host_id
.data
, hd
->host_id
.len
, MDL
)) {
402 * If this option is already present, then add
403 * this host to the list in n_ipaddr, unless
404 * we have already done so previously.
406 * XXXSK: This seems scary to me, but I don't
407 * fully understand how these are used.
408 * Shouldn't there be multiple lists, or
409 * maybe we should just forbid duplicates?
413 while (np
->n_ipaddr
!= NULL
) {
417 host_reference(&np
->n_ipaddr
, hd
, MDL
);
420 host_dereference(&hp
, MDL
);
422 host_hash_add(h_id_info
->values_hash
,
429 if (dynamicp
&& commit
) {
430 if (!write_host (hd
))
431 return ISC_R_IOERROR
;
432 if (!commit_leases ())
433 return ISC_R_IOERROR
;
436 return ISC_R_SUCCESS
;
440 isc_result_t
delete_class (cp
, commit
)
444 cp
->flags
|= CLASS_DECL_DELETED
;
446 /* do the write first as we won't be leaving it in any data
447 structures, unlike the host objects */
450 write_named_billing_class ((unsigned char *)cp
->name
, 0, cp
);
451 if (!commit_leases ())
452 return ISC_R_IOERROR
;
455 unlink_class(&cp
); /* remove from collections */
457 class_dereference(&cp
, MDL
);
459 return ISC_R_SUCCESS
;
463 isc_result_t
delete_host (hd
, commit
)
464 struct host_decl
*hd
;
467 struct host_decl
*hp
= (struct host_decl
*)0;
468 struct host_decl
*np
= (struct host_decl
*)0;
469 struct host_decl
*foo
;
470 struct executable_statement
*esp
;
471 int hw_head
= 0, uid_head
= 1;
473 /* Don't need to do it twice. */
474 if (hd
-> flags
& HOST_DECL_DELETED
)
475 return ISC_R_SUCCESS
;
477 /* But we do need to do it once! :') */
478 hd
-> flags
|= HOST_DECL_DELETED
;
480 if (hd
-> interface
.hlen
) {
481 if (host_hw_addr_hash
) {
482 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
483 hd
-> interface
.hbuf
,
484 hd
-> interface
.hlen
, MDL
)) {
486 host_hash_delete (host_hw_addr_hash
,
487 hd
-> interface
.hbuf
,
488 hd
-> interface
.hlen
, MDL
);
491 np
= (struct host_decl
*)0;
492 foo
= (struct host_decl
*)0;
493 host_reference (&foo
, hp
, MDL
);
498 host_dereference (&np
, MDL
);
499 host_reference (&np
, foo
, MDL
);
500 host_dereference (&foo
, MDL
);
502 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
506 host_dereference (&np
-> n_ipaddr
, MDL
);
508 host_reference (&np
-> n_ipaddr
,
509 hd
-> n_ipaddr
, MDL
);
510 host_dereference (&foo
, MDL
);
513 host_dereference (&np
, MDL
);
515 host_dereference (&hp
, MDL
);
520 /* If we got a client identifier, hash this entry by
521 client identifier. */
522 if (hd
-> client_identifier
.len
) {
524 if (host_hash_lookup (&hp
, host_uid_hash
,
525 hd
-> client_identifier
.data
,
526 hd
-> client_identifier
.len
, MDL
)) {
528 host_hash_delete (host_uid_hash
,
529 hd
-> client_identifier
.data
,
530 hd
-> client_identifier
.len
, MDL
);
533 np
= (struct host_decl
*)0;
534 foo
= (struct host_decl
*)0;
535 host_reference (&foo
, hp
, MDL
);
540 host_dereference (&np
, MDL
);
541 host_reference (&np
, foo
, MDL
);
542 host_dereference (&foo
, MDL
);
544 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
548 host_dereference (&np
-> n_ipaddr
, MDL
);
550 host_reference (&np
-> n_ipaddr
,
551 hd
-> n_ipaddr
, MDL
);
552 host_dereference (&foo
, MDL
);
555 host_dereference (&np
, MDL
);
557 host_dereference (&hp
, MDL
);
562 if (hd
->host_id_option
!= NULL
) {
563 option_dereference(&hd
->host_id_option
, MDL
);
564 data_string_forget(&hd
->host_id
, MDL
);
567 if (hd
-> n_ipaddr
) {
568 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
571 hd
-> n_ipaddr
-> client_identifier
.data
,
572 hd
-> n_ipaddr
-> client_identifier
.len
,
573 hd
-> n_ipaddr
, MDL
);
575 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
576 host_hash_add (host_hw_addr_hash
,
577 hd
-> n_ipaddr
-> interface
.hbuf
,
578 hd
-> n_ipaddr
-> interface
.hlen
,
579 hd
-> n_ipaddr
, MDL
);
581 host_dereference (&hd
-> n_ipaddr
, MDL
);
584 if (host_name_hash
) {
585 if (host_hash_lookup (&hp
, host_name_hash
,
586 (unsigned char *)hd
-> name
,
587 strlen (hd
-> name
), MDL
)) {
588 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
589 host_hash_delete (host_name_hash
,
590 (unsigned char *)hd
-> name
,
591 strlen (hd
-> name
), MDL
);
593 host_dereference (&hp
, MDL
);
598 if (!write_host (hd
))
599 return ISC_R_IOERROR
;
600 if (!commit_leases ())
601 return ISC_R_IOERROR
;
603 return ISC_R_SUCCESS
;
606 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
607 const unsigned char *haddr
, unsigned hlen
,
608 const char *file
, int line
)
610 struct host_decl
*foo
;
615 memcpy (&h
.hbuf
[1], haddr
, hlen
);
617 return host_hash_lookup (hp
, host_hw_addr_hash
,
618 h
.hbuf
, h
.hlen
, file
, line
);
621 int find_hosts_by_uid (struct host_decl
**hp
,
622 const unsigned char *data
, unsigned len
,
623 const char *file
, int line
)
625 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
629 find_hosts_by_option(struct host_decl
**hp
,
630 struct packet
*packet
,
631 struct option_state
*opt_state
,
632 const char *file
, int line
) {
634 struct option_cache
*oc
;
635 struct data_string data
;
638 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
639 oc
= lookup_option(p
->option
->universe
,
640 opt_state
, p
->option
->code
);
642 memset(&data
, 0, sizeof(data
));
643 if (!evaluate_option_cache(&data
, packet
, NULL
, NULL
,
647 log_error("Error evaluating option cache");
651 found
= host_hash_lookup(hp
, p
->values_hash
,
655 data_string_forget(&data
, MDL
);
665 /* More than one host_decl can be returned by find_hosts_by_haddr or
666 find_hosts_by_uid, and each host_decl can have multiple addresses.
667 Loop through the list of hosts, and then for each host, through the
668 list of addresses, looking for an address that's in the same shared
669 network as the one specified. Store the matching address through
670 the addr pointer, update the host pointer to point at the host_decl
671 that matched, and return the subnet that matched. */
673 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
674 struct iaddr
*addr
, struct shared_network
*share
)
677 struct subnet
*subnet
;
678 struct iaddr ip_address
;
679 struct host_decl
*hp
;
680 struct data_string fixed_addr
;
682 memset (&fixed_addr
, 0, sizeof fixed_addr
);
684 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
685 if (!hp
-> fixed_addr
)
687 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
689 (struct client_state
*)0,
690 (struct option_state
*)0,
691 (struct option_state
*)0,
693 hp
-> fixed_addr
, MDL
))
695 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
697 memcpy (ip_address
.iabuf
,
698 fixed_addr
.data
+ i
, 4);
699 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
700 struct host_decl
*tmp
= (struct host_decl
*)0;
702 /* This is probably not necessary, but
703 just in case *host is the only reference
704 to that host declaration, make a temporary
705 reference so that dereferencing it doesn't
706 dereference hp out from under us. */
707 host_reference (&tmp
, *host
, MDL
);
708 host_dereference (host
, MDL
);
709 host_reference (host
, hp
, MDL
);
710 host_dereference (&tmp
, MDL
);
711 data_string_forget (&fixed_addr
, MDL
);
715 data_string_forget (&fixed_addr
, MDL
);
720 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
722 struct iaddr low
, high
;
723 struct subnet
*subnet
;
725 struct lease
**lpchain
;
727 struct lease
*address_range
, *lp
, *plp
;
729 unsigned min
, max
, i
;
730 char lowbuf
[16], highbuf
[16], netbuf
[16];
731 struct shared_network
*share
= subnet
-> shared_network
;
733 struct lease
*lt
= (struct lease
*)0;
735 /* All subnets should have attached shared network structures. */
737 strcpy (netbuf
, piaddr (subnet
-> net
));
738 log_fatal ("No shared network for network %s (%s)",
739 netbuf
, piaddr (subnet
-> netmask
));
742 /* Initialize the hash table if it hasn't been done yet. */
743 if (!lease_uid_hash
) {
744 if (!lease_id_new_hash(&lease_uid_hash
, LEASE_HASH_SIZE
, MDL
))
745 log_fatal ("Can't allocate lease/uid hash");
747 if (!lease_ip_addr_hash
) {
748 if (!lease_ip_new_hash(&lease_ip_addr_hash
, LEASE_HASH_SIZE
,
750 log_fatal ("Can't allocate lease/ip hash");
752 if (!lease_hw_addr_hash
) {
753 if (!lease_id_new_hash(&lease_hw_addr_hash
, LEASE_HASH_SIZE
,
755 log_fatal ("Can't allocate lease/hw hash");
758 /* Make sure that high and low addresses are in same subnet. */
759 net
= subnet_number (low
, subnet
-> netmask
);
760 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
761 strcpy (lowbuf
, piaddr (low
));
762 strcpy (highbuf
, piaddr (high
));
763 strcpy (netbuf
, piaddr (subnet
-> netmask
));
764 log_fatal ("Address range %s to %s, netmask %s spans %s!",
765 lowbuf
, highbuf
, netbuf
, "multiple subnets");
768 /* Make sure that the addresses are on the correct subnet. */
769 if (!addr_eq (net
, subnet
-> net
)) {
770 strcpy (lowbuf
, piaddr (low
));
771 strcpy (highbuf
, piaddr (high
));
772 strcpy (netbuf
, piaddr (subnet
-> netmask
));
773 log_fatal ("Address range %s to %s not on net %s/%s!",
774 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
777 /* Get the high and low host addresses... */
778 max
= host_addr (high
, subnet
-> netmask
);
779 min
= host_addr (low
, subnet
-> netmask
);
781 /* Allow range to be specified high-to-low as well as low-to-high. */
784 min
= host_addr (high
, subnet
-> netmask
);
787 /* Get a lease structure for each address in the range. */
788 #if defined (COMPACT_LEASES)
789 address_range
= new_leases (max
- min
+ 1, MDL
);
790 if (!address_range
) {
791 strcpy (lowbuf
, piaddr (low
));
792 strcpy (highbuf
, piaddr (high
));
793 log_fatal ("No memory for address range %s-%s.",
798 /* Fill out the lease structures with some minimal information. */
799 for (i
= 0; i
< max
- min
+ 1; i
++) {
800 struct lease
*lp
= (struct lease
*)0;
801 #if defined (COMPACT_LEASES)
802 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
804 0, sizeof (struct lease
), MDL
);
805 lease_reference (&lp
, &address_range
[i
], MDL
);
807 status
= lease_allocate (&lp
, MDL
);
808 if (status
!= ISC_R_SUCCESS
)
809 log_fatal ("No memory for lease %s: %s",
810 piaddr (ip_addr (subnet
-> net
,
813 isc_result_totext (status
));
815 lp
-> ip_addr
= ip_addr (subnet
-> net
,
816 subnet
-> netmask
, i
+ min
);
817 lp
-> starts
= MIN_TIME
;
818 lp
-> ends
= MIN_TIME
;
819 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
820 pool_reference (&lp
-> pool
, pool
, MDL
);
821 lp
-> binding_state
= FTS_FREE
;
822 lp
-> next_binding_state
= FTS_FREE
;
825 /* Remember the lease in the IP address hash. */
826 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
829 "lease %s is declared twice!",
830 piaddr (lp
-> ip_addr
));
832 pool_reference (<
-> pool
, pool
, MDL
);
833 lease_dereference (<
, MDL
);
835 lease_ip_hash_add(lease_ip_addr_hash
,
836 lp
->ip_addr
.iabuf
, lp
->ip_addr
.len
,
838 /* Put the lease on the chain for the caller. */
841 lease_reference (&lp
-> next
, *lpchain
, MDL
);
842 lease_dereference (lpchain
, MDL
);
844 lease_reference (lpchain
, lp
, MDL
);
846 lease_dereference (&lp
, MDL
);
850 int find_subnet (struct subnet
**sp
,
851 struct iaddr addr
, const char *file
, int line
)
855 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
856 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
857 if (subnet_reference (sp
, rv
,
858 file
, line
) != ISC_R_SUCCESS
)
866 int find_grouped_subnet (struct subnet
**sp
,
867 struct shared_network
*share
, struct iaddr addr
,
868 const char *file
, int line
)
872 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
873 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
874 if (subnet_reference (sp
, rv
,
875 file
, line
) != ISC_R_SUCCESS
)
883 /* XXX: could speed up if everyone had a prefix length */
885 subnet_inner_than(const struct subnet
*subnet
,
886 const struct subnet
*scan
,
888 if (addr_eq(subnet_number(subnet
->net
, scan
->netmask
), scan
->net
) ||
889 addr_eq(subnet_number(scan
->net
, subnet
->netmask
), subnet
->net
)) {
890 char n1buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
892 for (i
= 0; i
< 128; i
++)
893 if (subnet
->netmask
.iabuf
[3 - (i
>> 3)]
896 for (j
= 0; j
< 128; j
++)
897 if (scan
->netmask
.iabuf
[3 - (j
>> 3)] &
901 strcpy(n1buf
, piaddr(subnet
->net
));
902 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
904 piaddr(scan
->net
), 32 - j
);
912 /* Enter a new subnet into the subnet list. */
913 void enter_subnet (subnet
)
914 struct subnet
*subnet
;
916 struct subnet
*scan
= (struct subnet
*)0;
917 struct subnet
*next
= (struct subnet
*)0;
918 struct subnet
*prev
= (struct subnet
*)0;
920 /* Check for duplicates... */
922 subnet_reference (&next
, subnets
, MDL
);
924 subnet_reference (&scan
, next
, MDL
);
925 subnet_dereference (&next
, MDL
);
927 /* When we find a conflict, make sure that the
928 subnet with the narrowest subnet mask comes
930 if (subnet_inner_than (subnet
, scan
, 1)) {
932 if (prev
-> next_subnet
)
933 subnet_dereference (&prev
-> next_subnet
, MDL
);
934 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
935 subnet_dereference (&prev
, MDL
);
937 subnet_dereference (&subnets
, MDL
);
938 subnet_reference (&subnets
, subnet
, MDL
);
940 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
941 subnet_dereference (&scan
, MDL
);
944 subnet_reference (&prev
, scan
, MDL
);
945 subnet_dereference (&scan
, MDL
);
948 subnet_dereference (&prev
, MDL
);
950 /* XXX use the BSD radix tree code instead of a linked list. */
952 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
953 subnet_dereference (&subnets
, MDL
);
955 subnet_reference (&subnets
, subnet
, MDL
);
958 /* Enter a new shared network into the shared network list. */
960 void enter_shared_network (share
)
961 struct shared_network
*share
;
963 if (shared_networks
) {
964 shared_network_reference (&share
-> next
,
965 shared_networks
, MDL
);
966 shared_network_dereference (&shared_networks
, MDL
);
968 shared_network_reference (&shared_networks
, share
, MDL
);
971 void new_shared_network_interface (cfile
, share
, name
)
973 struct shared_network
*share
;
976 struct interface_info
*ip
;
979 if (share
-> interface
) {
981 "A subnet or shared network can't be connected %s",
982 "to two interfaces.");
986 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
987 if (!strcmp (ip
-> name
, name
))
990 status
= interface_allocate (&ip
, MDL
);
991 if (status
!= ISC_R_SUCCESS
)
992 log_fatal ("new_shared_network_interface %s: %s",
993 name
, isc_result_totext (status
));
994 if (strlen (name
) > sizeof ip
-> name
) {
995 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
996 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
998 strcpy (ip
-> name
, name
);
1000 interface_reference (&ip
-> next
, interfaces
, MDL
);
1001 interface_dereference (&interfaces
, MDL
);
1003 interface_reference (&interfaces
, ip
, MDL
);
1004 ip
-> flags
= INTERFACE_REQUESTED
;
1005 /* XXX this is a reference loop. */
1006 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
1007 interface_reference (&share
-> interface
, ip
, MDL
);
1011 /* Enter a lease into the system. This is called by the parser each
1012 time it reads in a new lease. If the subnet for that lease has
1013 already been read in (usually the case), just update that lease;
1014 otherwise, allocate temporary storage for the lease and keep it around
1015 until we're done reading in the config file. */
1017 void enter_lease (lease
)
1018 struct lease
*lease
;
1020 struct lease
*comp
= (struct lease
*)0;
1021 isc_result_t status
;
1023 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
1024 if (!comp
-> pool
) {
1025 log_error ("undeclared lease found in database: %s",
1026 piaddr (lease
-> ip_addr
));
1028 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
1031 subnet_reference (&lease
-> subnet
,
1032 comp
-> subnet
, MDL
);
1033 lease_ip_hash_delete(lease_ip_addr_hash
,
1034 lease
->ip_addr
.iabuf
, lease
->ip_addr
.len
,
1036 lease_dereference (&comp
, MDL
);
1039 /* The only way a lease can get here without a subnet is if it's in
1040 the lease file, but not in the dhcpd.conf file. In this case, we
1041 *should* keep it around until it's expired, but never reallocate it
1042 or renew it. Currently, to maintain consistency, we are not doing
1044 XXX fix this so that the lease is kept around until it expires.
1045 XXX this will be important in IPv6 with addresses that become
1046 XXX non-renewable as a result of a renumbering event. */
1048 if (!lease
-> subnet
) {
1049 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
1052 lease_ip_hash_add(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
1053 lease
->ip_addr
.len
, lease
, MDL
);
1056 /* Replace the data in an existing lease with the data in a new lease;
1057 adjust hash tables to suit, and insertion sort the lease into the
1058 list of leases by expiry time so that we can always find the oldest
1061 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
1062 struct lease
*comp
, *lease
;
1068 int enter_hwaddr
= 0;
1069 struct lease
*lp
, **lq
, *prev
;
1071 #if defined (FAILOVER_PROTOCOL)
1072 int do_pool_check
= 0;
1074 /* We must commit leases before sending updates regarding them
1075 to failover peers. It is, therefore, an error to set pimmediate
1077 if (pimmediate
&& !commit
)
1081 /* If there is no sample lease, just do the move. */
1085 /* Static leases are not currently kept in the database... */
1086 if (lease
-> flags
& STATIC_LEASE
)
1089 /* If the existing lease hasn't expired and has a different
1090 unique identifier or, if it doesn't have a unique
1091 identifier, a different hardware address, then the two
1092 leases are in conflict. If the existing lease has a uid
1093 and the new one doesn't, but they both have the same
1094 hardware address, and dynamic bootp is allowed on this
1095 lease, then we allow that, in case a dynamic BOOTP lease is
1096 requested *after* a DHCP lease has been assigned. */
1098 if (lease
-> binding_state
!= FTS_ABANDONED
&&
1099 lease
-> next_binding_state
!= FTS_ABANDONED
&&
1100 comp
-> binding_state
== FTS_ACTIVE
&&
1101 (((comp
-> uid
&& lease
-> uid
) &&
1102 (comp
-> uid_len
!= lease
-> uid_len
||
1103 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
1105 ((comp
-> hardware_addr
.hlen
!=
1106 lease
-> hardware_addr
.hlen
) ||
1107 memcmp (comp
-> hardware_addr
.hbuf
,
1108 lease
-> hardware_addr
.hbuf
,
1109 comp
-> hardware_addr
.hlen
))))) {
1110 log_error ("Lease conflict at %s",
1111 piaddr (comp
-> ip_addr
));
1114 /* If there's a Unique ID, dissociate it from the hash
1115 table and free it if necessary. */
1117 uid_hash_delete (comp
);
1119 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
1120 dfree (comp
-> uid
, MDL
);
1121 comp
-> uid_max
= 0;
1122 comp
-> uid_len
= 0;
1124 comp
-> uid
= (unsigned char *)0;
1128 if (comp
-> hardware_addr
.hlen
&&
1129 ((comp
-> hardware_addr
.hlen
!=
1130 lease
-> hardware_addr
.hlen
) ||
1131 memcmp (comp
-> hardware_addr
.hbuf
,
1132 lease
-> hardware_addr
.hbuf
,
1133 comp
-> hardware_addr
.hlen
))) {
1134 hw_hash_delete (comp
);
1136 } else if (!comp
-> hardware_addr
.hlen
)
1139 /* If the lease has been billed to a class, remove the billing. */
1140 if (comp
-> billing_class
!= lease
-> billing_class
) {
1141 if (comp
-> billing_class
)
1142 unbill_class (comp
, comp
-> billing_class
);
1143 if (lease
-> billing_class
)
1144 bill_class (comp
, lease
-> billing_class
);
1147 /* Copy the data files, but not the linkages. */
1148 comp
-> starts
= lease
-> starts
;
1150 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
1151 memcpy (comp
-> uid_buf
,
1152 lease
-> uid
, lease
-> uid_len
);
1153 comp
-> uid
= &comp
-> uid_buf
[0];
1154 comp
-> uid_max
= sizeof comp
-> uid_buf
;
1155 comp
-> uid_len
= lease
-> uid_len
;
1156 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
1157 comp
-> uid
= lease
-> uid
;
1158 comp
-> uid_max
= lease
-> uid_max
;
1159 lease
-> uid
= (unsigned char *)0;
1160 lease
-> uid_max
= 0;
1161 comp
-> uid_len
= lease
-> uid_len
;
1162 lease
-> uid_len
= 0;
1164 log_fatal ("corrupt lease uid."); /* XXX */
1167 comp
-> uid
= (unsigned char *)0;
1168 comp
-> uid_len
= comp
-> uid_max
= 0;
1171 host_dereference (&comp
-> host
, MDL
);
1172 host_reference (&comp
-> host
, lease
-> host
, MDL
);
1173 comp
-> hardware_addr
= lease
-> hardware_addr
;
1174 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
1175 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
1177 binding_scope_dereference (&comp
-> scope
, MDL
);
1178 if (lease
-> scope
) {
1179 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
1180 binding_scope_dereference (&lease
-> scope
, MDL
);
1183 if (comp
-> agent_options
)
1184 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
1185 if (lease
-> agent_options
) {
1186 /* Only retain the agent options if the lease is still
1187 affirmatively associated with a client. */
1188 if (lease
-> next_binding_state
== FTS_ACTIVE
||
1189 lease
-> next_binding_state
== FTS_EXPIRED
)
1190 option_chain_head_reference (&comp
-> agent_options
,
1191 lease
-> agent_options
,
1193 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
1196 /* Record the hostname information in the lease. */
1197 if (comp
-> client_hostname
)
1198 dfree (comp
-> client_hostname
, MDL
);
1199 comp
-> client_hostname
= lease
-> client_hostname
;
1200 lease
-> client_hostname
= (char *)0;
1202 if (lease
-> on_expiry
) {
1203 if (comp
-> on_expiry
)
1204 executable_statement_dereference (&comp
-> on_expiry
,
1206 executable_statement_reference (&comp
-> on_expiry
,
1210 if (lease
-> on_commit
) {
1211 if (comp
-> on_commit
)
1212 executable_statement_dereference (&comp
-> on_commit
,
1214 executable_statement_reference (&comp
-> on_commit
,
1218 if (lease
-> on_release
) {
1219 if (comp
-> on_release
)
1220 executable_statement_dereference (&comp
-> on_release
,
1222 executable_statement_reference (&comp
-> on_release
,
1223 lease
-> on_release
, MDL
);
1226 /* Record the lease in the uid hash if necessary. */
1227 if (enter_uid
&& comp
-> uid
) {
1228 uid_hash_add (comp
);
1231 /* Record it in the hardware address hash if necessary. */
1232 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
1236 comp
->cltt
= lease
->cltt
;
1237 #if defined (FAILOVER_PROTOCOL)
1238 comp
->tstp
= lease
->tstp
;
1239 comp
->tsfp
= lease
->tsfp
;
1240 comp
->atsfp
= lease
->atsfp
;
1241 #endif /* FAILOVER_PROTOCOL */
1242 comp
->ends
= lease
->ends
;
1243 comp
->next_binding_state
= lease
->next_binding_state
;
1246 #if defined (FAILOVER_PROTOCOL)
1247 /* Atsfp should be cleared upon any state change that implies
1248 * propogation whether supersede_lease was given a copy lease
1249 * structure or not (often from the pool_timer()).
1253 #endif /* FAILOVER_PROTOCOL */
1255 if (!comp
-> pool
) {
1256 log_error ("Supersede_lease: lease %s with no pool.",
1257 piaddr (comp
-> ip_addr
));
1261 /* Figure out which queue it's on. */
1262 switch (comp
-> binding_state
) {
1264 lq
= &comp
-> pool
-> free
;
1265 if (!(comp
->flags
& RESERVED_LEASE
))
1266 comp
->pool
->free_leases
--;
1268 #if defined(FAILOVER_PROTOCOL)
1274 lq
= &comp
-> pool
-> active
;
1280 lq
= &comp
-> pool
-> expired
;
1284 lq
= &comp
-> pool
-> abandoned
;
1288 lq
= &comp
-> pool
-> backup
;
1289 if (!(comp
->flags
& RESERVED_LEASE
))
1290 comp
->pool
->backup_leases
--;
1292 #if defined(FAILOVER_PROTOCOL)
1298 log_error ("Lease with bogus binding state: %d",
1299 comp
-> binding_state
);
1300 #if defined (BINDING_STATE_DEBUG)
1306 /* Remove the lease from its current place in its current
1308 /* XXX this is horrid. */
1309 prev
= (struct lease
*)0;
1310 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1317 log_fatal("Lease with binding state %s not on its queue.",
1318 (comp
->binding_state
< 1 ||
1319 comp
->binding_state
> FTS_LAST
)
1321 : binding_state_names
[comp
->binding_state
- 1]);
1325 lease_dereference (&prev
-> next
, MDL
);
1327 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1328 lease_dereference (&comp
-> next
, MDL
);
1331 lease_dereference (lq
, MDL
);
1333 lease_reference (lq
, comp
-> next
, MDL
);
1334 lease_dereference (&comp
-> next
, MDL
);
1338 /* Make the state transition. */
1339 if (commit
|| !pimmediate
)
1340 make_binding_state_transition (comp
);
1342 /* Put the lease back on the appropriate queue. If the lease
1343 is corrupt (as detected by lease_enqueue), don't go any farther. */
1344 if (!lease_enqueue (comp
))
1347 /* If this is the next lease that will timeout on the pool,
1348 zap the old timeout and set the timeout on this pool to the
1349 time that the lease's next event will happen.
1351 We do not actually set the timeout unless commit is true -
1352 we don't want to thrash the timer queue when reading the
1353 lease database. Instead, the database code calls the
1354 expiry event on each pool after reading in the lease file,
1355 and the expiry code sets the timer if there's anything left
1356 to expire after it's run any outstanding expiry events on
1358 if ((commit
|| !pimmediate
) &&
1359 comp
-> sort_time
!= MIN_TIME
&&
1360 comp
-> sort_time
> cur_time
&&
1361 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1362 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1363 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1364 add_timeout (comp
-> pool
-> next_event_time
,
1365 pool_timer
, comp
-> pool
,
1366 (tvref_t
)pool_reference
,
1367 (tvunref_t
)pool_dereference
);
1371 if (!write_lease (comp
))
1373 if ((server_starting
& SS_NOSYNC
) == 0) {
1374 if (!commit_leases ())
1379 #if defined (FAILOVER_PROTOCOL)
1381 comp
-> desired_binding_state
= comp
-> binding_state
;
1382 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1385 if (do_pool_check
&& comp
->pool
->failover_peer
)
1386 dhcp_failover_pool_check(comp
->pool
);
1389 /* If the current binding state has already expired, do an
1390 expiry event right now. */
1391 /* XXX At some point we should optimize this so that we don't
1392 XXX write the lease twice, but this is a safe way to fix the
1393 XXX problem for 3.0 (I hope!). */
1394 if ((commit
|| !pimmediate
) &&
1395 comp
-> sort_time
< cur_time
&&
1396 comp
-> next_binding_state
!= comp
-> binding_state
)
1397 pool_timer (comp
-> pool
);
1402 void make_binding_state_transition (struct lease
*lease
)
1404 #if defined (FAILOVER_PROTOCOL)
1405 dhcp_failover_state_t
*peer
;
1407 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1408 peer
= lease
-> pool
-> failover_peer
;
1410 peer
= (dhcp_failover_state_t
*)0;
1413 /* If the lease was active and is now no longer active, but isn't
1414 released, then it just expired, so do the expiry event. */
1415 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1417 #if defined (FAILOVER_PROTOCOL)
1419 (lease
-> binding_state
== FTS_EXPIRED
||
1420 (peer
-> i_am
== secondary
&&
1421 lease
-> binding_state
== FTS_ACTIVE
)) &&
1422 (lease
-> next_binding_state
== FTS_FREE
||
1423 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1426 lease
-> binding_state
== FTS_ACTIVE
&&
1427 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1428 #if defined (NSUPDATE)
1429 ddns_removals(lease
, NULL
);
1431 if (lease
-> on_expiry
) {
1432 execute_statements ((struct binding_value
**)0,
1433 (struct packet
*)0, lease
,
1434 (struct client_state
*)0,
1435 (struct option_state
*)0,
1436 (struct option_state
*)0, /* XXX */
1438 lease
-> on_expiry
);
1439 if (lease
-> on_expiry
)
1440 executable_statement_dereference
1441 (&lease
-> on_expiry
, MDL
);
1444 /* No sense releasing a lease after it's expired. */
1445 if (lease
-> on_release
)
1446 executable_statement_dereference (&lease
-> on_release
,
1448 /* Get rid of client-specific bindings that are only
1449 correct when the lease is active. */
1450 if (lease
-> billing_class
)
1451 unbill_class (lease
, lease
-> billing_class
);
1452 if (lease
-> agent_options
)
1453 option_chain_head_dereference (&lease
-> agent_options
,
1455 if (lease
-> client_hostname
) {
1456 dfree (lease
-> client_hostname
, MDL
);
1457 lease
-> client_hostname
= (char *)0;
1460 host_dereference (&lease
-> host
, MDL
);
1462 /* Send the expiry time to the peer. */
1463 lease
-> tstp
= lease
-> ends
;
1466 /* If the lease was active and is now released, do the release
1468 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1470 #if defined (FAILOVER_PROTOCOL)
1472 lease
-> binding_state
== FTS_RELEASED
&&
1473 (lease
-> next_binding_state
== FTS_FREE
||
1474 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1477 lease
-> binding_state
== FTS_ACTIVE
&&
1478 lease
-> next_binding_state
== FTS_RELEASED
))) {
1479 #if defined (NSUPDATE)
1480 ddns_removals(lease
, NULL
);
1482 if (lease
-> on_release
) {
1483 execute_statements ((struct binding_value
**)0,
1484 (struct packet
*)0, lease
,
1485 (struct client_state
*)0,
1486 (struct option_state
*)0,
1487 (struct option_state
*)0, /* XXX */
1489 lease
-> on_release
);
1490 executable_statement_dereference (&lease
-> on_release
,
1494 /* A released lease can't expire. */
1495 if (lease
-> on_expiry
)
1496 executable_statement_dereference (&lease
-> on_expiry
,
1499 /* Get rid of client-specific bindings that are only
1500 correct when the lease is active. */
1501 if (lease
-> billing_class
)
1502 unbill_class (lease
, lease
-> billing_class
);
1503 if (lease
-> agent_options
)
1504 option_chain_head_dereference (&lease
-> agent_options
,
1506 if (lease
-> client_hostname
) {
1507 dfree (lease
-> client_hostname
, MDL
);
1508 lease
-> client_hostname
= (char *)0;
1511 host_dereference (&lease
-> host
, MDL
);
1513 /* Send the release time (should be == cur_time) to the
1515 lease
-> tstp
= lease
-> ends
;
1518 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1519 log_debug ("lease %s moves from %s to %s",
1520 piaddr (lease
-> ip_addr
),
1521 binding_state_print (lease
-> binding_state
),
1522 binding_state_print (lease
-> next_binding_state
));
1525 lease
-> binding_state
= lease
-> next_binding_state
;
1526 switch (lease
-> binding_state
) {
1528 #if defined (FAILOVER_PROTOCOL)
1529 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1530 lease
-> next_binding_state
= FTS_EXPIRED
;
1533 lease
-> next_binding_state
= FTS_FREE
;
1540 lease
-> next_binding_state
= FTS_FREE
;
1541 /* If we are not in partner_down, leases don't go from
1542 EXPIRED to FREE on a timeout - only on an update.
1543 If we're in partner_down, they expire at mclt past
1544 the time we entered partner_down. */
1545 if (lease
-> pool
-> failover_peer
&&
1546 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1548 (lease
-> pool
-> failover_peer
-> me
.stos
+
1549 lease
-> pool
-> failover_peer
-> mclt
);
1554 lease
-> next_binding_state
= lease
-> binding_state
;
1557 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1558 log_debug ("lease %s: next binding state %s",
1559 piaddr (lease
-> ip_addr
),
1560 binding_state_print (lease
-> next_binding_state
));
1565 /* Copy the contents of one lease into another, correctly maintaining
1566 reference counts. */
1567 int lease_copy (struct lease
**lp
,
1568 struct lease
*lease
, const char *file
, int line
)
1570 struct lease
*lt
= (struct lease
*)0;
1571 isc_result_t status
;
1573 status
= lease_allocate (<
, MDL
);
1574 if (status
!= ISC_R_SUCCESS
)
1577 lt
-> ip_addr
= lease
-> ip_addr
;
1578 lt
-> starts
= lease
-> starts
;
1579 lt
-> ends
= lease
-> ends
;
1580 lt
-> uid_len
= lease
-> uid_len
;
1581 lt
-> uid_max
= lease
-> uid_max
;
1582 if (lease
-> uid
== lease
-> uid_buf
) {
1583 lt
-> uid
= lt
-> uid_buf
;
1584 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1585 } else if (!lease
-> uid_max
) {
1586 lt
-> uid
= (unsigned char *)0;
1588 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1590 lease_dereference (<
, MDL
);
1593 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1595 if (lease
-> client_hostname
) {
1596 lt
-> client_hostname
=
1597 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1598 if (!lt
-> client_hostname
) {
1599 lease_dereference (<
, MDL
);
1602 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1605 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1606 if (lease
-> agent_options
)
1607 option_chain_head_reference (<
-> agent_options
,
1608 lease
-> agent_options
, MDL
);
1609 host_reference (<
-> host
, lease
-> host
, file
, line
);
1610 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1611 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1612 class_reference (<
-> billing_class
,
1613 lease
-> billing_class
, file
, line
);
1614 lt
-> hardware_addr
= lease
-> hardware_addr
;
1615 if (lease
-> on_expiry
)
1616 executable_statement_reference (<
-> on_expiry
,
1619 if (lease
-> on_commit
)
1620 executable_statement_reference (<
-> on_commit
,
1623 if (lease
-> on_release
)
1624 executable_statement_reference (<
-> on_release
,
1625 lease
-> on_release
,
1627 lt
->flags
= lease
->flags
;
1628 lt
->tstp
= lease
->tstp
;
1629 lt
->tsfp
= lease
->tsfp
;
1630 lt
->atsfp
= lease
->atsfp
;
1631 lt
->cltt
= lease
-> cltt
;
1632 lt
->binding_state
= lease
->binding_state
;
1633 lt
->next_binding_state
= lease
->next_binding_state
;
1634 status
= lease_reference(lp
, lt
, file
, line
);
1635 lease_dereference(<
, MDL
);
1636 return status
== ISC_R_SUCCESS
;
1639 /* Release the specified lease and re-hash it as appropriate. */
1640 void release_lease (lease
, packet
)
1641 struct lease
*lease
;
1642 struct packet
*packet
;
1644 /* If there are statements to execute when the lease is
1645 released, execute them. */
1646 #if defined (NSUPDATE)
1647 ddns_removals(lease
, NULL
);
1649 if (lease
-> on_release
) {
1650 execute_statements ((struct binding_value
**)0,
1651 packet
, lease
, (struct client_state
*)0,
1653 (struct option_state
*)0, /* XXX */
1654 &lease
-> scope
, lease
-> on_release
);
1655 if (lease
-> on_release
)
1656 executable_statement_dereference (&lease
-> on_release
,
1660 /* We do either the on_release or the on_expiry events, but
1661 not both (it's possible that they could be the same,
1663 if (lease
-> on_expiry
)
1664 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1666 if (lease
-> binding_state
!= FTS_FREE
&&
1667 lease
-> binding_state
!= FTS_BACKUP
&&
1668 lease
-> binding_state
!= FTS_RELEASED
&&
1669 lease
-> binding_state
!= FTS_EXPIRED
&&
1670 lease
-> binding_state
!= FTS_RESET
) {
1671 if (lease
-> on_commit
)
1672 executable_statement_dereference (&lease
-> on_commit
,
1675 /* Blow away any bindings. */
1677 binding_scope_dereference (&lease
-> scope
, MDL
);
1679 /* Set sort times to the present. */
1680 lease
-> ends
= cur_time
;
1681 /* Lower layers of muckery set tstp to ->ends. But we send
1682 * protocol messages before this. So it is best to set
1685 lease
->tstp
= cur_time
;
1686 #if defined (FAILOVER_PROTOCOL)
1687 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1688 lease
-> next_binding_state
= FTS_RELEASED
;
1690 lease
-> next_binding_state
= FTS_FREE
;
1693 lease
-> next_binding_state
= FTS_FREE
;
1695 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1699 /* Abandon the specified lease (set its timeout to infinity and its
1700 particulars to zero, and re-hash it as appropriate. */
1702 void abandon_lease (lease
, message
)
1703 struct lease
*lease
;
1704 const char *message
;
1706 struct lease
*lt
= (struct lease
*)0;
1707 #if defined (NSUPDATE)
1708 ddns_removals(lease
, NULL
);
1711 if (!lease_copy (<
, lease
, MDL
))
1715 binding_scope_dereference(<
->scope
, MDL
);
1717 lt
-> ends
= cur_time
; /* XXX */
1718 lt
-> next_binding_state
= FTS_ABANDONED
;
1720 log_error ("Abandoning IP address %s: %s",
1721 piaddr (lease
-> ip_addr
), message
);
1722 lt
-> hardware_addr
.hlen
= 0;
1723 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1724 dfree (lt
-> uid
, MDL
);
1725 lt
-> uid
= (unsigned char *)0;
1728 supersede_lease (lease
, lt
, 1, 1, 1);
1729 lease_dereference (<
, MDL
);
1732 /* Abandon the specified lease (set its timeout to infinity and its
1733 particulars to zero, and re-hash it as appropriate. */
1735 void dissociate_lease (lease
)
1736 struct lease
*lease
;
1738 struct lease
*lt
= (struct lease
*)0;
1739 #if defined (NSUPDATE)
1740 ddns_removals(lease
, NULL
);
1743 if (!lease_copy (<
, lease
, MDL
))
1746 #if defined (FAILOVER_PROTOCOL)
1747 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1748 lt
-> next_binding_state
= FTS_RESET
;
1750 lt
-> next_binding_state
= FTS_FREE
;
1753 lt
-> next_binding_state
= FTS_FREE
;
1755 lt
-> ends
= cur_time
; /* XXX */
1756 lt
-> hardware_addr
.hlen
= 0;
1757 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1758 dfree (lt
-> uid
, MDL
);
1759 lt
-> uid
= (unsigned char *)0;
1762 supersede_lease (lease
, lt
, 1, 1, 1);
1763 lease_dereference (<
, MDL
);
1766 /* Timer called when a lease in a particular pool expires. */
1767 void pool_timer (vpool
)
1771 struct lease
*lt
= (struct lease
*)0;
1772 struct lease
*next
= (struct lease
*)0;
1773 struct lease
*lease
= (struct lease
*)0;
1774 #define FREE_LEASES 0
1775 #define ACTIVE_LEASES 1
1776 #define EXPIRED_LEASES 2
1777 #define ABANDONED_LEASES 3
1778 #define BACKUP_LEASES 4
1779 #define RESERVED_LEASES 5
1780 struct lease
**lptr
[RESERVED_LEASES
+1];
1781 TIME next_expiry
= MAX_TIME
;
1784 pool
= (struct pool
*)vpool
;
1786 lptr
[FREE_LEASES
] = &pool
-> free
;
1787 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1788 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1789 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1790 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1791 lptr
[RESERVED_LEASES
] = &pool
->reserved
;
1793 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
1794 /* If there's nothing on the queue, skip it. */
1798 #if defined (FAILOVER_PROTOCOL)
1799 if (pool
-> failover_peer
&&
1800 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1801 /* The secondary can't remove a lease from the
1802 active state except in partner_down. */
1803 if (i
== ACTIVE_LEASES
&&
1804 pool
-> failover_peer
-> i_am
== secondary
)
1806 /* Leases in an expired state don't move to
1807 free because of a timeout unless we're in
1809 if (i
== EXPIRED_LEASES
)
1813 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1816 /* Remember the next lease in the list. */
1818 lease_dereference (&next
, MDL
);
1820 lease_reference (&next
, lease
-> next
, MDL
);
1822 /* If we've run out of things to expire on this list,
1824 if (lease
-> sort_time
> cur_time
) {
1825 if (lease
-> sort_time
< next_expiry
)
1826 next_expiry
= lease
-> sort_time
;
1830 /* If there is a pending state change, and
1831 this lease has gotten to the time when the
1832 state change should happen, just call
1833 supersede_lease on it to make the change
1835 if (lease
-> next_binding_state
!=
1836 lease
-> binding_state
)
1837 supersede_lease (lease
,
1838 (struct lease
*)0, 1, 1, 1);
1840 lease_dereference (&lease
, MDL
);
1842 lease_reference (&lease
, next
, MDL
);
1845 lease_dereference (&next
, MDL
);
1847 lease_dereference (&lease
, MDL
);
1849 if (next_expiry
!= MAX_TIME
) {
1850 pool
-> next_event_time
= next_expiry
;
1851 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1852 (tvref_t
)pool_reference
,
1853 (tvunref_t
)pool_dereference
);
1855 pool
-> next_event_time
= MIN_TIME
;
1859 /* Locate the lease associated with a given IP address... */
1861 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1862 const char *file
, int line
)
1864 return lease_ip_hash_lookup(lp
, lease_ip_addr_hash
, addr
.iabuf
,
1865 addr
.len
, file
, line
);
1868 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1869 unsigned len
, const char *file
, int line
)
1873 return lease_id_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1876 int find_lease_by_hw_addr (struct lease
**lp
,
1877 const unsigned char *hwaddr
, unsigned hwlen
,
1878 const char *file
, int line
)
1882 return lease_id_hash_lookup(lp
, lease_hw_addr_hash
, hwaddr
, hwlen
,
1886 /* If the lease is preferred over the candidate, return truth. The
1887 * 'cand' and 'lease' names are retained to read more clearly against
1888 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
1889 * to those two functions).
1891 * 1) ACTIVE leases are preferred. The active lease with
1892 * the longest lifetime is preferred over shortest.
1893 * 2) "transitional states" are next, this time with the
1895 * 3) free/backup/etc states are next, again with CLTT. In truth we
1896 * should never see reset leases for this.
1897 * 4) Abandoned leases are always dead last.
1899 static isc_boolean_t
1900 client_lease_preferred(struct lease
*cand
, struct lease
*lease
)
1902 if (cand
->binding_state
== FTS_ACTIVE
) {
1903 if (lease
->binding_state
== FTS_ACTIVE
&&
1904 lease
->ends
>= cand
->ends
)
1906 } else if (cand
->binding_state
== FTS_EXPIRED
||
1907 cand
->binding_state
== FTS_RELEASED
) {
1908 if (lease
->binding_state
== FTS_ACTIVE
)
1911 if ((lease
->binding_state
== FTS_EXPIRED
||
1912 lease
->binding_state
== FTS_RELEASED
) &&
1913 lease
->cltt
>= cand
->cltt
)
1915 } else if (cand
->binding_state
!= FTS_ABANDONED
) {
1916 if (lease
->binding_state
== FTS_ACTIVE
||
1917 lease
->binding_state
== FTS_EXPIRED
||
1918 lease
->binding_state
== FTS_RELEASED
)
1921 if (lease
->binding_state
!= FTS_ABANDONED
&&
1922 lease
->cltt
>= cand
->cltt
)
1924 } else /* (cand->binding_state == FTS_ABANDONED) */ {
1925 if (lease
->binding_state
!= FTS_ABANDONED
||
1926 lease
->cltt
>= cand
->cltt
)
1933 /* Add the specified lease to the uid hash. */
1935 uid_hash_add(struct lease
*lease
)
1937 struct lease
*head
= NULL
;
1938 struct lease
*cand
= NULL
;
1939 struct lease
*prev
= NULL
;
1940 struct lease
*next
= NULL
;
1942 /* If it's not in the hash, just add it. */
1943 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1944 lease_id_hash_add(lease_uid_hash
, lease
->uid
, lease
->uid_len
,
1947 /* Otherwise, insert it into the list in order of its
1948 * preference for "resuming allocation to the client."
1950 * Because we don't have control of the hash bucket index
1951 * directly, we have to remove and re-insert the client
1952 * id into the hash if we're inserting onto the head.
1954 lease_reference(&cand
, head
, MDL
);
1955 while (cand
!= NULL
) {
1956 if (client_lease_preferred(cand
, lease
))
1960 lease_dereference(&prev
, MDL
);
1961 lease_reference(&prev
, cand
, MDL
);
1963 if (cand
->n_uid
!= NULL
)
1964 lease_reference(&next
, cand
->n_uid
, MDL
);
1966 lease_dereference(&cand
, MDL
);
1969 lease_reference(&cand
, next
, MDL
);
1970 lease_dereference(&next
, MDL
);
1974 /* If we want to insert 'before cand', and prev is NULL,
1975 * then it was the head of the list. Assume that position.
1978 lease_reference(&lease
->n_uid
, head
, MDL
);
1979 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
1980 lease
->uid_len
, MDL
);
1981 lease_id_hash_add(lease_uid_hash
, lease
->uid
,
1982 lease
->uid_len
, lease
, MDL
);
1983 } else /* (prev != NULL) */ {
1984 if(prev
->n_uid
!= NULL
) {
1985 lease_reference(&lease
->n_uid
, prev
->n_uid
,
1987 lease_dereference(&prev
->n_uid
, MDL
);
1989 lease_reference(&prev
->n_uid
, lease
, MDL
);
1991 lease_dereference(&prev
, MDL
);
1995 lease_dereference(&cand
, MDL
);
1996 lease_dereference(&head
, MDL
);
2000 /* Delete the specified lease from the uid hash. */
2002 void uid_hash_delete (lease
)
2003 struct lease
*lease
;
2005 struct lease
*head
= (struct lease
*)0;
2008 /* If it's not in the hash, we have no work to do. */
2009 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
2011 lease_dereference (&lease
-> n_uid
, MDL
);
2015 /* If the lease we're freeing is at the head of the list,
2016 remove the hash table entry and add a new one with the
2017 next lease on the list (if there is one). */
2018 if (head
== lease
) {
2019 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2020 lease
->uid_len
, MDL
);
2021 if (lease
-> n_uid
) {
2022 lease_id_hash_add(lease_uid_hash
, lease
->n_uid
->uid
,
2023 lease
->n_uid
->uid_len
, lease
->n_uid
,
2025 lease_dereference (&lease
-> n_uid
, MDL
);
2028 /* Otherwise, look for the lease in the list of leases
2029 attached to the hash table entry, and remove it if
2031 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
2032 if (scan
-> n_uid
== lease
) {
2033 lease_dereference (&scan
-> n_uid
, MDL
);
2034 if (lease
-> n_uid
) {
2035 lease_reference (&scan
-> n_uid
,
2036 lease
-> n_uid
, MDL
);
2037 lease_dereference (&lease
-> n_uid
,
2044 lease_dereference (&head
, MDL
);
2047 /* Add the specified lease to the hardware address hash. */
2050 hw_hash_add(struct lease
*lease
)
2052 struct lease
*head
= NULL
;
2053 struct lease
*cand
= NULL
;
2054 struct lease
*prev
= NULL
;
2055 struct lease
*next
= NULL
;
2057 /* If it's not in the hash, just add it. */
2058 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2059 lease
-> hardware_addr
.hlen
, MDL
))
2060 lease_id_hash_add(lease_hw_addr_hash
,
2061 lease
->hardware_addr
.hbuf
,
2062 lease
->hardware_addr
.hlen
, lease
, MDL
);
2064 /* Otherwise, insert it into the list in order of its
2065 * preference for "resuming allocation to the client."
2067 * Because we don't have control of the hash bucket index
2068 * directly, we have to remove and re-insert the client
2069 * id into the hash if we're inserting onto the head.
2071 lease_reference(&cand
, head
, MDL
);
2072 while (cand
!= NULL
) {
2073 if (client_lease_preferred(cand
, lease
))
2077 lease_dereference(&prev
, MDL
);
2078 lease_reference(&prev
, cand
, MDL
);
2080 if (cand
->n_hw
!= NULL
)
2081 lease_reference(&next
, cand
->n_hw
, MDL
);
2083 lease_dereference(&cand
, MDL
);
2086 lease_reference(&cand
, next
, MDL
);
2087 lease_dereference(&next
, MDL
);
2091 /* If we want to insert 'before cand', and prev is NULL,
2092 * then it was the head of the list. Assume that position.
2095 lease_reference(&lease
->n_hw
, head
, MDL
);
2096 lease_id_hash_delete(lease_hw_addr_hash
,
2097 lease
->hardware_addr
.hbuf
,
2098 lease
->hardware_addr
.hlen
, MDL
);
2099 lease_id_hash_add(lease_hw_addr_hash
,
2100 lease
->hardware_addr
.hbuf
,
2101 lease
->hardware_addr
.hlen
,
2103 } else /* (prev != NULL) */ {
2104 if(prev
->n_hw
!= NULL
) {
2105 lease_reference(&lease
->n_hw
, prev
->n_hw
,
2107 lease_dereference(&prev
->n_hw
, MDL
);
2109 lease_reference(&prev
->n_hw
, lease
, MDL
);
2111 lease_dereference(&prev
, MDL
);
2115 lease_dereference(&cand
, MDL
);
2116 lease_dereference(&head
, MDL
);
2120 /* Delete the specified lease from the hardware address hash. */
2122 void hw_hash_delete (lease
)
2123 struct lease
*lease
;
2125 struct lease
*head
= (struct lease
*)0;
2126 struct lease
*next
= (struct lease
*)0;
2128 /* If it's not in the hash, we have no work to do. */
2129 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2130 lease
-> hardware_addr
.hlen
, MDL
)) {
2132 lease_dereference (&lease
-> n_hw
, MDL
);
2136 /* If the lease we're freeing is at the head of the list,
2137 remove the hash table entry and add a new one with the
2138 next lease on the list (if there is one). */
2139 if (head
== lease
) {
2140 lease_id_hash_delete(lease_hw_addr_hash
,
2141 lease
->hardware_addr
.hbuf
,
2142 lease
->hardware_addr
.hlen
, MDL
);
2144 lease_id_hash_add(lease_hw_addr_hash
,
2145 lease
->n_hw
->hardware_addr
.hbuf
,
2146 lease
->n_hw
->hardware_addr
.hlen
,
2148 lease_dereference(&lease
->n_hw
, MDL
);
2151 /* Otherwise, look for the lease in the list of leases
2152 attached to the hash table entry, and remove it if
2154 while (head
-> n_hw
) {
2155 if (head
-> n_hw
== lease
) {
2156 lease_dereference (&head
-> n_hw
, MDL
);
2157 if (lease
-> n_hw
) {
2158 lease_reference (&head
-> n_hw
,
2159 lease
-> n_hw
, MDL
);
2160 lease_dereference (&lease
-> n_hw
,
2165 lease_reference (&next
, head
-> n_hw
, MDL
);
2166 lease_dereference (&head
, MDL
);
2167 lease_reference (&head
, next
, MDL
);
2168 lease_dereference (&next
, MDL
);
2172 lease_dereference (&head
, MDL
);
2175 /* Write all interesting leases to permanent storage. */
2180 struct shared_network
*s
;
2182 struct host_decl
*hp
;
2183 struct group_object
*gp
;
2184 struct hash_bucket
*hb
;
2186 struct collection
*colp
;
2189 struct lease
**lptr
[RESERVED_LEASES
+1];
2191 /* write all the dynamically-created class declarations. */
2192 if (collections
->classes
) {
2193 numclasseswritten
= 0;
2194 for (colp
= collections
; colp
; colp
= colp
->next
) {
2195 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
2196 write_named_billing_class(
2197 (unsigned char *)cp
->name
,
2202 /* XXXJAB this number doesn't include subclasses... */
2203 log_info ("Wrote %d class decls to leases file.",
2208 /* Write all the dynamically-created group declarations. */
2209 if (group_name_hash
) {
2211 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
2212 for (hb
= group_name_hash
-> buckets
[i
];
2213 hb
; hb
= hb
-> next
) {
2214 gp
= (struct group_object
*)hb
-> value
;
2215 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
2216 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
2217 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
2218 if (!write_group (gp
))
2224 log_info ("Wrote %d group decls to leases file.", num_written
);
2227 /* Write all the deleted host declarations. */
2228 if (host_name_hash
) {
2230 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2231 for (hb
= host_name_hash
-> buckets
[i
];
2232 hb
; hb
= hb
-> next
) {
2233 hp
= (struct host_decl
*)hb
-> value
;
2234 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
2235 (hp
-> flags
& HOST_DECL_DELETED
))) {
2236 if (!write_host (hp
))
2242 log_info ("Wrote %d deleted host decls to leases file.",
2246 /* Write all the new, dynamic host declarations. */
2247 if (host_name_hash
) {
2249 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2250 for (hb
= host_name_hash
-> buckets
[i
];
2251 hb
; hb
= hb
-> next
) {
2252 hp
= (struct host_decl
*)hb
-> value
;
2253 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
2254 if (!write_host (hp
))
2259 log_info ("Wrote %d new dynamic host decls to leases file.",
2263 #if defined (FAILOVER_PROTOCOL)
2264 /* Write all the failover states. */
2265 if (!dhcp_failover_write_all_states ())
2269 /* Write all the leases. */
2271 for (s
= shared_networks
; s
; s
= s
-> next
) {
2272 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2273 lptr
[FREE_LEASES
] = &p
-> free
;
2274 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2275 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2276 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2277 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2278 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2280 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2281 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2282 #if !defined (DEBUG_DUMP_ALL_LEASES)
2283 if (l
-> hardware_addr
.hlen
||
2285 (l
-> binding_state
!= FTS_FREE
))
2288 if (!write_lease (l
))
2296 log_info ("Wrote %d leases to leases file.", num_written
);
2298 if (!write_leases6()) {
2302 if (!commit_leases ())
2307 /* In addition to placing this lease upon a lease queue depending on its
2308 * state, it also keeps track of the number of FREE and BACKUP leases in
2309 * existence, and sets the sort_time on the lease.
2311 * Sort_time is used in pool_timer() to determine when the lease will
2312 * bubble to the top of the list and be supersede_lease()'d into its next
2313 * state (possibly, if all goes well). Example, ACTIVE leases move to
2314 * EXPIRED state when the 'ends' value is reached, so that is its sort
2315 * time. Most queues are sorted by 'ends', since it is generally best
2316 * practice to re-use the oldest lease, to reduce address collision
2319 int lease_enqueue (struct lease
*comp
)
2321 struct lease
**lq
, *prev
, *lp
;
2322 static struct lease
**last_lq
= NULL
;
2323 static struct lease
*last_insert_point
= NULL
;
2325 /* No queue to put it on? */
2329 /* Figure out which queue it's going to. */
2330 switch (comp
-> binding_state
) {
2332 if (comp
->flags
& RESERVED_LEASE
) {
2333 lq
= &comp
->pool
->reserved
;
2335 lq
= &comp
->pool
->free
;
2336 comp
->pool
->free_leases
++;
2338 comp
-> sort_time
= comp
-> ends
;
2342 lq
= &comp
-> pool
-> active
;
2343 comp
-> sort_time
= comp
-> ends
;
2349 lq
= &comp
-> pool
-> expired
;
2350 #if defined(FAILOVER_PROTOCOL)
2351 /* In partner_down, tsfp is the time at which the lease
2352 * may be reallocated (stos+mclt). We can do that with
2353 * lease_mine_to_reallocate() anywhere between tsfp and
2354 * ends. But we prefer to wait until ends before doing it
2355 * automatically (choose the greater of the two). Note
2356 * that 'ends' is usually a historic timestamp in the
2357 * case of expired leases, is really only in the future
2358 * on released leases, and if we know a lease to be released
2359 * the peer might still know it to be active...in which case
2360 * it's possible the peer has renewed this lease, so avoid
2363 if (comp
->pool
->failover_peer
&&
2364 comp
->pool
->failover_peer
->me
.state
== partner_down
)
2365 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
2366 comp
->tsfp
: comp
->ends
;
2369 comp
->sort_time
= comp
->ends
;
2374 lq
= &comp
-> pool
-> abandoned
;
2375 comp
-> sort_time
= comp
-> ends
;
2379 if (comp
->flags
& RESERVED_LEASE
) {
2380 lq
= &comp
->pool
->reserved
;
2382 lq
= &comp
->pool
->backup
;
2383 comp
->pool
->backup_leases
++;
2385 comp
-> sort_time
= comp
-> ends
;
2389 log_error ("Lease with bogus binding state: %d",
2390 comp
-> binding_state
);
2391 #if defined (BINDING_STATE_DEBUG)
2397 /* This only works during server startup: during runtime, the last
2398 * lease may be dequeued inbetween calls. If the queue is the same
2399 * as was used previously, and the lease structure isn't (this is not
2400 * a re-queue), use that as a starting point for the insertion-sort.
2402 if ((server_starting
& SS_QFOLLOW
) && (lq
== last_lq
) &&
2403 (comp
!= last_insert_point
) &&
2404 (last_insert_point
->sort_time
<= comp
->sort_time
)) {
2405 prev
= last_insert_point
;
2412 /* Insertion sort the lease onto the appropriate queue. */
2413 for (; lp
; lp
= lp
->next
) {
2414 if (lp
-> sort_time
>= comp
-> sort_time
)
2421 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
2422 lease_dereference (&prev
-> next
, MDL
);
2424 lease_reference (&prev
-> next
, comp
, MDL
);
2427 lease_reference (&comp
-> next
, *lq
, MDL
);
2428 lease_dereference (lq
, MDL
);
2430 lease_reference (lq
, comp
, MDL
);
2432 last_insert_point
= comp
;
2437 /* For a given lease, sort it onto the right list in its pool and put it
2438 in each appropriate hash, understanding that it's already by definition
2439 in lease_ip_addr_hash. */
2442 lease_instantiate(const void *key
, unsigned len
, void *object
)
2444 struct lease
*lease
= object
;
2445 struct class *class;
2446 /* XXX If the lease doesn't have a pool at this point, it's an
2447 XXX orphan, which we *should* keep around until it expires,
2448 XXX but which right now we just forget. */
2449 if (!lease
-> pool
) {
2450 lease_ip_hash_delete(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
2451 lease
->ip_addr
.len
, MDL
);
2452 return ISC_R_SUCCESS
;
2455 /* Put the lease on the right queue. Failure to queue is probably
2456 * due to a bogus binding state. In such a case, we claim success,
2457 * so that later leases in a hash_foreach are processed, but we
2458 * return early as we really don't want hw address hash entries or
2459 * other cruft to surround such a bogus entry.
2461 if (!lease_enqueue(lease
))
2462 return ISC_R_SUCCESS
;
2464 /* Record the lease in the uid hash if possible. */
2466 uid_hash_add (lease
);
2469 /* Record it in the hardware address hash if possible. */
2470 if (lease
-> hardware_addr
.hlen
) {
2471 hw_hash_add (lease
);
2474 /* If the lease has a billing class, set up the billing. */
2475 if (lease
-> billing_class
) {
2476 class = (struct class *)0;
2477 class_reference (&class, lease
-> billing_class
, MDL
);
2478 class_dereference (&lease
-> billing_class
, MDL
);
2479 /* If the lease is available for allocation, the billing
2480 is invalid, so we don't keep it. */
2481 if (lease
-> binding_state
== FTS_ACTIVE
||
2482 lease
-> binding_state
== FTS_EXPIRED
||
2483 lease
-> binding_state
== FTS_RELEASED
||
2484 lease
-> binding_state
== FTS_RESET
)
2485 bill_class (lease
, class);
2486 class_dereference (&class, MDL
);
2488 return ISC_R_SUCCESS
;
2491 /* Run expiry events on every pool. This is called on startup so that
2492 any expiry events that occurred after the server stopped and before it
2493 was restarted can be run. At the same time, if failover support is
2494 compiled in, we compute the balance of leases for the pool. */
2496 void expire_all_pools ()
2498 struct shared_network
*s
;
2500 struct hash_bucket
*hb
;
2503 struct lease
**lptr
[RESERVED_LEASES
+1];
2505 /* Indicate that we are in the startup phase */
2506 server_starting
= SS_NOSYNC
| SS_QFOLLOW
;
2508 /* First, go over the hash list and actually put all the leases
2509 on the appropriate lists. */
2510 lease_ip_hash_foreach(lease_ip_addr_hash
, lease_instantiate
);
2512 /* Loop through each pool in each shared network and call the
2513 * expiry routine on the pool. It is no longer safe to follow
2514 * the queue insertion point, as expiration of a lease can move
2515 * it between queues (and this may be the lease that function
2518 server_starting
&= ~SS_QFOLLOW
;
2519 for (s
= shared_networks
; s
; s
= s
-> next
) {
2520 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2523 p
-> lease_count
= 0;
2524 p
-> free_leases
= 0;
2525 p
-> backup_leases
= 0;
2527 lptr
[FREE_LEASES
] = &p
-> free
;
2528 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2529 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2530 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2531 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2532 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2534 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2535 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2537 if (l
-> ends
<= cur_time
) {
2538 if (l
->binding_state
== FTS_FREE
) {
2539 if (i
== FREE_LEASES
)
2542 log_fatal("Impossible case "
2544 } else if (l
->binding_state
== FTS_BACKUP
) {
2545 if (i
== BACKUP_LEASES
)
2548 log_fatal("Impossible case "
2552 #if defined (FAILOVER_PROTOCOL)
2553 if (p
-> failover_peer
&&
2554 l
-> tstp
> l
-> atsfp
&&
2555 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2556 l
-> desired_binding_state
= l
-> binding_state
;
2557 dhcp_failover_queue_update (l
, 1);
2565 /* turn off startup phase */
2566 server_starting
= 0;
2569 void dump_subnets ()
2572 struct shared_network
*s
;
2575 struct lease
**lptr
[RESERVED_LEASES
+1];
2578 log_info ("Subnets:");
2579 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2580 log_debug (" Subnet %s", piaddr (n
-> net
));
2581 log_debug (" netmask %s",
2582 piaddr (n
-> netmask
));
2584 log_info ("Shared networks:");
2585 for (s
= shared_networks
; s
; s
= s
-> next
) {
2586 log_info (" %s", s
-> name
);
2587 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2588 lptr
[FREE_LEASES
] = &p
-> free
;
2589 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2590 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2591 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2592 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2593 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2595 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2596 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2604 HASH_FUNCTIONS(lease_ip
, const unsigned char *, struct lease
, lease_ip_hash_t
,
2605 lease_reference
, lease_dereference
, do_ip4_hash
)
2606 HASH_FUNCTIONS(lease_id
, const unsigned char *, struct lease
, lease_id_hash_t
,
2607 lease_reference
, lease_dereference
, do_id_hash
)
2608 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2609 host_reference
, host_dereference
, do_string_hash
)
2610 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2611 class_reference
, class_dereference
, do_string_hash
)
2613 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2614 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2615 extern struct hash_table
*dns_zone_hash
;
2616 extern struct interface_info
**interface_vector
;
2617 extern int interface_count
;
2618 dhcp_control_object_t
*dhcp_control_object
;
2619 extern struct hash_table
*auth_key_hash
;
2620 struct hash_table
*universe_hash
;
2621 struct universe
**universes
;
2622 int universe_count
, universe_max
;
2627 #if defined (COMPACT_LEASES)
2628 extern struct lease
*lease_hunks
;
2631 void free_everything ()
2633 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2634 struct shared_network
*nc
= (struct shared_network
*)0,
2635 *nn
= (struct shared_network
*)0;
2636 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2637 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2638 struct interface_info
*ic
= (struct interface_info
*)0,
2639 *in
= (struct interface_info
*)0;
2640 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2641 struct collection
*lp
;
2642 void *st
= (shared_networks
2643 ? (shared_networks
-> next
2644 ? shared_networks
-> next
-> next
: 0) : 0);
2648 /* Get rid of all the hash tables. */
2649 if (host_hw_addr_hash
)
2650 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2651 host_hw_addr_hash
= 0;
2653 host_free_hash_table (&host_uid_hash
, MDL
);
2656 lease_free_hash_table (&lease_uid_hash
, MDL
);
2658 if (lease_ip_addr_hash
)
2659 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2660 lease_ip_addr_hash
= 0;
2661 if (lease_hw_addr_hash
)
2662 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2663 lease_hw_addr_hash
= 0;
2665 host_free_hash_table (&host_name_hash
, MDL
);
2668 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2671 while (host_id_info
!= NULL
) {
2672 host_id_info_t
*tmp
;
2673 option_dereference(&host_id_info
->option
, MDL
);
2674 host_free_hash_table(&host_id_info
->values_hash
, MDL
);
2675 tmp
= host_id_info
->next
;
2676 dfree(host_id_info
, MDL
);
2681 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2685 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2688 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2689 if (lp
-> classes
) {
2690 class_reference (&cn
, lp
-> classes
, MDL
);
2693 class_reference (&cc
, cn
, MDL
);
2694 class_dereference (&cn
, MDL
);
2697 class_reference (&cn
, cc
-> nic
, MDL
);
2698 class_dereference (&cc
-> nic
, MDL
);
2700 group_dereference (&cc
-> group
, MDL
);
2702 class_free_hash_table (&cc
-> hash
, MDL
);
2703 cc
-> hash
= (struct hash_table
*)0;
2705 class_dereference (&cc
, MDL
);
2707 class_dereference (&lp
-> classes
, MDL
);
2711 if (interface_vector
) {
2712 for (i
= 0; i
< interface_count
; i
++) {
2713 if (interface_vector
[i
])
2714 interface_dereference (&interface_vector
[i
], MDL
);
2716 dfree (interface_vector
, MDL
);
2717 interface_vector
= 0;
2721 interface_reference (&in
, interfaces
, MDL
);
2724 interface_reference (&ic
, in
, MDL
);
2725 interface_dereference (&in
, MDL
);
2728 interface_reference (&in
, ic
-> next
, MDL
);
2729 interface_dereference (&ic
-> next
, MDL
);
2731 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2732 if (ic
-> shared_network
) {
2733 if (ic
-> shared_network
-> interface
)
2734 interface_dereference
2735 (&ic
-> shared_network
-> interface
, MDL
);
2736 shared_network_dereference (&ic
-> shared_network
, MDL
);
2738 interface_dereference (&ic
, MDL
);
2740 interface_dereference (&interfaces
, MDL
);
2743 /* Subnets are complicated because of the extra links. */
2745 subnet_reference (&sn
, subnets
, MDL
);
2748 subnet_reference (&sc
, sn
, MDL
);
2749 subnet_dereference (&sn
, MDL
);
2751 if (sc
-> next_subnet
) {
2752 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2753 subnet_dereference (&sc
-> next_subnet
, MDL
);
2755 if (sc
-> next_sibling
)
2756 subnet_dereference (&sc
-> next_sibling
, MDL
);
2757 if (sc
-> shared_network
)
2758 shared_network_dereference (&sc
-> shared_network
, MDL
);
2759 group_dereference (&sc
-> group
, MDL
);
2760 if (sc
-> interface
)
2761 interface_dereference (&sc
-> interface
, MDL
);
2762 subnet_dereference (&sc
, MDL
);
2764 subnet_dereference (&subnets
, MDL
);
2767 /* So are shared networks. */
2768 if (shared_networks
) {
2769 shared_network_reference (&nn
, shared_networks
, MDL
);
2772 shared_network_reference (&nc
, nn
, MDL
);
2773 shared_network_dereference (&nn
, MDL
);
2776 shared_network_reference (&nn
, nc
-> next
, MDL
);
2777 shared_network_dereference (&nc
-> next
, MDL
);
2782 pool_reference (&pn
, nc
-> pools
, MDL
);
2784 struct lease
**lptr
[RESERVED_LEASES
+1];
2787 pool_reference (&pc
, pn
, MDL
);
2788 pool_dereference (&pn
, MDL
);
2791 pool_reference (&pn
, pc
-> next
, MDL
);
2792 pool_dereference (&pc
-> next
, MDL
);
2795 lptr
[FREE_LEASES
] = &pc
-> free
;
2796 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2797 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2798 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2799 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2800 lptr
[RESERVED_LEASES
] = &pc
->reserved
;
2802 /* As (sigh) are leases. */
2803 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2805 lease_reference (&ln
, *lptr
[i
], MDL
);
2808 lease_reference (&lc
, ln
, MDL
);
2809 lease_dereference (&ln
, MDL
);
2812 lease_reference (&ln
, lc
-> next
, MDL
);
2813 lease_dereference (&lc
-> next
, MDL
);
2815 if (lc
-> billing_class
)
2816 class_dereference (&lc
-> billing_class
,
2819 free_lease_state (lc
-> state
, MDL
);
2820 lc
-> state
= (struct lease_state
*)0;
2822 lease_dereference (&lc
-> n_hw
, MDL
);
2824 lease_dereference (&lc
-> n_uid
, MDL
);
2825 lease_dereference (&lc
, MDL
);
2827 lease_dereference (lptr
[i
], MDL
);
2831 group_dereference (&pc
-> group
, MDL
);
2832 if (pc
-> shared_network
)
2833 shared_network_dereference (&pc
-> shared_network
,
2835 pool_dereference (&pc
, MDL
);
2837 pool_dereference (&nc
-> pools
, MDL
);
2839 /* Because of a circular reference, we need to nuke this
2841 group_dereference (&nc
-> group
, MDL
);
2842 shared_network_dereference (&nc
, MDL
);
2844 shared_network_dereference (&shared_networks
, MDL
);
2847 cancel_all_timeouts ();
2848 relinquish_timeouts ();
2850 group_dereference (&root_group
, MDL
);
2851 executable_statement_dereference (&default_classification_rules
, MDL
);
2853 shutdown_state
= shutdown_drop_omapi_connections
;
2854 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2855 shutdown_state
= shutdown_listeners
;
2856 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2857 shutdown_state
= shutdown_dhcp
;
2858 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2860 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2862 universe_free_hash_table (&universe_hash
, MDL
);
2863 for (i
= 0; i
< universe_count
; i
++) {
2868 if (universes
[i
]) {
2869 if (universes
[i
] -> hash
)
2870 option_free_hash_table (&universes
[i
] -> hash
,
2873 if (universes
[i
] -> name
> (char *)&end
) {
2874 foo
.c
= universes
[i
] -> name
;
2877 if (universes
[i
] > (struct universe
*)&end
)
2878 dfree (universes
[i
], MDL
);
2882 dfree (universes
, MDL
);
2884 relinquish_free_lease_states ();
2885 relinquish_free_pairs ();
2886 relinquish_free_expressions ();
2887 relinquish_free_binding_values ();
2888 relinquish_free_option_caches ();
2889 relinquish_free_packets ();
2890 relinquish_lease_hunks ();
2891 relinquish_hash_bucket_hunks ();
2892 omapi_type_relinquish ();
2894 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */