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