Home | History | Annotate | Line # | Download | only in server
      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 (at) 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 
     37 struct subnet *subnets;
     38 struct shared_network *shared_networks;
     39 host_hash_t *host_hw_addr_hash;
     40 host_hash_t *host_uid_hash;
     41 host_hash_t *host_name_hash;
     42 lease_id_hash_t *lease_uid_hash;
     43 lease_ip_hash_t *lease_ip_addr_hash;
     44 lease_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  */
     64 typedef 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 
     71 static host_id_info_t *host_id_info = NULL;
     72 
     73 int numclasseswritten;
     74 
     75 extern omapi_object_type_t *dhcp_type_host;
     76 
     77 isc_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
    126 static int server_starting = 0;
    127 
    128 static 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 
    154 static host_id_info_t *
    155 find_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
    169 isc_result_t
    170 print_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 
    180 void
    181 hash_print_hosts(struct hash_table *h) {
    182 	hash_foreach(h, print_host);
    183 	printf("--------------\n");
    184 }
    185 #endif /* 0 */
    186 
    187 void
    188 change_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 
    225 isc_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 
    462 isc_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 
    494 isc_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 
    636 int 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 
    656 int 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 
    663 int
    664 find_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 
    740 int 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 
    786 void 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 
    937 int 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 
    957 int 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 */
    979 int
    980 subnet_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. */
   1012 void 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 
   1059 void 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 
   1070 void 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 
   1116 void 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 
   1159 int 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 
   1507 void 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. */
   1685 int 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. */
   1759 void 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 
   1834 void 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 
   1885 void 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. */
   1918 void 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 
   2056 int 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 
   2063 int 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 
   2071 int 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  */
   2102 static isc_boolean_t
   2103 client_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. */
   2137 void
   2138 uid_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 
   2205 void 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 
   2254 void
   2255 hw_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 
   2335 void 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. */
   2397 static 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 
   2438 int 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. */
   2546 void 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  */
   2585 void 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  */
   2623 void 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  */
   2683 int 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 
   2768 isc_result_t
   2769 lease_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 
   2839 void 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 
   2937 void 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 
   2974 HASH_FUNCTIONS(lease_ip, const unsigned char *, struct lease, lease_ip_hash_t,
   2975 	       lease_reference, lease_dereference, do_ip4_hash)
   2976 HASH_FUNCTIONS(lease_id, const unsigned char *, struct lease, lease_id_hash_t,
   2977 	       lease_reference, lease_dereference, do_id_hash)
   2978 HASH_FUNCTIONS (host, const unsigned char *, struct host_decl, host_hash_t,
   2979 		host_reference, host_dereference, do_string_hash)
   2980 HASH_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)
   2985 extern struct hash_table *dns_zone_hash;
   2986 extern struct interface_info **interface_vector;
   2987 extern int interface_count;
   2988 dhcp_control_object_t *dhcp_control_object;
   2989 extern struct hash_table *auth_key_hash;
   2990 struct hash_table *universe_hash;
   2991 struct universe **universes;
   2992 int universe_count, universe_max;
   2993 #if 0
   2994 extern int end;
   2995 #endif
   2996 
   2997 #if defined (COMPACT_LEASES)
   2998 extern struct lease *lease_hunks;
   2999 #endif
   3000 
   3001 void 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