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