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