Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / network / stacks / AROSTCP / dhcp / server / mdb.c
blob86c2f29a9ed89291408d66a099c5d06f99353200
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$ 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 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 if (lt->scope)
1408 binding_scope_dereference(&lt->scope, MDL);
1410 lt -> ends = cur_time; /* XXX */
1411 lt -> next_binding_state = FTS_ABANDONED;
1413 log_error ("Abandoning IP address %s: %s",
1414 piaddr (lease -> ip_addr), message);
1415 lt -> hardware_addr.hlen = 0;
1416 if (lt -> uid && lt -> uid != lt -> uid_buf)
1417 dfree (lt -> uid, MDL);
1418 lt -> uid = (unsigned char *)0;
1419 lt -> uid_len = 0;
1420 lt -> uid_max = 0;
1421 supersede_lease (lease, lt, 1, 1, 1);
1422 lease_dereference (&lt, MDL);
1425 /* Abandon the specified lease (set its timeout to infinity and its
1426 particulars to zero, and re-hash it as appropriate. */
1428 void dissociate_lease (lease)
1429 struct lease *lease;
1431 struct lease *lt = (struct lease *)0;
1433 if (!lease_copy (&lt, lease, MDL))
1434 return;
1436 #if defined (FAILOVER_PROTOCOL)
1437 if (lease -> pool && lease -> pool -> failover_peer) {
1438 lt -> next_binding_state = FTS_RESET;
1439 } else {
1440 lt -> next_binding_state = FTS_FREE;
1442 #else
1443 lt -> next_binding_state = FTS_FREE;
1444 #endif
1445 lt -> ends = cur_time; /* XXX */
1446 lt -> hardware_addr.hlen = 0;
1447 if (lt -> uid && lt -> uid != lt -> uid_buf)
1448 dfree (lt -> uid, MDL);
1449 lt -> uid = (unsigned char *)0;
1450 lt -> uid_len = 0;
1451 lt -> uid_max = 0;
1452 supersede_lease (lease, lt, 1, 1, 1);
1453 lease_dereference (&lt, MDL);
1456 /* Timer called when a lease in a particular pool expires. */
1457 void pool_timer (vpool)
1458 void *vpool;
1460 struct pool *pool;
1461 struct lease *lt = (struct lease *)0;
1462 struct lease *next = (struct lease *)0;
1463 struct lease *lease = (struct lease *)0;
1464 struct lease **lptr [5];
1465 TIME next_expiry = MAX_TIME;
1466 int i;
1468 pool = (struct pool *)vpool;
1470 #define FREE_LEASES 0
1471 lptr [FREE_LEASES] = &pool -> free;
1472 #define ACTIVE_LEASES 1
1473 lptr [ACTIVE_LEASES] = &pool -> active;
1474 #define EXPIRED_LEASES 2
1475 lptr [EXPIRED_LEASES] = &pool -> expired;
1476 #define ABANDONED_LEASES 3
1477 lptr [ABANDONED_LEASES] = &pool -> abandoned;
1478 #define BACKUP_LEASES 4
1479 lptr [BACKUP_LEASES] = &pool -> backup;
1481 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1482 /* If there's nothing on the queue, skip it. */
1483 if (!*(lptr [i]))
1484 continue;
1486 #if defined (FAILOVER_PROTOCOL)
1487 if (pool -> failover_peer &&
1488 pool -> failover_peer -> me.state != partner_down) {
1489 /* The secondary can't remove a lease from the
1490 active state except in partner_down. */
1491 if (i == ACTIVE_LEASES &&
1492 pool -> failover_peer -> i_am == secondary)
1493 continue;
1494 /* Leases in an expired state don't move to
1495 free because of a timeout unless we're in
1496 partner_down. */
1497 if (i == EXPIRED_LEASES)
1498 continue;
1500 #endif
1501 lease_reference (&lease, *(lptr [i]), MDL);
1503 while (lease) {
1504 /* Remember the next lease in the list. */
1505 if (next)
1506 lease_dereference (&next, MDL);
1507 if (lease -> next)
1508 lease_reference (&next, lease -> next, MDL);
1510 /* If we've run out of things to expire on this list,
1511 stop. */
1512 if (lease -> sort_time > cur_time) {
1513 if (lease -> sort_time < next_expiry)
1514 next_expiry = lease -> sort_time;
1515 break;
1518 /* If there is a pending state change, and
1519 this lease has gotten to the time when the
1520 state change should happen, just call
1521 supersede_lease on it to make the change
1522 happen. */
1523 if (lease -> next_binding_state !=
1524 lease -> binding_state)
1525 supersede_lease (lease,
1526 (struct lease *)0, 1, 1, 1);
1528 lease_dereference (&lease, MDL);
1529 if (next)
1530 lease_reference (&lease, next, MDL);
1532 if (next)
1533 lease_dereference (&next, MDL);
1534 if (lease)
1535 lease_dereference (&lease, MDL);
1537 if (next_expiry != MAX_TIME) {
1538 pool -> next_event_time = next_expiry;
1539 add_timeout (pool -> next_event_time, pool_timer, pool,
1540 (tvref_t)pool_reference,
1541 (tvunref_t)pool_dereference);
1542 } else
1543 pool -> next_event_time = MIN_TIME;
1547 /* Locate the lease associated with a given IP address... */
1549 int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
1550 const char *file, int line)
1552 return lease_hash_lookup (lp, lease_ip_addr_hash,
1553 addr.iabuf, addr.len, file, line);
1556 int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
1557 unsigned len, const char *file, int line)
1559 if (len == 0)
1560 return 0;
1561 return lease_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
1564 int find_lease_by_hw_addr (struct lease **lp,
1565 const unsigned char *hwaddr, unsigned hwlen,
1566 const char *file, int line)
1568 if (hwlen == 0)
1569 return 0;
1570 return lease_hash_lookup (lp, lease_hw_addr_hash,
1571 hwaddr, hwlen, file, line);
1574 /* Add the specified lease to the uid hash. */
1576 void uid_hash_add (lease)
1577 struct lease *lease;
1579 struct lease *head = (struct lease *)0;
1580 struct lease *next = (struct lease *)0;
1583 /* If it's not in the hash, just add it. */
1584 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
1585 lease_hash_add (lease_uid_hash, lease -> uid,
1586 lease -> uid_len, lease, MDL);
1587 else {
1588 /* Otherwise, attach it to the end of the list. */
1589 while (head -> n_uid) {
1590 lease_reference (&next, head -> n_uid, MDL);
1591 lease_dereference (&head, MDL);
1592 lease_reference (&head, next, MDL);
1593 lease_dereference (&next, MDL);
1595 lease_reference (&head -> n_uid, lease, MDL);
1596 lease_dereference (&head, MDL);
1600 /* Delete the specified lease from the uid hash. */
1602 void uid_hash_delete (lease)
1603 struct lease *lease;
1605 struct lease *head = (struct lease *)0;
1606 struct lease *scan;
1608 /* If it's not in the hash, we have no work to do. */
1609 if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
1610 if (lease -> n_uid)
1611 lease_dereference (&lease -> n_uid, MDL);
1612 return;
1615 /* If the lease we're freeing is at the head of the list,
1616 remove the hash table entry and add a new one with the
1617 next lease on the list (if there is one). */
1618 if (head == lease) {
1619 lease_hash_delete (lease_uid_hash,
1620 lease -> uid, lease -> uid_len, MDL);
1621 if (lease -> n_uid) {
1622 lease_hash_add (lease_uid_hash,
1623 lease -> n_uid -> uid,
1624 lease -> n_uid -> uid_len,
1625 lease -> n_uid, MDL);
1626 lease_dereference (&lease -> n_uid, MDL);
1628 } else {
1629 /* Otherwise, look for the lease in the list of leases
1630 attached to the hash table entry, and remove it if
1631 we find it. */
1632 for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
1633 if (scan -> n_uid == lease) {
1634 lease_dereference (&scan -> n_uid, MDL);
1635 if (lease -> n_uid) {
1636 lease_reference (&scan -> n_uid,
1637 lease -> n_uid, MDL);
1638 lease_dereference (&lease -> n_uid,
1639 MDL);
1641 break;
1645 lease_dereference (&head, MDL);
1648 /* Add the specified lease to the hardware address hash. */
1650 void hw_hash_add (lease)
1651 struct lease *lease;
1653 struct lease *head = (struct lease *)0;
1654 struct lease *next = (struct lease *)0;
1656 /* If it's not in the hash, just add it. */
1657 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1658 lease -> hardware_addr.hlen, MDL))
1659 lease_hash_add (lease_hw_addr_hash,
1660 lease -> hardware_addr.hbuf,
1661 lease -> hardware_addr.hlen,
1662 lease, MDL);
1663 else {
1664 /* Otherwise, attach it to the end of the list. */
1665 while (head -> n_hw) {
1666 lease_reference (&next, head -> n_hw, MDL);
1667 lease_dereference (&head, MDL);
1668 lease_reference (&head, next, MDL);
1669 lease_dereference (&next, MDL);
1672 lease_reference (&head -> n_hw, lease, MDL);
1673 lease_dereference (&head, MDL);
1677 /* Delete the specified lease from the hardware address hash. */
1679 void hw_hash_delete (lease)
1680 struct lease *lease;
1682 struct lease *head = (struct lease *)0;
1683 struct lease *next = (struct lease *)0;
1685 /* If it's not in the hash, we have no work to do. */
1686 if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
1687 lease -> hardware_addr.hlen, MDL)) {
1688 if (lease -> n_hw)
1689 lease_dereference (&lease -> n_hw, MDL);
1690 return;
1693 /* If the lease we're freeing is at the head of the list,
1694 remove the hash table entry and add a new one with the
1695 next lease on the list (if there is one). */
1696 if (head == lease) {
1697 lease_hash_delete (lease_hw_addr_hash,
1698 lease -> hardware_addr.hbuf,
1699 lease -> hardware_addr.hlen, MDL);
1700 if (lease -> n_hw) {
1701 lease_hash_add (lease_hw_addr_hash,
1702 lease -> n_hw -> hardware_addr.hbuf,
1703 lease -> n_hw -> hardware_addr.hlen,
1704 lease -> n_hw, MDL);
1705 lease_dereference (&lease -> n_hw, MDL);
1707 } else {
1708 /* Otherwise, look for the lease in the list of leases
1709 attached to the hash table entry, and remove it if
1710 we find it. */
1711 while (head -> n_hw) {
1712 if (head -> n_hw == lease) {
1713 lease_dereference (&head -> n_hw, MDL);
1714 if (lease -> n_hw) {
1715 lease_reference (&head -> n_hw,
1716 lease -> n_hw, MDL);
1717 lease_dereference (&lease -> n_hw,
1718 MDL);
1720 break;
1722 lease_reference (&next, head -> n_hw, MDL);
1723 lease_dereference (&head, MDL);
1724 lease_reference (&head, next, MDL);
1725 lease_dereference (&next, MDL);
1728 if (head)
1729 lease_dereference (&head, MDL);
1732 /* Write all interesting leases to permanent storage. */
1734 int write_leases ()
1736 struct lease *l;
1737 struct shared_network *s;
1738 struct pool *p;
1739 struct host_decl *hp;
1740 struct group_object *gp;
1741 struct hash_bucket *hb;
1742 int i;
1743 int num_written;
1744 struct lease **lptr [5];
1746 /* Write all the dynamically-created group declarations. */
1747 if (group_name_hash) {
1748 num_written = 0;
1749 for (i = 0; i < group_name_hash -> hash_count; i++) {
1750 for (hb = group_name_hash -> buckets [i];
1751 hb; hb = hb -> next) {
1752 gp = (struct group_object *)hb -> value;
1753 if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
1754 ((gp -> flags & GROUP_OBJECT_STATIC) &&
1755 (gp -> flags & GROUP_OBJECT_DELETED))) {
1756 if (!write_group (gp))
1757 return 0;
1758 ++num_written;
1762 log_info ("Wrote %d group decls to leases file.", num_written);
1765 /* Write all the deleted host declarations. */
1766 if (host_name_hash) {
1767 num_written = 0;
1768 for (i = 0; i < host_name_hash -> hash_count; i++) {
1769 for (hb = host_name_hash -> buckets [i];
1770 hb; hb = hb -> next) {
1771 hp = (struct host_decl *)hb -> value;
1772 if (((hp -> flags & HOST_DECL_STATIC) &&
1773 (hp -> flags & HOST_DECL_DELETED))) {
1774 if (!write_host (hp))
1775 return 0;
1776 ++num_written;
1780 log_info ("Wrote %d deleted host decls to leases file.",
1781 num_written);
1784 /* Write all the new, dynamic host declarations. */
1785 if (host_name_hash) {
1786 num_written = 0;
1787 for (i = 0; i < host_name_hash -> hash_count; i++) {
1788 for (hb = host_name_hash -> buckets [i];
1789 hb; hb = hb -> next) {
1790 hp = (struct host_decl *)hb -> value;
1791 if ((hp -> flags & HOST_DECL_DYNAMIC)) {
1792 if (!write_host (hp))
1793 ++num_written;
1797 log_info ("Wrote %d new dynamic host decls to leases file.",
1798 num_written);
1801 #if defined (FAILOVER_PROTOCOL)
1802 /* Write all the failover states. */
1803 if (!dhcp_failover_write_all_states ())
1804 return 0;
1805 #endif
1807 /* Write all the leases. */
1808 num_written = 0;
1809 for (s = shared_networks; s; s = s -> next) {
1810 for (p = s -> pools; p; p = p -> next) {
1811 lptr [FREE_LEASES] = &p -> free;
1812 lptr [ACTIVE_LEASES] = &p -> active;
1813 lptr [EXPIRED_LEASES] = &p -> expired;
1814 lptr [ABANDONED_LEASES] = &p -> abandoned;
1815 lptr [BACKUP_LEASES] = &p -> backup;
1817 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1818 for (l = *(lptr [i]); l; l = l -> next) {
1819 #if !defined (DEBUG_DUMP_ALL_LEASES)
1820 if (l -> hardware_addr.hlen ||
1821 l -> uid_len ||
1822 (l -> binding_state != FTS_FREE))
1823 #endif
1825 if (!write_lease (l))
1826 return 0;
1827 num_written++;
1833 log_info ("Wrote %d leases to leases file.", num_written);
1834 if (!commit_leases ())
1835 return 0;
1836 return 1;
1839 int lease_enqueue (struct lease *comp)
1841 struct lease **lq, *prev, *lp;
1843 /* No queue to put it on? */
1844 if (!comp -> pool)
1845 return 0;
1847 /* Figure out which queue it's going to. */
1848 switch (comp -> binding_state) {
1849 case FTS_FREE:
1850 lq = &comp -> pool -> free;
1851 comp -> pool -> free_leases++;
1852 comp -> sort_time = comp -> ends;
1853 break;
1855 case FTS_ACTIVE:
1856 lq = &comp -> pool -> active;
1857 comp -> sort_time = comp -> ends;
1858 break;
1860 case FTS_EXPIRED:
1861 case FTS_RELEASED:
1862 case FTS_RESET:
1863 lq = &comp -> pool -> expired;
1864 comp -> sort_time = comp -> ends;
1866 break;
1868 case FTS_ABANDONED:
1869 lq = &comp -> pool -> abandoned;
1870 comp -> sort_time = comp -> ends;
1871 break;
1873 case FTS_BACKUP:
1874 lq = &comp -> pool -> backup;
1875 comp -> pool -> backup_leases++;
1876 comp -> sort_time = comp -> ends;
1877 break;
1879 default:
1880 log_error ("Lease with bogus binding state: %d",
1881 comp -> binding_state);
1882 #if defined (BINDING_STATE_DEBUG)
1883 abort ();
1884 #endif
1885 return 0;
1888 /* Insertion sort the lease onto the appropriate queue. */
1889 prev = (struct lease *)0;
1890 for (lp = *lq; lp; lp = lp -> next) {
1891 if (lp -> sort_time >= comp -> sort_time)
1892 break;
1893 prev = lp;
1895 if (prev) {
1896 if (prev -> next) {
1897 lease_reference (&comp -> next, prev -> next, MDL);
1898 lease_dereference (&prev -> next, MDL);
1900 lease_reference (&prev -> next, comp, MDL);
1901 } else {
1902 if (*lq) {
1903 lease_reference (&comp -> next, *lq, MDL);
1904 lease_dereference (lq, MDL);
1906 lease_reference (lq, comp, MDL);
1908 return 1;
1911 /* For a given lease, sort it onto the right list in its pool and put it
1912 in each appropriate hash, understanding that it's already by definition
1913 in lease_ip_addr_hash. */
1915 void lease_instantiate (const unsigned char *val, unsigned len,
1916 struct lease *lease)
1918 struct class *class;
1919 /* XXX If the lease doesn't have a pool at this point, it's an
1920 XXX orphan, which we *should* keep around until it expires,
1921 XXX but which right now we just forget. */
1922 if (!lease -> pool) {
1923 lease_hash_delete (lease_ip_addr_hash,
1924 lease -> ip_addr.iabuf,
1925 lease -> ip_addr.len, MDL);
1926 return;
1929 /* Put the lease on the right queue. */
1930 lease_enqueue (lease);
1932 /* Record the lease in the uid hash if possible. */
1933 if (lease -> uid) {
1934 uid_hash_add (lease);
1937 /* Record it in the hardware address hash if possible. */
1938 if (lease -> hardware_addr.hlen) {
1939 hw_hash_add (lease);
1942 /* If the lease has a billing class, set up the billing. */
1943 if (lease -> billing_class) {
1944 class = (struct class *)0;
1945 class_reference (&class, lease -> billing_class, MDL);
1946 class_dereference (&lease -> billing_class, MDL);
1947 /* If the lease is available for allocation, the billing
1948 is invalid, so we don't keep it. */
1949 if (lease -> binding_state == FTS_ACTIVE ||
1950 lease -> binding_state == FTS_EXPIRED ||
1951 lease -> binding_state == FTS_RELEASED ||
1952 lease -> binding_state == FTS_RESET)
1953 bill_class (lease, class);
1954 class_dereference (&class, MDL);
1956 return;
1959 /* Run expiry events on every pool. This is called on startup so that
1960 any expiry events that occurred after the server stopped and before it
1961 was restarted can be run. At the same time, if failover support is
1962 compiled in, we compute the balance of leases for the pool. */
1964 void expire_all_pools ()
1966 struct shared_network *s;
1967 struct pool *p;
1968 struct hash_bucket *hb;
1969 int i;
1970 struct lease *l;
1971 struct lease **lptr [5];
1973 /* First, go over the hash list and actually put all the leases
1974 on the appropriate lists. */
1975 lease_hash_foreach (lease_ip_addr_hash, lease_instantiate);
1977 /* Loop through each pool in each shared network and call the
1978 expiry routine on the pool. */
1979 for (s = shared_networks; s; s = s -> next) {
1980 for (p = s -> pools; p; p = p -> next) {
1981 pool_timer (p);
1983 p -> lease_count = 0;
1984 p -> free_leases = 0;
1985 p -> backup_leases = 0;
1987 lptr [FREE_LEASES] = &p -> free;
1988 lptr [ACTIVE_LEASES] = &p -> active;
1989 lptr [EXPIRED_LEASES] = &p -> expired;
1990 lptr [ABANDONED_LEASES] = &p -> abandoned;
1991 lptr [BACKUP_LEASES] = &p -> backup;
1993 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
1994 for (l = *(lptr [i]); l; l = l -> next) {
1995 p -> lease_count++;
1996 if (l -> ends <= cur_time) {
1997 if (l -> binding_state == FTS_FREE)
1998 p -> free_leases++;
1999 else if (l -> binding_state == FTS_BACKUP)
2000 p -> backup_leases++;
2002 #if defined (FAILOVER_PROTOCOL)
2003 if (p -> failover_peer &&
2004 l -> tstp > l -> tsfp &&
2005 !(l -> flags & ON_UPDATE_QUEUE)) {
2006 l -> desired_binding_state = l -> binding_state;
2007 dhcp_failover_queue_update (l, 1);
2009 #endif
2016 void dump_subnets ()
2018 struct lease *l;
2019 struct shared_network *s;
2020 struct subnet *n;
2021 struct pool *p;
2022 struct lease **lptr [5];
2023 int i;
2025 log_info ("Subnets:");
2026 for (n = subnets; n; n = n -> next_subnet) {
2027 log_debug (" Subnet %s", piaddr (n -> net));
2028 log_debug (" netmask %s",
2029 piaddr (n -> netmask));
2031 log_info ("Shared networks:");
2032 for (s = shared_networks; s; s = s -> next) {
2033 log_info (" %s", s -> name);
2034 for (p = s -> pools; p; p = p -> next) {
2035 lptr [FREE_LEASES] = &p -> free;
2036 lptr [ACTIVE_LEASES] = &p -> active;
2037 lptr [EXPIRED_LEASES] = &p -> expired;
2038 lptr [ABANDONED_LEASES] = &p -> abandoned;
2039 lptr [BACKUP_LEASES] = &p -> backup;
2041 for (i = FREE_LEASES; i <= BACKUP_LEASES; i++) {
2042 for (l = *(lptr [i]); l; l = l -> next) {
2043 print_lease (l);
2050 HASH_FUNCTIONS (lease, const unsigned char *, struct lease, lease_hash_t,
2051 lease_reference, lease_dereference)
2052 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2053 host_reference, host_dereference)
2054 HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2055 class_reference, class_dereference)
2057 #if defined (DEBUG_MEMORY_LEAKAGE) && \
2058 defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2059 extern struct hash_table *dns_zone_hash;
2060 extern struct interface_info **interface_vector;
2061 extern int interface_count;
2062 dhcp_control_object_t *dhcp_control_object;
2063 extern struct hash_table *auth_key_hash;
2064 struct hash_table *universe_hash;
2065 struct universe **universes;
2066 int universe_count, universe_max;
2067 #if 0
2068 extern int end;
2069 #endif
2071 #if defined (COMPACT_LEASES)
2072 extern struct lease *lease_hunks;
2073 #endif
2075 void free_everything ()
2077 struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
2078 struct shared_network *nc = (struct shared_network *)0,
2079 *nn = (struct shared_network *)0;
2080 struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
2081 struct lease *lc = (struct lease *)0, *ln = (struct lease *)0;
2082 struct interface_info *ic = (struct interface_info *)0,
2083 *in = (struct interface_info *)0;
2084 struct class *cc = (struct class *)0, *cn = (struct class *)0;
2085 struct collection *lp;
2086 void *st = (shared_networks
2087 ? (shared_networks -> next
2088 ? shared_networks -> next -> next : 0) : 0);
2089 int i;
2092 /* Get rid of all the hash tables. */
2093 if (host_hw_addr_hash)
2094 host_free_hash_table (&host_hw_addr_hash, MDL);
2095 host_hw_addr_hash = 0;
2096 if (host_uid_hash)
2097 host_free_hash_table (&host_uid_hash, MDL);
2098 host_uid_hash = 0;
2099 if (lease_uid_hash)
2100 lease_free_hash_table (&lease_uid_hash, MDL);
2101 lease_uid_hash = 0;
2102 if (lease_ip_addr_hash)
2103 lease_free_hash_table (&lease_ip_addr_hash, MDL);
2104 lease_ip_addr_hash = 0;
2105 if (lease_hw_addr_hash)
2106 lease_free_hash_table (&lease_hw_addr_hash, MDL);
2107 lease_hw_addr_hash = 0;
2108 if (host_name_hash)
2109 host_free_hash_table (&host_name_hash, MDL);
2110 host_name_hash = 0;
2111 if (dns_zone_hash)
2112 dns_zone_free_hash_table (&dns_zone_hash, MDL);
2113 dns_zone_hash = 0;
2114 #if 0
2115 if (auth_key_hash)
2116 auth_key_free_hash_table (&auth_key_hash, MDL);
2117 #endif
2118 auth_key_hash = 0;
2120 omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
2121 MDL);
2123 for (lp = collections; lp; lp = lp -> next) {
2124 if (lp -> classes) {
2125 class_reference (&cn, lp -> classes, MDL);
2126 do {
2127 if (cn) {
2128 class_reference (&cc, cn, MDL);
2129 class_dereference (&cn, MDL);
2131 if (cc -> nic) {
2132 class_reference (&cn, cc -> nic, MDL);
2133 class_dereference (&cc -> nic, MDL);
2135 group_dereference (&cc -> group, MDL);
2136 if (cc -> hash) {
2137 class_free_hash_table (&cc -> hash, MDL);
2138 cc -> hash = (struct hash_table *)0;
2140 class_dereference (&cc, MDL);
2141 } while (cn);
2142 class_dereference (&lp -> classes, MDL);
2146 if (interface_vector) {
2147 for (i = 0; i < interface_count; i++) {
2148 if (interface_vector [i])
2149 interface_dereference (&interface_vector [i], MDL);
2151 dfree (interface_vector, MDL);
2152 interface_vector = 0;
2155 if (interfaces) {
2156 interface_reference (&in, interfaces, MDL);
2157 do {
2158 if (in) {
2159 interface_reference (&ic, in, MDL);
2160 interface_dereference (&in, MDL);
2162 if (ic -> next) {
2163 interface_reference (&in, ic -> next, MDL);
2164 interface_dereference (&ic -> next, MDL);
2166 omapi_unregister_io_object ((omapi_object_t *)ic);
2167 if (ic -> shared_network) {
2168 if (ic -> shared_network -> interface)
2169 interface_dereference
2170 (&ic -> shared_network -> interface, MDL);
2171 shared_network_dereference (&ic -> shared_network, MDL);
2173 interface_dereference (&ic, MDL);
2174 } while (in);
2175 interface_dereference (&interfaces, MDL);
2178 /* Subnets are complicated because of the extra links. */
2179 if (subnets) {
2180 subnet_reference (&sn, subnets, MDL);
2181 do {
2182 if (sn) {
2183 subnet_reference (&sc, sn, MDL);
2184 subnet_dereference (&sn, MDL);
2186 if (sc -> next_subnet) {
2187 subnet_reference (&sn, sc -> next_subnet, MDL);
2188 subnet_dereference (&sc -> next_subnet, MDL);
2190 if (sc -> next_sibling)
2191 subnet_dereference (&sc -> next_sibling, MDL);
2192 if (sc -> shared_network)
2193 shared_network_dereference (&sc -> shared_network, MDL);
2194 group_dereference (&sc -> group, MDL);
2195 if (sc -> interface)
2196 interface_dereference (&sc -> interface, MDL);
2197 subnet_dereference (&sc, MDL);
2198 } while (sn);
2199 subnet_dereference (&subnets, MDL);
2202 /* So are shared networks. */
2203 if (shared_networks) {
2204 shared_network_reference (&nn, shared_networks, MDL);
2205 do {
2206 if (nn) {
2207 shared_network_reference (&nc, nn, MDL);
2208 shared_network_dereference (&nn, MDL);
2210 if (nc -> next) {
2211 shared_network_reference (&nn, nc -> next, MDL);
2212 shared_network_dereference (&nc -> next, MDL);
2215 /* As are pools. */
2216 if (nc -> pools) {
2217 pool_reference (&pn, nc -> pools, MDL);
2218 do {
2219 struct lease **lptr [5];
2221 if (pn) {
2222 pool_reference (&pc, pn, MDL);
2223 pool_dereference (&pn, MDL);
2225 if (pc -> next) {
2226 pool_reference (&pn, pc -> next, MDL);
2227 pool_dereference (&pc -> next, MDL);
2230 lptr [FREE_LEASES] = &pc -> free;
2231 lptr [ACTIVE_LEASES] = &pc -> active;
2232 lptr [EXPIRED_LEASES] = &pc -> expired;
2233 lptr [ABANDONED_LEASES] = &pc -> abandoned;
2234 lptr [BACKUP_LEASES] = &pc -> backup;
2236 /* As (sigh) are leases. */
2237 for (i = 0; i < 5; i++) {
2238 if (*lptr [i]) {
2239 lease_reference (&ln, *lptr [i], MDL);
2240 do {
2241 if (ln) {
2242 lease_reference (&lc, ln, MDL);
2243 lease_dereference (&ln, MDL);
2245 if (lc -> next) {
2246 lease_reference (&ln, lc -> next, MDL);
2247 lease_dereference (&lc -> next, MDL);
2249 if (lc -> billing_class)
2250 class_dereference (&lc -> billing_class,
2251 MDL);
2252 if (lc -> state)
2253 free_lease_state (lc -> state, MDL);
2254 lc -> state = (struct lease_state *)0;
2255 if (lc -> n_hw)
2256 lease_dereference (&lc -> n_hw, MDL);
2257 if (lc -> n_uid)
2258 lease_dereference (&lc -> n_uid, MDL);
2259 lease_dereference (&lc, MDL);
2260 } while (ln);
2261 lease_dereference (lptr [i], MDL);
2264 if (pc -> group)
2265 group_dereference (&pc -> group, MDL);
2266 if (pc -> shared_network)
2267 shared_network_dereference (&pc -> shared_network,
2268 MDL);
2269 pool_dereference (&pc, MDL);
2270 } while (pn);
2271 pool_dereference (&nc -> pools, MDL);
2273 /* Because of a circular reference, we need to nuke this
2274 manually. */
2275 group_dereference (&nc -> group, MDL);
2276 shared_network_dereference (&nc, MDL);
2277 } while (nn);
2278 shared_network_dereference (&shared_networks, MDL);
2281 cancel_all_timeouts ();
2282 relinquish_timeouts ();
2283 trace_free_all ();
2284 group_dereference (&root_group, MDL);
2285 executable_statement_dereference (&default_classification_rules, MDL);
2287 shutdown_state = shutdown_drop_omapi_connections;
2288 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2289 shutdown_state = shutdown_listeners;
2290 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2291 shutdown_state = shutdown_dhcp;
2292 omapi_io_state_foreach (dhcp_io_shutdown, 0);
2294 omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
2296 universe_free_hash_table (&universe_hash, MDL);
2297 for (i = 0; i < universe_count; i++) {
2298 union {
2299 const char *c;
2300 char *s;
2301 } foo;
2302 if (universes [i]) {
2303 if (universes [i] -> hash)
2304 option_free_hash_table (&universes [i] -> hash,
2305 MDL);
2306 #if 0
2307 if (universes [i] -> name > (char *)&end) {
2308 foo.c = universes [i] -> name;
2309 dfree (foo.s, MDL);
2311 if (universes [i] > (struct universe *)&end)
2312 dfree (universes [i], MDL);
2313 #endif
2316 dfree (universes, MDL);
2318 relinquish_free_lease_states ();
2319 relinquish_free_pairs ();
2320 relinquish_free_expressions ();
2321 relinquish_free_binding_values ();
2322 relinquish_free_option_caches ();
2323 relinquish_free_packets ();
2324 relinquish_lease_hunks ();
2325 relinquish_hash_bucket_hunks ();
2326 omapi_type_relinquish ();
2328 #endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */