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.53 2001/02/15 21:34:07 neild 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 defined (FAILOVER_PROTOCOL)
779 /* We must commit leases before sending updates regarding them
780 to failover peers. It is, therefore, an error to set pimmediate
782 if (pimmediate
&& !commit
)
786 /* If there is no sample lease, just do the move. */
790 /* Static leases are not currently kept in the database... */
791 if (lease
-> flags
& STATIC_LEASE
)
794 /* If the existing lease hasn't expired and has a different
795 unique identifier or, if it doesn't have a unique
796 identifier, a different hardware address, then the two
797 leases are in conflict. If the existing lease has a uid
798 and the new one doesn't, but they both have the same
799 hardware address, and dynamic bootp is allowed on this
800 lease, then we allow that, in case a dynamic BOOTP lease is
801 requested *after* a DHCP lease has been assigned. */
803 if (lease
-> binding_state
!= FTS_ABANDONED
&&
804 (comp
-> binding_state
== FTS_ACTIVE
||
805 comp
-> binding_state
== FTS_RESERVED
||
806 comp
-> binding_state
== FTS_BOOTP
) &&
807 (((comp
-> uid
&& lease
-> uid
) &&
808 (comp
-> uid_len
!= lease
-> uid_len
||
809 memcmp (comp
-> uid
, lease
-> uid
, comp
-> uid_len
))) ||
811 ((comp
-> hardware_addr
.hlen
!=
812 lease
-> hardware_addr
.hlen
) ||
813 memcmp (comp
-> hardware_addr
.hbuf
,
814 lease
-> hardware_addr
.hbuf
,
815 comp
-> hardware_addr
.hlen
))))) {
816 log_error ("Lease conflict at %s",
817 piaddr (comp
-> ip_addr
));
821 /* If there's a Unique ID, dissociate it from the hash
822 table and free it if necessary. */
824 uid_hash_delete (comp
);
826 if (comp
-> uid
!= &comp
-> uid_buf
[0]) {
827 dfree (comp
-> uid
, MDL
);
831 comp
-> uid
= (unsigned char *)0;
835 if (comp
-> hardware_addr
.hlen
&&
836 ((comp
-> hardware_addr
.hlen
!=
837 lease
-> hardware_addr
.hlen
) ||
838 memcmp (comp
-> hardware_addr
.hbuf
,
839 lease
-> hardware_addr
.hbuf
,
840 comp
-> hardware_addr
.hlen
))) {
841 hw_hash_delete (comp
);
843 } else if (!comp
-> hardware_addr
.hlen
)
846 /* If the lease has been billed to a class, remove the billing. */
847 if (comp
-> billing_class
!= lease
-> billing_class
) {
848 if (comp
-> billing_class
)
849 unbill_class (comp
, comp
-> billing_class
);
850 if (lease
-> billing_class
)
851 bill_class (comp
, lease
-> billing_class
);
854 /* Copy the data files, but not the linkages. */
855 comp
-> starts
= lease
-> starts
;
857 if (lease
-> uid_len
<= sizeof (lease
-> uid_buf
)) {
858 memcpy (comp
-> uid_buf
,
859 lease
-> uid
, lease
-> uid_len
);
860 comp
-> uid
= &comp
-> uid_buf
[0];
861 comp
-> uid_max
= sizeof comp
-> uid_buf
;
862 comp
-> uid_len
= lease
-> uid_len
;
863 } else if (lease
-> uid
!= &lease
-> uid_buf
[0]) {
864 comp
-> uid
= lease
-> uid
;
865 comp
-> uid_max
= lease
-> uid_max
;
866 lease
-> uid
= (unsigned char *)0;
867 lease
-> uid_max
= 0;
868 comp
-> uid_len
= lease
-> uid_len
;
869 lease
-> uid_len
= 0;
871 log_fatal ("corrupt lease uid."); /* XXX */
874 comp
-> uid
= (unsigned char *)0;
875 comp
-> uid_len
= comp
-> uid_max
= 0;
878 host_dereference (&comp
-> host
, MDL
);
879 host_reference (&comp
-> host
, lease
-> host
, MDL
);
880 comp
-> hardware_addr
= lease
-> hardware_addr
;
881 comp
-> flags
= ((lease
-> flags
& ~PERSISTENT_FLAGS
) |
882 (comp
-> flags
& ~EPHEMERAL_FLAGS
));
884 binding_scope_dereference (&comp
-> scope
, MDL
);
885 if (lease
-> scope
) {
886 binding_scope_reference (&comp
-> scope
, lease
-> scope
, MDL
);
887 binding_scope_dereference (&lease
-> scope
, MDL
);
890 if (comp
-> agent_options
)
891 option_chain_head_dereference (&comp
-> agent_options
, MDL
);
892 if (lease
-> agent_options
) {
893 /* Only retain the agent options if the lease is still
894 affirmatively associated with a client. */
895 if (lease
-> next_binding_state
== FTS_ACTIVE
||
896 lease
-> next_binding_state
== FTS_EXPIRED
||
897 lease
-> next_binding_state
== FTS_RESERVED
||
898 lease
-> next_binding_state
== FTS_BOOTP
)
899 option_chain_head_reference (&comp
-> agent_options
,
900 lease
-> agent_options
,
902 option_chain_head_dereference (&lease
-> agent_options
, MDL
);
905 /* Record the hostname information in the lease. */
906 if (comp
-> client_hostname
)
907 dfree (comp
-> client_hostname
, MDL
);
908 comp
-> client_hostname
= lease
-> client_hostname
;
909 lease
-> client_hostname
= (char *)0;
911 if (lease
-> on_expiry
) {
912 if (comp
-> on_expiry
)
913 executable_statement_dereference (&comp
-> on_expiry
,
915 executable_statement_reference (&comp
-> on_expiry
,
919 if (lease
-> on_commit
) {
920 if (comp
-> on_commit
)
921 executable_statement_dereference (&comp
-> on_commit
,
923 executable_statement_reference (&comp
-> on_commit
,
927 if (lease
-> on_release
) {
928 if (comp
-> on_release
)
929 executable_statement_dereference (&comp
-> on_release
,
931 executable_statement_reference (&comp
-> on_release
,
932 lease
-> on_release
, MDL
);
935 /* Record the lease in the uid hash if necessary. */
936 if (enter_uid
&& lease
-> uid
) {
940 /* Record it in the hardware address hash if necessary. */
941 if (enter_hwaddr
&& lease
-> hardware_addr
.hlen
) {
945 #if defined (FAILOVER_PROTOCOL)
946 comp
-> cltt
= lease
-> cltt
;
947 comp
-> tstp
= lease
-> tstp
;
948 comp
-> tsfp
= lease
-> tsfp
;
949 #endif /* FAILOVER_PROTOCOL */
950 comp
-> ends
= lease
-> ends
;
951 comp
-> next_binding_state
= lease
-> next_binding_state
;
955 log_error ("Supersede_lease: lease %s with no pool.",
956 piaddr (comp
-> ip_addr
));
960 /* Figure out which queue it's on. */
961 switch (comp
-> binding_state
) {
963 lq
= &comp
-> pool
-> free
;
964 comp
-> pool
-> free_leases
--;
970 lq
= &comp
-> pool
-> active
;
976 lq
= &comp
-> pool
-> expired
;
980 lq
= &comp
-> pool
-> abandoned
;
984 lq
= &comp
-> pool
-> backup
;
985 comp
-> pool
-> backup_leases
--;
989 log_error ("Lease with bogus binding state: %d",
990 comp
-> binding_state
);
994 /* Remove the lease from its current place in its current
996 prev
= (struct lease
*)0;
997 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1004 log_error ("Lease with binding state %s not on its queue.",
1005 (comp
-> binding_state
< 1 &&
1006 comp
-> binding_state
< FTS_BOOTP
)
1008 : binding_state_names
[comp
-> binding_state
- 1]);
1013 lease_dereference (&prev
-> next
, MDL
);
1015 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1016 lease_dereference (&comp
-> next
, MDL
);
1019 lease_dereference (lq
, MDL
);
1021 lease_reference (lq
, comp
-> next
, MDL
);
1022 lease_dereference (&comp
-> next
, MDL
);
1026 /* Make the state transition. */
1028 process_state_transition (comp
);
1030 /* Put the lease back on the appropriate queue. If the lease
1031 is corrupt (as detected by lease_enqueue), don't go any farther. */
1032 if (!lease_enqueue (comp
))
1035 /* If this is the next lease that will timeout on the pool,
1036 zap the old timeout and set the timeout on this pool to the
1037 time that the lease's next event will happen.
1039 We do not actually set the timeout unless commit is true -
1040 we don't want to thrash the timer queue when reading the
1041 lease database. Instead, the database code calls the
1042 expiry event on each pool after reading in the lease file,
1043 and the expiry code sets the timer if there's anything left
1044 to expire after it's run any outstanding expiry events on
1047 comp
-> sort_time
!= MIN_TIME
&&
1048 comp
-> sort_time
> cur_time
&&
1049 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1050 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1051 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1052 add_timeout (comp
-> pool
-> next_event_time
,
1053 pool_timer
, comp
-> pool
,
1054 (tvref_t
)pool_reference
,
1055 (tvunref_t
)pool_dereference
);
1059 if (!write_lease (comp
))
1061 if (!commit_leases ())
1065 #if defined (FAILOVER_PROTOCOL)
1067 if (!dhcp_failover_queue_update (comp
, pimmediate
))
1075 void process_state_transition (struct lease
*lease
)
1077 #if defined (FAILOVER_PROTOCOL)
1078 dhcp_failover_state_t
*peer
;
1080 if (lease
&& lease
-> pool
&& lease
-> pool
-> failover_peer
)
1081 peer
= lease
-> pool
-> failover_peer
;
1083 peer
= (dhcp_failover_state_t
*)0;
1086 /* If the lease was active and is now no longer active, but isn't
1087 released, then it just expired, so do the expiry event. */
1088 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1090 #if defined (FAILOVER_PROTOCOL)
1092 lease
-> binding_state
== FTS_EXPIRED
&&
1093 (lease
-> next_binding_state
== FTS_FREE
||
1094 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1097 (lease
-> binding_state
== FTS_ACTIVE
||
1098 lease
-> binding_state
== FTS_BOOTP
||
1099 lease
-> binding_state
== FTS_RESERVED
) &&
1100 lease
-> next_binding_state
!= FTS_RELEASED
))) {
1101 ddns_removals (lease
);
1102 if (lease
-> on_expiry
) {
1103 execute_statements ((struct binding_value
**)0,
1104 (struct packet
*)0, lease
,
1105 (struct client_state
*)0,
1106 (struct option_state
*)0,
1107 (struct option_state
*)0, /* XXX */
1109 lease
-> on_expiry
);
1110 if (lease
-> on_expiry
)
1111 executable_statement_dereference
1112 (&lease
-> on_expiry
, MDL
);
1115 /* No sense releasing a lease after it's expired. */
1116 if (lease
-> on_release
)
1117 executable_statement_dereference (&lease
-> on_release
,
1119 /* Send the expiry time to the peer. */
1120 lease
-> tstp
= lease
-> ends
;
1123 /* If the lease was active and is now released, do the release
1125 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1127 #if defined (FAILOVER_PROTOCOL)
1129 lease
-> binding_state
== FTS_RELEASED
&&
1130 (lease
-> next_binding_state
== FTS_FREE
||
1131 lease
-> next_binding_state
== FTS_BACKUP
)) ||
1134 (lease
-> binding_state
== FTS_ACTIVE
||
1135 lease
-> binding_state
== FTS_BOOTP
||
1136 lease
-> binding_state
== FTS_RESERVED
) &&
1137 lease
-> next_binding_state
== FTS_RELEASED
))) {
1138 ddns_removals (lease
);
1139 if (lease
-> on_release
) {
1140 execute_statements ((struct binding_value
**)0,
1141 (struct packet
*)0, lease
,
1142 (struct client_state
*)0,
1143 (struct option_state
*)0,
1144 (struct option_state
*)0, /* XXX */
1146 lease
-> on_release
);
1147 executable_statement_dereference (&lease
-> on_release
,
1151 /* A released lease can't expire. */
1152 if (lease
-> on_expiry
)
1153 executable_statement_dereference (&lease
-> on_expiry
,
1156 /* Send the release time (should be == cur_time) to the
1158 lease
-> tstp
= lease
-> ends
;
1161 lease
-> binding_state
= lease
-> next_binding_state
;
1162 if (lease
-> binding_state
== FTS_ACTIVE
||
1163 lease
-> binding_state
== FTS_BACKUP
) {
1164 #if defined (FAILOVER_PROTOCOL)
1165 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1166 lease
-> next_binding_state
= FTS_EXPIRED
;
1169 lease
-> next_binding_state
= FTS_FREE
;
1173 /* Copy the contents of one lease into another, correctly maintaining
1174 reference counts. */
1175 int lease_copy (struct lease
**lp
,
1176 struct lease
*lease
, const char *file
, int line
)
1178 struct lease
*lt
= (struct lease
*)0;
1179 isc_result_t status
;
1181 status
= lease_allocate (<
, MDL
);
1182 if (status
!= ISC_R_SUCCESS
)
1185 lt
-> ip_addr
= lease
-> ip_addr
;
1186 lt
-> starts
= lease
-> starts
;
1187 lt
-> ends
= lease
-> ends
;
1188 lt
-> timestamp
= lease
-> timestamp
;
1189 lt
-> uid_len
= lease
-> uid_len
;
1190 lt
-> uid_max
= lease
-> uid_max
;
1191 if (lease
-> uid
== lease
-> uid_buf
) {
1192 lt
-> uid
= lt
-> uid_buf
;
1193 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1195 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1197 lease_dereference (<
, MDL
);
1200 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1202 if (lease
-> client_hostname
) {
1203 lt
-> client_hostname
=
1204 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1205 if (!lt
-> client_hostname
) {
1206 lease_dereference (<
, MDL
);
1209 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1212 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1213 if (lease
-> agent_options
)
1214 option_chain_head_reference (<
-> agent_options
,
1215 lease
-> agent_options
, MDL
);
1216 host_reference (<
-> host
, lease
-> host
, file
, line
);
1217 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1218 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1219 class_reference (<
-> billing_class
,
1220 lease
-> billing_class
, file
, line
);
1221 lt
-> hardware_addr
= lease
-> hardware_addr
;
1222 if (lease
-> on_expiry
)
1223 executable_statement_reference (<
-> on_expiry
,
1226 if (lease
-> on_commit
)
1227 executable_statement_reference (<
-> on_commit
,
1230 if (lease
-> on_release
)
1231 executable_statement_reference (<
-> on_release
,
1232 lease
-> on_release
,
1234 lt
-> flags
= lease
-> flags
;
1235 lt
-> tstp
= lease
-> tstp
;
1236 lt
-> tsfp
= lease
-> tsfp
;
1237 lt
-> cltt
= lease
-> cltt
;
1238 lt
-> binding_state
= lease
-> binding_state
;
1239 lt
-> next_binding_state
= lease
-> next_binding_state
;
1240 status
= lease_reference (lp
, lt
, file
, line
);
1241 lease_dereference (<
, MDL
);
1242 return status
== ISC_R_SUCCESS
;
1245 /* Release the specified lease and re-hash it as appropriate. */
1246 void release_lease (lease
, packet
)
1247 struct lease
*lease
;
1248 struct packet
*packet
;
1250 /* If there are statements to execute when the lease is
1251 released, execute them. */
1252 ddns_removals (lease
);
1253 if (lease
-> on_release
) {
1254 execute_statements ((struct binding_value
**)0,
1255 packet
, lease
, (struct client_state
*)0,
1257 (struct option_state
*)0, /* XXX */
1258 &lease
-> scope
, lease
-> on_release
);
1259 if (lease
-> on_release
)
1260 executable_statement_dereference (&lease
-> on_release
,
1264 /* We do either the on_release or the on_expiry events, but
1265 not both (it's possible that they could be the same,
1267 if (lease
-> on_expiry
)
1268 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1270 if (lease
-> ends
> cur_time
) {
1271 if (lease
-> on_commit
)
1272 executable_statement_dereference (&lease
-> on_commit
,
1275 /* Blow away any bindings. */
1277 binding_scope_dereference (&lease
-> scope
, MDL
);
1278 lease
-> ends
= cur_time
;
1279 #if defined (FAILOVER_PROTOCOL)
1280 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1281 lease
-> next_binding_state
= FTS_RELEASED
;
1283 lease
-> next_binding_state
= FTS_FREE
;
1286 lease
-> next_binding_state
= FTS_FREE
;
1288 if (lease
-> billing_class
)
1289 class_dereference (&lease
-> billing_class
, MDL
);
1290 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1294 /* Abandon the specified lease (set its timeout to infinity and its
1295 particulars to zero, and re-hash it as appropriate. */
1297 void abandon_lease (lease
, message
)
1298 struct lease
*lease
;
1299 const char *message
;
1301 struct lease
*lt
= (struct lease
*)0;
1303 if (!lease_copy (<
, lease
, MDL
))
1307 if (lt
-> on_expiry
)
1308 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1309 if (lt
-> on_release
)
1310 executable_statement_dereference (&lease
-> on_release
, MDL
);
1311 if (lt
-> on_commit
)
1312 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1314 /* Blow away any bindings. */
1316 binding_scope_dereference (<
-> scope
, MDL
);
1319 lt
-> ends
= cur_time
; /* XXX */
1320 lt
-> next_binding_state
= FTS_ABANDONED
;
1322 log_error ("Abandoning IP address %s: %s",
1323 piaddr (lease
-> ip_addr
), message
);
1324 lt
-> hardware_addr
.hlen
= 0;
1325 if (lt
-> uid
!= lt
-> uid_buf
)
1326 dfree (lt
-> uid
, MDL
);
1327 lt
-> uid
= (unsigned char *)0;
1330 if (lt
-> billing_class
)
1331 class_dereference (<
-> billing_class
, MDL
);
1332 supersede_lease (lease
, lt
, 1, 1, 1);
1333 lease_dereference (<
, MDL
);
1336 /* Abandon the specified lease (set its timeout to infinity and its
1337 particulars to zero, and re-hash it as appropriate. */
1339 void dissociate_lease (lease
)
1340 struct lease
*lease
;
1342 struct lease
*lt
= (struct lease
*)0;
1344 if (!lease_copy (<
, lease
, MDL
))
1348 if (lt
-> on_expiry
)
1349 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1350 if (lt
-> on_release
)
1351 executable_statement_dereference (&lease
-> on_release
, MDL
);
1352 if (lt
-> on_commit
)
1353 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1355 /* Blow away any bindings. */
1357 binding_scope_dereference (<
-> scope
, MDL
);
1360 #if defined (FAILOVER_PROTOCOL)
1361 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1362 lt
-> next_binding_state
= FTS_RESET
;
1364 lt
-> next_binding_state
= FTS_FREE
;
1367 lt
-> next_binding_state
= FTS_FREE
;
1369 lt
-> ends
= cur_time
; /* XXX */
1370 lt
-> hardware_addr
.hlen
= 0;
1371 if (lt
-> uid
!= lt
-> uid_buf
)
1372 dfree (lt
-> uid
, MDL
);
1373 lt
-> uid
= (unsigned char *)0;
1376 if (lt
-> billing_class
)
1377 class_dereference (<
-> billing_class
, MDL
);
1378 supersede_lease (lease
, lt
, 1, 1, 1);
1379 lease_dereference (<
, MDL
);
1382 /* Timer called when a lease in a particular pool expires. */
1383 void pool_timer (vpool
)
1387 struct lease
*lt
= (struct lease
*)0;
1388 struct lease
*next
= (struct lease
*)0;
1389 struct lease
*lease
= (struct lease
*)0;
1390 struct lease
**lptr
[5];
1391 TIME next_expiry
= MAX_TIME
;
1394 pool
= (struct pool
*)vpool
;
1396 #define FREE_LEASES 0
1397 lptr
[FREE_LEASES
] = &pool
-> free
;
1398 #define ACTIVE_LEASES 1
1399 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1400 #define EXPIRED_LEASES 2
1401 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1402 #define ABANDONED_LEASES 3
1403 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1404 #define BACKUP_LEASES 4
1405 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1407 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1408 /* If there's nothing on the queue, skip it. */
1412 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1415 /* Remember the next lease in the list. */
1417 lease_dereference (&next
, MDL
);
1419 lease_reference (&next
, lease
-> next
, MDL
);
1421 /* If we've run out of things to expire on this list,
1423 if (lease
-> sort_time
> cur_time
) {
1424 if (lease
-> sort_time
< next_expiry
)
1425 next_expiry
= lease
-> sort_time
;
1429 /* If there is a pending state change, and
1430 this lease has gotten to the time when the
1431 state change should happen, just call
1432 supersede_lease on it to make the change
1434 if (lease
-> next_binding_state
!=
1435 lease
-> binding_state
)
1436 supersede_lease (lease
,
1437 (struct lease
*)0, 1, 1, 1);
1439 lease_dereference (&lease
, MDL
);
1441 lease_reference (&lease
, next
, MDL
);
1444 lease_dereference (&next
, MDL
);
1446 lease_dereference (&lease
, MDL
);
1448 if (next_expiry
!= MAX_TIME
) {
1449 pool
-> next_event_time
= next_expiry
;
1450 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1451 (tvref_t
)pool_reference
,
1452 (tvunref_t
)pool_dereference
);
1454 pool
-> next_event_time
= MIN_TIME
;
1458 /* Locate the lease associated with a given IP address... */
1460 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1461 const char *file
, int line
)
1463 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1464 addr
.iabuf
, addr
.len
, file
, line
);
1467 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1468 unsigned len
, const char *file
, int line
)
1472 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1475 int find_lease_by_hw_addr (struct lease
**lp
,
1476 const unsigned char *hwaddr
, unsigned hwlen
,
1477 const char *file
, int line
)
1481 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1482 hwaddr
, hwlen
, file
, line
);
1485 /* Add the specified lease to the uid hash. */
1487 void uid_hash_add (lease
)
1488 struct lease
*lease
;
1490 struct lease
*head
= (struct lease
*)0;
1494 /* If it's not in the hash, just add it. */
1495 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1496 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1497 lease
-> uid_len
, lease
, MDL
);
1499 /* Otherwise, attach it to the end of the list. */
1500 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
)
1502 lease_reference (&scan
-> n_uid
, lease
, MDL
);
1503 lease_dereference (&head
, MDL
);
1507 /* Delete the specified lease from the uid hash. */
1509 void uid_hash_delete (lease
)
1510 struct lease
*lease
;
1512 struct lease
*head
= (struct lease
*)0;
1515 /* If it's not in the hash, we have no work to do. */
1516 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1518 lease_dereference (&lease
-> n_uid
, MDL
);
1522 /* If the lease we're freeing is at the head of the list,
1523 remove the hash table entry and add a new one with the
1524 next lease on the list (if there is one). */
1525 if (head
== lease
) {
1526 lease_hash_delete (lease_uid_hash
,
1527 lease
-> uid
, lease
-> uid_len
, MDL
);
1528 if (lease
-> n_uid
) {
1529 lease_hash_add (lease_uid_hash
,
1530 lease
-> n_uid
-> uid
,
1531 lease
-> n_uid
-> uid_len
,
1532 lease
-> n_uid
, MDL
);
1533 lease_dereference (&lease
-> n_uid
, MDL
);
1536 /* Otherwise, look for the lease in the list of leases
1537 attached to the hash table entry, and remove it if
1539 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1540 if (scan
-> n_uid
== lease
) {
1541 lease_dereference (&scan
-> n_uid
, MDL
);
1542 if (lease
-> n_uid
) {
1543 lease_reference (&scan
-> n_uid
,
1544 lease
-> n_uid
, MDL
);
1545 lease_dereference (&lease
-> n_uid
,
1552 lease_dereference (&head
, MDL
);
1555 /* Add the specified lease to the hardware address hash. */
1557 void hw_hash_add (lease
)
1558 struct lease
*lease
;
1560 struct lease
*head
= (struct lease
*)0;
1563 /* If it's not in the hash, just add it. */
1564 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1565 lease
-> hardware_addr
.hlen
, MDL
))
1566 lease_hash_add (lease_hw_addr_hash
,
1567 lease
-> hardware_addr
.hbuf
,
1568 lease
-> hardware_addr
.hlen
,
1571 /* Otherwise, attach it to the end of the list. */
1572 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
)
1574 lease_reference (&scan
-> n_hw
, lease
, MDL
);
1575 lease_dereference (&head
, MDL
);
1579 /* Delete the specified lease from the hardware address hash. */
1581 void hw_hash_delete (lease
)
1582 struct lease
*lease
;
1584 struct lease
*head
= (struct lease
*)0;
1587 /* If it's not in the hash, we have no work to do. */
1588 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1589 lease
-> hardware_addr
.hlen
, MDL
)) {
1591 lease_dereference (&lease
-> n_hw
, MDL
);
1595 /* If the lease we're freeing is at the head of the list,
1596 remove the hash table entry and add a new one with the
1597 next lease on the list (if there is one). */
1598 if (head
== lease
) {
1599 lease_hash_delete (lease_hw_addr_hash
,
1600 lease
-> hardware_addr
.hbuf
,
1601 lease
-> hardware_addr
.hlen
, MDL
);
1602 if (lease
-> n_hw
) {
1603 lease_hash_add (lease_hw_addr_hash
,
1604 lease
-> n_hw
-> hardware_addr
.hbuf
,
1605 lease
-> n_hw
-> hardware_addr
.hlen
,
1606 lease
-> n_hw
, MDL
);
1607 lease_dereference (&lease
-> n_hw
, MDL
);
1610 /* Otherwise, look for the lease in the list of leases
1611 attached to the hash table entry, and remove it if
1613 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
) {
1614 if (scan
-> n_hw
== lease
) {
1615 lease_dereference (&scan
-> n_hw
, MDL
);
1616 if (lease
-> n_hw
) {
1617 lease_reference (&scan
-> n_hw
,
1618 lease
-> n_hw
, MDL
);
1619 lease_dereference (&lease
-> n_hw
,
1626 lease_dereference (&head
, MDL
);
1629 /* Write all interesting leases to permanent storage. */
1631 void write_leases ()
1634 struct shared_network
*s
;
1636 struct host_decl
*hp
;
1637 struct group_object
*gp
;
1638 struct hash_bucket
*hb
;
1641 struct lease
**lptr
[5];
1643 /* Write all the dynamically-created group declarations. */
1644 if (group_name_hash
) {
1646 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1647 for (hb
= group_name_hash
-> buckets
[i
];
1648 hb
; hb
= hb
-> next
) {
1649 gp
= (struct group_object
*)hb
-> value
;
1650 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1651 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1652 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1658 log_info ("Wrote %d group decls to leases file.", num_written
);
1661 /* Write all the deleted host declarations. */
1662 if (host_name_hash
) {
1664 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1665 for (hb
= host_name_hash
-> buckets
[i
];
1666 hb
; hb
= hb
-> next
) {
1667 hp
= (struct host_decl
*)hb
-> value
;
1668 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1669 (hp
-> flags
& HOST_DECL_DELETED
))) {
1675 log_info ("Wrote %d deleted host decls to leases file.",
1679 /* Write all the new, dynamic host declarations. */
1680 if (host_name_hash
) {
1682 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1683 for (hb
= host_name_hash
-> buckets
[i
];
1684 hb
; hb
= hb
-> next
) {
1685 hp
= (struct host_decl
*)hb
-> value
;
1686 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1692 log_info ("Wrote %d new dynamic host decls to leases file.",
1696 #if defined (FAILOVER_PROTOCOL)
1697 /* Write all the failover states. */
1698 dhcp_failover_write_all_states ();
1701 /* Write all the leases. */
1703 for (s
= shared_networks
; s
; s
= s
-> next
) {
1704 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1705 lptr
[FREE_LEASES
] = &p
-> free
;
1706 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1707 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1708 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1709 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1711 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1712 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1713 if (l
-> hardware_addr
.hlen
||
1715 (l
-> binding_state
!= FTS_FREE
)) {
1716 if (!write_lease (l
))
1717 log_fatal ("Can't rewrite lease database");
1724 log_info ("Wrote %d leases to leases file.", num_written
);
1725 if (!commit_leases ())
1726 log_fatal ("Can't commit leases to new database: %m");
1729 int lease_enqueue (struct lease
*comp
)
1731 struct lease
**lq
, *prev
, *lp
;
1733 /* No queue to put it on? */
1737 /* Figure out which queue it's going to. */
1738 switch (comp
-> binding_state
) {
1740 lq
= &comp
-> pool
-> free
;
1741 comp
-> pool
-> free_leases
++;
1742 comp
-> sort_time
= comp
-> ends
;
1748 lq
= &comp
-> pool
-> active
;
1749 comp
-> sort_time
= comp
-> ends
;
1755 lq
= &comp
-> pool
-> expired
;
1756 comp
-> sort_time
= comp
-> ends
;
1761 lq
= &comp
-> pool
-> abandoned
;
1762 comp
-> sort_time
= comp
-> ends
;
1766 lq
= &comp
-> pool
-> backup
;
1767 comp
-> pool
-> backup_leases
++;
1768 comp
-> sort_time
= comp
-> ends
;
1772 log_error ("Lease with bogus binding state: %d",
1773 comp
-> binding_state
);
1777 /* Insertion sort the lease onto the appropriate queue. */
1778 prev
= (struct lease
*)0;
1779 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1780 if (lp
-> sort_time
>= comp
-> sort_time
)
1786 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1787 lease_dereference (&prev
-> next
, MDL
);
1789 lease_reference (&prev
-> next
, comp
, MDL
);
1792 lease_reference (&comp
-> next
, *lq
, MDL
);
1793 lease_dereference (lq
, MDL
);
1795 lease_reference (lq
, comp
, MDL
);
1800 /* For a given lease, sort it onto the right list in its pool and put it
1801 in each appropriate hash, understanding that it's already by definition
1802 in lease_ip_addr_hash. */
1804 void lease_instantiate (const unsigned char *val
, unsigned len
,
1805 struct lease
*lease
)
1808 /* XXX If the lease doesn't have a pool at this point, it's an
1809 XXX orphan, which we *should* keep around until it expires,
1810 XXX but which right now we just forget. */
1811 if (!lease
-> pool
) {
1812 lease_hash_delete (lease_ip_addr_hash
,
1813 lease
-> ip_addr
.iabuf
,
1814 lease
-> ip_addr
.len
, MDL
);
1818 /* Put the lease on the right queue. */
1819 lease_enqueue (lease
);
1821 /* Record the lease in the uid hash if possible. */
1823 uid_hash_add (lease
);
1826 /* Record it in the hardware address hash if possible. */
1827 if (lease
-> hardware_addr
.hlen
) {
1828 hw_hash_add (lease
);
1834 /* Run expiry events on every pool. This is called on startup so that
1835 any expiry events that occurred after the server stopped and before it
1836 was restarted can be run. At the same time, if failover support is
1837 compiled in, we compute the balance of leases for the pool. */
1839 void expire_all_pools ()
1841 struct shared_network
*s
;
1843 struct hash_bucket
*hb
;
1846 struct lease
**lptr
[5];
1848 /* First, go over the hash list and actually put all the leases
1849 on the appropriate lists. */
1850 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1852 /* Loop through each pool in each shared network and call the
1853 expiry routine on the pool. */
1854 for (s
= shared_networks
; s
; s
= s
-> next
) {
1855 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1858 p
-> lease_count
= 0;
1859 p
-> free_leases
= 0;
1860 p
-> backup_leases
= 0;
1862 lptr
[FREE_LEASES
] = &p
-> free
;
1863 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1864 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1865 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1866 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1868 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1869 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1871 if (l
-> ends
<= cur_time
) {
1872 if (l
-> binding_state
== FTS_FREE
)
1874 else if (l
-> binding_state
== FTS_BACKUP
)
1875 p
-> backup_leases
++;
1877 #if defined (FAILOVER_PROTOCOL)
1878 if (p
-> failover_peer
&&
1879 l
-> tstp
> l
-> tsfp
&&
1880 !(l
-> flags
& ON_UPDATE_QUEUE
))
1881 dhcp_failover_queue_update (l
, 1);
1889 void dump_subnets ()
1892 struct shared_network
*s
;
1895 struct lease
**lptr
[5];
1898 log_info ("Subnets:");
1899 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
1900 log_debug (" Subnet %s", piaddr (n
-> net
));
1901 log_debug (" netmask %s",
1902 piaddr (n
-> netmask
));
1904 log_info ("Shared networks:");
1905 for (s
= shared_networks
; s
; s
= s
-> next
) {
1906 log_info (" %s", s
-> name
);
1907 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1908 lptr
[FREE_LEASES
] = &p
-> free
;
1909 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1910 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1911 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1912 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1914 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1915 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1923 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
)
1924 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
)
1925 HASH_FUNCTIONS (class, const char *, struct class)