3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2008 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 #include "omapip/hash.h"
38 struct subnet
*subnets
;
39 struct shared_network
*shared_networks
;
40 host_hash_t
*host_hw_addr_hash
;
41 host_hash_t
*host_uid_hash
;
42 host_hash_t
*host_name_hash
;
43 lease_id_hash_t
*lease_uid_hash
;
44 lease_ip_hash_t
*lease_ip_addr_hash
;
45 lease_id_hash_t
*lease_hw_addr_hash
;
48 * We allow users to specify any option as a host identifier.
50 * Any host is uniquely identified by the combination of
51 * option type & option data.
53 * We expect people will only use a few types of options as host
54 * identifier. Because of this, we store a list with an entry for
55 * each option type. Each of these has a hash table, which contains
56 * hash of the option data.
58 typedef struct host_id_info
{
59 struct option
*option
;
60 host_hash_t
*values_hash
;
61 struct host_id_info
*next
;
64 static host_id_info_t
*host_id_info
= NULL
;
66 int numclasseswritten
;
68 omapi_object_type_t
*dhcp_type_host
;
70 isc_result_t
enter_class(cd
, dynamicp
, commit
)
75 if (!collections
-> classes
) {
76 /* A subclass with no parent is invalid. */
78 return ISC_R_INVALIDARG
;
80 class_reference (&collections
-> classes
, cd
, MDL
);
81 } else if (cd
->name
!= NULL
) { /* regular class */
84 if (find_class(&c
, cd
->name
, MDL
) != ISC_R_NOTFOUND
) {
85 class_dereference(&c
, MDL
);
90 for (c
= collections
-> classes
;
91 c
-> nic
; c
= c
-> nic
)
93 class_reference (&c
-> nic
, cd
, MDL
);
96 if (dynamicp
&& commit
) {
97 const char *name
= cd
->name
;
100 name
= cd
->superclass
->name
;
103 write_named_billing_class ((const unsigned char *)name
, 0, cd
);
104 if (!commit_leases ())
105 return ISC_R_IOERROR
;
108 return ISC_R_SUCCESS
;
112 /* Variable to check if we're starting the server. The server will init as
113 * starting - but just to be safe start out as false to avoid triggering new
115 * XXX: There is actually a server_startup state...which is never entered...
119 static int server_starting
= 0;
121 static int find_uid_statement (struct executable_statement
*esp
,
124 struct executable_statement
**evp
= vp
;
126 if (esp
-> op
== supersede_option_statement
&&
127 esp
-> data
.option
&&
128 (esp
-> data
.option
-> option
-> universe
==
130 (esp
-> data
.option
-> option
-> code
==
131 DHO_DHCP_CLIENT_IDENTIFIER
)) {
133 log_error ("dhcp client identifier may not be %s",
134 "specified conditionally.");
135 } else if (!(*evp
)) {
136 executable_statement_reference (evp
, esp
, MDL
);
139 log_error ("only one dhcp client identifier may be %s",
147 static host_id_info_t
*
148 find_host_id_info(unsigned int option_code
) {
151 for (p
=host_id_info
; p
!= NULL
; p
= p
->next
) {
152 if (p
->option
->code
== option_code
) {
162 print_host(const void *name
, unsigned len
, void *value
) {
164 printf("--------------\n");
165 printf("name:'%s'\n", print_hex_1(len
, name
, 60));
166 printf("len:%d\n", len
);
167 h
= (struct host_decl
*)value
;
168 printf("host @%p is '%s'\n", h
, h
->name
);
169 return ISC_R_SUCCESS
;
173 hash_print_hosts(struct hash_table
*h
) {
174 hash_foreach(h
, print_host
);
175 printf("--------------\n");
180 change_host_uid(struct host_decl
*host
, const char *uid
, int len
) {
181 /* XXX: should consolidate this type of code throughout */
182 if (host_uid_hash
== NULL
) {
183 if (!host_new_hash(&host_uid_hash
, HOST_HASH_SIZE
, MDL
)) {
184 log_fatal("Can't allocate host/uid hash");
189 * Remove the old entry, if one exists.
191 if (host
->client_identifier
.data
!= NULL
) {
192 host_hash_delete(host_uid_hash
,
193 host
->client_identifier
.data
,
194 host
->client_identifier
.len
,
196 data_string_forget(&host
->client_identifier
, MDL
);
202 memset(&host
->client_identifier
, 0, sizeof(host
->client_identifier
));
203 host
->client_identifier
.len
= len
;
204 if (!buffer_allocate(&host
->client_identifier
.buffer
, len
, MDL
)) {
205 log_fatal("Can't allocate uid buffer");
207 host
->client_identifier
.data
= host
->client_identifier
.buffer
->data
;
208 memcpy((char *)host
->client_identifier
.data
, uid
, len
);
213 host_hash_add(host_uid_hash
, host
->client_identifier
.data
,
214 host
->client_identifier
.len
, host
, MDL
);
217 isc_result_t
enter_host (hd
, dynamicp
, commit
)
218 struct host_decl
*hd
;
222 struct host_decl
*hp
= (struct host_decl
*)0;
223 struct host_decl
*np
= (struct host_decl
*)0;
224 struct executable_statement
*esp
;
225 host_id_info_t
*h_id_info
;
227 if (!host_name_hash
) {
228 if (!host_new_hash(&host_name_hash
, HOST_HASH_SIZE
, MDL
))
229 log_fatal ("Can't allocate host name hash");
230 host_hash_add (host_name_hash
,
231 (unsigned char *)hd
-> name
,
232 strlen (hd
-> name
), hd
, MDL
);
234 host_hash_lookup (&hp
, host_name_hash
,
235 (unsigned char *)hd
-> name
,
236 strlen (hd
-> name
), MDL
);
238 /* If it's deleted, we can supersede it. */
239 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
240 host_hash_delete (host_name_hash
,
241 (unsigned char *)hd
-> name
,
242 strlen (hd
-> name
), MDL
);
243 /* If the old entry wasn't dynamic, then we
244 always have to keep the deletion. */
245 if (hp
-> flags
& HOST_DECL_STATIC
) {
246 hd
-> flags
|= HOST_DECL_STATIC
;
248 host_dereference (&hp
, MDL
);
251 /* If we are updating an existing host declaration, we
252 can just delete it and add it again. */
253 if (hp
&& hp
== hd
) {
254 host_dereference (&hp
, MDL
);
256 if (!write_host (hd
))
257 return ISC_R_IOERROR
;
258 hd
-> flags
&= ~HOST_DECL_DELETED
;
261 /* If there isn't already a host decl matching this
262 address, add it to the hash table. */
264 host_hash_add (host_name_hash
,
265 (unsigned char *)hd
-> name
,
266 strlen (hd
-> name
), hd
, MDL
);
268 /* XXX actually, we have to delete the old one
269 XXX carefully and replace it. Not done yet. */
270 host_dereference (&hp
, MDL
);
276 host_dereference (&hd
-> n_ipaddr
, MDL
);
279 hd
-> type
= dhcp_type_host
;
281 if (hd
-> interface
.hlen
) {
282 if (!host_hw_addr_hash
) {
283 if (!host_new_hash(&host_hw_addr_hash
,
284 HOST_HASH_SIZE
, MDL
))
285 log_fatal ("Can't allocate host/hw hash");
287 /* If there isn't already a host decl matching this
288 address, add it to the hash table. */
289 host_hash_lookup (&hp
, host_hw_addr_hash
,
290 hd
-> interface
.hbuf
,
291 hd
-> interface
.hlen
, MDL
);
294 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
295 hd
-> interface
.hlen
, hd
, MDL
);
297 /* If there was already a host declaration for
298 this hardware address, add this one to the
300 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
302 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
303 host_dereference (&hp
, MDL
);
307 /* See if there's a statement that sets the client identifier.
308 This is a kludge - the client identifier really shouldn't be
309 set with an executable statement. */
310 esp
= (struct executable_statement
*)0;
311 if (executable_statement_foreach (hd
-> group
-> statements
,
312 find_uid_statement
, &esp
, 0)) {
313 evaluate_option_cache (&hd
-> client_identifier
,
316 (struct client_state
*)0,
317 (struct option_state
*)0,
318 (struct option_state
*)0, &global_scope
,
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
);
375 if (h_id_info
== NULL
) {
376 h_id_info
= dmalloc(sizeof(*h_id_info
), MDL
);
377 if (h_id_info
== NULL
) {
378 log_fatal("No memory for host-identifier "
379 "option information.");
381 option_reference(&h_id_info
->option
,
382 hd
->host_id_option
, MDL
);
383 if (!host_new_hash(&h_id_info
->values_hash
,
384 HOST_HASH_SIZE
, MDL
)) {
385 log_fatal("No memory for host-identifier "
388 h_id_info
->next
= host_id_info
;
389 host_id_info
= h_id_info
;
392 if (host_hash_lookup(&hp
, h_id_info
->values_hash
,
393 hd
->host_id
.data
, hd
->host_id
.len
, MDL
)) {
395 * If this option is already present, then add
396 * this host to the list in n_ipaddr, unless
397 * we have already done so previously.
399 * XXXSK: This seems scary to me, but I don't
400 * fully understand how these are used.
401 * Shouldn't there be multiple lists, or
402 * maybe we should just forbid duplicates?
406 while (np
->n_ipaddr
!= NULL
) {
410 host_reference(&np
->n_ipaddr
, hd
, MDL
);
413 host_dereference(&hp
, MDL
);
415 host_hash_add(h_id_info
->values_hash
,
422 if (dynamicp
&& commit
) {
423 if (!write_host (hd
))
424 return ISC_R_IOERROR
;
425 if (!commit_leases ())
426 return ISC_R_IOERROR
;
429 return ISC_R_SUCCESS
;
433 isc_result_t
delete_class (cp
, commit
)
437 cp
->flags
|= CLASS_DECL_DELETED
;
439 /* do the write first as we won't be leaving it in any data
440 structures, unlike the host objects */
443 write_named_billing_class ((unsigned char *)cp
->name
, 0, cp
);
444 if (!commit_leases ())
445 return ISC_R_IOERROR
;
448 unlink_class(&cp
); /* remove from collections */
450 class_dereference(&cp
, MDL
);
452 return ISC_R_SUCCESS
;
456 isc_result_t
delete_host (hd
, commit
)
457 struct host_decl
*hd
;
460 struct host_decl
*hp
= (struct host_decl
*)0;
461 struct host_decl
*np
= (struct host_decl
*)0;
462 struct host_decl
*foo
;
463 int hw_head
= 0, uid_head
= 1;
465 /* Don't need to do it twice. */
466 if (hd
-> flags
& HOST_DECL_DELETED
)
467 return ISC_R_SUCCESS
;
469 /* But we do need to do it once! :') */
470 hd
-> flags
|= HOST_DECL_DELETED
;
472 if (hd
-> interface
.hlen
) {
473 if (host_hw_addr_hash
) {
474 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
475 hd
-> interface
.hbuf
,
476 hd
-> interface
.hlen
, MDL
)) {
478 host_hash_delete (host_hw_addr_hash
,
479 hd
-> interface
.hbuf
,
480 hd
-> interface
.hlen
, MDL
);
483 np
= (struct host_decl
*)0;
484 foo
= (struct host_decl
*)0;
485 host_reference (&foo
, hp
, MDL
);
490 host_dereference (&np
, MDL
);
491 host_reference (&np
, foo
, MDL
);
492 host_dereference (&foo
, MDL
);
494 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
498 host_dereference (&np
-> n_ipaddr
, MDL
);
500 host_reference (&np
-> n_ipaddr
,
501 hd
-> n_ipaddr
, MDL
);
502 host_dereference (&foo
, MDL
);
505 host_dereference (&np
, MDL
);
507 host_dereference (&hp
, MDL
);
512 /* If we got a client identifier, hash this entry by
513 client identifier. */
514 if (hd
-> client_identifier
.len
) {
516 if (host_hash_lookup (&hp
, host_uid_hash
,
517 hd
-> client_identifier
.data
,
518 hd
-> client_identifier
.len
, MDL
)) {
520 host_hash_delete (host_uid_hash
,
521 hd
-> client_identifier
.data
,
522 hd
-> client_identifier
.len
, MDL
);
525 np
= (struct host_decl
*)0;
526 foo
= (struct host_decl
*)0;
527 host_reference (&foo
, hp
, MDL
);
532 host_dereference (&np
, MDL
);
533 host_reference (&np
, foo
, MDL
);
534 host_dereference (&foo
, MDL
);
536 host_reference (&foo
, np
-> n_ipaddr
, MDL
);
540 host_dereference (&np
-> n_ipaddr
, MDL
);
542 host_reference (&np
-> n_ipaddr
,
543 hd
-> n_ipaddr
, MDL
);
544 host_dereference (&foo
, MDL
);
547 host_dereference (&np
, MDL
);
549 host_dereference (&hp
, MDL
);
554 if (hd
->host_id_option
!= NULL
) {
555 option_dereference(&hd
->host_id_option
, MDL
);
556 data_string_forget(&hd
->host_id
, MDL
);
559 if (hd
-> n_ipaddr
) {
560 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
563 hd
-> n_ipaddr
-> client_identifier
.data
,
564 hd
-> n_ipaddr
-> client_identifier
.len
,
565 hd
-> n_ipaddr
, MDL
);
567 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
568 host_hash_add (host_hw_addr_hash
,
569 hd
-> n_ipaddr
-> interface
.hbuf
,
570 hd
-> n_ipaddr
-> interface
.hlen
,
571 hd
-> n_ipaddr
, MDL
);
573 host_dereference (&hd
-> n_ipaddr
, MDL
);
576 if (host_name_hash
) {
577 if (host_hash_lookup (&hp
, host_name_hash
,
578 (unsigned char *)hd
-> name
,
579 strlen (hd
-> name
), MDL
)) {
580 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
581 host_hash_delete (host_name_hash
,
582 (unsigned char *)hd
-> name
,
583 strlen (hd
-> name
), MDL
);
585 host_dereference (&hp
, MDL
);
590 if (!write_host (hd
))
591 return ISC_R_IOERROR
;
592 if (!commit_leases ())
593 return ISC_R_IOERROR
;
595 return ISC_R_SUCCESS
;
598 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
599 const unsigned char *haddr
, unsigned hlen
,
600 const char *file
, int line
)
606 memcpy (&h
.hbuf
[1], haddr
, hlen
);
608 return host_hash_lookup (hp
, host_hw_addr_hash
,
609 h
.hbuf
, h
.hlen
, file
, line
);
612 int find_hosts_by_uid (struct host_decl
**hp
,
613 const unsigned char *data
, unsigned len
,
614 const char *file
, int line
)
616 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
620 find_hosts_by_option(struct host_decl
**hp
,
621 struct packet
*packet
,
622 struct option_state
*opt_state
,
623 const char *file
, int line
) {
625 struct option_cache
*oc
;
626 struct data_string data
;
629 for (p
= host_id_info
; p
!= NULL
; p
= p
->next
) {
630 oc
= lookup_option(p
->option
->universe
,
631 opt_state
, p
->option
->code
);
633 memset(&data
, 0, sizeof(data
));
634 if (!evaluate_option_cache(&data
, packet
, NULL
, NULL
,
638 log_error("Error evaluating option cache");
642 found
= host_hash_lookup(hp
, p
->values_hash
,
646 data_string_forget(&data
, MDL
);
656 /* More than one host_decl can be returned by find_hosts_by_haddr or
657 find_hosts_by_uid, and each host_decl can have multiple addresses.
658 Loop through the list of hosts, and then for each host, through the
659 list of addresses, looking for an address that's in the same shared
660 network as the one specified. Store the matching address through
661 the addr pointer, update the host pointer to point at the host_decl
662 that matched, and return the subnet that matched. */
664 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
665 struct iaddr
*addr
, struct shared_network
*share
)
668 struct iaddr ip_address
;
669 struct host_decl
*hp
;
670 struct data_string fixed_addr
;
672 memset (&fixed_addr
, 0, sizeof fixed_addr
);
674 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
675 if (!hp
-> fixed_addr
)
677 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
679 (struct client_state
*)0,
680 (struct option_state
*)0,
681 (struct option_state
*)0,
683 hp
-> fixed_addr
, MDL
))
685 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
687 memcpy (ip_address
.iabuf
,
688 fixed_addr
.data
+ i
, 4);
689 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
690 struct host_decl
*tmp
= (struct host_decl
*)0;
692 /* This is probably not necessary, but
693 just in case *host is the only reference
694 to that host declaration, make a temporary
695 reference so that dereferencing it doesn't
696 dereference hp out from under us. */
697 host_reference (&tmp
, *host
, MDL
);
698 host_dereference (host
, MDL
);
699 host_reference (host
, hp
, MDL
);
700 host_dereference (&tmp
, MDL
);
701 data_string_forget (&fixed_addr
, MDL
);
705 data_string_forget (&fixed_addr
, MDL
);
710 void new_address_range (cfile
, low
, high
, subnet
, pool
, lpchain
)
712 struct iaddr low
, high
;
713 struct subnet
*subnet
;
715 struct lease
**lpchain
;
717 #if defined(COMPACT_LEASES)
718 struct lease
*address_range
;
720 unsigned min
, max
, i
;
721 char lowbuf
[16], highbuf
[16], netbuf
[16];
722 struct shared_network
*share
= subnet
-> shared_network
;
723 struct lease
*lt
= (struct lease
*)0;
724 #if !defined(COMPACT_LEASES)
728 /* All subnets should have attached shared network structures. */
730 strcpy (netbuf
, piaddr (subnet
-> net
));
731 log_fatal ("No shared network for network %s (%s)",
732 netbuf
, piaddr (subnet
-> netmask
));
735 /* Initialize the hash table if it hasn't been done yet. */
736 if (!lease_uid_hash
) {
737 if (!lease_id_new_hash(&lease_uid_hash
, LEASE_HASH_SIZE
, MDL
))
738 log_fatal ("Can't allocate lease/uid hash");
740 if (!lease_ip_addr_hash
) {
741 if (!lease_ip_new_hash(&lease_ip_addr_hash
, LEASE_HASH_SIZE
,
743 log_fatal ("Can't allocate lease/ip hash");
745 if (!lease_hw_addr_hash
) {
746 if (!lease_id_new_hash(&lease_hw_addr_hash
, LEASE_HASH_SIZE
,
748 log_fatal ("Can't allocate lease/hw hash");
751 /* Make sure that high and low addresses are in this subnet. */
752 if (!addr_eq(subnet
->net
, subnet_number(low
, subnet
->netmask
))) {
753 strcpy(lowbuf
, piaddr(low
));
754 strcpy(netbuf
, piaddr(subnet
->net
));
755 log_fatal("bad range, address %s not in subnet %s netmask %s",
756 lowbuf
, netbuf
, piaddr(subnet
->netmask
));
759 if (!addr_eq(subnet
->net
, subnet_number(high
, subnet
->netmask
))) {
760 strcpy(highbuf
, piaddr(high
));
761 strcpy(netbuf
, piaddr(subnet
->net
));
762 log_fatal("bad range, address %s not in subnet %s netmask %s",
763 highbuf
, netbuf
, piaddr(subnet
->netmask
));
766 /* Get the high and low host addresses... */
767 max
= host_addr (high
, subnet
-> netmask
);
768 min
= host_addr (low
, subnet
-> netmask
);
770 /* Allow range to be specified high-to-low as well as low-to-high. */
773 min
= host_addr (high
, subnet
-> netmask
);
776 /* Get a lease structure for each address in the range. */
777 #if defined (COMPACT_LEASES)
778 address_range
= new_leases (max
- min
+ 1, MDL
);
779 if (!address_range
) {
780 strcpy (lowbuf
, piaddr (low
));
781 strcpy (highbuf
, piaddr (high
));
782 log_fatal ("No memory for address range %s-%s.",
787 /* Fill out the lease structures with some minimal information. */
788 for (i
= 0; i
< max
- min
+ 1; i
++) {
789 struct lease
*lp
= (struct lease
*)0;
790 #if defined (COMPACT_LEASES)
791 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
793 0, sizeof (struct lease
), MDL
);
794 lease_reference (&lp
, &address_range
[i
], MDL
);
796 status
= lease_allocate (&lp
, MDL
);
797 if (status
!= ISC_R_SUCCESS
)
798 log_fatal ("No memory for lease %s: %s",
799 piaddr (ip_addr (subnet
-> net
,
802 isc_result_totext (status
));
804 lp
-> ip_addr
= ip_addr (subnet
-> net
,
805 subnet
-> netmask
, i
+ min
);
806 lp
-> starts
= MIN_TIME
;
807 lp
-> ends
= MIN_TIME
;
808 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
809 pool_reference (&lp
-> pool
, pool
, MDL
);
810 lp
-> binding_state
= FTS_FREE
;
811 lp
-> next_binding_state
= FTS_FREE
;
814 /* Remember the lease in the IP address hash. */
815 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
818 "lease %s is declared twice!",
819 piaddr (lp
-> ip_addr
));
821 pool_reference (<
-> pool
, pool
, MDL
);
822 lease_dereference (<
, MDL
);
824 lease_ip_hash_add(lease_ip_addr_hash
,
825 lp
->ip_addr
.iabuf
, lp
->ip_addr
.len
,
827 /* Put the lease on the chain for the caller. */
830 lease_reference (&lp
-> next
, *lpchain
, MDL
);
831 lease_dereference (lpchain
, MDL
);
833 lease_reference (lpchain
, lp
, MDL
);
835 lease_dereference (&lp
, MDL
);
839 int find_subnet (struct subnet
**sp
,
840 struct iaddr addr
, const char *file
, int line
)
844 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
845 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
846 if (subnet_reference (sp
, rv
,
847 file
, line
) != ISC_R_SUCCESS
)
855 int find_grouped_subnet (struct subnet
**sp
,
856 struct shared_network
*share
, struct iaddr addr
,
857 const char *file
, int line
)
861 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
862 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
863 if (subnet_reference (sp
, rv
,
864 file
, line
) != ISC_R_SUCCESS
)
872 /* XXX: could speed up if everyone had a prefix length */
874 subnet_inner_than(const struct subnet
*subnet
,
875 const struct subnet
*scan
,
877 if (addr_eq(subnet_number(subnet
->net
, scan
->netmask
), scan
->net
) ||
878 addr_eq(subnet_number(scan
->net
, subnet
->netmask
), subnet
->net
)) {
879 char n1buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
881 for (i
= 0; i
< 128; i
++)
882 if (subnet
->netmask
.iabuf
[3 - (i
>> 3)]
885 for (j
= 0; j
< 128; j
++)
886 if (scan
->netmask
.iabuf
[3 - (j
>> 3)] &
890 strcpy(n1buf
, piaddr(subnet
->net
));
891 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
893 piaddr(scan
->net
), 32 - j
);
901 /* Enter a new subnet into the subnet list. */
902 void enter_subnet (subnet
)
903 struct subnet
*subnet
;
905 struct subnet
*scan
= (struct subnet
*)0;
906 struct subnet
*next
= (struct subnet
*)0;
907 struct subnet
*prev
= (struct subnet
*)0;
909 /* Check for duplicates... */
911 subnet_reference (&next
, subnets
, MDL
);
913 subnet_reference (&scan
, next
, MDL
);
914 subnet_dereference (&next
, MDL
);
916 /* When we find a conflict, make sure that the
917 subnet with the narrowest subnet mask comes
919 if (subnet_inner_than (subnet
, scan
, 1)) {
921 if (prev
-> next_subnet
)
922 subnet_dereference (&prev
-> next_subnet
, MDL
);
923 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
924 subnet_dereference (&prev
, MDL
);
926 subnet_dereference (&subnets
, MDL
);
927 subnet_reference (&subnets
, subnet
, MDL
);
929 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
930 subnet_dereference (&scan
, MDL
);
933 subnet_reference (&prev
, scan
, MDL
);
934 subnet_dereference (&scan
, MDL
);
937 subnet_dereference (&prev
, MDL
);
939 /* XXX use the BSD radix tree code instead of a linked list. */
941 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
942 subnet_dereference (&subnets
, MDL
);
944 subnet_reference (&subnets
, subnet
, MDL
);
947 /* Enter a new shared network into the shared network list. */
949 void enter_shared_network (share
)
950 struct shared_network
*share
;
952 if (shared_networks
) {
953 shared_network_reference (&share
-> next
,
954 shared_networks
, MDL
);
955 shared_network_dereference (&shared_networks
, MDL
);
957 shared_network_reference (&shared_networks
, share
, MDL
);
960 void new_shared_network_interface (cfile
, share
, name
)
962 struct shared_network
*share
;
965 struct interface_info
*ip
;
968 if (share
-> interface
) {
970 "A subnet or shared network can't be connected %s",
971 "to two interfaces.");
975 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
976 if (!strcmp (ip
-> name
, name
))
979 status
= interface_allocate (&ip
, MDL
);
980 if (status
!= ISC_R_SUCCESS
)
981 log_fatal ("new_shared_network_interface %s: %s",
982 name
, isc_result_totext (status
));
983 if (strlen (name
) > sizeof ip
-> name
) {
984 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
985 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
987 strcpy (ip
-> name
, name
);
989 interface_reference (&ip
-> next
, interfaces
, MDL
);
990 interface_dereference (&interfaces
, MDL
);
992 interface_reference (&interfaces
, ip
, MDL
);
993 ip
-> flags
= INTERFACE_REQUESTED
;
994 /* XXX this is a reference loop. */
995 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
996 interface_reference (&share
-> interface
, ip
, MDL
);
1000 /* Enter a lease into the system. This is called by the parser each
1001 time it reads in a new lease. If the subnet for that lease has
1002 already been read in (usually the case), just update that lease;
1003 otherwise, allocate temporary storage for the lease and keep it around
1004 until we're done reading in the config file. */
1006 void enter_lease (lease
)
1007 struct lease
*lease
;
1009 struct lease
*comp
= (struct lease
*)0;
1011 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
1012 if (!comp
-> pool
) {
1013 log_error ("undeclared lease found in database: %s",
1014 piaddr (lease
-> ip_addr
));
1016 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
1019 subnet_reference (&lease
-> subnet
,
1020 comp
-> subnet
, MDL
);
1021 lease_ip_hash_delete(lease_ip_addr_hash
,
1022 lease
->ip_addr
.iabuf
, lease
->ip_addr
.len
,
1024 lease_dereference (&comp
, MDL
);
1027 /* The only way a lease can get here without a subnet is if it's in
1028 the lease file, but not in the dhcpd.conf file. In this case, we
1029 *should* keep it around until it's expired, but never reallocate it
1030 or renew it. Currently, to maintain consistency, we are not doing
1032 XXX fix this so that the lease is kept around until it expires.
1033 XXX this will be important in IPv6 with addresses that become
1034 XXX non-renewable as a result of a renumbering event. */
1036 if (!lease
-> subnet
) {
1037 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
1040 lease_ip_hash_add(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
1041 lease
->ip_addr
.len
, lease
, MDL
);
1044 /* Replace the data in an existing lease with the data in a new lease;
1045 adjust hash tables to suit, and insertion sort the lease into the
1046 list of leases by expiry time so that we can always find the oldest
1049 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
1050 struct lease
*comp
, *lease
;
1055 struct lease
*lp
, **lq
, *prev
;
1057 #if defined (FAILOVER_PROTOCOL)
1058 int do_pool_check
= 0;
1060 /* We must commit leases before sending updates regarding them
1061 to failover peers. It is, therefore, an error to set pimmediate
1063 if (pimmediate
&& !commit
)
1067 /* If there is no sample lease, just do the move. */
1071 /* Static leases are not currently kept in the database... */
1072 if (lease
-> flags
& STATIC_LEASE
)
1075 /* If the existing lease hasn't expired and has a different
1076 unique identifier or, if it doesn't have a unique
1077 identifier, a different hardware address, then the two
1078 leases are in conflict. If the existing lease has a uid
1079 and the new one doesn't, but they both have the same
1080 hardware address, and dynamic bootp is allowed on this
1081 lease, then we allow that, in case a dynamic BOOTP lease is
1082 requested *after* a DHCP lease has been assigned. */
1084 if (lease
-> binding_state
!= FTS_ABANDONED
&&
1085 lease
-> next_binding_state
!= FTS_ABANDONED
&&
1086 comp
-> binding_state
== FTS_ACTIVE
&&
1087 (((comp
-> uid
&& lease
-> uid
) &&
1088 (comp
-> uid_len
!= lease
-> uid_len
||
1089 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
1091 ((comp
-> hardware_addr
.hlen
!=
1092 lease
-> hardware_addr
.hlen
) ||
1093 memcmp (comp
-> hardware_addr
.hbuf
,
1094 lease
-> hardware_addr
.hbuf
,
1095 comp
-> hardware_addr
.hlen
))))) {
1096 log_error ("Lease conflict at %s",
1097 piaddr (comp
-> ip_addr
));
1100 /* If there's a Unique ID, dissociate it from the hash
1101 table and free it if necessary. */
1103 uid_hash_delete(comp
);
1104 if (comp
->uid
!= comp
->uid_buf
) {
1105 dfree(comp
->uid
, MDL
);
1109 comp
-> uid
= (unsigned char *)0;
1112 /* If there's a hardware address, remove the lease from its
1113 * old position in the hash bucket's ordered list.
1115 if (comp
->hardware_addr
.hlen
)
1116 hw_hash_delete(comp
);
1118 /* If the lease has been billed to a class, remove the billing. */
1119 if (comp
-> billing_class
!= lease
-> billing_class
) {
1120 if (comp
-> billing_class
)
1121 unbill_class (comp
, comp
-> billing_class
);
1122 if (lease
-> billing_class
)
1123 bill_class (comp
, lease
-> billing_class
);
1126 /* Copy the data files, but not the linkages. */
1127 comp
-> starts
= lease
-> starts
;
1129 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
1130 memcpy (comp
-> uid_buf
,
1131 lease
-> uid
, lease
-> uid_len
);
1132 comp
-> uid
= &comp
-> uid_buf
[0];
1133 comp
-> uid_max
= sizeof comp
-> uid_buf
;
1134 comp
-> uid_len
= lease
-> uid_len
;
1135 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
1136 comp
-> uid
= lease
-> uid
;
1137 comp
-> uid_max
= lease
-> uid_max
;
1138 lease
-> uid
= (unsigned char *)0;
1139 lease
-> uid_max
= 0;
1140 comp
-> uid_len
= lease
-> uid_len
;
1141 lease
-> uid_len
= 0;
1143 log_fatal ("corrupt lease uid."); /* XXX */
1146 comp
-> uid
= (unsigned char *)0;
1147 comp
-> uid_len
= comp
-> uid_max
= 0;
1150 host_dereference (&comp
-> host
, MDL
);
1151 host_reference (&comp
-> host
, lease
-> host
, MDL
);
1152 comp
-> hardware_addr
= lease
-> hardware_addr
;
1153 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
1154 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
1156 binding_scope_dereference (&comp
-> scope
, MDL
);
1157 if (lease
-> scope
) {
1158 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
1159 binding_scope_dereference (&lease
-> scope
, MDL
);
1162 if (comp
-> agent_options
)
1163 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
1164 if (lease
-> agent_options
) {
1165 /* Only retain the agent options if the lease is still
1166 affirmatively associated with a client. */
1167 if (lease
-> next_binding_state
== FTS_ACTIVE
||
1168 lease
-> next_binding_state
== FTS_EXPIRED
)
1169 option_chain_head_reference (&comp
-> agent_options
,
1170 lease
-> agent_options
,
1172 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
1175 /* Record the hostname information in the lease. */
1176 if (comp
-> client_hostname
)
1177 dfree (comp
-> client_hostname
, MDL
);
1178 comp
-> client_hostname
= lease
-> client_hostname
;
1179 lease
-> client_hostname
= (char *)0;
1181 if (lease
-> on_expiry
) {
1182 if (comp
-> on_expiry
)
1183 executable_statement_dereference (&comp
-> on_expiry
,
1185 executable_statement_reference (&comp
-> on_expiry
,
1189 if (lease
-> on_commit
) {
1190 if (comp
-> on_commit
)
1191 executable_statement_dereference (&comp
-> on_commit
,
1193 executable_statement_reference (&comp
-> on_commit
,
1197 if (lease
-> on_release
) {
1198 if (comp
-> on_release
)
1199 executable_statement_dereference (&comp
-> on_release
,
1201 executable_statement_reference (&comp
-> on_release
,
1202 lease
-> on_release
, MDL
);
1205 /* Record the lease in the uid hash if necessary. */
1209 /* Record it in the hardware address hash if necessary. */
1210 if (comp
->hardware_addr
.hlen
)
1213 comp
->cltt
= lease
->cltt
;
1214 #if defined (FAILOVER_PROTOCOL)
1215 comp
->tstp
= lease
->tstp
;
1216 comp
->tsfp
= lease
->tsfp
;
1217 comp
->atsfp
= lease
->atsfp
;
1218 #endif /* FAILOVER_PROTOCOL */
1219 comp
->ends
= lease
->ends
;
1220 comp
->next_binding_state
= lease
->next_binding_state
;
1223 #if defined (FAILOVER_PROTOCOL)
1224 /* Atsfp should be cleared upon any state change that implies
1225 * propagation whether supersede_lease was given a copy lease
1226 * structure or not (often from the pool_timer()).
1230 #endif /* FAILOVER_PROTOCOL */
1232 if (!comp
-> pool
) {
1233 log_error ("Supersede_lease: lease %s with no pool.",
1234 piaddr (comp
-> ip_addr
));
1238 /* Figure out which queue it's on. */
1239 switch (comp
-> binding_state
) {
1241 if (comp
->flags
& RESERVED_LEASE
)
1242 lq
= &comp
->pool
->reserved
;
1244 lq
= &comp
->pool
->free
;
1245 comp
->pool
->free_leases
--;
1248 #if defined(FAILOVER_PROTOCOL)
1254 lq
= &comp
-> pool
-> active
;
1260 lq
= &comp
-> pool
-> expired
;
1264 lq
= &comp
-> pool
-> abandoned
;
1268 if (comp
->flags
& RESERVED_LEASE
)
1269 lq
= &comp
->pool
->reserved
;
1271 lq
= &comp
->pool
->backup
;
1272 comp
->pool
->backup_leases
--;
1275 #if defined(FAILOVER_PROTOCOL)
1281 log_error ("Lease with bogus binding state: %d",
1282 comp
-> binding_state
);
1283 #if defined (BINDING_STATE_DEBUG)
1289 /* Remove the lease from its current place in its current
1291 /* XXX this is horrid. */
1292 prev
= (struct lease
*)0;
1293 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1300 log_fatal("Lease with binding state %s not on its queue.",
1301 (comp
->binding_state
< 1 ||
1302 comp
->binding_state
> FTS_LAST
)
1304 : binding_state_names
[comp
->binding_state
- 1]);
1308 lease_dereference (&prev
-> next
, MDL
);
1310 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1311 lease_dereference (&comp
-> next
, MDL
);
1314 lease_dereference (lq
, MDL
);
1316 lease_reference (lq
, comp
-> next
, MDL
);
1317 lease_dereference (&comp
-> next
, MDL
);
1321 /* Make the state transition. */
1322 if (commit
|| !pimmediate
)
1323 make_binding_state_transition (comp
);
1325 /* Put the lease back on the appropriate queue. If the lease
1326 is corrupt (as detected by lease_enqueue), don't go any farther. */
1327 if (!lease_enqueue (comp
))
1330 /* If this is the next lease that will timeout on the pool,
1331 zap the old timeout and set the timeout on this pool to the
1332 time that the lease's next event will happen.
1334 We do not actually set the timeout unless commit is true -
1335 we don't want to thrash the timer queue when reading the
1336 lease database. Instead, the database code calls the
1337 expiry event on each pool after reading in the lease file,
1338 and the expiry code sets the timer if there's anything left
1339 to expire after it's run any outstanding expiry events on
1341 if ((commit
|| !pimmediate
) &&
1342 comp
-> sort_time
!= MIN_TIME
&&
1343 comp
-> sort_time
> cur_time
&&
1344 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1345 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1346 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1347 tv
. tv_sec
= comp
-> pool
-> next_event_time
;
1350 pool_timer
, comp
-> pool
,
1351 (tvref_t
)pool_reference
,
1352 (tvunref_t
)pool_dereference
);
1356 if (!write_lease (comp
))
1358 if ((server_starting
& SS_NOSYNC
) == 0) {
1359 if (!commit_leases ())
1364 #if defined (FAILOVER_PROTOCOL)
1366 comp
-> desired_binding_state
= comp
-> binding_state
;
1367 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1370 if (do_pool_check
&& comp
->pool
->failover_peer
)
1371 dhcp_failover_pool_check(comp
->pool
);
1374 /* If the current binding state has already expired, do an
1375 expiry event right now. */
1376 /* XXX At some point we should optimize this so that we don't
1377 XXX write the lease twice, but this is a safe way to fix the
1378 XXX problem for 3.0 (I hope!). */
1379 if ((commit
|| !pimmediate
) &&
1380 comp
-> sort_time
< cur_time
&&
1381 comp
-> next_binding_state
!= comp
-> binding_state
)
1382 pool_timer (comp
-> pool
);
1387 void make_binding_state_transition (struct lease
*lease
)
1389 #if defined (FAILOVER_PROTOCOL)
1390 dhcp_failover_state_t
*peer
;
1392 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1393 peer
= lease
-> pool
-> failover_peer
;
1395 peer
= (dhcp_failover_state_t
*)0;
1398 /* If the lease was active and is now no longer active, but isn't
1399 released, then it just expired, so do the expiry event. */
1400 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1402 #if defined (FAILOVER_PROTOCOL)
1404 (lease
-> binding_state
== FTS_EXPIRED
||
1405 (peer
-> i_am
== secondary
&&
1406 lease
-> binding_state
== FTS_ACTIVE
)) &&
1407 (lease
-> next_binding_state
== FTS_FREE
||
1408 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1411 lease
-> binding_state
== FTS_ACTIVE
&&
1412 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1413 #if defined (NSUPDATE)
1414 ddns_removals(lease
, NULL
);
1416 if (lease
-> on_expiry
) {
1417 execute_statements ((struct binding_value
**)0,
1418 (struct packet
*)0, lease
,
1419 (struct client_state
*)0,
1420 (struct option_state
*)0,
1421 (struct option_state
*)0, /* XXX */
1423 lease
-> on_expiry
);
1424 if (lease
-> on_expiry
)
1425 executable_statement_dereference
1426 (&lease
-> on_expiry
, MDL
);
1429 /* No sense releasing a lease after it's expired. */
1430 if (lease
-> on_release
)
1431 executable_statement_dereference (&lease
-> on_release
,
1433 /* Get rid of client-specific bindings that are only
1434 correct when the lease is active. */
1435 if (lease
-> billing_class
)
1436 unbill_class (lease
, lease
-> billing_class
);
1437 if (lease
-> agent_options
)
1438 option_chain_head_dereference (&lease
-> agent_options
,
1440 if (lease
-> client_hostname
) {
1441 dfree (lease
-> client_hostname
, MDL
);
1442 lease
-> client_hostname
= (char *)0;
1445 host_dereference (&lease
-> host
, MDL
);
1447 /* Send the expiry time to the peer. */
1448 lease
-> tstp
= lease
-> ends
;
1451 /* If the lease was active and is now released, do the release
1453 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1455 #if defined (FAILOVER_PROTOCOL)
1457 lease
-> binding_state
== FTS_RELEASED
&&
1458 (lease
-> next_binding_state
== FTS_FREE
||
1459 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1462 lease
-> binding_state
== FTS_ACTIVE
&&
1463 lease
-> next_binding_state
== FTS_RELEASED
))) {
1464 #if defined (NSUPDATE)
1465 ddns_removals(lease
, NULL
);
1467 if (lease
-> on_release
) {
1468 execute_statements ((struct binding_value
**)0,
1469 (struct packet
*)0, lease
,
1470 (struct client_state
*)0,
1471 (struct option_state
*)0,
1472 (struct option_state
*)0, /* XXX */
1474 lease
-> on_release
);
1475 executable_statement_dereference (&lease
-> on_release
,
1479 /* A released lease can't expire. */
1480 if (lease
-> on_expiry
)
1481 executable_statement_dereference (&lease
-> on_expiry
,
1484 /* Get rid of client-specific bindings that are only
1485 correct when the lease is active. */
1486 if (lease
-> billing_class
)
1487 unbill_class (lease
, lease
-> billing_class
);
1488 if (lease
-> agent_options
)
1489 option_chain_head_dereference (&lease
-> agent_options
,
1491 if (lease
-> client_hostname
) {
1492 dfree (lease
-> client_hostname
, MDL
);
1493 lease
-> client_hostname
= (char *)0;
1496 host_dereference (&lease
-> host
, MDL
);
1498 /* Send the release time (should be == cur_time) to the
1500 lease
-> tstp
= lease
-> ends
;
1503 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1504 log_debug ("lease %s moves from %s to %s",
1505 piaddr (lease
-> ip_addr
),
1506 binding_state_print (lease
-> binding_state
),
1507 binding_state_print (lease
-> next_binding_state
));
1510 lease
-> binding_state
= lease
-> next_binding_state
;
1511 switch (lease
-> binding_state
) {
1513 #if defined (FAILOVER_PROTOCOL)
1514 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1515 lease
-> next_binding_state
= FTS_EXPIRED
;
1518 lease
-> next_binding_state
= FTS_FREE
;
1525 lease
-> next_binding_state
= FTS_FREE
;
1526 #if defined(FAILOVER_PROTOCOL)
1527 /* If we are not in partner_down, leases don't go from
1528 EXPIRED to FREE on a timeout - only on an update.
1529 If we're in partner_down, they expire at mclt past
1530 the time we entered partner_down. */
1531 if (lease
-> pool
-> failover_peer
&&
1532 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1534 (lease
-> pool
-> failover_peer
-> me
.stos
+
1535 lease
-> pool
-> failover_peer
-> mclt
);
1536 #endif /* FAILOVER_PROTOCOL */
1541 lease
-> next_binding_state
= lease
-> binding_state
;
1544 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1545 log_debug ("lease %s: next binding state %s",
1546 piaddr (lease
-> ip_addr
),
1547 binding_state_print (lease
-> next_binding_state
));
1552 /* Copy the contents of one lease into another, correctly maintaining
1553 reference counts. */
1554 int lease_copy (struct lease
**lp
,
1555 struct lease
*lease
, const char *file
, int line
)
1557 struct lease
*lt
= (struct lease
*)0;
1558 isc_result_t status
;
1560 status
= lease_allocate (<
, MDL
);
1561 if (status
!= ISC_R_SUCCESS
)
1564 lt
-> ip_addr
= lease
-> ip_addr
;
1565 lt
-> starts
= lease
-> starts
;
1566 lt
-> ends
= lease
-> ends
;
1567 lt
-> uid_len
= lease
-> uid_len
;
1568 lt
-> uid_max
= lease
-> uid_max
;
1569 if (lease
-> uid
== lease
-> uid_buf
) {
1570 lt
-> uid
= lt
-> uid_buf
;
1571 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1572 } else if (!lease
-> uid_max
) {
1573 lt
-> uid
= (unsigned char *)0;
1575 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1577 lease_dereference (<
, MDL
);
1580 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1582 if (lease
-> client_hostname
) {
1583 lt
-> client_hostname
=
1584 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1585 if (!lt
-> client_hostname
) {
1586 lease_dereference (<
, MDL
);
1589 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1592 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1593 if (lease
-> agent_options
)
1594 option_chain_head_reference (<
-> agent_options
,
1595 lease
-> agent_options
, MDL
);
1596 host_reference (<
-> host
, lease
-> host
, file
, line
);
1597 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1598 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1599 class_reference (<
-> billing_class
,
1600 lease
-> billing_class
, file
, line
);
1601 lt
-> hardware_addr
= lease
-> hardware_addr
;
1602 if (lease
-> on_expiry
)
1603 executable_statement_reference (<
-> on_expiry
,
1606 if (lease
-> on_commit
)
1607 executable_statement_reference (<
-> on_commit
,
1610 if (lease
-> on_release
)
1611 executable_statement_reference (<
-> on_release
,
1612 lease
-> on_release
,
1614 lt
->flags
= lease
->flags
;
1615 lt
->tstp
= lease
->tstp
;
1616 lt
->tsfp
= lease
->tsfp
;
1617 lt
->atsfp
= lease
->atsfp
;
1618 lt
->cltt
= lease
-> cltt
;
1619 lt
->binding_state
= lease
->binding_state
;
1620 lt
->next_binding_state
= lease
->next_binding_state
;
1621 status
= lease_reference(lp
, lt
, file
, line
);
1622 lease_dereference(<
, MDL
);
1623 return status
== ISC_R_SUCCESS
;
1626 /* Release the specified lease and re-hash it as appropriate. */
1627 void release_lease (lease
, packet
)
1628 struct lease
*lease
;
1629 struct packet
*packet
;
1631 /* If there are statements to execute when the lease is
1632 released, execute them. */
1633 #if defined (NSUPDATE)
1634 ddns_removals(lease
, NULL
);
1636 if (lease
-> on_release
) {
1637 execute_statements ((struct binding_value
**)0,
1638 packet
, lease
, (struct client_state
*)0,
1640 (struct option_state
*)0, /* XXX */
1641 &lease
-> scope
, lease
-> on_release
);
1642 if (lease
-> on_release
)
1643 executable_statement_dereference (&lease
-> on_release
,
1647 /* We do either the on_release or the on_expiry events, but
1648 not both (it's possible that they could be the same,
1650 if (lease
-> on_expiry
)
1651 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1653 if (lease
-> binding_state
!= FTS_FREE
&&
1654 lease
-> binding_state
!= FTS_BACKUP
&&
1655 lease
-> binding_state
!= FTS_RELEASED
&&
1656 lease
-> binding_state
!= FTS_EXPIRED
&&
1657 lease
-> binding_state
!= FTS_RESET
) {
1658 if (lease
-> on_commit
)
1659 executable_statement_dereference (&lease
-> on_commit
,
1662 /* Blow away any bindings. */
1664 binding_scope_dereference (&lease
-> scope
, MDL
);
1666 /* Set sort times to the present. */
1667 lease
-> ends
= cur_time
;
1668 /* Lower layers of muckery set tstp to ->ends. But we send
1669 * protocol messages before this. So it is best to set
1672 lease
->tstp
= cur_time
;
1673 #if defined (FAILOVER_PROTOCOL)
1674 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1675 lease
-> next_binding_state
= FTS_RELEASED
;
1677 lease
-> next_binding_state
= FTS_FREE
;
1680 lease
-> next_binding_state
= FTS_FREE
;
1682 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1686 /* Abandon the specified lease (set its timeout to infinity and its
1687 particulars to zero, and re-hash it as appropriate. */
1689 void abandon_lease (lease
, message
)
1690 struct lease
*lease
;
1691 const char *message
;
1693 struct lease
*lt
= (struct lease
*)0;
1694 #if defined (NSUPDATE)
1695 ddns_removals(lease
, NULL
);
1698 if (!lease_copy (<
, lease
, MDL
))
1702 binding_scope_dereference(<
->scope
, MDL
);
1704 lt
-> ends
= cur_time
; /* XXX */
1705 lt
-> next_binding_state
= FTS_ABANDONED
;
1707 log_error ("Abandoning IP address %s: %s",
1708 piaddr (lease
-> ip_addr
), message
);
1709 lt
-> hardware_addr
.hlen
= 0;
1710 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1711 dfree (lt
-> uid
, MDL
);
1712 lt
-> uid
= (unsigned char *)0;
1715 supersede_lease (lease
, lt
, 1, 1, 1);
1716 lease_dereference (<
, MDL
);
1719 /* Abandon the specified lease (set its timeout to infinity and its
1720 particulars to zero, and re-hash it as appropriate. */
1722 void dissociate_lease (lease
)
1723 struct lease
*lease
;
1725 struct lease
*lt
= (struct lease
*)0;
1726 #if defined (NSUPDATE)
1727 ddns_removals(lease
, NULL
);
1730 if (!lease_copy (<
, lease
, MDL
))
1733 #if defined (FAILOVER_PROTOCOL)
1734 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1735 lt
-> next_binding_state
= FTS_RESET
;
1737 lt
-> next_binding_state
= FTS_FREE
;
1740 lt
-> next_binding_state
= FTS_FREE
;
1742 lt
-> ends
= cur_time
; /* XXX */
1743 lt
-> hardware_addr
.hlen
= 0;
1744 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1745 dfree (lt
-> uid
, MDL
);
1746 lt
-> uid
= (unsigned char *)0;
1749 supersede_lease (lease
, lt
, 1, 1, 1);
1750 lease_dereference (<
, MDL
);
1753 /* Timer called when a lease in a particular pool expires. */
1754 void pool_timer (vpool
)
1758 struct lease
*next
= (struct lease
*)0;
1759 struct lease
*lease
= (struct lease
*)0;
1760 #define FREE_LEASES 0
1761 #define ACTIVE_LEASES 1
1762 #define EXPIRED_LEASES 2
1763 #define ABANDONED_LEASES 3
1764 #define BACKUP_LEASES 4
1765 #define RESERVED_LEASES 5
1766 struct lease
**lptr
[RESERVED_LEASES
+1];
1767 TIME next_expiry
= MAX_TIME
;
1771 pool
= (struct pool
*)vpool
;
1773 lptr
[FREE_LEASES
] = &pool
-> free
;
1774 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1775 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1776 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1777 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1778 lptr
[RESERVED_LEASES
] = &pool
->reserved
;
1780 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
1781 /* If there's nothing on the queue, skip it. */
1785 #if defined (FAILOVER_PROTOCOL)
1786 if (pool
-> failover_peer
&&
1787 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1788 /* The secondary can't remove a lease from the
1789 active state except in partner_down. */
1790 if (i
== ACTIVE_LEASES
&&
1791 pool
-> failover_peer
-> i_am
== secondary
)
1793 /* Leases in an expired state don't move to
1794 free because of a timeout unless we're in
1796 if (i
== EXPIRED_LEASES
)
1800 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1803 /* Remember the next lease in the list. */
1805 lease_dereference (&next
, MDL
);
1807 lease_reference (&next
, lease
-> next
, MDL
);
1809 /* If we've run out of things to expire on this list,
1811 if (lease
-> sort_time
> cur_time
) {
1812 if (lease
-> sort_time
< next_expiry
)
1813 next_expiry
= lease
-> sort_time
;
1817 /* If there is a pending state change, and
1818 this lease has gotten to the time when the
1819 state change should happen, just call
1820 supersede_lease on it to make the change
1822 if (lease
-> next_binding_state
!=
1823 lease
-> binding_state
)
1824 supersede_lease (lease
,
1825 (struct lease
*)0, 1, 1, 1);
1827 lease_dereference (&lease
, MDL
);
1829 lease_reference (&lease
, next
, MDL
);
1832 lease_dereference (&next
, MDL
);
1834 lease_dereference (&lease
, MDL
);
1836 if (next_expiry
!= MAX_TIME
) {
1837 pool
-> next_event_time
= next_expiry
;
1838 tv
. tv_sec
= pool
-> next_event_time
;
1840 add_timeout (&tv
, pool_timer
, pool
,
1841 (tvref_t
)pool_reference
,
1842 (tvunref_t
)pool_dereference
);
1844 pool
-> next_event_time
= MIN_TIME
;
1848 /* Locate the lease associated with a given IP address... */
1850 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1851 const char *file
, int line
)
1853 return lease_ip_hash_lookup(lp
, lease_ip_addr_hash
, addr
.iabuf
,
1854 addr
.len
, file
, line
);
1857 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1858 unsigned len
, const char *file
, int line
)
1862 return lease_id_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1865 int find_lease_by_hw_addr (struct lease
**lp
,
1866 const unsigned char *hwaddr
, unsigned hwlen
,
1867 const char *file
, int line
)
1871 return lease_id_hash_lookup(lp
, lease_hw_addr_hash
, hwaddr
, hwlen
,
1875 /* If the lease is preferred over the candidate, return truth. The
1876 * 'cand' and 'lease' names are retained to read more clearly against
1877 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
1878 * to those two functions).
1880 * 1) ACTIVE leases are preferred. The active lease with
1881 * the longest lifetime is preferred over shortest.
1882 * 2) "transitional states" are next, this time with the
1884 * 3) free/backup/etc states are next, again with CLTT. In truth we
1885 * should never see reset leases for this.
1886 * 4) Abandoned leases are always dead last.
1888 static isc_boolean_t
1889 client_lease_preferred(struct lease
*cand
, struct lease
*lease
)
1891 if (cand
->binding_state
== FTS_ACTIVE
) {
1892 if (lease
->binding_state
== FTS_ACTIVE
&&
1893 lease
->ends
>= cand
->ends
)
1895 } else if (cand
->binding_state
== FTS_EXPIRED
||
1896 cand
->binding_state
== FTS_RELEASED
) {
1897 if (lease
->binding_state
== FTS_ACTIVE
)
1900 if ((lease
->binding_state
== FTS_EXPIRED
||
1901 lease
->binding_state
== FTS_RELEASED
) &&
1902 lease
->cltt
>= cand
->cltt
)
1904 } else if (cand
->binding_state
!= FTS_ABANDONED
) {
1905 if (lease
->binding_state
== FTS_ACTIVE
||
1906 lease
->binding_state
== FTS_EXPIRED
||
1907 lease
->binding_state
== FTS_RELEASED
)
1910 if (lease
->binding_state
!= FTS_ABANDONED
&&
1911 lease
->cltt
>= cand
->cltt
)
1913 } else /* (cand->binding_state == FTS_ABANDONED) */ {
1914 if (lease
->binding_state
!= FTS_ABANDONED
||
1915 lease
->cltt
>= cand
->cltt
)
1922 /* Add the specified lease to the uid hash. */
1924 uid_hash_add(struct lease
*lease
)
1926 struct lease
*head
= NULL
;
1927 struct lease
*cand
= NULL
;
1928 struct lease
*prev
= NULL
;
1929 struct lease
*next
= NULL
;
1931 /* If it's not in the hash, just add it. */
1932 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1933 lease_id_hash_add(lease_uid_hash
, lease
->uid
, lease
->uid_len
,
1936 /* Otherwise, insert it into the list in order of its
1937 * preference for "resuming allocation to the client."
1939 * Because we don't have control of the hash bucket index
1940 * directly, we have to remove and re-insert the client
1941 * id into the hash if we're inserting onto the head.
1943 lease_reference(&cand
, head
, MDL
);
1944 while (cand
!= NULL
) {
1945 if (client_lease_preferred(cand
, lease
))
1949 lease_dereference(&prev
, MDL
);
1950 lease_reference(&prev
, cand
, MDL
);
1952 if (cand
->n_uid
!= NULL
)
1953 lease_reference(&next
, cand
->n_uid
, MDL
);
1955 lease_dereference(&cand
, MDL
);
1958 lease_reference(&cand
, next
, MDL
);
1959 lease_dereference(&next
, MDL
);
1963 /* If we want to insert 'before cand', and prev is NULL,
1964 * then it was the head of the list. Assume that position.
1967 lease_reference(&lease
->n_uid
, head
, MDL
);
1968 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
1969 lease
->uid_len
, MDL
);
1970 lease_id_hash_add(lease_uid_hash
, lease
->uid
,
1971 lease
->uid_len
, lease
, MDL
);
1972 } else /* (prev != NULL) */ {
1973 if(prev
->n_uid
!= NULL
) {
1974 lease_reference(&lease
->n_uid
, prev
->n_uid
,
1976 lease_dereference(&prev
->n_uid
, MDL
);
1978 lease_reference(&prev
->n_uid
, lease
, MDL
);
1980 lease_dereference(&prev
, MDL
);
1984 lease_dereference(&cand
, MDL
);
1985 lease_dereference(&head
, MDL
);
1989 /* Delete the specified lease from the uid hash. */
1991 void uid_hash_delete (lease
)
1992 struct lease
*lease
;
1994 struct lease
*head
= (struct lease
*)0;
1997 /* If it's not in the hash, we have no work to do. */
1998 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
2000 lease_dereference (&lease
-> n_uid
, MDL
);
2004 /* If the lease we're freeing is at the head of the list,
2005 remove the hash table entry and add a new one with the
2006 next lease on the list (if there is one). */
2007 if (head
== lease
) {
2008 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
2009 lease
->uid_len
, MDL
);
2010 if (lease
-> n_uid
) {
2011 lease_id_hash_add(lease_uid_hash
, lease
->n_uid
->uid
,
2012 lease
->n_uid
->uid_len
, lease
->n_uid
,
2014 lease_dereference (&lease
-> n_uid
, MDL
);
2017 /* Otherwise, look for the lease in the list of leases
2018 attached to the hash table entry, and remove it if
2020 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
2021 if (scan
-> n_uid
== lease
) {
2022 lease_dereference (&scan
-> n_uid
, MDL
);
2023 if (lease
-> n_uid
) {
2024 lease_reference (&scan
-> n_uid
,
2025 lease
-> n_uid
, MDL
);
2026 lease_dereference (&lease
-> n_uid
,
2033 lease_dereference (&head
, MDL
);
2036 /* Add the specified lease to the hardware address hash. */
2039 hw_hash_add(struct lease
*lease
)
2041 struct lease
*head
= NULL
;
2042 struct lease
*cand
= NULL
;
2043 struct lease
*prev
= NULL
;
2044 struct lease
*next
= NULL
;
2046 /* If it's not in the hash, just add it. */
2047 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2048 lease
-> hardware_addr
.hlen
, MDL
))
2049 lease_id_hash_add(lease_hw_addr_hash
,
2050 lease
->hardware_addr
.hbuf
,
2051 lease
->hardware_addr
.hlen
, lease
, MDL
);
2053 /* Otherwise, insert it into the list in order of its
2054 * preference for "resuming allocation to the client."
2056 * Because we don't have control of the hash bucket index
2057 * directly, we have to remove and re-insert the client
2058 * id into the hash if we're inserting onto the head.
2060 lease_reference(&cand
, head
, MDL
);
2061 while (cand
!= NULL
) {
2062 if (client_lease_preferred(cand
, lease
))
2066 lease_dereference(&prev
, MDL
);
2067 lease_reference(&prev
, cand
, MDL
);
2069 if (cand
->n_hw
!= NULL
)
2070 lease_reference(&next
, cand
->n_hw
, MDL
);
2072 lease_dereference(&cand
, MDL
);
2075 lease_reference(&cand
, next
, MDL
);
2076 lease_dereference(&next
, MDL
);
2080 /* If we want to insert 'before cand', and prev is NULL,
2081 * then it was the head of the list. Assume that position.
2084 lease_reference(&lease
->n_hw
, head
, MDL
);
2085 lease_id_hash_delete(lease_hw_addr_hash
,
2086 lease
->hardware_addr
.hbuf
,
2087 lease
->hardware_addr
.hlen
, MDL
);
2088 lease_id_hash_add(lease_hw_addr_hash
,
2089 lease
->hardware_addr
.hbuf
,
2090 lease
->hardware_addr
.hlen
,
2092 } else /* (prev != NULL) */ {
2093 if(prev
->n_hw
!= NULL
) {
2094 lease_reference(&lease
->n_hw
, prev
->n_hw
,
2096 lease_dereference(&prev
->n_hw
, MDL
);
2098 lease_reference(&prev
->n_hw
, lease
, MDL
);
2100 lease_dereference(&prev
, MDL
);
2104 lease_dereference(&cand
, MDL
);
2105 lease_dereference(&head
, MDL
);
2109 /* Delete the specified lease from the hardware address hash. */
2111 void hw_hash_delete (lease
)
2112 struct lease
*lease
;
2114 struct lease
*head
= (struct lease
*)0;
2115 struct lease
*next
= (struct lease
*)0;
2117 /* If it's not in the hash, we have no work to do. */
2118 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2119 lease
-> hardware_addr
.hlen
, MDL
)) {
2121 lease_dereference (&lease
-> n_hw
, MDL
);
2125 /* If the lease we're freeing is at the head of the list,
2126 remove the hash table entry and add a new one with the
2127 next lease on the list (if there is one). */
2128 if (head
== lease
) {
2129 lease_id_hash_delete(lease_hw_addr_hash
,
2130 lease
->hardware_addr
.hbuf
,
2131 lease
->hardware_addr
.hlen
, MDL
);
2133 lease_id_hash_add(lease_hw_addr_hash
,
2134 lease
->n_hw
->hardware_addr
.hbuf
,
2135 lease
->n_hw
->hardware_addr
.hlen
,
2137 lease_dereference(&lease
->n_hw
, MDL
);
2140 /* Otherwise, look for the lease in the list of leases
2141 attached to the hash table entry, and remove it if
2143 while (head
-> n_hw
) {
2144 if (head
-> n_hw
== lease
) {
2145 lease_dereference (&head
-> n_hw
, MDL
);
2146 if (lease
-> n_hw
) {
2147 lease_reference (&head
-> n_hw
,
2148 lease
-> n_hw
, MDL
);
2149 lease_dereference (&lease
-> n_hw
,
2154 lease_reference (&next
, head
-> n_hw
, MDL
);
2155 lease_dereference (&head
, MDL
);
2156 lease_reference (&head
, next
, MDL
);
2157 lease_dereference (&next
, MDL
);
2161 lease_dereference (&head
, MDL
);
2164 /* Write all interesting leases to permanent storage. */
2169 struct shared_network
*s
;
2171 struct host_decl
*hp
;
2172 struct group_object
*gp
;
2173 struct hash_bucket
*hb
;
2175 struct collection
*colp
;
2178 struct lease
**lptr
[RESERVED_LEASES
+1];
2180 /* write all the dynamically-created class declarations. */
2181 if (collections
->classes
) {
2182 numclasseswritten
= 0;
2183 for (colp
= collections
; colp
; colp
= colp
->next
) {
2184 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
2185 write_named_billing_class(
2186 (unsigned char *)cp
->name
,
2191 /* XXXJAB this number doesn't include subclasses... */
2192 log_info ("Wrote %d class decls to leases file.",
2197 /* Write all the dynamically-created group declarations. */
2198 if (group_name_hash
) {
2200 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
2201 for (hb
= group_name_hash
-> buckets
[i
];
2202 hb
; hb
= hb
-> next
) {
2203 gp
= (struct group_object
*)hb
-> value
;
2204 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
2205 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
2206 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
2207 if (!write_group (gp
))
2213 log_info ("Wrote %d group decls to leases file.", num_written
);
2216 /* Write all the deleted host declarations. */
2217 if (host_name_hash
) {
2219 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2220 for (hb
= host_name_hash
-> buckets
[i
];
2221 hb
; hb
= hb
-> next
) {
2222 hp
= (struct host_decl
*)hb
-> value
;
2223 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
2224 (hp
-> flags
& HOST_DECL_DELETED
))) {
2225 if (!write_host (hp
))
2231 log_info ("Wrote %d deleted host decls to leases file.",
2235 /* Write all the new, dynamic host declarations. */
2236 if (host_name_hash
) {
2238 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2239 for (hb
= host_name_hash
-> buckets
[i
];
2240 hb
; hb
= hb
-> next
) {
2241 hp
= (struct host_decl
*)hb
-> value
;
2242 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
2243 if (!write_host (hp
))
2248 log_info ("Wrote %d new dynamic host decls to leases file.",
2252 #if defined (FAILOVER_PROTOCOL)
2253 /* Write all the failover states. */
2254 if (!dhcp_failover_write_all_states ())
2258 /* Write all the leases. */
2260 for (s
= shared_networks
; s
; s
= s
-> next
) {
2261 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2262 lptr
[FREE_LEASES
] = &p
-> free
;
2263 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2264 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2265 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2266 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2267 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2269 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2270 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2271 #if !defined (DEBUG_DUMP_ALL_LEASES)
2272 if (l
-> hardware_addr
.hlen
||
2274 (l
-> binding_state
!= FTS_FREE
))
2277 if (!write_lease (l
))
2285 log_info ("Wrote %d leases to leases file.", num_written
);
2287 if (!write_leases6()) {
2291 if (!commit_leases ())
2296 /* In addition to placing this lease upon a lease queue depending on its
2297 * state, it also keeps track of the number of FREE and BACKUP leases in
2298 * existence, and sets the sort_time on the lease.
2300 * Sort_time is used in pool_timer() to determine when the lease will
2301 * bubble to the top of the list and be supersede_lease()'d into its next
2302 * state (possibly, if all goes well). Example, ACTIVE leases move to
2303 * EXPIRED state when the 'ends' value is reached, so that is its sort
2304 * time. Most queues are sorted by 'ends', since it is generally best
2305 * practice to re-use the oldest lease, to reduce address collision
2308 int lease_enqueue (struct lease
*comp
)
2310 struct lease
**lq
, *prev
, *lp
;
2311 static struct lease
**last_lq
= NULL
;
2312 static struct lease
*last_insert_point
= NULL
;
2314 /* No queue to put it on? */
2318 /* Figure out which queue it's going to. */
2319 switch (comp
-> binding_state
) {
2321 if (comp
->flags
& RESERVED_LEASE
) {
2322 lq
= &comp
->pool
->reserved
;
2324 lq
= &comp
->pool
->free
;
2325 comp
->pool
->free_leases
++;
2327 comp
-> sort_time
= comp
-> ends
;
2331 lq
= &comp
-> pool
-> active
;
2332 comp
-> sort_time
= comp
-> ends
;
2338 lq
= &comp
-> pool
-> expired
;
2339 #if defined(FAILOVER_PROTOCOL)
2340 /* In partner_down, tsfp is the time at which the lease
2341 * may be reallocated (stos+mclt). We can do that with
2342 * lease_mine_to_reallocate() anywhere between tsfp and
2343 * ends. But we prefer to wait until ends before doing it
2344 * automatically (choose the greater of the two). Note
2345 * that 'ends' is usually a historic timestamp in the
2346 * case of expired leases, is really only in the future
2347 * on released leases, and if we know a lease to be released
2348 * the peer might still know it to be active...in which case
2349 * it's possible the peer has renewed this lease, so avoid
2352 if (comp
->pool
->failover_peer
&&
2353 comp
->pool
->failover_peer
->me
.state
== partner_down
)
2354 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
2355 comp
->tsfp
: comp
->ends
;
2358 comp
->sort_time
= comp
->ends
;
2363 lq
= &comp
-> pool
-> abandoned
;
2364 comp
-> sort_time
= comp
-> ends
;
2368 if (comp
->flags
& RESERVED_LEASE
) {
2369 lq
= &comp
->pool
->reserved
;
2371 lq
= &comp
->pool
->backup
;
2372 comp
->pool
->backup_leases
++;
2374 comp
-> sort_time
= comp
-> ends
;
2378 log_error ("Lease with bogus binding state: %d",
2379 comp
-> binding_state
);
2380 #if defined (BINDING_STATE_DEBUG)
2386 /* This only works during server startup: during runtime, the last
2387 * lease may be dequeued in between calls. If the queue is the same
2388 * as was used previously, and the lease structure isn't (this is not
2389 * a re-queue), use that as a starting point for the insertion-sort.
2391 if ((server_starting
& SS_QFOLLOW
) && (lq
== last_lq
) &&
2392 (comp
!= last_insert_point
) &&
2393 (last_insert_point
->sort_time
<= comp
->sort_time
)) {
2394 prev
= last_insert_point
;
2401 /* Insertion sort the lease onto the appropriate queue. */
2402 for (; lp
; lp
= lp
->next
) {
2403 if (lp
-> sort_time
>= comp
-> sort_time
)
2410 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
2411 lease_dereference (&prev
-> next
, MDL
);
2413 lease_reference (&prev
-> next
, comp
, MDL
);
2416 lease_reference (&comp
-> next
, *lq
, MDL
);
2417 lease_dereference (lq
, MDL
);
2419 lease_reference (lq
, comp
, MDL
);
2421 last_insert_point
= comp
;
2426 /* For a given lease, sort it onto the right list in its pool and put it
2427 in each appropriate hash, understanding that it's already by definition
2428 in lease_ip_addr_hash. */
2431 lease_instantiate(const void *key
, unsigned len
, void *object
)
2433 struct lease
*lease
= object
;
2434 struct class *class;
2435 /* XXX If the lease doesn't have a pool at this point, it's an
2436 XXX orphan, which we *should* keep around until it expires,
2437 XXX but which right now we just forget. */
2438 if (!lease
-> pool
) {
2439 lease_ip_hash_delete(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
2440 lease
->ip_addr
.len
, MDL
);
2441 return ISC_R_SUCCESS
;
2444 /* Put the lease on the right queue. Failure to queue is probably
2445 * due to a bogus binding state. In such a case, we claim success,
2446 * so that later leases in a hash_foreach are processed, but we
2447 * return early as we really don't want hw address hash entries or
2448 * other cruft to surround such a bogus entry.
2450 if (!lease_enqueue(lease
))
2451 return ISC_R_SUCCESS
;
2453 /* Record the lease in the uid hash if possible. */
2455 uid_hash_add (lease
);
2458 /* Record it in the hardware address hash if possible. */
2459 if (lease
-> hardware_addr
.hlen
) {
2460 hw_hash_add (lease
);
2463 /* If the lease has a billing class, set up the billing. */
2464 if (lease
-> billing_class
) {
2465 class = (struct class *)0;
2466 class_reference (&class, lease
-> billing_class
, MDL
);
2467 class_dereference (&lease
-> billing_class
, MDL
);
2468 /* If the lease is available for allocation, the billing
2469 is invalid, so we don't keep it. */
2470 if (lease
-> binding_state
== FTS_ACTIVE
||
2471 lease
-> binding_state
== FTS_EXPIRED
||
2472 lease
-> binding_state
== FTS_RELEASED
||
2473 lease
-> binding_state
== FTS_RESET
)
2474 bill_class (lease
, class);
2475 class_dereference (&class, MDL
);
2477 return ISC_R_SUCCESS
;
2480 /* Run expiry events on every pool. This is called on startup so that
2481 any expiry events that occurred after the server stopped and before it
2482 was restarted can be run. At the same time, if failover support is
2483 compiled in, we compute the balance of leases for the pool. */
2485 void expire_all_pools ()
2487 struct shared_network
*s
;
2491 struct lease
**lptr
[RESERVED_LEASES
+1];
2493 /* Indicate that we are in the startup phase */
2494 server_starting
= SS_NOSYNC
| SS_QFOLLOW
;
2496 /* First, go over the hash list and actually put all the leases
2497 on the appropriate lists. */
2498 lease_ip_hash_foreach(lease_ip_addr_hash
, lease_instantiate
);
2500 /* Loop through each pool in each shared network and call the
2501 * expiry routine on the pool. It is no longer safe to follow
2502 * the queue insertion point, as expiration of a lease can move
2503 * it between queues (and this may be the lease that function
2506 server_starting
&= ~SS_QFOLLOW
;
2507 for (s
= shared_networks
; s
; s
= s
-> next
) {
2508 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2511 p
-> lease_count
= 0;
2512 p
-> free_leases
= 0;
2513 p
-> backup_leases
= 0;
2515 lptr
[FREE_LEASES
] = &p
-> free
;
2516 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2517 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2518 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2519 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2520 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2522 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2523 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2525 if (l
-> ends
<= cur_time
) {
2526 if (l
->binding_state
== FTS_FREE
) {
2527 if (i
== FREE_LEASES
)
2529 else if (i
!= RESERVED_LEASES
)
2530 log_fatal("Impossible case "
2532 } else if (l
->binding_state
== FTS_BACKUP
) {
2533 if (i
== BACKUP_LEASES
)
2535 else if (i
!= RESERVED_LEASES
)
2536 log_fatal("Impossible case "
2540 #if defined (FAILOVER_PROTOCOL)
2541 if (p
-> failover_peer
&&
2542 l
-> tstp
> l
-> atsfp
&&
2543 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2544 l
-> desired_binding_state
= l
-> binding_state
;
2545 dhcp_failover_queue_update (l
, 1);
2553 /* turn off startup phase */
2554 server_starting
= 0;
2557 void dump_subnets ()
2560 struct shared_network
*s
;
2563 struct lease
**lptr
[RESERVED_LEASES
+1];
2566 log_info ("Subnets:");
2567 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2568 log_debug (" Subnet %s", piaddr (n
-> net
));
2569 log_debug (" netmask %s",
2570 piaddr (n
-> netmask
));
2572 log_info ("Shared networks:");
2573 for (s
= shared_networks
; s
; s
= s
-> next
) {
2574 log_info (" %s", s
-> name
);
2575 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2576 lptr
[FREE_LEASES
] = &p
-> free
;
2577 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2578 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2579 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2580 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2581 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2583 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2584 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2592 HASH_FUNCTIONS(lease_ip
, const unsigned char *, struct lease
, lease_ip_hash_t
,
2593 lease_reference
, lease_dereference
, do_ip4_hash
)
2594 HASH_FUNCTIONS(lease_id
, const unsigned char *, struct lease
, lease_id_hash_t
,
2595 lease_reference
, lease_dereference
, do_id_hash
)
2596 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2597 host_reference
, host_dereference
, do_string_hash
)
2598 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2599 class_reference
, class_dereference
, do_string_hash
)
2601 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2602 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2603 extern struct hash_table
*dns_zone_hash
;
2604 extern struct interface_info
**interface_vector
;
2605 extern int interface_count
;
2606 dhcp_control_object_t
*dhcp_control_object
;
2607 extern struct hash_table
*auth_key_hash
;
2608 struct hash_table
*universe_hash
;
2609 struct universe
**universes
;
2610 int universe_count
, universe_max
;
2615 #if defined (COMPACT_LEASES)
2616 extern struct lease
*lease_hunks
;
2619 void free_everything(void)
2621 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2622 struct shared_network
*nc
= (struct shared_network
*)0,
2623 *nn
= (struct shared_network
*)0;
2624 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2625 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2626 struct interface_info
*ic
= (struct interface_info
*)0,
2627 *in
= (struct interface_info
*)0;
2628 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2629 struct collection
*lp
;
2632 /* Get rid of all the hash tables. */
2633 if (host_hw_addr_hash
)
2634 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2635 host_hw_addr_hash
= 0;
2637 host_free_hash_table (&host_uid_hash
, MDL
);
2640 lease_id_free_hash_table (&lease_uid_hash
, MDL
);
2642 if (lease_ip_addr_hash
)
2643 lease_ip_free_hash_table (&lease_ip_addr_hash
, MDL
);
2644 lease_ip_addr_hash
= 0;
2645 if (lease_hw_addr_hash
)
2646 lease_id_free_hash_table (&lease_hw_addr_hash
, MDL
);
2647 lease_hw_addr_hash
= 0;
2649 host_free_hash_table (&host_name_hash
, MDL
);
2652 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2655 while (host_id_info
!= NULL
) {
2656 host_id_info_t
*tmp
;
2657 option_dereference(&host_id_info
->option
, MDL
);
2658 host_free_hash_table(&host_id_info
->values_hash
, MDL
);
2659 tmp
= host_id_info
->next
;
2660 dfree(host_id_info
, MDL
);
2665 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2669 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2672 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2673 if (lp
-> classes
) {
2674 class_reference (&cn
, lp
-> classes
, MDL
);
2677 class_reference (&cc
, cn
, MDL
);
2678 class_dereference (&cn
, MDL
);
2681 class_reference (&cn
, cc
-> nic
, MDL
);
2682 class_dereference (&cc
-> nic
, MDL
);
2684 group_dereference (&cc
-> group
, MDL
);
2686 class_free_hash_table (&cc
-> hash
, MDL
);
2687 cc
-> hash
= (struct hash_table
*)0;
2689 class_dereference (&cc
, MDL
);
2691 class_dereference (&lp
-> classes
, MDL
);
2695 if (interface_vector
) {
2696 for (i
= 0; i
< interface_count
; i
++) {
2697 if (interface_vector
[i
])
2698 interface_dereference (&interface_vector
[i
], MDL
);
2700 dfree (interface_vector
, MDL
);
2701 interface_vector
= 0;
2705 interface_reference (&in
, interfaces
, MDL
);
2708 interface_reference (&ic
, in
, MDL
);
2709 interface_dereference (&in
, MDL
);
2712 interface_reference (&in
, ic
-> next
, MDL
);
2713 interface_dereference (&ic
-> next
, MDL
);
2715 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2716 if (ic
-> shared_network
) {
2717 if (ic
-> shared_network
-> interface
)
2718 interface_dereference
2719 (&ic
-> shared_network
-> interface
, MDL
);
2720 shared_network_dereference (&ic
-> shared_network
, MDL
);
2722 interface_dereference (&ic
, MDL
);
2724 interface_dereference (&interfaces
, MDL
);
2727 /* Subnets are complicated because of the extra links. */
2729 subnet_reference (&sn
, subnets
, MDL
);
2732 subnet_reference (&sc
, sn
, MDL
);
2733 subnet_dereference (&sn
, MDL
);
2735 if (sc
-> next_subnet
) {
2736 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2737 subnet_dereference (&sc
-> next_subnet
, MDL
);
2739 if (sc
-> next_sibling
)
2740 subnet_dereference (&sc
-> next_sibling
, MDL
);
2741 if (sc
-> shared_network
)
2742 shared_network_dereference (&sc
-> shared_network
, MDL
);
2743 group_dereference (&sc
-> group
, MDL
);
2744 if (sc
-> interface
)
2745 interface_dereference (&sc
-> interface
, MDL
);
2746 subnet_dereference (&sc
, MDL
);
2748 subnet_dereference (&subnets
, MDL
);
2751 /* So are shared networks. */
2752 /* XXX: this doesn't work presently, but i'm ok just filtering
2753 * it out of the noise (you get a bigger spike on the real leaks).
2754 * It would be good to fix this, but it is not a "real bug," so not
2755 * today. This hack is incomplete, it doesn't trim out sub-values.
2757 if (shared_networks
) {
2758 shared_network_dereference (&shared_networks
, MDL
);
2759 /* This is the old method (tries to free memory twice, broken) */
2761 shared_network_reference (&nn
, shared_networks
, MDL
);
2764 shared_network_reference (&nc
, nn
, MDL
);
2765 shared_network_dereference (&nn
, MDL
);
2768 shared_network_reference (&nn
, nc
-> next
, MDL
);
2769 shared_network_dereference (&nc
-> next
, MDL
);
2774 pool_reference (&pn
, nc
-> pools
, MDL
);
2776 struct lease
**lptr
[RESERVED_LEASES
+1];
2779 pool_reference (&pc
, pn
, MDL
);
2780 pool_dereference (&pn
, MDL
);
2783 pool_reference (&pn
, pc
-> next
, MDL
);
2784 pool_dereference (&pc
-> next
, MDL
);
2787 lptr
[FREE_LEASES
] = &pc
-> free
;
2788 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2789 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2790 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2791 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2792 lptr
[RESERVED_LEASES
] = &pc
->reserved
;
2794 /* As (sigh) are leases. */
2795 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2797 lease_reference (&ln
, *lptr
[i
], MDL
);
2800 lease_reference (&lc
, ln
, MDL
);
2801 lease_dereference (&ln
, MDL
);
2804 lease_reference (&ln
, lc
-> next
, MDL
);
2805 lease_dereference (&lc
-> next
, MDL
);
2807 if (lc
-> billing_class
)
2808 class_dereference (&lc
-> billing_class
,
2811 free_lease_state (lc
-> state
, MDL
);
2812 lc
-> state
= (struct lease_state
*)0;
2814 lease_dereference (&lc
-> n_hw
, MDL
);
2816 lease_dereference (&lc
-> n_uid
, MDL
);
2817 lease_dereference (&lc
, MDL
);
2819 lease_dereference (lptr
[i
], MDL
);
2823 group_dereference (&pc
-> group
, MDL
);
2824 if (pc
-> shared_network
)
2825 shared_network_dereference (&pc
-> shared_network
,
2827 pool_dereference (&pc
, MDL
);
2829 pool_dereference (&nc
-> pools
, MDL
);
2831 /* Because of a circular reference, we need to nuke this
2833 group_dereference (&nc
-> group
, MDL
);
2834 shared_network_dereference (&nc
, MDL
);
2836 shared_network_dereference (&shared_networks
, MDL
);
2839 cancel_all_timeouts ();
2840 relinquish_timeouts ();
2841 relinquish_ackqueue();
2843 group_dereference (&root_group
, MDL
);
2844 executable_statement_dereference (&default_classification_rules
, MDL
);
2846 shutdown_state
= shutdown_drop_omapi_connections
;
2847 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2848 shutdown_state
= shutdown_listeners
;
2849 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2850 shutdown_state
= shutdown_dhcp
;
2851 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2853 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2855 universe_free_hash_table (&universe_hash
, MDL
);
2856 for (i
= 0; i
< universe_count
; i
++) {
2863 if (universes
[i
]) {
2864 if (universes
[i
]->name_hash
)
2865 option_name_free_hash_table(
2866 &universes
[i
]->name_hash
,
2868 if (universes
[i
]->code_hash
)
2869 option_code_free_hash_table(
2870 &universes
[i
]->code_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 #if defined(COMPACT_LEASES)
2891 relinquish_lease_hunks ();
2893 relinquish_hash_bucket_hunks ();
2894 omapi_type_relinquish ();
2896 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */