Switch from bioq_insert_tail() to bioqdisksort(). When the kernel is
[dragonfly.git] / contrib / dhcp-3.0 / server / mdb.c
blob7ee779e7070a550c131b828a93f7a06058e36ae6
1 /* mdb.c
3 Server-specific in-memory database support. */
5 /*
6 * Copyright (c) 2004 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.67.2.20 2004/09/01 20:19:44 dhankins Exp $ Copyright (c) 2004 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 struct executable_statement *esp;
242 int hw_head = 0, uid_head = 1;
244 /* Don't need to do it twice. */
245 if (hd -> flags & HOST_DECL_DELETED)
246 return ISC_R_SUCCESS;
248 /* But we do need to do it once! :') */
249 hd -> flags |= HOST_DECL_DELETED;
251 if (hd -> interface.hlen) {
252 if (host_hw_addr_hash) {
253 if (host_hash_lookup (&hp, host_hw_addr_hash,
254 hd -> interface.hbuf,
255 hd -> interface.hlen, MDL)) {
256 if (hp == hd) {
257 host_hash_delete (host_hw_addr_hash,
258 hd -> interface.hbuf,
259 hd -> interface.hlen, MDL);
260 hw_head = 1;
261 } else {
262 np = (struct host_decl *)0;
263 foo = (struct host_decl *)0;
264 host_reference (&foo, hp, MDL);
265 while (foo) {
266 if (foo == hd)
267 break;
268 if (np)
269 host_dereference (&np, MDL);
270 host_reference (&np, foo, MDL);
271 host_dereference (&foo, MDL);
272 if (np -> n_ipaddr)
273 host_reference (&foo, np -> n_ipaddr, MDL);
276 if (foo) {
277 host_dereference (&np -> n_ipaddr, MDL);
278 if (hd -> n_ipaddr)
279 host_reference (&np -> n_ipaddr,
280 hd -> n_ipaddr, MDL);
281 host_dereference (&foo, MDL);
283 if (np)
284 host_dereference (&np, MDL);
286 host_dereference (&hp, MDL);
291 /* If we got a client identifier, hash this entry by
292 client identifier. */
293 if (hd -> client_identifier.len) {
294 if (host_uid_hash) {
295 if (host_hash_lookup (&hp, host_uid_hash,
296 hd -> client_identifier.data,
297 hd -> client_identifier.len, MDL)) {
298 if (hp == hd) {
299 host_hash_delete (host_uid_hash,
300 hd -> client_identifier.data,
301 hd -> client_identifier.len, MDL);
302 uid_head = 1;
303 } else {
304 np = (struct host_decl *)0;
305 foo = (struct host_decl *)0;
306 host_reference (&foo, hp, MDL);
307 while (foo) {
308 if (foo == hd)
309 break;
310 if (np)
311 host_dereference (&np, MDL);
312 host_reference (&np, foo, MDL);
313 host_dereference (&foo, MDL);
314 if (np -> n_ipaddr)
315 host_reference (&foo, np -> n_ipaddr, MDL);
318 if (foo) {
319 host_dereference (&np -> n_ipaddr, MDL);
320 if (hd -> n_ipaddr)
321 host_reference (&np -> n_ipaddr,
322 hd -> n_ipaddr, MDL);
323 host_dereference (&foo, MDL);
325 if (np)
326 host_dereference (&np, MDL);
328 host_dereference (&hp, MDL);
333 if (hd -> n_ipaddr) {
334 if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
335 host_hash_add
336 (host_uid_hash,
337 hd -> n_ipaddr -> client_identifier.data,
338 hd -> n_ipaddr -> client_identifier.len,
339 hd -> n_ipaddr, MDL);
341 if (hw_head && hd -> n_ipaddr -> interface.hlen) {
342 host_hash_add (host_hw_addr_hash,
343 hd -> n_ipaddr -> interface.hbuf,
344 hd -> n_ipaddr -> interface.hlen,
345 hd -> n_ipaddr, MDL);
347 host_dereference (&hd -> n_ipaddr, MDL);
350 if (host_name_hash) {
351 if (host_hash_lookup (&hp, host_name_hash,
352 (unsigned char *)hd -> name,
353 strlen (hd -> name), MDL)) {
354 if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
355 host_hash_delete (host_name_hash,
356 (unsigned char *)hd -> name,
357 strlen (hd -> name), MDL);
359 host_dereference (&hp, MDL);
363 if (commit) {
364 if (!write_host (hd))
365 return ISC_R_IOERROR;
366 if (!commit_leases ())
367 return ISC_R_IOERROR;
369 return ISC_R_SUCCESS;
372 int find_hosts_by_haddr (struct host_decl **hp, int htype,
373 const unsigned char *haddr, unsigned hlen,
374 const char *file, int line)
376 struct host_decl *foo;
377 struct hardware h;
379 h.hlen = hlen + 1;
380 h.hbuf [0] = htype;
381 memcpy (&h.hbuf [1], haddr, hlen);
383 return host_hash_lookup (hp, host_hw_addr_hash,
384 h.hbuf, h.hlen, file, line);
387 int find_hosts_by_uid (struct host_decl **hp,
388 const unsigned char *data, unsigned len,
389 const char *file, int line)
391 return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
394 /* More than one host_decl can be returned by find_hosts_by_haddr or
395 find_hosts_by_uid, and each host_decl can have multiple addresses.
396 Loop through the list of hosts, and then for each host, through the
397 list of addresses, looking for an address that's in the same shared
398 network as the one specified. Store the matching address through
399 the addr pointer, update the host pointer to point at the host_decl
400 that matched, and return the subnet that matched. */
402 int find_host_for_network (struct subnet **sp, struct host_decl **host,
403 struct iaddr *addr, struct shared_network *share)
405 int i;
406 struct subnet *subnet;
407 struct iaddr ip_address;
408 struct host_decl *hp;
409 struct data_string fixed_addr;
411 memset (&fixed_addr, 0, sizeof fixed_addr);
413 for (hp = *host; hp; hp = hp -> n_ipaddr) {
414 if (!hp -> fixed_addr)
415 continue;
416 if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
417 (struct lease *)0,
418 (struct client_state *)0,
419 (struct option_state *)0,
420 (struct option_state *)0,
421 &global_scope,
422 hp -> fixed_addr, MDL))
423 continue;
424 for (i = 0; i < fixed_addr.len; i += 4) {
425 ip_address.len = 4;
426 memcpy (ip_address.iabuf,
427 fixed_addr.data + i, 4);
428 if (find_grouped_subnet (sp, share, ip_address, MDL)) {
429 struct host_decl *tmp = (struct host_decl *)0;
430 *addr = ip_address;
431 /* This is probably not necessary, but
432 just in case *host is the only reference
433 to that host declaration, make a temporary
434 reference so that dereferencing it doesn't
435 dereference hp out from under us. */
436 host_reference (&tmp, *host, MDL);
437 host_dereference (host, MDL);
438 host_reference (host, hp, MDL);
439 host_dereference (&tmp, MDL);
440 data_string_forget (&fixed_addr, MDL);
441 return 1;
444 data_string_forget (&fixed_addr, MDL);
446 return 0;
449 void new_address_range (cfile, low, high, subnet, pool, lpchain)
450 struct parse *cfile;
451 struct iaddr low, high;
452 struct subnet *subnet;
453 struct pool *pool;
454 struct lease **lpchain;
456 struct lease *address_range, *lp, *plp;
457 struct iaddr net;
458 unsigned min, max, i;
459 char lowbuf [16], highbuf [16], netbuf [16];
460 struct shared_network *share = subnet -> shared_network;
461 isc_result_t status;
462 struct lease *lt = (struct lease *)0;
464 /* All subnets should have attached shared network structures. */
465 if (!share) {
466 strcpy (netbuf, piaddr (subnet -> net));
467 log_fatal ("No shared network for network %s (%s)",
468 netbuf, piaddr (subnet -> netmask));
471 /* Initialize the hash table if it hasn't been done yet. */
472 if (!lease_uid_hash) {
473 if (!lease_new_hash (&lease_uid_hash, 0, MDL))
474 log_fatal ("Can't allocate lease/uid hash");
476 if (!lease_ip_addr_hash) {
477 if (!lease_new_hash (&lease_ip_addr_hash, 0, MDL))
478 log_fatal ("Can't allocate lease/ip hash");
480 if (!lease_hw_addr_hash) {
481 if (!lease_new_hash (&lease_hw_addr_hash, 0, MDL))
482 log_fatal ("Can't allocate lease/hw hash");
485 /* Make sure that high and low addresses are in same subnet. */
486 net = subnet_number (low, subnet -> netmask);
487 if (!addr_eq (net, subnet_number (high, subnet -> netmask))) {
488 strcpy (lowbuf, piaddr (low));
489 strcpy (highbuf, piaddr (high));
490 strcpy (netbuf, piaddr (subnet -> netmask));
491 log_fatal ("Address range %s to %s, netmask %s spans %s!",
492 lowbuf, highbuf, netbuf, "multiple subnets");
495 /* Make sure that the addresses are on the correct subnet. */
496 if (!addr_eq (net, subnet -> net)) {
497 strcpy (lowbuf, piaddr (low));
498 strcpy (highbuf, piaddr (high));
499 strcpy (netbuf, piaddr (subnet -> netmask));
500 log_fatal ("Address range %s to %s not on net %s/%s!",
501 lowbuf, highbuf, piaddr (subnet -> net), netbuf);
504 /* Get the high and low host addresses... */
505 max = host_addr (high, subnet -> netmask);
506 min = host_addr (low, subnet -> netmask);
508 /* Allow range to be specified high-to-low as well as low-to-high. */
509 if (min > max) {
510 max = min;
511 min = host_addr (high, subnet -> netmask);
514 /* Get a lease structure for each address in the range. */
515 #if defined (COMPACT_LEASES)
516 address_range = new_leases (max - min + 1, MDL);
517 if (!address_range) {
518 strcpy (lowbuf, piaddr (low));
519 strcpy (highbuf, piaddr (high));
520 log_fatal ("No memory for address range %s-%s.",
521 lowbuf, highbuf);
523 #endif
525 /* Fill out the lease structures with some minimal information. */
526 for (i = 0; i < max - min + 1; i++) {
527 struct lease *lp = (struct lease *)0;
528 #if defined (COMPACT_LEASES)
529 omapi_object_initialize ((omapi_object_t *)&address_range [i],
530 dhcp_type_lease,
531 0, sizeof (struct lease), MDL);
532 lease_reference (&lp, &address_range [i], MDL);
533 #else
534 status = lease_allocate (&lp, MDL);
535 if (status != ISC_R_SUCCESS)
536 log_fatal ("No memory for lease %s: %s",
537 piaddr (ip_addr (subnet -> net,
538 subnet -> netmask,
539 i + min)),
540 isc_result_totext (status));
541 #endif
542 lp -> ip_addr = ip_addr (subnet -> net,
543 subnet -> netmask, i + min);
544 lp -> starts = lp -> timestamp = MIN_TIME;
545 lp -> ends = MIN_TIME;
546 subnet_reference (&lp -> subnet, subnet, MDL);
547 pool_reference (&lp -> pool, pool, MDL);
548 lp -> binding_state = FTS_FREE;
549 lp -> next_binding_state = FTS_FREE;
550 lp -> flags = 0;
552 /* Remember the lease in the IP address hash. */
553 if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
554 if (lt -> pool) {
555 parse_warn (cfile,
556 "lease %s is declared twice!",
557 piaddr (lp -> ip_addr));
558 } else
559 pool_reference (&lt -> pool, pool, MDL);
560 lease_dereference (&lt, MDL);
561 } else
562 lease_hash_add (lease_ip_addr_hash,
563 lp -> ip_addr.iabuf,
564 lp -> ip_addr.len, lp, MDL);
565 /* Put the lease on the chain for the caller. */
566 if (lpchain) {
567 if (*lpchain) {
568 lease_reference (&lp -> next, *lpchain, MDL);
569 lease_dereference (lpchain, MDL);
571 lease_reference (lpchain, lp, MDL);
573 lease_dereference (&lp, MDL);
577 int find_subnet (struct subnet **sp,
578 struct iaddr addr, const char *file, int line)
580 struct subnet *rv;
582 for (rv = subnets; rv; rv = rv -> next_subnet) {
583 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
584 if (subnet_reference (sp, rv,
585 file, line) != ISC_R_SUCCESS)
586 return 0;
587 return 1;
590 return 0;
593 int find_grouped_subnet (struct subnet **sp,
594 struct shared_network *share, struct iaddr addr,
595 const char *file, int line)
597 struct subnet *rv;
599 for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
600 if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
601 if (subnet_reference (sp, rv,
602 file, line) != ISC_R_SUCCESS)
603 return 0;
604 return 1;
607 return 0;
610 int subnet_inner_than (subnet, scan, warnp)
611 struct subnet *subnet, *scan;
612 int warnp;
614 if (addr_eq (subnet_number (subnet -> net, scan -> netmask),
615 scan -> net) ||
616 addr_eq (subnet_number (scan -> net, subnet -> netmask),
617 subnet -> net)) {
618 char n1buf [16];
619 int i, j;
620 for (i = 0; i < 32; i++)
621 if (subnet -> netmask.iabuf [3 - (i >> 3)]
622 & (1 << (i & 7)))
623 break;
624 for (j = 0; j < 32; j++)
625 if (scan -> netmask.iabuf [3 - (j >> 3)] &
626 (1 << (j & 7)))
627 break;
628 strcpy (n1buf, piaddr (subnet -> net));
629 if (warnp)
630 log_error ("%ssubnet %s/%d overlaps subnet %s/%d",
631 "Warning: ", n1buf, 32 - i,
632 piaddr (scan -> net), 32 - j);
633 if (i < j)
634 return 1;
636 return 0;
639 /* Enter a new subnet into the subnet list. */
640 void enter_subnet (subnet)
641 struct subnet *subnet;
643 struct subnet *scan = (struct subnet *)0;
644 struct subnet *next = (struct subnet *)0;
645 struct subnet *prev = (struct subnet *)0;
647 /* Check for duplicates... */
648 if (subnets)
649 subnet_reference (&next, subnets, MDL);
650 while (next) {
651 subnet_reference (&scan, next, MDL);
652 subnet_dereference (&next, MDL);
654 /* When we find a conflict, make sure that the
655 subnet with the narrowest subnet mask comes
656 first. */
657 if (subnet_inner_than (subnet, scan, 1)) {
658 if (prev) {
659 if (prev -> next_subnet)
660 subnet_dereference (&prev -> next_subnet, MDL);
661 subnet_reference (&prev -> next_subnet, subnet, MDL);
662 subnet_dereference (&prev, MDL);
663 } else {
664 subnet_dereference (&subnets, MDL);
665 subnet_reference (&subnets, subnet, MDL);
667 subnet_reference (&subnet -> next_subnet, scan, MDL);
668 subnet_dereference (&scan, MDL);
669 return;
671 subnet_reference (&prev, scan, MDL);
672 subnet_dereference (&scan, MDL);
674 if (prev)
675 subnet_dereference (&prev, MDL);
677 /* XXX use the BSD radix tree code instead of a linked list. */
678 if (subnets) {
679 subnet_reference (&subnet -> next_subnet, subnets, MDL);
680 subnet_dereference (&subnets, MDL);
682 subnet_reference (&subnets, subnet, MDL);
685 /* Enter a new shared network into the shared network list. */
687 void enter_shared_network (share)
688 struct shared_network *share;
690 if (shared_networks) {
691 shared_network_reference (&share -> next,
692 shared_networks, MDL);
693 shared_network_dereference (&shared_networks, MDL);
695 shared_network_reference (&shared_networks, share, MDL);
698 void new_shared_network_interface (cfile, share, name)
699 struct parse *cfile;
700 struct shared_network *share;
701 const char *name;
703 struct interface_info *ip;
704 isc_result_t status;
706 if (share -> interface) {
707 parse_warn (cfile,
708 "A subnet or shared network can't be connected %s",
709 "to two interfaces.");
710 return;
713 for (ip = interfaces; ip; ip = ip -> next)
714 if (!strcmp (ip -> name, name))
715 break;
716 if (!ip) {
717 status = interface_allocate (&ip, MDL);
718 if (status != ISC_R_SUCCESS)
719 log_fatal ("new_shared_network_interface %s: %s",
720 name, isc_result_totext (status));
721 if (strlen (name) > sizeof ip -> name) {
722 memcpy (ip -> name, name, (sizeof ip -> name) - 1);
723 ip -> name [(sizeof ip -> name) - 1] = 0;
724 } else
725 strcpy (ip -> name, name);
726 if (interfaces) {
727 interface_reference (&ip -> next, interfaces, MDL);
728 interface_dereference (&interfaces, MDL);
730 interface_reference (&interfaces, ip, MDL);
731 ip -> flags = INTERFACE_REQUESTED;
732 /* XXX this is a reference loop. */
733 shared_network_reference (&ip -> shared_network, share, MDL);
734 interface_reference (&share -> interface, ip, MDL);
738 /* Enter a lease into the system. This is called by the parser each
739 time it reads in a new lease. If the subnet for that lease has
740 already been read in (usually the case), just update that lease;
741 otherwise, allocate temporary storage for the lease and keep it around
742 until we're done reading in the config file. */
744 void enter_lease (lease)
745 struct lease *lease;
747 struct lease *comp = (struct lease *)0;
748 isc_result_t status;
750 if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
751 if (!comp -> pool) {
752 log_error ("undeclared lease found in database: %s",
753 piaddr (lease -> ip_addr));
754 } else
755 pool_reference (&lease -> pool, comp -> pool, MDL);
757 if (comp -> subnet)
758 subnet_reference (&lease -> subnet,
759 comp -> subnet, MDL);
760 lease_hash_delete (lease_ip_addr_hash,
761 lease -> ip_addr.iabuf,
762 lease -> ip_addr.len, MDL);
763 lease_dereference (&comp, MDL);
766 /* The only way a lease can get here without a subnet is if it's in
767 the lease file, but not in the dhcpd.conf file. In this case, we
768 *should* keep it around until it's expired, but never reallocate it
769 or renew it. Currently, to maintain consistency, we are not doing
770 this.
771 XXX fix this so that the lease is kept around until it expires.
772 XXX this will be important in IPv6 with addresses that become
773 XXX non-renewable as a result of a renumbering event. */
775 if (!lease -> subnet) {
776 log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
777 return;
779 lease_hash_add (lease_ip_addr_hash,
780 lease -> ip_addr.iabuf,
781 lease -> ip_addr.len, lease, MDL);
784 /* Replace the data in an existing lease with the data in a new lease;
785 adjust hash tables to suit, and insertion sort the lease into the
786 list of leases by expiry time so that we can always find the oldest
787 lease. */
789 int supersede_lease (comp, lease, commit, propogate, pimmediate)
790 struct lease *comp, *lease;
791 int commit;
792 int propogate;
793 int pimmediate;
795 int enter_uid = 0;
796 int enter_hwaddr = 0;
797 struct lease *lp, **lq, *prev;
798 TIME lp_next_state;
800 #if defined (FAILOVER_PROTOCOL)
801 /* We must commit leases before sending updates regarding them
802 to failover peers. It is, therefore, an error to set pimmediate
803 and not commit. */
804 if (pimmediate && !commit)
805 return 0;
806 #endif
808 /* If there is no sample lease, just do the move. */
809 if (!lease)
810 goto just_move_it;
812 /* Static leases are not currently kept in the database... */
813 if (lease -> flags & STATIC_LEASE)
814 return 1;
816 /* If the existing lease hasn't expired and has a different
817 unique identifier or, if it doesn't have a unique
818 identifier, a different hardware address, then the two
819 leases are in conflict. If the existing lease has a uid
820 and the new one doesn't, but they both have the same
821 hardware address, and dynamic bootp is allowed on this
822 lease, then we allow that, in case a dynamic BOOTP lease is
823 requested *after* a DHCP lease has been assigned. */
825 if (lease -> binding_state != FTS_ABANDONED &&
826 lease -> next_binding_state != FTS_ABANDONED &&
827 comp -> binding_state == FTS_ACTIVE &&
828 (((comp -> uid && lease -> uid) &&
829 (comp -> uid_len != lease -> uid_len ||
830 memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
831 (!comp -> uid &&
832 ((comp -> hardware_addr.hlen !=
833 lease -> hardware_addr.hlen) ||
834 memcmp (comp -> hardware_addr.hbuf,
835 lease -> hardware_addr.hbuf,
836 comp -> hardware_addr.hlen))))) {
837 log_error ("Lease conflict at %s",
838 piaddr (comp -> ip_addr));
841 /* If there's a Unique ID, dissociate it from the hash
842 table and free it if necessary. */
843 if (comp -> uid) {
844 uid_hash_delete (comp);
845 enter_uid = 1;
846 if (comp -> uid != &comp -> uid_buf [0]) {
847 dfree (comp -> uid, MDL);
848 comp -> uid_max = 0;
849 comp -> uid_len = 0;
851 comp -> uid = (unsigned char *)0;
852 } else
853 enter_uid = 1;
855 if (comp -> hardware_addr.hlen &&
856 ((comp -> hardware_addr.hlen !=
857 lease -> hardware_addr.hlen) ||
858 memcmp (comp -> hardware_addr.hbuf,
859 lease -> hardware_addr.hbuf,
860 comp -> hardware_addr.hlen))) {
861 hw_hash_delete (comp);
862 enter_hwaddr = 1;
863 } else if (!comp -> hardware_addr.hlen)
864 enter_hwaddr = 1;
866 /* If the lease has been billed to a class, remove the billing. */
867 if (comp -> billing_class != lease -> billing_class) {
868 if (comp -> billing_class)
869 unbill_class (comp, comp -> billing_class);
870 if (lease -> billing_class)
871 bill_class (comp, lease -> billing_class);
874 /* Copy the data files, but not the linkages. */
875 comp -> starts = lease -> starts;
876 if (lease -> uid) {
877 if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
878 memcpy (comp -> uid_buf,
879 lease -> uid, lease -> uid_len);
880 comp -> uid = &comp -> uid_buf [0];
881 comp -> uid_max = sizeof comp -> uid_buf;
882 comp -> uid_len = lease -> uid_len;
883 } else if (lease -> uid != &lease -> uid_buf [0]) {
884 comp -> uid = lease -> uid;
885 comp -> uid_max = lease -> uid_max;
886 lease -> uid = (unsigned char *)0;
887 lease -> uid_max = 0;
888 comp -> uid_len = lease -> uid_len;
889 lease -> uid_len = 0;
890 } else {
891 log_fatal ("corrupt lease uid."); /* XXX */
893 } else {
894 comp -> uid = (unsigned char *)0;
895 comp -> uid_len = comp -> uid_max = 0;
897 if (comp -> host)
898 host_dereference (&comp -> host, MDL);
899 host_reference (&comp -> host, lease -> host, MDL);
900 comp -> hardware_addr = lease -> hardware_addr;
901 comp -> flags = ((lease -> flags & ~PERSISTENT_FLAGS) |
902 (comp -> flags & ~EPHEMERAL_FLAGS));
903 if (comp -> scope)
904 binding_scope_dereference (&comp -> scope, MDL);
905 if (lease -> scope) {
906 binding_scope_reference (&comp -> scope, lease -> scope, MDL);
907 binding_scope_dereference (&lease -> scope, MDL);
910 if (comp -> agent_options)
911 option_chain_head_dereference (&comp -> agent_options, MDL);
912 if (lease -> agent_options) {
913 /* Only retain the agent options if the lease is still
914 affirmatively associated with a client. */
915 if (lease -> next_binding_state == FTS_ACTIVE ||
916 lease -> next_binding_state == FTS_EXPIRED)
917 option_chain_head_reference (&comp -> agent_options,
918 lease -> agent_options,
919 MDL);
920 option_chain_head_dereference (&lease -> agent_options, MDL);
923 /* Record the hostname information in the lease. */
924 if (comp -> client_hostname)
925 dfree (comp -> client_hostname, MDL);
926 comp -> client_hostname = lease -> client_hostname;
927 lease -> client_hostname = (char *)0;
929 if (lease -> on_expiry) {
930 if (comp -> on_expiry)
931 executable_statement_dereference (&comp -> on_expiry,
932 MDL);
933 executable_statement_reference (&comp -> on_expiry,
934 lease -> on_expiry,
935 MDL);
937 if (lease -> on_commit) {
938 if (comp -> on_commit)
939 executable_statement_dereference (&comp -> on_commit,
940 MDL);
941 executable_statement_reference (&comp -> on_commit,
942 lease -> on_commit,
943 MDL);
945 if (lease -> on_release) {
946 if (comp -> on_release)
947 executable_statement_dereference (&comp -> on_release,
948 MDL);
949 executable_statement_reference (&comp -> on_release,
950 lease -> on_release, MDL);
953 /* Record the lease in the uid hash if necessary. */
954 if (enter_uid && comp -> uid) {
955 uid_hash_add (comp);
958 /* Record it in the hardware address hash if necessary. */
959 if (enter_hwaddr && lease -> hardware_addr.hlen) {
960 hw_hash_add (comp);
963 #if defined (FAILOVER_PROTOCOL)
964 comp -> cltt = lease -> cltt;
965 comp -> tstp = lease -> tstp;
966 comp -> tsfp = lease -> tsfp;
967 #endif /* FAILOVER_PROTOCOL */
968 comp -> ends = lease -> ends;
969 comp -> next_binding_state = lease -> next_binding_state;
971 just_move_it:
972 if (!comp -> pool) {
973 log_error ("Supersede_lease: lease %s with no pool.",
974 piaddr (comp -> ip_addr));
975 return 0;
978 /* Figure out which queue it's on. */
979 switch (comp -> binding_state) {
980 case FTS_FREE:
981 lq = &comp -> pool -> free;
982 comp -> pool -> free_leases--;
983 break;
985 case FTS_ACTIVE:
986 lq = &comp -> pool -> active;
987 break;
989 case FTS_EXPIRED:
990 case FTS_RELEASED:
991 case FTS_RESET:
992 lq = &comp -> pool -> expired;
993 break;
995 case FTS_ABANDONED:
996 lq = &comp -> pool -> abandoned;
997 break;
999 case FTS_BACKUP:
1000 lq = &comp -> pool -> backup;
1001 comp -> pool -> backup_leases--;
1002 break;
1004 default:
1005 log_error ("Lease with bogus binding state: %d",
1006 comp -> binding_state);
1007 #if defined (BINDING_STATE_DEBUG)
1008 abort ();
1009 #endif
1010 return 0;
1013 /* Remove the lease from its current place in its current
1014 timer sequence. */
1015 prev = (struct lease *)0;
1016 for (lp = *lq; lp; lp = lp -> next) {
1017 if (lp == comp)
1018 break;
1019 prev = lp;
1022 if (!lp) {
1023 log_error ("Lease with binding state %s not on its queue.",
1024 (comp -> binding_state < 1 ||
1025 comp -> binding_state > FTS_LAST)
1026 ? "unknown"
1027 : binding_state_names [comp -> binding_state - 1]);
1028 return 0;
1031 if (prev) {
1032 lease_dereference (&prev -> next, MDL);
1033 if (comp -> next) {
1034 lease_reference (&prev -> next, comp -> next, MDL);
1035 lease_dereference (&comp -> next, MDL);
1037 } else {
1038 lease_dereference (lq, MDL);
1039 if (comp -> next) {
1040 lease_reference (lq, comp -> next, MDL);
1041 lease_dereference (&comp -> next, MDL);
1045 /* Make the state transition. */
1046 if (commit || !pimmediate)
1047 make_binding_state_transition (comp);
1049 /* Put the lease back on the appropriate queue. If the lease
1050 is corrupt (as detected by lease_enqueue), don't go any farther. */
1051 if (!lease_enqueue (comp))
1052 return 0;
1054 /* If this is the next lease that will timeout on the pool,
1055 zap the old timeout and set the timeout on this pool to the
1056 time that the lease's next event will happen.
1058 We do not actually set the timeout unless commit is true -
1059 we don't want to thrash the timer queue when reading the
1060 lease database. Instead, the database code calls the
1061 expiry event on each pool after reading in the lease file,
1062 and the expiry code sets the timer if there's anything left
1063 to expire after it's run any outstanding expiry events on
1064 the pool. */
1065 if ((commit || !pimmediate) &&
1066 comp -> sort_time != MIN_TIME &&
1067 comp -> sort_time > cur_time &&
1068 (comp -> sort_time < comp -> pool -> next_event_time ||
1069 comp -> pool -> next_event_time == MIN_TIME)) {
1070 comp -> pool -> next_event_time = comp -> sort_time;
1071 add_timeout (comp -> pool -> next_event_time,
1072 pool_timer, comp -> pool,
1073 (tvref_t)pool_reference,
1074 (tvunref_t)pool_dereference);
1077 if (commit) {
1078 if (!write_lease (comp))
1079 return 0;
1080 if (!commit_leases ())
1081 return 0;
1084 #if defined (FAILOVER_PROTOCOL)
1085 if (propogate) {
1086 comp -> desired_binding_state = comp -> binding_state;
1087 if (!dhcp_failover_queue_update (comp, pimmediate))
1088 return 0;
1090 #endif
1092 /* If the current binding state has already expired, do an
1093 expiry event right now. */
1094 /* XXX At some point we should optimize this so that we don't
1095 XXX write the lease twice, but this is a safe way to fix the
1096 XXX problem for 3.0 (I hope!). */
1097 if ((commit || !pimmediate) &&
1098 comp -> sort_time < cur_time &&
1099 comp -> next_binding_state != comp -> binding_state)
1100 pool_timer (comp -> pool);
1102 return 1;
1105 void make_binding_state_transition (struct lease *lease)
1107 #if defined (FAILOVER_PROTOCOL)
1108 dhcp_failover_state_t *peer;
1110 if (lease && lease -> pool && lease -> pool -> failover_peer)
1111 peer = lease -> pool -> failover_peer;
1112 else
1113 peer = (dhcp_failover_state_t *)0;
1114 #endif
1116 /* If the lease was active and is now no longer active, but isn't
1117 released, then it just expired, so do the expiry event. */
1118 if (lease -> next_binding_state != lease -> binding_state &&
1120 #if defined (FAILOVER_PROTOCOL)
1121 peer &&
1122 (lease -> binding_state == FTS_EXPIRED ||
1123 (peer -> i_am == secondary &&
1124 lease -> binding_state == FTS_ACTIVE)) &&
1125 (lease -> next_binding_state == FTS_FREE ||
1126 lease -> next_binding_state == FTS_BACKUP)) ||
1127 (!peer &&
1128 #endif
1129 lease -> binding_state == FTS_ACTIVE &&
1130 lease -> next_binding_state != FTS_RELEASED))) {
1131 #if defined (NSUPDATE)
1132 ddns_removals (lease);
1133 #endif
1134 if (lease -> on_expiry) {
1135 execute_statements ((struct binding_value **)0,
1136 (struct packet *)0, lease,
1137 (struct client_state *)0,
1138 (struct option_state *)0,
1139 (struct option_state *)0, /* XXX */
1140 &lease -> scope,
1141 lease -> on_expiry);
1142 if (lease -> on_expiry)
1143 executable_statement_dereference
1144 (&lease -> on_expiry, MDL);
1147 /* No sense releasing a lease after it's expired. */
1148 if (lease -> on_release)
1149 executable_statement_dereference (&lease -> on_release,
1150 MDL);
1151 /* Get rid of client-specific bindings that are only
1152 correct when the lease is active. */
1153 if (lease -> billing_class)
1154 unbill_class (lease, lease -> billing_class);
1155 if (lease -> agent_options)
1156 option_chain_head_dereference (&lease -> agent_options,
1157 MDL);
1158 if (lease -> client_hostname) {
1159 dfree (lease -> client_hostname, MDL);
1160 lease -> client_hostname = (char *)0;
1162 if (lease -> host)
1163 host_dereference (&lease -> host, MDL);
1165 /* Send the expiry time to the peer. */
1166 lease -> tstp = lease -> ends;
1169 /* If the lease was active and is now released, do the release
1170 event. */
1171 if (lease -> next_binding_state != lease -> binding_state &&
1173 #if defined (FAILOVER_PROTOCOL)
1174 peer &&
1175 lease -> binding_state == FTS_RELEASED &&
1176 (lease -> next_binding_state == FTS_FREE ||
1177 lease -> next_binding_state == FTS_BACKUP)) ||
1178 (!peer &&
1179 #endif
1180 lease -> binding_state == FTS_ACTIVE &&
1181 lease -> next_binding_state == FTS_RELEASED))) {
1182 #if defined (NSUPDATE)
1183 ddns_removals (lease);
1184 #endif
1185 if (lease -> on_release) {
1186 execute_statements ((struct binding_value **)0,
1187 (struct packet *)0, lease,
1188 (struct client_state *)0,
1189 (struct option_state *)0,
1190 (struct option_state *)0, /* XXX */
1191 &lease -> scope,
1192 lease -> on_release);
1193 executable_statement_dereference (&lease -> on_release,
1194 MDL);
1197 /* A released lease can't expire. */
1198 if (lease -> on_expiry)
1199 executable_statement_dereference (&lease -> on_expiry,
1200 MDL);
1202 /* Get rid of client-specific bindings that are only
1203 correct when the lease is active. */
1204 if (lease -> billing_class)
1205 unbill_class (lease, lease -> billing_class);
1206 if (lease -> agent_options)
1207 option_chain_head_dereference (&lease -> agent_options,
1208 MDL);
1209 if (lease -> client_hostname) {
1210 dfree (lease -> client_hostname, MDL);
1211 lease -> client_hostname = (char *)0;
1213 if (lease -> host)
1214 host_dereference (&lease -> host, MDL);
1216 /* Send the release time (should be == cur_time) to the
1217 peer. */
1218 lease -> tstp = lease -> ends;
1221 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1222 log_debug ("lease %s moves from %s to %s",
1223 piaddr (lease -> ip_addr),
1224 binding_state_print (lease -> binding_state),
1225 binding_state_print (lease -> next_binding_state));
1226 #endif
1228 lease -> binding_state = lease -> next_binding_state;
1229 switch (lease -> binding_state) {
1230 case FTS_ACTIVE:
1231 #if defined (FAILOVER_PROTOCOL)
1232 if (lease -> pool && lease -> pool -> failover_peer)
1233 lease -> next_binding_state = FTS_EXPIRED;
1234 else
1235 #endif
1236 lease -> next_binding_state = FTS_FREE;
1237 break;
1239 case FTS_EXPIRED:
1240 case FTS_RELEASED:
1241 case FTS_ABANDONED:
1242 case FTS_RESET:
1243 lease -> next_binding_state = FTS_FREE;
1244 /* If we are not in partner_down, leases don't go from
1245 EXPIRED to FREE on a timeout - only on an update.
1246 If we're in partner_down, they expire at mclt past
1247 the time we entered partner_down. */
1248 if (lease -> pool -> failover_peer &&
1249 lease -> pool -> failover_peer -> me.state == partner_down)
1250 lease -> tsfp =
1251 (lease -> pool -> failover_peer -> me.stos +
1252 lease -> pool -> failover_peer -> mclt);
1253 break;
1255 case FTS_FREE:
1256 case FTS_BACKUP:
1257 lease -> next_binding_state = lease -> binding_state;
1258 break;
1260 #if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1261 log_debug ("lease %s: next binding state %s",
1262 piaddr (lease -> ip_addr),
1263 binding_state_print (lease -> next_binding_state));
1264 #endif
1268 /* Copy the contents of one lease into another, correctly maintaining
1269 reference counts. */
1270 int lease_copy (struct lease **lp,
1271 struct lease *lease, const char *file, int line)
1273 struct lease *lt = (struct lease *)0;
1274 isc_result_t status;
1276 status = lease_allocate (&lt, MDL);
1277 if (status != ISC_R_SUCCESS)
1278 return 0;
1280 lt -> ip_addr = lease -> ip_addr;
1281 lt -> starts = lease -> starts;
1282 lt -> ends = lease -> ends;
1283 lt -> timestamp = lease -> timestamp;
1284 lt -> uid_len = lease -> uid_len;
1285 lt -> uid_max = lease -> uid_max;
1286 if (lease -> uid == lease -> uid_buf) {
1287 lt -> uid = lt -> uid_buf;
1288 memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1289 } else if (!lease -> uid_max) {
1290 lt -> uid = (unsigned char *)0;
1291 } else {
1292 lt -> uid = dmalloc (lt -> uid_max, MDL);
1293 if (!lt -> uid) {
1294 lease_dereference (&lt, MDL);
1295 return 0;
1297 memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1299 if (lease -> client_hostname) {
1300 lt -> client_hostname =
1301 dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1302 if (!lt -> client_hostname) {
1303 lease_dereference (&lt, MDL);
1304 return 0;
1306 strcpy (lt -> client_hostname, lease -> client_hostname);
1308 if (lease -> scope)
1309 binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1310 if (lease -> agent_options)
1311 option_chain_head_reference (&lt -> agent_options,
1312 lease -> agent_options, MDL);
1313 host_reference (&lt -> host, lease -> host, file, line);
1314 subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1315 pool_reference (&lt -> pool, lease -> pool, file, line);
1316 class_reference (&lt -> billing_class,
1317 lease -> billing_class, file, line);
1318 lt -> hardware_addr = lease -> hardware_addr;
1319 if (lease -> on_expiry)
1320 executable_statement_reference (&lt -> on_expiry,
1321 lease -> on_expiry,
1322 file, line);
1323 if (lease -> on_commit)
1324 executable_statement_reference (&lt -> on_commit,
1325 lease -> on_commit,
1326 file, line);
1327 if (lease -> on_release)
1328 executable_statement_reference (&lt -> on_release,
1329 lease -> on_release,
1330 file, line);
1331 lt -> flags = lease -> flags;
1332 lt -> tstp = lease -> tstp;
1333 lt -> tsfp = lease -> tsfp;
1334 lt -> cltt = lease -> cltt;
1335 lt -> binding_state = lease -> binding_state;
1336 lt -> next_binding_state = lease -> next_binding_state;
1337 status = lease_reference (lp, lt, file, line);
1338 lease_dereference (&lt, MDL);
1339 return status == ISC_R_SUCCESS;
1342 /* Release the specified lease and re-hash it as appropriate. */
1343 void release_lease (lease, packet)
1344 struct lease *lease;
1345 struct packet *packet;
1347 /* If there are statements to execute when the lease is
1348 released, execute them. */
1349 #if defined (NSUPDATE)
1350 ddns_removals (lease);
1351 #endif
1352 if (lease -> on_release) {
1353 execute_statements ((struct binding_value **)0,
1354 packet, lease, (struct client_state *)0,
1355 packet -> options,
1356 (struct option_state *)0, /* XXX */
1357 &lease -> scope, lease -> on_release);
1358 if (lease -> on_release)
1359 executable_statement_dereference (&lease -> on_release,
1360 MDL);
1363 /* We do either the on_release or the on_expiry events, but
1364 not both (it's possible that they could be the same,
1365 in any case). */
1366 if (lease -> on_expiry)
1367 executable_statement_dereference (&lease -> on_expiry, MDL);
1369 if (lease -> binding_state != FTS_FREE &&
1370 lease -> binding_state != FTS_BACKUP &&
1371 lease -> binding_state != FTS_RELEASED &&
1372 lease -> binding_state != FTS_EXPIRED &&
1373 lease -> binding_state != FTS_RESET) {
1374 if (lease -> on_commit)
1375 executable_statement_dereference (&lease -> on_commit,
1376 MDL);
1378 /* Blow away any bindings. */
1379 if (lease -> scope)
1380 binding_scope_dereference (&lease -> scope, MDL);
1381 lease -> ends = cur_time;
1382 #if defined (FAILOVER_PROTOCOL)
1383 if (lease -> pool && lease -> pool -> failover_peer) {
1384 lease -> next_binding_state = FTS_RELEASED;
1385 } else {
1386 lease -> next_binding_state = FTS_FREE;
1388 #else
1389 lease -> next_binding_state = FTS_FREE;
1390 #endif
1391 supersede_lease (lease, (struct lease *)0, 1, 1, 1);
1395 /* Abandon the specified lease (set its timeout to infinity and its
1396 particulars to zero, and re-hash it as appropriate. */
1398 void abandon_lease (lease, message)
1399 struct lease *lease;
1400 const char *message;
1402 struct lease *lt = (struct lease *)0;
1404 if (!lease_copy (&lt, lease, MDL))
1405 return;
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 *lt = (struct lease *)0;
1459 struct lease *next = (struct lease *)0;
1460 struct lease *lease = (struct lease *)0;
1461 struct lease **lptr [5];
1462 TIME next_expiry = MAX_TIME;
1463 int i;
1465 pool = (struct pool *)vpool;
1467 #define FREE_LEASES 0
1468 lptr [FREE_LEASES] = &pool -> free;
1469 #define ACTIVE_LEASES 1
1470 lptr [ACTIVE_LEASES] = &pool -> active;
1471 #define EXPIRED_LEASES 2
1472 lptr [EXPIRED_LEASES] = &pool -> expired;
1473 #define ABANDONED_LEASES 3
1474 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1475 #define BACKUP_LEASES 4
1476 lptr [BACKUP_LEASES] = &pool -> backup;
1478 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1479 /* If there's nothing on the queue, skip it. */
1480 if (!*(lptr [i]))
1481 continue;
1483 #if defined (FAILOVER_PROTOCOL)
1484 if (pool -> failover_peer &&
1485 pool -> failover_peer -> me.state != partner_down) {
1486 /* The secondary can't remove a lease from the
1487 active state except in partner_down. */
1488 if (i == ACTIVE_LEASES &&
1489 pool -> failover_peer -> i_am == secondary)
1490 continue;
1491 /* Leases in an expired state don't move to
1492 free because of a timeout unless we're in
1493 partner_down. */
1494 if (i == EXPIRED_LEASES)
1495 continue;
1497 #endif
1498 lease_reference (&lease, *(lptr [i]), MDL);
1500 while (lease) {
1501 /* Remember the next lease in the list. */
1502 if (next)
1503 lease_dereference (&next, MDL);
1504 if (lease -> next)
1505 lease_reference (&next, lease -> next, MDL);
1507 /* If we've run out of things to expire on this list,
1508 stop. */
1509 if (lease -> sort_time > cur_time) {
1510 if (lease -> sort_time < next_expiry)
1511 next_expiry = lease -> sort_time;
1512 break;
1515 /* If there is a pending state change, and
1516 this lease has gotten to the time when the
1517 state change should happen, just call
1518 supersede_lease on it to make the change
1519 happen. */
1520 if (lease -> next_binding_state !=
1521 lease -> binding_state)
1522 supersede_lease (lease,
1523 (struct lease *)0, 1, 1, 1);
1525 lease_dereference (&lease, MDL);
1526 if (next)
1527 lease_reference (&lease, next, MDL);
1529 if (next)
1530 lease_dereference (&next, MDL);
1531 if (lease)
1532 lease_dereference (&lease, MDL);
1534 if (next_expiry != MAX_TIME) {
1535 pool -> next_event_time = next_expiry;
1536 add_timeout (pool -> next_event_time, pool_timer, pool,
1537 (tvref_t)pool_reference,
1538 (tvunref_t)pool_dereference);
1539 } else
1540 pool -> next_event_time = MIN_TIME;
1544 /* Locate the lease associated with a given IP address... */
1546 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1547 const char *file, int line)
1549 return lease_hash_lookup (lp, lease_ip_addr_hash,
1550 addr.iabuf, addr.len, file, line);
1553 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1554 unsigned len, const char *file, int line)
1556 if (len == 0)
1557 return 0;
1558 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1561 int find_lease_by_hw_addr (struct lease **lp,
1562 const unsigned char *hwaddr, unsigned hwlen,
1563 const char *file, int line)
1565 if (hwlen == 0)
1566 return 0;
1567 return lease_hash_lookup (lp, lease_hw_addr_hash,
1568 hwaddr, hwlen, file, line);
1571 /* Add the specified lease to the uid hash. */
1573 void uid_hash_add (lease)
1574 struct lease *lease;
1576 struct lease *head = (struct lease *)0;
1577 struct lease *next = (struct lease *)0;
1580 /* If it's not in the hash, just add it. */
1581 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1582 lease_hash_add (lease_uid_hash, lease -> uid,
1583 lease -> uid_len, lease, MDL);
1584 else {
1585 /* Otherwise, attach it to the end of the list. */
1586 while (head -> n_uid) {
1587 lease_reference (&next, head -> n_uid, MDL);
1588 lease_dereference (&head, MDL);
1589 lease_reference (&head, next, MDL);
1590 lease_dereference (&next, MDL);
1592 lease_reference (&head -> n_uid, lease, MDL);
1593 lease_dereference (&head, MDL);
1597 /* Delete the specified lease from the uid hash. */
1599 void uid_hash_delete (lease)
1600 struct lease *lease;
1602 struct lease *head = (struct lease *)0;
1603 struct lease *scan;
1605 /* If it's not in the hash, we have no work to do. */
1606 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1607 if (lease -> n_uid)
1608 lease_dereference (&lease -> n_uid, MDL);
1609 return;
1612 /* If the lease we're freeing is at the head of the list,
1613 remove the hash table entry and add a new one with the
1614 next lease on the list (if there is one). */
1615 if (head == lease) {
1616 lease_hash_delete (lease_uid_hash,
1617 lease -> uid, lease -> uid_len, MDL);
1618 if (lease -> n_uid) {
1619 lease_hash_add (lease_uid_hash,
1620 lease -> n_uid -> uid,
1621 lease -> n_uid -> uid_len,
1622 lease -> n_uid, MDL);
1623 lease_dereference (&lease -> n_uid, MDL);
1625 } else {
1626 /* Otherwise, look for the lease in the list of leases
1627 attached to the hash table entry, and remove it if
1628 we find it. */
1629 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1630 if (scan -> n_uid == lease) {
1631 lease_dereference (&scan -> n_uid, MDL);
1632 if (lease -> n_uid) {
1633 lease_reference (&scan -> n_uid,
1634 lease -> n_uid, MDL);
1635 lease_dereference (&lease -> n_uid,
1636 MDL);
1638 break;
1642 lease_dereference (&head, MDL);
1645 /* Add the specified lease to the hardware address hash. */
1647 void hw_hash_add (lease)
1648 struct lease *lease;
1650 struct lease *head = (struct lease *)0;
1651 struct lease *next = (struct lease *)0;
1653 /* If it's not in the hash, just add it. */
1654 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1655 lease -> hardware_addr.hlen, MDL))
1656 lease_hash_add (lease_hw_addr_hash,
1657 lease -> hardware_addr.hbuf,
1658 lease -> hardware_addr.hlen,
1659 lease, MDL);
1660 else {
1661 /* Otherwise, attach it to the end of the list. */
1662 while (head -> n_hw) {
1663 lease_reference (&next, head -> n_hw, MDL);
1664 lease_dereference (&head, MDL);
1665 lease_reference (&head, next, MDL);
1666 lease_dereference (&next, MDL);
1669 lease_reference (&head -> n_hw, lease, MDL);
1670 lease_dereference (&head, MDL);
1674 /* Delete the specified lease from the hardware address hash. */
1676 void hw_hash_delete (lease)
1677 struct lease *lease;
1679 struct lease *head = (struct lease *)0;
1680 struct lease *next = (struct lease *)0;
1682 /* If it's not in the hash, we have no work to do. */
1683 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1684 lease -> hardware_addr.hlen, MDL)) {
1685 if (lease -> n_hw)
1686 lease_dereference (&lease -> n_hw, MDL);
1687 return;
1690 /* If the lease we're freeing is at the head of the list,
1691 remove the hash table entry and add a new one with the
1692 next lease on the list (if there is one). */
1693 if (head == lease) {
1694 lease_hash_delete (lease_hw_addr_hash,
1695 lease -> hardware_addr.hbuf,
1696 lease -> hardware_addr.hlen, MDL);
1697 if (lease -> n_hw) {
1698 lease_hash_add (lease_hw_addr_hash,
1699 lease -> n_hw -> hardware_addr.hbuf,
1700 lease -> n_hw -> hardware_addr.hlen,
1701 lease -> n_hw, MDL);
1702 lease_dereference (&lease -> n_hw, MDL);
1704 } else {
1705 /* Otherwise, look for the lease in the list of leases
1706 attached to the hash table entry, and remove it if
1707 we find it. */
1708 while (head -> n_hw) {
1709 if (head -> n_hw == lease) {
1710 lease_dereference (&head -> n_hw, MDL);
1711 if (lease -> n_hw) {
1712 lease_reference (&head -> n_hw,
1713 lease -> n_hw, MDL);
1714 lease_dereference (&lease -> n_hw,
1715 MDL);
1717 break;
1719 lease_reference (&next, head -> n_hw, MDL);
1720 lease_dereference (&head, MDL);
1721 lease_reference (&head, next, MDL);
1722 lease_dereference (&next, MDL);
1725 if (head)
1726 lease_dereference (&head, MDL);
1729 /* Write all interesting leases to permanent storage. */
1731 int write_leases ()
1733 struct lease *l;
1734 struct shared_network *s;
1735 struct pool *p;
1736 struct host_decl *hp;
1737 struct group_object *gp;
1738 struct hash_bucket *hb;
1739 int i;
1740 int num_written;
1741 struct lease **lptr [5];
1743 /* Write all the dynamically-created group declarations. */
1744 if (group_name_hash) {
1745 num_written = 0;
1746 for (i = 0; i < group_name_hash -> hash_count; i++) {
1747 for (hb = group_name_hash -> buckets [i];
1748 hb; hb = hb -> next) {
1749 gp = (struct group_object *)hb -> value;
1750 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1751 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1752 (gp -> flags & GROUP_OBJECT_DELETED))) {
1753 if (!write_group (gp))
1754 return 0;
1755 ++num_written;
1759 log_info ("Wrote %d group decls to leases file.", num_written);
1762 /* Write all the deleted host declarations. */
1763 if (host_name_hash) {
1764 num_written = 0;
1765 for (i = 0; i < host_name_hash -> hash_count; i++) {
1766 for (hb = host_name_hash -> buckets [i];
1767 hb; hb = hb -> next) {
1768 hp = (struct host_decl *)hb -> value;
1769 if (((hp -> flags & HOST_DECL_STATIC) &&
1770 (hp -> flags & HOST_DECL_DELETED))) {
1771 if (!write_host (hp))
1772 return 0;
1773 ++num_written;
1777 log_info ("Wrote %d deleted host decls to leases file.",
1778 num_written);
1781 /* Write all the new, dynamic host declarations. */
1782 if (host_name_hash) {
1783 num_written = 0;
1784 for (i = 0; i < host_name_hash -> hash_count; i++) {
1785 for (hb = host_name_hash -> buckets [i];
1786 hb; hb = hb -> next) {
1787 hp = (struct host_decl *)hb -> value;
1788 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1789 if (!write_host (hp))
1790 ++num_written;
1794 log_info ("Wrote %d new dynamic host decls to leases file.",
1795 num_written);
1798 #if defined (FAILOVER_PROTOCOL)
1799 /* Write all the failover states. */
1800 if (!dhcp_failover_write_all_states ())
1801 return 0;
1802 #endif
1804 /* Write all the leases. */
1805 num_written = 0;
1806 for (s = shared_networks; s; s = s -> next) {
1807 for (p = s -> pools; p; p = p -> next) {
1808 lptr [FREE_LEASES] = &p -> free;
1809 lptr [ACTIVE_LEASES] = &p -> active;
1810 lptr [EXPIRED_LEASES] = &p -> expired;
1811 lptr [ABANDONED_LEASES] = &p -> abandoned;
1812 lptr [BACKUP_LEASES] = &p -> backup;
1814 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1815 for (l = *(lptr [i]); l; l = l -> next) {
1816 #if !defined (DEBUG_DUMP_ALL_LEASES)
1817 if (l -> hardware_addr.hlen ||
1818 l -> uid_len ||
1819 (l -> binding_state != FTS_FREE))
1820 #endif
1822 if (!write_lease (l))
1823 return 0;
1824 num_written++;
1830 log_info ("Wrote %d leases to leases file.", num_written);
1831 if (!commit_leases ())
1832 return 0;
1833 return 1;
1836 int lease_enqueue (struct lease *comp)
1838 struct lease **lq, *prev, *lp;
1840 /* No queue to put it on? */
1841 if (!comp -> pool)
1842 return 0;
1844 /* Figure out which queue it's going to. */
1845 switch (comp -> binding_state) {
1846 case FTS_FREE:
1847 lq = &comp -> pool -> free;
1848 comp -> pool -> free_leases++;
1849 comp -> sort_time = comp -> ends;
1850 break;
1852 case FTS_ACTIVE:
1853 lq = &comp -> pool -> active;
1854 comp -> sort_time = comp -> ends;
1855 break;
1857 case FTS_EXPIRED:
1858 case FTS_RELEASED:
1859 case FTS_RESET:
1860 lq = &comp -> pool -> expired;
1861 comp -> sort_time = comp -> ends;
1863 break;
1865 case FTS_ABANDONED:
1866 lq = &comp -> pool -> abandoned;
1867 comp -> sort_time = comp -> ends;
1868 break;
1870 case FTS_BACKUP:
1871 lq = &comp -> pool -> backup;
1872 comp -> pool -> backup_leases++;
1873 comp -> sort_time = comp -> ends;
1874 break;
1876 default:
1877 log_error ("Lease with bogus binding state: %d",
1878 comp -> binding_state);
1879 #if defined (BINDING_STATE_DEBUG)
1880 abort ();
1881 #endif
1882 return 0;
1885 /* Insertion sort the lease onto the appropriate queue. */
1886 prev = (struct lease *)0;
1887 for (lp = *lq; lp; lp = lp -> next) {
1888 if (lp -> sort_time >= comp -> sort_time)
1889 break;
1890 prev = lp;
1892 if (prev) {
1893 if (prev -> next) {
1894 lease_reference (&comp -> next, prev -> next, MDL);
1895 lease_dereference (&prev -> next, MDL);
1897 lease_reference (&prev -> next, comp, MDL);
1898 } else {
1899 if (*lq) {
1900 lease_reference (&comp -> next, *lq, MDL);
1901 lease_dereference (lq, MDL);
1903 lease_reference (lq, comp, MDL);
1905 return 1;
1908 /* For a given lease, sort it onto the right list in its pool and put it
1909 in each appropriate hash, understanding that it's already by definition
1910 in lease_ip_addr_hash. */
1912 void lease_instantiate (const unsigned char *val, unsigned len,
1913 struct lease *lease)
1915 struct class *class;
1916 /* XXX If the lease doesn't have a pool at this point, it's an
1917 XXX orphan, which we *should* keep around until it expires,
1918 XXX but which right now we just forget. */
1919 if (!lease -> pool) {
1920 lease_hash_delete (lease_ip_addr_hash,
1921 lease -> ip_addr.iabuf,
1922 lease -> ip_addr.len, MDL);
1923 return;
1926 /* Put the lease on the right queue. */
1927 lease_enqueue (lease);
1929 /* Record the lease in the uid hash if possible. */
1930 if (lease -> uid) {
1931 uid_hash_add (lease);
1934 /* Record it in the hardware address hash if possible. */
1935 if (lease -> hardware_addr.hlen) {
1936 hw_hash_add (lease);
1939 /* If the lease has a billing class, set up the billing. */
1940 if (lease -> billing_class) {
1941 class = (struct class *)0;
1942 class_reference (&class, lease -> billing_class, MDL);
1943 class_dereference (&lease -> billing_class, MDL);
1944 /* If the lease is available for allocation, the billing
1945 is invalid, so we don't keep it. */
1946 if (lease -> binding_state == FTS_ACTIVE ||
1947 lease -> binding_state == FTS_EXPIRED ||
1948 lease -> binding_state == FTS_RELEASED ||
1949 lease -> binding_state == FTS_RESET)
1950 bill_class (lease, class);
1951 class_dereference (&class, MDL);
1953 return;
1956 /* Run expiry events on every pool. This is called on startup so that
1957 any expiry events that occurred after the server stopped and before it
1958 was restarted can be run. At the same time, if failover support is
1959 compiled in, we compute the balance of leases for the pool. */
1961 void expire_all_pools ()
1963 struct shared_network *s;
1964 struct pool *p;
1965 struct hash_bucket *hb;
1966 int i;
1967 struct lease *l;
1968 struct lease **lptr [5];
1970 /* First, go over the hash list and actually put all the leases
1971 on the appropriate lists. */
1972 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1974 /* Loop through each pool in each shared network and call the
1975 expiry routine on the pool. */
1976 for (s = shared_networks; s; s = s -> next) {
1977 for (p = s -> pools; p; p = p -> next) {
1978 pool_timer (p);
1980 p -> lease_count = 0;
1981 p -> free_leases = 0;
1982 p -> backup_leases = 0;
1984 lptr [FREE_LEASES] = &p -> free;
1985 lptr [ACTIVE_LEASES] = &p -> active;
1986 lptr [EXPIRED_LEASES] = &p -> expired;
1987 lptr [ABANDONED_LEASES] = &p -> abandoned;
1988 lptr [BACKUP_LEASES] = &p -> backup;
1990 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1991 for (l = *(lptr [i]); l; l = l -> next) {
1992 p -> lease_count++;
1993 if (l -> ends <= cur_time) {
1994 if (l -> binding_state == FTS_FREE)
1995 p -> free_leases++;
1996 else if (l -> binding_state == FTS_BACKUP)
1997 p -> backup_leases++;
1999 #if defined (FAILOVER_PROTOCOL)
2000 if (p -> failover_peer &&
2001 l -> tstp > l -> tsfp &&
2002 !(l -> flags & ON_UPDATE_QUEUE)) {
2003 l -> desired_binding_state = l -> binding_state;
2004 dhcp_failover_queue_update (l, 1);
2006 #endif
2013 void dump_subnets ()
2015 struct lease *l;
2016 struct shared_network *s;
2017 struct subnet *n;
2018 struct pool *p;
2019 struct lease **lptr [5];
2020 int i;
2022 log_info ("Subnets:");
2023 for (n = subnets; n; n = n -> next_subnet) {
2024 log_debug (" Subnet %s", piaddr (n -> net));
2025 log_debug (" netmask %s",
2026 piaddr (n -> netmask));
2028 log_info ("Shared networks:");
2029 for (s = shared_networks; s; s = s -> next) {
2030 log_info (" %s", s -> name);
2031 for (p = s -> pools; p; p = p -> next) {
2032 lptr [FREE_LEASES] = &p -> free;
2033 lptr [ACTIVE_LEASES] = &p -> active;
2034 lptr [EXPIRED_LEASES] = &p -> expired;
2035 lptr [ABANDONED_LEASES] = &p -> abandoned;
2036 lptr [BACKUP_LEASES] = &p -> backup;
2038 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
2039 for (l = *(lptr [i]); l; l = l -> next) {
2040 print_lease (l);
2047 HASH_FUNCTIONS (lease, const unsigned char *, struct lease, lease_hash_t,
2048 lease_reference, lease_dereference)
2049 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2050 host_reference, host_dereference)
2051 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2052 class_reference, class_dereference)
2054 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2055 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2056 extern struct hash_table *dns_zone_hash;
2057 extern struct interface_info **interface_vector;
2058 extern int interface_count;
2059 dhcp_control_object_t *dhcp_control_object;
2060 extern struct hash_table *auth_key_hash;
2061 struct hash_table *universe_hash;
2062 struct universe **universes;
2063 int universe_count, universe_max;
2064 #if 0
2065 extern int end;
2066 #endif
2068 #if defined (COMPACT_LEASES)
2069 extern struct lease *lease_hunks;
2070 #endif
2072 void free_everything ()
2074 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
2075 struct shared_network *nc = (struct shared_network *)0,
2076 *nn = (struct shared_network *)0;
2077 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
2078 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
2079 struct interface_info *ic = (struct interface_info *)0,
2080 *in = (struct interface_info *)0;
2081 struct class *cc = (struct class *)0, *cn = (struct class *)0;
2082 struct collection *lp;
2083 void *st = (shared_networks
2084 ? (shared_networks -> next
2085 ? shared_networks -> next -> next : 0) : 0);
2086 int i;
2089 /* Get rid of all the hash tables. */
2090 if (host_hw_addr_hash)
2091 host_free_hash_table (&host_hw_addr_hash, MDL);
2092 host_hw_addr_hash = 0;
2093 if (host_uid_hash)
2094 host_free_hash_table (&host_uid_hash, MDL);
2095 host_uid_hash = 0;
2096 if (lease_uid_hash)
2097 lease_free_hash_table (&lease_uid_hash, MDL);
2098 lease_uid_hash = 0;
2099 if (lease_ip_addr_hash)
2100 lease_free_hash_table (&lease_ip_addr_hash, MDL);
2101 lease_ip_addr_hash = 0;
2102 if (lease_hw_addr_hash)
2103 lease_free_hash_table (&lease_hw_addr_hash, MDL);
2104 lease_hw_addr_hash = 0;
2105 if (host_name_hash)
2106 host_free_hash_table (&host_name_hash, MDL);
2107 host_name_hash = 0;
2108 if (dns_zone_hash)
2109 dns_zone_free_hash_table (&dns_zone_hash, MDL);
2110 dns_zone_hash = 0;
2111 #if 0
2112 if (auth_key_hash)
2113 auth_key_free_hash_table (&auth_key_hash, MDL);
2114 #endif
2115 auth_key_hash = 0;
2117 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
2118 MDL);
2120 for (lp = collections; lp; lp = lp -> next) {
2121 if (lp -> classes) {
2122 class_reference (&cn, lp -> classes, MDL);
2123 do {
2124 if (cn) {
2125 class_reference (&cc, cn, MDL);
2126 class_dereference (&cn, MDL);
2128 if (cc -> nic) {
2129 class_reference (&cn, cc -> nic, MDL);
2130 class_dereference (&cc -> nic, MDL);
2132 group_dereference (&cc -> group, MDL);
2133 if (cc -> hash) {
2134 class_free_hash_table (&cc -> hash, MDL);
2135 cc -> hash = (struct hash_table *)0;
2137 class_dereference (&cc, MDL);
2138 } while (cn);
2139 class_dereference (&lp -> classes, MDL);
2143 if (interface_vector) {
2144 for (i = 0; i < interface_count; i++) {
2145 if (interface_vector [i])
2146 interface_dereference (&interface_vector [i], MDL);
2148 dfree (interface_vector, MDL);
2149 interface_vector = 0;
2152 if (interfaces) {
2153 interface_reference (&in, interfaces, MDL);
2154 do {
2155 if (in) {
2156 interface_reference (&ic, in, MDL);
2157 interface_dereference (&in, MDL);
2159 if (ic -> next) {
2160 interface_reference (&in, ic -> next, MDL);
2161 interface_dereference (&ic -> next, MDL);
2163 omapi_unregister_io_object ((omapi_object_t *)ic);
2164 if (ic -> shared_network) {
2165 if (ic -> shared_network -> interface)
2166 interface_dereference
2167 (&ic -> shared_network -> interface, MDL);
2168 shared_network_dereference (&ic -> shared_network, MDL);
2170 interface_dereference (&ic, MDL);
2171 } while (in);
2172 interface_dereference (&interfaces, MDL);
2175 /* Subnets are complicated because of the extra links. */
2176 if (subnets) {
2177 subnet_reference (&sn, subnets, MDL);
2178 do {
2179 if (sn) {
2180 subnet_reference (&sc, sn, MDL);
2181 subnet_dereference (&sn, MDL);
2183 if (sc -> next_subnet) {
2184 subnet_reference (&sn, sc -> next_subnet, MDL);
2185 subnet_dereference (&sc -> next_subnet, MDL);
2187 if (sc -> next_sibling)
2188 subnet_dereference (&sc -> next_sibling, MDL);
2189 if (sc -> shared_network)
2190 shared_network_dereference (&sc -> shared_network, MDL);
2191 group_dereference (&sc -> group, MDL);
2192 if (sc -> interface)
2193 interface_dereference (&sc -> interface, MDL);
2194 subnet_dereference (&sc, MDL);
2195 } while (sn);
2196 subnet_dereference (&subnets, MDL);
2199 /* So are shared networks. */
2200 if (shared_networks) {
2201 shared_network_reference (&nn, shared_networks, MDL);
2202 do {
2203 if (nn) {
2204 shared_network_reference (&nc, nn, MDL);
2205 shared_network_dereference (&nn, MDL);
2207 if (nc -> next) {
2208 shared_network_reference (&nn, nc -> next, MDL);
2209 shared_network_dereference (&nc -> next, MDL);
2212 /* As are pools. */
2213 if (nc -> pools) {
2214 pool_reference (&pn, nc -> pools, MDL);
2215 do {
2216 struct lease **lptr [5];
2218 if (pn) {
2219 pool_reference (&pc, pn, MDL);
2220 pool_dereference (&pn, MDL);
2222 if (pc -> next) {
2223 pool_reference (&pn, pc -> next, MDL);
2224 pool_dereference (&pc -> next, MDL);
2227 lptr [FREE_LEASES] = &pc -> free;
2228 lptr [ACTIVE_LEASES] = &pc -> active;
2229 lptr [EXPIRED_LEASES] = &pc -> expired;
2230 lptr [ABANDONED_LEASES] = &pc -> abandoned;
2231 lptr [BACKUP_LEASES] = &pc -> backup;
2233 /* As (sigh) are leases. */
2234 for (i = 0; i < 5; i++) {
2235 if (*lptr [i]) {
2236 lease_reference (&ln, *lptr [i], MDL);
2237 do {
2238 if (ln) {
2239 lease_reference (&lc, ln, MDL);
2240 lease_dereference (&ln, MDL);
2242 if (lc -> next) {
2243 lease_reference (&ln, lc -> next, MDL);
2244 lease_dereference (&lc -> next, MDL);
2246 if (lc -> billing_class)
2247 class_dereference (&lc -> billing_class,
2248 MDL);
2249 if (lc -> state)
2250 free_lease_state (lc -> state, MDL);
2251 lc -> state = (struct lease_state *)0;
2252 if (lc -> n_hw)
2253 lease_dereference (&lc -> n_hw, MDL);
2254 if (lc -> n_uid)
2255 lease_dereference (&lc -> n_uid, MDL);
2256 lease_dereference (&lc, MDL);
2257 } while (ln);
2258 lease_dereference (lptr [i], MDL);
2261 if (pc -> group)
2262 group_dereference (&pc -> group, MDL);
2263 if (pc -> shared_network)
2264 shared_network_dereference (&pc -> shared_network,
2265 MDL);
2266 pool_dereference (&pc, MDL);
2267 } while (pn);
2268 pool_dereference (&nc -> pools, MDL);
2270 /* Because of a circular reference, we need to nuke this
2271 manually. */
2272 group_dereference (&nc -> group, MDL);
2273 shared_network_dereference (&nc, MDL);
2274 } while (nn);
2275 shared_network_dereference (&shared_networks, MDL);
2278 cancel_all_timeouts ();
2279 relinquish_timeouts ();
2280 trace_free_all ();
2281 group_dereference (&root_group, MDL);
2282 executable_statement_dereference (&default_classification_rules, MDL);
2284 shutdown_state = shutdown_drop_omapi_connections;
2285 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2286 shutdown_state = shutdown_listeners;
2287 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2288 shutdown_state = shutdown_dhcp;
2289 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2291 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
2293 universe_free_hash_table (&universe_hash, MDL);
2294 for (i = 0; i < universe_count; i++) {
2295 union {
2296 const char *c;
2297 char *s;
2298 } foo;
2299 if (universes [i]) {
2300 if (universes [i] -> hash)
2301 option_free_hash_table (&universes [i] -> hash,
2302 MDL);
2303 #if 0
2304 if (universes [i] -> name > (char *)&end) {
2305 foo.c = universes [i] -> name;
2306 dfree (foo.s, MDL);
2308 if (universes [i] > (struct universe *)&end)
2309 dfree (universes [i], MDL);
2310 #endif
2313 dfree (universes, MDL);
2315 relinquish_free_lease_states ();
2316 relinquish_free_pairs ();
2317 relinquish_free_expressions ();
2318 relinquish_free_binding_values ();
2319 relinquish_free_option_caches ();
2320 relinquish_free_packets ();
2321 relinquish_lease_hunks ();
2322 relinquish_hash_bucket_hunks ();
2323 omapi_type_relinquish ();
2325 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */