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.48 2001/01/04 00:30:53 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_cache_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
-> binding_state
== FTS_ACTIVE
||
886 lease
-> binding_state
== FTS_EXPIRED
||
887 lease
-> binding_state
== FTS_ABANDONED
||
888 lease
-> binding_state
== FTS_RESERVED
||
889 lease
-> binding_state
== FTS_BOOTP
)
890 option_cache_reference (&comp
-> agent_options
,
891 lease
-> agent_options
, MDL
);
892 option_cache_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
;
948 /* Figure out which queue it's on. */
949 switch (comp
-> binding_state
) {
951 lq
= &comp
-> pool
-> free
;
952 comp
-> pool
-> free_leases
--;
958 lq
= &comp
-> pool
-> active
;
964 lq
= &comp
-> pool
-> expired
;
968 lq
= &comp
-> pool
-> abandoned
;
972 lq
= &comp
-> pool
-> backup
;
973 comp
-> pool
-> backup_leases
--;
977 log_error ("Lease with bogus binding state: %d",
978 comp
-> binding_state
);
982 /* Remove the lease from its current place in its current
984 prev
= (struct lease
*)0;
985 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
992 log_error ("Lease with binding state %s not on its queue.",
993 (comp
-> binding_state
< 1 &&
994 comp
-> binding_state
< FTS_BOOTP
)
996 : binding_state_names
[comp
-> binding_state
- 1]);
1001 lease_dereference (&prev
-> next
, MDL
);
1003 lease_reference (&prev
-> next
, comp
-> next
, MDL
);
1004 lease_dereference (&comp
-> next
, MDL
);
1007 lease_dereference (lq
, MDL
);
1009 lease_reference (lq
, comp
-> next
, MDL
);
1010 lease_dereference (&comp
-> next
, MDL
);
1014 /* Make the state transition. */
1016 process_state_transition (comp
);
1018 /* Put the lease back on the appropriate queue. If the lease
1019 is corrupt (as detected by lease_enqueue), don't go any farther. */
1020 if (!lease_enqueue (comp
))
1023 /* If this is the next lease that will timeout on the pool,
1024 zap the old timeout and set the timeout on this pool to the
1025 time that the lease's next event will happen.
1027 We do not actually set the timeout unless commit is true -
1028 we don't want to thrash the timer queue when reading the
1029 lease database. Instead, the database code calls the
1030 expiry event on each pool after reading in the lease file,
1031 and the expiry code sets the timer if there's anything left
1032 to expire after it's run any outstanding expiry events on
1035 comp
-> sort_time
!= MIN_TIME
&&
1036 comp
-> sort_time
> cur_time
&&
1037 (comp
-> sort_time
< comp
-> pool
-> next_event_time
||
1038 comp
-> pool
-> next_event_time
== MIN_TIME
)) {
1039 comp
-> pool
-> next_event_time
= comp
-> sort_time
;
1040 add_timeout (comp
-> pool
-> next_event_time
,
1041 pool_timer
, comp
-> pool
,
1042 (tvref_t
)pool_reference
,
1043 (tvunref_t
)pool_dereference
);
1046 /* Return zero if we didn't commit the lease to permanent storage;
1047 nonzero if we did. */
1048 return commit
&& write_lease (comp
) && commit_leases ()
1049 #if defined (FAILOVER_PROTOCOL)
1051 dhcp_failover_queue_update (comp
, pimmediate
))
1056 void process_state_transition (struct lease
*lease
)
1058 /* If the lease was active and is now no longer active, but isn't
1059 released, then it just expired, so do the expiry event. */
1060 if (lease
-> next_binding_state
!= lease
-> binding_state
&&
1061 (lease
-> binding_state
== FTS_ACTIVE
||
1062 lease
-> binding_state
== FTS_BOOTP
||
1063 lease
-> binding_state
== FTS_RESERVED
) &&
1064 lease
-> next_binding_state
!= FTS_RELEASED
) {
1065 ddns_removals (lease
);
1066 if (lease
-> on_expiry
) {
1067 execute_statements ((struct binding_value
**)0,
1068 (struct packet
*)0, lease
,
1069 (struct client_state
*)0,
1070 (struct option_state
*)0,
1071 (struct option_state
*)0, /* XXX */
1073 lease
-> on_expiry
);
1074 if (lease
-> on_expiry
)
1075 executable_statement_dereference
1076 (&lease
-> on_expiry
, MDL
);
1079 /* No sense releasing a lease after it's expired. */
1080 if (lease
-> on_release
)
1081 executable_statement_dereference (&lease
-> on_release
,
1083 /* Send the expiry time to the peer. */
1084 lease
-> tstp
= lease
-> ends
;
1087 /* If the lease was active and is now released, do the release
1089 if ((lease
-> binding_state
== FTS_ACTIVE
||
1090 lease
-> binding_state
== FTS_BOOTP
||
1091 lease
-> binding_state
== FTS_RESERVED
) &&
1092 lease
-> next_binding_state
== FTS_RELEASED
) {
1093 ddns_removals (lease
);
1094 if (lease
-> on_release
) {
1095 execute_statements ((struct binding_value
**)0,
1096 (struct packet
*)0, lease
,
1097 (struct client_state
*)0,
1098 (struct option_state
*)0,
1099 (struct option_state
*)0, /* XXX */
1101 lease
-> on_release
);
1102 executable_statement_dereference (&lease
-> on_release
,
1106 /* A released lease can't expire. */
1107 if (lease
-> on_expiry
)
1108 executable_statement_dereference (&lease
-> on_expiry
,
1111 /* Send the release time (should be == cur_time) to the
1113 lease
-> tstp
= lease
-> ends
;
1116 lease
-> binding_state
= lease
-> next_binding_state
;
1117 if (lease
-> binding_state
== FTS_ACTIVE
||
1118 lease
-> binding_state
== FTS_BACKUP
) {
1119 #if defined (FAILOVER_PROTOCOL)
1120 if (lease
-> pool
&& lease
-> pool
-> failover_peer
)
1121 lease
-> next_binding_state
= FTS_EXPIRED
;
1124 lease
-> next_binding_state
= FTS_FREE
;
1128 /* Copy the contents of one lease into another, correctly maintaining
1129 reference counts. */
1130 int lease_copy (struct lease
**lp
,
1131 struct lease
*lease
, const char *file
, int line
)
1133 struct lease
*lt
= (struct lease
*)0;
1134 isc_result_t status
;
1136 status
= lease_allocate (<
, MDL
);
1137 if (status
!= ISC_R_SUCCESS
)
1140 lt
-> ip_addr
= lease
-> ip_addr
;
1141 lt
-> starts
= lease
-> starts
;
1142 lt
-> ends
= lease
-> ends
;
1143 lt
-> timestamp
= lease
-> timestamp
;
1144 lt
-> uid_len
= lease
-> uid_len
;
1145 lt
-> uid_max
= lease
-> uid_max
;
1146 if (lease
-> uid
== lease
-> uid_buf
) {
1147 lt
-> uid
= lt
-> uid_buf
;
1148 memcpy (lt
-> uid_buf
, lease
-> uid_buf
, sizeof lt
-> uid_buf
);
1150 lt
-> uid
= dmalloc (lt
-> uid_max
, MDL
);
1152 lease_dereference (<
, MDL
);
1155 memcpy (lt
-> uid
, lease
-> uid
, lease
-> uid_max
);
1157 if (lease
-> hostname
) {
1158 lt
-> hostname
= dmalloc (strlen (lease
-> hostname
) + 1, MDL
);
1159 if (!lt
-> hostname
) {
1160 lease_dereference (<
, MDL
);
1163 strcpy (lt
-> hostname
, lease
-> hostname
);
1165 if (lease
-> client_hostname
) {
1166 lt
-> client_hostname
=
1167 dmalloc (strlen (lease
-> client_hostname
) + 1, MDL
);
1168 if (!lt
-> client_hostname
) {
1169 lease_dereference (<
, MDL
);
1172 strcpy (lt
-> client_hostname
, lease
-> client_hostname
);
1175 binding_scope_reference (<
-> scope
, lease
-> scope
, MDL
);
1176 if (lease
-> agent_options
)
1177 option_cache_reference (<
-> agent_options
,
1178 lease
-> agent_options
, MDL
);
1179 host_reference (<
-> host
, lease
-> host
, file
, line
);
1180 subnet_reference (<
-> subnet
, lease
-> subnet
, file
, line
);
1181 pool_reference (<
-> pool
, lease
-> pool
, file
, line
);
1182 class_reference (<
-> billing_class
,
1183 lease
-> billing_class
, file
, line
);
1184 lt
-> hardware_addr
= lease
-> hardware_addr
;
1185 if (lease
-> on_expiry
)
1186 executable_statement_reference (<
-> on_expiry
,
1189 if (lease
-> on_commit
)
1190 executable_statement_reference (<
-> on_commit
,
1193 if (lease
-> on_release
)
1194 executable_statement_reference (<
-> on_release
,
1195 lease
-> on_release
,
1197 lt
-> flags
= lease
-> flags
;
1198 lt
-> tstp
= lease
-> tstp
;
1199 lt
-> tsfp
= lease
-> tsfp
;
1200 lt
-> cltt
= lease
-> cltt
;
1201 lt
-> binding_state
= lease
-> binding_state
;
1202 lt
-> next_binding_state
= lease
-> next_binding_state
;
1203 status
= lease_reference (lp
, lt
, file
, line
);
1204 lease_dereference (<
, MDL
);
1205 return status
== ISC_R_SUCCESS
;
1208 /* Release the specified lease and re-hash it as appropriate. */
1209 void release_lease (lease
, packet
)
1210 struct lease
*lease
;
1211 struct packet
*packet
;
1213 /* If there are statements to execute when the lease is
1214 released, execute them. */
1215 ddns_removals (lease
);
1216 if (lease
-> on_release
) {
1217 execute_statements ((struct binding_value
**)0,
1218 packet
, lease
, (struct client_state
*)0,
1220 (struct option_state
*)0, /* XXX */
1221 &lease
-> scope
, lease
-> on_release
);
1222 if (lease
-> on_release
)
1223 executable_statement_dereference (&lease
-> on_release
,
1227 /* We do either the on_release or the on_expiry events, but
1228 not both (it's possible that they could be the same,
1230 if (lease
-> on_expiry
)
1231 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1233 if (lease
-> ends
> cur_time
) {
1234 if (lease
-> on_commit
)
1235 executable_statement_dereference (&lease
-> on_commit
,
1238 /* Blow away any bindings. */
1240 binding_scope_dereference (&lease
-> scope
, MDL
);
1241 lease
-> ends
= cur_time
;
1242 #if defined (FAILOVER_PROTOCOL)
1243 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1244 lease
-> next_binding_state
= FTS_RELEASED
;
1246 lease
-> next_binding_state
= FTS_FREE
;
1249 lease
-> next_binding_state
= FTS_FREE
;
1251 if (lease
-> billing_class
)
1252 class_dereference (&lease
-> billing_class
, MDL
);
1253 supersede_lease (lease
, (struct lease
*)0, 1, 1, 1);
1257 /* Abandon the specified lease (set its timeout to infinity and its
1258 particulars to zero, and re-hash it as appropriate. */
1260 void abandon_lease (lease
, message
)
1261 struct lease
*lease
;
1262 const char *message
;
1264 struct lease
*lt
= (struct lease
*)0;
1266 if (!lease_copy (<
, lease
, MDL
))
1270 if (lt
-> on_expiry
)
1271 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1272 if (lt
-> on_release
)
1273 executable_statement_dereference (&lease
-> on_release
, MDL
);
1274 if (lt
-> on_commit
)
1275 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1277 /* Blow away any bindings. */
1279 binding_scope_dereference (<
-> scope
, MDL
);
1282 lt
-> ends
= cur_time
; /* XXX */
1283 lt
-> next_binding_state
= FTS_ABANDONED
;
1285 log_error ("Abandoning IP address %s: %s",
1286 piaddr (lease
-> ip_addr
), message
);
1287 lt
-> hardware_addr
.hlen
= 0;
1288 if (lt
-> uid
!= lt
-> uid_buf
)
1289 dfree (lt
-> uid
, MDL
);
1290 lt
-> uid
= (unsigned char *)0;
1293 if (lt
-> billing_class
)
1294 class_dereference (<
-> billing_class
, MDL
);
1295 supersede_lease (lease
, lt
, 1, 1, 1);
1296 lease_dereference (<
, MDL
);
1299 /* Abandon the specified lease (set its timeout to infinity and its
1300 particulars to zero, and re-hash it as appropriate. */
1302 void dissociate_lease (lease
)
1303 struct lease
*lease
;
1305 struct lease
*lt
= (struct lease
*)0;
1307 if (!lease_copy (<
, lease
, MDL
))
1311 if (lt
-> on_expiry
)
1312 executable_statement_dereference (&lease
-> on_expiry
, MDL
);
1313 if (lt
-> on_release
)
1314 executable_statement_dereference (&lease
-> on_release
, MDL
);
1315 if (lt
-> on_commit
)
1316 executable_statement_dereference (&lease
-> on_commit
, MDL
);
1318 /* Blow away any bindings. */
1320 binding_scope_dereference (<
-> scope
, MDL
);
1323 #if defined (FAILOVER_PROTOCOL)
1324 if (lease
-> pool
&& lease
-> pool
-> failover_peer
) {
1325 lt
-> next_binding_state
= FTS_RESET
;
1327 lt
-> next_binding_state
= FTS_FREE
;
1330 lt
-> next_binding_state
= FTS_FREE
;
1332 lt
-> ends
= cur_time
; /* XXX */
1333 lt
-> hardware_addr
.hlen
= 0;
1334 if (lt
-> uid
!= lt
-> uid_buf
)
1335 dfree (lt
-> uid
, MDL
);
1336 lt
-> uid
= (unsigned char *)0;
1339 if (lt
-> billing_class
)
1340 class_dereference (<
-> billing_class
, MDL
);
1341 supersede_lease (lease
, lt
, 1, 1, 1);
1342 lease_dereference (<
, MDL
);
1345 /* Timer called when a lease in a particular pool expires. */
1346 void pool_timer (vpool
)
1350 struct lease
*lt
= (struct lease
*)0;
1351 struct lease
*next
= (struct lease
*)0;
1352 struct lease
*lease
= (struct lease
*)0;
1353 struct lease
**lptr
[5];
1354 TIME next_expiry
= MAX_TIME
;
1357 pool
= (struct pool
*)vpool
;
1359 #define FREE_LEASES 0
1360 lptr
[FREE_LEASES
] = &pool
-> free
;
1361 #define ACTIVE_LEASES 1
1362 lptr
[ACTIVE_LEASES
] = &pool
-> active
;
1363 #define EXPIRED_LEASES 2
1364 lptr
[EXPIRED_LEASES
] = &pool
-> expired
;
1365 #define ABANDONED_LEASES 3
1366 lptr
[ABANDONED_LEASES
] = &pool
-> abandoned
;
1367 #define BACKUP_LEASES 4
1368 lptr
[BACKUP_LEASES
] = &pool
-> backup
;
1370 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1371 /* If there's nothing on the queue, skip it. */
1375 lease_reference (&lease
, *(lptr
[i
]), MDL
);
1378 /* Remember the next lease in the list. */
1380 lease_dereference (&next
, MDL
);
1382 lease_reference (&next
, lease
-> next
, MDL
);
1384 /* If we've run out of things to expire on this list,
1386 if (lease
-> sort_time
> cur_time
) {
1387 if (lease
-> sort_time
< next_expiry
)
1388 next_expiry
= lease
-> sort_time
;
1392 /* If there is a pending state change, and
1393 this lease has gotten to the time when the
1394 state change should happen, just call
1395 supersede_lease on it to make the change
1397 if (lease
-> next_binding_state
!=
1398 lease
-> binding_state
)
1399 supersede_lease (lease
,
1400 (struct lease
*)0, 1, 1, 1);
1402 lease_dereference (&lease
, MDL
);
1404 lease_reference (&lease
, next
, MDL
);
1407 lease_dereference (&next
, MDL
);
1409 lease_dereference (&lease
, MDL
);
1411 if (next_expiry
!= MAX_TIME
) {
1412 pool
-> next_event_time
= next_expiry
;
1413 add_timeout (pool
-> next_event_time
, pool_timer
, pool
,
1414 (tvref_t
)pool_reference
,
1415 (tvunref_t
)pool_dereference
);
1417 pool
-> next_event_time
= MIN_TIME
;
1421 /* Locate the lease associated with a given IP address... */
1423 int find_lease_by_ip_addr (struct lease
**lp
, struct iaddr addr
,
1424 const char *file
, int line
)
1426 return lease_hash_lookup (lp
, lease_ip_addr_hash
,
1427 addr
.iabuf
, addr
.len
, file
, line
);
1430 int find_lease_by_uid (struct lease
**lp
, const unsigned char *uid
,
1431 unsigned len
, const char *file
, int line
)
1435 return lease_hash_lookup (lp
, lease_uid_hash
, uid
, len
, file
, line
);
1438 int find_lease_by_hw_addr (struct lease
**lp
,
1439 const unsigned char *hwaddr
, unsigned hwlen
,
1440 const char *file
, int line
)
1444 return lease_hash_lookup (lp
, lease_hw_addr_hash
,
1445 hwaddr
, hwlen
, file
, line
);
1448 /* Add the specified lease to the uid hash. */
1450 void uid_hash_add (lease
)
1451 struct lease
*lease
;
1453 struct lease
*head
= (struct lease
*)0;
1457 /* If it's not in the hash, just add it. */
1458 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
))
1459 lease_hash_add (lease_uid_hash
, lease
-> uid
,
1460 lease
-> uid_len
, lease
, MDL
);
1462 /* Otherwise, attach it to the end of the list. */
1463 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
)
1465 lease_reference (&scan
-> n_uid
, lease
, MDL
);
1466 lease_dereference (&head
, MDL
);
1470 /* Delete the specified lease from the uid hash. */
1472 void uid_hash_delete (lease
)
1473 struct lease
*lease
;
1475 struct lease
*head
= (struct lease
*)0;
1478 /* If it's not in the hash, we have no work to do. */
1479 if (!find_lease_by_uid (&head
, lease
-> uid
, lease
-> uid_len
, MDL
)) {
1481 lease_dereference (&lease
-> n_uid
, MDL
);
1485 /* If the lease we're freeing is at the head of the list,
1486 remove the hash table entry and add a new one with the
1487 next lease on the list (if there is one). */
1488 if (head
== lease
) {
1489 lease_hash_delete (lease_uid_hash
,
1490 lease
-> uid
, lease
-> uid_len
, MDL
);
1491 if (lease
-> n_uid
) {
1492 lease_hash_add (lease_uid_hash
,
1493 lease
-> n_uid
-> uid
,
1494 lease
-> n_uid
-> uid_len
,
1495 lease
-> n_uid
, MDL
);
1496 lease_dereference (&lease
-> n_uid
, MDL
);
1499 /* Otherwise, look for the lease in the list of leases
1500 attached to the hash table entry, and remove it if
1502 for (scan
= head
; scan
-> n_uid
; scan
= scan
-> n_uid
) {
1503 if (scan
-> n_uid
== lease
) {
1504 lease_dereference (&scan
-> n_uid
, MDL
);
1505 if (lease
-> n_uid
) {
1506 lease_reference (&scan
-> n_uid
,
1507 lease
-> n_uid
, MDL
);
1508 lease_dereference (&lease
-> n_uid
,
1515 lease_dereference (&head
, MDL
);
1518 /* Add the specified lease to the hardware address hash. */
1520 void hw_hash_add (lease
)
1521 struct lease
*lease
;
1523 struct lease
*head
= (struct lease
*)0;
1526 /* If it's not in the hash, just add it. */
1527 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1528 lease
-> hardware_addr
.hlen
, MDL
))
1529 lease_hash_add (lease_hw_addr_hash
,
1530 lease
-> hardware_addr
.hbuf
,
1531 lease
-> hardware_addr
.hlen
,
1534 /* Otherwise, attach it to the end of the list. */
1535 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
)
1537 lease_reference (&scan
-> n_hw
, lease
, MDL
);
1538 lease_dereference (&head
, MDL
);
1542 /* Delete the specified lease from the hardware address hash. */
1544 void hw_hash_delete (lease
)
1545 struct lease
*lease
;
1547 struct lease
*head
= (struct lease
*)0;
1550 /* If it's not in the hash, we have no work to do. */
1551 if (!find_lease_by_hw_addr (&head
, lease
-> hardware_addr
.hbuf
,
1552 lease
-> hardware_addr
.hlen
, MDL
)) {
1554 lease_dereference (&lease
-> n_hw
, MDL
);
1558 /* If the lease we're freeing is at the head of the list,
1559 remove the hash table entry and add a new one with the
1560 next lease on the list (if there is one). */
1561 if (head
== lease
) {
1562 lease_hash_delete (lease_hw_addr_hash
,
1563 lease
-> hardware_addr
.hbuf
,
1564 lease
-> hardware_addr
.hlen
, MDL
);
1565 if (lease
-> n_hw
) {
1566 lease_hash_add (lease_hw_addr_hash
,
1567 lease
-> n_hw
-> hardware_addr
.hbuf
,
1568 lease
-> n_hw
-> hardware_addr
.hlen
,
1569 lease
-> n_hw
, MDL
);
1570 lease_dereference (&lease
-> n_hw
, MDL
);
1573 /* Otherwise, look for the lease in the list of leases
1574 attached to the hash table entry, and remove it if
1576 for (scan
= head
; scan
-> n_hw
; scan
= scan
-> n_hw
) {
1577 if (scan
-> n_hw
== lease
) {
1578 lease_dereference (&scan
-> n_hw
, MDL
);
1579 if (lease
-> n_hw
) {
1580 lease_reference (&scan
-> n_hw
,
1581 lease
-> n_hw
, MDL
);
1582 lease_dereference (&lease
-> n_hw
,
1589 lease_dereference (&head
, MDL
);
1592 /* Write all interesting leases to permanent storage. */
1594 void write_leases ()
1597 struct shared_network
*s
;
1599 struct host_decl
*hp
;
1600 struct group_object
*gp
;
1601 struct hash_bucket
*hb
;
1604 struct lease
**lptr
[5];
1606 /* Write all the dynamically-created group declarations. */
1607 if (group_name_hash
) {
1609 for (i
= 0; i
< group_name_hash
-> hash_count
; i
++) {
1610 for (hb
= group_name_hash
-> buckets
[i
];
1611 hb
; hb
= hb
-> next
) {
1612 gp
= (struct group_object
*)hb
-> value
;
1613 if ((gp
-> flags
& GROUP_OBJECT_DYNAMIC
) ||
1614 ((gp
-> flags
& GROUP_OBJECT_STATIC
) &&
1615 (gp
-> flags
& GROUP_OBJECT_DELETED
))) {
1621 log_info ("Wrote %d group decls to leases file.", num_written
);
1624 /* Write all the deleted host declarations. */
1625 if (host_name_hash
) {
1627 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1628 for (hb
= host_name_hash
-> buckets
[i
];
1629 hb
; hb
= hb
-> next
) {
1630 hp
= (struct host_decl
*)hb
-> value
;
1631 if (((hp
-> flags
& HOST_DECL_STATIC
) &&
1632 (hp
-> flags
& HOST_DECL_DELETED
))) {
1638 log_info ("Wrote %d deleted host decls to leases file.",
1642 /* Write all the new, dynamic host declarations. */
1643 if (host_name_hash
) {
1645 for (i
= 0; i
< host_name_hash
-> hash_count
; i
++) {
1646 for (hb
= host_name_hash
-> buckets
[i
];
1647 hb
; hb
= hb
-> next
) {
1648 hp
= (struct host_decl
*)hb
-> value
;
1649 if ((hp
-> flags
& HOST_DECL_DYNAMIC
)) {
1655 log_info ("Wrote %d new dynamic host decls to leases file.",
1659 #if defined (FAILOVER_PROTOCOL)
1660 /* Write all the failover states. */
1661 dhcp_failover_write_all_states ();
1664 /* Write all the leases. */
1666 for (s
= shared_networks
; s
; s
= s
-> next
) {
1667 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1668 lptr
[FREE_LEASES
] = &p
-> free
;
1669 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1670 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1671 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1672 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1674 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1675 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1676 if (l
-> hardware_addr
.hlen
||
1678 (l
-> binding_state
!= FTS_FREE
)) {
1679 if (!write_lease (l
))
1680 log_fatal ("Can't rewrite lease database");
1687 log_info ("Wrote %d leases to leases file.", num_written
);
1688 if (!commit_leases ())
1689 log_fatal ("Can't commit leases to new database: %m");
1692 int lease_enqueue (struct lease
*comp
)
1694 struct lease
**lq
, *prev
, *lp
;
1696 /* No queue to put it on? */
1700 /* Figure out which queue it's going to. */
1701 switch (comp
-> binding_state
) {
1703 lq
= &comp
-> pool
-> free
;
1704 comp
-> pool
-> free_leases
++;
1705 comp
-> sort_time
= comp
-> ends
;
1711 lq
= &comp
-> pool
-> active
;
1712 comp
-> sort_time
= comp
-> ends
;
1718 lq
= &comp
-> pool
-> expired
;
1719 comp
-> sort_time
= comp
-> ends
;
1724 lq
= &comp
-> pool
-> abandoned
;
1725 comp
-> sort_time
= comp
-> ends
;
1729 lq
= &comp
-> pool
-> backup
;
1730 comp
-> pool
-> backup_leases
++;
1731 comp
-> sort_time
= comp
-> ends
;
1735 log_error ("Lease with bogus binding state: %d",
1736 comp
-> binding_state
);
1740 /* Insertion sort the lease onto the appropriate queue. */
1741 prev
= (struct lease
*)0;
1742 for (lp
= *lq
; lp
; lp
= lp
-> next
) {
1743 if (lp
-> sort_time
>= comp
-> sort_time
)
1749 lease_reference (&comp
-> next
, prev
-> next
, MDL
);
1750 lease_dereference (&prev
-> next
, MDL
);
1752 lease_reference (&prev
-> next
, comp
, MDL
);
1755 lease_reference (&comp
-> next
, *lq
, MDL
);
1756 lease_dereference (lq
, MDL
);
1758 lease_reference (lq
, comp
, MDL
);
1763 /* For a given lease, sort it onto the right list in its pool and put it
1764 in each appropriate hash, understanding that it's already by definition
1765 in lease_ip_addr_hash. */
1767 void lease_instantiate (const unsigned char *val
, unsigned len
,
1768 struct lease
*lease
)
1771 /* XXX If the lease doesn't have a pool at this point, it's an
1772 XXX orphan, which we *should* keep around until it expires,
1773 XXX but which right now we just forget. */
1774 if (!lease
-> pool
) {
1775 lease_hash_delete (lease_ip_addr_hash
,
1776 lease
-> ip_addr
.iabuf
,
1777 lease
-> ip_addr
.len
, MDL
);
1781 /* Put the lease on the right queue. */
1782 lease_enqueue (lease
);
1784 /* Record the lease in the uid hash if possible. */
1786 uid_hash_add (lease
);
1789 /* Record it in the hardware address hash if possible. */
1790 if (lease
-> hardware_addr
.hlen
) {
1791 hw_hash_add (lease
);
1797 /* Run expiry events on every pool. This is called on startup so that
1798 any expiry events that occurred after the server stopped and before it
1799 was restarted can be run. At the same time, if failover support is
1800 compiled in, we compute the balance of leases for the pool. */
1802 void expire_all_pools ()
1804 struct shared_network
*s
;
1806 struct hash_bucket
*hb
;
1809 struct lease
**lptr
[5];
1811 /* First, go over the hash list and actually put all the leases
1812 on the appropriate lists. */
1813 lease_hash_foreach (lease_ip_addr_hash
, lease_instantiate
);
1815 /* Loop through each pool in each shared network and call the
1816 expiry routine on the pool. */
1817 for (s
= shared_networks
; s
; s
= s
-> next
) {
1818 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1821 p
-> lease_count
= 0;
1822 p
-> free_leases
= 0;
1823 p
-> backup_leases
= 0;
1825 lptr
[FREE_LEASES
] = &p
-> free
;
1826 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1827 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1828 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1829 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1831 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1832 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1834 if (l
-> ends
<= cur_time
) {
1835 if (l
-> binding_state
== FTS_FREE
)
1837 else if (l
-> binding_state
== FTS_BACKUP
)
1838 p
-> backup_leases
++;
1840 #if defined (FAILOVER_PROTOCOL)
1841 if (p
-> failover_peer
&&
1842 l
-> tstp
> l
-> tsfp
&&
1843 !(l
-> flags
& ON_UPDATE_QUEUE
))
1844 dhcp_failover_queue_update (l
, 1);
1852 void dump_subnets ()
1855 struct shared_network
*s
;
1858 struct lease
**lptr
[5];
1861 log_info ("Subnets:");
1862 for (n
= subnets
; n
; n
= n
-> next_subnet
) {
1863 log_debug (" Subnet %s", piaddr (n
-> net
));
1864 log_debug (" netmask %s",
1865 piaddr (n
-> netmask
));
1867 log_info ("Shared networks:");
1868 for (s
= shared_networks
; s
; s
= s
-> next
) {
1869 log_info (" %s", s
-> name
);
1870 for (p
= s
-> pools
; p
; p
= p
-> next
) {
1871 lptr
[FREE_LEASES
] = &p
-> free
;
1872 lptr
[ACTIVE_LEASES
] = &p
-> active
;
1873 lptr
[EXPIRED_LEASES
] = &p
-> expired
;
1874 lptr
[ABANDONED_LEASES
] = &p
-> abandoned
;
1875 lptr
[BACKUP_LEASES
] = &p
-> backup
;
1877 for (i
= FREE_LEASES
; i
<= BACKUP_LEASES
; i
++) {
1878 for (l
= *(lptr
[i
]); l
; l
= l
-> next
) {
1886 HASH_FUNCTIONS (lease
, const unsigned char *, struct lease
)
1887 HASH_FUNCTIONS (host
, const unsigned char *, struct host_decl
)
1888 HASH_FUNCTIONS (class, const char *, struct class)