3 Server-specific in-memory database support. */
6 * Copyright (c) 1996-2000 Internet Software Consortium.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
38 * To learn more about the Internet Software Consortium, see
39 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
40 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
41 * ``http://www.nominum.com''.
45 static char copyright
[] =
46 "$Id: mdb.c,v 1.51 2001/01/25 08:36:36 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
51 struct subnet
*subnets
;
52 struct shared_network
*shared_networks
;
53 struct hash_table
*host_hw_addr_hash
;
54 struct hash_table
*host_uid_hash
;
55 struct hash_table
*lease_uid_hash
;
56 struct hash_table
*lease_ip_addr_hash
;
57 struct hash_table
*lease_hw_addr_hash
;
58 struct hash_table
*host_name_hash
;
60 omapi_object_type_t
*dhcp_type_host
;
62 isc_result_t
enter_host (hd
, dynamicp
, commit
)
67 struct host_decl
*hp
= (struct host_decl
*)0;
68 struct host_decl
*np
= (struct host_decl
*)0;
69 struct executable_statement
*esp
;
71 if (!host_name_hash
) {
73 new_hash ((hash_reference
)host_reference
,
74 (hash_dereference
)host_dereference
, 0);
76 log_fatal ("Can't allocate host name hash");
77 host_hash_add (host_name_hash
,
78 (unsigned char *)hd
-> name
,
79 strlen (hd
-> name
), hd
, MDL
);
81 host_hash_lookup (&hp
, host_name_hash
,
82 (unsigned char *)hd
-> name
,
83 strlen (hd
-> name
), MDL
);
85 /* If it's deleted, we can supersede it. */
86 if (hp
&& (hp
-> flags
& HOST_DECL_DELETED
)) {
87 host_hash_delete (host_name_hash
,
88 (unsigned char *)hd
-> name
,
89 strlen (hd
-> name
), MDL
);
90 /* If the old entry wasn't dynamic, then we
91 always have to keep the deletion. */
92 if (!hp
-> flags
& HOST_DECL_DYNAMIC
)
93 hd
-> flags
|= HOST_DECL_STATIC
;
96 /* If there isn't already a host decl matching this
97 address, add it to the hash table. */
99 host_hash_add (host_name_hash
,
100 (unsigned char *)hd
-> name
,
101 strlen (hd
-> name
), hd
, MDL
);
103 /* XXX actually, we have to delete the old one
104 XXX carefully and replace it. Not done yet. */
105 host_dereference (&hp
, MDL
);
111 host_dereference (&hd
-> n_ipaddr
, MDL
);
114 hd
-> type
= dhcp_type_host
;
116 if (hd
-> interface
.hlen
) {
117 if (!host_hw_addr_hash
) {
119 new_hash ((hash_reference
)host_reference
,
120 (hash_dereference
)host_dereference
,
122 if (!host_hw_addr_hash
)
123 log_fatal ("Can't allocate host/hw hash");
125 /* If there isn't already a host decl matching this
126 address, add it to the hash table. */
127 host_hash_lookup (&hp
, host_hw_addr_hash
,
128 hd
-> interface
.hbuf
,
129 hd
-> interface
.hlen
, MDL
);
132 host_hash_add (host_hw_addr_hash
, hd
-> interface
.hbuf
,
133 hd
-> interface
.hlen
, hd
, MDL
);
135 /* If there was already a host declaration for
136 this hardware address, add this one to the
138 for (np
= hp
; np
-> n_ipaddr
; np
= np
-> n_ipaddr
)
140 host_reference (&np
-> n_ipaddr
, hd
, MDL
);
141 host_dereference (&hp
, MDL
);
145 /* See if there's a statement that sets the client identifier.
146 This is a kludge - the client identifier really shouldn't be
147 set with an executable statement. */
148 for (esp
= hd
-> group
-> statements
; esp
; esp
= esp
-> next
) {
149 if (esp
-> op
== supersede_option_statement
&&
150 esp
-> data
.option
&&
151 (esp
-> data
.option
-> option
-> universe
==
153 (esp
-> data
.option
-> option
-> code
==
154 DHO_DHCP_CLIENT_IDENTIFIER
)) {
155 evaluate_option_cache
156 (&hd
-> client_identifier
, (struct packet
*)0,
157 (struct lease
*)0, (struct client_state
*)0,
158 (struct option_state
*)0,
159 (struct option_state
*)0, &global_scope
,
160 esp
-> data
.option
, MDL
);
165 /* If we got a client identifier, hash this entry by
166 client identifier. */
167 if (hd
-> client_identifier
.len
) {
168 /* If there's no uid hash, make one; otherwise, see if
169 there's already an entry in the hash for this host. */
170 if (!host_uid_hash
) {
172 new_hash ((hash_reference
)host_reference
,
173 (hash_dereference
)host_dereference
,
176 log_fatal ("Can't allocate host/uid hash");
178 host_hash_add (host_uid_hash
,
179 hd
-> client_identifier
.data
,
180 hd
-> client_identifier
.len
,
183 /* If there's already a host declaration for this
184 client identifier, add this one to the end of the
185 list. Otherwise, add it to the hash table. */
186 if (host_hash_lookup (&hp
, host_uid_hash
,
187 hd
-> client_identifier
.data
,
188 hd
-> client_identifier
.len
,
190 /* Don't link it in twice... */
192 for (np
= hp
; np
-> n_ipaddr
;
193 np
= np
-> n_ipaddr
) {
198 host_reference (&np
-> n_ipaddr
,
201 host_dereference (&hp
, MDL
);
203 host_hash_add (host_uid_hash
,
204 hd
-> client_identifier
.data
,
205 hd
-> client_identifier
.len
,
211 if (dynamicp
&& commit
) {
212 if (!write_host (hd
))
213 return ISC_R_IOERROR
;
214 if (!commit_leases ())
215 return ISC_R_IOERROR
;
218 return ISC_R_SUCCESS
;
221 isc_result_t
delete_host (hd
, commit
)
222 struct host_decl
*hd
;
225 struct host_decl
*hp
= (struct host_decl
*)0;
226 struct host_decl
*np
= (struct host_decl
*)0;
227 struct host_decl
*foo
;
228 struct executable_statement
*esp
;
229 int hw_head
= 0, uid_head
= 1;
231 /* Don't need to do it twice. */
232 if (hd
-> flags
& HOST_DECL_DELETED
)
233 return ISC_R_SUCCESS
;
235 /* But we do need to do it once! :') */
236 hd
-> flags
|= HOST_DECL_DELETED
;
238 if (hd
-> interface
.hlen
) {
239 if (host_hw_addr_hash
) {
240 if (host_hash_lookup (&hp
, host_hw_addr_hash
,
241 hd
-> interface
.hbuf
,
242 hd
-> interface
.hlen
, MDL
)) {
244 host_hash_delete (host_hw_addr_hash
,
245 hd
-> interface
.hbuf
,
246 hd
-> interface
.hlen
, MDL
);
249 for (foo
= hp
; foo
; foo
= foo
-> n_ipaddr
) {
255 host_dereference (&np
-> n_ipaddr
, MDL
);
257 host_reference (&np
-> n_ipaddr
,
258 hd
-> n_ipaddr
, MDL
);
261 host_dereference (&hp
, MDL
);
266 /* If we got a client identifier, hash this entry by
267 client identifier. */
268 if (hd
-> client_identifier
.len
) {
270 if (host_hash_lookup (&hp
, host_uid_hash
,
271 hd
-> client_identifier
.data
,
272 hd
-> client_identifier
.len
, MDL
)) {
274 host_hash_delete (host_uid_hash
,
275 hd
-> client_identifier
.data
,
276 hd
-> client_identifier
.len
, MDL
);
279 for (foo
= hp
; foo
; foo
= foo
-> n_ipaddr
) {
286 host_dereference (&np
-> n_ipaddr
, MDL
);
287 host_reference (&np
-> n_ipaddr
,
288 hd
-> n_ipaddr
, MDL
);
291 host_dereference (&hp
, MDL
);
296 if (hd
-> n_ipaddr
) {
297 if (uid_head
&& hd
-> n_ipaddr
-> client_identifier
.len
) {
300 hd
-> n_ipaddr
-> client_identifier
.data
,
301 hd
-> n_ipaddr
-> client_identifier
.len
,
302 hd
-> n_ipaddr
, MDL
);
304 if (hw_head
&& hd
-> n_ipaddr
-> interface
.hlen
) {
305 host_hash_add (host_hw_addr_hash
,
306 hd
-> n_ipaddr
-> interface
.hbuf
,
307 hd
-> n_ipaddr
-> interface
.hlen
,
308 hd
-> n_ipaddr
, MDL
);
310 host_dereference (&hd
-> n_ipaddr
, MDL
);
313 if (host_name_hash
) {
314 if (host_hash_lookup (&hp
, host_name_hash
,
315 (unsigned char *)hd
-> name
,
316 strlen (hd
-> name
), MDL
)) {
317 if (hp
== hd
&& !(hp
-> flags
& HOST_DECL_STATIC
)) {
318 host_hash_delete (host_name_hash
,
319 (unsigned char *)hd
-> name
,
320 strlen (hd
-> name
), MDL
);
322 host_dereference (&hp
, MDL
);
327 if (!write_host (hd
))
328 return ISC_R_IOERROR
;
329 if (!commit_leases ())
330 return ISC_R_IOERROR
;
332 return ISC_R_SUCCESS
;
335 int find_hosts_by_haddr (struct host_decl
**hp
, int htype
,
336 const unsigned char *haddr
, unsigned hlen
,
337 const char *file
, int line
)
339 struct host_decl
*foo
;
344 memcpy (&h
.hbuf
[1], haddr
, hlen
);
346 return host_hash_lookup (hp
, host_hw_addr_hash
,
347 h
.hbuf
, h
.hlen
, file
, line
);
350 int find_hosts_by_uid (struct host_decl
**hp
,
351 const unsigned char *data
, unsigned len
,
352 const char *file
, int line
)
354 return host_hash_lookup (hp
, host_uid_hash
, data
, len
, file
, line
);
357 /* More than one host_decl can be returned by find_hosts_by_haddr or
358 find_hosts_by_uid, and each host_decl can have multiple addresses.
359 Loop through the list of hosts, and then for each host, through the
360 list of addresses, looking for an address that's in the same shared
361 network as the one specified. Store the matching address through
362 the addr pointer, update the host pointer to point at the host_decl
363 that matched, and return the subnet that matched. */
365 int find_host_for_network (struct subnet
**sp
, struct host_decl
**host
,
366 struct iaddr
*addr
, struct shared_network
*share
)
369 struct subnet
*subnet
;
370 struct iaddr ip_address
;
371 struct host_decl
*hp
;
372 struct data_string fixed_addr
;
374 memset (&fixed_addr
, 0, sizeof fixed_addr
);
376 for (hp
= *host
; hp
; hp
= hp
-> n_ipaddr
) {
377 if (!hp
-> fixed_addr
)
379 if (!evaluate_option_cache (&fixed_addr
, (struct packet
*)0,
381 (struct client_state
*)0,
382 (struct option_state
*)0,
383 (struct option_state
*)0,
385 hp
-> fixed_addr
, MDL
))
387 for (i
= 0; i
< fixed_addr
.len
; i
+= 4) {
389 memcpy (ip_address
.iabuf
,
390 fixed_addr
.data
+ i
, 4);
391 if (find_grouped_subnet (sp
, share
, ip_address
, MDL
)) {
392 struct host_decl
*tmp
= (struct host_decl
*)0;
394 /* This is probably not necessary, but
395 just in case *host is the only reference
396 to that host declaration, make a temporary
397 reference so that dereferencing it doesn't
398 dereference hp out from under us. */
399 host_reference (&tmp
, *host
, MDL
);
400 host_dereference (host
, MDL
);
401 host_reference (host
, hp
, MDL
);
402 host_dereference (&tmp
, MDL
);
403 data_string_forget (&fixed_addr
, MDL
);
407 data_string_forget (&fixed_addr
, MDL
);
412 void new_address_range (low
, high
, subnet
, pool
)
413 struct iaddr low
, high
;
414 struct subnet
*subnet
;
417 struct lease
*address_range
, *lp
, *plp
;
419 unsigned min
, max
, i
;
420 char lowbuf
[16], highbuf
[16], netbuf
[16];
421 struct shared_network
*share
= subnet
-> shared_network
;
423 struct lease
*lt
= (struct lease
*)0;
425 /* All subnets should have attached shared network structures. */
427 strcpy (netbuf
, piaddr (subnet
-> net
));
428 log_fatal ("No shared network for network %s (%s)",
429 netbuf
, piaddr (subnet
-> netmask
));
432 /* Initialize the hash table if it hasn't been done yet. */
433 if (!lease_uid_hash
) {
435 new_hash ((hash_reference
)lease_reference
,
436 (hash_dereference
)lease_dereference
, 0);
438 log_fatal ("Can't allocate lease/uid hash");
440 if (!lease_ip_addr_hash
) {
442 new_hash ((hash_reference
)lease_reference
,
443 (hash_dereference
)lease_dereference
, 0);
445 log_fatal ("Can't allocate lease/ip hash");
447 if (!lease_hw_addr_hash
) {
449 new_hash ((hash_reference
)lease_reference
,
450 (hash_dereference
)lease_dereference
, 0);
452 log_fatal ("Can't allocate lease/hw hash");
455 /* Make sure that high and low addresses are in same subnet. */
456 net
= subnet_number (low
, subnet
-> netmask
);
457 if (!addr_eq (net
, subnet_number (high
, subnet
-> netmask
))) {
458 strcpy (lowbuf
, piaddr (low
));
459 strcpy (highbuf
, piaddr (high
));
460 strcpy (netbuf
, piaddr (subnet
-> netmask
));
461 log_fatal ("Address range %s to %s, netmask %s spans %s!",
462 lowbuf
, highbuf
, netbuf
, "multiple subnets");
465 /* Make sure that the addresses are on the correct subnet. */
466 if (!addr_eq (net
, subnet
-> net
)) {
467 strcpy (lowbuf
, piaddr (low
));
468 strcpy (highbuf
, piaddr (high
));
469 strcpy (netbuf
, piaddr (subnet
-> netmask
));
470 log_fatal ("Address range %s to %s not on net %s/%s!",
471 lowbuf
, highbuf
, piaddr (subnet
-> net
), netbuf
);
474 /* Get the high and low host addresses... */
475 max
= host_addr (high
, subnet
-> netmask
);
476 min
= host_addr (low
, subnet
-> netmask
);
478 /* Allow range to be specified high-to-low as well as low-to-high. */
481 min
= host_addr (high
, subnet
-> netmask
);
484 /* Get a lease structure for each address in the range. */
485 #if defined (COMPACT_LEASES)
486 address_range
= new_leases (max
- min
+ 1, MDL
);
487 if (!address_range
) {
488 strcpy (lowbuf
, piaddr (low
));
489 strcpy (highbuf
, piaddr (high
));
490 log_fatal ("No memory for address range %s-%s.",
495 /* Fill out the lease structures with some minimal information. */
496 for (i
= 0; i
< max
- min
+ 1; i
++) {
497 struct lease
*lp
= (struct lease
*)0;
498 #if defined (COMPACT_LEASES)
499 omapi_object_initialize ((omapi_object_t
*)&address_range
[i
],
501 0, sizeof (struct lease
), MDL
);
502 lease_reference (&lp
, &address_range
[i
], MDL
);
504 status
= lease_allocate (&lp
, MDL
);
505 if (status
!= ISC_R_SUCCESS
)
506 log_fatal ("No memory for lease %s: %s",
507 piaddr (ip_addr (subnet
-> net
,
510 isc_result_totext (status
));
512 lp
-> ip_addr
= ip_addr (subnet
-> net
,
513 subnet
-> netmask
, i
+ min
);
514 lp
-> starts
= lp
-> timestamp
= MIN_TIME
;
515 lp
-> ends
= MIN_TIME
;
516 subnet_reference (&lp
-> subnet
, subnet
, MDL
);
517 pool_reference (&lp
-> pool
, pool
, MDL
);
518 lp
-> binding_state
= FTS_FREE
;
519 lp
-> next_binding_state
= FTS_FREE
;
522 /* Remember the lease in the IP address hash. */
523 if (find_lease_by_ip_addr (<
, lp
-> ip_addr
, MDL
)) {
525 log_error ("duplicate entries for lease %s",
526 piaddr (lp
-> ip_addr
));
528 pool_reference (<
-> pool
, pool
, MDL
);
529 lease_dereference (<
, MDL
);
531 lease_hash_add (lease_ip_addr_hash
,
533 lp
-> ip_addr
.len
, lp
, MDL
);
534 lease_dereference (&lp
, MDL
);
539 #if defined (COMPACT_LEASES)
540 struct lease
*free_leases
;
542 /* If we are allocating leases in aggregations, there's really no way
543 to free one, although perhaps we can maintain a free list. */
545 isc_result_t
dhcp_lease_free (omapi_object_t
*lo
,
546 const char *file
, int line
)
549 if (lo
-> type
!= dhcp_type_lease
)
550 return ISC_R_INVALIDARG
;
551 lease
= (struct lease
*)lo
;
552 lease
-> next
= free_leases
;
554 return ISC_R_SUCCESS
;
557 isc_result_t
dhcp_lease_get (omapi_object_t
**lp
,
558 const char *file
, int line
)
560 struct lease
**lease
= (struct lease
**)lp
;
565 free_leases
= lt
-> next
;
567 return ISC_R_SUCCESS
;
569 return ISC_R_NOMEMORY
;
573 int find_subnet (struct subnet
**sp
,
574 struct iaddr addr
, const char *file
, int line
)
578 for (rv
= subnets
; rv
; rv
= rv
-> next_subnet
) {
579 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
580 if (subnet_reference (sp
, rv
,
581 file
, line
) != ISC_R_SUCCESS
)
589 int find_grouped_subnet (struct subnet
**sp
,
590 struct shared_network
*share
, struct iaddr addr
,
591 const char *file
, int line
)
595 for (rv
= share
-> subnets
; rv
; rv
= rv
-> next_sibling
) {
596 if (addr_eq (subnet_number (addr
, rv
-> netmask
), rv
-> net
)) {
597 if (subnet_reference (sp
, rv
,
598 file
, line
) != ISC_R_SUCCESS
)
606 int subnet_inner_than (subnet
, scan
, warnp
)
607 struct subnet
*subnet
, *scan
;
610 if (addr_eq (subnet_number (subnet
-> net
, scan
-> netmask
),
612 addr_eq (subnet_number (scan
-> net
, subnet
-> netmask
),
616 for (i
= 0; i
< 32; i
++)
617 if (subnet
-> netmask
.iabuf
[3 - (i
>> 3)]
620 for (j
= 0; j
< 32; j
++)
621 if (scan
-> netmask
.iabuf
[3 - (j
>> 3)] &
624 strcpy (n1buf
, piaddr (subnet
-> net
));
626 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
627 "Warning: ", n1buf
, 32 - i
,
628 piaddr (scan
-> net
), 32 - j
);
635 /* Enter a new subnet into the subnet list. */
636 void enter_subnet (subnet
)
637 struct subnet
*subnet
;
639 struct subnet
*scan
, *prev
= (struct subnet
*)0;
641 /* Check for duplicates... */
642 for (scan
= subnets
; scan
; scan
= scan
-> next_subnet
) {
643 /* When we find a conflict, make sure that the
644 subnet with the narrowest subnet mask comes
646 if (subnet_inner_than (subnet
, scan
, 1)) {
648 subnet_reference (&prev
-> next_subnet
,
651 subnet_reference (&subnets
, subnet
, MDL
);
652 subnet_reference (&subnet
-> next_subnet
, scan
, MDL
);
658 /* XXX use the BSD radix tree code instead of a linked list. */
659 subnet
-> next_subnet
= subnets
;
663 /* Enter a new shared network into the shared network list. */
665 void enter_shared_network (share
)
666 struct shared_network
*share
;
668 if (shared_networks
) {
669 shared_network_reference (&share
-> next
,
670 shared_networks
, MDL
);
671 shared_network_dereference (&shared_networks
, MDL
);
673 shared_network_reference (&shared_networks
, share
, MDL
);
676 void new_shared_network_interface (cfile
, share
, name
)
678 struct shared_network
*share
;
681 struct interface_info
*ip
;
684 if (share
-> interface
) {
686 "A subnet or shared network can't be connected %s",
687 "to two interfaces.");
691 for (ip
= interfaces
; ip
; ip
= ip
-> next
)
692 if (!strcmp (ip
-> name
, name
))
695 status
= interface_allocate (&ip
, MDL
);
696 if (status
!= ISC_R_SUCCESS
)
697 log_fatal ("new_shared_network_interface %s: %s",
698 name
, isc_result_totext (status
));
699 if (strlen (name
) > sizeof ip
-> name
) {
700 memcpy (ip
-> name
, name
, (sizeof ip
-> name
) - 1);
701 ip
-> name
[(sizeof ip
-> name
) - 1] = 0;
703 strcpy (ip
-> name
, name
);
705 interface_reference (&ip
-> next
, interfaces
, MDL
);
706 interface_dereference (&interfaces
, MDL
);
708 interface_reference (&interfaces
, ip
, MDL
);
709 ip
-> flags
= INTERFACE_REQUESTED
;
710 /* XXX this is a reference loop. */
711 shared_network_reference (&ip
-> shared_network
, share
, MDL
);
712 interface_reference (&share
-> interface
, ip
, MDL
);
716 /* Enter a lease into the system. This is called by the parser each
717 time it reads in a new lease. If the subnet for that lease has
718 already been read in (usually the case), just update that lease;
719 otherwise, allocate temporary storage for the lease and keep it around
720 until we're done reading in the config file. */
722 void enter_lease (lease
)
725 struct lease
*comp
= (struct lease
*)0;
728 if (find_lease_by_ip_addr (&comp
, lease
-> ip_addr
, MDL
)) {
730 log_error ("undeclared lease found in database: %s",
731 piaddr (lease
-> ip_addr
));
733 pool_reference (&lease
-> pool
, comp
-> pool
, MDL
);
736 subnet_reference (&lease
-> subnet
,
737 comp
-> subnet
, MDL
);
738 lease_hash_delete (lease_ip_addr_hash
,
739 lease
-> ip_addr
.iabuf
,
740 lease
-> ip_addr
.len
, MDL
);
741 lease_dereference (&comp
, MDL
);
744 /* The only way a lease can get here without a subnet is if it's in
745 the lease file, but not in the dhcpd.conf file. In this case, we
746 *should* keep it around until it's expired, but never reallocate it
747 or renew it. Currently, to maintain consistency, we are not doing
749 XXX fix this so that the lease is kept around until it expires.
750 XXX this will be important in IPv6 with addresses that become
751 XXX non-renewable as a result of a renumbering event. */
753 if (!lease
-> subnet
) {
754 log_error ("lease %s: no subnet.", piaddr (lease
-> ip_addr
));
757 lease_hash_add (lease_ip_addr_hash
,
758 lease
-> ip_addr
.iabuf
,
759 lease
-> ip_addr
.len
, lease
, MDL
);
762 /* Replace the data in an existing lease with the data in a new lease;
763 adjust hash tables to suit, and insertion sort the lease into the
764 list of leases by expiry time so that we can always find the oldest
767 int supersede_lease (comp
, lease
, commit
, propogate
, pimmediate
)
768 struct lease
*comp
, *lease
;
774 int enter_hwaddr
= 0;
775 struct lease
*lp
, **lq
, *prev
;
778 /* If there is no sample lease, just do the move. */
782 /* Static leases are not currently kept in the database... */
783 if (lease
-> flags
& STATIC_LEASE
)
786 /* If the existing lease hasn't expired and has a different
787 unique identifier or, if it doesn't have a unique
788 identifier, a different hardware address, then the two
789 leases are in conflict. If the existing lease has a uid
790 and the new one doesn't, but they both have the same
791 hardware address, and dynamic bootp is allowed on this
792 lease, then we allow that, in case a dynamic BOOTP lease is
793 requested *after* a DHCP lease has been assigned. */
795 if (lease
-> binding_state
!= FTS_ABANDONED
&&
796 (comp
-> binding_state
== FTS_ACTIVE
||
797 comp
-> binding_state
== FTS_RESERVED
||
798 comp
-> binding_state
== FTS_BOOTP
) &&
799 (((comp
-> uid
&& lease
-> uid
) &&
800 (comp
-> uid_len
!= lease
-> uid_len
||
801 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
803 ((comp
-> hardware_addr
.hlen
!=
804 lease
-> hardware_addr
.hlen
) ||
805 memcmp (comp
-> hardware_addr
.hbuf
,
806 lease
-> hardware_addr
.hbuf
,
807 comp
-> hardware_addr
.hlen
))))) {
808 log_error ("Lease conflict at %s",
809 piaddr (comp
-> ip_addr
));
813 /* If there's a Unique ID, dissociate it from the hash
814 table and free it if necessary. */
816 uid_hash_delete (comp
);
818 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
819 dfree (comp
-> uid
, MDL
);
823 comp
-> uid
= (unsigned char *)0;
827 if (comp
-> hardware_addr
.hlen
&&
828 ((comp
-> hardware_addr
.hlen
!=
829 lease
-> hardware_addr
.hlen
) ||
830 memcmp (comp
-> hardware_addr
.hbuf
,
831 lease
-> hardware_addr
.hbuf
,
832 comp
-> hardware_addr
.hlen
))) {
833 hw_hash_delete (comp
);
835 } else if (!comp
-> hardware_addr
.hlen
)
838 /* If the lease has been billed to a class, remove the billing. */
839 if (comp
-> billing_class
!= lease
-> billing_class
) {
840 if (comp
-> billing_class
)
841 unbill_class (comp
, comp
-> billing_class
);
842 if (lease
-> billing_class
)
843 bill_class (comp
, lease
-> billing_class
);
846 /* Copy the data files, but not the linkages. */
847 comp
-> starts
= lease
-> starts
;
849 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
850 memcpy (comp
-> uid_buf
,
851 lease
-> uid
, lease
-> uid_len
);
852 comp
-> uid
= &comp
-> uid_buf
[0];
853 comp
-> uid_max
= sizeof comp
-> uid_buf
;
854 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
855 comp
-> uid
= lease
-> uid
;
856 comp
-> uid_max
= lease
-> uid_max
;
857 lease
-> uid
= (unsigned char *)0;
858 lease
-> uid_max
= 0;
860 log_fatal ("corrupt lease uid."); /* XXX */
863 comp
-> uid
= (unsigned char *)0;
866 comp
-> uid_len
= lease
-> uid_len
;
868 host_dereference (&comp
-> host
, MDL
);
869 host_reference (&comp
-> host
, lease
-> host
, MDL
);
870 comp
-> hardware_addr
= lease
-> hardware_addr
;
871 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
872 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
874 binding_scope_dereference (&comp
-> scope
, MDL
);
875 if (lease
-> scope
) {
876 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
877 binding_scope_dereference (&lease
-> scope
, MDL
);
880 if (comp
-> agent_options
)
881 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
882 if (lease
-> agent_options
) {
883 /* Only retain the agent options if the lease is still
884 affirmatively associated with a client. */
885 if (lease
-> next_binding_state
== FTS_ACTIVE
||
886 lease
-> next_binding_state
== FTS_EXPIRED
||
887 lease
-> next_binding_state
== FTS_RESERVED
||
888 lease
-> next_binding_state
== FTS_BOOTP
)
889 option_chain_head_reference (&comp
-> agent_options
,
890 lease
-> agent_options
,
892 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
895 /* Record the hostname information in the lease. */
896 if (comp
-> hostname
)
897 dfree (comp
-> hostname
, MDL
);
898 comp
-> hostname
= lease
-> hostname
;
899 lease
-> hostname
= (char *)0;
900 if (comp
-> client_hostname
)
901 dfree (comp
-> client_hostname
, MDL
);
902 comp
-> client_hostname
= lease
-> client_hostname
;
903 lease
-> client_hostname
= (char *)0;
905 if (lease
-> on_expiry
) {
906 if (comp
-> on_expiry
)
907 executable_statement_dereference (&comp
-> on_expiry
,
909 executable_statement_reference (&comp
-> on_expiry
,
913 if (lease
-> on_commit
) {
914 if (comp
-> on_commit
)
915 executable_statement_dereference (&comp
-> on_commit
,
917 executable_statement_reference (&comp
-> on_commit
,
921 if (lease
-> on_release
) {
922 if (comp
-> on_release
)
923 executable_statement_dereference (&comp
-> on_release
,
925 executable_statement_reference (&comp
-> on_release
,
926 lease
-> on_release
, MDL
);
929 /* Record the lease in the uid hash if necessary. */
930 if (enter_uid
&& lease
-> uid
) {
934 /* Record it in the hardware address hash if necessary. */
935 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
939 #if defined (FAILOVER_PROTOCOL)
940 comp
-> cltt
= lease
-> cltt
;
941 comp
-> tstp
= lease
-> tstp
;
942 comp
-> tsfp
= lease
-> tsfp
;
943 #endif /* FAILOVER_PROTOCOL */
944 comp
-> ends
= lease
-> ends
;
945 comp
-> next_binding_state
= lease
-> next_binding_state
;
949 log_error ("Supersede_lease: lease %s with no pool.",
950 piaddr (comp
-> ip_addr
));
954 /* Figure out which queue it's on. */
955 switch (comp
-> binding_state
) {
957 lq
= &comp
-> pool
-> free
;
958 comp
-> pool
-> free_leases
--;
964 lq
= &comp
-> pool
-> active
;
970 lq
= &comp
-> pool
-> expired
;
974 lq
= &comp
-> pool
-> abandoned
;
978 lq
= &comp
-> pool
-> backup
;
979 comp
-> pool
-> backup_leases
--;
983 log_error ("Lease with bogus binding state: %d",
984 comp
-> binding_state
);
988 /* Remove the lease from its current place in its current
990 prev
= (struct lease
*)0;
991 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
998 log_error ("Lease with binding state %s not on its queue.",
999 (comp
-> binding_state
< 1 &&
1000 comp
-> binding_state
< FTS_BOOTP
)
1002 : binding_state_names
[comp
-> binding_state
- 1]);
1007 lease_dereference (&prev
-> next
, MDL
);
1009 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1010 lease_dereference (&comp
-> next
, MDL
);
1013 lease_dereference (lq
, MDL
);
1015 lease_reference (lq
, comp
-> next
, MDL
);
1016 lease_dereference (&comp
-> next
, MDL
);
1020 /* Make the state transition. */
1022 process_state_transition (comp
);
1024 /* Put the lease back on the appropriate queue. If the lease
1025 is corrupt (as detected by lease_enqueue), don't go any farther. */
1026 if (!lease_enqueue (comp
))
1029 /* If this is the next lease that will timeout on the pool,
1030 zap the old timeout and set the timeout on this pool to the
1031 time that the lease's next event will happen.
1033 We do not actually set the timeout unless commit is true -
1034 we don't want to thrash the timer queue when reading the
1035 lease database. Instead, the database code calls the
1036 expiry event on each pool after reading in the lease file,
1037 and the expiry code sets the timer if there's anything left
1038 to expire after it's run any outstanding expiry events on
1041 comp
-> sort_time
!= MIN_TIME
&&
1042 comp
-> sort_time
> cur_time
&&
1043 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1044 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1045 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1046 add_timeout (comp
-> pool
-> next_event_time
,
1047 pool_timer
, comp
-> pool
,
1048 (tvref_t
)pool_reference
,
1049 (tvunref_t
)pool_dereference
);
1052 /* Return zero if we didn't commit the lease to permanent storage;
1053 nonzero if we did. */
1054 return commit
&& write_lease (comp
) && commit_leases ()
1055 #if defined (FAILOVER_PROTOCOL)
1057 dhcp_failover_queue_update (comp
, pimmediate
))
1062 void process_state_transition (struct lease
*lease
)
1064 #if defined (FAILOVER_PROTOCOL)
1065 dhcp_failover_state_t
*peer
;
1067 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1068 peer
= lease
-> pool
-> failover_peer
;
1070 peer
= (dhcp_failover_state_t
*)0;
1073 /* If the lease was active and is now no longer active, but isn't
1074 released, then it just expired, so do the expiry event. */
1075 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1077 #if defined (FAILOVER_PROTOCOL)
1079 lease
-> binding_state
== FTS_EXPIRED
&&
1080 (lease
-> next_binding_state
== FTS_FREE
||
1081 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1084 (lease
-> binding_state
== FTS_ACTIVE
||
1085 lease
-> binding_state
== FTS_BOOTP
||
1086 lease
-> binding_state
== FTS_RESERVED
) &&
1087 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1088 ddns_removals (lease
);
1089 if (lease
-> on_expiry
) {
1090 execute_statements ((struct binding_value
**)0,
1091 (struct packet
*)0, lease
,
1092 (struct client_state
*)0,
1093 (struct option_state
*)0,
1094 (struct option_state
*)0, /* XXX */
1096 lease
-> on_expiry
);
1097 if (lease
-> on_expiry
)
1098 executable_statement_dereference
1099 (&lease
-> on_expiry
, MDL
);
1102 /* No sense releasing a lease after it's expired. */
1103 if (lease
-> on_release
)
1104 executable_statement_dereference (&lease
-> on_release
,
1106 /* Send the expiry time to the peer. */
1107 lease
-> tstp
= lease
-> ends
;
1110 /* If the lease was active and is now released, do the release
1112 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1114 #if defined (FAILOVER_PROTOCOL)
1116 lease
-> binding_state
== FTS_RELEASED
&&
1117 (lease
-> next_binding_state
== FTS_FREE
||
1118 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1121 (lease
-> binding_state
== FTS_ACTIVE
||
1122 lease
-> binding_state
== FTS_BOOTP
||
1123 lease
-> binding_state
== FTS_RESERVED
) &&
1124 lease
-> next_binding_state
== FTS_RELEASED
))) {
1125 ddns_removals (lease
);
1126 if (lease
-> on_release
) {
1127 execute_statements ((struct binding_value
**)0,
1128 (struct packet
*)0, lease
,
1129 (struct client_state
*)0,
1130 (struct option_state
*)0,
1131 (struct option_state
*)0, /* XXX */
1133 lease
-> on_release
);
1134 executable_statement_dereference (&lease
-> on_release
,
1138 /* A released lease can't expire. */
1139 if (lease
-> on_expiry
)
1140 executable_statement_dereference (&lease
-> on_expiry
,
1143 /* Send the release time (should be == cur_time) to the
1145 lease
-> tstp
= lease
-> ends
;
1148 lease
-> binding_state
= lease
-> next_binding_state
;
1149 if (lease
-> binding_state
== FTS_ACTIVE
||
1150 lease
-> binding_state
== FTS_BACKUP
) {
1151 #if defined (FAILOVER_PROTOCOL)
1152 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1153 lease
-> next_binding_state
= FTS_EXPIRED
;
1156 lease
-> next_binding_state
= FTS_FREE
;
1160 /* Copy the contents of one lease into another, correctly maintaining
1161 reference counts. */
1162 int lease_copy (struct lease
**lp
,
1163 struct lease
*lease
, const char *file
, int line
)
1165 struct lease
*lt
= (struct lease
*)0;
1166 isc_result_t status
;
1168 status
= lease_allocate (<
, MDL
);
1169 if (status
!= ISC_R_SUCCESS
)
1172 lt
-> ip_addr
= lease
-> ip_addr
;
1173 lt
-> starts
= lease
-> starts
;
1174 lt
-> ends
= lease
-> ends
;
1175 lt
-> timestamp
= lease
-> timestamp
;
1176 lt
-> uid_len
= lease
-> uid_len
;
1177 lt
-> uid_max
= lease
-> uid_max
;
1178 if (lease
-> uid
== lease
-> uid_buf
) {
1179 lt
-> uid
= lt
-> uid_buf
;
1180 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1182 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1184 lease_dereference (<
, MDL
);
1187 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1189 if (lease
-> hostname
) {
1190 lt
-> hostname
= dmalloc (strlen (lease
-> hostname
) + 1, MDL
);
1191 if (!lt
-> hostname
) {
1192 lease_dereference (<
, MDL
);
1195 strcpy (lt
-> hostname
, lease
-> hostname
);
1197 if (lease
-> client_hostname
) {
1198 lt
-> client_hostname
=
1199 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1200 if (!lt
-> client_hostname
) {
1201 lease_dereference (<
, MDL
);
1204 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1207 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1208 if (lease
-> agent_options
)
1209 option_chain_head_reference (<
-> agent_options
,
1210 lease
-> agent_options
, MDL
);
1211 host_reference (<
-> host
, lease
-> host
, file
, line
);
1212 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1213 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1214 class_reference (<
-> billing_class
,
1215 lease
-> billing_class
, file
, line
);
1216 lt
-> hardware_addr
= lease
-> hardware_addr
;
1217 if (lease
-> on_expiry
)
1218 executable_statement_reference (<
-> on_expiry
,
1221 if (lease
-> on_commit
)
1222 executable_statement_reference (<
-> on_commit
,
1225 if (lease
-> on_release
)
1226 executable_statement_reference (<
-> on_release
,
1227 lease
-> on_release
,
1229 lt
-> flags
= lease
-> flags
;
1230 lt
-> tstp
= lease
-> tstp
;
1231 lt
-> tsfp
= lease
-> tsfp
;
1232 lt
-> cltt
= lease
-> cltt
;
1233 lt
-> binding_state
= lease
-> binding_state
;
1234 lt
-> next_binding_state
= lease
-> next_binding_state
;
1235 status
= lease_reference (lp
, lt
, file
, line
);
1236 lease_dereference (<
, MDL
);
1237 return status
== ISC_R_SUCCESS
;
1240 /* Release the specified lease and re-hash it as appropriate. */
1241 void release_lease (lease
, packet
)
1242 struct lease
*lease
;
1243 struct packet
*packet
;
1245 /* If there are statements to execute when the lease is
1246 released, execute them. */
1247 ddns_removals (lease
);
1248 if (lease
-> on_release
) {
1249 execute_statements ((struct binding_value
**)0,
1250 packet
, lease
, (struct client_state
*)0,
1252 (struct option_state
*)0, /* XXX */
1253 &lease
-> scope
, lease
-> on_release
);
1254 if (lease
-> on_release
)
1255 executable_statement_dereference (&lease
-> on_release
,
1259 /* We do either the on_release or the on_expiry events, but
1260 not both (it's possible that they could be the same,
1262 if (lease
-> on_expiry
)
1263 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1265 if (lease
-> ends
> cur_time
) {
1266 if (lease
-> on_commit
)
1267 executable_statement_dereference (&lease
-> on_commit
,
1270 /* Blow away any bindings. */
1272 binding_scope_dereference (&lease
-> scope
, MDL
);
1273 lease
-> ends
= cur_time
;
1274 #if defined (FAILOVER_PROTOCOL)
1275 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1276 lease
-> next_binding_state
= FTS_RELEASED
;
1278 lease
-> next_binding_state
= FTS_FREE
;
1281 lease
-> next_binding_state
= FTS_FREE
;
1283 if (lease
-> billing_class
)
1284 class_dereference (&lease
-> billing_class
, MDL
);
1285 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1289 /* Abandon the specified lease (set its timeout to infinity and its
1290 particulars to zero, and re-hash it as appropriate. */
1292 void abandon_lease (lease
, message
)
1293 struct lease
*lease
;
1294 const char *message
;
1296 struct lease
*lt
= (struct lease
*)0;
1298 if (!lease_copy (<
, lease
, MDL
))
1302 if (lt
-> on_expiry
)
1303 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1304 if (lt
-> on_release
)
1305 executable_statement_dereference (&lease
-> on_release
, MDL
);
1306 if (lt
-> on_commit
)
1307 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1309 /* Blow away any bindings. */
1311 binding_scope_dereference (<
-> scope
, MDL
);
1314 lt
-> ends
= cur_time
; /* XXX */
1315 lt
-> next_binding_state
= FTS_ABANDONED
;
1317 log_error ("Abandoning IP address %s: %s",
1318 piaddr (lease
-> ip_addr
), message
);
1319 lt
-> hardware_addr
.hlen
= 0;
1320 if (lt
-> uid
!= lt
-> uid_buf
)
1321 dfree (lt
-> uid
, MDL
);
1322 lt
-> uid
= (unsigned char *)0;
1325 if (lt
-> billing_class
)
1326 class_dereference (<
-> billing_class
, MDL
);
1327 supersede_lease (lease
, lt
, 1, 1, 1);
1328 lease_dereference (<
, MDL
);
1331 /* Abandon the specified lease (set its timeout to infinity and its
1332 particulars to zero, and re-hash it as appropriate. */
1334 void dissociate_lease (lease
)
1335 struct lease
*lease
;
1337 struct lease
*lt
= (struct lease
*)0;
1339 if (!lease_copy (<
, lease
, MDL
))
1343 if (lt
-> on_expiry
)
1344 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1345 if (lt
-> on_release
)
1346 executable_statement_dereference (&lease
-> on_release
, MDL
);
1347 if (lt
-> on_commit
)
1348 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1350 /* Blow away any bindings. */
1352 binding_scope_dereference (<
-> scope
, MDL
);
1355 #if defined (FAILOVER_PROTOCOL)
1356 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1357 lt
-> next_binding_state
= FTS_RESET
;
1359 lt
-> next_binding_state
= FTS_FREE
;
1362 lt
-> next_binding_state
= FTS_FREE
;
1364 lt
-> ends
= cur_time
; /* XXX */
1365 lt
-> hardware_addr
.hlen
= 0;
1366 if (lt
-> uid
!= lt
-> uid_buf
)
1367 dfree (lt
-> uid
, MDL
);
1368 lt
-> uid
= (unsigned char *)0;
1371 if (lt
-> billing_class
)
1372 class_dereference (<
-> billing_class
, MDL
);
1373 supersede_lease (lease
, lt
, 1, 1, 1);
1374 lease_dereference (<
, MDL
);
1377 /* Timer called when a lease in a particular pool expires. */
1378 void pool_timer (vpool
)
1382 struct lease
*lt
= (struct lease
*)0;
1383 struct lease
*next
= (struct lease
*)0;
1384 struct lease
*lease
= (struct lease
*)0;
1385 struct lease
**lptr
[5];
1386 TIME next_expiry
= MAX_TIME
;
1389 pool
= (struct pool
*)vpool
;
1391 #define FREE_LEASES 0
1392 lptr
[FREE_LEASES
] = &pool
-> free
;
1393 #define ACTIVE_LEASES 1
1394 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1395 #define EXPIRED_LEASES 2
1396 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1397 #define ABANDONED_LEASES 3
1398 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1399 #define BACKUP_LEASES 4
1400 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1402 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1403 /* If there's nothing on the queue, skip it. */
1407 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1410 /* Remember the next lease in the list. */
1412 lease_dereference (&next
, MDL
);
1414 lease_reference (&next
, lease
-> next
, MDL
);
1416 /* If we've run out of things to expire on this list,
1418 if (lease
-> sort_time
> cur_time
) {
1419 if (lease
-> sort_time
< next_expiry
)
1420 next_expiry
= lease
-> sort_time
;
1424 /* If there is a pending state change, and
1425 this lease has gotten to the time when the
1426 state change should happen, just call
1427 supersede_lease on it to make the change
1429 if (lease
-> next_binding_state
!=
1430 lease
-> binding_state
)
1431 supersede_lease (lease
,
1432 (struct lease
*)0, 1, 1, 1);
1434 lease_dereference (&lease
, MDL
);
1436 lease_reference (&lease
, next
, MDL
);
1439 lease_dereference (&next
, MDL
);
1441 lease_dereference (&lease
, MDL
);
1443 if (next_expiry
!= MAX_TIME
) {
1444 pool
-> next_event_time
= next_expiry
;
1445 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1446 (tvref_t
)pool_reference
,
1447 (tvunref_t
)pool_dereference
);
1449 pool
-> next_event_time
= MIN_TIME
;
1453 /* Locate the lease associated with a given IP address... */
1455 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1456 const char *file
, int line
)
1458 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1459 addr
.iabuf
, addr
.len
, file
, line
);
1462 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1463 unsigned len
, const char *file
, int line
)
1467 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1470 int find_lease_by_hw_addr (struct lease
**lp
,
1471 const unsigned char *hwaddr
, unsigned hwlen
,
1472 const char *file
, int line
)
1476 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1477 hwaddr
, hwlen
, file
, line
);
1480 /* Add the specified lease to the uid hash. */
1482 void uid_hash_add (lease
)
1483 struct lease
*lease
;
1485 struct lease
*head
= (struct lease
*)0;
1489 /* If it's not in the hash, just add it. */
1490 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1491 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1492 lease
-> uid_len
, lease
, MDL
);
1494 /* Otherwise, attach it to the end of the list. */
1495 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
)
1497 lease_reference (&scan
-> n_uid
, lease
, MDL
);
1498 lease_dereference (&head
, MDL
);
1502 /* Delete the specified lease from the uid hash. */
1504 void uid_hash_delete (lease
)
1505 struct lease
*lease
;
1507 struct lease
*head
= (struct lease
*)0;
1510 /* If it's not in the hash, we have no work to do. */
1511 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1513 lease_dereference (&lease
-> n_uid
, MDL
);
1517 /* If the lease we're freeing is at the head of the list,
1518 remove the hash table entry and add a new one with the
1519 next lease on the list (if there is one). */
1520 if (head
== lease
) {
1521 lease_hash_delete (lease_uid_hash
,
1522 lease
-> uid
, lease
-> uid_len
, MDL
);
1523 if (lease
-> n_uid
) {
1524 lease_hash_add (lease_uid_hash
,
1525 lease
-> n_uid
-> uid
,
1526 lease
-> n_uid
-> uid_len
,
1527 lease
-> n_uid
, MDL
);
1528 lease_dereference (&lease
-> n_uid
, MDL
);
1531 /* Otherwise, look for the lease in the list of leases
1532 attached to the hash table entry, and remove it if
1534 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1535 if (scan
-> n_uid
== lease
) {
1536 lease_dereference (&scan
-> n_uid
, MDL
);
1537 if (lease
-> n_uid
) {
1538 lease_reference (&scan
-> n_uid
,
1539 lease
-> n_uid
, MDL
);
1540 lease_dereference (&lease
-> n_uid
,
1547 lease_dereference (&head
, MDL
);
1550 /* Add the specified lease to the hardware address hash. */
1552 void hw_hash_add (lease
)
1553 struct lease
*lease
;
1555 struct lease
*head
= (struct lease
*)0;
1558 /* If it's not in the hash, just add it. */
1559 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1560 lease
-> hardware_addr
.hlen
, MDL
))
1561 lease_hash_add (lease_hw_addr_hash
,
1562 lease
-> hardware_addr
.hbuf
,
1563 lease
-> hardware_addr
.hlen
,
1566 /* Otherwise, attach it to the end of the list. */
1567 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
)
1569 lease_reference (&scan
-> n_hw
, lease
, MDL
);
1570 lease_dereference (&head
, MDL
);
1574 /* Delete the specified lease from the hardware address hash. */
1576 void hw_hash_delete (lease
)
1577 struct lease
*lease
;
1579 struct lease
*head
= (struct lease
*)0;
1582 /* If it's not in the hash, we have no work to do. */
1583 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1584 lease
-> hardware_addr
.hlen
, MDL
)) {
1586 lease_dereference (&lease
-> n_hw
, MDL
);
1590 /* If the lease we're freeing is at the head of the list,
1591 remove the hash table entry and add a new one with the
1592 next lease on the list (if there is one). */
1593 if (head
== lease
) {
1594 lease_hash_delete (lease_hw_addr_hash
,
1595 lease
-> hardware_addr
.hbuf
,
1596 lease
-> hardware_addr
.hlen
, MDL
);
1597 if (lease
-> n_hw
) {
1598 lease_hash_add (lease_hw_addr_hash
,
1599 lease
-> n_hw
-> hardware_addr
.hbuf
,
1600 lease
-> n_hw
-> hardware_addr
.hlen
,
1601 lease
-> n_hw
, MDL
);
1602 lease_dereference (&lease
-> n_hw
, MDL
);
1605 /* Otherwise, look for the lease in the list of leases
1606 attached to the hash table entry, and remove it if
1608 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
) {
1609 if (scan
-> n_hw
== lease
) {
1610 lease_dereference (&scan
-> n_hw
, MDL
);
1611 if (lease
-> n_hw
) {
1612 lease_reference (&scan
-> n_hw
,
1613 lease
-> n_hw
, MDL
);
1614 lease_dereference (&lease
-> n_hw
,
1621 lease_dereference (&head
, MDL
);
1624 /* Write all interesting leases to permanent storage. */
1626 void write_leases ()
1629 struct shared_network
*s
;
1631 struct host_decl
*hp
;
1632 struct group_object
*gp
;
1633 struct hash_bucket
*hb
;
1636 struct lease
**lptr
[5];
1638 /* Write all the dynamically-created group declarations. */
1639 if (group_name_hash
) {
1641 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1642 for (hb
= group_name_hash
-> buckets
[i
];
1643 hb
; hb
= hb
-> next
) {
1644 gp
= (struct group_object
*)hb
-> value
;
1645 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1646 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1647 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1653 log_info ("Wrote %d group decls to leases file.", num_written
);
1656 /* Write all the deleted host declarations. */
1657 if (host_name_hash
) {
1659 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1660 for (hb
= host_name_hash
-> buckets
[i
];
1661 hb
; hb
= hb
-> next
) {
1662 hp
= (struct host_decl
*)hb
-> value
;
1663 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1664 (hp
-> flags
& HOST_DECL_DELETED
))) {
1670 log_info ("Wrote %d deleted host decls to leases file.",
1674 /* Write all the new, dynamic host declarations. */
1675 if (host_name_hash
) {
1677 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1678 for (hb
= host_name_hash
-> buckets
[i
];
1679 hb
; hb
= hb
-> next
) {
1680 hp
= (struct host_decl
*)hb
-> value
;
1681 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1687 log_info ("Wrote %d new dynamic host decls to leases file.",
1691 #if defined (FAILOVER_PROTOCOL)
1692 /* Write all the failover states. */
1693 dhcp_failover_write_all_states ();
1696 /* Write all the leases. */
1698 for (s
= shared_networks
; s
; s
= s
-> next
) {
1699 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1700 lptr
[FREE_LEASES
] = &p
-> free
;
1701 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1702 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1703 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1704 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1706 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1707 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1708 if (l
-> hardware_addr
.hlen
||
1710 (l
-> binding_state
!= FTS_FREE
)) {
1711 if (!write_lease (l
))
1712 log_fatal ("Can't rewrite lease database");
1719 log_info ("Wrote %d leases to leases file.", num_written
);
1720 if (!commit_leases ())
1721 log_fatal ("Can't commit leases to new database: %m");
1724 int lease_enqueue (struct lease
*comp
)
1726 struct lease
**lq
, *prev
, *lp
;
1728 /* No queue to put it on? */
1732 /* Figure out which queue it's going to. */
1733 switch (comp
-> binding_state
) {
1735 lq
= &comp
-> pool
-> free
;
1736 comp
-> pool
-> free_leases
++;
1737 comp
-> sort_time
= comp
-> ends
;
1743 lq
= &comp
-> pool
-> active
;
1744 comp
-> sort_time
= comp
-> ends
;
1750 lq
= &comp
-> pool
-> expired
;
1751 comp
-> sort_time
= comp
-> ends
;
1756 lq
= &comp
-> pool
-> abandoned
;
1757 comp
-> sort_time
= comp
-> ends
;
1761 lq
= &comp
-> pool
-> backup
;
1762 comp
-> pool
-> backup_leases
++;
1763 comp
-> sort_time
= comp
-> ends
;
1767 log_error ("Lease with bogus binding state: %d",
1768 comp
-> binding_state
);
1772 /* Insertion sort the lease onto the appropriate queue. */
1773 prev
= (struct lease
*)0;
1774 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1775 if (lp
-> sort_time
>= comp
-> sort_time
)
1781 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1782 lease_dereference (&prev
-> next
, MDL
);
1784 lease_reference (&prev
-> next
, comp
, MDL
);
1787 lease_reference (&comp
-> next
, *lq
, MDL
);
1788 lease_dereference (lq
, MDL
);
1790 lease_reference (lq
, comp
, MDL
);
1795 /* For a given lease, sort it onto the right list in its pool and put it
1796 in each appropriate hash, understanding that it's already by definition
1797 in lease_ip_addr_hash. */
1799 void lease_instantiate (const unsigned char *val
, unsigned len
,
1800 struct lease
*lease
)
1803 /* XXX If the lease doesn't have a pool at this point, it's an
1804 XXX orphan, which we *should* keep around until it expires,
1805 XXX but which right now we just forget. */
1806 if (!lease
-> pool
) {
1807 lease_hash_delete (lease_ip_addr_hash
,
1808 lease
-> ip_addr
.iabuf
,
1809 lease
-> ip_addr
.len
, MDL
);
1813 /* Put the lease on the right queue. */
1814 lease_enqueue (lease
);
1816 /* Record the lease in the uid hash if possible. */
1818 uid_hash_add (lease
);
1821 /* Record it in the hardware address hash if possible. */
1822 if (lease
-> hardware_addr
.hlen
) {
1823 hw_hash_add (lease
);
1829 /* Run expiry events on every pool. This is called on startup so that
1830 any expiry events that occurred after the server stopped and before it
1831 was restarted can be run. At the same time, if failover support is
1832 compiled in, we compute the balance of leases for the pool. */
1834 void expire_all_pools ()
1836 struct shared_network
*s
;
1838 struct hash_bucket
*hb
;
1841 struct lease
**lptr
[5];
1843 /* First, go over the hash list and actually put all the leases
1844 on the appropriate lists. */
1845 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1847 /* Loop through each pool in each shared network and call the
1848 expiry routine on the pool. */
1849 for (s
= shared_networks
; s
; s
= s
-> next
) {
1850 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1853 p
-> lease_count
= 0;
1854 p
-> free_leases
= 0;
1855 p
-> backup_leases
= 0;
1857 lptr
[FREE_LEASES
] = &p
-> free
;
1858 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1859 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1860 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1861 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1863 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1864 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1866 if (l
-> ends
<= cur_time
) {
1867 if (l
-> binding_state
== FTS_FREE
)
1869 else if (l
-> binding_state
== FTS_BACKUP
)
1870 p
-> backup_leases
++;
1872 #if defined (FAILOVER_PROTOCOL)
1873 if (p
-> failover_peer
&&
1874 l
-> tstp
> l
-> tsfp
&&
1875 !(l
-> flags
& ON_UPDATE_QUEUE
))
1876 dhcp_failover_queue_update (l
, 1);
1884 void dump_subnets ()
1887 struct shared_network
*s
;
1890 struct lease
**lptr
[5];
1893 log_info ("Subnets:");
1894 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
1895 log_debug (" Subnet %s", piaddr (n
-> net
));
1896 log_debug (" netmask %s",
1897 piaddr (n
-> netmask
));
1899 log_info ("Shared networks:");
1900 for (s
= shared_networks
; s
; s
= s
-> next
) {
1901 log_info (" %s", s
-> name
);
1902 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1903 lptr
[FREE_LEASES
] = &p
-> free
;
1904 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1905 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1906 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1907 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1909 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1910 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1918 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
)
1919 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
)
1920 HASH_FUNCTIONS (class, const char *, struct class)