]> git.ipfire.org Git - thirdparty/dhcp.git/blob - server/mdb.c
Sync with 3.0rc7
[thirdparty/dhcp.git] / server / mdb.c
1 /* mdb.c
2
3 Server-specific in-memory database support. */
4
5 /*
6 * Copyright (c) 1996-2000 Internet Software Consortium.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
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.
21 *
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
34 * SUCH DAMAGE.
35 *
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''.
42 */
43
44 #ifndef lint
45 static char copyright[] =
46 "$Id: mdb.c,v 1.68 2001/05/17 19:04:08 mellon Exp $ Copyright (c) 1996-2000 The Internet Software Consortium. All rights reserved.\n";
47 #endif /* not lint */
48
49 #include "dhcpd.h"
50
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;
59
60 omapi_object_type_t *dhcp_type_host;
61
62 isc_result_t enter_host (hd, dynamicp, commit)
63 struct host_decl *hd;
64 int dynamicp;
65 int commit;
66 {
67 struct host_decl *hp = (struct host_decl *)0;
68 struct host_decl *np = (struct host_decl *)0;
69 struct executable_statement *esp;
70
71 if (!host_name_hash) {
72 host_name_hash =
73 new_hash ((hash_reference)host_reference,
74 (hash_dereference)host_dereference, 0);
75 if (!host_name_hash)
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);
80 } else {
81 host_hash_lookup (&hp, host_name_hash,
82 (unsigned char *)hd -> name,
83 strlen (hd -> name), MDL);
84
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;
94 }
95
96 /* If there isn't already a host decl matching this
97 address, add it to the hash table. */
98 if (!hp) {
99 host_hash_add (host_name_hash,
100 (unsigned char *)hd -> name,
101 strlen (hd -> name), hd, MDL);
102 } else {
103 /* XXX actually, we have to delete the old one
104 XXX carefully and replace it. Not done yet. */
105 host_dereference (&hp, MDL);
106 return ISC_R_EXISTS;
107 }
108 }
109
110 if (hd -> n_ipaddr)
111 host_dereference (&hd -> n_ipaddr, MDL);
112
113 if (!hd -> type)
114 hd -> type = dhcp_type_host;
115
116 if (hd -> interface.hlen) {
117 if (!host_hw_addr_hash) {
118 host_hw_addr_hash =
119 new_hash ((hash_reference)host_reference,
120 (hash_dereference)host_dereference,
121 0);
122 if (!host_hw_addr_hash)
123 log_fatal ("Can't allocate host/hw hash");
124 } else {
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);
130 }
131 if (!hp)
132 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
133 hd -> interface.hlen, hd, MDL);
134 else {
135 /* If there was already a host declaration for
136 this hardware address, add this one to the
137 end of the list. */
138 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
139 ;
140 host_reference (&np -> n_ipaddr, hd, MDL);
141 host_dereference (&hp, MDL);
142 }
143 }
144
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 ==
152 &dhcp_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);
161 break;
162 }
163 }
164
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) {
171 host_uid_hash =
172 new_hash ((hash_reference)host_reference,
173 (hash_dereference)host_dereference,
174 0);
175 if (!host_uid_hash)
176 log_fatal ("Can't allocate host/uid hash");
177
178 host_hash_add (host_uid_hash,
179 hd -> client_identifier.data,
180 hd -> client_identifier.len,
181 hd, MDL);
182 } else {
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,
189 MDL)) {
190 /* Don't link it in twice... */
191 if (!np) {
192 for (np = hp; np -> n_ipaddr;
193 np = np -> n_ipaddr) {
194 if (hd == np)
195 break;
196 }
197 if (hd != np)
198 host_reference (&np -> n_ipaddr,
199 hd, MDL);
200 }
201 host_dereference (&hp, MDL);
202 } else {
203 host_hash_add (host_uid_hash,
204 hd -> client_identifier.data,
205 hd -> client_identifier.len,
206 hd, MDL);
207 }
208 }
209 }
210
211 if (dynamicp && commit) {
212 if (!write_host (hd))
213 return ISC_R_IOERROR;
214 if (!commit_leases ())
215 return ISC_R_IOERROR;
216 }
217
218 return ISC_R_SUCCESS;
219 }
220
221 isc_result_t delete_host (hd, commit)
222 struct host_decl *hd;
223 int commit;
224 {
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;
230
231 /* Don't need to do it twice. */
232 if (hd -> flags & HOST_DECL_DELETED)
233 return ISC_R_SUCCESS;
234
235 /* But we do need to do it once! :') */
236 hd -> flags |= HOST_DECL_DELETED;
237
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)) {
243 if (hp == hd) {
244 host_hash_delete (host_hw_addr_hash,
245 hd -> interface.hbuf,
246 hd -> interface.hlen, MDL);
247 hw_head = 1;
248 } else {
249 np = (struct host_decl *)0;
250 foo = (struct host_decl *)0;
251 host_reference (&foo, hp, MDL);
252 while (foo) {
253 if (foo == hd)
254 break;
255 host_reference (&np, foo, MDL);
256 host_dereference (&foo, MDL);
257 if (np -> n_ipaddr)
258 host_reference (&foo, np -> n_ipaddr, MDL);
259 }
260
261 if (foo) {
262 host_dereference (&np -> n_ipaddr, MDL);
263 if (hd -> n_ipaddr)
264 host_reference (&np -> n_ipaddr,
265 hd -> n_ipaddr, MDL);
266 host_dereference (&foo, MDL);
267 }
268 if (np)
269 host_dereference (&np, MDL);
270 }
271 host_dereference (&hp, MDL);
272 }
273 }
274 }
275
276 /* If we got a client identifier, hash this entry by
277 client identifier. */
278 if (hd -> client_identifier.len) {
279 if (host_uid_hash) {
280 if (host_hash_lookup (&hp, host_uid_hash,
281 hd -> client_identifier.data,
282 hd -> client_identifier.len, MDL)) {
283 if (hp == hd) {
284 host_hash_delete (host_uid_hash,
285 hd -> client_identifier.data,
286 hd -> client_identifier.len, MDL);
287 uid_head = 1;
288 } else {
289 np = (struct host_decl *)0;
290 foo = (struct host_decl *)0;
291 host_reference (&foo, hp, MDL);
292 while (foo) {
293 if (foo == hd)
294 break;
295 host_reference (&np, foo, MDL);
296 host_dereference (&foo, MDL);
297 if (np -> n_ipaddr)
298 host_reference (&foo, np -> n_ipaddr, MDL);
299 }
300
301 if (foo) {
302 host_dereference (&np -> n_ipaddr, MDL);
303 if (hd -> n_ipaddr)
304 host_reference (&np -> n_ipaddr,
305 hd -> n_ipaddr, MDL);
306 host_dereference (&foo, MDL);
307 }
308 if (np)
309 host_dereference (&np, MDL);
310 }
311 host_dereference (&hp, MDL);
312 }
313 }
314 }
315
316 if (hd -> n_ipaddr) {
317 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
318 host_hash_add
319 (host_uid_hash,
320 hd -> n_ipaddr -> client_identifier.data,
321 hd -> n_ipaddr -> client_identifier.len,
322 hd -> n_ipaddr, MDL);
323 }
324 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
325 host_hash_add (host_hw_addr_hash,
326 hd -> n_ipaddr -> interface.hbuf,
327 hd -> n_ipaddr -> interface.hlen,
328 hd -> n_ipaddr, MDL);
329 }
330 host_dereference (&hd -> n_ipaddr, MDL);
331 }
332
333 if (host_name_hash) {
334 if (host_hash_lookup (&hp, host_name_hash,
335 (unsigned char *)hd -> name,
336 strlen (hd -> name), MDL)) {
337 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
338 host_hash_delete (host_name_hash,
339 (unsigned char *)hd -> name,
340 strlen (hd -> name), MDL);
341 }
342 host_dereference (&hp, MDL);
343 }
344 }
345
346 if (commit) {
347 if (!write_host (hd))
348 return ISC_R_IOERROR;
349 if (!commit_leases ())
350 return ISC_R_IOERROR;
351 }
352 return ISC_R_SUCCESS;
353 }
354
355 int find_hosts_by_haddr (struct host_decl **hp, int htype,
356 const unsigned char *haddr, unsigned hlen,
357 const char *file, int line)
358 {
359 struct host_decl *foo;
360 struct hardware h;
361
362 h.hlen = hlen + 1;
363 h.hbuf [0] = htype;
364 memcpy (&h.hbuf [1], haddr, hlen);
365
366 return host_hash_lookup (hp, host_hw_addr_hash,
367 h.hbuf, h.hlen, file, line);
368 }
369
370 int find_hosts_by_uid (struct host_decl **hp,
371 const unsigned char *data, unsigned len,
372 const char *file, int line)
373 {
374 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
375 }
376
377 /* More than one host_decl can be returned by find_hosts_by_haddr or
378 find_hosts_by_uid, and each host_decl can have multiple addresses.
379 Loop through the list of hosts, and then for each host, through the
380 list of addresses, looking for an address that's in the same shared
381 network as the one specified. Store the matching address through
382 the addr pointer, update the host pointer to point at the host_decl
383 that matched, and return the subnet that matched. */
384
385 int find_host_for_network (struct subnet **sp, struct host_decl **host,
386 struct iaddr *addr, struct shared_network *share)
387 {
388 int i;
389 struct subnet *subnet;
390 struct iaddr ip_address;
391 struct host_decl *hp;
392 struct data_string fixed_addr;
393
394 memset (&fixed_addr, 0, sizeof fixed_addr);
395
396 for (hp = *host; hp; hp = hp -> n_ipaddr) {
397 if (!hp -> fixed_addr)
398 continue;
399 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
400 (struct lease *)0,
401 (struct client_state *)0,
402 (struct option_state *)0,
403 (struct option_state *)0,
404 &global_scope,
405 hp -> fixed_addr, MDL))
406 continue;
407 for (i = 0; i < fixed_addr.len; i += 4) {
408 ip_address.len = 4;
409 memcpy (ip_address.iabuf,
410 fixed_addr.data + i, 4);
411 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
412 struct host_decl *tmp = (struct host_decl *)0;
413 *addr = ip_address;
414 /* This is probably not necessary, but
415 just in case *host is the only reference
416 to that host declaration, make a temporary
417 reference so that dereferencing it doesn't
418 dereference hp out from under us. */
419 host_reference (&tmp, *host, MDL);
420 host_dereference (host, MDL);
421 host_reference (host, hp, MDL);
422 host_dereference (&tmp, MDL);
423 data_string_forget (&fixed_addr, MDL);
424 return 1;
425 }
426 }
427 data_string_forget (&fixed_addr, MDL);
428 }
429 return 0;
430 }
431
432 void new_address_range (low, high, subnet, pool)
433 struct iaddr low, high;
434 struct subnet *subnet;
435 struct pool *pool;
436 {
437 struct lease *address_range, *lp, *plp;
438 struct iaddr net;
439 unsigned min, max, i;
440 char lowbuf [16], highbuf [16], netbuf [16];
441 struct shared_network *share = subnet -> shared_network;
442 isc_result_t status;
443 struct lease *lt = (struct lease *)0;
444
445 /* All subnets should have attached shared network structures. */
446 if (!share) {
447 strcpy (netbuf, piaddr (subnet -> net));
448 log_fatal ("No shared network for network %s (%s)",
449 netbuf, piaddr (subnet -> netmask));
450 }
451
452 /* Initialize the hash table if it hasn't been done yet. */
453 if (!lease_uid_hash) {
454 lease_uid_hash =
455 new_hash ((hash_reference)lease_reference,
456 (hash_dereference)lease_dereference, 0);
457 if (!lease_uid_hash)
458 log_fatal ("Can't allocate lease/uid hash");
459 }
460 if (!lease_ip_addr_hash) {
461 lease_ip_addr_hash =
462 new_hash ((hash_reference)lease_reference,
463 (hash_dereference)lease_dereference, 0);
464 if (!lease_uid_hash)
465 log_fatal ("Can't allocate lease/ip hash");
466 }
467 if (!lease_hw_addr_hash) {
468 lease_hw_addr_hash =
469 new_hash ((hash_reference)lease_reference,
470 (hash_dereference)lease_dereference, 0);
471 if (!lease_uid_hash)
472 log_fatal ("Can't allocate lease/hw hash");
473 }
474
475 /* Make sure that high and low addresses are in same subnet. */
476 net = subnet_number (low, subnet -> netmask);
477 if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
478 strcpy (lowbuf, piaddr (low));
479 strcpy (highbuf, piaddr (high));
480 strcpy (netbuf, piaddr (subnet -> netmask));
481 log_fatal ("Address range %s to %s, netmask %s spans %s!",
482 lowbuf, highbuf, netbuf, "multiple subnets");
483 }
484
485 /* Make sure that the addresses are on the correct subnet. */
486 if (!addr_eq (net, subnet -> net)) {
487 strcpy (lowbuf, piaddr (low));
488 strcpy (highbuf, piaddr (high));
489 strcpy (netbuf, piaddr (subnet -> netmask));
490 log_fatal ("Address range %s to %s not on net %s/%s!",
491 lowbuf, highbuf, piaddr (subnet -> net), netbuf);
492 }
493
494 /* Get the high and low host addresses... */
495 max = host_addr (high, subnet -> netmask);
496 min = host_addr (low, subnet -> netmask);
497
498 /* Allow range to be specified high-to-low as well as low-to-high. */
499 if (min > max) {
500 max = min;
501 min = host_addr (high, subnet -> netmask);
502 }
503
504 /* Get a lease structure for each address in the range. */
505 #if defined (COMPACT_LEASES)
506 address_range = new_leases (max - min + 1, MDL);
507 if (!address_range) {
508 strcpy (lowbuf, piaddr (low));
509 strcpy (highbuf, piaddr (high));
510 log_fatal ("No memory for address range %s-%s.",
511 lowbuf, highbuf);
512 }
513 #endif
514
515 /* Fill out the lease structures with some minimal information. */
516 for (i = 0; i < max - min + 1; i++) {
517 struct lease *lp = (struct lease *)0;
518 #if defined (COMPACT_LEASES)
519 omapi_object_initialize ((omapi_object_t *)&address_range [i],
520 dhcp_type_lease,
521 0, sizeof (struct lease), MDL);
522 lease_reference (&lp, &address_range [i], MDL);
523 #else
524 status = lease_allocate (&lp, MDL);
525 if (status != ISC_R_SUCCESS)
526 log_fatal ("No memory for lease %s: %s",
527 piaddr (ip_addr (subnet -> net,
528 subnet -> netmask,
529 i + min)),
530 isc_result_totext (status));
531 #endif
532 lp -> ip_addr = ip_addr (subnet -> net,
533 subnet -> netmask, i + min);
534 lp -> starts = lp -> timestamp = MIN_TIME;
535 lp -> ends = MIN_TIME;
536 subnet_reference (&lp -> subnet, subnet, MDL);
537 pool_reference (&lp -> pool, pool, MDL);
538 lp -> binding_state = FTS_FREE;
539 lp -> next_binding_state = FTS_FREE;
540 lp -> flags = 0;
541
542 /* Remember the lease in the IP address hash. */
543 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
544 if (lt -> pool) {
545 log_error ("duplicate entries for lease %s",
546 piaddr (lp -> ip_addr));
547 } else
548 pool_reference (&lt -> pool, pool, MDL);
549 lease_dereference (&lt, MDL);
550 } else
551 lease_hash_add (lease_ip_addr_hash,
552 lp -> ip_addr.iabuf,
553 lp -> ip_addr.len, lp, MDL);
554 lease_dereference (&lp, MDL);
555 }
556 }
557
558
559 #if defined (COMPACT_LEASES)
560 struct lease *free_leases;
561
562 /* If we are allocating leases in aggregations, there's really no way
563 to free one, although perhaps we can maintain a free list. */
564
565 isc_result_t dhcp_lease_free (omapi_object_t *lo,
566 const char *file, int line)
567 {
568 struct lease *lease;
569 if (lo -> type != dhcp_type_lease)
570 return ISC_R_INVALIDARG;
571 lease = (struct lease *)lo;
572 lease -> next = free_leases;
573 free_leases = lease;
574 return ISC_R_SUCCESS;
575 }
576
577 isc_result_t dhcp_lease_get (omapi_object_t **lp,
578 const char *file, int line)
579 {
580 struct lease **lease = (struct lease **)lp;
581 struct lease *lt;
582
583 if (free_leases) {
584 lt = free_leases;
585 free_leases = lt -> next;
586 *lease = lt;
587 return ISC_R_SUCCESS;
588 }
589 return ISC_R_NOMEMORY;
590 }
591 #endif
592
593 int find_subnet (struct subnet **sp,
594 struct iaddr addr, const char *file, int line)
595 {
596 struct subnet *rv;
597
598 for (rv = subnets; rv; rv = rv -> next_subnet) {
599 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
600 if (subnet_reference (sp, rv,
601 file, line) != ISC_R_SUCCESS)
602 return 0;
603 return 1;
604 }
605 }
606 return 0;
607 }
608
609 int find_grouped_subnet (struct subnet **sp,
610 struct shared_network *share, struct iaddr addr,
611 const char *file, int line)
612 {
613 struct subnet *rv;
614
615 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
616 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
617 if (subnet_reference (sp, rv,
618 file, line) != ISC_R_SUCCESS)
619 return 0;
620 return 1;
621 }
622 }
623 return 0;
624 }
625
626 int subnet_inner_than (subnet, scan, warnp)
627 struct subnet *subnet, *scan;
628 int warnp;
629 {
630 if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
631 scan -> net) ||
632 addr_eq (subnet_number (scan -> net, subnet -> netmask),
633 subnet -> net)) {
634 char n1buf [16];
635 int i, j;
636 for (i = 0; i < 32; i++)
637 if (subnet -> netmask.iabuf [3 - (i >> 3)]
638 & (1 << (i & 7)))
639 break;
640 for (j = 0; j < 32; j++)
641 if (scan -> netmask.iabuf [3 - (j >> 3)] &
642 (1 << (j & 7)))
643 break;
644 strcpy (n1buf, piaddr (subnet -> net));
645 if (warnp)
646 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
647 "Warning: ", n1buf, 32 - i,
648 piaddr (scan -> net), 32 - j);
649 if (i < j)
650 return 1;
651 }
652 return 0;
653 }
654
655 /* Enter a new subnet into the subnet list. */
656 void enter_subnet (subnet)
657 struct subnet *subnet;
658 {
659 struct subnet *scan, *prev = (struct subnet *)0;
660
661 /* Check for duplicates... */
662 for (scan = subnets; scan; scan = scan -> next_subnet) {
663 /* When we find a conflict, make sure that the
664 subnet with the narrowest subnet mask comes
665 first. */
666 if (subnet_inner_than (subnet, scan, 1)) {
667 if (prev) {
668 subnet_reference (&prev -> next_subnet,
669 subnet, MDL);
670 } else
671 subnet_reference (&subnets, subnet, MDL);
672 subnet_reference (&subnet -> next_subnet, scan, MDL);
673 return;
674 }
675 prev = scan;
676 }
677
678 /* XXX use the BSD radix tree code instead of a linked list. */
679 subnet -> next_subnet = subnets;
680 subnets = subnet;
681 }
682
683 /* Enter a new shared network into the shared network list. */
684
685 void enter_shared_network (share)
686 struct shared_network *share;
687 {
688 if (shared_networks) {
689 shared_network_reference (&share -> next,
690 shared_networks, MDL);
691 shared_network_dereference (&shared_networks, MDL);
692 }
693 shared_network_reference (&shared_networks, share, MDL);
694 }
695
696 void new_shared_network_interface (cfile, share, name)
697 struct parse *cfile;
698 struct shared_network *share;
699 const char *name;
700 {
701 struct interface_info *ip;
702 isc_result_t status;
703
704 if (share -> interface) {
705 parse_warn (cfile,
706 "A subnet or shared network can't be connected %s",
707 "to two interfaces.");
708 return;
709 }
710
711 for (ip = interfaces; ip; ip = ip -> next)
712 if (!strcmp (ip -> name, name))
713 break;
714 if (!ip) {
715 status = interface_allocate (&ip, MDL);
716 if (status != ISC_R_SUCCESS)
717 log_fatal ("new_shared_network_interface %s: %s",
718 name, isc_result_totext (status));
719 if (strlen (name) > sizeof ip -> name) {
720 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
721 ip -> name [(sizeof ip -> name) - 1] = 0;
722 } else
723 strcpy (ip -> name, name);
724 if (interfaces) {
725 interface_reference (&ip -> next, interfaces, MDL);
726 interface_dereference (&interfaces, MDL);
727 }
728 interface_reference (&interfaces, ip, MDL);
729 ip -> flags = INTERFACE_REQUESTED;
730 /* XXX this is a reference loop. */
731 shared_network_reference (&ip -> shared_network, share, MDL);
732 interface_reference (&share -> interface, ip, MDL);
733 }
734 }
735
736 /* Enter a lease into the system. This is called by the parser each
737 time it reads in a new lease. If the subnet for that lease has
738 already been read in (usually the case), just update that lease;
739 otherwise, allocate temporary storage for the lease and keep it around
740 until we're done reading in the config file. */
741
742 void enter_lease (lease)
743 struct lease *lease;
744 {
745 struct lease *comp = (struct lease *)0;
746 isc_result_t status;
747
748 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
749 if (!comp -> pool) {
750 log_error ("undeclared lease found in database: %s",
751 piaddr (lease -> ip_addr));
752 } else
753 pool_reference (&lease -> pool, comp -> pool, MDL);
754
755 if (comp -> subnet)
756 subnet_reference (&lease -> subnet,
757 comp -> subnet, MDL);
758 lease_hash_delete (lease_ip_addr_hash,
759 lease -> ip_addr.iabuf,
760 lease -> ip_addr.len, MDL);
761 lease_dereference (&comp, MDL);
762 }
763
764 /* The only way a lease can get here without a subnet is if it's in
765 the lease file, but not in the dhcpd.conf file. In this case, we
766 *should* keep it around until it's expired, but never reallocate it
767 or renew it. Currently, to maintain consistency, we are not doing
768 this.
769 XXX fix this so that the lease is kept around until it expires.
770 XXX this will be important in IPv6 with addresses that become
771 XXX non-renewable as a result of a renumbering event. */
772
773 if (!lease -> subnet) {
774 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
775 return;
776 }
777 lease_hash_add (lease_ip_addr_hash,
778 lease -> ip_addr.iabuf,
779 lease -> ip_addr.len, lease, MDL);
780 }
781
782 /* Replace the data in an existing lease with the data in a new lease;
783 adjust hash tables to suit, and insertion sort the lease into the
784 list of leases by expiry time so that we can always find the oldest
785 lease. */
786
787 int supersede_lease (comp, lease, commit, propogate, pimmediate)
788 struct lease *comp, *lease;
789 int commit;
790 int propogate;
791 int pimmediate;
792 {
793 int enter_uid = 0;
794 int enter_hwaddr = 0;
795 struct lease *lp, **lq, *prev;
796 TIME lp_next_state;
797
798 #if defined (FAILOVER_PROTOCOL)
799 /* We must commit leases before sending updates regarding them
800 to failover peers. It is, therefore, an error to set pimmediate
801 and not commit. */
802 if (pimmediate && !commit)
803 return 0;
804 #endif
805
806 /* If there is no sample lease, just do the move. */
807 if (!lease)
808 goto just_move_it;
809
810 /* Static leases are not currently kept in the database... */
811 if (lease -> flags & STATIC_LEASE)
812 return 1;
813
814 /* If the existing lease hasn't expired and has a different
815 unique identifier or, if it doesn't have a unique
816 identifier, a different hardware address, then the two
817 leases are in conflict. If the existing lease has a uid
818 and the new one doesn't, but they both have the same
819 hardware address, and dynamic bootp is allowed on this
820 lease, then we allow that, in case a dynamic BOOTP lease is
821 requested *after* a DHCP lease has been assigned. */
822
823 if (lease -> binding_state != FTS_ABANDONED &&
824 lease -> next_binding_state != FTS_ABANDONED &&
825 (comp -> binding_state == FTS_ACTIVE ||
826 comp -> binding_state == FTS_RESERVED ||
827 comp -> binding_state == FTS_BOOTP) &&
828 (((comp -> uid && lease -> uid) &&
829 (comp -> uid_len != lease -> uid_len ||
830 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
831 (!comp -> uid &&
832 ((comp -> hardware_addr.hlen !=
833 lease -> hardware_addr.hlen) ||
834 memcmp (comp -> hardware_addr.hbuf,
835 lease -> hardware_addr.hbuf,
836 comp -> hardware_addr.hlen))))) {
837 log_error ("Lease conflict at %s",
838 piaddr (comp -> ip_addr));
839 return 0;
840 }
841
842 /* If there's a Unique ID, dissociate it from the hash
843 table and free it if necessary. */
844 if (comp -> uid) {
845 uid_hash_delete (comp);
846 enter_uid = 1;
847 if (comp -> uid != &comp -> uid_buf [0]) {
848 dfree (comp -> uid, MDL);
849 comp -> uid_max = 0;
850 comp -> uid_len = 0;
851 }
852 comp -> uid = (unsigned char *)0;
853 } else
854 enter_uid = 1;
855
856 if (comp -> hardware_addr.hlen &&
857 ((comp -> hardware_addr.hlen !=
858 lease -> hardware_addr.hlen) ||
859 memcmp (comp -> hardware_addr.hbuf,
860 lease -> hardware_addr.hbuf,
861 comp -> hardware_addr.hlen))) {
862 hw_hash_delete (comp);
863 enter_hwaddr = 1;
864 } else if (!comp -> hardware_addr.hlen)
865 enter_hwaddr = 1;
866
867 /* If the lease has been billed to a class, remove the billing. */
868 if (comp -> billing_class != lease -> billing_class) {
869 if (comp -> billing_class)
870 unbill_class (comp, comp -> billing_class);
871 if (lease -> billing_class)
872 bill_class (comp, lease -> billing_class);
873 }
874
875 /* Copy the data files, but not the linkages. */
876 comp -> starts = lease -> starts;
877 if (lease -> uid) {
878 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
879 memcpy (comp -> uid_buf,
880 lease -> uid, lease -> uid_len);
881 comp -> uid = &comp -> uid_buf [0];
882 comp -> uid_max = sizeof comp -> uid_buf;
883 comp -> uid_len = lease -> uid_len;
884 } else if (lease -> uid != &lease -> uid_buf [0]) {
885 comp -> uid = lease -> uid;
886 comp -> uid_max = lease -> uid_max;
887 lease -> uid = (unsigned char *)0;
888 lease -> uid_max = 0;
889 comp -> uid_len = lease -> uid_len;
890 lease -> uid_len = 0;
891 } else {
892 log_fatal ("corrupt lease uid."); /* XXX */
893 }
894 } else {
895 comp -> uid = (unsigned char *)0;
896 comp -> uid_len = comp -> uid_max = 0;
897 }
898 if (comp -> host)
899 host_dereference (&comp -> host, MDL);
900 host_reference (&comp -> host, lease -> host, MDL);
901 comp -> hardware_addr = lease -> hardware_addr;
902 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
903 (comp -> flags & ~EPHEMERAL_FLAGS));
904 if (comp -> scope)
905 binding_scope_dereference (&comp -> scope, MDL);
906 if (lease -> scope) {
907 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
908 binding_scope_dereference (&lease -> scope, MDL);
909 }
910
911 if (comp -> agent_options)
912 option_chain_head_dereference (&comp -> agent_options, MDL);
913 if (lease -> agent_options) {
914 /* Only retain the agent options if the lease is still
915 affirmatively associated with a client. */
916 if (lease -> next_binding_state == FTS_ACTIVE ||
917 lease -> next_binding_state == FTS_EXPIRED ||
918 lease -> next_binding_state == FTS_RESERVED ||
919 lease -> next_binding_state == FTS_BOOTP)
920 option_chain_head_reference (&comp -> agent_options,
921 lease -> agent_options,
922 MDL);
923 option_chain_head_dereference (&lease -> agent_options, MDL);
924 }
925
926 /* Record the hostname information in the lease. */
927 if (comp -> client_hostname)
928 dfree (comp -> client_hostname, MDL);
929 comp -> client_hostname = lease -> client_hostname;
930 lease -> client_hostname = (char *)0;
931
932 if (lease -> on_expiry) {
933 if (comp -> on_expiry)
934 executable_statement_dereference (&comp -> on_expiry,
935 MDL);
936 executable_statement_reference (&comp -> on_expiry,
937 lease -> on_expiry,
938 MDL);
939 }
940 if (lease -> on_commit) {
941 if (comp -> on_commit)
942 executable_statement_dereference (&comp -> on_commit,
943 MDL);
944 executable_statement_reference (&comp -> on_commit,
945 lease -> on_commit,
946 MDL);
947 }
948 if (lease -> on_release) {
949 if (comp -> on_release)
950 executable_statement_dereference (&comp -> on_release,
951 MDL);
952 executable_statement_reference (&comp -> on_release,
953 lease -> on_release, MDL);
954 }
955
956 /* Record the lease in the uid hash if necessary. */
957 if (enter_uid && comp -> uid) {
958 uid_hash_add (comp);
959 }
960
961 /* Record it in the hardware address hash if necessary. */
962 if (enter_hwaddr && lease -> hardware_addr.hlen) {
963 hw_hash_add (comp);
964 }
965
966 #if defined (FAILOVER_PROTOCOL)
967 comp -> cltt = lease -> cltt;
968 comp -> tstp = lease -> tstp;
969 comp -> tsfp = lease -> tsfp;
970 #endif /* FAILOVER_PROTOCOL */
971 comp -> ends = lease -> ends;
972 comp -> next_binding_state = lease -> next_binding_state;
973
974 just_move_it:
975 if (!comp -> pool) {
976 log_error ("Supersede_lease: lease %s with no pool.",
977 piaddr (comp -> ip_addr));
978 return 0;
979 }
980
981 /* Figure out which queue it's on. */
982 switch (comp -> binding_state) {
983 case FTS_FREE:
984 lq = &comp -> pool -> free;
985 comp -> pool -> free_leases--;
986 break;
987
988 case FTS_ACTIVE:
989 case FTS_RESERVED:
990 case FTS_BOOTP:
991 lq = &comp -> pool -> active;
992 break;
993
994 case FTS_EXPIRED:
995 case FTS_RELEASED:
996 case FTS_RESET:
997 lq = &comp -> pool -> expired;
998 break;
999
1000 case FTS_ABANDONED:
1001 lq = &comp -> pool -> abandoned;
1002 break;
1003
1004 case FTS_BACKUP:
1005 lq = &comp -> pool -> backup;
1006 comp -> pool -> backup_leases--;
1007 break;
1008
1009 default:
1010 log_error ("Lease with bogus binding state: %d",
1011 comp -> binding_state);
1012 #if defined (BINDING_STATE_DEBUG)
1013 abort ();
1014 #endif
1015 return 0;
1016 }
1017
1018 /* Remove the lease from its current place in its current
1019 timer sequence. */
1020 prev = (struct lease *)0;
1021 for (lp = *lq; lp; lp = lp -> next) {
1022 if (lp == comp)
1023 break;
1024 prev = lp;
1025 }
1026
1027 if (!lp) {
1028 log_error ("Lease with binding state %s not on its queue.",
1029 (comp -> binding_state < 1 &&
1030 comp -> binding_state < FTS_BOOTP)
1031 ? "unknown"
1032 : binding_state_names [comp -> binding_state - 1]);
1033 return 0;
1034 }
1035
1036 if (prev) {
1037 lease_dereference (&prev -> next, MDL);
1038 if (comp -> next) {
1039 lease_reference (&prev -> next, comp -> next, MDL);
1040 lease_dereference (&comp -> next, MDL);
1041 }
1042 } else {
1043 lease_dereference (lq, MDL);
1044 if (comp -> next) {
1045 lease_reference (lq, comp -> next, MDL);
1046 lease_dereference (&comp -> next, MDL);
1047 }
1048 }
1049
1050 /* Make the state transition. */
1051 if (commit || !pimmediate)
1052 make_binding_state_transition (comp);
1053
1054 /* Put the lease back on the appropriate queue. If the lease
1055 is corrupt (as detected by lease_enqueue), don't go any farther. */
1056 if (!lease_enqueue (comp))
1057 return 0;
1058
1059 /* If this is the next lease that will timeout on the pool,
1060 zap the old timeout and set the timeout on this pool to the
1061 time that the lease's next event will happen.
1062
1063 We do not actually set the timeout unless commit is true -
1064 we don't want to thrash the timer queue when reading the
1065 lease database. Instead, the database code calls the
1066 expiry event on each pool after reading in the lease file,
1067 and the expiry code sets the timer if there's anything left
1068 to expire after it's run any outstanding expiry events on
1069 the pool. */
1070 if ((commit || !pimmediate) &&
1071 comp -> sort_time != MIN_TIME &&
1072 comp -> sort_time > cur_time &&
1073 (comp -> sort_time < comp -> pool -> next_event_time ||
1074 comp -> pool -> next_event_time == MIN_TIME)) {
1075 comp -> pool -> next_event_time = comp -> sort_time;
1076 add_timeout (comp -> pool -> next_event_time,
1077 pool_timer, comp -> pool,
1078 (tvref_t)pool_reference,
1079 (tvunref_t)pool_dereference);
1080 }
1081
1082 if (commit) {
1083 if (!write_lease (comp))
1084 return 0;
1085 if (!commit_leases ())
1086 return 0;
1087 }
1088
1089 #if defined (FAILOVER_PROTOCOL)
1090 if (propogate) {
1091 if (!dhcp_failover_queue_update (comp, pimmediate))
1092 return 0;
1093 }
1094 #endif
1095
1096 return 1;
1097 }
1098
1099 void make_binding_state_transition (struct lease *lease)
1100 {
1101 #if defined (FAILOVER_PROTOCOL)
1102 dhcp_failover_state_t *peer;
1103
1104 if (lease && lease -> pool && lease -> pool -> failover_peer)
1105 peer = lease -> pool -> failover_peer;
1106 else
1107 peer = (dhcp_failover_state_t *)0;
1108 #endif
1109
1110 /* If the lease was active and is now no longer active, but isn't
1111 released, then it just expired, so do the expiry event. */
1112 if (lease -> next_binding_state != lease -> binding_state &&
1113 ((
1114 #if defined (FAILOVER_PROTOCOL)
1115 peer &&
1116 lease -> binding_state == FTS_EXPIRED &&
1117 (lease -> next_binding_state == FTS_FREE ||
1118 lease -> next_binding_state == FTS_BACKUP)) ||
1119 (!peer &&
1120 #endif
1121 (lease -> binding_state == FTS_ACTIVE ||
1122 lease -> binding_state == FTS_BOOTP ||
1123 lease -> binding_state == FTS_RESERVED) &&
1124 lease -> next_binding_state != FTS_RELEASED))) {
1125 #if defined (NSUPDATE)
1126 ddns_removals (lease);
1127 #endif
1128 if (lease -> on_expiry) {
1129 execute_statements ((struct binding_value **)0,
1130 (struct packet *)0, lease,
1131 (struct client_state *)0,
1132 (struct option_state *)0,
1133 (struct option_state *)0, /* XXX */
1134 &lease -> scope,
1135 lease -> on_expiry);
1136 if (lease -> on_expiry)
1137 executable_statement_dereference
1138 (&lease -> on_expiry, MDL);
1139 }
1140
1141 /* No sense releasing a lease after it's expired. */
1142 if (lease -> on_release)
1143 executable_statement_dereference (&lease -> on_release,
1144 MDL);
1145 if (lease -> billing_class)
1146 unbill_class (lease, lease -> billing_class);
1147
1148 /* Send the expiry time to the peer. */
1149 lease -> tstp = lease -> ends;
1150 }
1151
1152 /* If the lease was active and is now released, do the release
1153 event. */
1154 if (lease -> next_binding_state != lease -> binding_state &&
1155 ((
1156 #if defined (FAILOVER_PROTOCOL)
1157 peer &&
1158 lease -> binding_state == FTS_RELEASED &&
1159 (lease -> next_binding_state == FTS_FREE ||
1160 lease -> next_binding_state == FTS_BACKUP)) ||
1161 (!peer &&
1162 #endif
1163 (lease -> binding_state == FTS_ACTIVE ||
1164 lease -> binding_state == FTS_BOOTP ||
1165 lease -> binding_state == FTS_RESERVED) &&
1166 lease -> next_binding_state == FTS_RELEASED))) {
1167 #if defined (NSUPDATE)
1168 ddns_removals (lease);
1169 #endif
1170 if (lease -> on_release) {
1171 execute_statements ((struct binding_value **)0,
1172 (struct packet *)0, lease,
1173 (struct client_state *)0,
1174 (struct option_state *)0,
1175 (struct option_state *)0, /* XXX */
1176 &lease -> scope,
1177 lease -> on_release);
1178 executable_statement_dereference (&lease -> on_release,
1179 MDL);
1180 }
1181
1182 /* A released lease can't expire. */
1183 if (lease -> on_expiry)
1184 executable_statement_dereference (&lease -> on_expiry,
1185 MDL);
1186
1187 if (lease -> billing_class)
1188 unbill_class (lease, lease -> billing_class);
1189
1190 /* Send the release time (should be == cur_time) to the
1191 peer. */
1192 lease -> tstp = lease -> ends;
1193 }
1194
1195 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1196 log_debug ("lease %s moves from %s to %s",
1197 piaddr (lease -> ip_addr),
1198 binding_state_print (lease -> binding_state),
1199 binding_state_print (lease -> next_binding_state));
1200 #endif
1201
1202 lease -> binding_state = lease -> next_binding_state;
1203 switch (lease -> binding_state) {
1204 case FTS_ACTIVE:
1205 case FTS_BOOTP:
1206 #if defined (FAILOVER_PROTOCOL)
1207 if (lease -> pool && lease -> pool -> failover_peer)
1208 lease -> next_binding_state = FTS_EXPIRED;
1209 else
1210 #endif
1211 lease -> next_binding_state = FTS_FREE;
1212 break;
1213
1214 case FTS_EXPIRED:
1215 case FTS_RELEASED:
1216 case FTS_ABANDONED:
1217 case FTS_RESET:
1218 lease -> next_binding_state = FTS_FREE;
1219 /* If we are not in partner_down, leases don't go from
1220 EXPIRED to FREE on a timeout - only on an update.
1221 If we're in partner_down, they expire at mclt past
1222 the time we entered partner_down. */
1223 if (lease -> pool -> failover_peer &&
1224 lease -> pool -> failover_peer -> me.state == partner_down)
1225 lease -> tsfp =
1226 (lease -> pool -> failover_peer -> me.stos +
1227 lease -> pool -> failover_peer -> mclt);
1228 break;
1229
1230 case FTS_FREE:
1231 case FTS_BACKUP:
1232 case FTS_RESERVED:
1233 lease -> next_binding_state = lease -> binding_state;
1234 break;
1235 }
1236 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1237 log_debug ("lease %s: next binding state %s",
1238 piaddr (lease -> ip_addr),
1239 binding_state_print (lease -> next_binding_state));
1240 #endif
1241
1242 }
1243
1244 /* Copy the contents of one lease into another, correctly maintaining
1245 reference counts. */
1246 int lease_copy (struct lease **lp,
1247 struct lease *lease, const char *file, int line)
1248 {
1249 struct lease *lt = (struct lease *)0;
1250 isc_result_t status;
1251
1252 status = lease_allocate (&lt, MDL);
1253 if (status != ISC_R_SUCCESS)
1254 return 0;
1255
1256 lt -> ip_addr = lease -> ip_addr;
1257 lt -> starts = lease -> starts;
1258 lt -> ends = lease -> ends;
1259 lt -> timestamp = lease -> timestamp;
1260 lt -> uid_len = lease -> uid_len;
1261 lt -> uid_max = lease -> uid_max;
1262 if (lease -> uid == lease -> uid_buf) {
1263 lt -> uid = lt -> uid_buf;
1264 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1265 } else if (!lease -> uid_max) {
1266 lt -> uid = (unsigned char *)0;
1267 } else {
1268 lt -> uid = dmalloc (lt -> uid_max, MDL);
1269 if (!lt -> uid) {
1270 lease_dereference (&lt, MDL);
1271 return 0;
1272 }
1273 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1274 }
1275 if (lease -> client_hostname) {
1276 lt -> client_hostname =
1277 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1278 if (!lt -> client_hostname) {
1279 lease_dereference (&lt, MDL);
1280 return 0;
1281 }
1282 strcpy (lt -> client_hostname, lease -> client_hostname);
1283 }
1284 if (lease -> scope)
1285 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1286 if (lease -> agent_options)
1287 option_chain_head_reference (&lt -> agent_options,
1288 lease -> agent_options, MDL);
1289 host_reference (&lt -> host, lease -> host, file, line);
1290 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1291 pool_reference (&lt -> pool, lease -> pool, file, line);
1292 class_reference (&lt -> billing_class,
1293 lease -> billing_class, file, line);
1294 lt -> hardware_addr = lease -> hardware_addr;
1295 if (lease -> on_expiry)
1296 executable_statement_reference (&lt -> on_expiry,
1297 lease -> on_expiry,
1298 file, line);
1299 if (lease -> on_commit)
1300 executable_statement_reference (&lt -> on_commit,
1301 lease -> on_commit,
1302 file, line);
1303 if (lease -> on_release)
1304 executable_statement_reference (&lt -> on_release,
1305 lease -> on_release,
1306 file, line);
1307 lt -> flags = lease -> flags;
1308 lt -> tstp = lease -> tstp;
1309 lt -> tsfp = lease -> tsfp;
1310 lt -> cltt = lease -> cltt;
1311 lt -> binding_state = lease -> binding_state;
1312 lt -> next_binding_state = lease -> next_binding_state;
1313 status = lease_reference (lp, lt, file, line);
1314 lease_dereference (&lt, MDL);
1315 return status == ISC_R_SUCCESS;
1316 }
1317
1318 /* Release the specified lease and re-hash it as appropriate. */
1319 void release_lease (lease, packet)
1320 struct lease *lease;
1321 struct packet *packet;
1322 {
1323 /* If there are statements to execute when the lease is
1324 released, execute them. */
1325 #if defined (NSUPDATE)
1326 ddns_removals (lease);
1327 #endif
1328 if (lease -> on_release) {
1329 execute_statements ((struct binding_value **)0,
1330 packet, lease, (struct client_state *)0,
1331 packet -> options,
1332 (struct option_state *)0, /* XXX */
1333 &lease -> scope, lease -> on_release);
1334 if (lease -> on_release)
1335 executable_statement_dereference (&lease -> on_release,
1336 MDL);
1337 }
1338
1339 /* We do either the on_release or the on_expiry events, but
1340 not both (it's possible that they could be the same,
1341 in any case). */
1342 if (lease -> on_expiry)
1343 executable_statement_dereference (&lease -> on_expiry, MDL);
1344
1345 if (lease -> binding_state != FTS_FREE &&
1346 lease -> binding_state != FTS_BACKUP &&
1347 lease -> binding_state != FTS_RELEASED &&
1348 lease -> binding_state != FTS_EXPIRED &&
1349 lease -> binding_state != FTS_RESET) {
1350 if (lease -> on_commit)
1351 executable_statement_dereference (&lease -> on_commit,
1352 MDL);
1353
1354 /* Blow away any bindings. */
1355 if (lease -> scope)
1356 binding_scope_dereference (&lease -> scope, MDL);
1357 lease -> ends = cur_time;
1358 #if defined (FAILOVER_PROTOCOL)
1359 if (lease -> pool && lease -> pool -> failover_peer) {
1360 lease -> next_binding_state = FTS_RELEASED;
1361 } else {
1362 lease -> next_binding_state = FTS_FREE;
1363 }
1364 #else
1365 lease -> next_binding_state = FTS_FREE;
1366 #endif
1367 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1368 }
1369 }
1370
1371 /* Abandon the specified lease (set its timeout to infinity and its
1372 particulars to zero, and re-hash it as appropriate. */
1373
1374 void abandon_lease (lease, message)
1375 struct lease *lease;
1376 const char *message;
1377 {
1378 struct lease *lt = (struct lease *)0;
1379
1380 if (!lease_copy (&lt, lease, MDL))
1381 return;
1382
1383 lt -> ends = cur_time; /* XXX */
1384 lt -> next_binding_state = FTS_ABANDONED;
1385
1386 log_error ("Abandoning IP address %s: %s",
1387 piaddr (lease -> ip_addr), message);
1388 lt -> hardware_addr.hlen = 0;
1389 if (lt -> uid && lt -> uid != lt -> uid_buf)
1390 dfree (lt -> uid, MDL);
1391 lt -> uid = (unsigned char *)0;
1392 lt -> uid_len = 0;
1393 lt -> uid_max = 0;
1394 supersede_lease (lease, lt, 1, 1, 1);
1395 lease_dereference (&lt, MDL);
1396 }
1397
1398 /* Abandon the specified lease (set its timeout to infinity and its
1399 particulars to zero, and re-hash it as appropriate. */
1400
1401 void dissociate_lease (lease)
1402 struct lease *lease;
1403 {
1404 struct lease *lt = (struct lease *)0;
1405
1406 if (!lease_copy (&lt, lease, MDL))
1407 return;
1408
1409 #if defined (FAILOVER_PROTOCOL)
1410 if (lease -> pool && lease -> pool -> failover_peer) {
1411 lt -> next_binding_state = FTS_RESET;
1412 } else {
1413 lt -> next_binding_state = FTS_FREE;
1414 }
1415 #else
1416 lt -> next_binding_state = FTS_FREE;
1417 #endif
1418 lt -> ends = cur_time; /* XXX */
1419 lt -> hardware_addr.hlen = 0;
1420 if (lt -> uid && lt -> uid != lt -> uid_buf)
1421 dfree (lt -> uid, MDL);
1422 lt -> uid = (unsigned char *)0;
1423 lt -> uid_len = 0;
1424 lt -> uid_max = 0;
1425 supersede_lease (lease, lt, 1, 1, 1);
1426 lease_dereference (&lt, MDL);
1427 }
1428
1429 /* Timer called when a lease in a particular pool expires. */
1430 void pool_timer (vpool)
1431 void *vpool;
1432 {
1433 struct pool *pool;
1434 struct lease *lt = (struct lease *)0;
1435 struct lease *next = (struct lease *)0;
1436 struct lease *lease = (struct lease *)0;
1437 struct lease **lptr [5];
1438 TIME next_expiry = MAX_TIME;
1439 int i;
1440
1441 pool = (struct pool *)vpool;
1442
1443 #define FREE_LEASES 0
1444 lptr [FREE_LEASES] = &pool -> free;
1445 #define ACTIVE_LEASES 1
1446 lptr [ACTIVE_LEASES] = &pool -> active;
1447 #define EXPIRED_LEASES 2
1448 lptr [EXPIRED_LEASES] = &pool -> expired;
1449 #define ABANDONED_LEASES 3
1450 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1451 #define BACKUP_LEASES 4
1452 lptr [BACKUP_LEASES] = &pool -> backup;
1453
1454 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1455 /* If there's nothing on the queue, skip it. */
1456 if (!*(lptr [i]))
1457 continue;
1458
1459 #if defined (FAILOVER_PROTOCOL)
1460 if (pool -> failover_peer &&
1461 pool -> failover_peer -> me.state != partner_down) {
1462 /* The secondary can't remove a lease from the
1463 active state except in partner_down. */
1464 if (i == ACTIVE_LEASES &&
1465 pool -> failover_peer -> i_am == secondary)
1466 continue;
1467 /* Leases in an expired state don't move to
1468 free because of a timeout unless we're in
1469 partner_down. */
1470 if (i == EXPIRED_LEASES)
1471 continue;
1472 }
1473 #endif
1474 lease_reference (&lease, *(lptr [i]), MDL);
1475
1476 while (lease) {
1477 /* Remember the next lease in the list. */
1478 if (next)
1479 lease_dereference (&next, MDL);
1480 if (lease -> next)
1481 lease_reference (&next, lease -> next, MDL);
1482
1483 /* If we've run out of things to expire on this list,
1484 stop. */
1485 if (lease -> sort_time > cur_time) {
1486 if (lease -> sort_time < next_expiry)
1487 next_expiry = lease -> sort_time;
1488 break;
1489 }
1490
1491 /* If there is a pending state change, and
1492 this lease has gotten to the time when the
1493 state change should happen, just call
1494 supersede_lease on it to make the change
1495 happen. */
1496 if (lease -> next_binding_state !=
1497 lease -> binding_state)
1498 supersede_lease (lease,
1499 (struct lease *)0, 1, 1, 1);
1500
1501 lease_dereference (&lease, MDL);
1502 if (next)
1503 lease_reference (&lease, next, MDL);
1504 }
1505 if (next)
1506 lease_dereference (&next, MDL);
1507 if (lease)
1508 lease_dereference (&lease, MDL);
1509 }
1510 if (next_expiry != MAX_TIME) {
1511 pool -> next_event_time = next_expiry;
1512 add_timeout (pool -> next_event_time, pool_timer, pool,
1513 (tvref_t)pool_reference,
1514 (tvunref_t)pool_dereference);
1515 } else
1516 pool -> next_event_time = MIN_TIME;
1517
1518 }
1519
1520 /* Locate the lease associated with a given IP address... */
1521
1522 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1523 const char *file, int line)
1524 {
1525 return lease_hash_lookup (lp, lease_ip_addr_hash,
1526 addr.iabuf, addr.len, file, line);
1527 }
1528
1529 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1530 unsigned len, const char *file, int line)
1531 {
1532 if (len == 0)
1533 return 0;
1534 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1535 }
1536
1537 int find_lease_by_hw_addr (struct lease **lp,
1538 const unsigned char *hwaddr, unsigned hwlen,
1539 const char *file, int line)
1540 {
1541 if (hwlen == 0)
1542 return 0;
1543 return lease_hash_lookup (lp, lease_hw_addr_hash,
1544 hwaddr, hwlen, file, line);
1545 }
1546
1547 /* Add the specified lease to the uid hash. */
1548
1549 void uid_hash_add (lease)
1550 struct lease *lease;
1551 {
1552 struct lease *head = (struct lease *)0;
1553 struct lease *next = (struct lease *)0;
1554
1555
1556 /* If it's not in the hash, just add it. */
1557 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1558 lease_hash_add (lease_uid_hash, lease -> uid,
1559 lease -> uid_len, lease, MDL);
1560 else {
1561 /* Otherwise, attach it to the end of the list. */
1562 while (head -> n_uid) {
1563 lease_reference (&next, head -> n_uid, MDL);
1564 lease_dereference (&head, MDL);
1565 lease_reference (&head, next, MDL);
1566 lease_dereference (&next, MDL);
1567 }
1568 lease_reference (&head -> n_uid, lease, MDL);
1569 lease_dereference (&head, MDL);
1570 }
1571 }
1572
1573 /* Delete the specified lease from the uid hash. */
1574
1575 void uid_hash_delete (lease)
1576 struct lease *lease;
1577 {
1578 struct lease *head = (struct lease *)0;
1579 struct lease *scan;
1580
1581 /* If it's not in the hash, we have no work to do. */
1582 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1583 if (lease -> n_uid)
1584 lease_dereference (&lease -> n_uid, MDL);
1585 return;
1586 }
1587
1588 /* If the lease we're freeing is at the head of the list,
1589 remove the hash table entry and add a new one with the
1590 next lease on the list (if there is one). */
1591 if (head == lease) {
1592 lease_hash_delete (lease_uid_hash,
1593 lease -> uid, lease -> uid_len, MDL);
1594 if (lease -> n_uid) {
1595 lease_hash_add (lease_uid_hash,
1596 lease -> n_uid -> uid,
1597 lease -> n_uid -> uid_len,
1598 lease -> n_uid, MDL);
1599 lease_dereference (&lease -> n_uid, MDL);
1600 }
1601 } else {
1602 /* Otherwise, look for the lease in the list of leases
1603 attached to the hash table entry, and remove it if
1604 we find it. */
1605 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1606 if (scan -> n_uid == lease) {
1607 lease_dereference (&scan -> n_uid, MDL);
1608 if (lease -> n_uid) {
1609 lease_reference (&scan -> n_uid,
1610 lease -> n_uid, MDL);
1611 lease_dereference (&lease -> n_uid,
1612 MDL);
1613 }
1614 break;
1615 }
1616 }
1617 }
1618 lease_dereference (&head, MDL);
1619 }
1620
1621 /* Add the specified lease to the hardware address hash. */
1622
1623 void hw_hash_add (lease)
1624 struct lease *lease;
1625 {
1626 struct lease *head = (struct lease *)0;
1627 struct lease *next = (struct lease *)0;
1628
1629 /* If it's not in the hash, just add it. */
1630 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1631 lease -> hardware_addr.hlen, MDL))
1632 lease_hash_add (lease_hw_addr_hash,
1633 lease -> hardware_addr.hbuf,
1634 lease -> hardware_addr.hlen,
1635 lease, MDL);
1636 else {
1637 /* Otherwise, attach it to the end of the list. */
1638 while (head -> n_hw) {
1639 lease_reference (&next, head -> n_hw, MDL);
1640 lease_dereference (&head, MDL);
1641 lease_reference (&head, next, MDL);
1642 lease_dereference (&next, MDL);
1643 }
1644
1645 lease_reference (&head -> n_hw, lease, MDL);
1646 lease_dereference (&head, MDL);
1647 }
1648 }
1649
1650 /* Delete the specified lease from the hardware address hash. */
1651
1652 void hw_hash_delete (lease)
1653 struct lease *lease;
1654 {
1655 struct lease *head = (struct lease *)0;
1656 struct lease *next = (struct lease *)0;
1657
1658 /* If it's not in the hash, we have no work to do. */
1659 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1660 lease -> hardware_addr.hlen, MDL)) {
1661 if (lease -> n_hw)
1662 lease_dereference (&lease -> n_hw, MDL);
1663 return;
1664 }
1665
1666 /* If the lease we're freeing is at the head of the list,
1667 remove the hash table entry and add a new one with the
1668 next lease on the list (if there is one). */
1669 if (head == lease) {
1670 lease_hash_delete (lease_hw_addr_hash,
1671 lease -> hardware_addr.hbuf,
1672 lease -> hardware_addr.hlen, MDL);
1673 if (lease -> n_hw) {
1674 lease_hash_add (lease_hw_addr_hash,
1675 lease -> n_hw -> hardware_addr.hbuf,
1676 lease -> n_hw -> hardware_addr.hlen,
1677 lease -> n_hw, MDL);
1678 lease_dereference (&lease -> n_hw, MDL);
1679 }
1680 } else {
1681 /* Otherwise, look for the lease in the list of leases
1682 attached to the hash table entry, and remove it if
1683 we find it. */
1684 while (head -> n_hw) {
1685 if (head -> n_hw == lease) {
1686 lease_dereference (&head -> n_hw, MDL);
1687 if (lease -> n_hw) {
1688 lease_reference (&head -> n_hw,
1689 lease -> n_hw, MDL);
1690 lease_dereference (&lease -> n_hw,
1691 MDL);
1692 }
1693 break;
1694 }
1695 lease_reference (&next, head -> n_hw, MDL);
1696 lease_dereference (&head, MDL);
1697 lease_reference (&head, next, MDL);
1698 lease_dereference (&next, MDL);
1699 }
1700 }
1701 if (head)
1702 lease_dereference (&head, MDL);
1703 }
1704
1705 /* Write all interesting leases to permanent storage. */
1706
1707 void write_leases ()
1708 {
1709 struct lease *l;
1710 struct shared_network *s;
1711 struct pool *p;
1712 struct host_decl *hp;
1713 struct group_object *gp;
1714 struct hash_bucket *hb;
1715 int i;
1716 int num_written;
1717 struct lease **lptr [5];
1718
1719 /* Write all the dynamically-created group declarations. */
1720 if (group_name_hash) {
1721 num_written = 0;
1722 for (i = 0; i < group_name_hash -> hash_count; i++) {
1723 for (hb = group_name_hash -> buckets [i];
1724 hb; hb = hb -> next) {
1725 gp = (struct group_object *)hb -> value;
1726 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1727 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1728 (gp -> flags & GROUP_OBJECT_DELETED))) {
1729 write_group (gp);
1730 ++num_written;
1731 }
1732 }
1733 }
1734 log_info ("Wrote %d group decls to leases file.", num_written);
1735 }
1736
1737 /* Write all the deleted host declarations. */
1738 if (host_name_hash) {
1739 num_written = 0;
1740 for (i = 0; i < host_name_hash -> hash_count; i++) {
1741 for (hb = host_name_hash -> buckets [i];
1742 hb; hb = hb -> next) {
1743 hp = (struct host_decl *)hb -> value;
1744 if (((hp -> flags & HOST_DECL_STATIC) &&
1745 (hp -> flags & HOST_DECL_DELETED))) {
1746 write_host (hp);
1747 ++num_written;
1748 }
1749 }
1750 }
1751 log_info ("Wrote %d deleted host decls to leases file.",
1752 num_written);
1753 }
1754
1755 /* Write all the new, dynamic host declarations. */
1756 if (host_name_hash) {
1757 num_written = 0;
1758 for (i = 0; i < host_name_hash -> hash_count; i++) {
1759 for (hb = host_name_hash -> buckets [i];
1760 hb; hb = hb -> next) {
1761 hp = (struct host_decl *)hb -> value;
1762 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1763 write_host (hp);
1764 ++num_written;
1765 }
1766 }
1767 }
1768 log_info ("Wrote %d new dynamic host decls to leases file.",
1769 num_written);
1770 }
1771
1772 #if defined (FAILOVER_PROTOCOL)
1773 /* Write all the failover states. */
1774 dhcp_failover_write_all_states ();
1775 #endif
1776
1777 /* Write all the leases. */
1778 num_written = 0;
1779 for (s = shared_networks; s; s = s -> next) {
1780 for (p = s -> pools; p; p = p -> next) {
1781 lptr [FREE_LEASES] = &p -> free;
1782 lptr [ACTIVE_LEASES] = &p -> active;
1783 lptr [EXPIRED_LEASES] = &p -> expired;
1784 lptr [ABANDONED_LEASES] = &p -> abandoned;
1785 lptr [BACKUP_LEASES] = &p -> backup;
1786
1787 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1788 for (l = *(lptr [i]); l; l = l -> next) {
1789 if (l -> hardware_addr.hlen ||
1790 l -> uid_len ||
1791 (l -> binding_state != FTS_FREE)) {
1792 if (!write_lease (l))
1793 log_fatal ("Can't rewrite lease database");
1794 num_written++;
1795 }
1796 }
1797 }
1798 }
1799 }
1800 log_info ("Wrote %d leases to leases file.", num_written);
1801 if (!commit_leases ())
1802 log_fatal ("Can't commit leases to new database: %m");
1803 }
1804
1805 int lease_enqueue (struct lease *comp)
1806 {
1807 struct lease **lq, *prev, *lp;
1808
1809 /* No queue to put it on? */
1810 if (!comp -> pool)
1811 return 0;
1812
1813 /* Figure out which queue it's going to. */
1814 switch (comp -> binding_state) {
1815 case FTS_FREE:
1816 lq = &comp -> pool -> free;
1817 comp -> pool -> free_leases++;
1818 comp -> sort_time = comp -> ends;
1819 break;
1820
1821 case FTS_ACTIVE:
1822 case FTS_RESERVED:
1823 case FTS_BOOTP:
1824 lq = &comp -> pool -> active;
1825 comp -> sort_time = comp -> ends;
1826 break;
1827
1828 case FTS_EXPIRED:
1829 case FTS_RELEASED:
1830 case FTS_RESET:
1831 lq = &comp -> pool -> expired;
1832 comp -> sort_time = comp -> ends;
1833
1834 break;
1835
1836 case FTS_ABANDONED:
1837 lq = &comp -> pool -> abandoned;
1838 comp -> sort_time = comp -> ends;
1839 break;
1840
1841 case FTS_BACKUP:
1842 lq = &comp -> pool -> backup;
1843 comp -> pool -> backup_leases++;
1844 comp -> sort_time = comp -> ends;
1845 break;
1846
1847 default:
1848 log_error ("Lease with bogus binding state: %d",
1849 comp -> binding_state);
1850 #if defined (BINDING_STATE_DEBUG)
1851 abort ();
1852 #endif
1853 return 0;
1854 }
1855
1856 /* Insertion sort the lease onto the appropriate queue. */
1857 prev = (struct lease *)0;
1858 for (lp = *lq; lp; lp = lp -> next) {
1859 if (lp -> sort_time >= comp -> sort_time)
1860 break;
1861 prev = lp;
1862 }
1863 if (prev) {
1864 if (prev -> next) {
1865 lease_reference (&comp -> next, prev -> next, MDL);
1866 lease_dereference (&prev -> next, MDL);
1867 }
1868 lease_reference (&prev -> next, comp, MDL);
1869 } else {
1870 if (*lq) {
1871 lease_reference (&comp -> next, *lq, MDL);
1872 lease_dereference (lq, MDL);
1873 }
1874 lease_reference (lq, comp, MDL);
1875 }
1876 return 1;
1877 }
1878
1879 /* For a given lease, sort it onto the right list in its pool and put it
1880 in each appropriate hash, understanding that it's already by definition
1881 in lease_ip_addr_hash. */
1882
1883 void lease_instantiate (const unsigned char *val, unsigned len,
1884 struct lease *lease)
1885 {
1886 struct class *class;
1887 /* XXX If the lease doesn't have a pool at this point, it's an
1888 XXX orphan, which we *should* keep around until it expires,
1889 XXX but which right now we just forget. */
1890 if (!lease -> pool) {
1891 lease_hash_delete (lease_ip_addr_hash,
1892 lease -> ip_addr.iabuf,
1893 lease -> ip_addr.len, MDL);
1894 return;
1895 }
1896
1897 /* Put the lease on the right queue. */
1898 lease_enqueue (lease);
1899
1900 /* Record the lease in the uid hash if possible. */
1901 if (lease -> uid) {
1902 uid_hash_add (lease);
1903 }
1904
1905 /* Record it in the hardware address hash if possible. */
1906 if (lease -> hardware_addr.hlen) {
1907 hw_hash_add (lease);
1908 }
1909
1910 /* If the lease has a billing class, set up the billing. */
1911 if (lease -> billing_class) {
1912 class = (struct class *)0;
1913 class_reference (&class, lease -> billing_class, MDL);
1914 class_dereference (&lease -> billing_class, MDL);
1915 /* If the lease is available for allocation, the billing
1916 is invalid, so we don't keep it. */
1917 if (lease -> binding_state == FTS_ACTIVE ||
1918 lease -> binding_state == FTS_EXPIRED ||
1919 lease -> binding_state == FTS_RELEASED ||
1920 lease -> binding_state == FTS_RESET ||
1921 lease -> binding_state == FTS_RESERVED ||
1922 lease -> binding_state == FTS_BOOTP)
1923 bill_class (lease, class);
1924 class_dereference (&class, MDL);
1925 }
1926 return;
1927 }
1928
1929 /* Run expiry events on every pool. This is called on startup so that
1930 any expiry events that occurred after the server stopped and before it
1931 was restarted can be run. At the same time, if failover support is
1932 compiled in, we compute the balance of leases for the pool. */
1933
1934 void expire_all_pools ()
1935 {
1936 struct shared_network *s;
1937 struct pool *p;
1938 struct hash_bucket *hb;
1939 int i;
1940 struct lease *l;
1941 struct lease **lptr [5];
1942
1943 /* First, go over the hash list and actually put all the leases
1944 on the appropriate lists. */
1945 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1946
1947 /* Loop through each pool in each shared network and call the
1948 expiry routine on the pool. */
1949 for (s = shared_networks; s; s = s -> next) {
1950 for (p = s -> pools; p; p = p -> next) {
1951 pool_timer (p);
1952
1953 p -> lease_count = 0;
1954 p -> free_leases = 0;
1955 p -> backup_leases = 0;
1956
1957 lptr [FREE_LEASES] = &p -> free;
1958 lptr [ACTIVE_LEASES] = &p -> active;
1959 lptr [EXPIRED_LEASES] = &p -> expired;
1960 lptr [ABANDONED_LEASES] = &p -> abandoned;
1961 lptr [BACKUP_LEASES] = &p -> backup;
1962
1963 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1964 for (l = *(lptr [i]); l; l = l -> next) {
1965 p -> lease_count++;
1966 if (l -> ends <= cur_time) {
1967 if (l -> binding_state == FTS_FREE)
1968 p -> free_leases++;
1969 else if (l -> binding_state == FTS_BACKUP)
1970 p -> backup_leases++;
1971 }
1972 #if defined (FAILOVER_PROTOCOL)
1973 if (p -> failover_peer &&
1974 l -> tstp > l -> tsfp &&
1975 !(l -> flags & ON_UPDATE_QUEUE))
1976 dhcp_failover_queue_update (l, 1);
1977 #endif
1978 }
1979 }
1980 }
1981 }
1982 }
1983
1984 void dump_subnets ()
1985 {
1986 struct lease *l;
1987 struct shared_network *s;
1988 struct subnet *n;
1989 struct pool *p;
1990 struct lease **lptr [5];
1991 int i;
1992
1993 log_info ("Subnets:");
1994 for (n = subnets; n; n = n -> next_subnet) {
1995 log_debug (" Subnet %s", piaddr (n -> net));
1996 log_debug (" netmask %s",
1997 piaddr (n -> netmask));
1998 }
1999 log_info ("Shared networks:");
2000 for (s = shared_networks; s; s = s -> next) {
2001 log_info (" %s", s -> name);
2002 for (p = s -> pools; p; p = p -> next) {
2003 lptr [FREE_LEASES] = &p -> free;
2004 lptr [ACTIVE_LEASES] = &p -> active;
2005 lptr [EXPIRED_LEASES] = &p -> expired;
2006 lptr [ABANDONED_LEASES] = &p -> abandoned;
2007 lptr [BACKUP_LEASES] = &p -> backup;
2008
2009 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
2010 for (l = *(lptr [i]); l; l = l -> next) {
2011 print_lease (l);
2012 }
2013 }
2014 }
2015 }
2016 }
2017
2018 HASH_FUNCTIONS (lease, const unsigned char *, struct lease)
2019 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl)
2020 HASH_FUNCTIONS (class, const char *, struct class)