xref: /minix/external/bsd/dhcp/dist/server/mdb6.c (revision bb9622b5)
1 /*	$NetBSD: mdb6.c,v 1.5 2014/07/12 12:09:38 spz Exp $	*/
2 /*
3  * Copyright (C) 2007-2013 by Internet Systems Consortium, Inc. ("ISC")
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/cdefs.h>
19 __RCSID("$NetBSD: mdb6.c,v 1.5 2014/07/12 12:09:38 spz Exp $");
20 
21 /*!
22  * \todo assert()
23  * \todo simplify functions, as pool is now in iaaddr
24  */
25 
26 /*! \file server/mdb6.c
27  *
28  * \page ipv6structures IPv6 Structures Overview
29  *
30  * A brief description of the IPv6 structures as reverse engineered.
31  *
32  * There are four major data structures in the lease configuraion.
33  *
34  * - shared_network - The shared network is the outer enclosing scope for a
35  *                    network region that shares a broadcast domain.  It is
36  *                    composed of one or more subnets all of which are valid
37  *                    in the given region.  The share network may be
38  *                    explicitly defined or implicitly created if there is
39  *                    only a subnet statement.  This structrure is shared
40  *                    with v4.  Each shared network statment or naked subnet
41  *                    will map to one of these structures
42  *
43  * - subnet     - The subnet structure mostly specifies the address range
44  *                that could be valid in a given region.  This structute
45  *                doesn't include the addresses that the server can delegate
46  *                those are in the ipv6_pool.  This structure is also shared
47  *                with v4.  Each subnet statement will map to one of these
48  *                structures.
49  *
50  * - ipv6_pond  - The pond structure is a grouping of the address and prefix
51  *                information via the pointers to the ipv6_pool and the
52  *                allowability of this pool for given clinets via the permit
53  *                lists and the valid TIMEs.  This is equivilent to the v4
54  *                pool structure and would have been named ip6_pool except
55  *                that the name was already in use.  Generally each pool6
56  *                statement will map to one of these structures. In addition
57  *                there may be one or for each group of naked range6 and
58  *                prefix6 statements within a shared network that share
59  *                the same group of statements.
60  *
61  * - ipv6_pool - this contains information about a pool of addresses or prefixes
62  *               that the server is using.  This includes a hash table that
63  *               tracks the active items and a pair of heap tables one for
64  *               active items and one for non-active items.  The heap tables
65  *               are used to determine the next items to be modified due to
66  *               timing events (expire mostly).
67  *
68  * The linkages then look like this:
69  * \verbatim
70  *+--------------+   +-------------+
71  *|Shared Network|   | ipv6_pond   |
72  *|   group      |   |   group     |
73  *|              |   | permit info |
74  *|              |   |    next    ---->
75  *|    ponds    ---->|             |
76  *|              |<----  shared    |
77  *|   Subnets    |   |    pools    |
78  *+-----|--------+   +------|------+
79  *      |  ^                |    ^
80  *      |  |                v    |
81  *      |  |         +-----------|-+
82  *      |  |         | ipv6_pool | |
83  *      |  |         |    type   | |
84  *      |  |         |   ipv6_pond |
85  *      |  |         |             |
86  *      |  |         |    next    ---->
87  *      |  |         |             |
88  *      |  |         |   subnet    |
89  *      |  |         +-----|-------+
90  *      |  |               |
91  *      |  |               v
92  *      |  |         +-------------+
93  *      |  |         |   subnet    |
94  *      |  +----------   shared    |
95  *      +----------->|             |
96  *                   |   group     |
97  *                   +-------------+
98  *
99  * The shared network contains a list of all the subnets that are on a broadcast
100  * doamin.  These can be used to determine if an address makes sense in a given
101  * domain, but the subnets do not contain the addresses the server can delegate.
102  * Those are stored in the ponds and pools.
103  *
104  * In the simple case to find an acceptable address the server would first find
105  * the shared network the client is on based on either the interface used to
106  * receive the request or the relay agent's information.  From the shared
107  * network the server will walk through it's list of ponds.  For each pond it
108  * will evaluate the permit information against the (already done) classification.
109  * If it finds an acceptable pond it will then walk through the pools for that
110  * pond.  The server first checks the type of the pool (NA, TA and PD) agaisnt the
111  * request and if they match it attemps to find an address within that pool.  On
112  * success the address is used, on failure the server steps to the next pool and
113  * if necessary to the next pond.
114  *
115  * When the server is successful in finding an address it will execute any
116  * statements assocaited with the pond, then the subnet, then the shared
117  * network the group field is for in the above picture).
118  *
119  * In configurations that don't include either a shared network or a pool6
120  * statement (or both) the missing pieces are created.
121  *
122  *
123  * There are three major data structuress involved in the lease database:
124  *
125  * - ipv6_pool - see above
126  * - ia_xx   - this contains information about a single IA from a request
127  *             normally it will contain one pointer to a lease for the client
128  *             but it may contain more in some circumstances.  There are 3
129  *             hash tables to aid in accessing these one each for NA, TA and PD.
130  * - iasubopt - the v6 lease structure.  These are created dynamically when
131  *              a client asks for something and will eventually be destroyed
132  *              if the client doesn't re-ask for that item.  A lease has space
133  *              for backpointers to the IA and to the pool to which it belongs.
134  *              The pool backpointer is always filled, the IA pointer may not be.
135  *
136  * In normal use we then have something like this:
137  *
138  * \verbatim
139  * ia hash tables
140  *  ia_na_active                           +----------------+
141  *  ia_ta_active          +------------+   | pool           |
142  *  ia_pd_active          | iasubopt   |<--|  active hash   |
143  * +-----------------+    | aka lease  |<--|  active heap   |
144  * | ia_xx           |    |  pool ptr  |-->|                |
145  * |  iasubopt array |<---|  iaptr     |<--|  inactive heap |
146  * |   lease ptr     |--->|            |   |                |
147  * +-----------------+    +------------+   +----------------+
148  * \endverbatim
149  *
150  * For the pool either the inactive heap will have a pointer
151  * or both the active heap and the active hash will have pointers.
152  *
153  * I think there are several major items to notice.   The first is
154  * that as a lease moves around it will be added to and removed
155  * from the address hash table in the pool and between the active
156  * and inactive hash tables.  The hash table and the active heap
157  * are used when the lease is either active or abandoned.  The
158  * inactive heap is used for all other states.  In particular a
159  * lease that has expired or been released will be cleaned
160  * (DDNS removal etc) and then moved to the inactive heap.  After
161  * some time period (currently 1 hour) it will be freed.
162  *
163  * The second is that when a client requests specific addresses,
164  * either because it previously owned them or if the server supplied
165  * them as part of a solicit, the server will try to lookup the ia_xx
166  * associated with the client and find the addresses there.  If it
167  * does find appropriate leases it moves them from the old IA to
168  * a new IA and eventually replaces the old IA with the new IA
169  * in the IA hash tables.
170  *
171  */
172 #include "config.h"
173 
174 #include <sys/types.h>
175 #include <time.h>
176 #include <netinet/in.h>
177 
178 #include <stdarg.h>
179 #include "dhcpd.h"
180 #include "omapip/omapip.h"
181 #include "omapip/hash.h"
182 #include <isc/md5.h>
183 
184 HASH_FUNCTIONS(ia, unsigned char *, struct ia_xx, ia_hash_t,
185 	       ia_reference, ia_dereference, do_string_hash)
186 
187 ia_hash_t *ia_na_active;
188 ia_hash_t *ia_ta_active;
189 ia_hash_t *ia_pd_active;
190 
191 HASH_FUNCTIONS(iasubopt, struct in6_addr *, struct iasubopt, iasubopt_hash_t,
192 	       iasubopt_reference, iasubopt_dereference, do_string_hash)
193 
194 struct ipv6_pool **pools;
195 int num_pools;
196 
197 /*
198  * Create a new IAADDR/PREFIX structure.
199  *
200  * - iasubopt must be a pointer to a (struct iasubopt *) pointer previously
201  *   initialized to NULL
202  */
203 isc_result_t
204 iasubopt_allocate(struct iasubopt **iasubopt, const char *file, int line) {
205 	struct iasubopt *tmp;
206 
207 	if (iasubopt == NULL) {
208 		log_error("%s(%d): NULL pointer reference", file, line);
209 		return DHCP_R_INVALIDARG;
210 	}
211 	if (*iasubopt != NULL) {
212 		log_error("%s(%d): non-NULL pointer", file, line);
213 		return DHCP_R_INVALIDARG;
214 	}
215 
216 	tmp = dmalloc(sizeof(*tmp), file, line);
217 	if (tmp == NULL) {
218 		return ISC_R_NOMEMORY;
219 	}
220 
221 	tmp->refcnt = 1;
222 	tmp->state = FTS_FREE;
223 	tmp->heap_index = -1;
224 	tmp->plen = 255;
225 
226 	*iasubopt = tmp;
227 	return ISC_R_SUCCESS;
228 }
229 
230 /*
231  * Reference an IAADDR/PREFIX structure.
232  *
233  * - iasubopt must be a pointer to a (struct iasubopt *) pointer previously
234  *   initialized to NULL
235  */
236 isc_result_t
237 iasubopt_reference(struct iasubopt **iasubopt, struct iasubopt *src,
238 		 const char *file, int line) {
239 	if (iasubopt == NULL) {
240 		log_error("%s(%d): NULL pointer reference", file, line);
241 		return DHCP_R_INVALIDARG;
242 	}
243 	if (*iasubopt != NULL) {
244 		log_error("%s(%d): non-NULL pointer", file, line);
245 		return DHCP_R_INVALIDARG;
246 	}
247 	if (src == NULL) {
248 		log_error("%s(%d): NULL pointer reference", file, line);
249 		return DHCP_R_INVALIDARG;
250 	}
251 	*iasubopt = src;
252 	src->refcnt++;
253 	return ISC_R_SUCCESS;
254 }
255 
256 
257 /*
258  * Dereference an IAADDR/PREFIX structure.
259  *
260  * If it is the last reference, then the memory for the
261  * structure is freed.
262  */
263 isc_result_t
264 iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line) {
265 	struct iasubopt *tmp;
266 
267 	if ((iasubopt == NULL) || (*iasubopt == NULL)) {
268 		log_error("%s(%d): NULL pointer", file, line);
269 		return DHCP_R_INVALIDARG;
270 	}
271 
272 	tmp = *iasubopt;
273 	*iasubopt = NULL;
274 
275 	tmp->refcnt--;
276 	if (tmp->refcnt < 0) {
277 		log_error("%s(%d): negative refcnt", file, line);
278 		tmp->refcnt = 0;
279 	}
280 	if (tmp->refcnt == 0) {
281 		if (tmp->ia != NULL) {
282 			ia_dereference(&(tmp->ia), file, line);
283 		}
284 		if (tmp->ipv6_pool != NULL) {
285 			ipv6_pool_dereference(&(tmp->ipv6_pool), file, line);
286 		}
287 		if (tmp->scope != NULL) {
288 			binding_scope_dereference(&tmp->scope, file, line);
289 		}
290 
291 		if (tmp->on_star.on_expiry != NULL) {
292 			executable_statement_dereference
293 				(&tmp->on_star.on_expiry, MDL);
294 		}
295 		if (tmp->on_star.on_commit != NULL) {
296 			executable_statement_dereference
297 				(&tmp->on_star.on_commit, MDL);
298 		}
299 		if (tmp->on_star.on_release != NULL) {
300 			executable_statement_dereference
301 				(&tmp->on_star.on_release, MDL);
302 		}
303 
304 		dfree(tmp, file, line);
305 	}
306 
307 	return ISC_R_SUCCESS;
308 }
309 
310 /*
311  * Make the key that we use for IA.
312  */
313 isc_result_t
314 ia_make_key(struct data_string *key, u_int32_t iaid,
315 	    const char *duid, unsigned int duid_len,
316 	    const char *file, int line) {
317 
318 	memset(key, 0, sizeof(*key));
319 	key->len = duid_len + sizeof(iaid);
320 	if (!buffer_allocate(&(key->buffer), key->len, file, line)) {
321 		return ISC_R_NOMEMORY;
322 	}
323 	key->data = key->buffer->data;
324 	memcpy((char *)key->data, &iaid, sizeof(iaid));
325 	memcpy((char *)key->data + sizeof(iaid), duid, duid_len);
326 
327 	return ISC_R_SUCCESS;
328 }
329 
330 /*
331  * Create a new IA structure.
332  *
333  * - ia must be a pointer to a (struct ia_xx *) pointer previously
334  *   initialized to NULL
335  * - iaid and duid are values from the client
336  *
337  * XXXsk: we don't concern ourself with the byte order of the IAID,
338  *        which might be a problem if we transfer this structure
339  *        between machines of different byte order
340  */
341 isc_result_t
342 ia_allocate(struct ia_xx **ia, u_int32_t iaid,
343 	    const char *duid, unsigned int duid_len,
344 	    const char *file, int line) {
345 	struct ia_xx *tmp;
346 
347 	if (ia == NULL) {
348 		log_error("%s(%d): NULL pointer reference", file, line);
349 		return DHCP_R_INVALIDARG;
350 	}
351 	if (*ia != NULL) {
352 		log_error("%s(%d): non-NULL pointer", file, line);
353 		return DHCP_R_INVALIDARG;
354 	}
355 
356 	tmp = dmalloc(sizeof(*tmp), file, line);
357 	if (tmp == NULL) {
358 		return ISC_R_NOMEMORY;
359 	}
360 
361 	if (ia_make_key(&tmp->iaid_duid, iaid,
362 			duid, duid_len, file, line) != ISC_R_SUCCESS) {
363 		dfree(tmp, file, line);
364 		return ISC_R_NOMEMORY;
365 	}
366 
367 	tmp->refcnt = 1;
368 
369 	*ia = tmp;
370 	return ISC_R_SUCCESS;
371 }
372 
373 /*
374  * Reference an IA structure.
375  *
376  * - ia must be a pointer to a (struct ia_xx *) pointer previously
377  *   initialized to NULL
378  */
379 isc_result_t
380 ia_reference(struct ia_xx **ia, struct ia_xx *src,
381 	     const char *file, int line) {
382 	if (ia == NULL) {
383 		log_error("%s(%d): NULL pointer reference", file, line);
384 		return DHCP_R_INVALIDARG;
385 	}
386 	if (*ia != NULL) {
387 		log_error("%s(%d): non-NULL pointer", file, line);
388 		return DHCP_R_INVALIDARG;
389 	}
390 	if (src == NULL) {
391 		log_error("%s(%d): NULL pointer reference", file, line);
392 		return DHCP_R_INVALIDARG;
393 	}
394 	*ia = src;
395 	src->refcnt++;
396 	return ISC_R_SUCCESS;
397 }
398 
399 /*
400  * Dereference an IA structure.
401  *
402  * If it is the last reference, then the memory for the
403  * structure is freed.
404  */
405 isc_result_t
406 ia_dereference(struct ia_xx **ia, const char *file, int line) {
407 	struct ia_xx *tmp;
408 	int i;
409 
410 	if ((ia == NULL) || (*ia == NULL)) {
411 		log_error("%s(%d): NULL pointer", file, line);
412 		return DHCP_R_INVALIDARG;
413 	}
414 
415 	tmp = *ia;
416 	*ia = NULL;
417 
418 	tmp->refcnt--;
419 	if (tmp->refcnt < 0) {
420 		log_error("%s(%d): negative refcnt", file, line);
421 		tmp->refcnt = 0;
422 	}
423 	if (tmp->refcnt == 0) {
424 		if (tmp->iasubopt != NULL) {
425 			for (i=0; i<tmp->num_iasubopt; i++) {
426 				iasubopt_dereference(&(tmp->iasubopt[i]),
427 						     file, line);
428 			}
429 			dfree(tmp->iasubopt, file, line);
430 		}
431 		data_string_forget(&(tmp->iaid_duid), file, line);
432 		dfree(tmp, file, line);
433 	}
434 	return ISC_R_SUCCESS;
435 }
436 
437 
438 /*
439  * Add an IAADDR/PREFIX entry to an IA structure.
440  */
441 isc_result_t
442 ia_add_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt,
443 		const char *file, int line) {
444 	int max;
445 	struct iasubopt **new;
446 
447 	/*
448 	 * Grow our array if we need to.
449 	 *
450 	 * Note: we pick 4 as the increment, as that seems a reasonable
451 	 *       guess as to how many addresses/prefixes we might expect
452 	 *       on an interface.
453 	 */
454 	if (ia->max_iasubopt <= ia->num_iasubopt) {
455 		max = ia->max_iasubopt + 4;
456 		new = dmalloc(max * sizeof(struct iasubopt *), file, line);
457 		if (new == NULL) {
458 			return ISC_R_NOMEMORY;
459 		}
460 		memcpy(new, ia->iasubopt,
461 		       ia->num_iasubopt * sizeof(struct iasubopt *));
462 		ia->iasubopt = new;
463 		ia->max_iasubopt = max;
464 	}
465 
466 	iasubopt_reference(&(ia->iasubopt[ia->num_iasubopt]), iasubopt,
467 			   file, line);
468 	ia->num_iasubopt++;
469 
470 	return ISC_R_SUCCESS;
471 }
472 
473 /*
474  * Remove an IAADDR/PREFIX entry to an IA structure.
475  *
476  * Note: if a suboption appears more than once, then only ONE will be removed.
477  */
478 void
479 ia_remove_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt,
480 		   const char *file, int line) {
481 	int i, j;
482         if (ia == NULL || iasubopt == NULL)
483             return;
484 
485 	for (i=0; i<ia->num_iasubopt; i++) {
486 		if (ia->iasubopt[i] == iasubopt) {
487 			/* remove this sub option */
488 			iasubopt_dereference(&(ia->iasubopt[i]), file, line);
489 			/* move remaining suboption pointers down one */
490 			for (j=i+1; j < ia->num_iasubopt; j++) {
491 				ia->iasubopt[j-1] = ia->iasubopt[j];
492 			}
493 			/* decrease our total count */
494 			/* remove the back-reference in the suboption itself */
495 			ia_dereference(&iasubopt->ia, file, line);
496 			ia->num_iasubopt--;
497 			return;
498 		}
499 	}
500 	log_error("%s(%d): IAADDR/PREFIX not in IA", file, line);
501 }
502 
503 /*
504  * Remove all addresses/prefixes from an IA.
505  */
506 void
507 ia_remove_all_lease(struct ia_xx *ia, const char *file, int line) {
508 	int i;
509 
510 	for (i=0; i<ia->num_iasubopt; i++) {
511 		ia_dereference(&(ia->iasubopt[i]->ia), file, line);
512 		iasubopt_dereference(&(ia->iasubopt[i]), file, line);
513 	}
514 	ia->num_iasubopt = 0;
515 }
516 
517 /*
518  * Compare two IA.
519  */
520 isc_boolean_t
521 ia_equal(const struct ia_xx *a, const struct ia_xx *b)
522 {
523 	isc_boolean_t found;
524 	int i, j;
525 
526 	/*
527 	 * Handle cases where one or both of the inputs is NULL.
528 	 */
529 	if (a == NULL) {
530 		if (b == NULL) {
531 			return ISC_TRUE;
532 		} else {
533 			return ISC_FALSE;
534 		}
535 	}
536 
537 	/*
538 	 * Check the type is the same.
539 	 */
540 	if (a->ia_type != b->ia_type) {
541 		return ISC_FALSE;
542 	}
543 
544 	/*
545 	 * Check the DUID is the same.
546 	 */
547 	if (a->iaid_duid.len != b->iaid_duid.len) {
548 		return ISC_FALSE;
549 	}
550 	if (memcmp(a->iaid_duid.data,
551 		   b->iaid_duid.data, a->iaid_duid.len) != 0) {
552 		return ISC_FALSE;
553 	}
554 
555 	/*
556 	 * Make sure we have the same number of addresses/prefixes in each.
557 	 */
558 	if (a->num_iasubopt != b->num_iasubopt) {
559 		return ISC_FALSE;
560 	}
561 
562 	/*
563 	 * Check that each address/prefix is present in both.
564 	 */
565 	for (i=0; i<a->num_iasubopt; i++) {
566 		found = ISC_FALSE;
567 		for (j=0; j<a->num_iasubopt; j++) {
568 			if (a->iasubopt[i]->plen != b->iasubopt[i]->plen)
569 				continue;
570 			if (memcmp(&(a->iasubopt[i]->addr),
571 			           &(b->iasubopt[j]->addr),
572 				   sizeof(struct in6_addr)) == 0) {
573 				found = ISC_TRUE;
574 				break;
575 			}
576 		}
577 		if (!found) {
578 			return ISC_FALSE;
579 		}
580 	}
581 
582 	/*
583 	 * These are the same in every way we care about.
584 	 */
585 	return ISC_TRUE;
586 }
587 
588 /*
589  * Helper function for lease heaps.
590  * Makes the top of the heap the oldest lease.
591  */
592 static isc_boolean_t
593 lease_older(void *a, void *b) {
594 	struct iasubopt *la = (struct iasubopt *)a;
595 	struct iasubopt *lb = (struct iasubopt *)b;
596 
597 	if (la->hard_lifetime_end_time == lb->hard_lifetime_end_time) {
598 		return difftime(la->soft_lifetime_end_time,
599 				lb->soft_lifetime_end_time) < 0;
600 	} else {
601 		return difftime(la->hard_lifetime_end_time,
602 				lb->hard_lifetime_end_time) < 0;
603 	}
604 }
605 
606 /*
607  * Helper function for lease address/prefix heaps.
608  * Callback when an address's position in the heap changes.
609  */
610 static void
611 lease_index_changed(void *iasubopt, unsigned int new_heap_index) {
612 	((struct iasubopt *)iasubopt)-> heap_index = new_heap_index;
613 }
614 
615 
616 /*!
617  *
618  * \brief Create a new IPv6 lease pool structure
619  *
620  * Allocate space for a new ipv6_pool structure and return a reference
621  * to it, includes setting the reference count to 1.
622  *
623  * \param     pool       = space for returning a referenced pointer to the pool.
624  *			   This must point to a space that has been initialzied
625  *			   to NULL by the caller.
626  * \param[in] type       = The type of the pool NA, TA or PD
627  * \param[in] start_addr = The first address in the range for the pool
628  * \param[in] bits       = The contiguous bits of the pool
629 
630  *
631  * \return
632  * ISC_R_SUCCESS     = The pool was successfully created, pool points to it.
633  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
634  *		       modified
635  * ISC_R_NOMEMORY    = The system wasn't able to allocate memory, pool has
636  *		       not been modified.
637  */
638 isc_result_t
639 ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type,
640 		   const struct in6_addr *start_addr, int bits,
641 		   int units, const char *file, int line) {
642 	struct ipv6_pool *tmp;
643 
644 	if (pool == NULL) {
645 		log_error("%s(%d): NULL pointer reference", file, line);
646 		return DHCP_R_INVALIDARG;
647 	}
648 	if (*pool != NULL) {
649 		log_error("%s(%d): non-NULL pointer", file, line);
650 		return DHCP_R_INVALIDARG;
651 	}
652 
653 	tmp = dmalloc(sizeof(*tmp), file, line);
654 	if (tmp == NULL) {
655 		return ISC_R_NOMEMORY;
656 	}
657 
658 	tmp->refcnt = 1;
659 	tmp->pool_type = type;
660 	tmp->start_addr = *start_addr;
661 	tmp->bits = bits;
662 	tmp->units = units;
663 	if (!iasubopt_new_hash(&tmp->leases, DEFAULT_HASH_SIZE, file, line)) {
664 		dfree(tmp, file, line);
665 		return ISC_R_NOMEMORY;
666 	}
667 	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, lease_index_changed,
668 			    0, &(tmp->active_timeouts)) != ISC_R_SUCCESS) {
669 		iasubopt_free_hash_table(&(tmp->leases), file, line);
670 		dfree(tmp, file, line);
671 		return ISC_R_NOMEMORY;
672 	}
673 	if (isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, lease_index_changed,
674 			    0, &(tmp->inactive_timeouts)) != ISC_R_SUCCESS) {
675 		isc_heap_destroy(&(tmp->active_timeouts));
676 		iasubopt_free_hash_table(&(tmp->leases), file, line);
677 		dfree(tmp, file, line);
678 		return ISC_R_NOMEMORY;
679 	}
680 
681 	*pool = tmp;
682 	return ISC_R_SUCCESS;
683 }
684 
685 /*!
686  *
687  * \brief reference an IPv6 pool structure.
688  *
689  * This function genreates a reference to an ipv6_pool structure
690  * and increments the reference count on the structure.
691  *
692  * \param[out] pool = space for returning a referenced pointer to the pool.
693  *		      This must point to a space that has been initialzied
694  *		      to NULL by the caller.
695  * \param[in]  src  = A pointer to the pool to reference.  This must not be
696  *		      NULL.
697  *
698  * \return
699  * ISC_R_SUCCESS     = The pool was successfully referenced, pool now points
700  *		       to src.
701  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
702  *		       modified.
703  */
704 isc_result_t
705 ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src,
706 		    const char *file, int line) {
707 	if (pool == NULL) {
708 		log_error("%s(%d): NULL pointer reference", file, line);
709 		return DHCP_R_INVALIDARG;
710 	}
711 	if (*pool != NULL) {
712 		log_error("%s(%d): non-NULL pointer", file, line);
713 		return DHCP_R_INVALIDARG;
714 	}
715 	if (src == NULL) {
716 		log_error("%s(%d): NULL pointer reference", file, line);
717 		return DHCP_R_INVALIDARG;
718 	}
719 	*pool = src;
720 	src->refcnt++;
721 	return ISC_R_SUCCESS;
722 }
723 
724 /*
725  * Note: Each IAADDR/PREFIX in a pool is referenced by the pool. This is needed
726  * to prevent the lease from being garbage collected out from under the
727  * pool.
728  *
729  * The references are made from the hash and from the heap. The following
730  * helper functions dereference these when a pool is destroyed.
731  */
732 
733 /*
734  * Helper function for pool cleanup.
735  * Dereference each of the hash entries in a pool.
736  */
737 static isc_result_t
738 dereference_hash_entry(const void *name, unsigned len, void *value) {
739 	struct iasubopt *iasubopt = (struct iasubopt *)value;
740 
741 	iasubopt_dereference(&iasubopt, MDL);
742 	return ISC_R_SUCCESS;
743 }
744 
745 /*
746  * Helper function for pool cleanup.
747  * Dereference each of the heap entries in a pool.
748  */
749 static void
750 dereference_heap_entry(void *value, void *dummy) {
751 	struct iasubopt *iasubopt = (struct iasubopt *)value;
752 
753 	iasubopt_dereference(&iasubopt, MDL);
754 }
755 
756 /*!
757  *
758  * \brief de-reference an IPv6 pool structure.
759  *
760  * This function decrements the reference count in an ipv6_pool structure.
761  * If this was the last reference then the memory for the structure is
762  * freed.
763  *
764  * \param[in] pool = A pointer to the pointer to the pool that should be
765  *		     de-referenced.  On success the pointer to the pool
766  *		     is cleared.  It must not be NULL and must not point
767  *		     to NULL.
768  *
769  * \return
770  * ISC_R_SUCCESS     = The pool was successfully de-referenced, pool now points
771  *		       to NULL
772  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
773  *		       modified.
774  */
775 isc_result_t
776 ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line) {
777 	struct ipv6_pool *tmp;
778 
779 	if ((pool == NULL) || (*pool == NULL)) {
780 		log_error("%s(%d): NULL pointer", file, line);
781 		return DHCP_R_INVALIDARG;
782 	}
783 
784 	tmp = *pool;
785 	*pool = NULL;
786 
787 	tmp->refcnt--;
788 	if (tmp->refcnt < 0) {
789 		log_error("%s(%d): negative refcnt", file, line);
790 		tmp->refcnt = 0;
791 	}
792 	if (tmp->refcnt == 0) {
793 		iasubopt_hash_foreach(tmp->leases, dereference_hash_entry);
794 		iasubopt_free_hash_table(&(tmp->leases), file, line);
795 		isc_heap_foreach(tmp->active_timeouts,
796 				 dereference_heap_entry, NULL);
797 		isc_heap_destroy(&(tmp->active_timeouts));
798 		isc_heap_foreach(tmp->inactive_timeouts,
799 				 dereference_heap_entry, NULL);
800 		isc_heap_destroy(&(tmp->inactive_timeouts));
801 		dfree(tmp, file, line);
802 	}
803 
804 	return ISC_R_SUCCESS;
805 }
806 
807 /*
808  * Create an address by hashing the input, and using that for
809  * the non-network part.
810  */
811 static void
812 build_address6(struct in6_addr *addr,
813 	       const struct in6_addr *net_start_addr, int net_bits,
814 	       const struct data_string *input) {
815 	isc_md5_t ctx;
816 	int net_bytes;
817 	int i;
818 	char *str;
819 	const char *net_str;
820 
821 	/*
822 	 * Use MD5 to get a nice 128 bit hash of the input.
823 	 * Yes, we know MD5 isn't cryptographically sound.
824 	 * No, we don't care.
825 	 */
826 	isc_md5_init(&ctx);
827 	isc_md5_update(&ctx, input->data, input->len);
828 	isc_md5_final(&ctx, (unsigned char *)addr);
829 
830 	/*
831 	 * Copy the [0..128] network bits over.
832 	 */
833 	str = (char *)addr;
834 	net_str = (const char *)net_start_addr;
835 	net_bytes = net_bits / 8;
836 	for (i = 0; i < net_bytes; i++) {
837 		str[i] = net_str[i];
838 	}
839 	switch (net_bits % 8) {
840 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
841 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
842 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
843 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
844 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
845 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
846 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
847 	}
848 
849 	/*
850 	 * Set the universal/local bit ("u bit") to zero for /64s.  The
851 	 * individual/group bit ("g bit") is unchanged, because the g-bit
852 	 * has no meaning when the u-bit is cleared.
853 	 */
854 	if (net_bits == 64)
855 		str[8] &= ~0x02;
856 }
857 
858 /*
859  * Create a temporary address by a variant of RFC 4941 algo.
860  * Note: this should not be used for prefixes shorter than 64 bits.
861  */
862 static void
863 build_temporary6(struct in6_addr *addr,
864 		 const struct in6_addr *net_start_addr, int net_bits,
865 		 const struct data_string *input) {
866 	static u_int32_t history[2];
867 	static u_int32_t counter = 0;
868 	isc_md5_t ctx;
869 	unsigned char md[16];
870 
871 	/*
872 	 * First time/time to reseed.
873 	 * Please use a good pseudo-random generator here!
874 	 */
875 	if (counter == 0) {
876 		isc_random_get(&history[0]);
877 		isc_random_get(&history[1]);
878 	}
879 
880 	/*
881 	 * Use MD5 as recommended by RFC 4941.
882 	 */
883 	isc_md5_init(&ctx);
884 	isc_md5_update(&ctx, (unsigned char *)&history[0], 8UL);
885 	isc_md5_update(&ctx, input->data, input->len);
886 	isc_md5_final(&ctx, md);
887 
888 	/*
889 	 * Build the address.
890 	 */
891 	if (net_bits == 64) {
892 		memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8);
893 		memcpy(&addr->s6_addr[8], md, 8);
894 		addr->s6_addr[8] &= ~0x02;
895 	} else {
896 		int net_bytes;
897 		int i;
898 		char *str;
899 		const char *net_str;
900 
901 		/*
902 		 * Copy the [0..128] network bits over.
903 		 */
904 		str = (char *)addr;
905 		net_str = (const char *)net_start_addr;
906 		net_bytes = net_bits / 8;
907 		for (i = 0; i < net_bytes; i++) {
908 			str[i] = net_str[i];
909 		}
910 		memcpy(str + net_bytes, md, 16 - net_bytes);
911 		switch (net_bits % 8) {
912 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
913 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
914 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
915 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
916 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
917 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
918 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
919 		}
920 	}
921 
922 
923 	/*
924 	 * Save history for the next call.
925 	 */
926 	memcpy((unsigned char *)&history[0], md + 8, 8);
927 	counter++;
928 }
929 
930 /* Reserved Subnet Router Anycast ::0:0:0:0. */
931 static struct in6_addr rtany;
932 /* Reserved Subnet Anycasts ::fdff:ffff:ffff:ff80-::fdff:ffff:ffff:ffff. */
933 static struct in6_addr resany;
934 
935 /*
936  * Create a lease for the given address and client duid.
937  *
938  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
939  *   initialized to NULL
940  *
941  * Right now we simply hash the DUID, and if we get a collision, we hash
942  * again until we find a free address. We try this a fixed number of times,
943  * to avoid getting stuck in a loop (this is important on small pools
944  * where we can run out of space).
945  *
946  * We return the number of attempts that it took to find an available
947  * lease. This tells callers when a pool is are filling up, as
948  * well as an indication of how full the pool is; statistically the
949  * more full a pool is the more attempts must be made before finding
950  * a free lease. Realistically this will only happen in very full
951  * pools.
952  *
953  * We probably want different algorithms depending on the network size, in
954  * the long term.
955  */
956 isc_result_t
957 create_lease6(struct ipv6_pool *pool, struct iasubopt **addr,
958 	      unsigned int *attempts,
959 	      const struct data_string *uid, time_t soft_lifetime_end_time) {
960 	struct data_string ds;
961 	struct in6_addr tmp;
962 	struct iasubopt *test_iaaddr;
963 	struct data_string new_ds;
964 	struct iasubopt *iaaddr;
965 	isc_result_t result;
966 	isc_boolean_t reserved_iid;
967 	static isc_boolean_t init_resiid = ISC_FALSE;
968 
969 	/*
970 	 * Fill the reserved IIDs.
971 	 */
972 	if (!init_resiid) {
973 		memset(&rtany, 0, 16);
974 		memset(&resany, 0, 8);
975 		resany.s6_addr[8] = 0xfd;
976 		memset(&resany.s6_addr[9], 0xff, 6);
977 		init_resiid = ISC_TRUE;
978 	}
979 
980 	/*
981 	 * Use the UID as our initial seed for the hash
982 	 */
983 	memset(&ds, 0, sizeof(ds));
984 	data_string_copy(&ds, (struct data_string *)uid, MDL);
985 
986 	*attempts = 0;
987 	for (;;) {
988 		/*
989 		 * Give up at some point.
990 		 */
991 		if (++(*attempts) > 100) {
992 			data_string_forget(&ds, MDL);
993 			return ISC_R_NORESOURCES;
994 		}
995 
996 		/*
997 		 * Build a resource.
998 		 */
999 		switch (pool->pool_type) {
1000 		case D6O_IA_NA:
1001 			/* address */
1002 			build_address6(&tmp, &pool->start_addr,
1003 				       pool->bits, &ds);
1004 			break;
1005 		case D6O_IA_TA:
1006 			/* temporary address */
1007 			build_temporary6(&tmp, &pool->start_addr,
1008 					 pool->bits, &ds);
1009 			break;
1010 		case D6O_IA_PD:
1011 			/* prefix */
1012 			log_error("create_lease6: prefix pool.");
1013 			return DHCP_R_INVALIDARG;
1014 		default:
1015 			log_error("create_lease6: untyped pool.");
1016 			return DHCP_R_INVALIDARG;
1017 		}
1018 
1019 		/*
1020 		 * Avoid reserved interface IDs. (cf. RFC 5453)
1021 		 */
1022 		reserved_iid = ISC_FALSE;
1023 		if (memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) {
1024 			reserved_iid = ISC_TRUE;
1025 		}
1026 		if (!reserved_iid &&
1027 		    (memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
1028 		    ((tmp.s6_addr[15] & 0x80) == 0x80)) {
1029 			reserved_iid = ISC_TRUE;
1030 		}
1031 
1032 		/*
1033 		 * If this address is not in use, we're happy with it
1034 		 */
1035 		test_iaaddr = NULL;
1036 		if (!reserved_iid &&
1037 		    (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
1038 					  &tmp, sizeof(tmp), MDL) == 0)) {
1039 			break;
1040 		}
1041 		if (test_iaaddr != NULL)
1042 			iasubopt_dereference(&test_iaaddr, MDL);
1043 
1044 		/*
1045 		 * Otherwise, we create a new input, adding the address
1046 		 */
1047 		memset(&new_ds, 0, sizeof(new_ds));
1048 		new_ds.len = ds.len + sizeof(tmp);
1049 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
1050 			data_string_forget(&ds, MDL);
1051 			return ISC_R_NOMEMORY;
1052 		}
1053 		new_ds.data = new_ds.buffer->data;
1054 		memcpy(new_ds.buffer->data, ds.data, ds.len);
1055 		memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
1056 		data_string_forget(&ds, MDL);
1057 		data_string_copy(&ds, &new_ds, MDL);
1058 		data_string_forget(&new_ds, MDL);
1059 	}
1060 
1061 	data_string_forget(&ds, MDL);
1062 
1063 	/*
1064 	 * We're happy with the address, create an IAADDR
1065 	 * to hold it.
1066 	 */
1067 	iaaddr = NULL;
1068 	result = iasubopt_allocate(&iaaddr, MDL);
1069 	if (result != ISC_R_SUCCESS) {
1070 		return result;
1071 	}
1072 	iaaddr->plen = 0;
1073 	memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
1074 
1075 	/*
1076 	 * Add the lease to the pool (note state is free, not active?!).
1077 	 */
1078 	result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
1079 	if (result == ISC_R_SUCCESS) {
1080 		iasubopt_reference(addr, iaaddr, MDL);
1081 	}
1082 	iasubopt_dereference(&iaaddr, MDL);
1083 	return result;
1084 }
1085 
1086 
1087 /*!
1088  *
1089  * \brief Cleans up leases when reading from a lease file
1090  *
1091  * This function is only expected to be run when reading leases in from a file.
1092  * It checks to see if a lease already exists for the new leases's address.
1093  * We don't add expired leases to the structures when reading a lease file
1094  * which limits what can happen.  We have two variables the owners of the leases
1095  * being the same or different and the new lease being active or non-active:
1096  * Owners active
1097  * same   no     remove old lease and its connections
1098  * same   yes    nothing to do, other code will update the structures.
1099  * diff   no     nothing to do
1100  * diff   yes    this combination shouldn't happen, we should only have a
1101  *               single active lease per address at a time and that lease
1102  *               should move to non-active before any other lease can
1103  *               become active for that address.
1104  *               Currently we delete the previous lease and pass an error
1105  *               to the caller who should log an error.
1106  *
1107  * When we remove a lease we remove it from the hash table and active heap
1108  * (remember only active leases are in the structures at this time) for the
1109  * pool, and from the IA's array.  If, after we've removed the pointer from
1110  * IA's array to the lease, the IA has no more pointers we remove it from
1111  * the appropriate hash table as well.
1112  *
1113  * \param[in] ia_table = the hash table for the IA
1114  * \param[in] pool     = the pool to update
1115  * \param[in] lease    = the new lease we want to add
1116  * \param[in] ia       = the new ia we are building
1117  *
1118  * \return
1119  * ISC_R_SUCCESS = the incoming lease and any previous lease were in
1120  *                 an expected state - one of the first 3 options above.
1121  *                 If necessary the old lease was removed.
1122  * ISC_R_FAILURE = there is already an active lease for the address in
1123  *                 the incoming lease.  This shouldn't happen if it does
1124  *                 flag an error for the caller to log.
1125  */
1126 
1127 isc_result_t
1128 cleanup_lease6(ia_hash_t *ia_table,
1129 	       struct ipv6_pool *pool,
1130 	       struct iasubopt *lease,
1131 	       struct ia_xx *ia) {
1132 
1133 	struct iasubopt *test_iasubopt, *tmp_iasubopt;
1134 	struct ia_xx *old_ia;
1135 	isc_result_t status = ISC_R_SUCCESS;
1136 
1137 	test_iasubopt = NULL;
1138 	old_ia = NULL;
1139 
1140 	/*
1141 	 * Look up the address - if we don't find a lease
1142 	 * we don't need to do anything.
1143 	 */
1144 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
1145 				 &lease->addr, sizeof(lease->addr),
1146 				 MDL) == 0) {
1147 		return (ISC_R_SUCCESS);
1148 	}
1149 
1150 	if (test_iasubopt->ia == NULL) {
1151 		/* no old ia, no work to do */
1152 		iasubopt_dereference(&test_iasubopt, MDL);
1153 		return (status);
1154 	}
1155 
1156 	ia_reference(&old_ia, test_iasubopt->ia, MDL);
1157 
1158 	if ((old_ia->iaid_duid.len == ia->iaid_duid.len) &&
1159 	    (memcmp((unsigned char *)ia->iaid_duid.data,
1160 		    (unsigned char *)old_ia->iaid_duid.data,
1161 		    ia->iaid_duid.len) == 0)) {
1162 		/* same IA */
1163 		if ((lease->state == FTS_ACTIVE) ||
1164 		    (lease->state == FTS_ABANDONED)) {
1165 			/* still active, no need to delete */
1166 			goto cleanup;
1167 		}
1168 	} else {
1169 		/* different IA */
1170 		if ((lease->state != FTS_ACTIVE) &&
1171 		    (lease->state != FTS_ABANDONED)) {
1172 			/* new lease isn't active, no work */
1173 			goto cleanup;
1174 		}
1175 
1176 		/*
1177 		 * We appear to have two active leases, this shouldn't happen.
1178 		 * Before a second lease can be set to active the first lease
1179 		 * should be set to inactive (released, expired etc). For now
1180 		 * delete the previous lease and indicate a failure to the
1181 		 * caller so it can generate a warning.
1182 		 * In the future we may try and determine which is the better
1183 		 * lease to keep.
1184 		 */
1185 
1186 		status = ISC_R_FAILURE;
1187 	}
1188 
1189 	/*
1190 	 * Remove the old lease from the active heap and from the hash table
1191 	 * then remove the lease from the IA and clean up the IA if necessary.
1192 	 */
1193 	isc_heap_delete(pool->active_timeouts, test_iasubopt->heap_index);
1194 	pool->num_active--;
1195 
1196 	iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
1197 			     sizeof(test_iasubopt->addr), MDL);
1198 	ia_remove_iasubopt(old_ia, test_iasubopt, MDL);
1199 	if (old_ia->num_iasubopt <= 0) {
1200 		ia_hash_delete(ia_table,
1201 			       (unsigned char *)old_ia->iaid_duid.data,
1202 			       old_ia->iaid_duid.len, MDL);
1203 	}
1204 
1205 	/*
1206 	 * We derefenrece the subopt here as we've just removed it from
1207 	 * the hash table in the pool.  We need to make a copy as we
1208 	 * need to derefernece it again later.
1209 	 */
1210 	tmp_iasubopt = test_iasubopt;
1211 	iasubopt_dereference(&tmp_iasubopt, MDL);
1212 
1213       cleanup:
1214 	ia_dereference(&old_ia, MDL);
1215 
1216 	/*
1217 	 * Clean up the reference, this is in addition to the deference
1218 	 * above after removing the entry from the hash table
1219 	 */
1220 	iasubopt_dereference(&test_iasubopt, MDL);
1221 
1222 	return (status);
1223 }
1224 
1225 /*
1226  * Put a lease in the pool directly. This is intended to be used when
1227  * loading leases from the file.
1228  */
1229 isc_result_t
1230 add_lease6(struct ipv6_pool *pool, struct iasubopt *lease,
1231 	   time_t valid_lifetime_end_time) {
1232 	isc_result_t insert_result;
1233 	struct iasubopt *test_iasubopt;
1234 	struct iasubopt *tmp_iasubopt;
1235 
1236 	/* If a state was not assigned by the caller, assume active. */
1237 	if (lease->state == 0)
1238 		lease->state = FTS_ACTIVE;
1239 
1240 	ipv6_pool_reference(&lease->ipv6_pool, pool, MDL);
1241 
1242 	/*
1243 	 * If this IAADDR/PREFIX is already in our structures, remove the
1244 	 * old one.
1245 	 */
1246 	test_iasubopt = NULL;
1247 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
1248 				 &lease->addr, sizeof(lease->addr), MDL)) {
1249 		/* XXX: we should probably ask the lease what heap it is on
1250 		 * (as a consistency check).
1251 		 * XXX: we should probably have one function to "put this lease
1252 		 * on its heap" rather than doing these if's everywhere.  If
1253 		 * you add more states to this list, don't.
1254 		 */
1255 		if ((test_iasubopt->state == FTS_ACTIVE) ||
1256 		    (test_iasubopt->state == FTS_ABANDONED)) {
1257 			isc_heap_delete(pool->active_timeouts,
1258 					test_iasubopt->heap_index);
1259 			pool->num_active--;
1260 		} else {
1261 			isc_heap_delete(pool->inactive_timeouts,
1262 					test_iasubopt->heap_index);
1263 			pool->num_inactive--;
1264 		}
1265 
1266 		iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
1267 				     sizeof(test_iasubopt->addr), MDL);
1268 
1269 		/*
1270 		 * We're going to do a bit of evil trickery here.
1271 		 *
1272 		 * We need to dereference the entry once to remove our
1273 		 * current reference (in test_iasubopt), and then one
1274 		 * more time to remove the reference left when the
1275 		 * address was added to the pool before.
1276 		 */
1277 		tmp_iasubopt = test_iasubopt;
1278 		iasubopt_dereference(&test_iasubopt, MDL);
1279 		iasubopt_dereference(&tmp_iasubopt, MDL);
1280 	}
1281 
1282 	/*
1283 	 * Add IAADDR/PREFIX to our structures.
1284 	 */
1285 	tmp_iasubopt = NULL;
1286 	iasubopt_reference(&tmp_iasubopt, lease, MDL);
1287 	if ((tmp_iasubopt->state == FTS_ACTIVE) ||
1288 	    (tmp_iasubopt->state == FTS_ABANDONED)) {
1289 		tmp_iasubopt->hard_lifetime_end_time = valid_lifetime_end_time;
1290 		iasubopt_hash_add(pool->leases, &tmp_iasubopt->addr,
1291 				  sizeof(tmp_iasubopt->addr), lease, MDL);
1292 		insert_result = isc_heap_insert(pool->active_timeouts,
1293 						tmp_iasubopt);
1294 		if (insert_result == ISC_R_SUCCESS)
1295 			pool->num_active++;
1296 	} else {
1297 		tmp_iasubopt->soft_lifetime_end_time = valid_lifetime_end_time;
1298 		insert_result = isc_heap_insert(pool->inactive_timeouts,
1299 						tmp_iasubopt);
1300 		if (insert_result == ISC_R_SUCCESS)
1301 			pool->num_inactive++;
1302 	}
1303 	if (insert_result != ISC_R_SUCCESS) {
1304 		iasubopt_hash_delete(pool->leases, &lease->addr,
1305 				     sizeof(lease->addr), MDL);
1306 		iasubopt_dereference(&tmp_iasubopt, MDL);
1307 		return insert_result;
1308 	}
1309 
1310 	/*
1311 	 * Note: we intentionally leave tmp_iasubopt referenced; there
1312 	 * is a reference in the heap/hash, after all.
1313 	 */
1314 
1315 	return ISC_R_SUCCESS;
1316 }
1317 
1318 /*
1319  * Determine if an address is present in a pool or not.
1320  */
1321 isc_boolean_t
1322 lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
1323 	struct iasubopt *test_iaaddr;
1324 
1325 	test_iaaddr = NULL;
1326 	if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
1327 				 (void *)addr, sizeof(*addr), MDL)) {
1328 		iasubopt_dereference(&test_iaaddr, MDL);
1329 		return ISC_TRUE;
1330 	} else {
1331 		return ISC_FALSE;
1332 	}
1333 }
1334 
1335 /*!
1336  *
1337  * \brief Check if address is available to a lease
1338  *
1339  * Determine if the address in the lease is available to that
1340  * lease.  Either the address isn't in use or it is in use
1341  * but by that lease.
1342  *
1343  * \param[in] lease = lease to check
1344  *
1345  * \return
1346  * ISC_TRUE  = The lease is allowed to use that address
1347  * ISC_FALSE = The lease isn't allowed to use that address
1348  */
1349 isc_boolean_t
1350 lease6_usable(struct iasubopt *lease) {
1351 	struct iasubopt *test_iaaddr;
1352 	isc_boolean_t status = ISC_TRUE;
1353 
1354 	test_iaaddr = NULL;
1355 	if (iasubopt_hash_lookup(&test_iaaddr, lease->ipv6_pool->leases,
1356 				 (void *)&lease->addr,
1357 				 sizeof(lease->addr), MDL)) {
1358 		if (test_iaaddr != lease) {
1359 			status = ISC_FALSE;
1360 		}
1361 		iasubopt_dereference(&test_iaaddr, MDL);
1362 	}
1363 
1364 	return (status);
1365 }
1366 
1367 /*
1368  * Put the lease on our active pool.
1369  */
1370 static isc_result_t
1371 move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) {
1372 	isc_result_t insert_result;
1373 	int old_heap_index;
1374 
1375 	old_heap_index = lease->heap_index;
1376 	insert_result = isc_heap_insert(pool->active_timeouts, lease);
1377 	if (insert_result == ISC_R_SUCCESS) {
1378        		iasubopt_hash_add(pool->leases, &lease->addr,
1379 				  sizeof(lease->addr), lease, MDL);
1380 		isc_heap_delete(pool->inactive_timeouts, old_heap_index);
1381 		pool->num_active++;
1382 		pool->num_inactive--;
1383 		lease->state = FTS_ACTIVE;
1384 	}
1385 	return insert_result;
1386 }
1387 
1388 /*!
1389  *
1390  * \brief Renew a lease in the pool.
1391  *
1392  * The hard_lifetime_end_time of the lease should be set to
1393  * the current expiration time.
1394  * The soft_lifetime_end_time of the lease should be set to
1395  * the desired expiration time.
1396  *
1397  * This routine will compare the two and call the correct
1398  * heap routine to move the lease.  If the lease is active
1399  * and the new expiration time is greater (the normal case)
1400  * then we call isc_heap_decreased() as a larger time is a
1401  * lower priority.  If the new expiration time is less then
1402  * we call isc_heap_increased().
1403  *
1404  * If the lease is abandoned then it will be on the active list
1405  * and we will always call isc_heap_increased() as the previous
1406  * expiration would have been all 1s (as close as we can get
1407  * to infinite).
1408  *
1409  * If the lease is moving to active we call that routine
1410  * which will move it from the inactive list to the active list.
1411  *
1412  * \param pool  = a pool the lease belongs to
1413  * \param lease = the lease to be renewed
1414  *
1415  * \return result of the renew operation (ISC_R_SUCCESS if successful,
1416            ISC_R_NOMEMORY when run out of memory)
1417  */
1418 isc_result_t
1419 renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1420 	time_t old_end_time = lease->hard_lifetime_end_time;
1421 	lease->hard_lifetime_end_time = lease->soft_lifetime_end_time;
1422 	lease->soft_lifetime_end_time = 0;
1423 
1424 	if (lease->state == FTS_ACTIVE) {
1425 		if (old_end_time <= lease->hard_lifetime_end_time) {
1426 			isc_heap_decreased(pool->active_timeouts,
1427 					   lease->heap_index);
1428 		} else {
1429 			isc_heap_increased(pool->active_timeouts,
1430 					   lease->heap_index);
1431 		}
1432 		return ISC_R_SUCCESS;
1433 	} else if (lease->state == FTS_ABANDONED) {
1434 		char tmp_addr[INET6_ADDRSTRLEN];
1435                 lease->state = FTS_ACTIVE;
1436                 isc_heap_increased(pool->active_timeouts, lease->heap_index);
1437 		log_info("Reclaiming previously abandoned address %s",
1438 			 inet_ntop(AF_INET6, &(lease->addr), tmp_addr,
1439 				   sizeof(tmp_addr)));
1440                 return ISC_R_SUCCESS;
1441 	} else {
1442 		return move_lease_to_active(pool, lease);
1443 	}
1444 }
1445 
1446 /*
1447  * Put the lease on our inactive pool, with the specified state.
1448  */
1449 static isc_result_t
1450 move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
1451 		       binding_state_t state) {
1452 	isc_result_t insert_result;
1453 	int old_heap_index;
1454 
1455 	old_heap_index = lease->heap_index;
1456 	insert_result = isc_heap_insert(pool->inactive_timeouts, lease);
1457 	if (insert_result == ISC_R_SUCCESS) {
1458 		/*
1459 		 * Handle expire and release statements
1460 		 * To get here we must be active and have done a commit so
1461 		 * we should run the proper statements if they exist, though
1462 		 * that will change when we remove the inactive heap.
1463 		 * In addition we get rid of the references for both as we
1464 		 * can only do one (expire or release) on a lease
1465 		 */
1466 		if (lease->on_star.on_expiry != NULL) {
1467 			if (state == FTS_EXPIRED) {
1468 				execute_statements(NULL, NULL, NULL,
1469 						   NULL, NULL, NULL,
1470 						   &lease->scope,
1471 						   lease->on_star.on_expiry,
1472 						   &lease->on_star);
1473 			}
1474 			executable_statement_dereference
1475 				(&lease->on_star.on_expiry, MDL);
1476 		}
1477 
1478 		if (lease->on_star.on_release != NULL) {
1479 			if (state == FTS_RELEASED) {
1480 				execute_statements(NULL, NULL, NULL,
1481 						   NULL, NULL, NULL,
1482 						   &lease->scope,
1483 						   lease->on_star.on_release,
1484 						   &lease->on_star);
1485 			}
1486 			executable_statement_dereference
1487 				(&lease->on_star.on_release, MDL);
1488 		}
1489 
1490 #if defined (NSUPDATE)
1491 		/* Process events upon expiration. */
1492 		if (pool->pool_type != D6O_IA_PD) {
1493 			(void) ddns_removals(NULL, lease, NULL, ISC_FALSE);
1494 		}
1495 #endif
1496 
1497 		/* Binding scopes are no longer valid after expiry or
1498 		 * release.
1499 		 */
1500 		if (lease->scope != NULL) {
1501 			binding_scope_dereference(&lease->scope, MDL);
1502 		}
1503 
1504 		iasubopt_hash_delete(pool->leases,
1505 				     &lease->addr, sizeof(lease->addr), MDL);
1506 		isc_heap_delete(pool->active_timeouts, old_heap_index);
1507 		lease->state = state;
1508 		pool->num_active--;
1509 		pool->num_inactive++;
1510 	}
1511 	return insert_result;
1512 }
1513 
1514 /*
1515  * Expire the oldest lease if it's lifetime_end_time is
1516  * older than the given time.
1517  *
1518  * - leasep must be a pointer to a (struct iasubopt *) pointer previously
1519  *   initialized to NULL
1520  *
1521  * On return leasep has a reference to the removed entry. It is left
1522  * pointing to NULL if the oldest lease has not expired.
1523  */
1524 isc_result_t
1525 expire_lease6(struct iasubopt **leasep, struct ipv6_pool *pool, time_t now) {
1526 	struct iasubopt *tmp;
1527 	isc_result_t result;
1528 
1529 	if (leasep == NULL) {
1530 		log_error("%s(%d): NULL pointer reference", MDL);
1531 		return DHCP_R_INVALIDARG;
1532 	}
1533 	if (*leasep != NULL) {
1534 		log_error("%s(%d): non-NULL pointer", MDL);
1535 		return DHCP_R_INVALIDARG;
1536 	}
1537 
1538 	if (pool->num_active > 0) {
1539 		tmp = (struct iasubopt *)
1540 				isc_heap_element(pool->active_timeouts, 1);
1541 		if (now > tmp->hard_lifetime_end_time) {
1542 			result = move_lease_to_inactive(pool, tmp,
1543 							FTS_EXPIRED);
1544 			if (result == ISC_R_SUCCESS) {
1545 				iasubopt_reference(leasep, tmp, MDL);
1546 			}
1547 			return result;
1548 		}
1549 	}
1550 	return ISC_R_SUCCESS;
1551 }
1552 
1553 
1554 /*
1555  * For a declined lease, leave it on the "active" pool, but mark
1556  * it as declined. Give it an infinite (well, really long) life.
1557  */
1558 isc_result_t
1559 decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1560 	isc_result_t result;
1561 
1562 	if ((lease->state != FTS_ACTIVE) &&
1563 	    (lease->state != FTS_ABANDONED)) {
1564 		result = move_lease_to_active(pool, lease);
1565 		if (result != ISC_R_SUCCESS) {
1566 			return result;
1567 		}
1568 	}
1569 	lease->state = FTS_ABANDONED;
1570 	lease->hard_lifetime_end_time = MAX_TIME;
1571 	isc_heap_decreased(pool->active_timeouts, lease->heap_index);
1572 	return ISC_R_SUCCESS;
1573 }
1574 
1575 /*
1576  * Put the returned lease on our inactive pool.
1577  */
1578 isc_result_t
1579 release_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
1580 	if (lease->state == FTS_ACTIVE) {
1581 		return move_lease_to_inactive(pool, lease, FTS_RELEASED);
1582 	} else {
1583 		return ISC_R_SUCCESS;
1584 	}
1585 }
1586 
1587 /*
1588  * Create a prefix by hashing the input, and using that for
1589  * the part subject to allocation.
1590  */
1591 static void
1592 build_prefix6(struct in6_addr *pref,
1593 	      const struct in6_addr *net_start_pref,
1594 	      int pool_bits, int pref_bits,
1595 	      const struct data_string *input) {
1596 	isc_md5_t ctx;
1597 	int net_bytes;
1598 	int i;
1599 	char *str;
1600 	const char *net_str;
1601 
1602 	/*
1603 	 * Use MD5 to get a nice 128 bit hash of the input.
1604 	 * Yes, we know MD5 isn't cryptographically sound.
1605 	 * No, we don't care.
1606 	 */
1607 	isc_md5_init(&ctx);
1608 	isc_md5_update(&ctx, input->data, input->len);
1609 	isc_md5_final(&ctx, (unsigned char *)pref);
1610 
1611 	/*
1612 	 * Copy the network bits over.
1613 	 */
1614 	str = (char *)pref;
1615 	net_str = (const char *)net_start_pref;
1616 	net_bytes = pool_bits / 8;
1617 	for (i = 0; i < net_bytes; i++) {
1618 		str[i] = net_str[i];
1619 	}
1620 	i = net_bytes;
1621 	switch (pool_bits % 8) {
1622 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
1623 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
1624 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
1625 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
1626 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
1627 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
1628 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
1629 	}
1630 	/*
1631 	 * Zero the remaining bits.
1632 	 */
1633 	net_bytes = pref_bits / 8;
1634 	for (i=net_bytes+1; i<16; i++) {
1635 		str[i] = 0;
1636 	}
1637 	i = net_bytes;
1638 	switch (pref_bits % 8) {
1639 		case 0: str[i] &= 0; break;
1640 		case 1: str[i] &= 0x80; break;
1641 		case 2: str[i] &= 0xC0; break;
1642 		case 3: str[i] &= 0xE0; break;
1643 		case 4: str[i] &= 0xF0; break;
1644 		case 5: str[i] &= 0xF8; break;
1645 		case 6: str[i] &= 0xFC; break;
1646 		case 7: str[i] &= 0xFE; break;
1647 	}
1648 }
1649 
1650 /*
1651  * Create a lease for the given prefix and client duid.
1652  *
1653  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
1654  *   initialized to NULL
1655  *
1656  * Right now we simply hash the DUID, and if we get a collision, we hash
1657  * again until we find a free prefix. We try this a fixed number of times,
1658  * to avoid getting stuck in a loop (this is important on small pools
1659  * where we can run out of space).
1660  *
1661  * We return the number of attempts that it took to find an available
1662  * prefix. This tells callers when a pool is are filling up, as
1663  * well as an indication of how full the pool is; statistically the
1664  * more full a pool is the more attempts must be made before finding
1665  * a free prefix. Realistically this will only happen in very full
1666  * pools.
1667  *
1668  * We probably want different algorithms depending on the network size, in
1669  * the long term.
1670  */
1671 isc_result_t
1672 create_prefix6(struct ipv6_pool *pool, struct iasubopt **pref,
1673 	       unsigned int *attempts,
1674 	       const struct data_string *uid,
1675 	       time_t soft_lifetime_end_time) {
1676 	struct data_string ds;
1677 	struct in6_addr tmp;
1678 	struct iasubopt *test_iapref;
1679 	struct data_string new_ds;
1680 	struct iasubopt *iapref;
1681 	isc_result_t result;
1682 
1683 	/*
1684 	 * Use the UID as our initial seed for the hash
1685 	 */
1686 	memset(&ds, 0, sizeof(ds));
1687 	data_string_copy(&ds, (struct data_string *)uid, MDL);
1688 
1689 	*attempts = 0;
1690 	for (;;) {
1691 		/*
1692 		 * Give up at some point.
1693 		 */
1694 		if (++(*attempts) > 10) {
1695 			data_string_forget(&ds, MDL);
1696 			return ISC_R_NORESOURCES;
1697 		}
1698 
1699 		/*
1700 		 * Build a prefix
1701 		 */
1702 		build_prefix6(&tmp, &pool->start_addr,
1703 			      pool->bits, pool->units, &ds);
1704 
1705 		/*
1706 		 * If this prefix is not in use, we're happy with it
1707 		 */
1708 		test_iapref = NULL;
1709 		if (iasubopt_hash_lookup(&test_iapref, pool->leases,
1710 					 &tmp, sizeof(tmp), MDL) == 0) {
1711 			break;
1712 		}
1713 		iasubopt_dereference(&test_iapref, MDL);
1714 
1715 		/*
1716 		 * Otherwise, we create a new input, adding the prefix
1717 		 */
1718 		memset(&new_ds, 0, sizeof(new_ds));
1719 		new_ds.len = ds.len + sizeof(tmp);
1720 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
1721 			data_string_forget(&ds, MDL);
1722 			return ISC_R_NOMEMORY;
1723 		}
1724 		new_ds.data = new_ds.buffer->data;
1725 		memcpy(new_ds.buffer->data, ds.data, ds.len);
1726 		memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
1727 		data_string_forget(&ds, MDL);
1728 		data_string_copy(&ds, &new_ds, MDL);
1729 		data_string_forget(&new_ds, MDL);
1730 	}
1731 
1732 	data_string_forget(&ds, MDL);
1733 
1734 	/*
1735 	 * We're happy with the prefix, create an IAPREFIX
1736 	 * to hold it.
1737 	 */
1738 	iapref = NULL;
1739 	result = iasubopt_allocate(&iapref, MDL);
1740 	if (result != ISC_R_SUCCESS) {
1741 		return result;
1742 	}
1743 	iapref->plen = (u_int8_t)pool->units;
1744 	memcpy(&iapref->addr, &tmp, sizeof(iapref->addr));
1745 
1746 	/*
1747 	 * Add the prefix to the pool (note state is free, not active?!).
1748 	 */
1749 	result = add_lease6(pool, iapref, soft_lifetime_end_time);
1750 	if (result == ISC_R_SUCCESS) {
1751 		iasubopt_reference(pref, iapref, MDL);
1752 	}
1753 	iasubopt_dereference(&iapref, MDL);
1754 	return result;
1755 }
1756 
1757 /*
1758  * Determine if a prefix is present in a pool or not.
1759  */
1760 isc_boolean_t
1761 prefix6_exists(const struct ipv6_pool *pool,
1762 	       const struct in6_addr *pref, u_int8_t plen) {
1763 	struct iasubopt *test_iapref;
1764 
1765 	if ((int)plen != pool->units)
1766 		return ISC_FALSE;
1767 
1768 	test_iapref = NULL;
1769 	if (iasubopt_hash_lookup(&test_iapref, pool->leases,
1770 				 (void *)pref, sizeof(*pref), MDL)) {
1771 		iasubopt_dereference(&test_iapref, MDL);
1772 		return ISC_TRUE;
1773 	} else {
1774 		return ISC_FALSE;
1775 	}
1776 }
1777 
1778 /*
1779  * Mark an IPv6 address/prefix as unavailable from a pool.
1780  *
1781  * This is used for host entries and the addresses of the server itself.
1782  */
1783 static isc_result_t
1784 mark_lease_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
1785 	struct iasubopt *dummy_iasubopt;
1786 	isc_result_t result;
1787 
1788 	dummy_iasubopt = NULL;
1789 	result = iasubopt_allocate(&dummy_iasubopt, MDL);
1790 	if (result == ISC_R_SUCCESS) {
1791 		dummy_iasubopt->addr = *addr;
1792 		iasubopt_hash_add(pool->leases, &dummy_iasubopt->addr,
1793 				  sizeof(*addr), dummy_iasubopt, MDL);
1794 	}
1795 	return result;
1796 }
1797 
1798 /*
1799  * Add a pool.
1800  */
1801 isc_result_t
1802 add_ipv6_pool(struct ipv6_pool *pool) {
1803 	struct ipv6_pool **new_pools;
1804 
1805 	new_pools = dmalloc(sizeof(struct ipv6_pool *) * (num_pools+1), MDL);
1806 	if (new_pools == NULL) {
1807 		return ISC_R_NOMEMORY;
1808 	}
1809 
1810 	if (num_pools > 0) {
1811 		memcpy(new_pools, pools,
1812 		       sizeof(struct ipv6_pool *) * num_pools);
1813 		dfree(pools, MDL);
1814 	}
1815 	pools = new_pools;
1816 
1817 	pools[num_pools] = NULL;
1818 	ipv6_pool_reference(&pools[num_pools], pool, MDL);
1819 	num_pools++;
1820 	return ISC_R_SUCCESS;
1821 }
1822 
1823 static void
1824 cleanup_old_expired(struct ipv6_pool *pool) {
1825 	struct iasubopt *tmp;
1826 	struct ia_xx *ia;
1827 	struct ia_xx *ia_active;
1828 	unsigned char *tmpd;
1829 	time_t timeout;
1830 
1831 	while (pool->num_inactive > 0) {
1832 		tmp = (struct iasubopt *)
1833 				isc_heap_element(pool->inactive_timeouts, 1);
1834 		if (tmp->hard_lifetime_end_time != 0) {
1835 			timeout = tmp->hard_lifetime_end_time;
1836 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
1837 		} else {
1838 			timeout = tmp->soft_lifetime_end_time;
1839 		}
1840 		if (cur_time < timeout) {
1841 			break;
1842 		}
1843 
1844 		isc_heap_delete(pool->inactive_timeouts, tmp->heap_index);
1845 		pool->num_inactive--;
1846 
1847 		if (tmp->ia != NULL) {
1848 			/*
1849 			 * Check to see if this IA is in an active list,
1850 			 * but has no remaining resources. If so, remove it
1851 			 * from the active list.
1852 			 */
1853 			ia = NULL;
1854 			ia_reference(&ia, tmp->ia, MDL);
1855 			ia_remove_iasubopt(ia, tmp, MDL);
1856 			ia_active = NULL;
1857 			tmpd = (unsigned char *)ia->iaid_duid.data;
1858 			if ((ia->ia_type == D6O_IA_NA) &&
1859 			    (ia->num_iasubopt <= 0) &&
1860 			    (ia_hash_lookup(&ia_active, ia_na_active, tmpd,
1861 					    ia->iaid_duid.len, MDL) == 0) &&
1862 			    (ia_active == ia)) {
1863 				ia_hash_delete(ia_na_active, tmpd,
1864 					       ia->iaid_duid.len, MDL);
1865 			}
1866 			if ((ia->ia_type == D6O_IA_TA) &&
1867 			    (ia->num_iasubopt <= 0) &&
1868 			    (ia_hash_lookup(&ia_active, ia_ta_active, tmpd,
1869 					    ia->iaid_duid.len, MDL) == 0) &&
1870 			    (ia_active == ia)) {
1871 				ia_hash_delete(ia_ta_active, tmpd,
1872 					       ia->iaid_duid.len, MDL);
1873 			}
1874 			if ((ia->ia_type == D6O_IA_PD) &&
1875 			    (ia->num_iasubopt <= 0) &&
1876 			    (ia_hash_lookup(&ia_active, ia_pd_active, tmpd,
1877 					    ia->iaid_duid.len, MDL) == 0) &&
1878 			    (ia_active == ia)) {
1879 				ia_hash_delete(ia_pd_active, tmpd,
1880 					       ia->iaid_duid.len, MDL);
1881 			}
1882 			ia_dereference(&ia, MDL);
1883 		}
1884 		iasubopt_dereference(&tmp, MDL);
1885 	}
1886 }
1887 
1888 static void
1889 lease_timeout_support(void *vpool) {
1890 	struct ipv6_pool *pool;
1891 	struct iasubopt *lease;
1892 
1893 	pool = (struct ipv6_pool *)vpool;
1894 	for (;;) {
1895 		/*
1896 		 * Get the next lease scheduled to expire.
1897 		 *
1898 		 * Note that if there are no leases in the pool,
1899 		 * expire_lease6() will return ISC_R_SUCCESS with
1900 		 * a NULL lease.
1901 		 *
1902 		 * expire_lease6() will call move_lease_to_inactive() which
1903 		 * calls ddns_removals() do we want that on the standard
1904 		 * expiration timer or a special 'depref' timer?  Original
1905 		 * query from DH, moved here by SAR.
1906 		 */
1907 		lease = NULL;
1908 		if (expire_lease6(&lease, pool, cur_time) != ISC_R_SUCCESS) {
1909 			break;
1910 		}
1911 		if (lease == NULL) {
1912 			break;
1913 		}
1914 
1915 		write_ia(lease->ia);
1916 
1917 		iasubopt_dereference(&lease, MDL);
1918 	}
1919 
1920 	/*
1921 	 * If appropriate commit and rotate the lease file
1922 	 * As commit_leases_timed() checks to see if we've done any writes
1923 	 * we don't bother tracking if this function called write _ia
1924 	 */
1925 	(void) commit_leases_timed();
1926 
1927 	/*
1928 	 * Do some cleanup of our expired leases.
1929 	 */
1930 	cleanup_old_expired(pool);
1931 
1932 	/*
1933 	 * Schedule next round of expirations.
1934 	 */
1935 	schedule_lease_timeout(pool);
1936 }
1937 
1938 /*
1939  * For a given pool, add a timer that will remove the next
1940  * lease to expire.
1941  */
1942 void
1943 schedule_lease_timeout(struct ipv6_pool *pool) {
1944 	struct iasubopt *tmp;
1945 	time_t timeout;
1946 	time_t next_timeout;
1947 	struct timeval tv;
1948 
1949 	next_timeout = MAX_TIME;
1950 
1951 	if (pool->num_active > 0) {
1952 		tmp = (struct iasubopt *)
1953 				isc_heap_element(pool->active_timeouts, 1);
1954 		if (tmp->hard_lifetime_end_time < next_timeout) {
1955 			next_timeout = tmp->hard_lifetime_end_time + 1;
1956 		}
1957 	}
1958 
1959 	if (pool->num_inactive > 0) {
1960 		tmp = (struct iasubopt *)
1961 				isc_heap_element(pool->inactive_timeouts, 1);
1962 		if (tmp->hard_lifetime_end_time != 0) {
1963 			timeout = tmp->hard_lifetime_end_time;
1964 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
1965 		} else {
1966 			timeout = tmp->soft_lifetime_end_time + 1;
1967 		}
1968 		if (timeout < next_timeout) {
1969 			next_timeout = timeout;
1970 		}
1971 	}
1972 
1973 	if (next_timeout < MAX_TIME) {
1974 		tv.tv_sec = next_timeout;
1975 		tv.tv_usec = 0;
1976 		add_timeout(&tv, lease_timeout_support, pool,
1977 			    (tvref_t)ipv6_pool_reference,
1978 			    (tvunref_t)ipv6_pool_dereference);
1979 	}
1980 }
1981 
1982 /*
1983  * Schedule timeouts across all pools.
1984  */
1985 void
1986 schedule_all_ipv6_lease_timeouts(void) {
1987 	int i;
1988 
1989 	for (i=0; i<num_pools; i++) {
1990 		schedule_lease_timeout(pools[i]);
1991 	}
1992 }
1993 
1994 /*
1995  * Given an address and the length of the network mask, return
1996  * only the network portion.
1997  *
1998  * Examples:
1999  *
2000  *   "fe80::216:6fff:fe49:7d9b", length 64 = "fe80::"
2001  *   "2001:888:1936:2:216:6fff:fe49:7d9b", length 48 = "2001:888:1936::"
2002  */
2003 static void
2004 ipv6_network_portion(struct in6_addr *result,
2005 		     const struct in6_addr *addr, int bits) {
2006 	unsigned char *addrp;
2007 	int mask_bits;
2008 	int bytes;
2009 	int extra_bits;
2010 	int i;
2011 
2012 	static const unsigned char bitmasks[] = {
2013 		0x00, 0xFE, 0xFC, 0xF8,
2014 		0xF0, 0xE0, 0xC0, 0x80,
2015 	};
2016 
2017 	/*
2018 	 *  Sanity check our bits. ;)
2019 	 */
2020 	if ((bits < 0) || (bits > 128)) {
2021 		log_fatal("ipv6_network_portion: bits %d not between 0 and 128",
2022 			  bits);
2023 	}
2024 
2025 	/*
2026 	 * Copy our address portion.
2027 	 */
2028 	*result = *addr;
2029 	addrp = ((unsigned char *)result) + 15;
2030 
2031 	/*
2032 	 * Zero out masked portion.
2033 	 */
2034 	mask_bits = 128 - bits;
2035 	bytes = mask_bits / 8;
2036 	extra_bits = mask_bits % 8;
2037 
2038 	for (i=0; i<bytes; i++) {
2039 		*addrp = 0;
2040 		addrp--;
2041 	}
2042 	if (extra_bits) {
2043 		*addrp &= bitmasks[extra_bits];
2044 	}
2045 }
2046 
2047 /*
2048  * Determine if the given address/prefix is in the pool.
2049  */
2050 isc_boolean_t
2051 ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
2052 	struct in6_addr tmp;
2053 
2054 	ipv6_network_portion(&tmp, addr, pool->bits);
2055 	if (memcmp(&tmp, &pool->start_addr, sizeof(tmp)) == 0) {
2056 		return ISC_TRUE;
2057 	} else {
2058 		return ISC_FALSE;
2059 	}
2060 }
2061 
2062 /*
2063  * Find the pool that contains the given address.
2064  *
2065  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
2066  *   initialized to NULL
2067  */
2068 isc_result_t
2069 find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type,
2070 	       const struct in6_addr *addr) {
2071 	int i;
2072 
2073 	if (pool == NULL) {
2074 		log_error("%s(%d): NULL pointer reference", MDL);
2075 		return DHCP_R_INVALIDARG;
2076 	}
2077 	if (*pool != NULL) {
2078 		log_error("%s(%d): non-NULL pointer", MDL);
2079 		return DHCP_R_INVALIDARG;
2080 	}
2081 
2082 	for (i=0; i<num_pools; i++) {
2083 		if (pools[i]->pool_type != type)
2084 			continue;
2085 		if (ipv6_in_pool(addr, pools[i])) {
2086 			ipv6_pool_reference(pool, pools[i], MDL);
2087 			return ISC_R_SUCCESS;
2088 		}
2089 	}
2090 	return ISC_R_NOTFOUND;
2091 }
2092 
2093 /*
2094  * Helper function for the various functions that act across all
2095  * pools.
2096  */
2097 static isc_result_t
2098 change_leases(struct ia_xx *ia,
2099 	      isc_result_t (*change_func)(struct ipv6_pool *,
2100 					  struct iasubopt *)) {
2101 	isc_result_t retval;
2102 	isc_result_t renew_retval;
2103 	struct ipv6_pool *pool;
2104 	struct in6_addr *addr;
2105 	int i;
2106 
2107 	retval = ISC_R_SUCCESS;
2108 	for (i=0; i<ia->num_iasubopt; i++) {
2109 		pool = NULL;
2110 		addr = &ia->iasubopt[i]->addr;
2111 		if (find_ipv6_pool(&pool, ia->ia_type,
2112 				   addr) == ISC_R_SUCCESS) {
2113 			renew_retval = change_func(pool, ia->iasubopt[i]);
2114 			if (renew_retval != ISC_R_SUCCESS) {
2115 				retval = renew_retval;
2116 			}
2117 		}
2118 		/* XXXsk: should we warn if we don't find a pool? */
2119 	}
2120 	return retval;
2121 }
2122 
2123 /*
2124  * Renew all leases in an IA from all pools.
2125  *
2126  * The new lifetime should be in the soft_lifetime_end_time
2127  * and will be moved to hard_lifetime_end_time by renew_lease6.
2128  */
2129 isc_result_t
2130 renew_leases(struct ia_xx *ia) {
2131 	return change_leases(ia, renew_lease6);
2132 }
2133 
2134 /*
2135  * Release all leases in an IA from all pools.
2136  */
2137 isc_result_t
2138 release_leases(struct ia_xx *ia) {
2139 	return change_leases(ia, release_lease6);
2140 }
2141 
2142 /*
2143  * Decline all leases in an IA from all pools.
2144  */
2145 isc_result_t
2146 decline_leases(struct ia_xx *ia) {
2147 	return change_leases(ia, decline_lease6);
2148 }
2149 
2150 #ifdef DHCPv6
2151 /*
2152  * Helper function to output leases.
2153  */
2154 static int write_error;
2155 
2156 static isc_result_t
2157 write_ia_leases(const void *name, unsigned len, void *value) {
2158 	struct ia_xx *ia = (struct ia_xx *)value;
2159 
2160 	if (!write_error) {
2161 		if (!write_ia(ia)) {
2162 			write_error = 1;
2163 		}
2164 	}
2165 	return ISC_R_SUCCESS;
2166 }
2167 
2168 /*
2169  * Write all DHCPv6 information.
2170  */
2171 int
2172 write_leases6(void) {
2173 	int nas, tas, pds;
2174 
2175 	write_error = 0;
2176 	write_server_duid();
2177 	nas = ia_hash_foreach(ia_na_active, write_ia_leases);
2178 	if (write_error) {
2179 		return 0;
2180 	}
2181 	tas = ia_hash_foreach(ia_ta_active, write_ia_leases);
2182 	if (write_error) {
2183 		return 0;
2184 	}
2185 	pds = ia_hash_foreach(ia_pd_active, write_ia_leases);
2186 	if (write_error) {
2187 		return 0;
2188 	}
2189 
2190 	log_info("Wrote %d NA, %d TA, %d PD leases to lease file.",
2191 		 nas, tas, pds);
2192 	return 1;
2193 }
2194 #endif /* DHCPv6 */
2195 
2196 static isc_result_t
2197 mark_hosts_unavailable_support(const void *name, unsigned len, void *value) {
2198 	struct host_decl *h;
2199 	struct data_string fixed_addr;
2200 	struct in6_addr addr;
2201 	struct ipv6_pool *p;
2202 
2203 	h = (struct host_decl *)value;
2204 
2205 	/*
2206 	 * If the host has no address, we don't need to mark anything.
2207 	 */
2208 	if (h->fixed_addr == NULL) {
2209 		return ISC_R_SUCCESS;
2210 	}
2211 
2212 	/*
2213 	 * Evaluate the fixed address.
2214 	 */
2215 	memset(&fixed_addr, 0, sizeof(fixed_addr));
2216 	if (!evaluate_option_cache(&fixed_addr, NULL, NULL, NULL, NULL, NULL,
2217 				   &global_scope, h->fixed_addr, MDL)) {
2218 		log_error("mark_hosts_unavailable: "
2219 			  "error evaluating host address.");
2220 		return ISC_R_SUCCESS;
2221 	}
2222 	if (fixed_addr.len != 16) {
2223 		log_error("mark_hosts_unavailable: "
2224 			  "host address is not 128 bits.");
2225 		return ISC_R_SUCCESS;
2226 	}
2227 	memcpy(&addr, fixed_addr.data, 16);
2228 	data_string_forget(&fixed_addr, MDL);
2229 
2230 	/*
2231 	 * Find the pool holding this host, and mark the address.
2232 	 * (I suppose it is arguably valid to have a host that does not
2233 	 * sit in any pool.)
2234 	 */
2235 	p = NULL;
2236 	if (find_ipv6_pool(&p, D6O_IA_NA, &addr) == ISC_R_SUCCESS) {
2237 		mark_lease_unavailable(p, &addr);
2238 		ipv6_pool_dereference(&p, MDL);
2239 	}
2240 	if (find_ipv6_pool(&p, D6O_IA_TA, &addr) == ISC_R_SUCCESS) {
2241 		mark_lease_unavailable(p, &addr);
2242 		ipv6_pool_dereference(&p, MDL);
2243 	}
2244 
2245 	return ISC_R_SUCCESS;
2246 }
2247 
2248 void
2249 mark_hosts_unavailable(void) {
2250 	hash_foreach(host_name_hash, mark_hosts_unavailable_support);
2251 }
2252 
2253 static isc_result_t
2254 mark_phosts_unavailable_support(const void *name, unsigned len, void *value) {
2255 	struct host_decl *h;
2256 	struct iaddrcidrnetlist *l;
2257 	struct in6_addr pref;
2258 	struct ipv6_pool *p;
2259 
2260 	h = (struct host_decl *)value;
2261 
2262 	/*
2263 	 * If the host has no prefix, we don't need to mark anything.
2264 	 */
2265 	if (h->fixed_prefix == NULL) {
2266 		return ISC_R_SUCCESS;
2267 	}
2268 
2269 	/*
2270 	 * Get the fixed prefixes.
2271 	 */
2272 	for (l = h->fixed_prefix; l != NULL; l = l->next) {
2273 		if (l->cidrnet.lo_addr.len != 16) {
2274 			continue;
2275 		}
2276 		memcpy(&pref, l->cidrnet.lo_addr.iabuf, 16);
2277 
2278 		/*
2279 		 * Find the pool holding this host, and mark the prefix.
2280 		 * (I suppose it is arguably valid to have a host that does not
2281 		 * sit in any pool.)
2282 		 */
2283 		p = NULL;
2284 		if (find_ipv6_pool(&p, D6O_IA_PD, &pref) != ISC_R_SUCCESS) {
2285 			continue;
2286 		}
2287 		if (l->cidrnet.bits != p->units) {
2288 			ipv6_pool_dereference(&p, MDL);
2289 			continue;
2290 		}
2291 		mark_lease_unavailable(p, &pref);
2292 		ipv6_pool_dereference(&p, MDL);
2293 	}
2294 
2295 	return ISC_R_SUCCESS;
2296 }
2297 
2298 void
2299 mark_phosts_unavailable(void) {
2300 	hash_foreach(host_name_hash, mark_phosts_unavailable_support);
2301 }
2302 
2303 void
2304 mark_interfaces_unavailable(void) {
2305 	struct interface_info *ip;
2306 	int i;
2307 	struct ipv6_pool *p;
2308 
2309 	ip = interfaces;
2310 	while (ip != NULL) {
2311 		for (i=0; i<ip->v6address_count; i++) {
2312 			p = NULL;
2313 			if (find_ipv6_pool(&p, D6O_IA_NA, &ip->v6addresses[i])
2314 							== ISC_R_SUCCESS) {
2315 				mark_lease_unavailable(p,
2316 						       &ip->v6addresses[i]);
2317 				ipv6_pool_dereference(&p, MDL);
2318 			}
2319 			if (find_ipv6_pool(&p, D6O_IA_TA, &ip->v6addresses[i])
2320 							== ISC_R_SUCCESS) {
2321 				mark_lease_unavailable(p,
2322 						       &ip->v6addresses[i]);
2323 				ipv6_pool_dereference(&p, MDL);
2324 			}
2325 		}
2326 		ip = ip->next;
2327 	}
2328 }
2329 
2330 /*!
2331  * \brief Create a new IPv6 pond structure.
2332  *
2333  * Allocate space for a new ipv6_pond structure and return a reference
2334  * to it, includes setting the reference count to 1.
2335  *
2336  * \param pond = space for returning a referenced pointer to the pond.
2337  *		 This must point to a space that has been initialzied
2338  *		 to NULL by the caller.
2339  *
2340  * \return
2341  * ISC_R_SUCCESS     = The pond was successfully created, pond points to it.
2342  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2343  *		       modified
2344  * ISC_R_NOMEMORY    = The system wasn't able to allocate memory, pond has
2345  *		       not been modified.
2346  */
2347 isc_result_t
2348 ipv6_pond_allocate(struct ipv6_pond **pond, const char *file, int line) {
2349 	struct ipv6_pond *tmp;
2350 
2351 	if (pond == NULL) {
2352 		log_error("%s(%d): NULL pointer reference", file, line);
2353 		return DHCP_R_INVALIDARG;
2354 	}
2355 	if (*pond != NULL) {
2356 		log_error("%s(%d): non-NULL pointer", file, line);
2357 		return DHCP_R_INVALIDARG;
2358 	}
2359 
2360 	tmp = dmalloc(sizeof(*tmp), file, line);
2361 	if (tmp == NULL) {
2362 		return ISC_R_NOMEMORY;
2363 	}
2364 
2365 	tmp->refcnt = 1;
2366 
2367 	*pond = tmp;
2368 	return ISC_R_SUCCESS;
2369 }
2370 
2371 /*!
2372  *
2373  * \brief reference an IPv6 pond structure.
2374  *
2375  * This function genreates a reference to an ipv6_pond structure
2376  * and increments the reference count on the structure.
2377  *
2378  * \param[out] pond = space for returning a referenced pointer to the pond.
2379  *		      This must point to a space that has been initialzied
2380  *		      to NULL by the caller.
2381  * \param[in]  src  = A pointer to the pond to reference.  This must not be
2382  *		      NULL.
2383  *
2384  * \return
2385  * ISC_R_SUCCESS     = The pond was successfully referenced, pond now points
2386  *		       to src.
2387  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2388  *		       modified.
2389  */
2390 isc_result_t
2391 ipv6_pond_reference(struct ipv6_pond **pond, struct ipv6_pond *src,
2392 		    const char *file, int line) {
2393 	if (pond == NULL) {
2394 		log_error("%s(%d): NULL pointer reference", file, line);
2395 		return DHCP_R_INVALIDARG;
2396 	}
2397 	if (*pond != NULL) {
2398 		log_error("%s(%d): non-NULL pointer", file, line);
2399 		return DHCP_R_INVALIDARG;
2400 	}
2401 	if (src == NULL) {
2402 		log_error("%s(%d): NULL pointer reference", file, line);
2403 		return DHCP_R_INVALIDARG;
2404 	}
2405 	*pond = src;
2406 	src->refcnt++;
2407 	return ISC_R_SUCCESS;
2408 }
2409 
2410 /*!
2411  *
2412  * \brief de-reference an IPv6 pond structure.
2413  *
2414  * This function decrements the reference count in an ipv6_pond structure.
2415  * If this was the last reference then the memory for the structure is
2416  * freed.
2417  *
2418  * \param[in] pond = A pointer to the pointer to the pond that should be
2419  *		     de-referenced.  On success the pointer to the pond
2420  *		     is cleared.  It must not be NULL and must not point
2421  *		     to NULL.
2422  *
2423  * \return
2424  * ISC_R_SUCCESS     = The pond was successfully de-referenced, pond now points
2425  *		       to NULL
2426  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
2427  *		       modified.
2428  */
2429 
2430 isc_result_t
2431 ipv6_pond_dereference(struct ipv6_pond **pond, const char *file, int line) {
2432 	struct ipv6_pond *tmp;
2433 
2434 	if ((pond == NULL) || (*pond == NULL)) {
2435 		log_error("%s(%d): NULL pointer", file, line);
2436 		return DHCP_R_INVALIDARG;
2437 	}
2438 
2439 	tmp = *pond;
2440 	*pond = NULL;
2441 
2442 	tmp->refcnt--;
2443 	if (tmp->refcnt < 0) {
2444 		log_error("%s(%d): negative refcnt", file, line);
2445 		tmp->refcnt = 0;
2446 	}
2447 	if (tmp->refcnt == 0) {
2448 		dfree(tmp, file, line);
2449 	}
2450 
2451 	return ISC_R_SUCCESS;
2452 }
2453 
2454 /* unittest moved to server/tests/mdb6_unittest.c */
2455