3 Server-specific in-memory database support. */
6 * Copyright (c) 2004-2007 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 struct lease
*address_range
;
718 unsigned min
, max
, i
;
719 char lowbuf
[16], highbuf
[16], netbuf
[16];
720 struct shared_network
*share
= subnet
-> shared_network
;
721 struct lease
*lt
= (struct lease
*)0;
722 #if !defined(COMPACT_LEASES)
726 /* All subnets should have attached shared network structures. */
728 strcpy (netbuf
, piaddr (subnet
-> net
));
729 log_fatal ("No shared network for network %s (%s)",
730 netbuf
, piaddr (subnet
-> netmask
));
733 /* Initialize the hash table if it hasn't been done yet. */
734 if (!lease_uid_hash
) {
735 if (!lease_id_new_hash(&lease_uid_hash
, LEASE_HASH_SIZE
, MDL
))
736 log_fatal ("Can't allocate lease/uid hash");
738 if (!lease_ip_addr_hash
) {
739 if (!lease_ip_new_hash(&lease_ip_addr_hash
, LEASE_HASH_SIZE
,
741 log_fatal ("Can't allocate lease/ip hash");
743 if (!lease_hw_addr_hash
) {
744 if (!lease_id_new_hash(&lease_hw_addr_hash
, LEASE_HASH_SIZE
,
746 log_fatal ("Can't allocate lease/hw hash");
749 /* Make sure that high and low addresses are in this subnet. */
750 if (!addr_eq(subnet
->net
, subnet_number(low
, subnet
->netmask
))) {
751 strcpy(lowbuf
, piaddr(low
));
752 strcpy(netbuf
, piaddr(subnet
->net
));
753 log_fatal("bad range, address %s not in subnet %s netmask %s",
754 lowbuf
, netbuf
, piaddr(subnet
->netmask
));
757 if (!addr_eq(subnet
->net
, subnet_number(high
, subnet
->netmask
))) {
758 strcpy(highbuf
, piaddr(high
));
759 strcpy(netbuf
, piaddr(subnet
->net
));
760 log_fatal("bad range, address %s not in subnet %s netmask %s",
761 highbuf
, netbuf
, piaddr(subnet
->netmask
));
764 /* Get the high and low host addresses... */
765 max
= host_addr (high
, subnet
-> netmask
);
766 min
= host_addr (low
, subnet
-> netmask
);
768 /* Allow range to be specified high-to-low as well as low-to-high. */
771 min
= host_addr (high
, subnet
-> netmask
);
774 /* Get a lease structure for each address in the range. */
775 #if defined (COMPACT_LEASES)
776 address_range
= new_leases (max
- min
+ 1, MDL
);
777 if (!address_range
) {
778 strcpy (lowbuf
, piaddr (low
));
779 strcpy (highbuf
, piaddr (high
));
780 log_fatal ("No memory for address range %s-%s.",
785 /* Fill out the lease structures with some minimal information. */
786 for (i
= 0; i
< max
- min
+ 1; i
++) {
787 struct lease
*lp
= (struct lease
*)0;
788 #if defined (COMPACT_LEASES)
789 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
791 0, sizeof (struct lease
), MDL
);
792 lease_reference (&lp
, &address_range
[i
], MDL
);
794 status
= lease_allocate (&lp
, MDL
);
795 if (status
!= ISC_R_SUCCESS
)
796 log_fatal ("No memory for lease %s: %s",
797 piaddr (ip_addr (subnet
-> net
,
800 isc_result_totext (status
));
802 lp
-> ip_addr
= ip_addr (subnet
-> net
,
803 subnet
-> netmask
, i
+ min
);
804 lp
-> starts
= MIN_TIME
;
805 lp
-> ends
= MIN_TIME
;
806 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
807 pool_reference (&lp
-> pool
, pool
, MDL
);
808 lp
-> binding_state
= FTS_FREE
;
809 lp
-> next_binding_state
= FTS_FREE
;
812 /* Remember the lease in the IP address hash. */
813 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
816 "lease %s is declared twice!",
817 piaddr (lp
-> ip_addr
));
819 pool_reference (<
-> pool
, pool
, MDL
);
820 lease_dereference (<
, MDL
);
822 lease_ip_hash_add(lease_ip_addr_hash
,
823 lp
->ip_addr
.iabuf
, lp
->ip_addr
.len
,
825 /* Put the lease on the chain for the caller. */
828 lease_reference (&lp
-> next
, *lpchain
, MDL
);
829 lease_dereference (lpchain
, MDL
);
831 lease_reference (lpchain
, lp
, MDL
);
833 lease_dereference (&lp
, MDL
);
837 int find_subnet (struct subnet
**sp
,
838 struct iaddr addr
, const char *file
, int line
)
842 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
843 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
844 if (subnet_reference (sp
, rv
,
845 file
, line
) != ISC_R_SUCCESS
)
853 int find_grouped_subnet (struct subnet
**sp
,
854 struct shared_network
*share
, struct iaddr addr
,
855 const char *file
, int line
)
859 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
860 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
861 if (subnet_reference (sp
, rv
,
862 file
, line
) != ISC_R_SUCCESS
)
870 /* XXX: could speed up if everyone had a prefix length */
872 subnet_inner_than(const struct subnet
*subnet
,
873 const struct subnet
*scan
,
875 if (addr_eq(subnet_number(subnet
->net
, scan
->netmask
), scan
->net
) ||
876 addr_eq(subnet_number(scan
->net
, subnet
->netmask
), subnet
->net
)) {
877 char n1buf
[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
879 for (i
= 0; i
< 128; i
++)
880 if (subnet
->netmask
.iabuf
[3 - (i
>> 3)]
883 for (j
= 0; j
< 128; j
++)
884 if (scan
->netmask
.iabuf
[3 - (j
>> 3)] &
888 strcpy(n1buf
, piaddr(subnet
->net
));
889 log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
891 piaddr(scan
->net
), 32 - j
);
899 /* Enter a new subnet into the subnet list. */
900 void enter_subnet (subnet
)
901 struct subnet
*subnet
;
903 struct subnet
*scan
= (struct subnet
*)0;
904 struct subnet
*next
= (struct subnet
*)0;
905 struct subnet
*prev
= (struct subnet
*)0;
907 /* Check for duplicates... */
909 subnet_reference (&next
, subnets
, MDL
);
911 subnet_reference (&scan
, next
, MDL
);
912 subnet_dereference (&next
, MDL
);
914 /* When we find a conflict, make sure that the
915 subnet with the narrowest subnet mask comes
917 if (subnet_inner_than (subnet
, scan
, 1)) {
919 if (prev
-> next_subnet
)
920 subnet_dereference (&prev
-> next_subnet
, MDL
);
921 subnet_reference (&prev
-> next_subnet
, subnet
, MDL
);
922 subnet_dereference (&prev
, MDL
);
924 subnet_dereference (&subnets
, MDL
);
925 subnet_reference (&subnets
, subnet
, MDL
);
927 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
928 subnet_dereference (&scan
, MDL
);
931 subnet_reference (&prev
, scan
, MDL
);
932 subnet_dereference (&scan
, MDL
);
935 subnet_dereference (&prev
, MDL
);
937 /* XXX use the BSD radix tree code instead of a linked list. */
939 subnet_reference (&subnet
-> next_subnet
, subnets
, MDL
);
940 subnet_dereference (&subnets
, MDL
);
942 subnet_reference (&subnets
, subnet
, MDL
);
945 /* Enter a new shared network into the shared network list. */
947 void enter_shared_network (share
)
948 struct shared_network
*share
;
950 if (shared_networks
) {
951 shared_network_reference (&share
-> next
,
952 shared_networks
, MDL
);
953 shared_network_dereference (&shared_networks
, MDL
);
955 shared_network_reference (&shared_networks
, share
, MDL
);
958 void new_shared_network_interface (cfile
, share
, name
)
960 struct shared_network
*share
;
963 struct interface_info
*ip
;
966 if (share
-> interface
) {
968 "A subnet or shared network can't be connected %s",
969 "to two interfaces.");
973 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
974 if (!strcmp (ip
-> name
, name
))
977 status
= interface_allocate (&ip
, MDL
);
978 if (status
!= ISC_R_SUCCESS
)
979 log_fatal ("new_shared_network_interface %s: %s",
980 name
, isc_result_totext (status
));
981 if (strlen (name
) > sizeof ip
-> name
) {
982 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
983 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
985 strcpy (ip
-> name
, name
);
987 interface_reference (&ip
-> next
, interfaces
, MDL
);
988 interface_dereference (&interfaces
, MDL
);
990 interface_reference (&interfaces
, ip
, MDL
);
991 ip
-> flags
= INTERFACE_REQUESTED
;
992 /* XXX this is a reference loop. */
993 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
994 interface_reference (&share
-> interface
, ip
, MDL
);
998 /* Enter a lease into the system. This is called by the parser each
999 time it reads in a new lease. If the subnet for that lease has
1000 already been read in (usually the case), just update that lease;
1001 otherwise, allocate temporary storage for the lease and keep it around
1002 until we're done reading in the config file. */
1004 void enter_lease (lease
)
1005 struct lease
*lease
;
1007 struct lease
*comp
= (struct lease
*)0;
1009 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
1010 if (!comp
-> pool
) {
1011 log_error ("undeclared lease found in database: %s",
1012 piaddr (lease
-> ip_addr
));
1014 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
1017 subnet_reference (&lease
-> subnet
,
1018 comp
-> subnet
, MDL
);
1019 lease_ip_hash_delete(lease_ip_addr_hash
,
1020 lease
->ip_addr
.iabuf
, lease
->ip_addr
.len
,
1022 lease_dereference (&comp
, MDL
);
1025 /* The only way a lease can get here without a subnet is if it's in
1026 the lease file, but not in the dhcpd.conf file. In this case, we
1027 *should* keep it around until it's expired, but never reallocate it
1028 or renew it. Currently, to maintain consistency, we are not doing
1030 XXX fix this so that the lease is kept around until it expires.
1031 XXX this will be important in IPv6 with addresses that become
1032 XXX non-renewable as a result of a renumbering event. */
1034 if (!lease
-> subnet
) {
1035 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
1038 lease_ip_hash_add(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
1039 lease
->ip_addr
.len
, lease
, MDL
);
1042 /* Replace the data in an existing lease with the data in a new lease;
1043 adjust hash tables to suit, and insertion sort the lease into the
1044 list of leases by expiry time so that we can always find the oldest
1047 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
1048 struct lease
*comp
, *lease
;
1053 struct lease
*lp
, **lq
, *prev
;
1054 #if defined (FAILOVER_PROTOCOL)
1055 int do_pool_check
= 0;
1057 /* We must commit leases before sending updates regarding them
1058 to failover peers. It is, therefore, an error to set pimmediate
1060 if (pimmediate
&& !commit
)
1064 /* If there is no sample lease, just do the move. */
1068 /* Static leases are not currently kept in the database... */
1069 if (lease
-> flags
& STATIC_LEASE
)
1072 /* If the existing lease hasn't expired and has a different
1073 unique identifier or, if it doesn't have a unique
1074 identifier, a different hardware address, then the two
1075 leases are in conflict. If the existing lease has a uid
1076 and the new one doesn't, but they both have the same
1077 hardware address, and dynamic bootp is allowed on this
1078 lease, then we allow that, in case a dynamic BOOTP lease is
1079 requested *after* a DHCP lease has been assigned. */
1081 if (lease
-> binding_state
!= FTS_ABANDONED
&&
1082 lease
-> next_binding_state
!= FTS_ABANDONED
&&
1083 comp
-> binding_state
== FTS_ACTIVE
&&
1084 (((comp
-> uid
&& lease
-> uid
) &&
1085 (comp
-> uid_len
!= lease
-> uid_len
||
1086 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
1088 ((comp
-> hardware_addr
.hlen
!=
1089 lease
-> hardware_addr
.hlen
) ||
1090 memcmp (comp
-> hardware_addr
.hbuf
,
1091 lease
-> hardware_addr
.hbuf
,
1092 comp
-> hardware_addr
.hlen
))))) {
1093 log_error ("Lease conflict at %s",
1094 piaddr (comp
-> ip_addr
));
1097 /* If there's a Unique ID, dissociate it from the hash
1098 table and free it if necessary. */
1100 uid_hash_delete(comp
);
1101 if (comp
->uid
!= comp
->uid_buf
) {
1102 dfree(comp
->uid
, MDL
);
1106 comp
-> uid
= (unsigned char *)0;
1109 /* If there's a hardware address, remove the lease from its
1110 * old position in the hash bucket's ordered list.
1112 if (comp
->hardware_addr
.hlen
)
1113 hw_hash_delete(comp
);
1115 /* If the lease has been billed to a class, remove the billing. */
1116 if (comp
-> billing_class
!= lease
-> billing_class
) {
1117 if (comp
-> billing_class
)
1118 unbill_class (comp
, comp
-> billing_class
);
1119 if (lease
-> billing_class
)
1120 bill_class (comp
, lease
-> billing_class
);
1123 /* Copy the data files, but not the linkages. */
1124 comp
-> starts
= lease
-> starts
;
1126 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
1127 memcpy (comp
-> uid_buf
,
1128 lease
-> uid
, lease
-> uid_len
);
1129 comp
-> uid
= &comp
-> uid_buf
[0];
1130 comp
-> uid_max
= sizeof comp
-> uid_buf
;
1131 comp
-> uid_len
= lease
-> uid_len
;
1132 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
1133 comp
-> uid
= lease
-> uid
;
1134 comp
-> uid_max
= lease
-> uid_max
;
1135 lease
-> uid
= (unsigned char *)0;
1136 lease
-> uid_max
= 0;
1137 comp
-> uid_len
= lease
-> uid_len
;
1138 lease
-> uid_len
= 0;
1140 log_fatal ("corrupt lease uid."); /* XXX */
1143 comp
-> uid
= (unsigned char *)0;
1144 comp
-> uid_len
= comp
-> uid_max
= 0;
1147 host_dereference (&comp
-> host
, MDL
);
1148 host_reference (&comp
-> host
, lease
-> host
, MDL
);
1149 comp
-> hardware_addr
= lease
-> hardware_addr
;
1150 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
1151 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
1153 binding_scope_dereference (&comp
-> scope
, MDL
);
1154 if (lease
-> scope
) {
1155 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
1156 binding_scope_dereference (&lease
-> scope
, MDL
);
1159 if (comp
-> agent_options
)
1160 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
1161 if (lease
-> agent_options
) {
1162 /* Only retain the agent options if the lease is still
1163 affirmatively associated with a client. */
1164 if (lease
-> next_binding_state
== FTS_ACTIVE
||
1165 lease
-> next_binding_state
== FTS_EXPIRED
)
1166 option_chain_head_reference (&comp
-> agent_options
,
1167 lease
-> agent_options
,
1169 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
1172 /* Record the hostname information in the lease. */
1173 if (comp
-> client_hostname
)
1174 dfree (comp
-> client_hostname
, MDL
);
1175 comp
-> client_hostname
= lease
-> client_hostname
;
1176 lease
-> client_hostname
= (char *)0;
1178 if (lease
-> on_expiry
) {
1179 if (comp
-> on_expiry
)
1180 executable_statement_dereference (&comp
-> on_expiry
,
1182 executable_statement_reference (&comp
-> on_expiry
,
1186 if (lease
-> on_commit
) {
1187 if (comp
-> on_commit
)
1188 executable_statement_dereference (&comp
-> on_commit
,
1190 executable_statement_reference (&comp
-> on_commit
,
1194 if (lease
-> on_release
) {
1195 if (comp
-> on_release
)
1196 executable_statement_dereference (&comp
-> on_release
,
1198 executable_statement_reference (&comp
-> on_release
,
1199 lease
-> on_release
, MDL
);
1202 /* Record the lease in the uid hash if necessary. */
1206 /* Record it in the hardware address hash if necessary. */
1207 if (comp
->hardware_addr
.hlen
)
1210 comp
->cltt
= lease
->cltt
;
1211 #if defined (FAILOVER_PROTOCOL)
1212 comp
->tstp
= lease
->tstp
;
1213 comp
->tsfp
= lease
->tsfp
;
1214 comp
->atsfp
= lease
->atsfp
;
1215 #endif /* FAILOVER_PROTOCOL */
1216 comp
->ends
= lease
->ends
;
1217 comp
->next_binding_state
= lease
->next_binding_state
;
1220 #if defined (FAILOVER_PROTOCOL)
1221 /* Atsfp should be cleared upon any state change that implies
1222 * propagation whether supersede_lease was given a copy lease
1223 * structure or not (often from the pool_timer()).
1227 #endif /* FAILOVER_PROTOCOL */
1229 if (!comp
-> pool
) {
1230 log_error ("Supersede_lease: lease %s with no pool.",
1231 piaddr (comp
-> ip_addr
));
1235 /* Figure out which queue it's on. */
1236 switch (comp
-> binding_state
) {
1238 lq
= &comp
-> pool
-> free
;
1239 if (!(comp
->flags
& RESERVED_LEASE
))
1240 comp
->pool
->free_leases
--;
1242 #if defined(FAILOVER_PROTOCOL)
1248 lq
= &comp
-> pool
-> active
;
1254 lq
= &comp
-> pool
-> expired
;
1258 lq
= &comp
-> pool
-> abandoned
;
1262 lq
= &comp
-> pool
-> backup
;
1263 if (!(comp
->flags
& RESERVED_LEASE
))
1264 comp
->pool
->backup_leases
--;
1266 #if defined(FAILOVER_PROTOCOL)
1272 log_error ("Lease with bogus binding state: %d",
1273 comp
-> binding_state
);
1274 #if defined (BINDING_STATE_DEBUG)
1280 /* Remove the lease from its current place in its current
1282 /* XXX this is horrid. */
1283 prev
= (struct lease
*)0;
1284 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1291 log_fatal("Lease with binding state %s not on its queue.",
1292 (comp
->binding_state
< 1 ||
1293 comp
->binding_state
> FTS_LAST
)
1295 : binding_state_names
[comp
->binding_state
- 1]);
1299 lease_dereference (&prev
-> next
, MDL
);
1301 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1302 lease_dereference (&comp
-> next
, MDL
);
1305 lease_dereference (lq
, MDL
);
1307 lease_reference (lq
, comp
-> next
, MDL
);
1308 lease_dereference (&comp
-> next
, MDL
);
1312 /* Make the state transition. */
1313 if (commit
|| !pimmediate
)
1314 make_binding_state_transition (comp
);
1316 /* Put the lease back on the appropriate queue. If the lease
1317 is corrupt (as detected by lease_enqueue), don't go any farther. */
1318 if (!lease_enqueue (comp
))
1321 /* If this is the next lease that will timeout on the pool,
1322 zap the old timeout and set the timeout on this pool to the
1323 time that the lease's next event will happen.
1325 We do not actually set the timeout unless commit is true -
1326 we don't want to thrash the timer queue when reading the
1327 lease database. Instead, the database code calls the
1328 expiry event on each pool after reading in the lease file,
1329 and the expiry code sets the timer if there's anything left
1330 to expire after it's run any outstanding expiry events on
1332 if ((commit
|| !pimmediate
) &&
1333 comp
-> sort_time
!= MIN_TIME
&&
1334 comp
-> sort_time
> cur_time
&&
1335 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1336 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1337 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1338 add_timeout (comp
-> pool
-> next_event_time
,
1339 pool_timer
, comp
-> pool
,
1340 (tvref_t
)pool_reference
,
1341 (tvunref_t
)pool_dereference
);
1345 if (!write_lease (comp
))
1347 if ((server_starting
& SS_NOSYNC
) == 0) {
1348 if (!commit_leases ())
1353 #if defined (FAILOVER_PROTOCOL)
1355 comp
-> desired_binding_state
= comp
-> binding_state
;
1356 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1359 if (do_pool_check
&& comp
->pool
->failover_peer
)
1360 dhcp_failover_pool_check(comp
->pool
);
1363 /* If the current binding state has already expired, do an
1364 expiry event right now. */
1365 /* XXX At some point we should optimize this so that we don't
1366 XXX write the lease twice, but this is a safe way to fix the
1367 XXX problem for 3.0 (I hope!). */
1368 if ((commit
|| !pimmediate
) &&
1369 comp
-> sort_time
< cur_time
&&
1370 comp
-> next_binding_state
!= comp
-> binding_state
)
1371 pool_timer (comp
-> pool
);
1376 void make_binding_state_transition (struct lease
*lease
)
1378 #if defined (FAILOVER_PROTOCOL)
1379 dhcp_failover_state_t
*peer
;
1381 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1382 peer
= lease
-> pool
-> failover_peer
;
1384 peer
= (dhcp_failover_state_t
*)0;
1387 /* If the lease was active and is now no longer active, but isn't
1388 released, then it just expired, so do the expiry event. */
1389 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1391 #if defined (FAILOVER_PROTOCOL)
1393 (lease
-> binding_state
== FTS_EXPIRED
||
1394 (peer
-> i_am
== secondary
&&
1395 lease
-> binding_state
== FTS_ACTIVE
)) &&
1396 (lease
-> next_binding_state
== FTS_FREE
||
1397 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1400 lease
-> binding_state
== FTS_ACTIVE
&&
1401 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1402 #if defined (NSUPDATE)
1403 ddns_removals(lease
, NULL
);
1405 if (lease
-> on_expiry
) {
1406 execute_statements ((struct binding_value
**)0,
1407 (struct packet
*)0, lease
,
1408 (struct client_state
*)0,
1409 (struct option_state
*)0,
1410 (struct option_state
*)0, /* XXX */
1412 lease
-> on_expiry
);
1413 if (lease
-> on_expiry
)
1414 executable_statement_dereference
1415 (&lease
-> on_expiry
, MDL
);
1418 /* No sense releasing a lease after it's expired. */
1419 if (lease
-> on_release
)
1420 executable_statement_dereference (&lease
-> on_release
,
1422 /* Get rid of client-specific bindings that are only
1423 correct when the lease is active. */
1424 if (lease
-> billing_class
)
1425 unbill_class (lease
, lease
-> billing_class
);
1426 if (lease
-> agent_options
)
1427 option_chain_head_dereference (&lease
-> agent_options
,
1429 if (lease
-> client_hostname
) {
1430 dfree (lease
-> client_hostname
, MDL
);
1431 lease
-> client_hostname
= (char *)0;
1434 host_dereference (&lease
-> host
, MDL
);
1436 /* Send the expiry time to the peer. */
1437 lease
-> tstp
= lease
-> ends
;
1440 /* If the lease was active and is now released, do the release
1442 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1444 #if defined (FAILOVER_PROTOCOL)
1446 lease
-> binding_state
== FTS_RELEASED
&&
1447 (lease
-> next_binding_state
== FTS_FREE
||
1448 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1451 lease
-> binding_state
== FTS_ACTIVE
&&
1452 lease
-> next_binding_state
== FTS_RELEASED
))) {
1453 #if defined (NSUPDATE)
1454 ddns_removals(lease
, NULL
);
1456 if (lease
-> on_release
) {
1457 execute_statements ((struct binding_value
**)0,
1458 (struct packet
*)0, lease
,
1459 (struct client_state
*)0,
1460 (struct option_state
*)0,
1461 (struct option_state
*)0, /* XXX */
1463 lease
-> on_release
);
1464 executable_statement_dereference (&lease
-> on_release
,
1468 /* A released lease can't expire. */
1469 if (lease
-> on_expiry
)
1470 executable_statement_dereference (&lease
-> on_expiry
,
1473 /* Get rid of client-specific bindings that are only
1474 correct when the lease is active. */
1475 if (lease
-> billing_class
)
1476 unbill_class (lease
, lease
-> billing_class
);
1477 if (lease
-> agent_options
)
1478 option_chain_head_dereference (&lease
-> agent_options
,
1480 if (lease
-> client_hostname
) {
1481 dfree (lease
-> client_hostname
, MDL
);
1482 lease
-> client_hostname
= (char *)0;
1485 host_dereference (&lease
-> host
, MDL
);
1487 /* Send the release time (should be == cur_time) to the
1489 lease
-> tstp
= lease
-> ends
;
1492 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1493 log_debug ("lease %s moves from %s to %s",
1494 piaddr (lease
-> ip_addr
),
1495 binding_state_print (lease
-> binding_state
),
1496 binding_state_print (lease
-> next_binding_state
));
1499 lease
-> binding_state
= lease
-> next_binding_state
;
1500 switch (lease
-> binding_state
) {
1502 #if defined (FAILOVER_PROTOCOL)
1503 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1504 lease
-> next_binding_state
= FTS_EXPIRED
;
1507 lease
-> next_binding_state
= FTS_FREE
;
1514 lease
-> next_binding_state
= FTS_FREE
;
1515 /* If we are not in partner_down, leases don't go from
1516 EXPIRED to FREE on a timeout - only on an update.
1517 If we're in partner_down, they expire at mclt past
1518 the time we entered partner_down. */
1519 if (lease
-> pool
-> failover_peer
&&
1520 lease
-> pool
-> failover_peer
-> me
.state
== partner_down
)
1522 (lease
-> pool
-> failover_peer
-> me
.stos
+
1523 lease
-> pool
-> failover_peer
-> mclt
);
1528 lease
-> next_binding_state
= lease
-> binding_state
;
1531 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1532 log_debug ("lease %s: next binding state %s",
1533 piaddr (lease
-> ip_addr
),
1534 binding_state_print (lease
-> next_binding_state
));
1539 /* Copy the contents of one lease into another, correctly maintaining
1540 reference counts. */
1541 int lease_copy (struct lease
**lp
,
1542 struct lease
*lease
, const char *file
, int line
)
1544 struct lease
*lt
= (struct lease
*)0;
1545 isc_result_t status
;
1547 status
= lease_allocate (<
, MDL
);
1548 if (status
!= ISC_R_SUCCESS
)
1551 lt
-> ip_addr
= lease
-> ip_addr
;
1552 lt
-> starts
= lease
-> starts
;
1553 lt
-> ends
= lease
-> ends
;
1554 lt
-> uid_len
= lease
-> uid_len
;
1555 lt
-> uid_max
= lease
-> uid_max
;
1556 if (lease
-> uid
== lease
-> uid_buf
) {
1557 lt
-> uid
= lt
-> uid_buf
;
1558 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1559 } else if (!lease
-> uid_max
) {
1560 lt
-> uid
= (unsigned char *)0;
1562 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1564 lease_dereference (<
, MDL
);
1567 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1569 if (lease
-> client_hostname
) {
1570 lt
-> client_hostname
=
1571 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1572 if (!lt
-> client_hostname
) {
1573 lease_dereference (<
, MDL
);
1576 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1579 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1580 if (lease
-> agent_options
)
1581 option_chain_head_reference (<
-> agent_options
,
1582 lease
-> agent_options
, MDL
);
1583 host_reference (<
-> host
, lease
-> host
, file
, line
);
1584 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1585 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1586 class_reference (<
-> billing_class
,
1587 lease
-> billing_class
, file
, line
);
1588 lt
-> hardware_addr
= lease
-> hardware_addr
;
1589 if (lease
-> on_expiry
)
1590 executable_statement_reference (<
-> on_expiry
,
1593 if (lease
-> on_commit
)
1594 executable_statement_reference (<
-> on_commit
,
1597 if (lease
-> on_release
)
1598 executable_statement_reference (<
-> on_release
,
1599 lease
-> on_release
,
1601 lt
->flags
= lease
->flags
;
1602 lt
->tstp
= lease
->tstp
;
1603 lt
->tsfp
= lease
->tsfp
;
1604 lt
->atsfp
= lease
->atsfp
;
1605 lt
->cltt
= lease
-> cltt
;
1606 lt
->binding_state
= lease
->binding_state
;
1607 lt
->next_binding_state
= lease
->next_binding_state
;
1608 status
= lease_reference(lp
, lt
, file
, line
);
1609 lease_dereference(<
, MDL
);
1610 return status
== ISC_R_SUCCESS
;
1613 /* Release the specified lease and re-hash it as appropriate. */
1614 void release_lease (lease
, packet
)
1615 struct lease
*lease
;
1616 struct packet
*packet
;
1618 /* If there are statements to execute when the lease is
1619 released, execute them. */
1620 #if defined (NSUPDATE)
1621 ddns_removals(lease
, NULL
);
1623 if (lease
-> on_release
) {
1624 execute_statements ((struct binding_value
**)0,
1625 packet
, lease
, (struct client_state
*)0,
1627 (struct option_state
*)0, /* XXX */
1628 &lease
-> scope
, lease
-> on_release
);
1629 if (lease
-> on_release
)
1630 executable_statement_dereference (&lease
-> on_release
,
1634 /* We do either the on_release or the on_expiry events, but
1635 not both (it's possible that they could be the same,
1637 if (lease
-> on_expiry
)
1638 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1640 if (lease
-> binding_state
!= FTS_FREE
&&
1641 lease
-> binding_state
!= FTS_BACKUP
&&
1642 lease
-> binding_state
!= FTS_RELEASED
&&
1643 lease
-> binding_state
!= FTS_EXPIRED
&&
1644 lease
-> binding_state
!= FTS_RESET
) {
1645 if (lease
-> on_commit
)
1646 executable_statement_dereference (&lease
-> on_commit
,
1649 /* Blow away any bindings. */
1651 binding_scope_dereference (&lease
-> scope
, MDL
);
1653 /* Set sort times to the present. */
1654 lease
-> ends
= cur_time
;
1655 /* Lower layers of muckery set tstp to ->ends. But we send
1656 * protocol messages before this. So it is best to set
1659 lease
->tstp
= cur_time
;
1660 #if defined (FAILOVER_PROTOCOL)
1661 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1662 lease
-> next_binding_state
= FTS_RELEASED
;
1664 lease
-> next_binding_state
= FTS_FREE
;
1667 lease
-> next_binding_state
= FTS_FREE
;
1669 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1673 /* Abandon the specified lease (set its timeout to infinity and its
1674 particulars to zero, and re-hash it as appropriate. */
1676 void abandon_lease (lease
, message
)
1677 struct lease
*lease
;
1678 const char *message
;
1680 struct lease
*lt
= (struct lease
*)0;
1681 #if defined (NSUPDATE)
1682 ddns_removals(lease
, NULL
);
1685 if (!lease_copy (<
, lease
, MDL
))
1689 binding_scope_dereference(<
->scope
, MDL
);
1691 lt
-> ends
= cur_time
; /* XXX */
1692 lt
-> next_binding_state
= FTS_ABANDONED
;
1694 log_error ("Abandoning IP address %s: %s",
1695 piaddr (lease
-> ip_addr
), message
);
1696 lt
-> hardware_addr
.hlen
= 0;
1697 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1698 dfree (lt
-> uid
, MDL
);
1699 lt
-> uid
= (unsigned char *)0;
1702 supersede_lease (lease
, lt
, 1, 1, 1);
1703 lease_dereference (<
, MDL
);
1706 /* Abandon the specified lease (set its timeout to infinity and its
1707 particulars to zero, and re-hash it as appropriate. */
1709 void dissociate_lease (lease
)
1710 struct lease
*lease
;
1712 struct lease
*lt
= (struct lease
*)0;
1713 #if defined (NSUPDATE)
1714 ddns_removals(lease
, NULL
);
1717 if (!lease_copy (<
, lease
, MDL
))
1720 #if defined (FAILOVER_PROTOCOL)
1721 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1722 lt
-> next_binding_state
= FTS_RESET
;
1724 lt
-> next_binding_state
= FTS_FREE
;
1727 lt
-> next_binding_state
= FTS_FREE
;
1729 lt
-> ends
= cur_time
; /* XXX */
1730 lt
-> hardware_addr
.hlen
= 0;
1731 if (lt
-> uid
&& lt
-> uid
!= lt
-> uid_buf
)
1732 dfree (lt
-> uid
, MDL
);
1733 lt
-> uid
= (unsigned char *)0;
1736 supersede_lease (lease
, lt
, 1, 1, 1);
1737 lease_dereference (<
, MDL
);
1740 /* Timer called when a lease in a particular pool expires. */
1741 void pool_timer (vpool
)
1745 struct lease
*next
= (struct lease
*)0;
1746 struct lease
*lease
= (struct lease
*)0;
1747 #define FREE_LEASES 0
1748 #define ACTIVE_LEASES 1
1749 #define EXPIRED_LEASES 2
1750 #define ABANDONED_LEASES 3
1751 #define BACKUP_LEASES 4
1752 #define RESERVED_LEASES 5
1753 struct lease
**lptr
[RESERVED_LEASES
+1];
1754 TIME next_expiry
= MAX_TIME
;
1757 pool
= (struct pool
*)vpool
;
1759 lptr
[FREE_LEASES
] = &pool
-> free
;
1760 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1761 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1762 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1763 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1764 lptr
[RESERVED_LEASES
] = &pool
->reserved
;
1766 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
1767 /* If there's nothing on the queue, skip it. */
1771 #if defined (FAILOVER_PROTOCOL)
1772 if (pool
-> failover_peer
&&
1773 pool
-> failover_peer
-> me
.state
!= partner_down
) {
1774 /* The secondary can't remove a lease from the
1775 active state except in partner_down. */
1776 if (i
== ACTIVE_LEASES
&&
1777 pool
-> failover_peer
-> i_am
== secondary
)
1779 /* Leases in an expired state don't move to
1780 free because of a timeout unless we're in
1782 if (i
== EXPIRED_LEASES
)
1786 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1789 /* Remember the next lease in the list. */
1791 lease_dereference (&next
, MDL
);
1793 lease_reference (&next
, lease
-> next
, MDL
);
1795 /* If we've run out of things to expire on this list,
1797 if (lease
-> sort_time
> cur_time
) {
1798 if (lease
-> sort_time
< next_expiry
)
1799 next_expiry
= lease
-> sort_time
;
1803 /* If there is a pending state change, and
1804 this lease has gotten to the time when the
1805 state change should happen, just call
1806 supersede_lease on it to make the change
1808 if (lease
-> next_binding_state
!=
1809 lease
-> binding_state
)
1810 supersede_lease (lease
,
1811 (struct lease
*)0, 1, 1, 1);
1813 lease_dereference (&lease
, MDL
);
1815 lease_reference (&lease
, next
, MDL
);
1818 lease_dereference (&next
, MDL
);
1820 lease_dereference (&lease
, MDL
);
1822 if (next_expiry
!= MAX_TIME
) {
1823 pool
-> next_event_time
= next_expiry
;
1824 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1825 (tvref_t
)pool_reference
,
1826 (tvunref_t
)pool_dereference
);
1828 pool
-> next_event_time
= MIN_TIME
;
1832 /* Locate the lease associated with a given IP address... */
1834 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1835 const char *file
, int line
)
1837 return lease_ip_hash_lookup(lp
, lease_ip_addr_hash
, addr
.iabuf
,
1838 addr
.len
, file
, line
);
1841 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1842 unsigned len
, const char *file
, int line
)
1846 return lease_id_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1849 int find_lease_by_hw_addr (struct lease
**lp
,
1850 const unsigned char *hwaddr
, unsigned hwlen
,
1851 const char *file
, int line
)
1855 return lease_id_hash_lookup(lp
, lease_hw_addr_hash
, hwaddr
, hwlen
,
1859 /* If the lease is preferred over the candidate, return truth. The
1860 * 'cand' and 'lease' names are retained to read more clearly against
1861 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
1862 * to those two functions).
1864 * 1) ACTIVE leases are preferred. The active lease with
1865 * the longest lifetime is preferred over shortest.
1866 * 2) "transitional states" are next, this time with the
1868 * 3) free/backup/etc states are next, again with CLTT. In truth we
1869 * should never see reset leases for this.
1870 * 4) Abandoned leases are always dead last.
1872 static isc_boolean_t
1873 client_lease_preferred(struct lease
*cand
, struct lease
*lease
)
1875 if (cand
->binding_state
== FTS_ACTIVE
) {
1876 if (lease
->binding_state
== FTS_ACTIVE
&&
1877 lease
->ends
>= cand
->ends
)
1879 } else if (cand
->binding_state
== FTS_EXPIRED
||
1880 cand
->binding_state
== FTS_RELEASED
) {
1881 if (lease
->binding_state
== FTS_ACTIVE
)
1884 if ((lease
->binding_state
== FTS_EXPIRED
||
1885 lease
->binding_state
== FTS_RELEASED
) &&
1886 lease
->cltt
>= cand
->cltt
)
1888 } else if (cand
->binding_state
!= FTS_ABANDONED
) {
1889 if (lease
->binding_state
== FTS_ACTIVE
||
1890 lease
->binding_state
== FTS_EXPIRED
||
1891 lease
->binding_state
== FTS_RELEASED
)
1894 if (lease
->binding_state
!= FTS_ABANDONED
&&
1895 lease
->cltt
>= cand
->cltt
)
1897 } else /* (cand->binding_state == FTS_ABANDONED) */ {
1898 if (lease
->binding_state
!= FTS_ABANDONED
||
1899 lease
->cltt
>= cand
->cltt
)
1906 /* Add the specified lease to the uid hash. */
1908 uid_hash_add(struct lease
*lease
)
1910 struct lease
*head
= NULL
;
1911 struct lease
*cand
= NULL
;
1912 struct lease
*prev
= NULL
;
1913 struct lease
*next
= NULL
;
1915 /* If it's not in the hash, just add it. */
1916 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1917 lease_id_hash_add(lease_uid_hash
, lease
->uid
, lease
->uid_len
,
1920 /* Otherwise, insert it into the list in order of its
1921 * preference for "resuming allocation to the client."
1923 * Because we don't have control of the hash bucket index
1924 * directly, we have to remove and re-insert the client
1925 * id into the hash if we're inserting onto the head.
1927 lease_reference(&cand
, head
, MDL
);
1928 while (cand
!= NULL
) {
1929 if (client_lease_preferred(cand
, lease
))
1933 lease_dereference(&prev
, MDL
);
1934 lease_reference(&prev
, cand
, MDL
);
1936 if (cand
->n_uid
!= NULL
)
1937 lease_reference(&next
, cand
->n_uid
, MDL
);
1939 lease_dereference(&cand
, MDL
);
1942 lease_reference(&cand
, next
, MDL
);
1943 lease_dereference(&next
, MDL
);
1947 /* If we want to insert 'before cand', and prev is NULL,
1948 * then it was the head of the list. Assume that position.
1951 lease_reference(&lease
->n_uid
, head
, MDL
);
1952 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
1953 lease
->uid_len
, MDL
);
1954 lease_id_hash_add(lease_uid_hash
, lease
->uid
,
1955 lease
->uid_len
, lease
, MDL
);
1956 } else /* (prev != NULL) */ {
1957 if(prev
->n_uid
!= NULL
) {
1958 lease_reference(&lease
->n_uid
, prev
->n_uid
,
1960 lease_dereference(&prev
->n_uid
, MDL
);
1962 lease_reference(&prev
->n_uid
, lease
, MDL
);
1964 lease_dereference(&prev
, MDL
);
1968 lease_dereference(&cand
, MDL
);
1969 lease_dereference(&head
, MDL
);
1973 /* Delete the specified lease from the uid hash. */
1975 void uid_hash_delete (lease
)
1976 struct lease
*lease
;
1978 struct lease
*head
= (struct lease
*)0;
1981 /* If it's not in the hash, we have no work to do. */
1982 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1984 lease_dereference (&lease
-> n_uid
, MDL
);
1988 /* If the lease we're freeing is at the head of the list,
1989 remove the hash table entry and add a new one with the
1990 next lease on the list (if there is one). */
1991 if (head
== lease
) {
1992 lease_id_hash_delete(lease_uid_hash
, lease
->uid
,
1993 lease
->uid_len
, MDL
);
1994 if (lease
-> n_uid
) {
1995 lease_id_hash_add(lease_uid_hash
, lease
->n_uid
->uid
,
1996 lease
->n_uid
->uid_len
, lease
->n_uid
,
1998 lease_dereference (&lease
-> n_uid
, MDL
);
2001 /* Otherwise, look for the lease in the list of leases
2002 attached to the hash table entry, and remove it if
2004 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
2005 if (scan
-> n_uid
== lease
) {
2006 lease_dereference (&scan
-> n_uid
, MDL
);
2007 if (lease
-> n_uid
) {
2008 lease_reference (&scan
-> n_uid
,
2009 lease
-> n_uid
, MDL
);
2010 lease_dereference (&lease
-> n_uid
,
2017 lease_dereference (&head
, MDL
);
2020 /* Add the specified lease to the hardware address hash. */
2023 hw_hash_add(struct lease
*lease
)
2025 struct lease
*head
= NULL
;
2026 struct lease
*cand
= NULL
;
2027 struct lease
*prev
= NULL
;
2028 struct lease
*next
= NULL
;
2030 /* If it's not in the hash, just add it. */
2031 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2032 lease
-> hardware_addr
.hlen
, MDL
))
2033 lease_id_hash_add(lease_hw_addr_hash
,
2034 lease
->hardware_addr
.hbuf
,
2035 lease
->hardware_addr
.hlen
, lease
, MDL
);
2037 /* Otherwise, insert it into the list in order of its
2038 * preference for "resuming allocation to the client."
2040 * Because we don't have control of the hash bucket index
2041 * directly, we have to remove and re-insert the client
2042 * id into the hash if we're inserting onto the head.
2044 lease_reference(&cand
, head
, MDL
);
2045 while (cand
!= NULL
) {
2046 if (client_lease_preferred(cand
, lease
))
2050 lease_dereference(&prev
, MDL
);
2051 lease_reference(&prev
, cand
, MDL
);
2053 if (cand
->n_hw
!= NULL
)
2054 lease_reference(&next
, cand
->n_hw
, MDL
);
2056 lease_dereference(&cand
, MDL
);
2059 lease_reference(&cand
, next
, MDL
);
2060 lease_dereference(&next
, MDL
);
2064 /* If we want to insert 'before cand', and prev is NULL,
2065 * then it was the head of the list. Assume that position.
2068 lease_reference(&lease
->n_hw
, head
, MDL
);
2069 lease_id_hash_delete(lease_hw_addr_hash
,
2070 lease
->hardware_addr
.hbuf
,
2071 lease
->hardware_addr
.hlen
, MDL
);
2072 lease_id_hash_add(lease_hw_addr_hash
,
2073 lease
->hardware_addr
.hbuf
,
2074 lease
->hardware_addr
.hlen
,
2076 } else /* (prev != NULL) */ {
2077 if(prev
->n_hw
!= NULL
) {
2078 lease_reference(&lease
->n_hw
, prev
->n_hw
,
2080 lease_dereference(&prev
->n_hw
, MDL
);
2082 lease_reference(&prev
->n_hw
, lease
, MDL
);
2084 lease_dereference(&prev
, MDL
);
2088 lease_dereference(&cand
, MDL
);
2089 lease_dereference(&head
, MDL
);
2093 /* Delete the specified lease from the hardware address hash. */
2095 void hw_hash_delete (lease
)
2096 struct lease
*lease
;
2098 struct lease
*head
= (struct lease
*)0;
2099 struct lease
*next
= (struct lease
*)0;
2101 /* If it's not in the hash, we have no work to do. */
2102 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
2103 lease
-> hardware_addr
.hlen
, MDL
)) {
2105 lease_dereference (&lease
-> n_hw
, MDL
);
2109 /* If the lease we're freeing is at the head of the list,
2110 remove the hash table entry and add a new one with the
2111 next lease on the list (if there is one). */
2112 if (head
== lease
) {
2113 lease_id_hash_delete(lease_hw_addr_hash
,
2114 lease
->hardware_addr
.hbuf
,
2115 lease
->hardware_addr
.hlen
, MDL
);
2117 lease_id_hash_add(lease_hw_addr_hash
,
2118 lease
->n_hw
->hardware_addr
.hbuf
,
2119 lease
->n_hw
->hardware_addr
.hlen
,
2121 lease_dereference(&lease
->n_hw
, MDL
);
2124 /* Otherwise, look for the lease in the list of leases
2125 attached to the hash table entry, and remove it if
2127 while (head
-> n_hw
) {
2128 if (head
-> n_hw
== lease
) {
2129 lease_dereference (&head
-> n_hw
, MDL
);
2130 if (lease
-> n_hw
) {
2131 lease_reference (&head
-> n_hw
,
2132 lease
-> n_hw
, MDL
);
2133 lease_dereference (&lease
-> n_hw
,
2138 lease_reference (&next
, head
-> n_hw
, MDL
);
2139 lease_dereference (&head
, MDL
);
2140 lease_reference (&head
, next
, MDL
);
2141 lease_dereference (&next
, MDL
);
2145 lease_dereference (&head
, MDL
);
2148 /* Write all interesting leases to permanent storage. */
2153 struct shared_network
*s
;
2155 struct host_decl
*hp
;
2156 struct group_object
*gp
;
2157 struct hash_bucket
*hb
;
2159 struct collection
*colp
;
2162 struct lease
**lptr
[RESERVED_LEASES
+1];
2164 /* write all the dynamically-created class declarations. */
2165 if (collections
->classes
) {
2166 numclasseswritten
= 0;
2167 for (colp
= collections
; colp
; colp
= colp
->next
) {
2168 for (cp
= colp
->classes
; cp
; cp
= cp
->nic
) {
2169 write_named_billing_class(
2170 (unsigned char *)cp
->name
,
2175 /* XXXJAB this number doesn't include subclasses... */
2176 log_info ("Wrote %d class decls to leases file.",
2181 /* Write all the dynamically-created group declarations. */
2182 if (group_name_hash
) {
2184 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
2185 for (hb
= group_name_hash
-> buckets
[i
];
2186 hb
; hb
= hb
-> next
) {
2187 gp
= (struct group_object
*)hb
-> value
;
2188 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
2189 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
2190 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
2191 if (!write_group (gp
))
2197 log_info ("Wrote %d group decls to leases file.", num_written
);
2200 /* Write all the deleted host declarations. */
2201 if (host_name_hash
) {
2203 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2204 for (hb
= host_name_hash
-> buckets
[i
];
2205 hb
; hb
= hb
-> next
) {
2206 hp
= (struct host_decl
*)hb
-> value
;
2207 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
2208 (hp
-> flags
& HOST_DECL_DELETED
))) {
2209 if (!write_host (hp
))
2215 log_info ("Wrote %d deleted host decls to leases file.",
2219 /* Write all the new, dynamic host declarations. */
2220 if (host_name_hash
) {
2222 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
2223 for (hb
= host_name_hash
-> buckets
[i
];
2224 hb
; hb
= hb
-> next
) {
2225 hp
= (struct host_decl
*)hb
-> value
;
2226 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
2227 if (!write_host (hp
))
2232 log_info ("Wrote %d new dynamic host decls to leases file.",
2236 #if defined (FAILOVER_PROTOCOL)
2237 /* Write all the failover states. */
2238 if (!dhcp_failover_write_all_states ())
2242 /* Write all the leases. */
2244 for (s
= shared_networks
; s
; s
= s
-> next
) {
2245 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2246 lptr
[FREE_LEASES
] = &p
-> free
;
2247 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2248 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2249 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2250 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2251 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2253 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2254 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2255 #if !defined (DEBUG_DUMP_ALL_LEASES)
2256 if (l
-> hardware_addr
.hlen
||
2258 (l
-> binding_state
!= FTS_FREE
))
2261 if (!write_lease (l
))
2269 log_info ("Wrote %d leases to leases file.", num_written
);
2271 if (!write_leases6()) {
2275 if (!commit_leases ())
2280 /* In addition to placing this lease upon a lease queue depending on its
2281 * state, it also keeps track of the number of FREE and BACKUP leases in
2282 * existence, and sets the sort_time on the lease.
2284 * Sort_time is used in pool_timer() to determine when the lease will
2285 * bubble to the top of the list and be supersede_lease()'d into its next
2286 * state (possibly, if all goes well). Example, ACTIVE leases move to
2287 * EXPIRED state when the 'ends' value is reached, so that is its sort
2288 * time. Most queues are sorted by 'ends', since it is generally best
2289 * practice to re-use the oldest lease, to reduce address collision
2292 int lease_enqueue (struct lease
*comp
)
2294 struct lease
**lq
, *prev
, *lp
;
2295 static struct lease
**last_lq
= NULL
;
2296 static struct lease
*last_insert_point
= NULL
;
2298 /* No queue to put it on? */
2302 /* Figure out which queue it's going to. */
2303 switch (comp
-> binding_state
) {
2305 if (comp
->flags
& RESERVED_LEASE
) {
2306 lq
= &comp
->pool
->reserved
;
2308 lq
= &comp
->pool
->free
;
2309 comp
->pool
->free_leases
++;
2311 comp
-> sort_time
= comp
-> ends
;
2315 lq
= &comp
-> pool
-> active
;
2316 comp
-> sort_time
= comp
-> ends
;
2322 lq
= &comp
-> pool
-> expired
;
2323 #if defined(FAILOVER_PROTOCOL)
2324 /* In partner_down, tsfp is the time at which the lease
2325 * may be reallocated (stos+mclt). We can do that with
2326 * lease_mine_to_reallocate() anywhere between tsfp and
2327 * ends. But we prefer to wait until ends before doing it
2328 * automatically (choose the greater of the two). Note
2329 * that 'ends' is usually a historic timestamp in the
2330 * case of expired leases, is really only in the future
2331 * on released leases, and if we know a lease to be released
2332 * the peer might still know it to be active...in which case
2333 * it's possible the peer has renewed this lease, so avoid
2336 if (comp
->pool
->failover_peer
&&
2337 comp
->pool
->failover_peer
->me
.state
== partner_down
)
2338 comp
->sort_time
= (comp
->tsfp
> comp
->ends
) ?
2339 comp
->tsfp
: comp
->ends
;
2342 comp
->sort_time
= comp
->ends
;
2347 lq
= &comp
-> pool
-> abandoned
;
2348 comp
-> sort_time
= comp
-> ends
;
2352 if (comp
->flags
& RESERVED_LEASE
) {
2353 lq
= &comp
->pool
->reserved
;
2355 lq
= &comp
->pool
->backup
;
2356 comp
->pool
->backup_leases
++;
2358 comp
-> sort_time
= comp
-> ends
;
2362 log_error ("Lease with bogus binding state: %d",
2363 comp
-> binding_state
);
2364 #if defined (BINDING_STATE_DEBUG)
2370 /* This only works during server startup: during runtime, the last
2371 * lease may be dequeued in between calls. If the queue is the same
2372 * as was used previously, and the lease structure isn't (this is not
2373 * a re-queue), use that as a starting point for the insertion-sort.
2375 if ((server_starting
& SS_QFOLLOW
) && (lq
== last_lq
) &&
2376 (comp
!= last_insert_point
) &&
2377 (last_insert_point
->sort_time
<= comp
->sort_time
)) {
2378 prev
= last_insert_point
;
2385 /* Insertion sort the lease onto the appropriate queue. */
2386 for (; lp
; lp
= lp
->next
) {
2387 if (lp
-> sort_time
>= comp
-> sort_time
)
2394 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
2395 lease_dereference (&prev
-> next
, MDL
);
2397 lease_reference (&prev
-> next
, comp
, MDL
);
2400 lease_reference (&comp
-> next
, *lq
, MDL
);
2401 lease_dereference (lq
, MDL
);
2403 lease_reference (lq
, comp
, MDL
);
2405 last_insert_point
= comp
;
2410 /* For a given lease, sort it onto the right list in its pool and put it
2411 in each appropriate hash, understanding that it's already by definition
2412 in lease_ip_addr_hash. */
2415 lease_instantiate(const void *key
, unsigned len
, void *object
)
2417 struct lease
*lease
= object
;
2418 struct class *class;
2419 /* XXX If the lease doesn't have a pool at this point, it's an
2420 XXX orphan, which we *should* keep around until it expires,
2421 XXX but which right now we just forget. */
2422 if (!lease
-> pool
) {
2423 lease_ip_hash_delete(lease_ip_addr_hash
, lease
->ip_addr
.iabuf
,
2424 lease
->ip_addr
.len
, MDL
);
2425 return ISC_R_SUCCESS
;
2428 /* Put the lease on the right queue. Failure to queue is probably
2429 * due to a bogus binding state. In such a case, we claim success,
2430 * so that later leases in a hash_foreach are processed, but we
2431 * return early as we really don't want hw address hash entries or
2432 * other cruft to surround such a bogus entry.
2434 if (!lease_enqueue(lease
))
2435 return ISC_R_SUCCESS
;
2437 /* Record the lease in the uid hash if possible. */
2439 uid_hash_add (lease
);
2442 /* Record it in the hardware address hash if possible. */
2443 if (lease
-> hardware_addr
.hlen
) {
2444 hw_hash_add (lease
);
2447 /* If the lease has a billing class, set up the billing. */
2448 if (lease
-> billing_class
) {
2449 class = (struct class *)0;
2450 class_reference (&class, lease
-> billing_class
, MDL
);
2451 class_dereference (&lease
-> billing_class
, MDL
);
2452 /* If the lease is available for allocation, the billing
2453 is invalid, so we don't keep it. */
2454 if (lease
-> binding_state
== FTS_ACTIVE
||
2455 lease
-> binding_state
== FTS_EXPIRED
||
2456 lease
-> binding_state
== FTS_RELEASED
||
2457 lease
-> binding_state
== FTS_RESET
)
2458 bill_class (lease
, class);
2459 class_dereference (&class, MDL
);
2461 return ISC_R_SUCCESS
;
2464 /* Run expiry events on every pool. This is called on startup so that
2465 any expiry events that occurred after the server stopped and before it
2466 was restarted can be run. At the same time, if failover support is
2467 compiled in, we compute the balance of leases for the pool. */
2469 void expire_all_pools ()
2471 struct shared_network
*s
;
2475 struct lease
**lptr
[RESERVED_LEASES
+1];
2477 /* Indicate that we are in the startup phase */
2478 server_starting
= SS_NOSYNC
| SS_QFOLLOW
;
2480 /* First, go over the hash list and actually put all the leases
2481 on the appropriate lists. */
2482 lease_ip_hash_foreach(lease_ip_addr_hash
, lease_instantiate
);
2484 /* Loop through each pool in each shared network and call the
2485 * expiry routine on the pool. It is no longer safe to follow
2486 * the queue insertion point, as expiration of a lease can move
2487 * it between queues (and this may be the lease that function
2490 server_starting
&= ~SS_QFOLLOW
;
2491 for (s
= shared_networks
; s
; s
= s
-> next
) {
2492 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2495 p
-> lease_count
= 0;
2496 p
-> free_leases
= 0;
2497 p
-> backup_leases
= 0;
2499 lptr
[FREE_LEASES
] = &p
-> free
;
2500 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2501 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2502 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2503 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2504 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2506 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2507 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2509 if (l
-> ends
<= cur_time
) {
2510 if (l
->binding_state
== FTS_FREE
) {
2511 if (i
== FREE_LEASES
)
2513 else if (i
!= RESERVED_LEASES
)
2514 log_fatal("Impossible case "
2516 } else if (l
->binding_state
== FTS_BACKUP
) {
2517 if (i
== BACKUP_LEASES
)
2519 else if (i
!= RESERVED_LEASES
)
2520 log_fatal("Impossible case "
2524 #if defined (FAILOVER_PROTOCOL)
2525 if (p
-> failover_peer
&&
2526 l
-> tstp
> l
-> atsfp
&&
2527 !(l
-> flags
& ON_UPDATE_QUEUE
)) {
2528 l
-> desired_binding_state
= l
-> binding_state
;
2529 dhcp_failover_queue_update (l
, 1);
2537 /* turn off startup phase */
2538 server_starting
= 0;
2541 void dump_subnets ()
2544 struct shared_network
*s
;
2547 struct lease
**lptr
[RESERVED_LEASES
+1];
2550 log_info ("Subnets:");
2551 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
2552 log_debug (" Subnet %s", piaddr (n
-> net
));
2553 log_debug (" netmask %s",
2554 piaddr (n
-> netmask
));
2556 log_info ("Shared networks:");
2557 for (s
= shared_networks
; s
; s
= s
-> next
) {
2558 log_info (" %s", s
-> name
);
2559 for (p
= s
-> pools
; p
; p
= p
-> next
) {
2560 lptr
[FREE_LEASES
] = &p
-> free
;
2561 lptr
[ACTIVE_LEASES
] = &p
-> active
;
2562 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
2563 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
2564 lptr
[BACKUP_LEASES
] = &p
-> backup
;
2565 lptr
[RESERVED_LEASES
] = &p
->reserved
;
2567 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2568 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
2576 HASH_FUNCTIONS(lease_ip
, const unsigned char *, struct lease
, lease_ip_hash_t
,
2577 lease_reference
, lease_dereference
, do_ip4_hash
)
2578 HASH_FUNCTIONS(lease_id
, const unsigned char *, struct lease
, lease_id_hash_t
,
2579 lease_reference
, lease_dereference
, do_id_hash
)
2580 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
, host_hash_t
,
2581 host_reference
, host_dereference
, do_string_hash
)
2582 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t
,
2583 class_reference
, class_dereference
, do_string_hash
)
2585 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2586 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2587 extern struct hash_table
*dns_zone_hash
;
2588 extern struct interface_info
**interface_vector
;
2589 extern int interface_count
;
2590 dhcp_control_object_t
*dhcp_control_object
;
2591 extern struct hash_table
*auth_key_hash
;
2592 struct hash_table
*universe_hash
;
2593 struct universe
**universes
;
2594 int universe_count
, universe_max
;
2599 #if defined (COMPACT_LEASES)
2600 extern struct lease
*lease_hunks
;
2603 void free_everything ()
2605 struct subnet
*sc
= (struct subnet
*)0, *sn
= (struct subnet
*)0;
2606 struct shared_network
*nc
= (struct shared_network
*)0,
2607 *nn
= (struct shared_network
*)0;
2608 struct pool
*pc
= (struct pool
*)0, *pn
= (struct pool
*)0;
2609 struct lease
*lc
= (struct lease
*)0, *ln
= (struct lease
*)0;
2610 struct interface_info
*ic
= (struct interface_info
*)0,
2611 *in
= (struct interface_info
*)0;
2612 struct class *cc
= (struct class *)0, *cn
= (struct class *)0;
2613 struct collection
*lp
;
2614 void *st
= (shared_networks
2615 ? (shared_networks
-> next
2616 ? shared_networks
-> next
-> next
: 0) : 0);
2620 /* Get rid of all the hash tables. */
2621 if (host_hw_addr_hash
)
2622 host_free_hash_table (&host_hw_addr_hash
, MDL
);
2623 host_hw_addr_hash
= 0;
2625 host_free_hash_table (&host_uid_hash
, MDL
);
2628 lease_free_hash_table (&lease_uid_hash
, MDL
);
2630 if (lease_ip_addr_hash
)
2631 lease_free_hash_table (&lease_ip_addr_hash
, MDL
);
2632 lease_ip_addr_hash
= 0;
2633 if (lease_hw_addr_hash
)
2634 lease_free_hash_table (&lease_hw_addr_hash
, MDL
);
2635 lease_hw_addr_hash
= 0;
2637 host_free_hash_table (&host_name_hash
, MDL
);
2640 dns_zone_free_hash_table (&dns_zone_hash
, MDL
);
2643 while (host_id_info
!= NULL
) {
2644 host_id_info_t
*tmp
;
2645 option_dereference(&host_id_info
->option
, MDL
);
2646 host_free_hash_table(&host_id_info
->values_hash
, MDL
);
2647 tmp
= host_id_info
->next
;
2648 dfree(host_id_info
, MDL
);
2653 auth_key_free_hash_table (&auth_key_hash
, MDL
);
2657 omapi_object_dereference ((omapi_object_t
**)&dhcp_control_object
,
2660 for (lp
= collections
; lp
; lp
= lp
-> next
) {
2661 if (lp
-> classes
) {
2662 class_reference (&cn
, lp
-> classes
, MDL
);
2665 class_reference (&cc
, cn
, MDL
);
2666 class_dereference (&cn
, MDL
);
2669 class_reference (&cn
, cc
-> nic
, MDL
);
2670 class_dereference (&cc
-> nic
, MDL
);
2672 group_dereference (&cc
-> group
, MDL
);
2674 class_free_hash_table (&cc
-> hash
, MDL
);
2675 cc
-> hash
= (struct hash_table
*)0;
2677 class_dereference (&cc
, MDL
);
2679 class_dereference (&lp
-> classes
, MDL
);
2683 if (interface_vector
) {
2684 for (i
= 0; i
< interface_count
; i
++) {
2685 if (interface_vector
[i
])
2686 interface_dereference (&interface_vector
[i
], MDL
);
2688 dfree (interface_vector
, MDL
);
2689 interface_vector
= 0;
2693 interface_reference (&in
, interfaces
, MDL
);
2696 interface_reference (&ic
, in
, MDL
);
2697 interface_dereference (&in
, MDL
);
2700 interface_reference (&in
, ic
-> next
, MDL
);
2701 interface_dereference (&ic
-> next
, MDL
);
2703 omapi_unregister_io_object ((omapi_object_t
*)ic
);
2704 if (ic
-> shared_network
) {
2705 if (ic
-> shared_network
-> interface
)
2706 interface_dereference
2707 (&ic
-> shared_network
-> interface
, MDL
);
2708 shared_network_dereference (&ic
-> shared_network
, MDL
);
2710 interface_dereference (&ic
, MDL
);
2712 interface_dereference (&interfaces
, MDL
);
2715 /* Subnets are complicated because of the extra links. */
2717 subnet_reference (&sn
, subnets
, MDL
);
2720 subnet_reference (&sc
, sn
, MDL
);
2721 subnet_dereference (&sn
, MDL
);
2723 if (sc
-> next_subnet
) {
2724 subnet_reference (&sn
, sc
-> next_subnet
, MDL
);
2725 subnet_dereference (&sc
-> next_subnet
, MDL
);
2727 if (sc
-> next_sibling
)
2728 subnet_dereference (&sc
-> next_sibling
, MDL
);
2729 if (sc
-> shared_network
)
2730 shared_network_dereference (&sc
-> shared_network
, MDL
);
2731 group_dereference (&sc
-> group
, MDL
);
2732 if (sc
-> interface
)
2733 interface_dereference (&sc
-> interface
, MDL
);
2734 subnet_dereference (&sc
, MDL
);
2736 subnet_dereference (&subnets
, MDL
);
2739 /* So are shared networks. */
2740 if (shared_networks
) {
2741 shared_network_reference (&nn
, shared_networks
, MDL
);
2744 shared_network_reference (&nc
, nn
, MDL
);
2745 shared_network_dereference (&nn
, MDL
);
2748 shared_network_reference (&nn
, nc
-> next
, MDL
);
2749 shared_network_dereference (&nc
-> next
, MDL
);
2754 pool_reference (&pn
, nc
-> pools
, MDL
);
2756 struct lease
**lptr
[RESERVED_LEASES
+1];
2759 pool_reference (&pc
, pn
, MDL
);
2760 pool_dereference (&pn
, MDL
);
2763 pool_reference (&pn
, pc
-> next
, MDL
);
2764 pool_dereference (&pc
-> next
, MDL
);
2767 lptr
[FREE_LEASES
] = &pc
-> free
;
2768 lptr
[ACTIVE_LEASES
] = &pc
-> active
;
2769 lptr
[EXPIRED_LEASES
] = &pc
-> expired
;
2770 lptr
[ABANDONED_LEASES
] = &pc
-> abandoned
;
2771 lptr
[BACKUP_LEASES
] = &pc
-> backup
;
2772 lptr
[RESERVED_LEASES
] = &pc
->reserved
;
2774 /* As (sigh) are leases. */
2775 for (i
= FREE_LEASES
; i
<= RESERVED_LEASES
; i
++) {
2777 lease_reference (&ln
, *lptr
[i
], MDL
);
2780 lease_reference (&lc
, ln
, MDL
);
2781 lease_dereference (&ln
, MDL
);
2784 lease_reference (&ln
, lc
-> next
, MDL
);
2785 lease_dereference (&lc
-> next
, MDL
);
2787 if (lc
-> billing_class
)
2788 class_dereference (&lc
-> billing_class
,
2791 free_lease_state (lc
-> state
, MDL
);
2792 lc
-> state
= (struct lease_state
*)0;
2794 lease_dereference (&lc
-> n_hw
, MDL
);
2796 lease_dereference (&lc
-> n_uid
, MDL
);
2797 lease_dereference (&lc
, MDL
);
2799 lease_dereference (lptr
[i
], MDL
);
2803 group_dereference (&pc
-> group
, MDL
);
2804 if (pc
-> shared_network
)
2805 shared_network_dereference (&pc
-> shared_network
,
2807 pool_dereference (&pc
, MDL
);
2809 pool_dereference (&nc
-> pools
, MDL
);
2811 /* Because of a circular reference, we need to nuke this
2813 group_dereference (&nc
-> group
, MDL
);
2814 shared_network_dereference (&nc
, MDL
);
2816 shared_network_dereference (&shared_networks
, MDL
);
2819 cancel_all_timeouts ();
2820 relinquish_timeouts ();
2822 group_dereference (&root_group
, MDL
);
2823 executable_statement_dereference (&default_classification_rules
, MDL
);
2825 shutdown_state
= shutdown_drop_omapi_connections
;
2826 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2827 shutdown_state
= shutdown_listeners
;
2828 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2829 shutdown_state
= shutdown_dhcp
;
2830 omapi_io_state_foreach (dhcp_io_shutdown
, 0);
2832 omapi_object_dereference ((omapi_object_t
**)&icmp_state
, MDL
);
2834 universe_free_hash_table (&universe_hash
, MDL
);
2835 for (i
= 0; i
< universe_count
; i
++) {
2840 if (universes
[i
]) {
2841 if (universes
[i
] -> hash
)
2842 option_free_hash_table (&universes
[i
] -> hash
,
2845 if (universes
[i
] -> name
> (char *)&end
) {
2846 foo
.c
= universes
[i
] -> name
;
2849 if (universes
[i
] > (struct universe
*)&end
)
2850 dfree (universes
[i
], MDL
);
2854 dfree (universes
, MDL
);
2856 relinquish_free_lease_states ();
2857 relinquish_free_pairs ();
2858 relinquish_free_expressions ();
2859 relinquish_free_binding_values ();
2860 relinquish_free_option_caches ();
2861 relinquish_free_packets ();
2862 relinquish_lease_hunks ();
2863 relinquish_hash_bucket_hunks ();
2864 omapi_type_relinquish ();
2866 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */