1/*	$NetBSD: mdb.c,v 1.4 2022/04/03 01:10:59 christos Exp $	*/
2
3/* mdb.c
4
5   Server-specific in-memory database support. */
6
7/*
8 * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
9 * Copyright (c) 1996-2003 by Internet Software Consortium
10 *
11 * This Source Code Form is subject to the terms of the Mozilla Public
12 * License, v. 2.0. If a copy of the MPL was not distributed with this
13 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 *   Internet Systems Consortium, Inc.
24 *   PO Box 360
25 *   Newmarket, NH 03857 USA
26 *   <info@isc.org>
27 *   https://www.isc.org/
28 *
29 */
30
31#include <sys/cdefs.h>
32__RCSID("$NetBSD: mdb.c,v 1.4 2022/04/03 01:10:59 christos Exp $");
33
34#include "dhcpd.h"
35#include "omapip/hash.h"
36
37struct subnet *subnets;
38struct shared_network *shared_networks;
39host_hash_t *host_hw_addr_hash;
40host_hash_t *host_uid_hash;
41host_hash_t *host_name_hash;
42lease_id_hash_t *lease_uid_hash;
43lease_ip_hash_t *lease_ip_addr_hash;
44lease_id_hash_t *lease_hw_addr_hash;
45
46/*
47 * We allow users to specify any option as a host identifier.
48 *
49 * Any host is uniquely identified by the combination of
50 * option type & option data.
51 *
52 * We expect people will only use a few types of options as host
53 * identifier. Because of this, we store a list with an entry for
54 * each option type. Each of these has a hash table, which contains
55 * hash of the option data.
56 *
57 * For v6 we also include a relay count - this specifies which
58 * relay to check for the requested option.  As each different
59 * value of relays creates a new instance admins should use the
60 * same value across each option for all host-identifers.
61 * A value of 0 indicates that we aren't doing relay options
62 * and should simply look in the current option list.
63 */
64typedef struct host_id_info {
65	struct option *option;
66	host_hash_t *values_hash;
67	int relays;
68	struct host_id_info *next;
69} host_id_info_t;
70
71static host_id_info_t *host_id_info = NULL;
72
73int numclasseswritten;
74
75extern omapi_object_type_t *dhcp_type_host;
76
77isc_result_t enter_class(cd, dynamicp, commit)
78	struct class *cd;
79	int dynamicp;
80	int commit;
81{
82	if (!collections -> classes) {
83		/* A subclass with no parent is invalid. */
84		if (cd->name == NULL)
85			return DHCP_R_INVALIDARG;
86
87		class_reference (&collections -> classes, cd, MDL);
88	} else if (cd->name != NULL) {	/* regular class */
89		struct class *c = 0;
90
91		if (find_class(&c, cd->name, MDL) != ISC_R_NOTFOUND) {
92			class_dereference(&c, MDL);
93			return ISC_R_EXISTS;
94		}
95
96		/* Find the tail. */
97		for (c = collections -> classes;
98		     c -> nic; c = c -> nic)
99			/* nothing */ ;
100		class_reference (&c -> nic, cd, MDL);
101	}
102
103	if (dynamicp && commit) {
104		const char *name = cd->name;
105
106		if (name == NULL) {
107			name = cd->superclass->name;
108		}
109
110		write_named_billing_class ((const unsigned char *)name, 0, cd);
111		if (!commit_leases ())
112			return ISC_R_IOERROR;
113	}
114
115	return ISC_R_SUCCESS;
116}
117
118
119/* Variable to check if we're starting the server.  The server will init as
120 * starting - but just to be safe start out as false to avoid triggering new
121 * special-case code
122 * XXX: There is actually a server_startup state...which is never entered...
123 */
124#define SS_NOSYNC	1
125#define SS_QFOLLOW	2
126static int server_starting = 0;
127
128static int find_uid_statement (struct executable_statement *esp,
129			       void *vp, int condp)
130{
131	struct executable_statement **evp = vp;
132
133	if (esp -> op == supersede_option_statement &&
134	    esp -> data.option &&
135	    (esp -> data.option -> option -> universe ==
136	     &dhcp_universe) &&
137	    (esp -> data.option -> option -> code ==
138	     DHO_DHCP_CLIENT_IDENTIFIER)) {
139		if (condp) {
140			log_error ("dhcp client identifier may not be %s",
141				   "specified conditionally.");
142		} else if (!(*evp)) {
143			executable_statement_reference (evp, esp, MDL);
144			return 1;
145		} else {
146			log_error ("only one dhcp client identifier may be %s",
147				   "specified");
148		}
149	}
150	return 0;
151}
152
153
154static host_id_info_t *
155find_host_id_info(unsigned int option_code, int relays) {
156	host_id_info_t *p;
157
158	for (p = host_id_info; p != NULL; p = p->next) {
159		if ((p->option->code == option_code) &&
160		    (p->relays == relays)) {
161			break;
162		}
163	}
164	return p;
165}
166
167/* Debugging code */
168#if 0
169isc_result_t
170print_host(const void *name, unsigned len, void *value) {
171	struct host_decl *h;
172	printf("--------------\n");
173	printf("name:'%s'\n", print_hex_1(len, name, 60));
174	printf("len:%d\n", len);
175	h = (struct host_decl *)value;
176	printf("host @%p is '%s'\n", h, h->name);
177	return ISC_R_SUCCESS;
178}
179
180void
181hash_print_hosts(struct hash_table *h) {
182	hash_foreach(h, print_host);
183	printf("--------------\n");
184}
185#endif /* 0 */
186
187void
188change_host_uid(struct host_decl *host, const char *uid, int len) {
189	/* XXX: should consolidate this type of code throughout */
190	if (host_uid_hash == NULL) {
191		if (!host_new_hash(&host_uid_hash, HOST_HASH_SIZE, MDL)) {
192			log_fatal("Can't allocate host/uid hash");
193		}
194	}
195
196	/*
197	 * Remove the old entry, if one exists.
198	 */
199	if (host->client_identifier.data != NULL) {
200		host_hash_delete(host_uid_hash,
201				 host->client_identifier.data,
202				 host->client_identifier.len,
203				 MDL);
204		data_string_forget(&host->client_identifier, MDL);
205	}
206
207	/*
208	 * Set our new value.
209	 */
210	memset(&host->client_identifier, 0, sizeof(host->client_identifier));
211	host->client_identifier.len = len;
212	if (!buffer_allocate(&host->client_identifier.buffer, len, MDL)) {
213		log_fatal("Can't allocate uid buffer");
214	}
215	host->client_identifier.data = host->client_identifier.buffer->data;
216	memcpy((char *)host->client_identifier.data, uid, len);
217
218	/*
219	 * And add to hash.
220	 */
221	host_hash_add(host_uid_hash, host->client_identifier.data,
222		      host->client_identifier.len, host, MDL);
223}
224
225isc_result_t enter_host (hd, dynamicp, commit)
226	struct host_decl *hd;
227	int dynamicp;
228	int commit;
229{
230	struct host_decl *hp = (struct host_decl *)0;
231	struct host_decl *np = (struct host_decl *)0;
232	struct executable_statement *esp;
233	host_id_info_t *h_id_info;
234
235	if (!host_name_hash) {
236		if (!host_new_hash(&host_name_hash, HOST_HASH_SIZE, MDL))
237			log_fatal ("Can't allocate host name hash");
238		host_hash_add (host_name_hash,
239			       (unsigned char *)hd -> name,
240			       strlen (hd -> name), hd, MDL);
241	} else {
242		host_hash_lookup (&hp, host_name_hash,
243				  (unsigned char *)hd -> name,
244				  strlen (hd -> name), MDL);
245
246		/* If it's deleted, we can supersede it. */
247		if (hp && (hp -> flags & HOST_DECL_DELETED)) {
248			host_hash_delete (host_name_hash,
249					  (unsigned char *)hd -> name,
250					  strlen (hd -> name), MDL);
251			/* If the old entry wasn't dynamic, then we
252			   always have to keep the deletion. */
253			if (hp -> flags & HOST_DECL_STATIC) {
254				hd -> flags |= HOST_DECL_STATIC;
255			}
256			host_dereference (&hp, MDL);
257		}
258
259		/* If we are updating an existing host declaration, we
260		   can just delete it and add it again. */
261		if (hp && hp == hd) {
262			host_dereference (&hp, MDL);
263			delete_host (hd, 0);
264			if (!write_host (hd))
265				return ISC_R_IOERROR;
266			hd -> flags &= ~HOST_DECL_DELETED;
267		}
268
269		/* If there isn't already a host decl matching this
270		   address, add it to the hash table. */
271		if (!hp) {
272			host_hash_add (host_name_hash,
273				       (unsigned char *)hd -> name,
274				       strlen (hd -> name), hd, MDL);
275		} else {
276			/* XXX actually, we have to delete the old one
277			   XXX carefully and replace it.   Not done yet. */
278			host_dereference (&hp, MDL);
279			return ISC_R_EXISTS;
280		}
281	}
282
283	if (hd -> n_ipaddr)
284		host_dereference (&hd -> n_ipaddr, MDL);
285
286	if (!hd -> type)
287		hd -> type = dhcp_type_host;
288
289	if (hd -> interface.hlen) {
290		if (!host_hw_addr_hash) {
291			if (!host_new_hash(&host_hw_addr_hash,
292					   HOST_HASH_SIZE, MDL))
293				log_fatal ("Can't allocate host/hw hash");
294		} else {
295			/* If there isn't already a host decl matching this
296			   address, add it to the hash table. */
297			host_hash_lookup (&hp, host_hw_addr_hash,
298					  hd -> interface.hbuf,
299					  hd -> interface.hlen, MDL);
300		}
301		if (!hp)
302			host_hash_add (host_hw_addr_hash, hd -> interface.hbuf,
303				       hd -> interface.hlen, hd, MDL);
304		else {
305			/* If there was already a host declaration for
306			   this hardware address, add this one to the
307			   end of the list. */
308			for (np = hp; np -> n_ipaddr; np = np -> n_ipaddr)
309				;
310			host_reference (&np -> n_ipaddr, hd, MDL);
311			host_dereference (&hp, MDL);
312		}
313	}
314
315	/* See if there's a statement that sets the client identifier.
316	   This is a kludge - the client identifier really shouldn't be
317	   set with an executable statement. */
318	esp = NULL;
319	if (executable_statement_foreach (hd->group->statements,
320					  find_uid_statement, &esp, 0)) {
321		struct data_string cid;
322		memset(&cid, 0, sizeof(cid));
323		(void) evaluate_option_cache (&cid,
324					      NULL, NULL, NULL, NULL, NULL,
325					      &global_scope,
326					      esp->data.option, MDL);
327
328		if (hd->client_identifier.len > 0 && cid.len > 0) {
329			char uid_buf[256];
330			char cid_buf[256];
331			print_hex_or_string(hd->client_identifier.len,
332					    hd->client_identifier.data,
333					    sizeof(uid_buf) - 1, uid_buf);
334
335			print_hex_or_string(cid.len, cid.data,
336					    sizeof(cid_buf) - 1, cid_buf);
337
338			log_error ("Warning, host declaration '%s'"
339				   " already has uid '%s',"
340				   " ignoring dhcp-client-identifier '%s'",
341				   hd->name, uid_buf, cid_buf);
342
343			data_string_forget(&cid, MDL);
344		} else {
345			memcpy(&hd->client_identifier, &cid, sizeof(cid));
346		}
347	}
348
349	/* If we got a client identifier, hash this entry by
350	   client identifier. */
351	if (hd -> client_identifier.len) {
352		/* If there's no uid hash, make one; otherwise, see if
353		   there's already an entry in the hash for this host. */
354		if (!host_uid_hash) {
355			if (!host_new_hash(&host_uid_hash,
356					   HOST_HASH_SIZE, MDL))
357				log_fatal ("Can't allocate host/uid hash");
358
359			host_hash_add (host_uid_hash,
360				       hd -> client_identifier.data,
361				       hd -> client_identifier.len,
362				       hd, MDL);
363		} else {
364			/* If there's already a host declaration for this
365			   client identifier, add this one to the end of the
366			   list.  Otherwise, add it to the hash table. */
367			if (host_hash_lookup (&hp, host_uid_hash,
368					      hd -> client_identifier.data,
369					      hd -> client_identifier.len,
370					      MDL)) {
371				/* Don't link it in twice... */
372				if (!np) {
373					for (np = hp; np -> n_ipaddr;
374					     np = np -> n_ipaddr) {
375						if (hd == np)
376						    break;
377					}
378					if (hd != np)
379					    host_reference (&np -> n_ipaddr,
380							    hd, MDL);
381				}
382				host_dereference (&hp, MDL);
383			} else {
384				host_hash_add (host_uid_hash,
385					       hd -> client_identifier.data,
386					       hd -> client_identifier.len,
387					       hd, MDL);
388			}
389		}
390	}
391
392
393	/*
394	 * If we use an option as our host identifier, record it here.
395	 */
396	if (hd->host_id_option != NULL) {
397		/*
398		 * Look for the host identifier information for this option,
399		 * and create a new entry if there is none.
400		 */
401		h_id_info = find_host_id_info(hd->host_id_option->code,
402					      hd->relays);
403		if (h_id_info == NULL) {
404			h_id_info = dmalloc(sizeof(*h_id_info), MDL);
405			if (h_id_info == NULL) {
406				log_fatal("No memory for host-identifier "
407					  "option information.");
408			}
409			option_reference(&h_id_info->option,
410					 hd->host_id_option, MDL);
411			if (!host_new_hash(&h_id_info->values_hash,
412					   HOST_HASH_SIZE, MDL)) {
413				log_fatal("No memory for host-identifier "
414					  "option hash.");
415			}
416			h_id_info->relays = hd->relays;
417			h_id_info->next = host_id_info;
418			host_id_info = h_id_info;
419		}
420
421		if (host_hash_lookup(&hp, h_id_info->values_hash,
422				     hd->host_id.data, hd->host_id.len, MDL)) {
423			/*
424			 * If this option is already present, then add
425			 * this host to the list in n_ipaddr, unless
426			 * we have already done so previously.
427			 *
428			 * XXXSK: This seems scary to me, but I don't
429			 *        fully understand how these are used.
430			 *        Shouldn't there be multiple lists, or
431			 *        maybe we should just forbid duplicates?
432			 */
433			if (np == NULL) {
434				np = hp;
435				while (np->n_ipaddr != NULL) {
436					np = np->n_ipaddr;
437				}
438				if (hd != np) {
439					host_reference(&np->n_ipaddr, hd, MDL);
440				}
441			}
442			host_dereference(&hp, MDL);
443		} else {
444			host_hash_add(h_id_info->values_hash,
445				      hd->host_id.data,
446				      hd->host_id.len,
447				      hd, MDL);
448		}
449	}
450
451	if (dynamicp && commit) {
452		if (!write_host (hd))
453			return ISC_R_IOERROR;
454		if (!commit_leases ())
455			return ISC_R_IOERROR;
456	}
457
458	return ISC_R_SUCCESS;
459}
460
461
462isc_result_t delete_class (cp, commit)
463	struct class *cp;
464	int commit;
465{
466	cp->flags |= CLASS_DECL_DELETED;
467
468	/* do the write first as we won't be leaving it in any data
469	   structures, unlike the host objects */
470
471	if (commit) {
472		write_named_billing_class ((unsigned char *)cp->name, 0, cp);
473		if (!commit_leases ())
474			return ISC_R_IOERROR;
475	}
476
477	/*
478	 * If this is a subclass remove it from the class's hash table
479	 */
480	if (cp->superclass) {
481		class_hash_delete(cp->superclass->hash,
482				  (const char *)cp->hash_string.data,
483				  cp->hash_string.len,
484				  MDL);
485	}
486
487	/* remove from collections */
488	unlink_class(&cp);
489
490	return ISC_R_SUCCESS;
491}
492
493
494isc_result_t delete_host (hd, commit)
495	struct host_decl *hd;
496	int commit;
497{
498	struct host_decl *hp = (struct host_decl *)0;
499	struct host_decl *np = (struct host_decl *)0;
500	struct host_decl *foo;
501	int hw_head = 0, uid_head = 1;
502
503	/* Don't need to do it twice. */
504	if (hd -> flags & HOST_DECL_DELETED)
505		return ISC_R_SUCCESS;
506
507	/* But we do need to do it once!   :') */
508	hd -> flags |= HOST_DECL_DELETED;
509
510	if (hd -> interface.hlen) {
511	    if (host_hw_addr_hash) {
512		if (host_hash_lookup (&hp, host_hw_addr_hash,
513				      hd -> interface.hbuf,
514				      hd -> interface.hlen, MDL)) {
515		    if (hp == hd) {
516			host_hash_delete (host_hw_addr_hash,
517					  hd -> interface.hbuf,
518					  hd -> interface.hlen, MDL);
519			hw_head = 1;
520		    } else {
521			np = (struct host_decl *)0;
522			foo = (struct host_decl *)0;
523			host_reference (&foo, hp, MDL);
524			while (foo) {
525			    if (foo == hd)
526				    break;
527			    if (np)
528				    host_dereference (&np, MDL);
529			    host_reference (&np, foo, MDL);
530			    host_dereference (&foo, MDL);
531			    if (np -> n_ipaddr)
532				    host_reference (&foo, np -> n_ipaddr, MDL);
533			}
534
535			if (foo) {
536			    host_dereference (&np -> n_ipaddr, MDL);
537			    if (hd -> n_ipaddr)
538				host_reference (&np -> n_ipaddr,
539						hd -> n_ipaddr, MDL);
540			    host_dereference (&foo, MDL);
541			}
542			if (np)
543				host_dereference (&np, MDL);
544		    }
545		    host_dereference (&hp, MDL);
546		}
547	    }
548	}
549
550	/* If we got a client identifier, hash this entry by
551	   client identifier. */
552	if (hd -> client_identifier.len) {
553	    if (host_uid_hash) {
554		if (host_hash_lookup (&hp, host_uid_hash,
555				      hd -> client_identifier.data,
556				      hd -> client_identifier.len, MDL)) {
557		    if (hp == hd) {
558			host_hash_delete (host_uid_hash,
559					  hd -> client_identifier.data,
560					  hd -> client_identifier.len, MDL);
561			uid_head = 1;
562		    } else {
563			np = (struct host_decl *)0;
564			foo = (struct host_decl *)0;
565			host_reference (&foo, hp, MDL);
566			while (foo) {
567			    if (foo == hd)
568				    break;
569			    if (np)
570				host_dereference (&np, MDL);
571			    host_reference (&np, foo, MDL);
572			    host_dereference (&foo, MDL);
573			    if (np -> n_ipaddr)
574				    host_reference (&foo, np -> n_ipaddr, MDL);
575			}
576
577			if (foo) {
578			    host_dereference (&np -> n_ipaddr, MDL);
579			    if (hd -> n_ipaddr)
580				host_reference (&np -> n_ipaddr,
581						hd -> n_ipaddr, MDL);
582			    host_dereference (&foo, MDL);
583			}
584			if (np)
585				host_dereference (&np, MDL);
586		    }
587		    host_dereference (&hp, MDL);
588		}
589	    }
590	}
591
592	if (hd->host_id_option != NULL) {
593		option_dereference(&hd->host_id_option, MDL);
594		data_string_forget(&hd->host_id, MDL);
595	}
596
597	if (hd -> n_ipaddr) {
598		if (uid_head && hd -> n_ipaddr -> client_identifier.len) {
599			host_hash_add
600				(host_uid_hash,
601				 hd -> n_ipaddr -> client_identifier.data,
602				 hd -> n_ipaddr -> client_identifier.len,
603				 hd -> n_ipaddr, MDL);
604		}
605		if (hw_head && hd -> n_ipaddr -> interface.hlen) {
606			host_hash_add (host_hw_addr_hash,
607				       hd -> n_ipaddr -> interface.hbuf,
608				       hd -> n_ipaddr -> interface.hlen,
609				       hd -> n_ipaddr, MDL);
610		}
611		host_dereference (&hd -> n_ipaddr, MDL);
612	}
613
614	if (host_name_hash) {
615		if (host_hash_lookup (&hp, host_name_hash,
616				      (unsigned char *)hd -> name,
617				      strlen (hd -> name), MDL)) {
618			if (hp == hd && !(hp -> flags & HOST_DECL_STATIC)) {
619				host_hash_delete (host_name_hash,
620						  (unsigned char *)hd -> name,
621						  strlen (hd -> name), MDL);
622			}
623			host_dereference (&hp, MDL);
624		}
625	}
626
627	if (commit) {
628		if (!write_host (hd))
629			return ISC_R_IOERROR;
630		if (!commit_leases ())
631			return ISC_R_IOERROR;
632	}
633	return ISC_R_SUCCESS;
634}
635
636int find_hosts_by_haddr (struct host_decl **hp, int htype,
637			 const unsigned char *haddr, unsigned hlen,
638			 const char *file, int line)
639{
640	struct hardware h;
641#if defined(LDAP_CONFIGURATION)
642	int ret;
643
644	if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
645		return ret;
646#endif
647
648	h.hlen = hlen + 1;
649	h.hbuf [0] = htype;
650	memcpy (&h.hbuf [1], haddr, hlen);
651
652	return host_hash_lookup (hp, host_hw_addr_hash,
653				 h.hbuf, h.hlen, file, line);
654}
655
656int find_hosts_by_uid (struct host_decl **hp,
657		       const unsigned char *data, unsigned len,
658		       const char *file, int line)
659{
660	return host_hash_lookup (hp, host_uid_hash, data, len, file, line);
661}
662
663int
664find_hosts_by_option(struct host_decl **hp,
665		     struct packet *packet,
666		     struct option_state *opt_state,
667		     const char *file, int line) {
668	host_id_info_t *p;
669	struct option_cache *oc;
670	struct data_string data;
671	int found;
672	struct packet *relay_packet;
673	struct option_state *relay_state;
674
675#if defined(LDAP_CONFIGURATION)
676	if ((found = find_client_in_ldap (hp, packet, opt_state, file, line)))
677		return found;
678#endif
679
680	for (p = host_id_info; p != NULL; p = p->next) {
681		relay_packet = packet;
682		relay_state = opt_state;
683
684		/* If this option block is for a relay (relays != 0)
685		 * and we are processing the main options and not
686		 * options from the IA (packet->options == opt_state)
687		 * try to find the proper relay
688		 */
689		if ((p->relays != 0) && (packet->options == opt_state)) {
690			int i = p->relays;
691			while ((i != 0) &&
692			       (relay_packet->dhcpv6_container_packet != NULL)) {
693				relay_packet =
694					relay_packet->dhcpv6_container_packet;
695				i--;
696			}
697			/* We wanted a specific relay but were
698			 * unable to find it */
699			if ((p->relays <= MAX_V6RELAY_HOPS) && (i != 0))
700				continue;
701
702			relay_state = relay_packet->options;
703		}
704
705		oc = lookup_option(p->option->universe,
706				   relay_state, p->option->code);
707		if (oc != NULL) {
708			memset(&data, 0, sizeof(data));
709
710			if (!evaluate_option_cache(&data, relay_packet, NULL,
711						   NULL, relay_state, NULL,
712						   &global_scope, oc,
713						   MDL)) {
714				log_error("Error evaluating option cache");
715				return 0;
716			}
717
718			found = host_hash_lookup(hp, p->values_hash,
719						 data.data, data.len,
720						 file, line);
721
722			data_string_forget(&data, MDL);
723
724			if (found) {
725				return 1;
726			}
727		}
728	}
729	return 0;
730}
731
732/* More than one host_decl can be returned by find_hosts_by_haddr or
733   find_hosts_by_uid, and each host_decl can have multiple addresses.
734   Loop through the list of hosts, and then for each host, through the
735   list of addresses, looking for an address that's in the same shared
736   network as the one specified.    Store the matching address through
737   the addr pointer, update the host pointer to point at the host_decl
738   that matched, and return the subnet that matched. */
739
740int find_host_for_network (struct subnet **sp, struct host_decl **host,
741			   struct iaddr *addr, struct shared_network *share)
742{
743	int i;
744	struct iaddr ip_address;
745	struct host_decl *hp;
746	struct data_string fixed_addr;
747
748	memset (&fixed_addr, 0, sizeof fixed_addr);
749
750	for (hp = *host; hp; hp = hp -> n_ipaddr) {
751		if (!hp -> fixed_addr)
752			continue;
753		if (!evaluate_option_cache (&fixed_addr, (struct packet *)0,
754					    (struct lease *)0,
755					    (struct client_state *)0,
756					    (struct option_state *)0,
757					    (struct option_state *)0,
758					    &global_scope,
759					    hp -> fixed_addr, MDL))
760			continue;
761		for (i = 0; i < fixed_addr.len; i += 4) {
762			ip_address.len = 4;
763			memcpy (ip_address.iabuf,
764				fixed_addr.data + i, 4);
765			if (find_grouped_subnet (sp, share, ip_address, MDL)) {
766				struct host_decl *tmp = (struct host_decl *)0;
767				*addr = ip_address;
768				/* This is probably not necessary, but
769				   just in case *host is the only reference
770				   to that host declaration, make a temporary
771				   reference so that dereferencing it doesn't
772				   dereference hp out from under us. */
773				host_reference (&tmp, *host, MDL);
774				host_dereference (host, MDL);
775				host_reference (host, hp, MDL);
776				host_dereference (&tmp, MDL);
777				data_string_forget (&fixed_addr, MDL);
778				return 1;
779			}
780		}
781		data_string_forget (&fixed_addr, MDL);
782	}
783	return 0;
784}
785
786void new_address_range (cfile, low, high, subnet, pool, lpchain)
787	struct parse *cfile;
788	struct iaddr low, high;
789	struct subnet *subnet;
790	struct pool *pool;
791	struct lease **lpchain;
792{
793#if defined(COMPACT_LEASES)
794	struct lease *address_range;
795	unsigned s;
796#endif
797	unsigned min, max, i, num_addrs;
798	char lowbuf [16], highbuf [16], netbuf [16];
799	struct shared_network *share = subnet -> shared_network;
800	struct lease *lt = (struct lease *)0;
801#if !defined(COMPACT_LEASES)
802	isc_result_t status;
803#endif
804
805	/* All subnets should have attached shared network structures. */
806	if (!share) {
807		strcpy (netbuf, piaddr (subnet -> net));
808		log_fatal ("No shared network for network %s (%s)",
809		       netbuf, piaddr (subnet -> netmask));
810	}
811
812	/* Initialize the hash table if it hasn't been done yet. */
813	if (!lease_uid_hash) {
814		if (!lease_id_new_hash(&lease_uid_hash, LEASE_HASH_SIZE, MDL))
815			log_fatal ("Can't allocate lease/uid hash");
816	}
817	if (!lease_ip_addr_hash) {
818		if (!lease_ip_new_hash(&lease_ip_addr_hash, LEASE_HASH_SIZE,
819				       MDL))
820			log_fatal ("Can't allocate lease/ip hash");
821	}
822	if (!lease_hw_addr_hash) {
823		if (!lease_id_new_hash(&lease_hw_addr_hash, LEASE_HASH_SIZE,
824				       MDL))
825			log_fatal ("Can't allocate lease/hw hash");
826	}
827
828	/* Make sure that high and low addresses are in this subnet. */
829	if (!addr_eq(subnet->net, subnet_number(low, subnet->netmask))) {
830		strcpy(lowbuf, piaddr(low));
831		strcpy(netbuf, piaddr(subnet->net));
832		log_fatal("bad range, address %s not in subnet %s netmask %s",
833			  lowbuf, netbuf, piaddr(subnet->netmask));
834	}
835
836	if (!addr_eq(subnet->net, subnet_number(high, subnet->netmask))) {
837		strcpy(highbuf, piaddr(high));
838		strcpy(netbuf, piaddr(subnet->net));
839		log_fatal("bad range, address %s not in subnet %s netmask %s",
840			  highbuf, netbuf, piaddr(subnet->netmask));
841	}
842
843	/* Get the high and low host addresses... */
844	max = host_addr (high, subnet -> netmask);
845	min = host_addr (low, subnet -> netmask);
846
847	/* Allow range to be specified high-to-low as well as low-to-high. */
848	if (min > max) {
849		max = min;
850		min = host_addr (high, subnet -> netmask);
851	}
852
853	/* get the number of addresses we want, and add it to the pool info
854	 * this value is only for use when setting up lease chains and will
855	 * be overwritten when expire_all_pools is run
856	 */
857	num_addrs = max - min + 1;
858#if defined (BINARY_LEASES)
859	pool->lease_count += num_addrs;
860#endif
861
862	/* Get a lease structure for each address in the range. */
863#if defined (COMPACT_LEASES)
864	s = (num_addrs + 1) * sizeof (struct lease);
865	/* Check unsigned overflow in new_leases().
866	   With 304 byte lease structure (x64_86), this happens at
867	   range 10.0.0.0 10.215.148.52; */
868	if (((s % sizeof (struct lease)) != 0) ||
869	    ((s / sizeof (struct lease)) != (num_addrs + 1))) {
870		strcpy (lowbuf, piaddr (low));
871		strcpy (highbuf, piaddr (high));
872		parse_warn (cfile, "%s-%s is an overly large address range.",
873			   lowbuf, highbuf);
874		log_fatal ("Memory overflow.");
875	}
876	address_range = new_leases (num_addrs, MDL);
877	if (!address_range) {
878		strcpy (lowbuf, piaddr (low));
879		strcpy (highbuf, piaddr (high));
880		log_fatal ("No memory for address range %s-%s.",
881			   lowbuf, highbuf);
882	}
883#endif
884
885	/* Fill out the lease structures with some minimal information. */
886	for (i = 0; i < num_addrs; i++) {
887		struct lease *lp = (struct lease *)0;
888#if defined (COMPACT_LEASES)
889		omapi_object_initialize ((omapi_object_t *)&address_range [i],
890					 dhcp_type_lease,
891					 0, sizeof (struct lease), MDL);
892		lease_reference (&lp, &address_range [i], MDL);
893#else
894		status = lease_allocate (&lp, MDL);
895		if (status != ISC_R_SUCCESS)
896			log_fatal ("No memory for lease %s: %s",
897				   piaddr (ip_addr (subnet -> net,
898						    subnet -> netmask,
899						    i + min)),
900				   isc_result_totext (status));
901#endif
902		lp->ip_addr = ip_addr(subnet->net, subnet->netmask, i + min);
903		lp->starts = MIN_TIME;
904		lp->ends = MIN_TIME;
905		subnet_reference(&lp->subnet, subnet, MDL);
906		pool_reference(&lp->pool, pool, MDL);
907		lp->binding_state = FTS_FREE;
908		lp->next_binding_state = FTS_FREE;
909		lp->rewind_binding_state = FTS_FREE;
910		lp->flags = 0;
911
912		/* Remember the lease in the IP address hash. */
913		if (find_lease_by_ip_addr (&lt, lp -> ip_addr, MDL)) {
914			if (lt -> pool) {
915				parse_warn (cfile,
916					    "lease %s is declared twice!",
917					    piaddr (lp -> ip_addr));
918			} else
919				pool_reference (&lt -> pool, pool, MDL);
920			lease_dereference (&lt, MDL);
921		} else
922			lease_ip_hash_add(lease_ip_addr_hash,
923					  lp->ip_addr.iabuf, lp->ip_addr.len,
924					  lp, MDL);
925		/* Put the lease on the chain for the caller. */
926		if (lpchain) {
927			if (*lpchain) {
928				lease_reference (&lp -> next, *lpchain, MDL);
929				lease_dereference (lpchain, MDL);
930			}
931			lease_reference (lpchain, lp, MDL);
932		}
933		lease_dereference (&lp, MDL);
934	}
935}
936
937int find_subnet (struct subnet **sp,
938		 struct iaddr addr, const char *file, int line)
939{
940	struct subnet *rv;
941
942	for (rv = subnets; rv; rv = rv -> next_subnet) {
943#if defined(DHCP4o6)
944		if (addr.len != rv->netmask.len)
945			continue;
946#endif
947		if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
948			if (subnet_reference (sp, rv,
949					      file, line) != ISC_R_SUCCESS)
950				return 0;
951			return 1;
952		}
953	}
954	return 0;
955}
956
957int find_grouped_subnet (struct subnet **sp,
958			 struct shared_network *share, struct iaddr addr,
959			 const char *file, int line)
960{
961	struct subnet *rv;
962
963	for (rv = share -> subnets; rv; rv = rv -> next_sibling) {
964#if defined(DHCP4o6)
965		if (addr.len != rv->netmask.len)
966			continue;
967#endif
968		if (addr_eq (subnet_number (addr, rv -> netmask), rv -> net)) {
969			if (subnet_reference (sp, rv,
970					      file, line) != ISC_R_SUCCESS)
971				return 0;
972			return 1;
973		}
974	}
975	return 0;
976}
977
978/* XXX: could speed up if everyone had a prefix length */
979int
980subnet_inner_than(const struct subnet *subnet,
981		  const struct subnet *scan,
982		  int warnp) {
983#if defined(DHCP4o6)
984	if (subnet->net.len != scan->net.len)
985		return 0;
986#endif
987	if (addr_eq(subnet_number(subnet->net, scan->netmask), scan->net) ||
988	    addr_eq(subnet_number(scan->net, subnet->netmask), subnet->net)) {
989		char n1buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255")];
990		int i, j;
991		for (i = 0; i < 128; i++)
992			if (subnet->netmask.iabuf[3 - (i >> 3)]
993			    & (1 << (i & 7)))
994				break;
995		for (j = 0; j < 128; j++)
996			if (scan->netmask.iabuf[3 - (j >> 3)] &
997			    (1 << (j & 7)))
998				break;
999		if (warnp) {
1000			strcpy(n1buf, piaddr(subnet->net));
1001			log_error("Warning: subnet %s/%d overlaps subnet %s/%d",
1002			      n1buf, 32 - i,
1003			      piaddr(scan->net), 32 - j);
1004		}
1005		if (i < j)
1006			return 1;
1007	}
1008	return 0;
1009}
1010
1011/* Enter a new subnet into the subnet list. */
1012void enter_subnet (subnet)
1013	struct subnet *subnet;
1014{
1015	struct subnet *scan = (struct subnet *)0;
1016	struct subnet *next = (struct subnet *)0;
1017	struct subnet *prev = (struct subnet *)0;
1018
1019	/* Check for duplicates... */
1020	if (subnets)
1021	    subnet_reference (&next, subnets, MDL);
1022	while (next) {
1023	    subnet_reference (&scan, next, MDL);
1024	    subnet_dereference (&next, MDL);
1025
1026	    /* When we find a conflict, make sure that the
1027	       subnet with the narrowest subnet mask comes
1028	       first. */
1029	    if (subnet_inner_than (subnet, scan, 1)) {
1030		if (prev) {
1031		    if (prev -> next_subnet)
1032			subnet_dereference (&prev -> next_subnet, MDL);
1033		    subnet_reference (&prev -> next_subnet, subnet, MDL);
1034		    subnet_dereference (&prev, MDL);
1035		} else {
1036		    subnet_dereference (&subnets, MDL);
1037		    subnet_reference (&subnets, subnet, MDL);
1038		}
1039		subnet_reference (&subnet -> next_subnet, scan, MDL);
1040		subnet_dereference (&scan, MDL);
1041		return;
1042	    }
1043	    subnet_reference (&prev, scan, MDL);
1044	    subnet_dereference (&scan, MDL);
1045	}
1046	if (prev)
1047		subnet_dereference (&prev, MDL);
1048
1049	/* XXX use the BSD radix tree code instead of a linked list. */
1050	if (subnets) {
1051		subnet_reference (&subnet -> next_subnet, subnets, MDL);
1052		subnet_dereference (&subnets, MDL);
1053	}
1054	subnet_reference (&subnets, subnet, MDL);
1055}
1056
1057/* Enter a new shared network into the shared network list. */
1058
1059void enter_shared_network (share)
1060	struct shared_network *share;
1061{
1062	if (shared_networks) {
1063		shared_network_reference (&share -> next,
1064					  shared_networks, MDL);
1065		shared_network_dereference (&shared_networks, MDL);
1066	}
1067	shared_network_reference (&shared_networks, share, MDL);
1068}
1069
1070void new_shared_network_interface (cfile, share, name)
1071	struct parse *cfile;
1072	struct shared_network *share;
1073	const char *name;
1074{
1075	struct interface_info *ip;
1076	isc_result_t status;
1077
1078	if (share -> interface) {
1079		parse_warn (cfile,
1080			    "A subnet or shared network can't be connected %s",
1081			    "to two interfaces.");
1082		return;
1083	}
1084
1085	for (ip = interfaces; ip; ip = ip -> next)
1086		if (!strcmp (ip -> name, name))
1087			break;
1088	if (!ip) {
1089		status = interface_allocate (&ip, MDL);
1090		if (status != ISC_R_SUCCESS)
1091			log_fatal ("new_shared_network_interface %s: %s",
1092				   name, isc_result_totext (status));
1093		if (strlen (name) > sizeof ip -> name) {
1094			memcpy (ip -> name, name, (sizeof ip -> name) - 1);
1095			ip -> name [(sizeof ip -> name) - 1] = 0;
1096		} else
1097			strcpy (ip -> name, name);
1098		if (interfaces) {
1099			interface_reference (&ip -> next, interfaces, MDL);
1100			interface_dereference (&interfaces, MDL);
1101		}
1102		interface_reference (&interfaces, ip, MDL);
1103		ip -> flags = INTERFACE_REQUESTED;
1104		/* XXX this is a reference loop. */
1105		shared_network_reference (&ip -> shared_network, share, MDL);
1106		interface_reference (&share -> interface, ip, MDL);
1107	}
1108}
1109
1110/* Enter a lease into the system.   This is called by the parser each
1111   time it reads in a new lease.   If the subnet for that lease has
1112   already been read in (usually the case), just update that lease;
1113   otherwise, allocate temporary storage for the lease and keep it around
1114   until we're done reading in the config file. */
1115
1116void enter_lease (lease)
1117	struct lease *lease;
1118{
1119	struct lease *comp = (struct lease *)0;
1120
1121	if (find_lease_by_ip_addr (&comp, lease -> ip_addr, MDL)) {
1122		if (!comp -> pool) {
1123			log_error ("undeclared lease found in database: %s",
1124				   piaddr (lease -> ip_addr));
1125		} else
1126			pool_reference (&lease -> pool, comp -> pool, MDL);
1127
1128		if (comp -> subnet)
1129			subnet_reference (&lease -> subnet,
1130					  comp -> subnet, MDL);
1131		lease_ip_hash_delete(lease_ip_addr_hash,
1132				     lease->ip_addr.iabuf, lease->ip_addr.len,
1133				     MDL);
1134		lease_dereference (&comp, MDL);
1135	}
1136
1137	/* The only way a lease can get here without a subnet is if it's in
1138	   the lease file, but not in the dhcpd.conf file.  In this case, we
1139	   *should* keep it around until it's expired, but never reallocate it
1140	   or renew it.  Currently, to maintain consistency, we are not doing
1141	   this.
1142	   XXX fix this so that the lease is kept around until it expires.
1143	   XXX this will be important in IPv6 with addresses that become
1144	   XXX non-renewable as a result of a renumbering event. */
1145
1146	if (!lease -> subnet) {
1147		log_error ("lease %s: no subnet.", piaddr (lease -> ip_addr));
1148		return;
1149	}
1150	lease_ip_hash_add(lease_ip_addr_hash, lease->ip_addr.iabuf,
1151			  lease->ip_addr.len, lease, MDL);
1152}
1153
1154/* Replace the data in an existing lease with the data in a new lease;
1155   adjust hash tables to suit, and insertion sort the lease into the
1156   list of leases by expiry time so that we can always find the oldest
1157   lease. */
1158
1159int supersede_lease (comp, lease, commit, propogate, pimmediate, from_pool)
1160	struct lease *comp, *lease;
1161	int commit;
1162	int propogate;
1163	int pimmediate;
1164	int from_pool;
1165{
1166	LEASE_STRUCT_PTR lq;
1167	struct timeval tv;
1168#if defined (FAILOVER_PROTOCOL)
1169	int do_pool_check = 0;
1170
1171	/* We must commit leases before sending updates regarding them
1172	   to failover peers.  It is, therefore, an error to set pimmediate
1173	   and not commit. */
1174	if (pimmediate && !commit)
1175		return 0;
1176#endif
1177	/* If there is no sample lease, just do the move. */
1178	if (!lease)
1179		goto just_move_it;
1180
1181	/* Static leases are not currently kept in the database... */
1182	if (lease -> flags & STATIC_LEASE)
1183		return 1;
1184
1185	/* If the existing lease hasn't expired and has a different
1186	   unique identifier or, if it doesn't have a unique
1187	   identifier, a different hardware address, then the two
1188	   leases are in conflict.  If the existing lease has a uid
1189	   and the new one doesn't, but they both have the same
1190	   hardware address, and dynamic bootp is allowed on this
1191	   lease, then we allow that, in case a dynamic BOOTP lease is
1192	   requested *after* a DHCP lease has been assigned. */
1193
1194	if (lease -> binding_state != FTS_ABANDONED &&
1195	    lease -> next_binding_state != FTS_ABANDONED &&
1196	    comp -> binding_state == FTS_ACTIVE &&
1197	    (((comp -> uid && lease -> uid) &&
1198	      (comp -> uid_len != lease -> uid_len ||
1199	       memcmp (comp -> uid, lease -> uid, comp -> uid_len))) ||
1200	     (!comp -> uid &&
1201	      ((comp -> hardware_addr.hlen !=
1202		lease -> hardware_addr.hlen) ||
1203	       memcmp (comp -> hardware_addr.hbuf,
1204		       lease -> hardware_addr.hbuf,
1205		       comp -> hardware_addr.hlen))))) {
1206		log_error ("Lease conflict at %s",
1207		      piaddr (comp -> ip_addr));
1208	}
1209
1210	/* If there's a Unique ID, dissociate it from the hash
1211	   table and free it if necessary. */
1212	if (comp->uid) {
1213		uid_hash_delete(comp);
1214		if (comp->uid != comp->uid_buf) {
1215			dfree(comp->uid, MDL);
1216			comp->uid_max = 0;
1217			comp->uid_len = 0;
1218		}
1219		comp -> uid = (unsigned char *)0;
1220	}
1221
1222	/* If there's a hardware address, remove the lease from its
1223	 * old position in the hash bucket's ordered list.
1224	 */
1225	if (comp->hardware_addr.hlen)
1226		hw_hash_delete(comp);
1227
1228	/* If the lease has been billed to a class, remove the billing. */
1229	if (comp -> billing_class != lease -> billing_class) {
1230		if (comp->billing_class)
1231			unbill_class(comp);
1232		if (lease -> billing_class)
1233			bill_class (comp, lease -> billing_class);
1234	}
1235
1236	/* Copy the data files, but not the linkages. */
1237	comp -> starts = lease -> starts;
1238	if (lease -> uid) {
1239		if (lease -> uid_len <= sizeof (lease -> uid_buf)) {
1240			memcpy (comp -> uid_buf,
1241				lease -> uid, lease -> uid_len);
1242			comp -> uid = &comp -> uid_buf [0];
1243			comp -> uid_max = sizeof comp -> uid_buf;
1244			comp -> uid_len = lease -> uid_len;
1245		} else if (lease -> uid != &lease -> uid_buf [0]) {
1246			comp -> uid = lease -> uid;
1247			comp -> uid_max = lease -> uid_max;
1248			lease -> uid = (unsigned char *)0;
1249			lease -> uid_max = 0;
1250			comp -> uid_len = lease -> uid_len;
1251			lease -> uid_len = 0;
1252		} else {
1253			log_fatal ("corrupt lease uid."); /* XXX */
1254		}
1255	} else {
1256		comp -> uid = (unsigned char *)0;
1257		comp -> uid_len = comp -> uid_max = 0;
1258	}
1259	if (comp -> host)
1260		host_dereference (&comp -> host, MDL);
1261	host_reference (&comp -> host, lease -> host, MDL);
1262	comp -> hardware_addr = lease -> hardware_addr;
1263	if (comp -> scope)
1264		binding_scope_dereference (&comp -> scope, MDL);
1265	if (lease -> scope) {
1266		binding_scope_reference (&comp -> scope, lease -> scope, MDL);
1267		binding_scope_dereference (&lease -> scope, MDL);
1268	}
1269
1270	if (comp -> agent_options)
1271		option_chain_head_dereference (&comp -> agent_options, MDL);
1272	if (lease -> agent_options) {
1273		/* Only retain the agent options if the lease is still
1274		   affirmatively associated with a client. */
1275		if (lease -> next_binding_state == FTS_ACTIVE ||
1276		    lease -> next_binding_state == FTS_EXPIRED)
1277			option_chain_head_reference (&comp -> agent_options,
1278						     lease -> agent_options,
1279						     MDL);
1280		option_chain_head_dereference (&lease -> agent_options, MDL);
1281	}
1282
1283	/* Record the hostname information in the lease. */
1284	if (comp -> client_hostname)
1285		dfree (comp -> client_hostname, MDL);
1286	comp -> client_hostname = lease -> client_hostname;
1287	lease -> client_hostname = (char *)0;
1288
1289	if (lease->on_star.on_expiry) {
1290		if (comp->on_star.on_expiry)
1291			executable_statement_dereference
1292				(&comp->on_star.on_expiry, MDL);
1293		executable_statement_reference (&comp->on_star.on_expiry,
1294						lease->on_star.on_expiry,
1295						MDL);
1296	}
1297	if (lease->on_star.on_commit) {
1298		if (comp->on_star.on_commit)
1299			executable_statement_dereference
1300				(&comp->on_star.on_commit, MDL);
1301		executable_statement_reference (&comp->on_star.on_commit,
1302						lease->on_star.on_commit,
1303						MDL);
1304	}
1305	if (lease->on_star.on_release) {
1306		if (comp->on_star.on_release)
1307			executable_statement_dereference
1308				(&comp->on_star.on_release, MDL);
1309		executable_statement_reference (&comp->on_star.on_release,
1310						lease->on_star.on_release,
1311						MDL);
1312	}
1313
1314	/* Record the lease in the uid hash if necessary. */
1315	if (comp->uid)
1316		uid_hash_add(comp);
1317
1318	/* Record it in the hardware address hash if necessary. */
1319	if (comp->hardware_addr.hlen)
1320		hw_hash_add(comp);
1321
1322	comp->cltt = lease->cltt;
1323#if defined (FAILOVER_PROTOCOL)
1324	comp->tstp = lease->tstp;
1325	comp->tsfp = lease->tsfp;
1326	comp->atsfp = lease->atsfp;
1327#endif /* FAILOVER_PROTOCOL */
1328	comp->ends = lease->ends;
1329	comp->next_binding_state = lease->next_binding_state;
1330
1331	/*
1332	 * If we have a control block pointer copy it in.
1333	 * We don't zero out an older ponter as it is still
1334	 * in use.  We shouldn't need to overwrite an
1335	 * old pointer with a new one as the old transaction
1336	 * should have been cancelled before getting here.
1337	 */
1338	if (lease->ddns_cb != NULL)
1339		comp->ddns_cb = lease->ddns_cb;
1340
1341      just_move_it:
1342#if defined (FAILOVER_PROTOCOL)
1343	/*
1344	 * Atsfp should be cleared upon any state change that implies
1345	 * propagation whether supersede_lease was given a copy lease
1346	 * structure or not (often from the pool_timer()).
1347	 */
1348	if (propogate)
1349		comp->atsfp = 0;
1350#endif /* FAILOVER_PROTOCOL */
1351
1352	if (!comp -> pool) {
1353		log_error ("Supersede_lease: lease %s with no pool.",
1354			   piaddr (comp -> ip_addr));
1355		return 0;
1356	}
1357
1358	/* Figure out which queue it's on. */
1359	switch (comp -> binding_state) {
1360	      case FTS_FREE:
1361		if (comp->flags & RESERVED_LEASE)
1362			lq = &comp->pool->reserved;
1363		else {
1364			lq = &comp->pool->free;
1365			comp->pool->free_leases--;
1366		}
1367
1368#if defined(FAILOVER_PROTOCOL)
1369		do_pool_check = 1;
1370#endif
1371		break;
1372
1373	      case FTS_ACTIVE:
1374		lq = &comp -> pool -> active;
1375		break;
1376
1377	      case FTS_EXPIRED:
1378	      case FTS_RELEASED:
1379	      case FTS_RESET:
1380		lq = &comp -> pool -> expired;
1381		break;
1382
1383	      case FTS_ABANDONED:
1384		lq = &comp -> pool -> abandoned;
1385		break;
1386
1387	      case FTS_BACKUP:
1388		if (comp->flags & RESERVED_LEASE)
1389			lq = &comp->pool->reserved;
1390		else {
1391			lq = &comp->pool->backup;
1392			comp->pool->backup_leases--;
1393		}
1394
1395#if defined(FAILOVER_PROTOCOL)
1396		do_pool_check = 1;
1397#endif
1398		break;
1399
1400	      default:
1401		log_error ("Lease with bogus binding state: %d",
1402			   comp -> binding_state);
1403#if defined (BINDING_STATE_DEBUG)
1404		abort ();
1405#endif
1406		return 0;
1407	}
1408
1409	/* Remove the lease from its current place in its current
1410	   timer sequence. */
1411	LEASE_REMOVEP(lq, comp);
1412
1413	/* Now that we've done the flag-affected queue removal
1414	 * we can update the new lease's flags, if there's an
1415	 * existing lease */
1416	if (lease) {
1417		comp->flags = ((lease->flags & ~PERSISTENT_FLAGS) |
1418				(comp->flags & ~EPHEMERAL_FLAGS));
1419	}
1420
1421	/* Make the state transition. */
1422	if (commit || !pimmediate)
1423		make_binding_state_transition (comp);
1424
1425	/* Put the lease back on the appropriate queue.    If the lease
1426	   is corrupt (as detected by lease_enqueue), don't go any farther. */
1427	if (!lease_enqueue (comp))
1428		return 0;
1429
1430	/* If this is the next lease that will timeout on the pool,
1431	   zap the old timeout and set the timeout on this pool to the
1432	   time that the lease's next event will happen.
1433
1434	   We do not actually set the timeout unless commit is true -
1435	   we don't want to thrash the timer queue when reading the
1436	   lease database.  Instead, the database code calls the
1437	   expiry event on each pool after reading in the lease file,
1438	   and the expiry code sets the timer if there's anything left
1439	   to expire after it's run any outstanding expiry events on
1440	   the pool. */
1441	if ((commit || !pimmediate) &&
1442	    comp -> sort_time != MIN_TIME &&
1443	    comp -> sort_time > cur_time &&
1444	    (comp -> sort_time < comp -> pool -> next_event_time ||
1445	     comp -> pool -> next_event_time == MIN_TIME)) {
1446		comp -> pool -> next_event_time = comp -> sort_time;
1447		tv . tv_sec = comp -> pool -> next_event_time;
1448		tv . tv_usec = 0;
1449		add_timeout (&tv,
1450			     pool_timer, comp -> pool,
1451			     (tvref_t)pool_reference,
1452			     (tvunref_t)pool_dereference);
1453	}
1454
1455	if (commit) {
1456#if defined(FAILOVER_PROTOCOL)
1457		/*
1458		 * If commit and propogate are set, then we can save a
1459		 * possible fsync later in BNDUPD socket transmission by
1460		 * stepping the rewind state forward to the new state, in
1461		 * case it has changed.  This is only worth doing if the
1462		 * failover connection is currently connected, as in this
1463		 * case it is likely we will be transmitting to the peer very
1464		 * shortly.
1465		 */
1466		if (propogate && (comp->pool->failover_peer != NULL) &&
1467		    ((comp->pool->failover_peer->service_state ==
1468							    cooperating) ||
1469		     (comp->pool->failover_peer->service_state ==
1470							    not_responding)))
1471			comp->rewind_binding_state = comp->binding_state;
1472#endif
1473
1474		if (!write_lease (comp))
1475			return 0;
1476		if ((server_starting & SS_NOSYNC) == 0) {
1477			if (!commit_leases ())
1478				return 0;
1479		}
1480	}
1481
1482#if defined (FAILOVER_PROTOCOL)
1483	if (propogate) {
1484		comp -> desired_binding_state = comp -> binding_state;
1485		if (!dhcp_failover_queue_update (comp, pimmediate))
1486			return 0;
1487	}
1488	if (do_pool_check && comp->pool->failover_peer)
1489		dhcp_failover_pool_check(comp->pool);
1490#endif
1491
1492	/* If the current binding state has already expired and we haven't
1493	 * been called from pool_timer, do an expiry event right now.
1494	 */
1495	/* XXX At some point we should optimize this so that we don't
1496	   XXX write the lease twice, but this is a safe way to fix the
1497	   XXX problem for 3.0 (I hope!). */
1498	if ((from_pool == 0) &&
1499	    (commit || !pimmediate) &&
1500	    (comp->sort_time < cur_time) &&
1501	    (comp->next_binding_state != comp->binding_state))
1502		pool_timer(comp->pool);
1503
1504	return 1;
1505}
1506
1507void make_binding_state_transition (struct lease *lease)
1508{
1509
1510#if defined (FAILOVER_PROTOCOL)
1511	dhcp_failover_state_t *peer;
1512
1513	if (lease -> pool && lease -> pool -> failover_peer)
1514		peer = lease -> pool -> failover_peer;
1515	else
1516		peer = (dhcp_failover_state_t *)0;
1517#endif
1518
1519	/* If the lease was active and is now no longer active, but isn't
1520	   released, then it just expired, so do the expiry event. */
1521	if (lease -> next_binding_state != lease -> binding_state &&
1522	    ((
1523#if defined (FAILOVER_PROTOCOL)
1524		    peer &&
1525		    (lease->binding_state == FTS_EXPIRED ||
1526		     lease->binding_state == FTS_ACTIVE) &&
1527		    (lease->next_binding_state == FTS_FREE ||
1528		     lease->next_binding_state == FTS_BACKUP)) ||
1529	     (!peer &&
1530#endif
1531	      lease -> binding_state == FTS_ACTIVE &&
1532	      lease -> next_binding_state != FTS_RELEASED))) {
1533#if defined (NSUPDATE)
1534		(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
1535#endif
1536		if (lease->on_star.on_expiry) {
1537			execute_statements(NULL, NULL, lease,
1538					   NULL, NULL, NULL,
1539					   &lease->scope,
1540					   lease->on_star.on_expiry,
1541					   NULL);
1542			if (lease->on_star.on_expiry)
1543				executable_statement_dereference
1544					(&lease->on_star.on_expiry, MDL);
1545		}
1546
1547		/* No sense releasing a lease after it's expired. */
1548		if (lease->on_star.on_release)
1549			executable_statement_dereference
1550				(&lease->on_star.on_release, MDL);
1551		/* Get rid of client-specific bindings that are only
1552		   correct when the lease is active. */
1553		if (lease->billing_class)
1554			unbill_class(lease);
1555		if (lease -> agent_options)
1556			option_chain_head_dereference (&lease -> agent_options,
1557						       MDL);
1558		if (lease -> client_hostname) {
1559			dfree (lease -> client_hostname, MDL);
1560			lease -> client_hostname = (char *)0;
1561		}
1562		if (lease -> host)
1563			host_dereference (&lease -> host, MDL);
1564
1565		/* Send the expiry time to the peer. */
1566		lease -> tstp = lease -> ends;
1567	}
1568
1569	/* If the lease was active and is now released, do the release
1570	   event. */
1571	if (lease -> next_binding_state != lease -> binding_state &&
1572	    ((
1573#if defined (FAILOVER_PROTOCOL)
1574		    peer &&
1575		    lease -> binding_state == FTS_RELEASED &&
1576		    (lease -> next_binding_state == FTS_FREE ||
1577		     lease -> next_binding_state == FTS_BACKUP)) ||
1578	     (!peer &&
1579#endif
1580	      lease -> binding_state == FTS_ACTIVE &&
1581	      lease -> next_binding_state == FTS_RELEASED))) {
1582#if defined (NSUPDATE)
1583		/*
1584		 * Note: ddns_removals() is also iterated when the lease
1585		 * enters state 'released' in 'release_lease()'.  The below
1586		 * is caught when a peer receives a BNDUPD from a failover
1587		 * peer; it may not have received the client's release (it
1588		 * may have been offline).
1589		 *
1590		 * We could remove the call from release_lease() because
1591		 * it will also catch here on the originating server after the
1592		 * peer acknowledges the state change.  However, there could
1593		 * be many hours inbetween, and in this case we /know/ the
1594		 * client is no longer using the lease when we receive the
1595		 * release message.  This is not true of expiry, where the
1596		 * peer may have extended the lease.
1597		 */
1598		(void) ddns_removals(lease, NULL, NULL, ISC_TRUE);
1599#endif
1600		if (lease->on_star.on_release) {
1601			execute_statements(NULL, NULL, lease,
1602					   NULL, NULL, NULL,
1603					   &lease->scope,
1604					   lease->on_star.on_release,
1605					   NULL);
1606			executable_statement_dereference
1607				(&lease->on_star.on_release, MDL);
1608		}
1609
1610		/* A released lease can't expire. */
1611		if (lease->on_star.on_expiry)
1612			executable_statement_dereference
1613				(&lease->on_star.on_expiry, MDL);
1614
1615		/* Get rid of client-specific bindings that are only
1616		   correct when the lease is active. */
1617		if (lease->billing_class)
1618			unbill_class(lease);
1619		if (lease -> agent_options)
1620			option_chain_head_dereference (&lease -> agent_options,
1621						       MDL);
1622		if (lease -> client_hostname) {
1623			dfree (lease -> client_hostname, MDL);
1624			lease -> client_hostname = (char *)0;
1625		}
1626		if (lease -> host)
1627			host_dereference (&lease -> host, MDL);
1628
1629		/* Send the release time (should be == cur_time) to the
1630		   peer. */
1631		lease -> tstp = lease -> ends;
1632	}
1633
1634#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1635	log_debug ("lease %s moves from %s to %s",
1636		   piaddr (lease -> ip_addr),
1637		   binding_state_print (lease -> binding_state),
1638		   binding_state_print (lease -> next_binding_state));
1639#endif
1640
1641	lease -> binding_state = lease -> next_binding_state;
1642	switch (lease -> binding_state) {
1643	      case FTS_ACTIVE:
1644#if defined (FAILOVER_PROTOCOL)
1645		if (lease -> pool && lease -> pool -> failover_peer)
1646			lease -> next_binding_state = FTS_EXPIRED;
1647		else
1648#endif
1649			lease -> next_binding_state = FTS_FREE;
1650		break;
1651
1652	      case FTS_EXPIRED:
1653	      case FTS_RELEASED:
1654	      case FTS_ABANDONED:
1655	      case FTS_RESET:
1656		lease->next_binding_state = FTS_FREE;
1657#if defined(FAILOVER_PROTOCOL)
1658		/* If we are not in partner_down, leases don't go from
1659		   EXPIRED to FREE on a timeout - only on an update.
1660		   If we're in partner_down, they expire at mclt past
1661		   the time we entered partner_down. */
1662		if ((lease->pool != NULL) &&
1663		    (lease->pool->failover_peer != NULL) &&
1664		    (lease->pool->failover_peer->me.state == partner_down))
1665			lease->tsfp =
1666			    (lease->pool->failover_peer->me.stos +
1667			     lease->pool->failover_peer->mclt);
1668#endif /* FAILOVER_PROTOCOL */
1669		break;
1670
1671	      case FTS_FREE:
1672	      case FTS_BACKUP:
1673		lease -> next_binding_state = lease -> binding_state;
1674		break;
1675	}
1676#if defined (DEBUG_LEASE_STATE_TRANSITIONS)
1677	log_debug ("lease %s: next binding state %s",
1678		   piaddr (lease -> ip_addr),
1679		   binding_state_print (lease -> next_binding_state));
1680#endif
1681}
1682
1683/* Copy the contents of one lease into another, correctly maintaining
1684   reference counts. */
1685int lease_copy (struct lease **lp,
1686		struct lease *lease, const char *file, int line)
1687{
1688	struct lease *lt = (struct lease *)0;
1689	isc_result_t status;
1690
1691	status = lease_allocate (&lt, MDL);
1692	if (status != ISC_R_SUCCESS)
1693		return 0;
1694
1695	lt -> ip_addr = lease -> ip_addr;
1696	lt -> starts = lease -> starts;
1697	lt -> ends = lease -> ends;
1698	lt -> uid_len = lease -> uid_len;
1699	lt -> uid_max = lease -> uid_max;
1700	if (lease -> uid == lease -> uid_buf) {
1701		lt -> uid = lt -> uid_buf;
1702		memcpy (lt -> uid_buf, lease -> uid_buf, sizeof lt -> uid_buf);
1703	} else if (!lease -> uid_max) {
1704		lt -> uid = (unsigned char *)0;
1705	} else {
1706		lt -> uid = dmalloc (lt -> uid_max, MDL);
1707		if (!lt -> uid) {
1708			lease_dereference (&lt, MDL);
1709			return 0;
1710		}
1711		memcpy (lt -> uid, lease -> uid, lease -> uid_max);
1712	}
1713	if (lease -> client_hostname) {
1714		lt -> client_hostname =
1715			dmalloc (strlen (lease -> client_hostname) + 1, MDL);
1716		if (!lt -> client_hostname) {
1717			lease_dereference (&lt, MDL);
1718			return 0;
1719		}
1720		strcpy (lt -> client_hostname, lease -> client_hostname);
1721	}
1722	if (lease -> scope)
1723		binding_scope_reference (&lt -> scope, lease -> scope, MDL);
1724	if (lease -> agent_options)
1725		option_chain_head_reference (&lt -> agent_options,
1726					     lease -> agent_options, MDL);
1727	host_reference (&lt -> host, lease -> host, file, line);
1728	subnet_reference (&lt -> subnet, lease -> subnet, file, line);
1729	pool_reference (&lt -> pool, lease -> pool, file, line);
1730	class_reference (&lt -> billing_class,
1731			 lease -> billing_class, file, line);
1732	lt -> hardware_addr = lease -> hardware_addr;
1733	if (lease->on_star.on_expiry)
1734		executable_statement_reference (&lt->on_star.on_expiry,
1735						lease->on_star.on_expiry,
1736						file, line);
1737	if (lease->on_star.on_commit)
1738		executable_statement_reference (&lt->on_star.on_commit,
1739						lease->on_star.on_commit,
1740						file, line);
1741	if (lease->on_star.on_release)
1742		executable_statement_reference (&lt->on_star.on_release,
1743						lease->on_star.on_release,
1744						file, line);
1745	lt->flags = lease->flags;
1746	lt->tstp = lease->tstp;
1747	lt->tsfp = lease->tsfp;
1748	lt->atsfp = lease->atsfp;
1749	lt->cltt = lease -> cltt;
1750	lt->binding_state = lease->binding_state;
1751	lt->next_binding_state = lease->next_binding_state;
1752	lt->rewind_binding_state = lease->rewind_binding_state;
1753	status = lease_reference(lp, lt, file, line);
1754	lease_dereference(&lt, MDL);
1755	return status == ISC_R_SUCCESS;
1756}
1757
1758/* Release the specified lease and re-hash it as appropriate. */
1759void release_lease (lease, packet)
1760	struct lease *lease;
1761	struct packet *packet;
1762{
1763	/* If there are statements to execute when the lease is
1764	   released, execute them. */
1765#if defined (NSUPDATE)
1766	(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1767#endif
1768	if (lease->on_star.on_release) {
1769		execute_statements (NULL, packet, lease,
1770				    NULL, packet->options,
1771				    NULL, &lease->scope,
1772				    lease->on_star.on_release, NULL);
1773		if (lease->on_star.on_release)
1774			executable_statement_dereference
1775				(&lease->on_star.on_release, MDL);
1776	}
1777
1778	/* We do either the on_release or the on_expiry events, but
1779	   not both (it's possible that they could be the same,
1780	   in any case). */
1781	if (lease->on_star.on_expiry)
1782		executable_statement_dereference
1783			(&lease->on_star.on_expiry, MDL);
1784
1785	if (lease -> binding_state != FTS_FREE &&
1786	    lease -> binding_state != FTS_BACKUP &&
1787	    lease -> binding_state != FTS_RELEASED &&
1788	    lease -> binding_state != FTS_EXPIRED &&
1789	    lease -> binding_state != FTS_RESET) {
1790		if (lease->on_star.on_commit)
1791			executable_statement_dereference
1792				(&lease->on_star.on_commit, MDL);
1793
1794		/* Blow away any bindings. */
1795		if (lease -> scope)
1796			binding_scope_dereference (&lease -> scope, MDL);
1797
1798		/* Set sort times to the present. */
1799		lease -> ends = cur_time;
1800		/* Lower layers of muckery set tstp to ->ends.  But we send
1801		 * protocol messages before this.  So it is best to set
1802		 * tstp now anyway.
1803		 */
1804		lease->tstp = cur_time;
1805#if defined (FAILOVER_PROTOCOL)
1806		if (lease -> pool && lease -> pool -> failover_peer) {
1807			dhcp_failover_state_t *peer = NULL;
1808
1809			if (lease->pool != NULL)
1810				peer = lease->pool->failover_peer;
1811
1812			if ((peer->service_state == not_cooperating) &&
1813			    (((peer->i_am == primary) &&
1814			      (lease->rewind_binding_state == FTS_FREE)) ||
1815			     ((peer->i_am == secondary) &&
1816			      (lease->rewind_binding_state == FTS_BACKUP)))) {
1817				lease->next_binding_state =
1818						  lease->rewind_binding_state;
1819			} else
1820				lease -> next_binding_state = FTS_RELEASED;
1821		} else {
1822			lease -> next_binding_state = FTS_FREE;
1823		}
1824#else
1825		lease -> next_binding_state = FTS_FREE;
1826#endif
1827		supersede_lease(lease, NULL, 1, 1, 1, 0);
1828	}
1829}
1830
1831/* Abandon the specified lease (set its timeout to infinity and its
1832   particulars to zero, and re-hash it as appropriate. */
1833
1834void abandon_lease (lease, message)
1835	struct lease *lease;
1836	const char *message;
1837{
1838	struct lease *lt = NULL;
1839#if defined (NSUPDATE)
1840	(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1841#endif
1842
1843	if (!lease_copy(&lt, lease, MDL)) {
1844		return;
1845	}
1846
1847	if (lt->scope) {
1848		binding_scope_dereference(&lt->scope, MDL);
1849	}
1850
1851	/* Calculate the abandone expiry time.  If it wraps,
1852 	 * use the maximum expiry time. */
1853	lt->ends = cur_time + abandon_lease_time;
1854	if (lt->ends < cur_time || lt->ends > MAX_TIME) {
1855		lt->ends = MAX_TIME;
1856	}
1857
1858	lt->next_binding_state = FTS_ABANDONED;
1859
1860	log_error ("Abandoning IP address %s: %s", piaddr(lease->ip_addr),
1861                    message);
1862	lt->hardware_addr.hlen = 0;
1863	if (lt->uid && lt->uid != lt->uid_buf) {
1864		dfree(lt->uid, MDL);
1865	}
1866
1867	lt->uid = NULL;
1868	lt->uid_len = 0;
1869	lt->uid_max = 0;
1870	supersede_lease(lease, lt, 1, 1, 1, 0);
1871	lease_dereference(&lt, MDL);
1872}
1873
1874#if 0
1875/*
1876 * This doesn't appear to be in use for anything anymore.
1877 * I'm ifdeffing it now and if there are no complaints in
1878 * the future it will be removed.
1879 * SAR
1880 */
1881
1882/* Abandon the specified lease (set its timeout to infinity and its
1883   particulars to zero, and re-hash it as appropriate. */
1884
1885void dissociate_lease (lease)
1886	struct lease *lease;
1887{
1888	struct lease *lt = (struct lease *)0;
1889#if defined (NSUPDATE)
1890	(void) ddns_removals(lease, NULL, NULL, ISC_FALSE);
1891#endif
1892
1893	if (!lease_copy (&lt, lease, MDL))
1894		return;
1895
1896#if defined (FAILOVER_PROTOCOL)
1897	if (lease -> pool && lease -> pool -> failover_peer) {
1898		lt -> next_binding_state = FTS_RESET;
1899	} else {
1900		lt -> next_binding_state = FTS_FREE;
1901	}
1902#else
1903	lt -> next_binding_state = FTS_FREE;
1904#endif
1905	lt -> ends = cur_time; /* XXX */
1906	lt -> hardware_addr.hlen = 0;
1907	if (lt -> uid && lt -> uid != lt -> uid_buf)
1908		dfree (lt -> uid, MDL);
1909	lt -> uid = (unsigned char *)0;
1910	lt -> uid_len = 0;
1911	lt -> uid_max = 0;
1912	supersede_lease (lease, lt, 1, 1, 1, 0);
1913	lease_dereference (&lt, MDL);
1914}
1915#endif
1916
1917/* Timer called when a lease in a particular pool expires. */
1918void pool_timer (vpool)
1919	void *vpool;
1920{
1921	struct pool *pool;
1922	struct lease *next = NULL;
1923	struct lease *lease = NULL;
1924	struct lease *ltemp = NULL;
1925#define FREE_LEASES 0
1926#define ACTIVE_LEASES 1
1927#define EXPIRED_LEASES 2
1928#define ABANDONED_LEASES 3
1929#define BACKUP_LEASES 4
1930#define RESERVED_LEASES 5
1931	LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
1932	TIME next_expiry = MAX_TIME;
1933	int i;
1934	struct timeval tv;
1935
1936	pool = (struct pool *)vpool;
1937
1938	lptr[FREE_LEASES] = &pool->free;
1939	lptr[ACTIVE_LEASES] = &pool->active;
1940	lptr[EXPIRED_LEASES] = &pool->expired;
1941	lptr[ABANDONED_LEASES] = &pool->abandoned;
1942	lptr[BACKUP_LEASES] = &pool->backup;
1943	lptr[RESERVED_LEASES] = &pool->reserved;
1944
1945	for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
1946		/* If there's nothing on the queue, skip it. */
1947		if (!(LEASE_NOT_EMPTYP(lptr[i])))
1948			continue;
1949
1950#if defined (FAILOVER_PROTOCOL)
1951		if (pool->failover_peer &&
1952		    pool->failover_peer->me.state != partner_down) {
1953			/*
1954			 * Normally the secondary doesn't initiate expiration
1955			 * events (unless in partner-down), but rather relies
1956			 * on the primary to expire the lease.  However, when
1957			 * disconnected from its peer, the server is allowed to
1958			 * rewind a lease to the previous state that the peer
1959			 * would have recorded it.  This means there may be
1960			 * opportunities for active->free or active->backup
1961			 * expirations while out of contact.
1962			 *
1963			 * Q: Should we limit this expiration to
1964			 *    comms-interrupt rather than not-normal?
1965			 */
1966			if ((i == ACTIVE_LEASES) &&
1967			    (pool->failover_peer->i_am == secondary) &&
1968			    (pool->failover_peer->me.state == normal))
1969				continue;
1970
1971			/* Leases in an expired state don't move to
1972			   free because of a timeout unless we're in
1973			   partner_down. */
1974			if (i == EXPIRED_LEASES)
1975				continue;
1976		}
1977#endif
1978		lease_reference(&lease, LEASE_GET_FIRSTP(lptr[i]), MDL);
1979
1980		while (lease) {
1981			/* Remember the next lease in the list. */
1982			if (next)
1983				lease_dereference(&next, MDL);
1984			ltemp = LEASE_GET_NEXTP(lptr[i], lease);
1985			if (ltemp)
1986				lease_reference(&next, ltemp, MDL);
1987
1988			/* If we've run out of things to expire on this list,
1989			   stop. */
1990			if (lease->sort_time > cur_time) {
1991				if (lease->sort_time < next_expiry)
1992					next_expiry = lease->sort_time;
1993				break;
1994			}
1995
1996			/* If there is a pending state change, and
1997			   this lease has gotten to the time when the
1998			   state change should happen, just call
1999			   supersede_lease on it to make the change
2000			   happen. */
2001			if (lease->next_binding_state != lease->binding_state)
2002			{
2003#if defined(FAILOVER_PROTOCOL)
2004				dhcp_failover_state_t *peer = NULL;
2005
2006				if (lease->pool != NULL)
2007					peer = lease->pool->failover_peer;
2008
2009				/* Can we rewind the lease to a free state? */
2010				if (peer != NULL &&
2011				    peer->service_state == not_cooperating &&
2012				    lease->next_binding_state == FTS_EXPIRED &&
2013				    ((peer->i_am == primary &&
2014				      lease->rewind_binding_state == FTS_FREE)
2015					||
2016				     (peer->i_am == secondary &&
2017				      lease->rewind_binding_state ==
2018								FTS_BACKUP)))
2019					lease->next_binding_state =
2020						   lease->rewind_binding_state;
2021#endif
2022				supersede_lease(lease, NULL, 1, 1, 1, 1);
2023			}
2024
2025			lease_dereference(&lease, MDL);
2026			if (next)
2027				lease_reference(&lease, next, MDL);
2028		}
2029		if (next)
2030			lease_dereference(&next, MDL);
2031		if (lease)
2032			lease_dereference(&lease, MDL);
2033	}
2034
2035	/* If we found something to expire and its expiration time
2036	 * is either less than the current expiration time or the
2037	 * current expiration time is already expired update the
2038	 * timer.
2039	 */
2040	if ((next_expiry != MAX_TIME) &&
2041	    ((pool->next_event_time > next_expiry) ||
2042	     (pool->next_event_time <= cur_time))) {
2043		pool->next_event_time = next_expiry;
2044		tv.tv_sec = pool->next_event_time;
2045		tv.tv_usec = 0;
2046		add_timeout (&tv, pool_timer, pool,
2047			     (tvref_t)pool_reference,
2048			     (tvunref_t)pool_dereference);
2049	} else
2050		pool->next_event_time = MIN_TIME;
2051
2052}
2053
2054/* Locate the lease associated with a given IP address... */
2055
2056int find_lease_by_ip_addr (struct lease **lp, struct iaddr addr,
2057			   const char *file, int line)
2058{
2059	return lease_ip_hash_lookup(lp, lease_ip_addr_hash, addr.iabuf,
2060				    addr.len, file, line);
2061}
2062
2063int find_lease_by_uid (struct lease **lp, const unsigned char *uid,
2064		       unsigned len, const char *file, int line)
2065{
2066	if (len == 0)
2067		return 0;
2068	return lease_id_hash_lookup (lp, lease_uid_hash, uid, len, file, line);
2069}
2070
2071int find_lease_by_hw_addr (struct lease **lp,
2072			   const unsigned char *hwaddr, unsigned hwlen,
2073			   const char *file, int line)
2074{
2075	if (hwlen == 0)
2076		return (0);
2077
2078	/*
2079	 * If it's an infiniband address don't bother
2080	 * as we don't have a useful address to hash.
2081	 */
2082	if ((hwlen == 1) && (hwaddr[0] == HTYPE_INFINIBAND))
2083		return (0);
2084
2085	return (lease_id_hash_lookup(lp, lease_hw_addr_hash, hwaddr, hwlen,
2086				     file, line));
2087}
2088
2089/* If the lease is preferred over the candidate, return truth.  The
2090 * 'cand' and 'lease' names are retained to read more clearly against
2091 * the 'uid_hash_add' and 'hw_hash_add' functions (this is common logic
2092 * to those two functions).
2093 *
2094 * 1) ACTIVE leases are preferred.  The active lease with
2095 *    the longest lifetime is preferred over shortest.
2096 * 2) "transitional states" are next, this time with the
2097 *    most recent CLTT.
2098 * 3) free/backup/etc states are next, again with CLTT.  In truth we
2099 *    should never see reset leases for this.
2100 * 4) Abandoned leases are always dead last.
2101 */
2102static isc_boolean_t
2103client_lease_preferred(struct lease *cand, struct lease *lease)
2104{
2105	if (cand->binding_state == FTS_ACTIVE) {
2106		if (lease->binding_state == FTS_ACTIVE &&
2107		    lease->ends >= cand->ends)
2108			return ISC_TRUE;
2109	} else if (cand->binding_state == FTS_EXPIRED ||
2110		   cand->binding_state == FTS_RELEASED) {
2111		if (lease->binding_state == FTS_ACTIVE)
2112			return ISC_TRUE;
2113
2114		if ((lease->binding_state == FTS_EXPIRED ||
2115		     lease->binding_state == FTS_RELEASED) &&
2116		    lease->cltt >= cand->cltt)
2117			return ISC_TRUE;
2118	} else if (cand->binding_state != FTS_ABANDONED) {
2119		if (lease->binding_state == FTS_ACTIVE ||
2120		    lease->binding_state == FTS_EXPIRED ||
2121		    lease->binding_state == FTS_RELEASED)
2122			return ISC_TRUE;
2123
2124		if (lease->binding_state != FTS_ABANDONED &&
2125		    lease->cltt >= cand->cltt)
2126			return ISC_TRUE;
2127	} else /* (cand->binding_state == FTS_ABANDONED) */ {
2128		if (lease->binding_state != FTS_ABANDONED ||
2129		    lease->cltt >= cand->cltt)
2130			return ISC_TRUE;
2131	}
2132
2133	return ISC_FALSE;
2134}
2135
2136/* Add the specified lease to the uid hash. */
2137void
2138uid_hash_add(struct lease *lease)
2139{
2140	struct lease *head = NULL;
2141	struct lease *cand = NULL;
2142	struct lease *prev = NULL;
2143	struct lease *next = NULL;
2144
2145	/* If it's not in the hash, just add it. */
2146	if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL))
2147		lease_id_hash_add(lease_uid_hash, lease->uid, lease->uid_len,
2148				  lease, MDL);
2149	else {
2150		/* Otherwise, insert it into the list in order of its
2151		 * preference for "resuming allocation to the client."
2152		 *
2153		 * Because we don't have control of the hash bucket index
2154		 * directly, we have to remove and re-insert the client
2155		 * id into the hash if we're inserting onto the head.
2156		 */
2157		lease_reference(&cand, head, MDL);
2158		while (cand != NULL) {
2159			if (client_lease_preferred(cand, lease))
2160				break;
2161
2162			if (prev != NULL)
2163				lease_dereference(&prev, MDL);
2164			lease_reference(&prev, cand, MDL);
2165
2166			if (cand->n_uid != NULL)
2167				lease_reference(&next, cand->n_uid, MDL);
2168
2169			lease_dereference(&cand, MDL);
2170
2171			if (next != NULL) {
2172				lease_reference(&cand, next, MDL);
2173				lease_dereference(&next, MDL);
2174			}
2175		}
2176
2177		/* If we want to insert 'before cand', and prev is NULL,
2178		 * then it was the head of the list.  Assume that position.
2179		 */
2180		if (prev == NULL) {
2181			lease_reference(&lease->n_uid, head, MDL);
2182			lease_id_hash_delete(lease_uid_hash, lease->uid,
2183					     lease->uid_len, MDL);
2184			lease_id_hash_add(lease_uid_hash, lease->uid,
2185					  lease->uid_len, lease, MDL);
2186		} else /* (prev != NULL) */ {
2187			if(prev->n_uid != NULL) {
2188				lease_reference(&lease->n_uid, prev->n_uid,
2189						MDL);
2190				lease_dereference(&prev->n_uid, MDL);
2191			}
2192			lease_reference(&prev->n_uid, lease, MDL);
2193
2194			lease_dereference(&prev, MDL);
2195		}
2196
2197		if (cand != NULL)
2198			lease_dereference(&cand, MDL);
2199		lease_dereference(&head, MDL);
2200	}
2201}
2202
2203/* Delete the specified lease from the uid hash. */
2204
2205void uid_hash_delete (lease)
2206	struct lease *lease;
2207{
2208	struct lease *head = (struct lease *)0;
2209	struct lease *scan;
2210
2211	/* If it's not in the hash, we have no work to do. */
2212	if (!find_lease_by_uid (&head, lease -> uid, lease -> uid_len, MDL)) {
2213		if (lease -> n_uid)
2214			lease_dereference (&lease -> n_uid, MDL);
2215		return;
2216	}
2217
2218	/* If the lease we're freeing is at the head of the list,
2219	   remove the hash table entry and add a new one with the
2220	   next lease on the list (if there is one). */
2221	if (head == lease) {
2222		lease_id_hash_delete(lease_uid_hash, lease->uid,
2223				     lease->uid_len, MDL);
2224		if (lease -> n_uid) {
2225			lease_id_hash_add(lease_uid_hash, lease->n_uid->uid,
2226					  lease->n_uid->uid_len, lease->n_uid,
2227					  MDL);
2228			lease_dereference (&lease -> n_uid, MDL);
2229		}
2230	} else {
2231		/* Otherwise, look for the lease in the list of leases
2232		   attached to the hash table entry, and remove it if
2233		   we find it. */
2234		for (scan = head; scan -> n_uid; scan = scan -> n_uid) {
2235			if (scan -> n_uid == lease) {
2236				lease_dereference (&scan -> n_uid, MDL);
2237				if (lease -> n_uid) {
2238					lease_reference (&scan -> n_uid,
2239							 lease -> n_uid, MDL);
2240					lease_dereference (&lease -> n_uid,
2241							   MDL);
2242				}
2243				break;
2244			}
2245		}
2246	}
2247	lease_dereference (&head, MDL);
2248}
2249
2250/* Add the specified lease to the hardware address hash. */
2251/* We don't add leases with infiniband addresses to the
2252 * hash as there isn't any address to hash on. */
2253
2254void
2255hw_hash_add(struct lease *lease)
2256{
2257	struct lease *head = NULL;
2258	struct lease *cand = NULL;
2259	struct lease *prev = NULL;
2260	struct lease *next = NULL;
2261
2262	/*
2263	 * If it's an infiniband address don't bother
2264	 * as we don't have a useful address to hash.
2265	 */
2266	if ((lease->hardware_addr.hlen == 1) &&
2267	    (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
2268		return;
2269
2270	/* If it's not in the hash, just add it. */
2271	if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
2272				    lease -> hardware_addr.hlen, MDL))
2273		lease_id_hash_add(lease_hw_addr_hash,
2274				  lease->hardware_addr.hbuf,
2275				  lease->hardware_addr.hlen, lease, MDL);
2276	else {
2277		/* Otherwise, insert it into the list in order of its
2278		 * preference for "resuming allocation to the client."
2279		 *
2280		 * Because we don't have control of the hash bucket index
2281		 * directly, we have to remove and re-insert the client
2282		 * id into the hash if we're inserting onto the head.
2283		 */
2284		lease_reference(&cand, head, MDL);
2285		while (cand != NULL) {
2286			if (client_lease_preferred(cand, lease))
2287				break;
2288
2289			if (prev != NULL)
2290				lease_dereference(&prev, MDL);
2291			lease_reference(&prev, cand, MDL);
2292
2293			if (cand->n_hw != NULL)
2294				lease_reference(&next, cand->n_hw, MDL);
2295
2296			lease_dereference(&cand, MDL);
2297
2298			if (next != NULL) {
2299				lease_reference(&cand, next, MDL);
2300				lease_dereference(&next, MDL);
2301			}
2302		}
2303
2304		/* If we want to insert 'before cand', and prev is NULL,
2305		 * then it was the head of the list.  Assume that position.
2306		 */
2307		if (prev == NULL) {
2308			lease_reference(&lease->n_hw, head, MDL);
2309			lease_id_hash_delete(lease_hw_addr_hash,
2310					     lease->hardware_addr.hbuf,
2311					     lease->hardware_addr.hlen, MDL);
2312			lease_id_hash_add(lease_hw_addr_hash,
2313					  lease->hardware_addr.hbuf,
2314					  lease->hardware_addr.hlen,
2315					  lease, MDL);
2316		} else /* (prev != NULL) */ {
2317			if(prev->n_hw != NULL) {
2318				lease_reference(&lease->n_hw, prev->n_hw,
2319						MDL);
2320				lease_dereference(&prev->n_hw, MDL);
2321			}
2322			lease_reference(&prev->n_hw, lease, MDL);
2323
2324			lease_dereference(&prev, MDL);
2325		}
2326
2327		if (cand != NULL)
2328			lease_dereference(&cand, MDL);
2329		lease_dereference(&head, MDL);
2330	}
2331}
2332
2333/* Delete the specified lease from the hardware address hash. */
2334
2335void hw_hash_delete (lease)
2336	struct lease *lease;
2337{
2338	struct lease *head = (struct lease *)0;
2339	struct lease *next = (struct lease *)0;
2340
2341	/*
2342	 * If it's an infiniband address don't bother
2343	 * as we don't have a useful address to hash.
2344	 */
2345	if ((lease->hardware_addr.hlen == 1) &&
2346	    (lease->hardware_addr.hbuf[0] == HTYPE_INFINIBAND))
2347		return;
2348
2349	/* If it's not in the hash, we have no work to do. */
2350	if (!find_lease_by_hw_addr (&head, lease -> hardware_addr.hbuf,
2351				    lease -> hardware_addr.hlen, MDL)) {
2352		if (lease -> n_hw)
2353			lease_dereference (&lease -> n_hw, MDL);
2354		return;
2355	}
2356
2357	/* If the lease we're freeing is at the head of the list,
2358	   remove the hash table entry and add a new one with the
2359	   next lease on the list (if there is one). */
2360	if (head == lease) {
2361		lease_id_hash_delete(lease_hw_addr_hash,
2362				     lease->hardware_addr.hbuf,
2363				     lease->hardware_addr.hlen, MDL);
2364		if (lease->n_hw) {
2365			lease_id_hash_add(lease_hw_addr_hash,
2366					  lease->n_hw->hardware_addr.hbuf,
2367					  lease->n_hw->hardware_addr.hlen,
2368					  lease->n_hw, MDL);
2369			lease_dereference(&lease->n_hw, MDL);
2370		}
2371	} else {
2372		/* Otherwise, look for the lease in the list of leases
2373		   attached to the hash table entry, and remove it if
2374		   we find it. */
2375		while (head -> n_hw) {
2376			if (head -> n_hw == lease) {
2377				lease_dereference (&head -> n_hw, MDL);
2378				if (lease -> n_hw) {
2379					lease_reference (&head -> n_hw,
2380							 lease -> n_hw, MDL);
2381					lease_dereference (&lease -> n_hw,
2382							   MDL);
2383				}
2384				break;
2385			}
2386			lease_reference (&next, head -> n_hw, MDL);
2387			lease_dereference (&head, MDL);
2388			lease_reference (&head, next, MDL);
2389			lease_dereference (&next, MDL);
2390		}
2391	}
2392	if (head)
2393		lease_dereference (&head, MDL);
2394}
2395
2396/* Write v4 leases to permanent storage. */
2397static int write_leases4(void) {
2398	struct lease *l;
2399	struct shared_network *s;
2400	struct pool *p;
2401	LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
2402	int num_written = 0, i;
2403
2404	/* Write all the leases. */
2405	for (s = shared_networks; s; s = s->next) {
2406	    for (p = s->pools; p; p = p->next) {
2407		lptr[FREE_LEASES] = &p->free;
2408		lptr[ACTIVE_LEASES] = &p->active;
2409		lptr[EXPIRED_LEASES] = &p->expired;
2410		lptr[ABANDONED_LEASES] = &p->abandoned;
2411		lptr[BACKUP_LEASES] = &p->backup;
2412		lptr[RESERVED_LEASES] = &p->reserved;
2413
2414		for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2415		    for (l = LEASE_GET_FIRSTP(lptr[i]);
2416			 l != NULL;
2417			 l = LEASE_GET_NEXTP(lptr[i], l)) {
2418#if !defined (DEBUG_DUMP_ALL_LEASES)
2419			if (l->hardware_addr.hlen != 0 || l->uid_len != 0 ||
2420			    l->tsfp != 0 || l->binding_state != FTS_FREE)
2421#endif
2422			{
2423			    if (write_lease(l) == 0)
2424				    return (0);
2425			    num_written++;
2426			}
2427		    }
2428		}
2429	    }
2430	}
2431
2432	log_info ("Wrote %d leases to leases file.", num_written);
2433	return (1);
2434}
2435
2436/* Write all interesting leases to permanent storage. */
2437
2438int write_leases ()
2439{
2440	struct host_decl *hp;
2441	struct group_object *gp;
2442	struct hash_bucket *hb;
2443	struct class *cp;
2444	struct collection *colp;
2445	int i;
2446	int num_written;
2447
2448	/* write all the dynamically-created class declarations. */
2449	if (collections->classes) {
2450		numclasseswritten = 0;
2451		for (colp = collections ; colp ; colp = colp->next) {
2452			for (cp = colp->classes ; cp ; cp = cp->nic) {
2453				write_named_billing_class(
2454						(unsigned char *)cp->name,
2455							  0, cp);
2456			}
2457		}
2458
2459		/* XXXJAB this number doesn't include subclasses... */
2460		log_info ("Wrote %d class decls to leases file.",
2461			  numclasseswritten);
2462	}
2463
2464
2465	/* Write all the dynamically-created group declarations. */
2466	if (group_name_hash) {
2467	    num_written = 0;
2468	    for (i = 0; i < group_name_hash -> hash_count; i++) {
2469		for (hb = group_name_hash -> buckets [i];
2470		     hb; hb = hb -> next) {
2471			gp = (struct group_object *)hb -> value;
2472			if ((gp -> flags & GROUP_OBJECT_DYNAMIC) ||
2473			    ((gp -> flags & GROUP_OBJECT_STATIC) &&
2474			     (gp -> flags & GROUP_OBJECT_DELETED))) {
2475				if (!write_group (gp))
2476					return 0;
2477				++num_written;
2478			}
2479		}
2480	    }
2481	    log_info ("Wrote %d group decls to leases file.", num_written);
2482	}
2483
2484	/* Write all the deleted host declarations. */
2485	if (host_name_hash) {
2486	    num_written = 0;
2487	    for (i = 0; i < host_name_hash -> hash_count; i++) {
2488		for (hb = host_name_hash -> buckets [i];
2489		     hb; hb = hb -> next) {
2490			hp = (struct host_decl *)hb -> value;
2491			if (((hp -> flags & HOST_DECL_STATIC) &&
2492			     (hp -> flags & HOST_DECL_DELETED))) {
2493				if (!write_host (hp))
2494					return 0;
2495				++num_written;
2496			}
2497		}
2498	    }
2499	    log_info ("Wrote %d deleted host decls to leases file.",
2500		      num_written);
2501	}
2502
2503	/* Write all the new, dynamic host declarations. */
2504	if (host_name_hash) {
2505	    num_written = 0;
2506	    for (i = 0; i < host_name_hash -> hash_count; i++) {
2507		for (hb = host_name_hash -> buckets [i];
2508		     hb; hb = hb -> next) {
2509			hp = (struct host_decl *)hb -> value;
2510			if ((hp -> flags & HOST_DECL_DYNAMIC)) {
2511				if (!write_host (hp))
2512					++num_written;
2513			}
2514		}
2515	    }
2516	    log_info ("Wrote %d new dynamic host decls to leases file.",
2517		      num_written);
2518	}
2519
2520#if defined (FAILOVER_PROTOCOL)
2521	/* Write all the failover states. */
2522	if (!dhcp_failover_write_all_states ())
2523		return 0;
2524#endif
2525
2526	switch (local_family) {
2527	      case AF_INET:
2528		if (write_leases4() == 0)
2529			return (0);
2530		break;
2531#ifdef DHCPv6
2532	      case AF_INET6:
2533		if (write_leases6() == 0)
2534			return (0);
2535		break;
2536#endif /* DHCPv6 */
2537	}
2538
2539	if (commit_leases() == 0)
2540		return (0);
2541	return (1);
2542}
2543
2544#if !defined (BINARY_LEASES)
2545/* Unlink all the leases in the queue. */
2546void lease_remove_all(struct lease **lq) {
2547	struct lease *lp, *ln = NULL;
2548
2549	/* nothing to do */
2550	if (*lq == NULL)
2551		return;
2552
2553	/* We simply derefernce the first item in the list.  When
2554	 * it's reference counter goes to zero it will be cleaned
2555	 * and the reference counter
2556	 *
2557	 * Get a pointer to the first item in the list and then
2558	 * drop the reference from the queue pointer
2559	 */
2560	lease_reference(&lp, *lq, MDL);
2561	lease_dereference(lq, MDL);
2562
2563	do {
2564		/* if we have a next save a pointer to it and unlink it */
2565		if (lp->next) {
2566			lease_reference(&ln, lp->next, MDL);
2567			lease_dereference(&lp->next, MDL);
2568		}
2569
2570		/* get rid of what we currently have */
2571		lease_dereference(&lp, MDL);
2572
2573		/* move the next to the current and loop */
2574		lp = ln;
2575		ln = NULL;
2576	} while (lp != NULL);
2577}
2578
2579/*
2580 * This routine walks through a given lease queue (lq) looking
2581 * for comp.  If it doesn't find the lease it is a fatal error
2582 * as it should be on the given queue.  Once we find the lease
2583 * we can remove it from this list.
2584 */
2585void lease_remove(struct lease **lq, struct lease *comp)
2586{
2587	struct lease *prev, *lp;
2588
2589	prev = NULL;
2590	for (lp = *lq; lp != NULL; lp = lp->next) {
2591		if (lp == comp)
2592			break;
2593		prev = lp;
2594	}
2595
2596	if (!lp) {
2597		log_fatal("Lease with binding state %s not on its queue.",
2598			  (comp->binding_state < 1 ||
2599			   comp->binding_state > FTS_LAST)
2600			  ? "unknown"
2601			  : binding_state_names[comp->binding_state - 1]);
2602	}
2603
2604	if (prev) {
2605		lease_dereference(&prev->next, MDL);
2606		if (comp->next) {
2607			lease_reference(&prev->next, comp->next, MDL);
2608			lease_dereference (&comp->next, MDL);
2609		}
2610	} else {
2611		lease_dereference(lq, MDL);
2612		if (comp->next) {
2613			lease_reference(lq, comp->next, MDL);
2614			lease_dereference(&comp->next, MDL);
2615		}
2616	}
2617}
2618
2619/* This routine inserts comp into lq in a sorted fashion.
2620 * The sort key is comp->sort_time, smaller values are
2621 * placed earlier in the list.
2622 */
2623void lease_insert(struct lease **lq, struct lease *comp)
2624{
2625	struct lease *prev, *lp;
2626	static struct lease **last_lq = NULL;
2627	static struct lease *last_insert_point = NULL;
2628
2629	/* This only works during server startup: during runtime, the last
2630	 * lease may be dequeued in between calls.  If the queue is the same
2631	 * as was used previously, and the lease structure isn't (this is not
2632	 * a re-queue), use that as a starting point for the insertion-sort.
2633	 */
2634	if ((server_starting & SS_QFOLLOW) && (lq == last_lq) &&
2635	    (comp != last_insert_point) &&
2636	    (last_insert_point->sort_time <= comp->sort_time)) {
2637		prev = last_insert_point;
2638		lp = prev->next;
2639	} else {
2640		prev = NULL;
2641		lp = *lq;
2642	}
2643
2644	/* Insertion sort the lease onto the appropriate queue. */
2645	for (; lp != NULL ; lp = lp->next) {
2646		if (lp->sort_time >= comp->sort_time)
2647			break;
2648		prev = lp;
2649	}
2650
2651	if (prev) {
2652		if (prev->next) {
2653			lease_reference(&comp->next, prev->next, MDL);
2654			lease_dereference(&prev->next, MDL);
2655		}
2656		lease_reference(&prev->next, comp, MDL);
2657	} else {
2658		if (*lq) {
2659			lease_reference (&comp->next, *lq, MDL);
2660			lease_dereference(lq, MDL);
2661		}
2662		lease_reference(lq, comp, MDL);
2663	}
2664	last_insert_point = comp;
2665	last_lq = lq;
2666
2667	return;
2668}
2669#endif
2670
2671/* In addition to placing this lease upon a lease queue depending on its
2672 * state, it also keeps track of the number of FREE and BACKUP leases in
2673 * existence, and sets the sort_time on the lease.
2674 *
2675 * Sort_time is used in pool_timer() to determine when the lease will
2676 * bubble to the top of the list and be supersede_lease()'d into its next
2677 * state (possibly, if all goes well).  Example, ACTIVE leases move to
2678 * EXPIRED state when the 'ends' value is reached, so that is its sort
2679 * time.  Most queues are sorted by 'ends', since it is generally best
2680 * practice to re-use the oldest lease, to reduce address collision
2681 * chances.
2682 */
2683int lease_enqueue (struct lease *comp)
2684{
2685	LEASE_STRUCT_PTR lq;
2686
2687	/* No queue to put it on? */
2688	if (!comp -> pool)
2689		return 0;
2690
2691	/* Figure out which queue it's going to. */
2692	switch (comp -> binding_state) {
2693	      case FTS_FREE:
2694		if (comp->flags & RESERVED_LEASE) {
2695			lq = &comp->pool->reserved;
2696		} else {
2697			lq = &comp->pool->free;
2698			comp->pool->free_leases++;
2699		}
2700		comp -> sort_time = comp -> ends;
2701		break;
2702
2703	      case FTS_ACTIVE:
2704		lq = &comp -> pool -> active;
2705		comp -> sort_time = comp -> ends;
2706		break;
2707
2708	      case FTS_EXPIRED:
2709	      case FTS_RELEASED:
2710	      case FTS_RESET:
2711		lq = &comp -> pool -> expired;
2712#if defined(FAILOVER_PROTOCOL)
2713		/* In partner_down, tsfp is the time at which the lease
2714		 * may be reallocated (stos+mclt).  We can do that with
2715		 * lease_mine_to_reallocate() anywhere between tsfp and
2716		 * ends.  But we prefer to wait until ends before doing it
2717		 * automatically (choose the greater of the two).  Note
2718		 * that 'ends' is usually a historic timestamp in the
2719		 * case of expired leases, is really only in the future
2720		 * on released leases, and if we know a lease to be released
2721		 * the peer might still know it to be active...in which case
2722		 * it's possible the peer has renewed this lease, so avoid
2723		 * doing that.
2724		 */
2725		if (comp->pool->failover_peer &&
2726		    comp->pool->failover_peer->me.state == partner_down)
2727			comp->sort_time = (comp->tsfp > comp->ends) ?
2728					  comp->tsfp : comp->ends;
2729		else
2730#endif
2731			comp->sort_time = comp->ends;
2732
2733		break;
2734
2735	      case FTS_ABANDONED:
2736		lq = &comp -> pool -> abandoned;
2737		comp -> sort_time = comp -> ends;
2738		break;
2739
2740	      case FTS_BACKUP:
2741		if (comp->flags & RESERVED_LEASE) {
2742			lq = &comp->pool->reserved;
2743		} else {
2744			lq = &comp->pool->backup;
2745			comp->pool->backup_leases++;
2746		}
2747		comp -> sort_time = comp -> ends;
2748		break;
2749
2750	      default:
2751		log_error ("Lease with bogus binding state: %d",
2752			   comp -> binding_state);
2753#if defined (BINDING_STATE_DEBUG)
2754		abort ();
2755#endif
2756		return 0;
2757	}
2758
2759	LEASE_INSERTP(lq, comp);
2760
2761	return 1;
2762}
2763
2764/* For a given lease, sort it onto the right list in its pool and put it
2765   in each appropriate hash, understanding that it's already by definition
2766   in lease_ip_addr_hash. */
2767
2768isc_result_t
2769lease_instantiate(const void *key, unsigned len, void *object)
2770{
2771	struct lease *lease = object;
2772	struct class *class;
2773	/* XXX If the lease doesn't have a pool at this point, it's an
2774	   XXX orphan, which we *should* keep around until it expires,
2775	   XXX but which right now we just forget. */
2776	if (!lease -> pool) {
2777		lease_ip_hash_delete(lease_ip_addr_hash, lease->ip_addr.iabuf,
2778				     lease->ip_addr.len, MDL);
2779		return ISC_R_SUCCESS;
2780	}
2781
2782#if defined (FAILOVER_PROTOCOL)
2783	/* If the lease is in FTS_BACKUP but there is no peer, then the
2784 	 * pool must have been formerly configured for failover and
2785 	 * is now configured as standalone. This means we need to
2786 	 * move the lease to FTS_FREE to make it available. */
2787	if ((lease->binding_state == FTS_BACKUP) &&
2788	    (lease->pool->failover_peer == NULL)) {
2789#else
2790	/* We aren't compiled for failover, so just move to FTS_FREE */
2791	if (lease->binding_state == FTS_BACKUP) {
2792#endif
2793		lease->binding_state = FTS_FREE;
2794		lease->next_binding_state = FTS_FREE;
2795		lease->rewind_binding_state = FTS_FREE;
2796	}
2797
2798	/* Put the lease on the right queue.  Failure to queue is probably
2799	 * due to a bogus binding state.  In such a case, we claim success,
2800	 * so that later leases in a hash_foreach are processed, but we
2801	 * return early as we really don't want hw address hash entries or
2802	 * other cruft to surround such a bogus entry.
2803	 */
2804	if (!lease_enqueue(lease))
2805		return ISC_R_SUCCESS;
2806
2807	/* Record the lease in the uid hash if possible. */
2808	if (lease -> uid) {
2809		uid_hash_add (lease);
2810	}
2811
2812	/* Record it in the hardware address hash if possible. */
2813	if (lease -> hardware_addr.hlen) {
2814		hw_hash_add (lease);
2815	}
2816
2817	/* If the lease has a billing class, set up the billing. */
2818	if (lease -> billing_class) {
2819		class = (struct class *)0;
2820		class_reference (&class, lease -> billing_class, MDL);
2821		class_dereference (&lease -> billing_class, MDL);
2822		/* If the lease is available for allocation, the billing
2823		   is invalid, so we don't keep it. */
2824		if (lease -> binding_state == FTS_ACTIVE ||
2825		    lease -> binding_state == FTS_EXPIRED ||
2826		    lease -> binding_state == FTS_RELEASED ||
2827		    lease -> binding_state == FTS_RESET)
2828			bill_class (lease, class);
2829		class_dereference (&class, MDL);
2830	}
2831	return ISC_R_SUCCESS;
2832}
2833
2834/* Run expiry events on every pool.   This is called on startup so that
2835   any expiry events that occurred after the server stopped and before it
2836   was restarted can be run.   At the same time, if failover support is
2837   compiled in, we compute the balance of leases for the pool. */
2838
2839void expire_all_pools ()
2840{
2841	struct shared_network *s;
2842	struct pool *p;
2843	int i;
2844	struct lease *l;
2845	LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
2846
2847	/* Indicate that we are in the startup phase */
2848	server_starting = SS_NOSYNC | SS_QFOLLOW;
2849
2850#if defined (BINARY_LEASES)
2851	/* set up the growth factors for the binary leases.
2852	 * We use 100% for free, 50% for active and backup
2853	 * 20% for expired, abandoned and reserved
2854	 * but no less than 100, 50, and 20.
2855	 */
2856	for (s = shared_networks; s; s = s -> next) {
2857	    for (p = s -> pools; p != NULL; p = p -> next) {
2858		size_t num_f = 100, num_a = 50, num_e = 20;
2859		if (p->lease_count > 100) {
2860		    num_f = p->lease_count;
2861		    num_a = num_f / 2;
2862		    num_e = num_f / 5;
2863		}
2864		lc_init_growth(&p->free, num_f);
2865		lc_init_growth(&p->active, num_a);
2866		lc_init_growth(&p->expired, num_a);
2867		lc_init_growth(&p->abandoned, num_e);
2868		lc_init_growth(&p->backup, num_e);
2869		lc_init_growth(&p->reserved, num_e);
2870	    }
2871	}
2872#endif
2873
2874	/* First, go over the hash list and actually put all the leases
2875	   on the appropriate lists. */
2876	lease_ip_hash_foreach(lease_ip_addr_hash, lease_instantiate);
2877
2878	/* Loop through each pool in each shared network and call the
2879	 * expiry routine on the pool.  It is no longer safe to follow
2880	 * the queue insertion point, as expiration of a lease can move
2881	 * it between queues (and this may be the lease that function
2882	 * points at).
2883	 */
2884	server_starting &= ~SS_QFOLLOW;
2885	for (s = shared_networks; s; s = s -> next) {
2886	    for (p = s -> pools; p; p = p -> next) {
2887		pool_timer (p);
2888
2889		p -> lease_count = 0;
2890		p -> free_leases = 0;
2891		p -> backup_leases = 0;
2892
2893		lptr [FREE_LEASES] = &p -> free;
2894		lptr [ACTIVE_LEASES] = &p -> active;
2895		lptr [EXPIRED_LEASES] = &p -> expired;
2896		lptr [ABANDONED_LEASES] = &p -> abandoned;
2897		lptr [BACKUP_LEASES] = &p -> backup;
2898		lptr [RESERVED_LEASES] = &p->reserved;
2899
2900		for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2901		    for (l = LEASE_GET_FIRSTP(lptr[i]);
2902			 l != NULL;
2903			 l = LEASE_GET_NEXTP(lptr[i], l)) {
2904			p -> lease_count++;
2905			if (l -> ends <= cur_time) {
2906				if (l->binding_state == FTS_FREE) {
2907					if (i == FREE_LEASES)
2908						p->free_leases++;
2909					else if (i != RESERVED_LEASES)
2910						log_fatal("Impossible case "
2911							  "at %s:%d.", MDL);
2912				} else if (l->binding_state == FTS_BACKUP) {
2913					if (i == BACKUP_LEASES)
2914						p->backup_leases++;
2915					else if (i != RESERVED_LEASES)
2916						log_fatal("Impossible case "
2917							  "at %s:%d.", MDL);
2918				}
2919			}
2920#if defined (FAILOVER_PROTOCOL)
2921			if (p -> failover_peer &&
2922			    l -> tstp > l -> atsfp &&
2923			    !(l -> flags & ON_UPDATE_QUEUE)) {
2924				l -> desired_binding_state = l -> binding_state;
2925				dhcp_failover_queue_update (l, 1);
2926			}
2927#endif
2928		    }
2929		}
2930	    }
2931	}
2932
2933	/* turn off startup phase */
2934	server_starting = 0;
2935}
2936
2937void dump_subnets ()
2938{
2939	struct lease *l;
2940	struct shared_network *s;
2941	struct subnet *n;
2942	struct pool *p;
2943	LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
2944	int i;
2945
2946	log_info ("Subnets:");
2947	for (n = subnets; n; n = n -> next_subnet) {
2948		log_debug ("  Subnet %s", piaddr (n -> net));
2949		log_debug ("     netmask %s",
2950		       piaddr (n -> netmask));
2951	}
2952	log_info ("Shared networks:");
2953	for (s = shared_networks; s; s = s -> next) {
2954	    log_info ("  %s", s -> name);
2955	    for (p = s -> pools; p; p = p -> next) {
2956		lptr [FREE_LEASES] = &p -> free;
2957		lptr [ACTIVE_LEASES] = &p -> active;
2958		lptr [EXPIRED_LEASES] = &p -> expired;
2959		lptr [ABANDONED_LEASES] = &p -> abandoned;
2960		lptr [BACKUP_LEASES] = &p -> backup;
2961		lptr [RESERVED_LEASES] = &p->reserved;
2962
2963		for (i = FREE_LEASES; i <= RESERVED_LEASES; i++) {
2964		    for (l = LEASE_GET_FIRSTP(lptr[i]);
2965			 l != NULL;
2966			 l = LEASE_GET_NEXTP(lptr[i], l)) {
2967			    print_lease (l);
2968		    }
2969		}
2970	    }
2971	}
2972}
2973
2974HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
2975	       lease_reference, lease_dereference, do_ip4_hash)
2976HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
2977	       lease_reference, lease_dereference, do_id_hash)
2978HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
2979		host_reference, host_dereference, do_string_hash)
2980HASH_FUNCTIONS (class, const char *, struct class, class_hash_t,
2981		class_reference, class_dereference, do_string_hash)
2982
2983#if defined (DEBUG_MEMORY_LEAKAGE) && \
2984		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
2985extern struct hash_table *dns_zone_hash;
2986extern struct interface_info **interface_vector;
2987extern int interface_count;
2988dhcp_control_object_t *dhcp_control_object;
2989extern struct hash_table *auth_key_hash;
2990struct hash_table *universe_hash;
2991struct universe **universes;
2992int universe_count, universe_max;
2993#if 0
2994extern int end;
2995#endif
2996
2997#if defined (COMPACT_LEASES)
2998extern struct lease *lease_hunks;
2999#endif
3000
3001void free_everything(void)
3002{
3003	struct subnet *sc = (struct subnet *)0, *sn = (struct subnet *)0;
3004	struct shared_network *nc = (struct shared_network *)0,
3005		*nn = (struct shared_network *)0;
3006	struct pool *pc = (struct pool *)0, *pn = (struct pool *)0;
3007	struct lease *lc = NULL, *ln = NULL,  *ltemp = NULL;
3008	struct interface_info *ic = (struct interface_info *)0,
3009		*in = (struct interface_info *)0;
3010	struct class *cc = (struct class *)0, *cn = (struct class *)0;
3011	struct collection *lp;
3012	int i;
3013
3014	/* Get rid of all the hash tables. */
3015	if (host_hw_addr_hash)
3016		host_free_hash_table (&host_hw_addr_hash, MDL);
3017	host_hw_addr_hash = 0;
3018	if (host_uid_hash)
3019		host_free_hash_table (&host_uid_hash, MDL);
3020	host_uid_hash = 0;
3021	if (lease_uid_hash)
3022		lease_id_free_hash_table (&lease_uid_hash, MDL);
3023	lease_uid_hash = 0;
3024	if (lease_ip_addr_hash)
3025		lease_ip_free_hash_table (&lease_ip_addr_hash, MDL);
3026	lease_ip_addr_hash = 0;
3027	if (lease_hw_addr_hash)
3028		lease_id_free_hash_table (&lease_hw_addr_hash, MDL);
3029	lease_hw_addr_hash = 0;
3030	if (host_name_hash)
3031		host_free_hash_table (&host_name_hash, MDL);
3032	host_name_hash = 0;
3033	if (dns_zone_hash)
3034		dns_zone_free_hash_table (&dns_zone_hash, MDL);
3035	dns_zone_hash = 0;
3036
3037	while (host_id_info != NULL) {
3038		host_id_info_t *tmp;
3039		option_dereference(&host_id_info->option, MDL);
3040		host_free_hash_table(&host_id_info->values_hash, MDL);
3041		tmp = host_id_info->next;
3042		dfree(host_id_info, MDL);
3043		host_id_info = tmp;
3044	}
3045#if 0
3046	if (auth_key_hash)
3047		auth_key_free_hash_table (&auth_key_hash, MDL);
3048#endif
3049	auth_key_hash = 0;
3050
3051	omapi_object_dereference ((omapi_object_t **)&dhcp_control_object,
3052				  MDL);
3053
3054	for (lp = collections; lp; lp = lp -> next) {
3055	    if (lp -> classes) {
3056		class_reference (&cn, lp -> classes, MDL);
3057		do {
3058		    if (cn) {
3059			class_reference (&cc, cn, MDL);
3060			class_dereference (&cn, MDL);
3061		    }
3062		    if (cc -> nic) {
3063			class_reference (&cn, cc -> nic, MDL);
3064			class_dereference (&cc -> nic, MDL);
3065		    }
3066		    group_dereference (&cc -> group, MDL);
3067		    if (cc -> hash) {
3068			    class_free_hash_table (&cc -> hash, MDL);
3069			    cc -> hash = (struct hash_table *)0;
3070		    }
3071		    class_dereference (&cc, MDL);
3072		} while (cn);
3073		class_dereference (&lp -> classes, MDL);
3074	    }
3075	}
3076
3077	if (interface_vector) {
3078	    for (i = 0; i < interface_count; i++) {
3079		if (interface_vector [i])
3080		    interface_dereference (&interface_vector [i], MDL);
3081	    }
3082	    dfree (interface_vector, MDL);
3083	    interface_vector = 0;
3084	}
3085
3086	if (interfaces) {
3087	    interface_reference (&in, interfaces, MDL);
3088	    do {
3089		if (in) {
3090		    interface_reference (&ic, in, MDL);
3091		    interface_dereference (&in, MDL);
3092		}
3093		if (ic -> next) {
3094		    interface_reference (&in, ic -> next, MDL);
3095		    interface_dereference (&ic -> next, MDL);
3096		}
3097		omapi_unregister_io_object ((omapi_object_t *)ic);
3098		if (ic -> shared_network) {
3099		    if (ic -> shared_network -> interface)
3100			interface_dereference
3101				(&ic -> shared_network -> interface, MDL);
3102		    shared_network_dereference (&ic -> shared_network, MDL);
3103		}
3104		interface_dereference (&ic, MDL);
3105	    } while (in);
3106	    interface_dereference (&interfaces, MDL);
3107	}
3108
3109	/* Subnets are complicated because of the extra links. */
3110	if (subnets) {
3111	    subnet_reference (&sn, subnets, MDL);
3112	    do {
3113		if (sn) {
3114		    subnet_reference (&sc, sn, MDL);
3115		    subnet_dereference (&sn, MDL);
3116		}
3117		if (sc -> next_subnet) {
3118		    subnet_reference (&sn, sc -> next_subnet, MDL);
3119		    subnet_dereference (&sc -> next_subnet, MDL);
3120		}
3121		if (sc -> next_sibling)
3122		    subnet_dereference (&sc -> next_sibling, MDL);
3123		if (sc -> shared_network)
3124		    shared_network_dereference (&sc -> shared_network, MDL);
3125		group_dereference (&sc -> group, MDL);
3126		if (sc -> interface)
3127		    interface_dereference (&sc -> interface, MDL);
3128		subnet_dereference (&sc, MDL);
3129	    } while (sn);
3130	    subnet_dereference (&subnets, MDL);
3131	}
3132
3133	/* So are shared networks. */
3134	/* XXX: this doesn't work presently, but i'm ok just filtering
3135	 * it out of the noise (you get a bigger spike on the real leaks).
3136	 * It would be good to fix this, but it is not a "real bug," so not
3137	 * today.  This hack is incomplete, it doesn't trim out sub-values.
3138	 */
3139	if (shared_networks) {
3140		shared_network_dereference (&shared_networks, MDL);
3141	/* This is the old method (tries to free memory twice, broken) */
3142	} else if (0) {
3143	    shared_network_reference (&nn, shared_networks, MDL);
3144	    do {
3145		if (nn) {
3146		    shared_network_reference (&nc, nn, MDL);
3147		    shared_network_dereference (&nn, MDL);
3148		}
3149		if (nc -> next) {
3150		    shared_network_reference (&nn, nc -> next, MDL);
3151		    shared_network_dereference (&nc -> next, MDL);
3152		}
3153
3154		/* As are pools. */
3155		if (nc -> pools) {
3156		    pool_reference (&pn, nc -> pools, MDL);
3157		    do {
3158			LEASE_STRUCT_PTR lptr[RESERVED_LEASES+1];
3159
3160			if (pn) {
3161			    pool_reference (&pc, pn, MDL);
3162			    pool_dereference (&pn, MDL);
3163			}
3164			if (pc -> next) {
3165			    pool_reference (&pn, pc -> next, MDL);
3166			    pool_dereference (&pc -> next, MDL);
3167			}
3168
3169			lptr [FREE_LEASES] = &pc -> free;
3170			lptr [ACTIVE_LEASES] = &pc -> active;
3171			lptr [EXPIRED_LEASES] = &pc -> expired;
3172			lptr [ABANDONED_LEASES] = &pc -> abandoned;
3173			lptr [BACKUP_LEASES] = &pc -> backup;
3174			lptr [RESERVED_LEASES] = &pc->reserved;
3175
3176			/* As (sigh) are leases. */
3177			for (i = FREE_LEASES ; i <= RESERVED_LEASES ; i++) {
3178			    if (LEASE_NOT_EMPTYP(lptr[i])) {
3179			        lease_reference(&ln, LEASE_GET_FIRSTP(lptr[i]), MDL);
3180				do {
3181				    /* save a pointer to the current lease */
3182				    lease_reference (&lc, ln, MDL);
3183				    lease_dereference (&ln, MDL);
3184
3185				    /* get the next lease if there is one */
3186				    ltemp = LEASE_GET_NEXTP(lptr[i], lc);
3187				    if (ltemp != NULL) {
3188					lease_reference(&ln, ltemp, MDL);
3189				    }
3190
3191				    /* remove the current lease from the queue */
3192				    LEASE_REMOVEP(lptr[i], lc);
3193
3194				    if (lc -> billing_class)
3195				       class_dereference (&lc -> billing_class,
3196							  MDL);
3197				    if (lc -> state)
3198					free_lease_state (lc -> state, MDL);
3199				    lc -> state = (struct lease_state *)0;
3200				    if (lc -> n_hw)
3201					lease_dereference (&lc -> n_hw, MDL);
3202				    if (lc -> n_uid)
3203					lease_dereference (&lc -> n_uid, MDL);
3204				    lease_dereference (&lc, MDL);
3205				} while (ln);
3206			    }
3207			}
3208			if (pc -> group)
3209			    group_dereference (&pc -> group, MDL);
3210			if (pc -> shared_network)
3211			    shared_network_dereference (&pc -> shared_network,
3212							MDL);
3213			pool_dereference (&pc, MDL);
3214		    } while (pn);
3215		    pool_dereference (&nc -> pools, MDL);
3216		}
3217		/* Because of a circular reference, we need to nuke this
3218		   manually. */
3219		group_dereference (&nc -> group, MDL);
3220		shared_network_dereference (&nc, MDL);
3221	    } while (nn);
3222	    shared_network_dereference (&shared_networks, MDL);
3223	}
3224
3225	cancel_all_timeouts ();
3226	relinquish_timeouts ();
3227#if defined(DELAYED_ACK)
3228	relinquish_ackqueue();
3229#endif
3230	trace_free_all ();
3231	group_dereference (&root_group, MDL);
3232	executable_statement_dereference (&default_classification_rules, MDL);
3233
3234	shutdown_state = shutdown_drop_omapi_connections;
3235	omapi_io_state_foreach (dhcp_io_shutdown, 0);
3236	shutdown_state = shutdown_listeners;
3237	omapi_io_state_foreach (dhcp_io_shutdown, 0);
3238	shutdown_state = shutdown_dhcp;
3239	omapi_io_state_foreach (dhcp_io_shutdown, 0);
3240
3241	omapi_object_dereference ((omapi_object_t **)&icmp_state, MDL);
3242
3243	universe_free_hash_table (&universe_hash, MDL);
3244	for (i = 0; i < universe_count; i++) {
3245#if 0
3246		union {
3247			const char *c;
3248			char *s;
3249		} foo;
3250#endif
3251		if (universes [i]) {
3252			if (universes[i]->name_hash)
3253			    option_name_free_hash_table(
3254						&universes[i]->name_hash,
3255						MDL);
3256			if (universes[i]->code_hash)
3257			    option_code_free_hash_table(
3258						&universes[i]->code_hash,
3259						MDL);
3260#if 0
3261			if (universes [i] -> name > (char *)&end) {
3262				foo.c = universes [i] -> name;
3263				dfree (foo.s, MDL);
3264			}
3265			if (universes [i] > (struct universe *)&end)
3266				dfree (universes [i], MDL);
3267#endif
3268		}
3269	}
3270	dfree (universes, MDL);
3271
3272	relinquish_free_lease_states ();
3273	relinquish_free_pairs ();
3274	relinquish_free_expressions ();
3275	relinquish_free_binding_values ();
3276	relinquish_free_option_caches ();
3277	relinquish_free_packets ();
3278#if defined(COMPACT_LEASES)
3279	relinquish_lease_hunks ();
3280#endif
3281	relinquish_hash_bucket_hunks ();
3282	omapi_type_relinquish ();
3283}
3284#endif /* DEBUG_MEMORY_LEAKAGE_ON_EXIT */
3285