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