Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / dhcp / server / mdb.c
blobcc7a1ed335a794307ee900e0ecaf6cc13566a558
1 /* mdb.c
3 Server-specific in-memory database support. */
5 /*
6 * Copyright (c) 2004-2005 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-2003 by Internet Software Consortium
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
22 * 950 Charter Street
23 * Redwood City, CA 94063
24 * <info@isc.org>
25 * http://www.isc.org/
27 * This software has been written for Internet Systems Consortium
28 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29 * To learn more about Internet Systems Consortium, see
30 * ``http://www.isc.org/''. To learn more about Vixie Enterprises,
31 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32 * ``http://www.nominum.com''.
35 #ifndef lint
36 static char copyright[] =
37 "$Id: mdb.c,v 1.4 2005/08/11 17:13:30 drochner Exp $ Copyright (c) 2004-2005 Internet Systems Consortium. All rights reserved.\n";
38 #endif /* not lint */
40 #include "dhcpd.h"
41 #include "omapip/hash.h"
43 struct subnet *subnets;
44 struct shared_network *shared_networks;
45 host_hash_t *host_hw_addr_hash;
46 host_hash_t *host_uid_hash;
47 host_hash_t *host_name_hash;
48 lease_hash_t *lease_uid_hash;
49 lease_hash_t *lease_ip_addr_hash;
50 lease_hash_t *lease_hw_addr_hash;
52 omapi_object_type_t *dhcp_type_host;
54 static int find_uid_statement (struct executable_statement *esp,
55 void *vp, int condp)
57 struct executable_statement **evp = vp;
59 if (esp -> op == supersede_option_statement &&
60 esp -> data.option &&
61 (esp -> data.option -> option -> universe ==
62 &dhcp_universe) &&
63 (esp -> data.option -> option -> code ==
64 DHO_DHCP_CLIENT_IDENTIFIER)) {
65 if (condp) {
66 log_error ("dhcp client identifier may not be %s",
67 "specified conditionally.");
68 } else if (!(*evp)) {
69 executable_statement_reference (evp, esp, MDL);
70 return 1;
71 } else {
72 log_error ("only one dhcp client identifier may be %s",
73 "specified");
76 return 0;
79 isc_result_t enter_host (hd, dynamicp, commit)
80 struct host_decl *hd;
81 int dynamicp;
82 int commit;
84 struct host_decl *hp = (struct host_decl *)0;
85 struct host_decl *np = (struct host_decl *)0;
86 struct executable_statement *esp;
88 if (!host_name_hash) {
89 if (!host_new_hash (&host_name_hash, 0, MDL))
90 log_fatal ("Can't allocate host name hash");
91 host_hash_add (host_name_hash,
92 (unsigned char *)hd -> name,
93 strlen (hd -> name), hd, MDL);
94 } else {
95 host_hash_lookup (&hp, host_name_hash,
96 (unsigned char *)hd -> name,
97 strlen (hd -> name), MDL);
99 /* If it's deleted, we can supersede it. */
100 if (hp && (hp -> flags & HOST_DECL_DELETED)) {
101 host_hash_delete (host_name_hash,
102 (unsigned char *)hd -> name,
103 strlen (hd -> name), MDL);
104 /* If the old entry wasn't dynamic, then we
105 always have to keep the deletion. */
106 if (hp -> flags & HOST_DECL_STATIC) {
107 hd -> flags |= HOST_DECL_STATIC;
109 host_dereference (&hp, MDL);
112 /* If we are updating an existing host declaration, we
113 can just delete it and add it again. */
114 if (hp && hp == hd) {
115 host_dereference (&hp, MDL);
116 delete_host (hd, 0);
117 if (!write_host (hd))
118 return ISC_R_IOERROR;
119 hd -> flags &= ~HOST_DECL_DELETED;
122 /* If there isn't already a host decl matching this
123 address, add it to the hash table. */
124 if (!hp) {
125 host_hash_add (host_name_hash,
126 (unsigned char *)hd -> name,
127 strlen (hd -> name), hd, MDL);
128 } else {
129 /* XXX actually, we have to delete the old one
130 XXX carefully and replace it. Not done yet. */
131 host_dereference (&hp, MDL);
132 return ISC_R_EXISTS;
136 if (hd -> n_ipaddr)
137 host_dereference (&hd -> n_ipaddr, MDL);
139 if (!hd -> type)
140 hd -> type = dhcp_type_host;
142 if (hd -> interface.hlen) {
143 if (!host_hw_addr_hash) {
144 if (!host_new_hash (&host_hw_addr_hash, 0, MDL))
145 log_fatal ("Can't allocate host/hw hash");
146 } else {
147 /* If there isn't already a host decl matching this
148 address, add it to the hash table. */
149 host_hash_lookup (&hp, host_hw_addr_hash,
150 hd -> interface.hbuf,
151 hd -> interface.hlen, MDL);
153 if (!hp)
154 host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
155 hd -> interface.hlen, hd, MDL);
156 else {
157 /* If there was already a host declaration for
158 this hardware address, add this one to the
159 end of the list. */
160 for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
162 host_reference (&np -> n_ipaddr, hd, MDL);
163 host_dereference (&hp, MDL);
167 /* See if there's a statement that sets the client identifier.
168 This is a kludge - the client identifier really shouldn't be
169 set with an executable statement. */
170 esp = (struct executable_statement *)0;
171 if (executable_statement_foreach (hd -> group -> statements,
172 find_uid_statement, &esp, 0)) {
173 evaluate_option_cache (&hd -> client_identifier,
174 (struct packet *)0,
175 (struct lease *)0,
176 (struct client_state *)0,
177 (struct option_state *)0,
178 (struct option_state *)0, &global_scope,
179 esp -> data.option, MDL);
182 /* If we got a client identifier, hash this entry by
183 client identifier. */
184 if (hd -> client_identifier.len) {
185 /* If there's no uid hash, make one; otherwise, see if
186 there's already an entry in the hash for this host. */
187 if (!host_uid_hash) {
188 if (!host_new_hash (&host_uid_hash, 0, MDL))
189 log_fatal ("Can't allocate host/uid hash");
191 host_hash_add (host_uid_hash,
192 hd -> client_identifier.data,
193 hd -> client_identifier.len,
194 hd, MDL);
195 } else {
196 /* If there's already a host declaration for this
197 client identifier, add this one to the end of the
198 list. Otherwise, add it to the hash table. */
199 if (host_hash_lookup (&hp, host_uid_hash,
200 hd -> client_identifier.data,
201 hd -> client_identifier.len,
202 MDL)) {
203 /* Don't link it in twice... */
204 if (!np) {
205 for (np = hp; np -> n_ipaddr;
206 np = np -> n_ipaddr) {
207 if (hd == np)
208 break;
210 if (hd != np)
211 host_reference (&np -> n_ipaddr,
212 hd, MDL);
214 host_dereference (&hp, MDL);
215 } else {
216 host_hash_add (host_uid_hash,
217 hd -> client_identifier.data,
218 hd -> client_identifier.len,
219 hd, MDL);
224 if (dynamicp && commit) {
225 if (!write_host (hd))
226 return ISC_R_IOERROR;
227 if (!commit_leases ())
228 return ISC_R_IOERROR;
231 return ISC_R_SUCCESS;
234 isc_result_t delete_host (hd, commit)
235 struct host_decl *hd;
236 int commit;
238 struct host_decl *hp = (struct host_decl *)0;
239 struct host_decl *np = (struct host_decl *)0;
240 struct host_decl *foo;
241 int hw_head = 0, uid_head = 1;
243 /* Don't need to do it twice. */
244 if (hd -> flags & HOST_DECL_DELETED)
245 return ISC_R_SUCCESS;
247 /* But we do need to do it once! :') */
248 hd -> flags |= HOST_DECL_DELETED;
250 if (hd -> interface.hlen) {
251 if (host_hw_addr_hash) {
252 if (host_hash_lookup (&hp, host_hw_addr_hash,
253 hd -> interface.hbuf,
254 hd -> interface.hlen, MDL)) {
255 if (hp == hd) {
256 host_hash_delete (host_hw_addr_hash,
257 hd -> interface.hbuf,
258 hd -> interface.hlen, MDL);
259 hw_head = 1;
260 } else {
261 np = (struct host_decl *)0;
262 foo = (struct host_decl *)0;
263 host_reference (&foo, hp, MDL);
264 while (foo) {
265 if (foo == hd)
266 break;
267 if (np)
268 host_dereference (&np, MDL);
269 host_reference (&np, foo, MDL);
270 host_dereference (&foo, MDL);
271 if (np -> n_ipaddr)
272 host_reference (&foo, np -> n_ipaddr, MDL);
275 if (foo) {
276 host_dereference (&np -> n_ipaddr, MDL);
277 if (hd -> n_ipaddr)
278 host_reference (&np -> n_ipaddr,
279 hd -> n_ipaddr, MDL);
280 host_dereference (&foo, MDL);
282 if (np)
283 host_dereference (&np, MDL);
285 host_dereference (&hp, MDL);
290 /* If we got a client identifier, hash this entry by
291 client identifier. */
292 if (hd -> client_identifier.len) {
293 if (host_uid_hash) {
294 if (host_hash_lookup (&hp, host_uid_hash,
295 hd -> client_identifier.data,
296 hd -> client_identifier.len, MDL)) {
297 if (hp == hd) {
298 host_hash_delete (host_uid_hash,
299 hd -> client_identifier.data,
300 hd -> client_identifier.len, MDL);
301 uid_head = 1;
302 } else {
303 np = (struct host_decl *)0;
304 foo = (struct host_decl *)0;
305 host_reference (&foo, hp, MDL);
306 while (foo) {
307 if (foo == hd)
308 break;
309 if (np)
310 host_dereference (&np, MDL);
311 host_reference (&np, foo, MDL);
312 host_dereference (&foo, MDL);
313 if (np -> n_ipaddr)
314 host_reference (&foo, np -> n_ipaddr, MDL);
317 if (foo) {
318 host_dereference (&np -> n_ipaddr, MDL);
319 if (hd -> n_ipaddr)
320 host_reference (&np -> n_ipaddr,
321 hd -> n_ipaddr, MDL);
322 host_dereference (&foo, MDL);
324 if (np)
325 host_dereference (&np, MDL);
327 host_dereference (&hp, MDL);
332 if (hd -> n_ipaddr) {
333 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
334 host_hash_add
335 (host_uid_hash,
336 hd -> n_ipaddr -> client_identifier.data,
337 hd -> n_ipaddr -> client_identifier.len,
338 hd -> n_ipaddr, MDL);
340 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
341 host_hash_add (host_hw_addr_hash,
342 hd -> n_ipaddr -> interface.hbuf,
343 hd -> n_ipaddr -> interface.hlen,
344 hd -> n_ipaddr, MDL);
346 host_dereference (&hd -> n_ipaddr, MDL);
349 if (host_name_hash) {
350 if (host_hash_lookup (&hp, host_name_hash,
351 (unsigned char *)hd -> name,
352 strlen (hd -> name), MDL)) {
353 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
354 host_hash_delete (host_name_hash,
355 (unsigned char *)hd -> name,
356 strlen (hd -> name), MDL);
358 host_dereference (&hp, MDL);
362 if (commit) {
363 if (!write_host (hd))
364 return ISC_R_IOERROR;
365 if (!commit_leases ())
366 return ISC_R_IOERROR;
368 return ISC_R_SUCCESS;
371 int find_hosts_by_haddr (struct host_decl **hp, int htype,
372 const unsigned char *haddr, unsigned hlen,
373 const char *file, int line)
375 struct hardware h;
377 h.hlen = hlen + 1;
378 h.hbuf [0] = htype;
379 memcpy (&h.hbuf [1], haddr, hlen);
381 return host_hash_lookup (hp, host_hw_addr_hash,
382 h.hbuf, h.hlen, file, line);
385 int find_hosts_by_uid (struct host_decl **hp,
386 const unsigned char *data, unsigned len,
387 const char *file, int line)
389 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
392 /* More than one host_decl can be returned by find_hosts_by_haddr or
393 find_hosts_by_uid, and each host_decl can have multiple addresses.
394 Loop through the list of hosts, and then for each host, through the
395 list of addresses, looking for an address that's in the same shared
396 network as the one specified. Store the matching address through
397 the addr pointer, update the host pointer to point at the host_decl
398 that matched, and return the subnet that matched. */
400 int find_host_for_network (struct subnet **sp, struct host_decl **host,
401 struct iaddr *addr, struct shared_network *share)
403 int i;
404 struct iaddr ip_address;
405 struct host_decl *hp;
406 struct data_string fixed_addr;
408 memset (&fixed_addr, 0, sizeof fixed_addr);
410 for (hp = *host; hp; hp = hp -> n_ipaddr) {
411 if (!hp -> fixed_addr)
412 continue;
413 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
414 (struct lease *)0,
415 (struct client_state *)0,
416 (struct option_state *)0,
417 (struct option_state *)0,
418 &global_scope,
419 hp -> fixed_addr, MDL))
420 continue;
421 for (i = 0; i < fixed_addr.len; i += 4) {
422 ip_address.len = 4;
423 memcpy (ip_address.iabuf,
424 fixed_addr.data + i, 4);
425 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
426 struct host_decl *tmp = (struct host_decl *)0;
427 *addr = ip_address;
428 /* This is probably not necessary, but
429 just in case *host is the only reference
430 to that host declaration, make a temporary
431 reference so that dereferencing it doesn't
432 dereference hp out from under us. */
433 host_reference (&tmp, *host, MDL);
434 host_dereference (host, MDL);
435 host_reference (host, hp, MDL);
436 host_dereference (&tmp, MDL);
437 data_string_forget (&fixed_addr, MDL);
438 return 1;
441 data_string_forget (&fixed_addr, MDL);
443 return 0;
446 void new_address_range (cfile, low, high, subnet, pool, lpchain)
447 struct parse *cfile;
448 struct iaddr low, high;
449 struct subnet *subnet;
450 struct pool *pool;
451 struct lease **lpchain;
453 struct lease *address_range;
454 struct iaddr net;
455 unsigned min, max, i;
456 char lowbuf [16], highbuf [16], netbuf [16];
457 struct shared_network *share = subnet -> shared_network;
458 #if !defined (COMPACT_LEASES)
459 isc_result_t status;
460 #endif
461 struct lease *lt = (struct lease *)0;
463 /* All subnets should have attached shared network structures. */
464 if (!share) {
465 strcpy (netbuf, piaddr (subnet -> net));
466 log_fatal ("No shared network for network %s (%s)",
467 netbuf, piaddr (subnet -> netmask));
470 /* Initialize the hash table if it hasn't been done yet. */
471 if (!lease_uid_hash) {
472 if (!lease_new_hash (&lease_uid_hash, 0, MDL))
473 log_fatal ("Can't allocate lease/uid hash");
475 if (!lease_ip_addr_hash) {
476 if (!lease_new_hash (&lease_ip_addr_hash, 0, MDL))
477 log_fatal ("Can't allocate lease/ip hash");
479 if (!lease_hw_addr_hash) {
480 if (!lease_new_hash (&lease_hw_addr_hash, 0, MDL))
481 log_fatal ("Can't allocate lease/hw hash");
484 /* Make sure that high and low addresses are in same subnet. */
485 net = subnet_number (low, subnet -> netmask);
486 if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
487 strcpy (lowbuf, piaddr (low));
488 strcpy (highbuf, piaddr (high));
489 strcpy (netbuf, piaddr (subnet -> netmask));
490 log_fatal ("Address range %s to %s, netmask %s spans %s!",
491 lowbuf, highbuf, netbuf, "multiple subnets");
494 /* Make sure that the addresses are on the correct subnet. */
495 if (!addr_eq (net, subnet -> net)) {
496 strcpy (lowbuf, piaddr (low));
497 strcpy (highbuf, piaddr (high));
498 strcpy (netbuf, piaddr (subnet -> netmask));
499 log_fatal ("Address range %s to %s not on net %s/%s!",
500 lowbuf, highbuf, piaddr (subnet -> net), netbuf);
503 /* Get the high and low host addresses... */
504 max = host_addr (high, subnet -> netmask);
505 min = host_addr (low, subnet -> netmask);
507 /* Allow range to be specified high-to-low as well as low-to-high. */
508 if (min > max) {
509 max = min;
510 min = host_addr (high, subnet -> netmask);
513 /* Get a lease structure for each address in the range. */
514 #if defined (COMPACT_LEASES)
515 address_range = new_leases (max - min + 1, MDL);
516 if (!address_range) {
517 strcpy (lowbuf, piaddr (low));
518 strcpy (highbuf, piaddr (high));
519 log_fatal ("No memory for address range %s-%s.",
520 lowbuf, highbuf);
522 #endif
524 /* Fill out the lease structures with some minimal information. */
525 for (i = 0; i < max - min + 1; i++) {
526 struct lease *lp = (struct lease *)0;
527 #if defined (COMPACT_LEASES)
528 omapi_object_initialize ((omapi_object_t *)&address_range [i],
529 dhcp_type_lease,
530 0, sizeof (struct lease), MDL);
531 lease_reference (&lp, &address_range [i], MDL);
532 #else
533 status = lease_allocate (&lp, MDL);
534 if (status != ISC_R_SUCCESS)
535 log_fatal ("No memory for lease %s: %s",
536 piaddr (ip_addr (subnet -> net,
537 subnet -> netmask,
538 i + min)),
539 isc_result_totext (status));
540 #endif
541 lp -> ip_addr = ip_addr (subnet -> net,
542 subnet -> netmask, i + min);
543 lp -> starts = lp -> timestamp = MIN_TIME;
544 lp -> ends = MIN_TIME;
545 subnet_reference (&lp -> subnet, subnet, MDL);
546 pool_reference (&lp -> pool, pool, MDL);
547 lp -> binding_state = FTS_FREE;
548 lp -> next_binding_state = FTS_FREE;
549 lp -> flags = 0;
551 /* Remember the lease in the IP address hash. */
552 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
553 if (lt -> pool) {
554 parse_warn (cfile,
555 "lease %s is declared twice!",
556 piaddr (lp -> ip_addr));
557 } else
558 pool_reference (&lt -> pool, pool, MDL);
559 lease_dereference (&lt, MDL);
560 } else
561 lease_hash_add (lease_ip_addr_hash,
562 lp -> ip_addr.iabuf,
563 lp -> ip_addr.len, lp, MDL);
564 /* Put the lease on the chain for the caller. */
565 if (lpchain) {
566 if (*lpchain) {
567 lease_reference (&lp -> next, *lpchain, MDL);
568 lease_dereference (lpchain, MDL);
570 lease_reference (lpchain, lp, MDL);
572 lease_dereference (&lp, MDL);
576 int find_subnet (struct subnet **sp,
577 struct iaddr addr, const char *file, int line)
579 struct subnet *rv;
581 for (rv = subnets; rv; rv = rv -> next_subnet) {
582 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
583 if (subnet_reference (sp, rv,
584 file, line) != ISC_R_SUCCESS)
585 return 0;
586 return 1;
589 return 0;
592 int find_grouped_subnet (struct subnet **sp,
593 struct shared_network *share, struct iaddr addr,
594 const char *file, int line)
596 struct subnet *rv;
598 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
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;
606 return 0;
609 int subnet_inner_than (subnet, scan, warnp)
610 struct subnet *subnet, *scan;
611 int warnp;
613 if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
614 scan -> net) ||
615 addr_eq (subnet_number (scan -> net, subnet -> netmask),
616 subnet -> net)) {
617 char n1buf [16];
618 int i, j;
619 for (i = 0; i < 32; i++)
620 if (subnet -> netmask.iabuf [3 - (i >> 3)]
621 & (1 << (i & 7)))
622 break;
623 for (j = 0; j < 32; j++)
624 if (scan -> netmask.iabuf [3 - (j >> 3)] &
625 (1 << (j & 7)))
626 break;
627 strcpy (n1buf, piaddr (subnet -> net));
628 if (warnp)
629 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
630 "Warning: ", n1buf, 32 - i,
631 piaddr (scan -> net), 32 - j);
632 if (i < j)
633 return 1;
635 return 0;
638 /* Enter a new subnet into the subnet list. */
639 void enter_subnet (subnet)
640 struct subnet *subnet;
642 struct subnet *scan = (struct subnet *)0;
643 struct subnet *next = (struct subnet *)0;
644 struct subnet *prev = (struct subnet *)0;
646 /* Check for duplicates... */
647 if (subnets)
648 subnet_reference (&next, subnets, MDL);
649 while (next) {
650 subnet_reference (&scan, next, MDL);
651 subnet_dereference (&next, MDL);
653 /* When we find a conflict, make sure that the
654 subnet with the narrowest subnet mask comes
655 first. */
656 if (subnet_inner_than (subnet, scan, 1)) {
657 if (prev) {
658 if (prev -> next_subnet)
659 subnet_dereference (&prev -> next_subnet, MDL);
660 subnet_reference (&prev -> next_subnet, subnet, MDL);
661 subnet_dereference (&prev, MDL);
662 } else {
663 subnet_dereference (&subnets, MDL);
664 subnet_reference (&subnets, subnet, MDL);
666 subnet_reference (&subnet -> next_subnet, scan, MDL);
667 subnet_dereference (&scan, MDL);
668 return;
670 subnet_reference (&prev, scan, MDL);
671 subnet_dereference (&scan, MDL);
673 if (prev)
674 subnet_dereference (&prev, MDL);
676 /* XXX use the BSD radix tree code instead of a linked list. */
677 if (subnets) {
678 subnet_reference (&subnet -> next_subnet, subnets, MDL);
679 subnet_dereference (&subnets, MDL);
681 subnet_reference (&subnets, subnet, MDL);
684 /* Enter a new shared network into the shared network list. */
686 void enter_shared_network (share)
687 struct shared_network *share;
689 if (shared_networks) {
690 shared_network_reference (&share -> next,
691 shared_networks, MDL);
692 shared_network_dereference (&shared_networks, MDL);
694 shared_network_reference (&shared_networks, share, MDL);
697 void new_shared_network_interface (cfile, share, name)
698 struct parse *cfile;
699 struct shared_network *share;
700 const char *name;
702 struct interface_info *ip;
703 isc_result_t status;
705 if (share -> interface) {
706 parse_warn (cfile,
707 "A subnet or shared network can't be connected %s",
708 "to two interfaces.");
709 return;
712 for (ip = interfaces; ip; ip = ip -> next)
713 if (!strcmp (ip -> name, name))
714 break;
715 if (!ip) {
716 status = interface_allocate (&ip, MDL);
717 if (status != ISC_R_SUCCESS)
718 log_fatal ("new_shared_network_interface %s: %s",
719 name, isc_result_totext (status));
720 if (strlen (name) > sizeof ip -> name) {
721 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
722 ip -> name [(sizeof ip -> name) - 1] = 0;
723 } else
724 strcpy (ip -> name, name);
725 if (interfaces) {
726 interface_reference (&ip -> next, interfaces, MDL);
727 interface_dereference (&interfaces, MDL);
729 interface_reference (&interfaces, ip, MDL);
730 ip -> flags = INTERFACE_REQUESTED;
731 /* XXX this is a reference loop. */
732 shared_network_reference (&ip -> shared_network, share, MDL);
733 interface_reference (&share -> interface, ip, MDL);
737 /* Enter a lease into the system. This is called by the parser each
738 time it reads in a new lease. If the subnet for that lease has
739 already been read in (usually the case), just update that lease;
740 otherwise, allocate temporary storage for the lease and keep it around
741 until we're done reading in the config file. */
743 void enter_lease (lease)
744 struct lease *lease;
746 struct lease *comp = (struct lease *)0;
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);
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);
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. */
773 if (!lease -> subnet) {
774 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
775 return;
777 lease_hash_add (lease_ip_addr_hash,
778 lease -> ip_addr.iabuf,
779 lease -> ip_addr.len, lease, MDL);
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. */
787 int supersede_lease (comp, lease, commit, propogate, pimmediate)
788 struct lease *comp, *lease;
789 int commit;
790 int propogate;
791 int pimmediate;
793 int enter_uid = 0;
794 int enter_hwaddr = 0;
795 struct lease *lp, **lq, *prev;
797 #if defined (FAILOVER_PROTOCOL)
798 /* We must commit leases before sending updates regarding them
799 to failover peers. It is, therefore, an error to set pimmediate
800 and not commit. */
801 if (pimmediate && !commit)
802 return 0;
803 #endif
805 /* If there is no sample lease, just do the move. */
806 if (!lease)
807 goto just_move_it;
809 /* Static leases are not currently kept in the database... */
810 if (lease -> flags & STATIC_LEASE)
811 return 1;
813 /* If the existing lease hasn't expired and has a different
814 unique identifier or, if it doesn't have a unique
815 identifier, a different hardware address, then the two
816 leases are in conflict. If the existing lease has a uid
817 and the new one doesn't, but they both have the same
818 hardware address, and dynamic bootp is allowed on this
819 lease, then we allow that, in case a dynamic BOOTP lease is
820 requested *after* a DHCP lease has been assigned. */
822 if (lease -> binding_state != FTS_ABANDONED &&
823 lease -> next_binding_state != FTS_ABANDONED &&
824 comp -> binding_state == FTS_ACTIVE &&
825 (((comp -> uid && lease -> uid) &&
826 (comp -> uid_len != lease -> uid_len ||
827 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
828 (!comp -> uid &&
829 ((comp -> hardware_addr.hlen !=
830 lease -> hardware_addr.hlen) ||
831 memcmp (comp -> hardware_addr.hbuf,
832 lease -> hardware_addr.hbuf,
833 comp -> hardware_addr.hlen))))) {
834 log_error ("Lease conflict at %s",
835 piaddr (comp -> ip_addr));
838 /* If there's a Unique ID, dissociate it from the hash
839 table and free it if necessary. */
840 if (comp -> uid) {
841 uid_hash_delete (comp);
842 enter_uid = 1;
843 if (comp -> uid != &comp -> uid_buf [0]) {
844 dfree (comp -> uid, MDL);
845 comp -> uid_max = 0;
846 comp -> uid_len = 0;
848 comp -> uid = (unsigned char *)0;
849 } else
850 enter_uid = 1;
852 if (comp -> hardware_addr.hlen &&
853 ((comp -> hardware_addr.hlen !=
854 lease -> hardware_addr.hlen) ||
855 memcmp (comp -> hardware_addr.hbuf,
856 lease -> hardware_addr.hbuf,
857 comp -> hardware_addr.hlen))) {
858 hw_hash_delete (comp);
859 enter_hwaddr = 1;
860 } else if (!comp -> hardware_addr.hlen)
861 enter_hwaddr = 1;
863 /* If the lease has been billed to a class, remove the billing. */
864 if (comp -> billing_class != lease -> billing_class) {
865 if (comp -> billing_class)
866 unbill_class (comp, comp -> billing_class);
867 if (lease -> billing_class)
868 bill_class (comp, lease -> billing_class);
871 /* Copy the data files, but not the linkages. */
872 comp -> starts = lease -> starts;
873 if (lease -> uid) {
874 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
875 memcpy (comp -> uid_buf,
876 lease -> uid, lease -> uid_len);
877 comp -> uid = &comp -> uid_buf [0];
878 comp -> uid_max = sizeof comp -> uid_buf;
879 comp -> uid_len = lease -> uid_len;
880 } else if (lease -> uid != &lease -> uid_buf [0]) {
881 comp -> uid = lease -> uid;
882 comp -> uid_max = lease -> uid_max;
883 lease -> uid = (unsigned char *)0;
884 lease -> uid_max = 0;
885 comp -> uid_len = lease -> uid_len;
886 lease -> uid_len = 0;
887 } else {
888 log_fatal ("corrupt lease uid."); /* XXX */
890 } else {
891 comp -> uid = (unsigned char *)0;
892 comp -> uid_len = comp -> uid_max = 0;
894 if (comp -> host)
895 host_dereference (&comp -> host, MDL);
896 host_reference (&comp -> host, lease -> host, MDL);
897 comp -> hardware_addr = lease -> hardware_addr;
898 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
899 (comp -> flags & ~EPHEMERAL_FLAGS));
900 if (comp -> scope)
901 binding_scope_dereference (&comp -> scope, MDL);
902 if (lease -> scope) {
903 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
904 binding_scope_dereference (&lease -> scope, MDL);
907 if (comp -> agent_options)
908 option_chain_head_dereference (&comp -> agent_options, MDL);
909 if (lease -> agent_options) {
910 /* Only retain the agent options if the lease is still
911 affirmatively associated with a client. */
912 if (lease -> next_binding_state == FTS_ACTIVE ||
913 lease -> next_binding_state == FTS_EXPIRED)
914 option_chain_head_reference (&comp -> agent_options,
915 lease -> agent_options,
916 MDL);
917 option_chain_head_dereference (&lease -> agent_options, MDL);
920 /* Record the hostname information in the lease. */
921 if (comp -> client_hostname)
922 dfree (comp -> client_hostname, MDL);
923 comp -> client_hostname = lease -> client_hostname;
924 lease -> client_hostname = (char *)0;
926 if (lease -> on_expiry) {
927 if (comp -> on_expiry)
928 executable_statement_dereference (&comp -> on_expiry,
929 MDL);
930 executable_statement_reference (&comp -> on_expiry,
931 lease -> on_expiry,
932 MDL);
934 if (lease -> on_commit) {
935 if (comp -> on_commit)
936 executable_statement_dereference (&comp -> on_commit,
937 MDL);
938 executable_statement_reference (&comp -> on_commit,
939 lease -> on_commit,
940 MDL);
942 if (lease -> on_release) {
943 if (comp -> on_release)
944 executable_statement_dereference (&comp -> on_release,
945 MDL);
946 executable_statement_reference (&comp -> on_release,
947 lease -> on_release, MDL);
950 /* Record the lease in the uid hash if necessary. */
951 if (enter_uid && comp -> uid) {
952 uid_hash_add (comp);
955 /* Record it in the hardware address hash if necessary. */
956 if (enter_hwaddr && lease -> hardware_addr.hlen) {
957 hw_hash_add (comp);
960 #if defined (FAILOVER_PROTOCOL)
961 comp -> cltt = lease -> cltt;
962 comp -> tstp = lease -> tstp;
963 comp -> tsfp = lease -> tsfp;
964 #endif /* FAILOVER_PROTOCOL */
965 comp -> ends = lease -> ends;
966 comp -> next_binding_state = lease -> next_binding_state;
968 just_move_it:
969 if (!comp -> pool) {
970 log_error ("Supersede_lease: lease %s with no pool.",
971 piaddr (comp -> ip_addr));
972 return 0;
975 /* Figure out which queue it's on. */
976 switch (comp -> binding_state) {
977 case FTS_FREE:
978 lq = &comp -> pool -> free;
979 comp -> pool -> free_leases--;
980 break;
982 case FTS_ACTIVE:
983 lq = &comp -> pool -> active;
984 break;
986 case FTS_EXPIRED:
987 case FTS_RELEASED:
988 case FTS_RESET:
989 lq = &comp -> pool -> expired;
990 break;
992 case FTS_ABANDONED:
993 lq = &comp -> pool -> abandoned;
994 break;
996 case FTS_BACKUP:
997 lq = &comp -> pool -> backup;
998 comp -> pool -> backup_leases--;
999 break;
1001 default:
1002 log_error ("Lease with bogus binding state: %d",
1003 comp -> binding_state);
1004 #if defined (BINDING_STATE_DEBUG)
1005 abort ();
1006 #endif
1007 return 0;
1010 /* Remove the lease from its current place in its current
1011 timer sequence. */
1012 prev = (struct lease *)0;
1013 for (lp = *lq; lp; lp = lp -> next) {
1014 if (lp == comp)
1015 break;
1016 prev = lp;
1019 if (!lp) {
1020 log_error ("Lease with binding state %s not on its queue.",
1021 (comp -> binding_state < 1 ||
1022 comp -> binding_state > FTS_LAST)
1023 ? "unknown"
1024 : binding_state_names [comp -> binding_state - 1]);
1025 return 0;
1028 if (prev) {
1029 lease_dereference (&prev -> next, MDL);
1030 if (comp -> next) {
1031 lease_reference (&prev -> next, comp -> next, MDL);
1032 lease_dereference (&comp -> next, MDL);
1034 } else {
1035 lease_dereference (lq, MDL);
1036 if (comp -> next) {
1037 lease_reference (lq, comp -> next, MDL);
1038 lease_dereference (&comp -> next, MDL);
1042 /* Make the state transition. */
1043 if (commit || !pimmediate)
1044 make_binding_state_transition (comp);
1046 /* Put the lease back on the appropriate queue. If the lease
1047 is corrupt (as detected by lease_enqueue), don't go any farther. */
1048 if (!lease_enqueue (comp))
1049 return 0;
1051 /* If this is the next lease that will timeout on the pool,
1052 zap the old timeout and set the timeout on this pool to the
1053 time that the lease's next event will happen.
1055 We do not actually set the timeout unless commit is true -
1056 we don't want to thrash the timer queue when reading the
1057 lease database. Instead, the database code calls the
1058 expiry event on each pool after reading in the lease file,
1059 and the expiry code sets the timer if there's anything left
1060 to expire after it's run any outstanding expiry events on
1061 the pool. */
1062 if ((commit || !pimmediate) &&
1063 comp -> sort_time != MIN_TIME &&
1064 comp -> sort_time > cur_time &&
1065 (comp -> sort_time < comp -> pool -> next_event_time ||
1066 comp -> pool -> next_event_time == MIN_TIME)) {
1067 comp -> pool -> next_event_time = comp -> sort_time;
1068 add_timeout (comp -> pool -> next_event_time,
1069 pool_timer, comp -> pool,
1070 (tvref_t)pool_reference,
1071 (tvunref_t)pool_dereference);
1074 if (commit) {
1075 if (!write_lease (comp))
1076 return 0;
1077 if (!commit_leases ())
1078 return 0;
1081 #if defined (FAILOVER_PROTOCOL)
1082 if (propogate) {
1083 comp -> desired_binding_state = comp -> binding_state;
1084 if (!dhcp_failover_queue_update (comp, pimmediate))
1085 return 0;
1087 #endif
1089 /* If the current binding state has already expired, do an
1090 expiry event right now. */
1091 /* XXX At some point we should optimize this so that we don't
1092 XXX write the lease twice, but this is a safe way to fix the
1093 XXX problem for 3.0 (I hope!). */
1094 if ((commit || !pimmediate) &&
1095 comp -> sort_time < cur_time &&
1096 comp -> next_binding_state != comp -> binding_state)
1097 pool_timer (comp -> pool);
1099 return 1;
1102 void make_binding_state_transition (struct lease *lease)
1104 #if defined (FAILOVER_PROTOCOL)
1105 dhcp_failover_state_t *peer;
1107 if (lease && lease -> pool && lease -> pool -> failover_peer)
1108 peer = lease -> pool -> failover_peer;
1109 else
1110 peer = (dhcp_failover_state_t *)0;
1111 #endif
1113 /* If the lease was active and is now no longer active, but isn't
1114 released, then it just expired, so do the expiry event. */
1115 if (lease -> next_binding_state != lease -> binding_state &&
1117 #if defined (FAILOVER_PROTOCOL)
1118 peer &&
1119 (lease -> binding_state == FTS_EXPIRED ||
1120 (peer -> i_am == secondary &&
1121 lease -> binding_state == FTS_ACTIVE)) &&
1122 (lease -> next_binding_state == FTS_FREE ||
1123 lease -> next_binding_state == FTS_BACKUP)) ||
1124 (!peer &&
1125 #endif
1126 lease -> binding_state == FTS_ACTIVE &&
1127 lease -> next_binding_state != FTS_RELEASED))) {
1128 #if defined (NSUPDATE)
1129 ddns_removals (lease);
1130 #endif
1131 if (lease -> on_expiry) {
1132 execute_statements ((struct binding_value **)0,
1133 (struct packet *)0, lease,
1134 (struct client_state *)0,
1135 (struct option_state *)0,
1136 (struct option_state *)0, /* XXX */
1137 &lease -> scope,
1138 lease -> on_expiry);
1139 if (lease -> on_expiry)
1140 executable_statement_dereference
1141 (&lease -> on_expiry, MDL);
1144 /* No sense releasing a lease after it's expired. */
1145 if (lease -> on_release)
1146 executable_statement_dereference (&lease -> on_release,
1147 MDL);
1148 /* Get rid of client-specific bindings that are only
1149 correct when the lease is active. */
1150 if (lease -> billing_class)
1151 unbill_class (lease, lease -> billing_class);
1152 if (lease -> agent_options)
1153 option_chain_head_dereference (&lease -> agent_options,
1154 MDL);
1155 if (lease -> client_hostname) {
1156 dfree (lease -> client_hostname, MDL);
1157 lease -> client_hostname = (char *)0;
1159 if (lease -> host)
1160 host_dereference (&lease -> host, MDL);
1162 /* Send the expiry time to the peer. */
1163 lease -> tstp = lease -> ends;
1166 /* If the lease was active and is now released, do the release
1167 event. */
1168 if (lease -> next_binding_state != lease -> binding_state &&
1170 #if defined (FAILOVER_PROTOCOL)
1171 peer &&
1172 lease -> binding_state == FTS_RELEASED &&
1173 (lease -> next_binding_state == FTS_FREE ||
1174 lease -> next_binding_state == FTS_BACKUP)) ||
1175 (!peer &&
1176 #endif
1177 lease -> binding_state == FTS_ACTIVE &&
1178 lease -> next_binding_state == FTS_RELEASED))) {
1179 #if defined (NSUPDATE)
1180 ddns_removals (lease);
1181 #endif
1182 if (lease -> on_release) {
1183 execute_statements ((struct binding_value **)0,
1184 (struct packet *)0, lease,
1185 (struct client_state *)0,
1186 (struct option_state *)0,
1187 (struct option_state *)0, /* XXX */
1188 &lease -> scope,
1189 lease -> on_release);
1190 executable_statement_dereference (&lease -> on_release,
1191 MDL);
1194 /* A released lease can't expire. */
1195 if (lease -> on_expiry)
1196 executable_statement_dereference (&lease -> on_expiry,
1197 MDL);
1199 /* Get rid of client-specific bindings that are only
1200 correct when the lease is active. */
1201 if (lease -> billing_class)
1202 unbill_class (lease, lease -> billing_class);
1203 if (lease -> agent_options)
1204 option_chain_head_dereference (&lease -> agent_options,
1205 MDL);
1206 if (lease -> client_hostname) {
1207 dfree (lease -> client_hostname, MDL);
1208 lease -> client_hostname = (char *)0;
1210 if (lease -> host)
1211 host_dereference (&lease -> host, MDL);
1213 /* Send the release time (should be == cur_time) to the
1214 peer. */
1215 lease -> tstp = lease -> ends;
1218 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1219 log_debug ("lease %s moves from %s to %s",
1220 piaddr (lease -> ip_addr),
1221 binding_state_print (lease -> binding_state),
1222 binding_state_print (lease -> next_binding_state));
1223 #endif
1225 lease -> binding_state = lease -> next_binding_state;
1226 switch (lease -> binding_state) {
1227 case FTS_ACTIVE:
1228 #if defined (FAILOVER_PROTOCOL)
1229 if (lease -> pool && lease -> pool -> failover_peer)
1230 lease -> next_binding_state = FTS_EXPIRED;
1231 else
1232 #endif
1233 lease -> next_binding_state = FTS_FREE;
1234 break;
1236 case FTS_EXPIRED:
1237 case FTS_RELEASED:
1238 case FTS_ABANDONED:
1239 case FTS_RESET:
1240 lease -> next_binding_state = FTS_FREE;
1241 /* If we are not in partner_down, leases don't go from
1242 EXPIRED to FREE on a timeout - only on an update.
1243 If we're in partner_down, they expire at mclt past
1244 the time we entered partner_down. */
1245 if (lease -> pool -> failover_peer &&
1246 lease -> pool -> failover_peer -> me.state == partner_down)
1247 lease -> tsfp =
1248 (lease -> pool -> failover_peer -> me.stos +
1249 lease -> pool -> failover_peer -> mclt);
1250 break;
1252 case FTS_FREE:
1253 case FTS_BACKUP:
1254 lease -> next_binding_state = lease -> binding_state;
1255 break;
1257 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1258 log_debug ("lease %s: next binding state %s",
1259 piaddr (lease -> ip_addr),
1260 binding_state_print (lease -> next_binding_state));
1261 #endif
1265 /* Copy the contents of one lease into another, correctly maintaining
1266 reference counts. */
1267 int lease_copy (struct lease **lp,
1268 struct lease *lease, const char *file, int line)
1270 struct lease *lt = (struct lease *)0;
1271 isc_result_t status;
1273 status = lease_allocate (&lt, MDL);
1274 if (status != ISC_R_SUCCESS)
1275 return 0;
1277 lt -> ip_addr = lease -> ip_addr;
1278 lt -> starts = lease -> starts;
1279 lt -> ends = lease -> ends;
1280 lt -> timestamp = lease -> timestamp;
1281 lt -> uid_len = lease -> uid_len;
1282 lt -> uid_max = lease -> uid_max;
1283 if (lease -> uid == lease -> uid_buf) {
1284 lt -> uid = lt -> uid_buf;
1285 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1286 } else if (!lease -> uid_max) {
1287 lt -> uid = (unsigned char *)0;
1288 } else {
1289 lt -> uid = dmalloc (lt -> uid_max, MDL);
1290 if (!lt -> uid) {
1291 lease_dereference (&lt, MDL);
1292 return 0;
1294 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1296 if (lease -> client_hostname) {
1297 lt -> client_hostname =
1298 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1299 if (!lt -> client_hostname) {
1300 lease_dereference (&lt, MDL);
1301 return 0;
1303 strcpy (lt -> client_hostname, lease -> client_hostname);
1305 if (lease -> scope)
1306 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1307 if (lease -> agent_options)
1308 option_chain_head_reference (&lt -> agent_options,
1309 lease -> agent_options, MDL);
1310 host_reference (&lt -> host, lease -> host, file, line);
1311 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1312 pool_reference (&lt -> pool, lease -> pool, file, line);
1313 class_reference (&lt -> billing_class,
1314 lease -> billing_class, file, line);
1315 lt -> hardware_addr = lease -> hardware_addr;
1316 if (lease -> on_expiry)
1317 executable_statement_reference (&lt -> on_expiry,
1318 lease -> on_expiry,
1319 file, line);
1320 if (lease -> on_commit)
1321 executable_statement_reference (&lt -> on_commit,
1322 lease -> on_commit,
1323 file, line);
1324 if (lease -> on_release)
1325 executable_statement_reference (&lt -> on_release,
1326 lease -> on_release,
1327 file, line);
1328 lt -> flags = lease -> flags;
1329 lt -> tstp = lease -> tstp;
1330 lt -> tsfp = lease -> tsfp;
1331 lt -> cltt = lease -> cltt;
1332 lt -> binding_state = lease -> binding_state;
1333 lt -> next_binding_state = lease -> next_binding_state;
1334 status = lease_reference (lp, lt, file, line);
1335 lease_dereference (&lt, MDL);
1336 return status == ISC_R_SUCCESS;
1339 /* Release the specified lease and re-hash it as appropriate. */
1340 void release_lease (lease, packet)
1341 struct lease *lease;
1342 struct packet *packet;
1344 /* If there are statements to execute when the lease is
1345 released, execute them. */
1346 #if defined (NSUPDATE)
1347 ddns_removals (lease);
1348 #endif
1349 if (lease -> on_release) {
1350 execute_statements ((struct binding_value **)0,
1351 packet, lease, (struct client_state *)0,
1352 packet -> options,
1353 (struct option_state *)0, /* XXX */
1354 &lease -> scope, lease -> on_release);
1355 if (lease -> on_release)
1356 executable_statement_dereference (&lease -> on_release,
1357 MDL);
1360 /* We do either the on_release or the on_expiry events, but
1361 not both (it's possible that they could be the same,
1362 in any case). */
1363 if (lease -> on_expiry)
1364 executable_statement_dereference (&lease -> on_expiry, MDL);
1366 if (lease -> binding_state != FTS_FREE &&
1367 lease -> binding_state != FTS_BACKUP &&
1368 lease -> binding_state != FTS_RELEASED &&
1369 lease -> binding_state != FTS_EXPIRED &&
1370 lease -> binding_state != FTS_RESET) {
1371 if (lease -> on_commit)
1372 executable_statement_dereference (&lease -> on_commit,
1373 MDL);
1375 /* Blow away any bindings. */
1376 if (lease -> scope)
1377 binding_scope_dereference (&lease -> scope, MDL);
1378 lease -> ends = cur_time;
1379 #if defined (FAILOVER_PROTOCOL)
1380 if (lease -> pool && lease -> pool -> failover_peer) {
1381 lease -> next_binding_state = FTS_RELEASED;
1382 } else {
1383 lease -> next_binding_state = FTS_FREE;
1385 #else
1386 lease -> next_binding_state = FTS_FREE;
1387 #endif
1388 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1392 /* Abandon the specified lease (set its timeout to infinity and its
1393 particulars to zero, and re-hash it as appropriate. */
1395 void abandon_lease (lease, message)
1396 struct lease *lease;
1397 const char *message;
1399 struct lease *lt = (struct lease *)0;
1401 if (!lease_copy (&lt, lease, MDL))
1402 return;
1404 if (lt->scope)
1405 binding_scope_dereference(&lt->scope, MDL);
1407 lt -> ends = cur_time; /* XXX */
1408 lt -> next_binding_state = FTS_ABANDONED;
1410 log_error ("Abandoning IP address %s: %s",
1411 piaddr (lease -> ip_addr), message);
1412 lt -> hardware_addr.hlen = 0;
1413 if (lt -> uid && lt -> uid != lt -> uid_buf)
1414 dfree (lt -> uid, MDL);
1415 lt -> uid = (unsigned char *)0;
1416 lt -> uid_len = 0;
1417 lt -> uid_max = 0;
1418 supersede_lease (lease, lt, 1, 1, 1);
1419 lease_dereference (&lt, MDL);
1422 /* Abandon the specified lease (set its timeout to infinity and its
1423 particulars to zero, and re-hash it as appropriate. */
1425 void dissociate_lease (lease)
1426 struct lease *lease;
1428 struct lease *lt = (struct lease *)0;
1430 if (!lease_copy (&lt, lease, MDL))
1431 return;
1433 #if defined (FAILOVER_PROTOCOL)
1434 if (lease -> pool && lease -> pool -> failover_peer) {
1435 lt -> next_binding_state = FTS_RESET;
1436 } else {
1437 lt -> next_binding_state = FTS_FREE;
1439 #else
1440 lt -> next_binding_state = FTS_FREE;
1441 #endif
1442 lt -> ends = cur_time; /* XXX */
1443 lt -> hardware_addr.hlen = 0;
1444 if (lt -> uid && lt -> uid != lt -> uid_buf)
1445 dfree (lt -> uid, MDL);
1446 lt -> uid = (unsigned char *)0;
1447 lt -> uid_len = 0;
1448 lt -> uid_max = 0;
1449 supersede_lease (lease, lt, 1, 1, 1);
1450 lease_dereference (&lt, MDL);
1453 /* Timer called when a lease in a particular pool expires. */
1454 void pool_timer (vpool)
1455 void *vpool;
1457 struct pool *pool;
1458 struct lease *next = (struct lease *)0;
1459 struct lease *lease = (struct lease *)0;
1460 struct lease **lptr [5];
1461 TIME next_expiry = MAX_TIME;
1462 int i;
1464 pool = (struct pool *)vpool;
1466 #define FREE_LEASES 0
1467 lptr [FREE_LEASES] = &pool -> free;
1468 #define ACTIVE_LEASES 1
1469 lptr [ACTIVE_LEASES] = &pool -> active;
1470 #define EXPIRED_LEASES 2
1471 lptr [EXPIRED_LEASES] = &pool -> expired;
1472 #define ABANDONED_LEASES 3
1473 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1474 #define BACKUP_LEASES 4
1475 lptr [BACKUP_LEASES] = &pool -> backup;
1477 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1478 /* If there's nothing on the queue, skip it. */
1479 if (!*(lptr [i]))
1480 continue;
1482 #if defined (FAILOVER_PROTOCOL)
1483 if (pool -> failover_peer &&
1484 pool -> failover_peer -> me.state != partner_down) {
1485 /* The secondary can't remove a lease from the
1486 active state except in partner_down. */
1487 if (i == ACTIVE_LEASES &&
1488 pool -> failover_peer -> i_am == secondary)
1489 continue;
1490 /* Leases in an expired state don't move to
1491 free because of a timeout unless we're in
1492 partner_down. */
1493 if (i == EXPIRED_LEASES)
1494 continue;
1496 #endif
1497 lease_reference (&lease, *(lptr [i]), MDL);
1499 while (lease) {
1500 /* Remember the next lease in the list. */
1501 if (next)
1502 lease_dereference (&next, MDL);
1503 if (lease -> next)
1504 lease_reference (&next, lease -> next, MDL);
1506 /* If we've run out of things to expire on this list,
1507 stop. */
1508 if (lease -> sort_time > cur_time) {
1509 if (lease -> sort_time < next_expiry)
1510 next_expiry = lease -> sort_time;
1511 break;
1514 /* If there is a pending state change, and
1515 this lease has gotten to the time when the
1516 state change should happen, just call
1517 supersede_lease on it to make the change
1518 happen. */
1519 if (lease -> next_binding_state !=
1520 lease -> binding_state)
1521 supersede_lease (lease,
1522 (struct lease *)0, 1, 1, 1);
1524 lease_dereference (&lease, MDL);
1525 if (next)
1526 lease_reference (&lease, next, MDL);
1528 if (next)
1529 lease_dereference (&next, MDL);
1530 if (lease)
1531 lease_dereference (&lease, MDL);
1533 if (next_expiry != MAX_TIME) {
1534 pool -> next_event_time = next_expiry;
1535 add_timeout (pool -> next_event_time, pool_timer, pool,
1536 (tvref_t)pool_reference,
1537 (tvunref_t)pool_dereference);
1538 } else
1539 pool -> next_event_time = MIN_TIME;
1543 /* Locate the lease associated with a given IP address... */
1545 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1546 const char *file, int line)
1548 return lease_hash_lookup (lp, lease_ip_addr_hash,
1549 addr.iabuf, addr.len, file, line);
1552 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1553 unsigned len, const char *file, int line)
1555 if (len == 0)
1556 return 0;
1557 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1560 int find_lease_by_hw_addr (struct lease **lp,
1561 const unsigned char *hwaddr, unsigned hwlen,
1562 const char *file, int line)
1564 if (hwlen == 0)
1565 return 0;
1566 return lease_hash_lookup (lp, lease_hw_addr_hash,
1567 hwaddr, hwlen, file, line);
1570 /* Add the specified lease to the uid hash. */
1572 void uid_hash_add (lease)
1573 struct lease *lease;
1575 struct lease *head = (struct lease *)0;
1576 struct lease *next = (struct lease *)0;
1579 /* If it's not in the hash, just add it. */
1580 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1581 lease_hash_add (lease_uid_hash, lease -> uid,
1582 lease -> uid_len, lease, MDL);
1583 else {
1584 /* Otherwise, attach it to the end of the list. */
1585 while (head -> n_uid) {
1586 lease_reference (&next, head -> n_uid, MDL);
1587 lease_dereference (&head, MDL);
1588 lease_reference (&head, next, MDL);
1589 lease_dereference (&next, MDL);
1591 lease_reference (&head -> n_uid, lease, MDL);
1592 lease_dereference (&head, MDL);
1596 /* Delete the specified lease from the uid hash. */
1598 void uid_hash_delete (lease)
1599 struct lease *lease;
1601 struct lease *head = (struct lease *)0;
1602 struct lease *scan;
1604 /* If it's not in the hash, we have no work to do. */
1605 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1606 if (lease -> n_uid)
1607 lease_dereference (&lease -> n_uid, MDL);
1608 return;
1611 /* If the lease we're freeing is at the head of the list,
1612 remove the hash table entry and add a new one with the
1613 next lease on the list (if there is one). */
1614 if (head == lease) {
1615 lease_hash_delete (lease_uid_hash,
1616 lease -> uid, lease -> uid_len, MDL);
1617 if (lease -> n_uid) {
1618 lease_hash_add (lease_uid_hash,
1619 lease -> n_uid -> uid,
1620 lease -> n_uid -> uid_len,
1621 lease -> n_uid, MDL);
1622 lease_dereference (&lease -> n_uid, MDL);
1624 } else {
1625 /* Otherwise, look for the lease in the list of leases
1626 attached to the hash table entry, and remove it if
1627 we find it. */
1628 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1629 if (scan -> n_uid == lease) {
1630 lease_dereference (&scan -> n_uid, MDL);
1631 if (lease -> n_uid) {
1632 lease_reference (&scan -> n_uid,
1633 lease -> n_uid, MDL);
1634 lease_dereference (&lease -> n_uid,
1635 MDL);
1637 break;
1641 lease_dereference (&head, MDL);
1644 /* Add the specified lease to the hardware address hash. */
1646 void hw_hash_add (lease)
1647 struct lease *lease;
1649 struct lease *head = (struct lease *)0;
1650 struct lease *next = (struct lease *)0;
1652 /* If it's not in the hash, just add it. */
1653 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1654 lease -> hardware_addr.hlen, MDL))
1655 lease_hash_add (lease_hw_addr_hash,
1656 lease -> hardware_addr.hbuf,
1657 lease -> hardware_addr.hlen,
1658 lease, MDL);
1659 else {
1660 /* Otherwise, attach it to the end of the list. */
1661 while (head -> n_hw) {
1662 lease_reference (&next, head -> n_hw, MDL);
1663 lease_dereference (&head, MDL);
1664 lease_reference (&head, next, MDL);
1665 lease_dereference (&next, MDL);
1668 lease_reference (&head -> n_hw, lease, MDL);
1669 lease_dereference (&head, MDL);
1673 /* Delete the specified lease from the hardware address hash. */
1675 void hw_hash_delete (lease)
1676 struct lease *lease;
1678 struct lease *head = (struct lease *)0;
1679 struct lease *next = (struct lease *)0;
1681 /* If it's not in the hash, we have no work to do. */
1682 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1683 lease -> hardware_addr.hlen, MDL)) {
1684 if (lease -> n_hw)
1685 lease_dereference (&lease -> n_hw, MDL);
1686 return;
1689 /* If the lease we're freeing is at the head of the list,
1690 remove the hash table entry and add a new one with the
1691 next lease on the list (if there is one). */
1692 if (head == lease) {
1693 lease_hash_delete (lease_hw_addr_hash,
1694 lease -> hardware_addr.hbuf,
1695 lease -> hardware_addr.hlen, MDL);
1696 if (lease -> n_hw) {
1697 lease_hash_add (lease_hw_addr_hash,
1698 lease -> n_hw -> hardware_addr.hbuf,
1699 lease -> n_hw -> hardware_addr.hlen,
1700 lease -> n_hw, MDL);
1701 lease_dereference (&lease -> n_hw, MDL);
1703 } else {
1704 /* Otherwise, look for the lease in the list of leases
1705 attached to the hash table entry, and remove it if
1706 we find it. */
1707 while (head -> n_hw) {
1708 if (head -> n_hw == lease) {
1709 lease_dereference (&head -> n_hw, MDL);
1710 if (lease -> n_hw) {
1711 lease_reference (&head -> n_hw,
1712 lease -> n_hw, MDL);
1713 lease_dereference (&lease -> n_hw,
1714 MDL);
1716 break;
1718 lease_reference (&next, head -> n_hw, MDL);
1719 lease_dereference (&head, MDL);
1720 lease_reference (&head, next, MDL);
1721 lease_dereference (&next, MDL);
1724 if (head)
1725 lease_dereference (&head, MDL);
1728 /* Write all interesting leases to permanent storage. */
1730 int write_leases ()
1732 struct lease *l;
1733 struct shared_network *s;
1734 struct pool *p;
1735 struct host_decl *hp;
1736 struct group_object *gp;
1737 struct hash_bucket *hb;
1738 int i;
1739 int num_written;
1740 struct lease **lptr [5];
1742 /* Write all the dynamically-created group declarations. */
1743 if (group_name_hash) {
1744 num_written = 0;
1745 for (i = 0; i < group_name_hash -> hash_count; i++) {
1746 for (hb = group_name_hash -> buckets [i];
1747 hb; hb = hb -> next) {
1748 gp = (struct group_object *)hb -> value;
1749 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1750 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1751 (gp -> flags & GROUP_OBJECT_DELETED))) {
1752 if (!write_group (gp))
1753 return 0;
1754 ++num_written;
1758 log_info ("Wrote %d group decls to leases file.", num_written);
1761 /* Write all the deleted host declarations. */
1762 if (host_name_hash) {
1763 num_written = 0;
1764 for (i = 0; i < host_name_hash -> hash_count; i++) {
1765 for (hb = host_name_hash -> buckets [i];
1766 hb; hb = hb -> next) {
1767 hp = (struct host_decl *)hb -> value;
1768 if (((hp -> flags & HOST_DECL_STATIC) &&
1769 (hp -> flags & HOST_DECL_DELETED))) {
1770 if (!write_host (hp))
1771 return 0;
1772 ++num_written;
1776 log_info ("Wrote %d deleted host decls to leases file.",
1777 num_written);
1780 /* Write all the new, dynamic host declarations. */
1781 if (host_name_hash) {
1782 num_written = 0;
1783 for (i = 0; i < host_name_hash -> hash_count; i++) {
1784 for (hb = host_name_hash -> buckets [i];
1785 hb; hb = hb -> next) {
1786 hp = (struct host_decl *)hb -> value;
1787 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1788 if (!write_host (hp))
1789 ++num_written;
1793 log_info ("Wrote %d new dynamic host decls to leases file.",
1794 num_written);
1797 #if defined (FAILOVER_PROTOCOL)
1798 /* Write all the failover states. */
1799 if (!dhcp_failover_write_all_states ())
1800 return 0;
1801 #endif
1803 /* Write all the leases. */
1804 num_written = 0;
1805 for (s = shared_networks; s; s = s -> next) {
1806 for (p = s -> pools; p; p = p -> next) {
1807 lptr [FREE_LEASES] = &p -> free;
1808 lptr [ACTIVE_LEASES] = &p -> active;
1809 lptr [EXPIRED_LEASES] = &p -> expired;
1810 lptr [ABANDONED_LEASES] = &p -> abandoned;
1811 lptr [BACKUP_LEASES] = &p -> backup;
1813 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1814 for (l = *(lptr [i]); l; l = l -> next) {
1815 #if !defined (DEBUG_DUMP_ALL_LEASES)
1816 if (l -> hardware_addr.hlen ||
1817 l -> uid_len ||
1818 (l -> binding_state != FTS_FREE))
1819 #endif
1821 if (!write_lease (l))
1822 return 0;
1823 num_written++;
1829 log_info ("Wrote %d leases to leases file.", num_written);
1830 if (!commit_leases ())
1831 return 0;
1832 return 1;
1835 int lease_enqueue (struct lease *comp)
1837 struct lease **lq, *prev, *lp;
1839 /* No queue to put it on? */
1840 if (!comp -> pool)
1841 return 0;
1843 /* Figure out which queue it's going to. */
1844 switch (comp -> binding_state) {
1845 case FTS_FREE:
1846 lq = &comp -> pool -> free;
1847 comp -> pool -> free_leases++;
1848 comp -> sort_time = comp -> ends;
1849 break;
1851 case FTS_ACTIVE:
1852 lq = &comp -> pool -> active;
1853 comp -> sort_time = comp -> ends;
1854 break;
1856 case FTS_EXPIRED:
1857 case FTS_RELEASED:
1858 case FTS_RESET:
1859 lq = &comp -> pool -> expired;
1860 comp -> sort_time = comp -> ends;
1862 break;
1864 case FTS_ABANDONED:
1865 lq = &comp -> pool -> abandoned;
1866 comp -> sort_time = comp -> ends;
1867 break;
1869 case FTS_BACKUP:
1870 lq = &comp -> pool -> backup;
1871 comp -> pool -> backup_leases++;
1872 comp -> sort_time = comp -> ends;
1873 break;
1875 default:
1876 log_error ("Lease with bogus binding state: %d",
1877 comp -> binding_state);
1878 #if defined (BINDING_STATE_DEBUG)
1879 abort ();
1880 #endif
1881 return 0;
1884 /* Insertion sort the lease onto the appropriate queue. */
1885 prev = (struct lease *)0;
1886 for (lp = *lq; lp; lp = lp -> next) {
1887 if (lp -> sort_time >= comp -> sort_time)
1888 break;
1889 prev = lp;
1891 if (prev) {
1892 if (prev -> next) {
1893 lease_reference (&comp -> next, prev -> next, MDL);
1894 lease_dereference (&prev -> next, MDL);
1896 lease_reference (&prev -> next, comp, MDL);
1897 } else {
1898 if (*lq) {
1899 lease_reference (&comp -> next, *lq, MDL);
1900 lease_dereference (lq, MDL);
1902 lease_reference (lq, comp, MDL);
1904 return 1;
1907 /* For a given lease, sort it onto the right list in its pool and put it
1908 in each appropriate hash, understanding that it's already by definition
1909 in lease_ip_addr_hash. */
1911 void lease_instantiate (const unsigned char *val, unsigned len,
1912 struct lease *lease)
1914 struct class *class;
1915 /* XXX If the lease doesn't have a pool at this point, it's an
1916 XXX orphan, which we *should* keep around until it expires,
1917 XXX but which right now we just forget. */
1918 if (!lease -> pool) {
1919 lease_hash_delete (lease_ip_addr_hash,
1920 lease -> ip_addr.iabuf,
1921 lease -> ip_addr.len, MDL);
1922 return;
1925 /* Put the lease on the right queue. */
1926 lease_enqueue (lease);
1928 /* Record the lease in the uid hash if possible. */
1929 if (lease -> uid) {
1930 uid_hash_add (lease);
1933 /* Record it in the hardware address hash if possible. */
1934 if (lease -> hardware_addr.hlen) {
1935 hw_hash_add (lease);
1938 /* If the lease has a billing class, set up the billing. */
1939 if (lease -> billing_class) {
1940 class = (struct class *)0;
1941 class_reference (&class, lease -> billing_class, MDL);
1942 class_dereference (&lease -> billing_class, MDL);
1943 /* If the lease is available for allocation, the billing
1944 is invalid, so we don't keep it. */
1945 if (lease -> binding_state == FTS_ACTIVE ||
1946 lease -> binding_state == FTS_EXPIRED ||
1947 lease -> binding_state == FTS_RELEASED ||
1948 lease -> binding_state == FTS_RESET)
1949 bill_class (lease, class);
1950 class_dereference (&class, MDL);
1952 return;
1955 /* Run expiry events on every pool. This is called on startup so that
1956 any expiry events that occurred after the server stopped and before it
1957 was restarted can be run. At the same time, if failover support is
1958 compiled in, we compute the balance of leases for the pool. */
1960 void expire_all_pools ()
1962 struct shared_network *s;
1963 struct pool *p;
1964 int i;
1965 struct lease *l;
1966 struct lease **lptr [5];
1968 /* First, go over the hash list and actually put all the leases
1969 on the appropriate lists. */
1970 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1972 /* Loop through each pool in each shared network and call the
1973 expiry routine on the pool. */
1974 for (s = shared_networks; s; s = s -> next) {
1975 for (p = s -> pools; p; p = p -> next) {
1976 pool_timer (p);
1978 p -> lease_count = 0;
1979 p -> free_leases = 0;
1980 p -> backup_leases = 0;
1982 lptr [FREE_LEASES] = &p -> free;
1983 lptr [ACTIVE_LEASES] = &p -> active;
1984 lptr [EXPIRED_LEASES] = &p -> expired;
1985 lptr [ABANDONED_LEASES] = &p -> abandoned;
1986 lptr [BACKUP_LEASES] = &p -> backup;
1988 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1989 for (l = *(lptr [i]); l; l = l -> next) {
1990 p -> lease_count++;
1991 if (l -> ends <= cur_time) {
1992 if (l -> binding_state == FTS_FREE)
1993 p -> free_leases++;
1994 else if (l -> binding_state == FTS_BACKUP)
1995 p -> backup_leases++;
1997 #if defined (FAILOVER_PROTOCOL)
1998 if (p -> failover_peer &&
1999 l -> tstp > l -> tsfp &&
2000 !(l -> flags & ON_UPDATE_QUEUE)) {
2001 l -> desired_binding_state = l -> binding_state;
2002 dhcp_failover_queue_update (l, 1);
2004 #endif
2011 void dump_subnets ()
2013 struct lease *l;
2014 struct shared_network *s;
2015 struct subnet *n;
2016 struct pool *p;
2017 struct lease **lptr [5];
2018 int i;
2020 log_info ("Subnets:");
2021 for (n = subnets; n; n = n -> next_subnet) {
2022 log_debug (" Subnet %s", piaddr (n -> net));
2023 log_debug (" netmask %s",
2024 piaddr (n -> netmask));
2026 log_info ("Shared networks:");
2027 for (s = shared_networks; s; s = s -> next) {
2028 log_info (" %s", s -> name);
2029 for (p = s -> pools; p; p = p -> next) {
2030 lptr [FREE_LEASES] = &p -> free;
2031 lptr [ACTIVE_LEASES] = &p -> active;
2032 lptr [EXPIRED_LEASES] = &p -> expired;
2033 lptr [ABANDONED_LEASES] = &p -> abandoned;
2034 lptr [BACKUP_LEASES] = &p -> backup;
2036 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
2037 for (l = *(lptr [i]); l; l = l -> next) {
2038 print_lease (l);
2045 HASH_FUNCTIONS (lease, const unsigned char *, struct lease, lease_hash_t,
2046 lease_reference, lease_dereference)
2047 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2048 host_reference, host_dereference)
2049 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2050 class_reference, class_dereference)
2052 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2053 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2054 extern struct hash_table *dns_zone_hash;
2055 extern struct interface_info **interface_vector;
2056 extern int interface_count;
2057 dhcp_control_object_t *dhcp_control_object;
2058 extern struct hash_table *auth_key_hash;
2059 struct hash_table *universe_hash;
2060 struct universe **universes;
2061 int universe_count, universe_max;
2062 #if 0
2063 extern int end;
2064 #endif
2066 #if defined (COMPACT_LEASES)
2067 extern struct lease *lease_hunks;
2068 #endif
2070 void free_everything ()
2072 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
2073 struct shared_network *nc = (struct shared_network *)0,
2074 *nn = (struct shared_network *)0;
2075 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
2076 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
2077 struct interface_info *ic = (struct interface_info *)0,
2078 *in = (struct interface_info *)0;
2079 struct class *cc = (struct class *)0, *cn = (struct class *)0;
2080 struct collection *lp;
2081 void *st = (shared_networks
2082 ? (shared_networks -> next
2083 ? shared_networks -> next -> next : 0) : 0);
2084 int i;
2087 /* Get rid of all the hash tables. */
2088 if (host_hw_addr_hash)
2089 host_free_hash_table (&host_hw_addr_hash, MDL);
2090 host_hw_addr_hash = 0;
2091 if (host_uid_hash)
2092 host_free_hash_table (&host_uid_hash, MDL);
2093 host_uid_hash = 0;
2094 if (lease_uid_hash)
2095 lease_free_hash_table (&lease_uid_hash, MDL);
2096 lease_uid_hash = 0;
2097 if (lease_ip_addr_hash)
2098 lease_free_hash_table (&lease_ip_addr_hash, MDL);
2099 lease_ip_addr_hash = 0;
2100 if (lease_hw_addr_hash)
2101 lease_free_hash_table (&lease_hw_addr_hash, MDL);
2102 lease_hw_addr_hash = 0;
2103 if (host_name_hash)
2104 host_free_hash_table (&host_name_hash, MDL);
2105 host_name_hash = 0;
2106 if (dns_zone_hash)
2107 dns_zone_free_hash_table (&dns_zone_hash, MDL);
2108 dns_zone_hash = 0;
2109 #if 0
2110 if (auth_key_hash)
2111 auth_key_free_hash_table (&auth_key_hash, MDL);
2112 #endif
2113 auth_key_hash = 0;
2115 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
2116 MDL);
2118 for (lp = collections; lp; lp = lp -> next) {
2119 if (lp -> classes) {
2120 class_reference (&cn, lp -> classes, MDL);
2121 do {
2122 if (cn) {
2123 class_reference (&cc, cn, MDL);
2124 class_dereference (&cn, MDL);
2126 if (cc -> nic) {
2127 class_reference (&cn, cc -> nic, MDL);
2128 class_dereference (&cc -> nic, MDL);
2130 group_dereference (&cc -> group, MDL);
2131 if (cc -> hash) {
2132 class_free_hash_table (&cc -> hash, MDL);
2133 cc -> hash = (struct hash_table *)0;
2135 class_dereference (&cc, MDL);
2136 } while (cn);
2137 class_dereference (&lp -> classes, MDL);
2141 if (interface_vector) {
2142 for (i = 0; i < interface_count; i++) {
2143 if (interface_vector [i])
2144 interface_dereference (&interface_vector [i], MDL);
2146 dfree (interface_vector, MDL);
2147 interface_vector = 0;
2150 if (interfaces) {
2151 interface_reference (&in, interfaces, MDL);
2152 do {
2153 if (in) {
2154 interface_reference (&ic, in, MDL);
2155 interface_dereference (&in, MDL);
2157 if (ic -> next) {
2158 interface_reference (&in, ic -> next, MDL);
2159 interface_dereference (&ic -> next, MDL);
2161 omapi_unregister_io_object ((omapi_object_t *)ic);
2162 if (ic -> shared_network) {
2163 if (ic -> shared_network -> interface)
2164 interface_dereference
2165 (&ic -> shared_network -> interface, MDL);
2166 shared_network_dereference (&ic -> shared_network, MDL);
2168 interface_dereference (&ic, MDL);
2169 } while (in);
2170 interface_dereference (&interfaces, MDL);
2173 /* Subnets are complicated because of the extra links. */
2174 if (subnets) {
2175 subnet_reference (&sn, subnets, MDL);
2176 do {
2177 if (sn) {
2178 subnet_reference (&sc, sn, MDL);
2179 subnet_dereference (&sn, MDL);
2181 if (sc -> next_subnet) {
2182 subnet_reference (&sn, sc -> next_subnet, MDL);
2183 subnet_dereference (&sc -> next_subnet, MDL);
2185 if (sc -> next_sibling)
2186 subnet_dereference (&sc -> next_sibling, MDL);
2187 if (sc -> shared_network)
2188 shared_network_dereference (&sc -> shared_network, MDL);
2189 group_dereference (&sc -> group, MDL);
2190 if (sc -> interface)
2191 interface_dereference (&sc -> interface, MDL);
2192 subnet_dereference (&sc, MDL);
2193 } while (sn);
2194 subnet_dereference (&subnets, MDL);
2197 /* So are shared networks. */
2198 if (shared_networks) {
2199 shared_network_reference (&nn, shared_networks, MDL);
2200 do {
2201 if (nn) {
2202 shared_network_reference (&nc, nn, MDL);
2203 shared_network_dereference (&nn, MDL);
2205 if (nc -> next) {
2206 shared_network_reference (&nn, nc -> next, MDL);
2207 shared_network_dereference (&nc -> next, MDL);
2210 /* As are pools. */
2211 if (nc -> pools) {
2212 pool_reference (&pn, nc -> pools, MDL);
2213 do {
2214 struct lease **lptr [5];
2216 if (pn) {
2217 pool_reference (&pc, pn, MDL);
2218 pool_dereference (&pn, MDL);
2220 if (pc -> next) {
2221 pool_reference (&pn, pc -> next, MDL);
2222 pool_dereference (&pc -> next, MDL);
2225 lptr [FREE_LEASES] = &pc -> free;
2226 lptr [ACTIVE_LEASES] = &pc -> active;
2227 lptr [EXPIRED_LEASES] = &pc -> expired;
2228 lptr [ABANDONED_LEASES] = &pc -> abandoned;
2229 lptr [BACKUP_LEASES] = &pc -> backup;
2231 /* As (sigh) are leases. */
2232 for (i = 0; i < 5; i++) {
2233 if (*lptr [i]) {
2234 lease_reference (&ln, *lptr [i], MDL);
2235 do {
2236 if (ln) {
2237 lease_reference (&lc, ln, MDL);
2238 lease_dereference (&ln, MDL);
2240 if (lc -> next) {
2241 lease_reference (&ln, lc -> next, MDL);
2242 lease_dereference (&lc -> next, MDL);
2244 if (lc -> billing_class)
2245 class_dereference (&lc -> billing_class,
2246 MDL);
2247 if (lc -> state)
2248 free_lease_state (lc -> state, MDL);
2249 lc -> state = (struct lease_state *)0;
2250 if (lc -> n_hw)
2251 lease_dereference (&lc -> n_hw, MDL);
2252 if (lc -> n_uid)
2253 lease_dereference (&lc -> n_uid, MDL);
2254 lease_dereference (&lc, MDL);
2255 } while (ln);
2256 lease_dereference (lptr [i], MDL);
2259 if (pc -> group)
2260 group_dereference (&pc -> group, MDL);
2261 if (pc -> shared_network)
2262 shared_network_dereference (&pc -> shared_network,
2263 MDL);
2264 pool_dereference (&pc, MDL);
2265 } while (pn);
2266 pool_dereference (&nc -> pools, MDL);
2268 /* Because of a circular reference, we need to nuke this
2269 manually. */
2270 group_dereference (&nc -> group, MDL);
2271 shared_network_dereference (&nc, MDL);
2272 } while (nn);
2273 shared_network_dereference (&shared_networks, MDL);
2276 cancel_all_timeouts ();
2277 relinquish_timeouts ();
2278 trace_free_all ();
2279 group_dereference (&root_group, MDL);
2280 executable_statement_dereference (&default_classification_rules, MDL);
2282 shutdown_state = shutdown_drop_omapi_connections;
2283 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2284 shutdown_state = shutdown_listeners;
2285 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2286 shutdown_state = shutdown_dhcp;
2287 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2289 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
2291 universe_free_hash_table (&universe_hash, MDL);
2292 for (i = 0; i < universe_count; i++) {
2293 union {
2294 const char *c;
2295 char *s;
2296 } foo;
2297 if (universes [i]) {
2298 if (universes [i] -> hash)
2299 option_free_hash_table (&universes [i] -> hash,
2300 MDL);
2301 #if 0
2302 if (universes [i] -> name > (char *)&end) {
2303 foo.c = universes [i] -> name;
2304 dfree (foo.s, MDL);
2306 if (universes [i] > (struct universe *)&end)
2307 dfree (universes [i], MDL);
2308 #endif
2311 dfree (universes, MDL);
2313 relinquish_free_lease_states ();
2314 relinquish_free_pairs ();
2315 relinquish_free_expressions ();
2316 relinquish_free_binding_values ();
2317 relinquish_free_option_caches ();
2318 relinquish_free_packets ();
2319 relinquish_lease_hunks ();
2320 relinquish_hash_bucket_hunks ();
2321 omapi_type_relinquish ();
2323 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */