Home | History | Annotate | Line # | Download | only in server
mdb6.c revision 1.7
      1 /*	$NetBSD: mdb6.c,v 1.7 2022/09/23 12:30:52 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.7 2022/09/23 12:30:52 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/md.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 	isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, active_changed,
    675 			0, &(tmp->active_timeouts));
    676 	isc_heap_create(dhcp_gbl_ctx.mctx, lease_older, inactive_changed,
    677 			0, &(tmp->inactive_timeouts));
    678 
    679 	*pool = tmp;
    680 	return ISC_R_SUCCESS;
    681 }
    682 
    683 /*!
    684  *
    685  * \brief reference an IPv6 pool structure.
    686  *
    687  * This function genreates a reference to an ipv6_pool structure
    688  * and increments the reference count on the structure.
    689  *
    690  * \param[out] pool = space for returning a referenced pointer to the pool.
    691  *		      This must point to a space that has been initialzied
    692  *		      to NULL by the caller.
    693  * \param[in]  src  = A pointer to the pool to reference.  This must not be
    694  *		      NULL.
    695  *
    696  * \return
    697  * ISC_R_SUCCESS     = The pool was successfully referenced, pool now points
    698  *		       to src.
    699  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
    700  *		       modified.
    701  */
    702 isc_result_t
    703 ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src,
    704 		    const char *file, int line) {
    705 	if (pool == NULL) {
    706 		log_error("%s(%d): NULL pointer reference", file, line);
    707 		return DHCP_R_INVALIDARG;
    708 	}
    709 	if (*pool != NULL) {
    710 		log_error("%s(%d): non-NULL pointer", file, line);
    711 		return DHCP_R_INVALIDARG;
    712 	}
    713 	if (src == NULL) {
    714 		log_error("%s(%d): NULL pointer reference", file, line);
    715 		return DHCP_R_INVALIDARG;
    716 	}
    717 	*pool = src;
    718 	src->refcnt++;
    719 	return ISC_R_SUCCESS;
    720 }
    721 
    722 /*
    723  * Note: Each IAADDR/PREFIX in a pool is referenced by the pool. This is needed
    724  * to prevent the lease from being garbage collected out from under the
    725  * pool.
    726  *
    727  * The references are made from the hash and from the heap. The following
    728  * helper functions dereference these when a pool is destroyed.
    729  */
    730 
    731 /*
    732  * Helper function for pool cleanup.
    733  * Dereference each of the hash entries in a pool.
    734  */
    735 static isc_result_t
    736 dereference_hash_entry(const void *name, unsigned len, void *value) {
    737 	struct iasubopt *iasubopt = (struct iasubopt *)value;
    738 
    739 	iasubopt_dereference(&iasubopt, MDL);
    740 	return ISC_R_SUCCESS;
    741 }
    742 
    743 /*
    744  * Helper function for pool cleanup.
    745  * Dereference each of the heap entries in a pool.
    746  */
    747 static void
    748 dereference_heap_entry(void *value, void *dummy) {
    749 	struct iasubopt *iasubopt = (struct iasubopt *)value;
    750 
    751 	iasubopt_dereference(&iasubopt, MDL);
    752 }
    753 
    754 /*!
    755  *
    756  * \brief de-reference an IPv6 pool structure.
    757  *
    758  * This function decrements the reference count in an ipv6_pool structure.
    759  * If this was the last reference then the memory for the structure is
    760  * freed.
    761  *
    762  * \param[in] pool = A pointer to the pointer to the pool that should be
    763  *		     de-referenced.  On success the pointer to the pool
    764  *		     is cleared.  It must not be NULL and must not point
    765  *		     to NULL.
    766  *
    767  * \return
    768  * ISC_R_SUCCESS     = The pool was successfully de-referenced, pool now points
    769  *		       to NULL
    770  * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been
    771  *		       modified.
    772  */
    773 isc_result_t
    774 ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line) {
    775 	struct ipv6_pool *tmp;
    776 
    777 	if ((pool == NULL) || (*pool == NULL)) {
    778 		log_error("%s(%d): NULL pointer", file, line);
    779 		return DHCP_R_INVALIDARG;
    780 	}
    781 
    782 	tmp = *pool;
    783 	*pool = NULL;
    784 
    785 	tmp->refcnt--;
    786 	if (tmp->refcnt < 0) {
    787 		log_error("%s(%d): negative refcnt", file, line);
    788 		tmp->refcnt = 0;
    789 	}
    790 	if (tmp->refcnt == 0) {
    791 		iasubopt_hash_foreach(tmp->leases, dereference_hash_entry);
    792 		iasubopt_free_hash_table(&(tmp->leases), file, line);
    793 		isc_heap_foreach(tmp->active_timeouts,
    794 				 dereference_heap_entry, NULL);
    795 		isc_heap_destroy(&(tmp->active_timeouts));
    796 		isc_heap_foreach(tmp->inactive_timeouts,
    797 				 dereference_heap_entry, NULL);
    798 		isc_heap_destroy(&(tmp->inactive_timeouts));
    799 		dfree(tmp, file, line);
    800 	}
    801 
    802 	return ISC_R_SUCCESS;
    803 }
    804 
    805 /*
    806  * Create an address by hashing the input, and using that for
    807  * the non-network part.
    808  */
    809 static void
    810 build_address6(struct in6_addr *addr,
    811 	       const struct in6_addr *net_start_addr, int net_bits,
    812 	       const struct data_string *input) {
    813 	int net_bytes;
    814 	int i;
    815 	unsigned int len;
    816 	char *str;
    817 	const char *net_str;
    818 
    819 	isc_md(ISC_MD_MD5, input->data, input->len, (void *)addr, &len);
    820 
    821 	/*
    822 	 * Copy the [0..128] network bits over.
    823 	 */
    824 	str = (char *)addr;
    825 	net_str = (const char *)net_start_addr;
    826 	net_bytes = net_bits / 8;
    827 	for (i = 0; i < net_bytes; i++) {
    828 		str[i] = net_str[i];
    829 	}
    830 	switch (net_bits % 8) {
    831 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
    832 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
    833 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
    834 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
    835 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
    836 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
    837 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
    838 	}
    839 
    840 	/*
    841 	 * Set the universal/local bit ("u bit") to zero for /64s.  The
    842 	 * individual/group bit ("g bit") is unchanged, because the g-bit
    843 	 * has no meaning when the u-bit is cleared.
    844 	 */
    845 	if (net_bits == 64)
    846 		str[8] &= ~0x02;
    847 }
    848 
    849 #ifdef EUI_64
    850 int
    851 valid_eui_64_duid(const struct data_string* uid, int offset) {
    852 	if (uid->len == (offset + EUI_64_ID_LEN)) {
    853 		const unsigned char* duid = uid->data + offset;
    854 		return (((duid[0] == 0x00 && duid[1] == 0x03)  &&
    855 			(duid[2] == 0x00 && duid[3] == 0x1b)));
    856 	}
    857 
    858     return(0);
    859 }
    860 
    861 
    862 /*
    863  * Create an EUI-64 address
    864  */
    865 static isc_result_t
    866 build_address6_eui_64(struct in6_addr *addr,
    867 		      const struct in6_addr *net_start_addr, int net_bits,
    868 		      const struct data_string *iaid_duid, int duid_beg) {
    869 
    870 	if (net_bits != 64) {
    871 		log_error("build_address_eui_64: network is not 64 bits");
    872 		return (ISC_R_FAILURE);
    873 	}
    874 
    875 	if (valid_eui_64_duid(iaid_duid, duid_beg)) {
    876 		const unsigned char *duid = iaid_duid->data + duid_beg;
    877 
    878 		/* copy network prefix to the high 64 bits */
    879 		memcpy(addr->s6_addr, net_start_addr->s6_addr, 8);
    880 
    881 		/* copy Link-layer address to low 64 bits */
    882 		memcpy(addr->s6_addr + 8, duid + 4, 8);
    883 
    884 		/* RFC-3315 Any address assigned by a server that is based
    885 		 * on an EUI-64 identifier MUST include an interface identifier
    886 		 * with the "u" (universal/local) and "g" (individual/group)
    887 		 * bits of the interface identifier set appropriately, as
    888 		 * indicated in section 2.5.1 of RFC 2373 [5]. */
    889 		addr->s6_addr[8] |= 0x02;
    890 		return (ISC_R_SUCCESS);
    891 	}
    892 
    893 	log_error("build_address_eui_64: iaid_duid not a valid EUI-64: %s",
    894 		  print_hex_1(iaid_duid->len, iaid_duid->data, 60));
    895 	return (ISC_R_FAILURE);
    896 }
    897 
    898 int
    899 valid_for_eui_64_pool(struct ipv6_pool* pool, struct data_string* uid,
    900 		      int duid_beg, struct in6_addr* ia_addr) {
    901         struct in6_addr test_addr;
    902 	/* If it's not an EUI-64 pool bail */
    903         if (!pool->ipv6_pond->use_eui_64) {
    904                 return (0);
    905         }
    906 
    907         if (!valid_eui_64_duid(uid, duid_beg)) {
    908                 /* Dynamic lease in a now eui_64 pond, toss it*/
    909                 return (0);
    910         }
    911 
    912         /*  Call build_address6_eui_64() and compare it's result to
    913 	 *  this lease and see if they match. */
    914         memset (&test_addr, 0, sizeof(test_addr));
    915         build_address6_eui_64(&test_addr, &pool->start_addr, pool->bits,
    916                               uid, duid_beg);
    917 
    918         return (!memcmp(ia_addr, &test_addr, sizeof(test_addr)));
    919 }
    920 #endif
    921 
    922 
    923 /*
    924  * Create a temporary address by a variant of RFC 4941 algo.
    925  * Note: this should not be used for prefixes shorter than 64 bits.
    926  */
    927 static void
    928 build_temporary6(struct in6_addr *addr,
    929 		 const struct in6_addr *net_start_addr, int net_bits,
    930 		 const struct data_string *input) {
    931 	static u_int32_t history[2];
    932 	static u_int32_t counter = 0;
    933 	unsigned char md[16] = {0};
    934 	unsigned int len;
    935 
    936 	/*
    937 	 * First time/time to reseed.
    938 	 * Please use a good pseudo-random generator here!
    939 	 */
    940 	if (counter == 0) {
    941 		history[0] = arc4random();
    942 		history[1] = arc4random();
    943 	}
    944 
    945 	/*
    946 	 * Use MD5 as recommended by RFC 4941.
    947 	 */
    948 	isc_md(ISC_MD_MD5, input->data, input->len, (void *)&history[0], &len);
    949 
    950 	/*
    951 	 * Build the address.
    952 	 */
    953 	if (net_bits == 64) {
    954 		memcpy(&addr->s6_addr[0], &net_start_addr->s6_addr[0], 8);
    955 		memcpy(&addr->s6_addr[8], md, 8);
    956 		addr->s6_addr[8] &= ~0x02;
    957 	} else {
    958 		int net_bytes;
    959 		int i;
    960 		char *str;
    961 		const char *net_str;
    962 
    963 		/*
    964 		 * Copy the [0..128] network bits over.
    965 		 */
    966 		str = (char *)addr;
    967 		net_str = (const char *)net_start_addr;
    968 		net_bytes = net_bits / 8;
    969 		for (i = 0; i < net_bytes; i++) {
    970 			str[i] = net_str[i];
    971 		}
    972 		memcpy(str + net_bytes, md, 16 - net_bytes);
    973 		switch (net_bits % 8) {
    974 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
    975 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
    976 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
    977 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
    978 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
    979 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
    980 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
    981 		}
    982 	}
    983 
    984 
    985 	/*
    986 	 * Save history for the next call.
    987 	 */
    988 	memcpy((unsigned char *)&history[0], md + 8, 8);
    989 	counter++;
    990 }
    991 
    992 /* Reserved Subnet Router Anycast ::0:0:0:0. */
    993 static struct in6_addr rtany;
    994 /* Reserved Subnet Anycasts ::fdff:ffff:ffff:ff80-::fdff:ffff:ffff:ffff. */
    995 static struct in6_addr resany;
    996 
    997 /*
    998  * Create a lease for the given address and client duid.
    999  *
   1000  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
   1001  *   initialized to NULL
   1002  *
   1003  * Right now we simply hash the DUID, and if we get a collision, we hash
   1004  * again until we find a free address. We try this a fixed number of times,
   1005  * to avoid getting stuck in a loop (this is important on small pools
   1006  * where we can run out of space).
   1007  *
   1008  * We return the number of attempts that it took to find an available
   1009  * lease. This tells callers when a pool is are filling up, as
   1010  * well as an indication of how full the pool is; statistically the
   1011  * more full a pool is the more attempts must be made before finding
   1012  * a free lease. Realistically this will only happen in very full
   1013  * pools.
   1014  *
   1015  * We probably want different algorithms depending on the network size, in
   1016  * the long term.
   1017  */
   1018 isc_result_t
   1019 create_lease6(struct ipv6_pool *pool, struct iasubopt **addr,
   1020 	      unsigned int *attempts,
   1021 	      const struct data_string *uid, time_t soft_lifetime_end_time) {
   1022 	struct data_string ds;
   1023 	struct in6_addr tmp;
   1024 	struct iasubopt *test_iaaddr;
   1025 	struct data_string new_ds;
   1026 	struct iasubopt *iaaddr;
   1027 	isc_result_t result;
   1028 	isc_boolean_t reserved_iid;
   1029 	static isc_boolean_t init_resiid = ISC_FALSE;
   1030 
   1031 	/*
   1032 	 * Fill the reserved IIDs.
   1033 	 */
   1034 	if (!init_resiid) {
   1035 		memset(&rtany, 0, 16);
   1036 		memset(&resany, 0, 8);
   1037 		resany.s6_addr[8] = 0xfd;
   1038 		memset(&resany.s6_addr[9], 0xff, 6);
   1039 		init_resiid = ISC_TRUE;
   1040 	}
   1041 
   1042 	/*
   1043 	 * Use the UID as our initial seed for the hash
   1044 	 */
   1045 	memset(&ds, 0, sizeof(ds));
   1046 	data_string_copy(&ds, (struct data_string *)uid, MDL);
   1047 
   1048 	*attempts = 0;
   1049 	for (;;) {
   1050 		/*
   1051 		 * Give up at some point.
   1052 		 */
   1053 		if (++(*attempts) > 100) {
   1054 			data_string_forget(&ds, MDL);
   1055 			return ISC_R_NORESOURCES;
   1056 		}
   1057 
   1058 		/*
   1059 		 * Build a resource.
   1060 		 */
   1061 		switch (pool->pool_type) {
   1062 		case D6O_IA_NA:
   1063 			/* address */
   1064 			build_address6(&tmp, &pool->start_addr,
   1065 				       pool->bits, &ds);
   1066 			break;
   1067 		case D6O_IA_TA:
   1068 			/* temporary address */
   1069 			build_temporary6(&tmp, &pool->start_addr,
   1070 					 pool->bits, &ds);
   1071 			break;
   1072 		case D6O_IA_PD:
   1073 			/* prefix */
   1074 			log_error("create_lease6: prefix pool.");
   1075 			data_string_forget(&ds, MDL);
   1076 			return DHCP_R_INVALIDARG;
   1077 		default:
   1078 			log_error("create_lease6: untyped pool.");
   1079 			data_string_forget(&ds, MDL);
   1080 			return DHCP_R_INVALIDARG;
   1081 		}
   1082 
   1083 		/*
   1084 		 * Avoid reserved interface IDs. (cf. RFC 5453)
   1085 		 */
   1086 		reserved_iid = ISC_FALSE;
   1087 		if (memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) {
   1088 			reserved_iid = ISC_TRUE;
   1089 		}
   1090 		if (!reserved_iid &&
   1091 		    (memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
   1092 		    ((tmp.s6_addr[15] & 0x80) == 0x80)) {
   1093 			reserved_iid = ISC_TRUE;
   1094 		}
   1095 
   1096 		/*
   1097 		 * If this address is not in use, we're happy with it
   1098 		 */
   1099 		test_iaaddr = NULL;
   1100 		if (!reserved_iid &&
   1101 		    (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
   1102 					  &tmp, sizeof(tmp), MDL) == 0)) {
   1103 			break;
   1104 		}
   1105 		if (test_iaaddr != NULL)
   1106 			iasubopt_dereference(&test_iaaddr, MDL);
   1107 
   1108 		/*
   1109 		 * Otherwise, we create a new input, adding the address
   1110 		 */
   1111 		memset(&new_ds, 0, sizeof(new_ds));
   1112 		new_ds.len = ds.len + sizeof(tmp);
   1113 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
   1114 			data_string_forget(&ds, MDL);
   1115 			return ISC_R_NOMEMORY;
   1116 		}
   1117 		new_ds.data = new_ds.buffer->data;
   1118 		memcpy(new_ds.buffer->data, ds.data, ds.len);
   1119 		memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
   1120 		data_string_forget(&ds, MDL);
   1121 		data_string_copy(&ds, &new_ds, MDL);
   1122 		data_string_forget(&new_ds, MDL);
   1123 	}
   1124 
   1125 	data_string_forget(&ds, MDL);
   1126 
   1127 	/*
   1128 	 * We're happy with the address, create an IAADDR
   1129 	 * to hold it.
   1130 	 */
   1131 	iaaddr = NULL;
   1132 	result = iasubopt_allocate(&iaaddr, MDL);
   1133 	if (result != ISC_R_SUCCESS) {
   1134 		return result;
   1135 	}
   1136 	iaaddr->plen = 0;
   1137 	memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
   1138 
   1139 	/*
   1140 	 * Add the lease to the pool (note state is free, not active?!).
   1141 	 */
   1142 	result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
   1143 	if (result == ISC_R_SUCCESS) {
   1144 		iasubopt_reference(addr, iaaddr, MDL);
   1145 	}
   1146 	iasubopt_dereference(&iaaddr, MDL);
   1147 	return result;
   1148 }
   1149 
   1150 #ifdef EUI_64
   1151 /*!
   1152  * \brief Assign an EUI-64 address from a pool for a given iaid-duid
   1153  *
   1154  *  \param pool - pool from which the address is assigned
   1155  *  \param iaddr - pointer to the iasubopt to contain the assigned address is
   1156  *  \param uid - data_string containing the iaid-duid tuple
   1157  *  \param soft_lifetime_end_time - lifetime of the lease for a solicit?
   1158  *
   1159  *  \return status indicating success or nature of the failure
   1160 */
   1161 isc_result_t
   1162 create_lease6_eui_64(struct ipv6_pool *pool, struct iasubopt **addr,
   1163 	      const struct data_string *uid,
   1164 	      time_t soft_lifetime_end_time) {
   1165 	struct in6_addr tmp;
   1166 	struct iasubopt *test_iaaddr;
   1167 	struct iasubopt *iaaddr;
   1168 	isc_result_t result;
   1169 	static isc_boolean_t init_resiid = ISC_FALSE;
   1170 
   1171 	/*  Fill the reserved IIDs.  */
   1172 	if (!init_resiid) {
   1173 		memset(&rtany, 0, 16);
   1174 		memset(&resany, 0, 8);
   1175 		resany.s6_addr[8] = 0xfd;
   1176 		memset(&resany.s6_addr[9], 0xff, 6);
   1177 		init_resiid = ISC_TRUE;
   1178 	}
   1179 
   1180 	/* Pool must be IA_NA */
   1181 	if (pool->pool_type != D6O_IA_NA) {
   1182 		log_error("create_lease6_eui_64: pool type is not IA_NA.");
   1183 		return (DHCP_R_INVALIDARG);
   1184 	}
   1185 
   1186 	/* Attempt to build the address */
   1187 	if (build_address6_eui_64 (&tmp, &pool->start_addr, pool->bits,
   1188 				   uid, IAID_LEN) != ISC_R_SUCCESS) {
   1189 		log_error("create_lease6_eui_64: build_address6_eui_64 failed");
   1190 		return (ISC_R_FAILURE);
   1191 	}
   1192 
   1193 	/* Avoid reserved interface IDs. (cf. RFC 5453) */
   1194 	if ((memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0)  ||
   1195 	    ((memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) &&
   1196 	    ((tmp.s6_addr[15] & 0x80) == 0x80))) {
   1197 		log_error("create_lease6_eui_64: "
   1198 			  "address conflicts with reserved IID");
   1199 		return (ISC_R_FAILURE);
   1200 	}
   1201 
   1202 	/* If this address is not in use, we're happy with it */
   1203 	test_iaaddr = NULL;
   1204 	if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
   1205 				  &tmp, sizeof(tmp), MDL) != 0) {
   1206 
   1207 		/* See if it's ours. Static leases won't have an ia */
   1208 		int ours = 0;
   1209 		if (!test_iaaddr->ia) {
   1210 			log_error("create_lease6_eui_64: "
   1211 				  "address  %s is assigned to static lease",
   1212 				  pin6_addr(&test_iaaddr->addr));
   1213 		} else {
   1214 			/* Not sure if this can actually happen */
   1215 			struct data_string* found = &test_iaaddr->ia->iaid_duid;
   1216 			ours = ((found->len == uid->len) &&
   1217 				(!memcmp(found->data, uid->data, uid->len)));
   1218 			log_error("create_lease6_eui_64: "
   1219 				  "address  %s belongs to %s",
   1220 				  pin6_addr(&test_iaaddr->addr),
   1221 				  print_hex_1(found->len, found->data, 60));
   1222 		}
   1223 
   1224 		iasubopt_dereference(&test_iaaddr, MDL);
   1225 		if (!ours) {
   1226 			/* Cant' use it */
   1227 			return (ISC_R_FAILURE);
   1228 		}
   1229 	}
   1230 
   1231 	/* We're happy with the address, create an IAADDR to hold it. */
   1232 	iaaddr = NULL;
   1233 	result = iasubopt_allocate(&iaaddr, MDL);
   1234 	if (result != ISC_R_SUCCESS) {
   1235 		log_error("create_lease6_eui_64: could not allocate iasubop");
   1236 		return result;
   1237 	}
   1238 	iaaddr->plen = 0;
   1239 	memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
   1240 
   1241 	/* Add the lease to the pool and the reply */
   1242 	result = add_lease6(pool, iaaddr, soft_lifetime_end_time);
   1243 	if (result == ISC_R_SUCCESS) {
   1244 		iasubopt_reference(addr, iaaddr, MDL);
   1245 	}
   1246 
   1247 	iasubopt_dereference(&iaaddr, MDL);
   1248 	return result;
   1249 }
   1250 #endif
   1251 
   1252 /*!
   1253  *
   1254  * \brief Cleans up leases when reading from a lease file
   1255  *
   1256  * This function is only expected to be run when reading leases in from a file.
   1257  * It checks to see if a lease already exists for the new leases's address.
   1258  * We don't add expired leases to the structures when reading a lease file
   1259  * which limits what can happen.  We have two variables the owners of the leases
   1260  * being the same or different and the new lease being active or non-active:
   1261  * Owners active
   1262  * same   no     remove old lease and its connections
   1263  * same   yes    nothing to do, other code will update the structures.
   1264  * diff   no     nothing to do
   1265  * diff   yes    this combination shouldn't happen, we should only have a
   1266  *               single active lease per address at a time and that lease
   1267  *               should move to non-active before any other lease can
   1268  *               become active for that address.
   1269  *               Currently we delete the previous lease and pass an error
   1270  *               to the caller who should log an error.
   1271  *
   1272  * When we remove a lease we remove it from the hash table and active heap
   1273  * (remember only active leases are in the structures at this time) for the
   1274  * pool, and from the IA's array.  If, after we've removed the pointer from
   1275  * IA's array to the lease, the IA has no more pointers we remove it from
   1276  * the appropriate hash table as well.
   1277  *
   1278  * \param[in] ia_table = the hash table for the IA
   1279  * \param[in] pool     = the pool to update
   1280  * \param[in] lease    = the new lease we want to add
   1281  * \param[in] ia       = the new ia we are building
   1282  *
   1283  * \return
   1284  * ISC_R_SUCCESS = the incoming lease and any previous lease were in
   1285  *                 an expected state - one of the first 3 options above.
   1286  *                 If necessary the old lease was removed.
   1287  * ISC_R_FAILURE = there is already an active lease for the address in
   1288  *                 the incoming lease.  This shouldn't happen if it does
   1289  *                 flag an error for the caller to log.
   1290  */
   1291 
   1292 isc_result_t
   1293 cleanup_lease6(ia_hash_t *ia_table,
   1294 	       struct ipv6_pool *pool,
   1295 	       struct iasubopt *lease,
   1296 	       struct ia_xx *ia) {
   1297 
   1298 	struct iasubopt *test_iasubopt, *tmp_iasubopt;
   1299 	struct ia_xx *old_ia;
   1300 	isc_result_t status = ISC_R_SUCCESS;
   1301 
   1302 	test_iasubopt = NULL;
   1303 	old_ia = NULL;
   1304 
   1305 	/*
   1306 	 * Look up the address - if we don't find a lease
   1307 	 * we don't need to do anything.
   1308 	 */
   1309 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
   1310 				 &lease->addr, sizeof(lease->addr),
   1311 				 MDL) == 0) {
   1312 		return (ISC_R_SUCCESS);
   1313 	}
   1314 
   1315 	if (test_iasubopt->ia == NULL) {
   1316 		/* no old ia, no work to do */
   1317 		iasubopt_dereference(&test_iasubopt, MDL);
   1318 		return (status);
   1319 	}
   1320 
   1321 	ia_reference(&old_ia, test_iasubopt->ia, MDL);
   1322 
   1323 	if ((old_ia->iaid_duid.len == ia->iaid_duid.len) &&
   1324 	    (memcmp((unsigned char *)ia->iaid_duid.data,
   1325 		    (unsigned char *)old_ia->iaid_duid.data,
   1326 		    ia->iaid_duid.len) == 0)) {
   1327 		/* same IA */
   1328 		if ((lease->state == FTS_ACTIVE) ||
   1329 		    (lease->state == FTS_ABANDONED)) {
   1330 			/* still active, no need to delete */
   1331 			goto cleanup;
   1332 		}
   1333 	} else {
   1334 		/* different IA */
   1335 		if ((lease->state != FTS_ACTIVE) &&
   1336 		    (lease->state != FTS_ABANDONED)) {
   1337 			/* new lease isn't active, no work */
   1338 			goto cleanup;
   1339 		}
   1340 
   1341 		/*
   1342 		 * We appear to have two active leases, this shouldn't happen.
   1343 		 * Before a second lease can be set to active the first lease
   1344 		 * should be set to inactive (released, expired etc). For now
   1345 		 * delete the previous lease and indicate a failure to the
   1346 		 * caller so it can generate a warning.
   1347 		 * In the future we may try and determine which is the better
   1348 		 * lease to keep.
   1349 		 */
   1350 
   1351 		status = ISC_R_FAILURE;
   1352 	}
   1353 
   1354 	/*
   1355 	 * Remove the old lease from the active heap and from the hash table
   1356 	 * then remove the lease from the IA and clean up the IA if necessary.
   1357 	 */
   1358 	isc_heap_delete(pool->active_timeouts, test_iasubopt->active_index);
   1359 	pool->num_active--;
   1360 	if (pool->ipv6_pond)
   1361 		pool->ipv6_pond->num_active--;
   1362 
   1363 	if (lease->state == FTS_ABANDONED) {
   1364 		pool->num_abandoned--;
   1365 		if (pool->ipv6_pond)
   1366 			pool->ipv6_pond->num_abandoned--;
   1367 	}
   1368 
   1369 	iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
   1370 			     sizeof(test_iasubopt->addr), MDL);
   1371 	ia_remove_iasubopt(old_ia, test_iasubopt, MDL);
   1372 	if (old_ia->num_iasubopt <= 0) {
   1373 		ia_hash_delete(ia_table,
   1374 			       (unsigned char *)old_ia->iaid_duid.data,
   1375 			       old_ia->iaid_duid.len, MDL);
   1376 	}
   1377 
   1378 	/*
   1379 	 * We derefenrece the subopt here as we've just removed it from
   1380 	 * the hash table in the pool.  We need to make a copy as we
   1381 	 * need to derefernece it again later.
   1382 	 */
   1383 	tmp_iasubopt = test_iasubopt;
   1384 	iasubopt_dereference(&tmp_iasubopt, MDL);
   1385 
   1386       cleanup:
   1387 	ia_dereference(&old_ia, MDL);
   1388 
   1389 	/*
   1390 	 * Clean up the reference, this is in addition to the deference
   1391 	 * above after removing the entry from the hash table
   1392 	 */
   1393 	iasubopt_dereference(&test_iasubopt, MDL);
   1394 
   1395 	return (status);
   1396 }
   1397 
   1398 /*
   1399  * Put a lease in the pool directly. This is intended to be used when
   1400  * loading leases from the file.
   1401  */
   1402 isc_result_t
   1403 add_lease6(struct ipv6_pool *pool, struct iasubopt *lease,
   1404 	   time_t valid_lifetime_end_time) {
   1405 	struct iasubopt *test_iasubopt;
   1406 	struct iasubopt *tmp_iasubopt;
   1407 
   1408 	/* If a state was not assigned by the caller, assume active. */
   1409 	if (lease->state == 0)
   1410 		lease->state = FTS_ACTIVE;
   1411 
   1412 	ipv6_pool_reference(&lease->ipv6_pool, pool, MDL);
   1413 
   1414 	/*
   1415 	 * If this IAADDR/PREFIX is already in our structures, remove the
   1416 	 * old one.
   1417 	 */
   1418 	test_iasubopt = NULL;
   1419 	if (iasubopt_hash_lookup(&test_iasubopt, pool->leases,
   1420 				 &lease->addr, sizeof(lease->addr), MDL)) {
   1421 		/* XXX: we should probably ask the lease what heap it is on
   1422 		 * (as a consistency check).
   1423 		 * XXX: we should probably have one function to "put this lease
   1424 		 * on its heap" rather than doing these if's everywhere.  If
   1425 		 * you add more states to this list, don't.
   1426 		 */
   1427 		if ((test_iasubopt->state == FTS_ACTIVE) ||
   1428 		    (test_iasubopt->state == FTS_ABANDONED)) {
   1429 			isc_heap_delete(pool->active_timeouts,
   1430 					test_iasubopt->active_index);
   1431 			pool->num_active--;
   1432 			if (pool->ipv6_pond)
   1433 				pool->ipv6_pond->num_active--;
   1434 
   1435 			if (test_iasubopt->state == FTS_ABANDONED) {
   1436 				pool->num_abandoned--;
   1437 				if (pool->ipv6_pond)
   1438 					pool->ipv6_pond->num_abandoned--;
   1439 			}
   1440 		} else {
   1441 			isc_heap_delete(pool->inactive_timeouts,
   1442 					test_iasubopt->inactive_index);
   1443 			pool->num_inactive--;
   1444 		}
   1445 
   1446 		iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
   1447 				     sizeof(test_iasubopt->addr), MDL);
   1448 
   1449 		/*
   1450 		 * We're going to do a bit of evil trickery here.
   1451 		 *
   1452 		 * We need to dereference the entry once to remove our
   1453 		 * current reference (in test_iasubopt), and then one
   1454 		 * more time to remove the reference left when the
   1455 		 * address was added to the pool before.
   1456 		 */
   1457 		tmp_iasubopt = test_iasubopt;
   1458 		iasubopt_dereference(&test_iasubopt, MDL);
   1459 		iasubopt_dereference(&tmp_iasubopt, MDL);
   1460 	}
   1461 
   1462 	/*
   1463 	 * Add IAADDR/PREFIX to our structures.
   1464 	 */
   1465 	tmp_iasubopt = NULL;
   1466 	iasubopt_reference(&tmp_iasubopt, lease, MDL);
   1467 	if ((tmp_iasubopt->state == FTS_ACTIVE) ||
   1468 	    (tmp_iasubopt->state == FTS_ABANDONED)) {
   1469 		tmp_iasubopt->hard_lifetime_end_time = valid_lifetime_end_time;
   1470 		iasubopt_hash_add(pool->leases, &tmp_iasubopt->addr,
   1471 				  sizeof(tmp_iasubopt->addr), lease, MDL);
   1472 		isc_heap_insert(pool->active_timeouts, tmp_iasubopt);
   1473 		pool->num_active++;
   1474 		if (pool->ipv6_pond)
   1475 			pool->ipv6_pond->num_active++;
   1476 
   1477 		if (tmp_iasubopt->state == FTS_ABANDONED) {
   1478 			pool->num_abandoned++;
   1479 			if (pool->ipv6_pond)
   1480 				pool->ipv6_pond->num_abandoned++;
   1481 		}
   1482 
   1483 	} else {
   1484 		tmp_iasubopt->soft_lifetime_end_time = valid_lifetime_end_time;
   1485 		isc_heap_insert(pool->inactive_timeouts, tmp_iasubopt);
   1486 		pool->num_inactive++;
   1487 	}
   1488 	iasubopt_hash_delete(pool->leases, &lease->addr,
   1489 			     sizeof(lease->addr), MDL);
   1490 	iasubopt_dereference(&tmp_iasubopt, MDL);
   1491 	/*
   1492 	 * Note: we intentionally leave tmp_iasubopt referenced; there
   1493 	 * is a reference in the heap/hash, after all.
   1494 	 */
   1495 
   1496 	return ISC_R_SUCCESS;
   1497 }
   1498 
   1499 /*
   1500  * Determine if an address is present in a pool or not.
   1501  */
   1502 isc_boolean_t
   1503 lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
   1504 	struct iasubopt *test_iaaddr;
   1505 
   1506 	test_iaaddr = NULL;
   1507 	if (iasubopt_hash_lookup(&test_iaaddr, pool->leases,
   1508 				 (void *)addr, sizeof(*addr), MDL)) {
   1509 		iasubopt_dereference(&test_iaaddr, MDL);
   1510 		return ISC_TRUE;
   1511 	} else {
   1512 		return ISC_FALSE;
   1513 	}
   1514 }
   1515 
   1516 /*!
   1517  *
   1518  * \brief Check if address is available to a lease
   1519  *
   1520  * Determine if the address in the lease is available to that
   1521  * lease.  Either the address isn't in use or it is in use
   1522  * but by that lease.
   1523  *
   1524  * \param[in] lease = lease to check
   1525  *
   1526  * \return
   1527  * ISC_TRUE  = The lease is allowed to use that address
   1528  * ISC_FALSE = The lease isn't allowed to use that address
   1529  */
   1530 isc_boolean_t
   1531 lease6_usable(struct iasubopt *lease) {
   1532 	struct iasubopt *test_iaaddr;
   1533 	isc_boolean_t status = ISC_TRUE;
   1534 
   1535 	test_iaaddr = NULL;
   1536 	if (iasubopt_hash_lookup(&test_iaaddr, lease->ipv6_pool->leases,
   1537 				 (void *)&lease->addr,
   1538 				 sizeof(lease->addr), MDL)) {
   1539 		if (test_iaaddr != lease) {
   1540 			status = ISC_FALSE;
   1541 		}
   1542 		iasubopt_dereference(&test_iaaddr, MDL);
   1543 	}
   1544 
   1545 	return (status);
   1546 }
   1547 
   1548 /*
   1549  * Put the lease on our active pool.
   1550  */
   1551 static isc_result_t
   1552 move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) {
   1553 	isc_heap_insert(pool->active_timeouts, lease);
   1554 	iasubopt_hash_add(pool->leases, &lease->addr,
   1555 			  sizeof(lease->addr), lease, MDL);
   1556 	isc_heap_delete(pool->inactive_timeouts,
   1557 			lease->inactive_index);
   1558 	pool->num_active++;
   1559 	pool->num_inactive--;
   1560 	lease->state = FTS_ACTIVE;
   1561 	if (pool->ipv6_pond)
   1562 		pool->ipv6_pond->num_active++;
   1563 
   1564 	return ISC_R_SUCCESS;
   1565 }
   1566 
   1567 /*!
   1568  *
   1569  * \brief Renew a lease in the pool.
   1570  *
   1571  * The hard_lifetime_end_time of the lease should be set to
   1572  * the current expiration time.
   1573  * The soft_lifetime_end_time of the lease should be set to
   1574  * the desired expiration time.
   1575  *
   1576  * This routine will compare the two and call the correct
   1577  * heap routine to move the lease.  If the lease is active
   1578  * and the new expiration time is greater (the normal case)
   1579  * then we call isc_heap_decreased() as a larger time is a
   1580  * lower priority.  If the new expiration time is less then
   1581  * we call isc_heap_increased().
   1582  *
   1583  * If the lease is abandoned then it will be on the active list
   1584  * and we will always call isc_heap_increased() as the previous
   1585  * expiration would have been all 1s (as close as we can get
   1586  * to infinite).
   1587  *
   1588  * If the lease is moving to active we call that routine
   1589  * which will move it from the inactive list to the active list.
   1590  *
   1591  * \param pool  = a pool the lease belongs to
   1592  * \param lease = the lease to be renewed
   1593  *
   1594  * \return result of the renew operation (ISC_R_SUCCESS if successful,
   1595            ISC_R_NOMEMORY when run out of memory)
   1596  */
   1597 isc_result_t
   1598 renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
   1599 	time_t old_end_time = lease->hard_lifetime_end_time;
   1600 	lease->hard_lifetime_end_time = lease->soft_lifetime_end_time;
   1601 	lease->soft_lifetime_end_time = 0;
   1602 
   1603 	if (lease->state == FTS_ACTIVE) {
   1604 		if (old_end_time <= lease->hard_lifetime_end_time) {
   1605 			isc_heap_decreased(pool->active_timeouts,
   1606 					   lease->active_index);
   1607 		} else {
   1608 			isc_heap_increased(pool->active_timeouts,
   1609 					   lease->active_index);
   1610 		}
   1611 		return ISC_R_SUCCESS;
   1612 	} else if (lease->state == FTS_ABANDONED) {
   1613 		char tmp_addr[INET6_ADDRSTRLEN];
   1614                 lease->state = FTS_ACTIVE;
   1615                 isc_heap_increased(pool->active_timeouts, lease->active_index);
   1616 		log_info("Reclaiming previously abandoned address %s",
   1617 			 inet_ntop(AF_INET6, &(lease->addr), tmp_addr,
   1618 				   sizeof(tmp_addr)));
   1619 
   1620 		pool->num_abandoned--;
   1621 		if (pool->ipv6_pond)
   1622 			pool->ipv6_pond->num_abandoned--;
   1623 
   1624                 return ISC_R_SUCCESS;
   1625 	} else {
   1626 		return move_lease_to_active(pool, lease);
   1627 	}
   1628 }
   1629 
   1630 /*
   1631  * Put the lease on our inactive pool, with the specified state.
   1632  */
   1633 static isc_result_t
   1634 move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
   1635 		       binding_state_t state) {
   1636 
   1637 	isc_heap_insert(pool->inactive_timeouts, lease);
   1638 	/*
   1639 	 * Handle expire and release statements
   1640 	 * To get here we must be active and have done a commit so
   1641 	 * we should run the proper statements if they exist, though
   1642 	 * that will change when we remove the inactive heap.
   1643 	 * In addition we get rid of the references for both as we
   1644 	 * can only do one (expire or release) on a lease
   1645 	 */
   1646 	if (lease->on_star.on_expiry != NULL) {
   1647 		if (state == FTS_EXPIRED) {
   1648 			execute_statements(NULL, NULL, NULL,
   1649 					   NULL, NULL, NULL,
   1650 					   &lease->scope,
   1651 					   lease->on_star.on_expiry,
   1652 					   &lease->on_star);
   1653 		}
   1654 		executable_statement_dereference
   1655 			(&lease->on_star.on_expiry, MDL);
   1656 	}
   1657 
   1658 	if (lease->on_star.on_release != NULL) {
   1659 		if (state == FTS_RELEASED) {
   1660 			execute_statements(NULL, NULL, NULL,
   1661 					   NULL, NULL, NULL,
   1662 					   &lease->scope,
   1663 					   lease->on_star.on_release,
   1664 					   &lease->on_star);
   1665 		}
   1666 		executable_statement_dereference
   1667 			(&lease->on_star.on_release, MDL);
   1668 	}
   1669 
   1670 #if defined (NSUPDATE)
   1671 	/* Process events upon expiration. */
   1672 	if (pool->pool_type != D6O_IA_PD) {
   1673 		(void) ddns_removals(NULL, lease, NULL, ISC_FALSE);
   1674 	}
   1675 #endif
   1676 
   1677 	/* Binding scopes are no longer valid after expiry or
   1678 	 * release.
   1679 	 */
   1680 	if (lease->scope != NULL) {
   1681 		binding_scope_dereference(&lease->scope, MDL);
   1682 	}
   1683 
   1684 	iasubopt_hash_delete(pool->leases,
   1685 			     &lease->addr, sizeof(lease->addr), MDL);
   1686 	isc_heap_delete(pool->active_timeouts, lease->active_index);
   1687 	lease->state = state;
   1688 	pool->num_active--;
   1689 	pool->num_inactive++;
   1690 	if (pool->ipv6_pond)
   1691 		pool->ipv6_pond->num_active--;
   1692 
   1693 	if (lease->state == FTS_ABANDONED) {
   1694 		pool->num_abandoned--;
   1695 		if (pool->ipv6_pond)
   1696 			pool->ipv6_pond->num_abandoned--;
   1697 	}
   1698 	return ISC_R_SUCCESS;
   1699 }
   1700 
   1701 /*
   1702  * Expire the oldest lease if it's lifetime_end_time is
   1703  * older than the given time.
   1704  *
   1705  * - leasep must be a pointer to a (struct iasubopt *) pointer previously
   1706  *   initialized to NULL
   1707  *
   1708  * On return leasep has a reference to the removed entry. It is left
   1709  * pointing to NULL if the oldest lease has not expired.
   1710  */
   1711 isc_result_t
   1712 expire_lease6(struct iasubopt **leasep, struct ipv6_pool *pool, time_t now) {
   1713 	struct iasubopt *tmp;
   1714 	isc_result_t result;
   1715 
   1716 	if (leasep == NULL) {
   1717 		log_error("%s(%d): NULL pointer reference", MDL);
   1718 		return DHCP_R_INVALIDARG;
   1719 	}
   1720 	if (*leasep != NULL) {
   1721 		log_error("%s(%d): non-NULL pointer", MDL);
   1722 		return DHCP_R_INVALIDARG;
   1723 	}
   1724 
   1725 	if (pool->num_active > 0) {
   1726 		tmp = (struct iasubopt *)
   1727 				isc_heap_element(pool->active_timeouts, 1);
   1728 		if (now > tmp->hard_lifetime_end_time) {
   1729 			result = move_lease_to_inactive(pool, tmp,
   1730 							FTS_EXPIRED);
   1731 			if (result == ISC_R_SUCCESS) {
   1732 				iasubopt_reference(leasep, tmp, MDL);
   1733 			}
   1734 			return result;
   1735 		}
   1736 	}
   1737 	return ISC_R_SUCCESS;
   1738 }
   1739 
   1740 
   1741 /*
   1742  * For a declined lease, leave it on the "active" pool, but mark
   1743  * it as declined. Give it an infinite (well, really long) life.
   1744  */
   1745 isc_result_t
   1746 decline_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
   1747 	isc_result_t result;
   1748 
   1749 	if ((lease->state != FTS_ACTIVE) &&
   1750 	    (lease->state != FTS_ABANDONED)) {
   1751 		result = move_lease_to_active(pool, lease);
   1752 		if (result != ISC_R_SUCCESS) {
   1753 			return result;
   1754 		}
   1755 	}
   1756 	lease->state = FTS_ABANDONED;
   1757 
   1758 	pool->num_abandoned++;
   1759 	if (pool->ipv6_pond)
   1760 		pool->ipv6_pond->num_abandoned++;
   1761 
   1762 	lease->hard_lifetime_end_time = MAX_TIME;
   1763 	isc_heap_decreased(pool->active_timeouts, lease->active_index);
   1764 	return ISC_R_SUCCESS;
   1765 }
   1766 
   1767 /*
   1768  * Put the returned lease on our inactive pool.
   1769  */
   1770 isc_result_t
   1771 release_lease6(struct ipv6_pool *pool, struct iasubopt *lease) {
   1772 	if (lease->state == FTS_ACTIVE) {
   1773 		return move_lease_to_inactive(pool, lease, FTS_RELEASED);
   1774 	} else {
   1775 		return ISC_R_SUCCESS;
   1776 	}
   1777 }
   1778 
   1779 /*
   1780  * Create a prefix by hashing the input, and using that for
   1781  * the part subject to allocation.
   1782  */
   1783 static void
   1784 build_prefix6(struct in6_addr *pref,
   1785 	      const struct in6_addr *net_start_pref,
   1786 	      int pool_bits, int pref_bits,
   1787 	      const struct data_string *input) {
   1788 	int net_bytes;
   1789 	int i;
   1790 	unsigned int len;
   1791 	char *str;
   1792 	const char *net_str;
   1793 
   1794 	/*
   1795 	 * Use MD5 to get a nice 128 bit hash of the input.
   1796 	 * Yes, we know MD5 isn't cryptographically sound.
   1797 	 * No, we don't care.
   1798 	 */
   1799 	isc_md(ISC_MD_MD5, input->data, input->len, (void *)&pref, &len);
   1800 
   1801 	/*
   1802 	 * Copy the network bits over.
   1803 	 */
   1804 	str = (char *)pref;
   1805 	net_str = (const char *)net_start_pref;
   1806 	net_bytes = pool_bits / 8;
   1807 	for (i = 0; i < net_bytes; i++) {
   1808 		str[i] = net_str[i];
   1809 	}
   1810 	i = net_bytes;
   1811 	switch (pool_bits % 8) {
   1812 		case 1: str[i] = (str[i] & 0x7F) | (net_str[i] & 0x80); break;
   1813 		case 2: str[i] = (str[i] & 0x3F) | (net_str[i] & 0xC0); break;
   1814 		case 3: str[i] = (str[i] & 0x1F) | (net_str[i] & 0xE0); break;
   1815 		case 4: str[i] = (str[i] & 0x0F) | (net_str[i] & 0xF0); break;
   1816 		case 5: str[i] = (str[i] & 0x07) | (net_str[i] & 0xF8); break;
   1817 		case 6: str[i] = (str[i] & 0x03) | (net_str[i] & 0xFC); break;
   1818 		case 7: str[i] = (str[i] & 0x01) | (net_str[i] & 0xFE); break;
   1819 	}
   1820 	/*
   1821 	 * Zero the remaining bits.
   1822 	 */
   1823 	net_bytes = pref_bits / 8;
   1824 	for (i=net_bytes+1; i<16; i++) {
   1825 		str[i] = 0;
   1826 	}
   1827 	i = net_bytes;
   1828 	switch (pref_bits % 8) {
   1829 		case 0: str[i] &= 0; break;
   1830 		case 1: str[i] &= 0x80; break;
   1831 		case 2: str[i] &= 0xC0; break;
   1832 		case 3: str[i] &= 0xE0; break;
   1833 		case 4: str[i] &= 0xF0; break;
   1834 		case 5: str[i] &= 0xF8; break;
   1835 		case 6: str[i] &= 0xFC; break;
   1836 		case 7: str[i] &= 0xFE; break;
   1837 	}
   1838 }
   1839 
   1840 /*
   1841  * Create a lease for the given prefix and client duid.
   1842  *
   1843  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
   1844  *   initialized to NULL
   1845  *
   1846  * Right now we simply hash the DUID, and if we get a collision, we hash
   1847  * again until we find a free prefix. We try this a fixed number of times,
   1848  * to avoid getting stuck in a loop (this is important on small pools
   1849  * where we can run out of space).
   1850  *
   1851  * We return the number of attempts that it took to find an available
   1852  * prefix. This tells callers when a pool is are filling up, as
   1853  * well as an indication of how full the pool is; statistically the
   1854  * more full a pool is the more attempts must be made before finding
   1855  * a free prefix. Realistically this will only happen in very full
   1856  * pools.
   1857  *
   1858  * We probably want different algorithms depending on the network size, in
   1859  * the long term.
   1860  */
   1861 isc_result_t
   1862 create_prefix6(struct ipv6_pool *pool, struct iasubopt **pref,
   1863 	       unsigned int *attempts,
   1864 	       const struct data_string *uid,
   1865 	       time_t soft_lifetime_end_time) {
   1866 	struct data_string ds;
   1867 	struct in6_addr tmp;
   1868 	struct iasubopt *test_iapref;
   1869 	struct data_string new_ds;
   1870 	struct iasubopt *iapref;
   1871 	isc_result_t result;
   1872 
   1873 	/*
   1874 	 * Use the UID as our initial seed for the hash
   1875 	 */
   1876 	memset(&ds, 0, sizeof(ds));
   1877 	data_string_copy(&ds, (struct data_string *)uid, MDL);
   1878 
   1879 	*attempts = 0;
   1880 	for (;;) {
   1881 		/*
   1882 		 * Give up at some point.
   1883 		 */
   1884 		if (++(*attempts) > 10) {
   1885 			data_string_forget(&ds, MDL);
   1886 			return ISC_R_NORESOURCES;
   1887 		}
   1888 
   1889 		/*
   1890 		 * Build a prefix
   1891 		 */
   1892 		build_prefix6(&tmp, &pool->start_addr,
   1893 			      pool->bits, pool->units, &ds);
   1894 
   1895 		/*
   1896 		 * If this prefix is not in use, we're happy with it
   1897 		 */
   1898 		test_iapref = NULL;
   1899 		if (iasubopt_hash_lookup(&test_iapref, pool->leases,
   1900 					 &tmp, sizeof(tmp), MDL) == 0) {
   1901 			break;
   1902 		}
   1903 		iasubopt_dereference(&test_iapref, MDL);
   1904 
   1905 		/*
   1906 		 * Otherwise, we create a new input, adding the prefix
   1907 		 */
   1908 		memset(&new_ds, 0, sizeof(new_ds));
   1909 		new_ds.len = ds.len + sizeof(tmp);
   1910 		if (!buffer_allocate(&new_ds.buffer, new_ds.len, MDL)) {
   1911 			data_string_forget(&ds, MDL);
   1912 			return ISC_R_NOMEMORY;
   1913 		}
   1914 		new_ds.data = new_ds.buffer->data;
   1915 		memcpy(new_ds.buffer->data, ds.data, ds.len);
   1916 		memcpy(&new_ds.buffer->data[0] + ds.len, &tmp, sizeof(tmp));
   1917 		data_string_forget(&ds, MDL);
   1918 		data_string_copy(&ds, &new_ds, MDL);
   1919 		data_string_forget(&new_ds, MDL);
   1920 	}
   1921 
   1922 	data_string_forget(&ds, MDL);
   1923 
   1924 	/*
   1925 	 * We're happy with the prefix, create an IAPREFIX
   1926 	 * to hold it.
   1927 	 */
   1928 	iapref = NULL;
   1929 	result = iasubopt_allocate(&iapref, MDL);
   1930 	if (result != ISC_R_SUCCESS) {
   1931 		return result;
   1932 	}
   1933 	iapref->plen = (u_int8_t)pool->units;
   1934 	memcpy(&iapref->addr, &tmp, sizeof(iapref->addr));
   1935 
   1936 	/*
   1937 	 * Add the prefix to the pool (note state is free, not active?!).
   1938 	 */
   1939 	result = add_lease6(pool, iapref, soft_lifetime_end_time);
   1940 	if (result == ISC_R_SUCCESS) {
   1941 		iasubopt_reference(pref, iapref, MDL);
   1942 	}
   1943 	iasubopt_dereference(&iapref, MDL);
   1944 	return result;
   1945 }
   1946 
   1947 /*
   1948  * Determine if a prefix is present in a pool or not.
   1949  */
   1950 isc_boolean_t
   1951 prefix6_exists(const struct ipv6_pool *pool,
   1952 	       const struct in6_addr *pref, u_int8_t plen) {
   1953 	struct iasubopt *test_iapref;
   1954 
   1955 	if ((int)plen != pool->units)
   1956 		return ISC_FALSE;
   1957 
   1958 	test_iapref = NULL;
   1959 	if (iasubopt_hash_lookup(&test_iapref, pool->leases,
   1960 				 (void *)pref, sizeof(*pref), MDL)) {
   1961 		iasubopt_dereference(&test_iapref, MDL);
   1962 		return ISC_TRUE;
   1963 	} else {
   1964 		return ISC_FALSE;
   1965 	}
   1966 }
   1967 
   1968 /*
   1969  * Mark an IPv6 address/prefix as unavailable from a pool.
   1970  *
   1971  * This is used for host entries and the addresses of the server itself.
   1972  */
   1973 static isc_result_t
   1974 mark_lease_unavailable(struct ipv6_pool *pool, const struct in6_addr *addr) {
   1975 	struct iasubopt *dummy_iasubopt;
   1976 	isc_result_t result;
   1977 
   1978 	dummy_iasubopt = NULL;
   1979 	result = iasubopt_allocate(&dummy_iasubopt, MDL);
   1980 	if (result == ISC_R_SUCCESS) {
   1981 		dummy_iasubopt->addr = *addr;
   1982 		iasubopt_hash_add(pool->leases, &dummy_iasubopt->addr,
   1983 				  sizeof(*addr), dummy_iasubopt, MDL);
   1984 	}
   1985 	return result;
   1986 }
   1987 
   1988 /*
   1989  * Add a pool.
   1990  */
   1991 isc_result_t
   1992 add_ipv6_pool(struct ipv6_pool *pool) {
   1993 	struct ipv6_pool **new_pools;
   1994 
   1995 	new_pools = dmalloc(sizeof(struct ipv6_pool *) * (num_pools+1), MDL);
   1996 	if (new_pools == NULL) {
   1997 		return ISC_R_NOMEMORY;
   1998 	}
   1999 
   2000 	if (num_pools > 0) {
   2001 		memcpy(new_pools, pools,
   2002 		       sizeof(struct ipv6_pool *) * num_pools);
   2003 		dfree(pools, MDL);
   2004 	}
   2005 	pools = new_pools;
   2006 
   2007 	pools[num_pools] = NULL;
   2008 	ipv6_pool_reference(&pools[num_pools], pool, MDL);
   2009 	num_pools++;
   2010 	return ISC_R_SUCCESS;
   2011 }
   2012 
   2013 static void
   2014 cleanup_old_expired(struct ipv6_pool *pool) {
   2015 	struct iasubopt *tmp;
   2016 	struct ia_xx *ia;
   2017 	struct ia_xx *ia_active;
   2018 	unsigned char *tmpd;
   2019 	time_t timeout;
   2020 
   2021 	while (pool->num_inactive > 0) {
   2022 		tmp = (struct iasubopt *)
   2023 				isc_heap_element(pool->inactive_timeouts, 1);
   2024 		if (tmp->hard_lifetime_end_time != 0) {
   2025 			timeout = tmp->hard_lifetime_end_time;
   2026 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
   2027 		} else {
   2028 			timeout = tmp->soft_lifetime_end_time;
   2029 		}
   2030 		if (cur_time < timeout) {
   2031 			break;
   2032 		}
   2033 
   2034 		isc_heap_delete(pool->inactive_timeouts, tmp->inactive_index);
   2035 		pool->num_inactive--;
   2036 
   2037 		if (tmp->ia != NULL) {
   2038 			/*
   2039 			 * Check to see if this IA is in an active list,
   2040 			 * but has no remaining resources. If so, remove it
   2041 			 * from the active list.
   2042 			 */
   2043 			ia = NULL;
   2044 			ia_reference(&ia, tmp->ia, MDL);
   2045 			ia_remove_iasubopt(ia, tmp, MDL);
   2046 			ia_active = NULL;
   2047 			tmpd = (unsigned char *)ia->iaid_duid.data;
   2048 			if ((ia->ia_type == D6O_IA_NA) &&
   2049 			    (ia->num_iasubopt <= 0) &&
   2050 			    (ia_hash_lookup(&ia_active, ia_na_active, tmpd,
   2051 					    ia->iaid_duid.len, MDL) == 0) &&
   2052 			    (ia_active == ia)) {
   2053 				ia_hash_delete(ia_na_active, tmpd,
   2054 					       ia->iaid_duid.len, MDL);
   2055 			}
   2056 			if ((ia->ia_type == D6O_IA_TA) &&
   2057 			    (ia->num_iasubopt <= 0) &&
   2058 			    (ia_hash_lookup(&ia_active, ia_ta_active, tmpd,
   2059 					    ia->iaid_duid.len, MDL) == 0) &&
   2060 			    (ia_active == ia)) {
   2061 				ia_hash_delete(ia_ta_active, tmpd,
   2062 					       ia->iaid_duid.len, MDL);
   2063 			}
   2064 			if ((ia->ia_type == D6O_IA_PD) &&
   2065 			    (ia->num_iasubopt <= 0) &&
   2066 			    (ia_hash_lookup(&ia_active, ia_pd_active, tmpd,
   2067 					    ia->iaid_duid.len, MDL) == 0) &&
   2068 			    (ia_active == ia)) {
   2069 				ia_hash_delete(ia_pd_active, tmpd,
   2070 					       ia->iaid_duid.len, MDL);
   2071 			}
   2072 			ia_dereference(&ia, MDL);
   2073 		}
   2074 		iasubopt_dereference(&tmp, MDL);
   2075 	}
   2076 }
   2077 
   2078 static void
   2079 lease_timeout_support(void *vpool) {
   2080 	struct ipv6_pool *pool;
   2081 	struct iasubopt *lease;
   2082 
   2083 	pool = (struct ipv6_pool *)vpool;
   2084 	for (;;) {
   2085 		/*
   2086 		 * Get the next lease scheduled to expire.
   2087 		 *
   2088 		 * Note that if there are no leases in the pool,
   2089 		 * expire_lease6() will return ISC_R_SUCCESS with
   2090 		 * a NULL lease.
   2091 		 *
   2092 		 * expire_lease6() will call move_lease_to_inactive() which
   2093 		 * calls ddns_removals() do we want that on the standard
   2094 		 * expiration timer or a special 'depref' timer?  Original
   2095 		 * query from DH, moved here by SAR.
   2096 		 */
   2097 		lease = NULL;
   2098 		if (expire_lease6(&lease, pool, cur_time) != ISC_R_SUCCESS) {
   2099 			break;
   2100 		}
   2101 		if (lease == NULL) {
   2102 			break;
   2103 		}
   2104 
   2105 		write_ia(lease->ia);
   2106 
   2107 		iasubopt_dereference(&lease, MDL);
   2108 	}
   2109 
   2110 	/*
   2111 	 * If appropriate commit and rotate the lease file
   2112 	 * As commit_leases_timed() checks to see if we've done any writes
   2113 	 * we don't bother tracking if this function called write _ia
   2114 	 */
   2115 	(void) commit_leases_timed();
   2116 
   2117 	/*
   2118 	 * Do some cleanup of our expired leases.
   2119 	 */
   2120 	cleanup_old_expired(pool);
   2121 
   2122 	/*
   2123 	 * Schedule next round of expirations.
   2124 	 */
   2125 	schedule_lease_timeout(pool);
   2126 }
   2127 
   2128 /*
   2129  * For a given pool, add a timer that will remove the next
   2130  * lease to expire.
   2131  */
   2132 void
   2133 schedule_lease_timeout(struct ipv6_pool *pool) {
   2134 	struct iasubopt *tmp;
   2135 	time_t timeout;
   2136 	time_t next_timeout;
   2137 	struct timeval tv;
   2138 
   2139 	next_timeout = MAX_TIME;
   2140 
   2141 	if (pool->num_active > 0) {
   2142 		tmp = (struct iasubopt *)
   2143 				isc_heap_element(pool->active_timeouts, 1);
   2144 		if (tmp->hard_lifetime_end_time < next_timeout) {
   2145 			next_timeout = tmp->hard_lifetime_end_time + 1;
   2146 		}
   2147 	}
   2148 
   2149 	if (pool->num_inactive > 0) {
   2150 		tmp = (struct iasubopt *)
   2151 				isc_heap_element(pool->inactive_timeouts, 1);
   2152 		if (tmp->hard_lifetime_end_time != 0) {
   2153 			timeout = tmp->hard_lifetime_end_time;
   2154 			timeout += EXPIRED_IPV6_CLEANUP_TIME;
   2155 		} else {
   2156 			timeout = tmp->soft_lifetime_end_time + 1;
   2157 		}
   2158 		if (timeout < next_timeout) {
   2159 			next_timeout = timeout;
   2160 		}
   2161 	}
   2162 
   2163 	if (next_timeout < MAX_TIME) {
   2164 		tv.tv_sec = next_timeout;
   2165 		tv.tv_usec = 0;
   2166 		add_timeout(&tv, lease_timeout_support, pool,
   2167 			    (tvref_t)ipv6_pool_reference,
   2168 			    (tvunref_t)ipv6_pool_dereference);
   2169 	}
   2170 }
   2171 
   2172 /*
   2173  * Schedule timeouts across all pools.
   2174  */
   2175 void
   2176 schedule_all_ipv6_lease_timeouts(void) {
   2177 	int i;
   2178 
   2179 	for (i=0; i<num_pools; i++) {
   2180 		schedule_lease_timeout(pools[i]);
   2181 	}
   2182 }
   2183 
   2184 /*
   2185  * Given an address and the length of the network mask, return
   2186  * only the network portion.
   2187  *
   2188  * Examples:
   2189  *
   2190  *   "fe80::216:6fff:fe49:7d9b", length 64 = "fe80::"
   2191  *   "2001:888:1936:2:216:6fff:fe49:7d9b", length 48 = "2001:888:1936::"
   2192  */
   2193 static void
   2194 ipv6_network_portion(struct in6_addr *result,
   2195 		     const struct in6_addr *addr, int bits) {
   2196 	unsigned char *addrp;
   2197 	int mask_bits;
   2198 	int bytes;
   2199 	int extra_bits;
   2200 	int i;
   2201 
   2202 	static const unsigned char bitmasks[] = {
   2203 		0x00, 0xFE, 0xFC, 0xF8,
   2204 		0xF0, 0xE0, 0xC0, 0x80,
   2205 	};
   2206 
   2207 	/*
   2208 	 *  Sanity check our bits. ;)
   2209 	 */
   2210 	if ((bits < 0) || (bits > 128)) {
   2211 		log_fatal("ipv6_network_portion: bits %d not between 0 and 128",
   2212 			  bits);
   2213 	}
   2214 
   2215 	/*
   2216 	 * Copy our address portion.
   2217 	 */
   2218 	*result = *addr;
   2219 	addrp = ((unsigned char *)result) + 15;
   2220 
   2221 	/*
   2222 	 * Zero out masked portion.
   2223 	 */
   2224 	mask_bits = 128 - bits;
   2225 	bytes = mask_bits / 8;
   2226 	extra_bits = mask_bits % 8;
   2227 
   2228 	for (i=0; i<bytes; i++) {
   2229 		*addrp = 0;
   2230 		addrp--;
   2231 	}
   2232 	if (extra_bits) {
   2233 		*addrp &= bitmasks[extra_bits];
   2234 	}
   2235 }
   2236 
   2237 /*
   2238  * Determine if the given address/prefix is in the pool.
   2239  */
   2240 isc_boolean_t
   2241 ipv6_in_pool(const struct in6_addr *addr, const struct ipv6_pool *pool) {
   2242 	struct in6_addr tmp;
   2243 
   2244 	ipv6_network_portion(&tmp, addr, pool->bits);
   2245 	if (memcmp(&tmp, &pool->start_addr, sizeof(tmp)) == 0) {
   2246 		return ISC_TRUE;
   2247 	} else {
   2248 		return ISC_FALSE;
   2249 	}
   2250 }
   2251 
   2252 /*
   2253  * Find the pool that contains the given address.
   2254  *
   2255  * - pool must be a pointer to a (struct ipv6_pool *) pointer previously
   2256  *   initialized to NULL
   2257  */
   2258 isc_result_t
   2259 find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type,
   2260 	       const struct in6_addr *addr) {
   2261 	int i;
   2262 
   2263 	if (pool == NULL) {
   2264 		log_error("%s(%d): NULL pointer reference", MDL);
   2265 		return DHCP_R_INVALIDARG;
   2266 	}
   2267 	if (*pool != NULL) {
   2268 		log_error("%s(%d): non-NULL pointer", MDL);
   2269 		return DHCP_R_INVALIDARG;
   2270 	}
   2271 
   2272 	for (i=0; i<num_pools; i++) {
   2273 		if (pools[i]->pool_type != type)
   2274 			continue;
   2275 		if (ipv6_in_pool(addr, pools[i])) {
   2276 			ipv6_pool_reference(pool, pools[i], MDL);
   2277 			return ISC_R_SUCCESS;
   2278 		}
   2279 	}
   2280 	return ISC_R_NOTFOUND;
   2281 }
   2282 
   2283 /*
   2284  * Helper function for the various functions that act across all
   2285  * pools.
   2286  */
   2287 static isc_result_t
   2288 change_leases(struct ia_xx *ia,
   2289 	      isc_result_t (*change_func)(struct ipv6_pool *,
   2290 					  struct iasubopt *)) {
   2291 	isc_result_t retval;
   2292 	isc_result_t renew_retval;
   2293 	struct ipv6_pool *pool;
   2294 	struct in6_addr *addr;
   2295 	int i;
   2296 
   2297 	retval = ISC_R_SUCCESS;
   2298 	for (i=0; i<ia->num_iasubopt; i++) {
   2299 		pool = NULL;
   2300 		addr = &ia->iasubopt[i]->addr;
   2301 		if (find_ipv6_pool(&pool, ia->ia_type,
   2302 				   addr) == ISC_R_SUCCESS) {
   2303 			renew_retval = change_func(pool, ia->iasubopt[i]);
   2304 			if (renew_retval != ISC_R_SUCCESS) {
   2305 				retval = renew_retval;
   2306 			}
   2307 		}
   2308 		/* XXXsk: should we warn if we don't find a pool? */
   2309 	}
   2310 	return retval;
   2311 }
   2312 
   2313 /*
   2314  * Renew all leases in an IA from all pools.
   2315  *
   2316  * The new lifetime should be in the soft_lifetime_end_time
   2317  * and will be moved to hard_lifetime_end_time by renew_lease6.
   2318  */
   2319 isc_result_t
   2320 renew_leases(struct ia_xx *ia) {
   2321 	return change_leases(ia, renew_lease6);
   2322 }
   2323 
   2324 /*
   2325  * Release all leases in an IA from all pools.
   2326  */
   2327 isc_result_t
   2328 release_leases(struct ia_xx *ia) {
   2329 	return change_leases(ia, release_lease6);
   2330 }
   2331 
   2332 /*
   2333  * Decline all leases in an IA from all pools.
   2334  */
   2335 isc_result_t
   2336 decline_leases(struct ia_xx *ia) {
   2337 	return change_leases(ia, decline_lease6);
   2338 }
   2339 
   2340 #ifdef DHCPv6
   2341 /*
   2342  * Helper function to output leases.
   2343  */
   2344 static int write_error;
   2345 
   2346 static isc_result_t
   2347 write_ia_leases(const void *name, unsigned len, void *value) {
   2348 	struct ia_xx *ia = (struct ia_xx *)value;
   2349 
   2350 	if (!write_error) {
   2351 		if (!write_ia(ia)) {
   2352 			write_error = 1;
   2353 		}
   2354 	}
   2355 	return ISC_R_SUCCESS;
   2356 }
   2357 
   2358 /*
   2359  * Write all DHCPv6 information.
   2360  */
   2361 int
   2362 write_leases6(void) {
   2363 	int nas, tas, pds;
   2364 
   2365 	write_error = 0;
   2366 	write_server_duid();
   2367 	nas = ia_hash_foreach(ia_na_active, write_ia_leases);
   2368 	if (write_error) {
   2369 		return 0;
   2370 	}
   2371 	tas = ia_hash_foreach(ia_ta_active, write_ia_leases);
   2372 	if (write_error) {
   2373 		return 0;
   2374 	}
   2375 	pds = ia_hash_foreach(ia_pd_active, write_ia_leases);
   2376 	if (write_error) {
   2377 		return 0;
   2378 	}
   2379 
   2380 	log_info("Wrote %d NA, %d TA, %d PD leases to lease file.",
   2381 		 nas, tas, pds);
   2382 	return 1;
   2383 }
   2384 #endif /* DHCPv6 */
   2385 
   2386 static isc_result_t
   2387 mark_hosts_unavailable_support(const void *name, unsigned len, void *value) {
   2388 	struct host_decl *h;
   2389 	struct data_string fixed_addr;
   2390 	struct in6_addr addr;
   2391 	struct ipv6_pool *p;
   2392 
   2393 	h = (struct host_decl *)value;
   2394 
   2395 	/*
   2396 	 * If the host has no address, we don't need to mark anything.
   2397 	 */
   2398 	if (h->fixed_addr == NULL) {
   2399 		return ISC_R_SUCCESS;
   2400 	}
   2401 
   2402 	/*
   2403 	 * Evaluate the fixed address.
   2404 	 */
   2405 	memset(&fixed_addr, 0, sizeof(fixed_addr));
   2406 	if (!evaluate_option_cache(&fixed_addr, NULL, NULL, NULL, NULL, NULL,
   2407 				   &global_scope, h->fixed_addr, MDL)) {
   2408 		log_error("mark_hosts_unavailable: "
   2409 			  "error evaluating host address.");
   2410 		return ISC_R_SUCCESS;
   2411 	}
   2412 	if (fixed_addr.len != 16) {
   2413 		log_error("mark_hosts_unavailable: "
   2414 			  "host address is not 128 bits.");
   2415 		return ISC_R_SUCCESS;
   2416 	}
   2417 	memcpy(&addr, fixed_addr.data, 16);
   2418 	data_string_forget(&fixed_addr, MDL);
   2419 
   2420 	/*
   2421 	 * Find the pool holding this host, and mark the address.
   2422 	 * (I suppose it is arguably valid to have a host that does not
   2423 	 * sit in any pool.)
   2424 	 */
   2425 	p = NULL;
   2426 	if (find_ipv6_pool(&p, D6O_IA_NA, &addr) == ISC_R_SUCCESS) {
   2427 		mark_lease_unavailable(p, &addr);
   2428 		ipv6_pool_dereference(&p, MDL);
   2429 	}
   2430 	if (find_ipv6_pool(&p, D6O_IA_TA, &addr) == ISC_R_SUCCESS) {
   2431 		mark_lease_unavailable(p, &addr);
   2432 		ipv6_pool_dereference(&p, MDL);
   2433 	}
   2434 
   2435 	return ISC_R_SUCCESS;
   2436 }
   2437 
   2438 void
   2439 mark_hosts_unavailable(void) {
   2440 	hash_foreach(host_name_hash, mark_hosts_unavailable_support);
   2441 }
   2442 
   2443 static isc_result_t
   2444 mark_phosts_unavailable_support(const void *name, unsigned len, void *value) {
   2445 	struct host_decl *h;
   2446 	struct iaddrcidrnetlist *l;
   2447 	struct in6_addr pref;
   2448 	struct ipv6_pool *p;
   2449 
   2450 	h = (struct host_decl *)value;
   2451 
   2452 	/*
   2453 	 * If the host has no prefix, we don't need to mark anything.
   2454 	 */
   2455 	if (h->fixed_prefix == NULL) {
   2456 		return ISC_R_SUCCESS;
   2457 	}
   2458 
   2459 	/*
   2460 	 * Get the fixed prefixes.
   2461 	 */
   2462 	for (l = h->fixed_prefix; l != NULL; l = l->next) {
   2463 		if (l->cidrnet.lo_addr.len != 16) {
   2464 			continue;
   2465 		}
   2466 		memcpy(&pref, l->cidrnet.lo_addr.iabuf, 16);
   2467 
   2468 		/*
   2469 		 * Find the pool holding this host, and mark the prefix.
   2470 		 * (I suppose it is arguably valid to have a host that does not
   2471 		 * sit in any pool.)
   2472 		 */
   2473 		p = NULL;
   2474 		if (find_ipv6_pool(&p, D6O_IA_PD, &pref) != ISC_R_SUCCESS) {
   2475 			continue;
   2476 		}
   2477 		if (l->cidrnet.bits != p->units) {
   2478 			ipv6_pool_dereference(&p, MDL);
   2479 			continue;
   2480 		}
   2481 		mark_lease_unavailable(p, &pref);
   2482 		ipv6_pool_dereference(&p, MDL);
   2483 	}
   2484 
   2485 	return ISC_R_SUCCESS;
   2486 }
   2487 
   2488 void
   2489 mark_phosts_unavailable(void) {
   2490 	hash_foreach(host_name_hash, mark_phosts_unavailable_support);
   2491 }
   2492 
   2493 void
   2494 mark_interfaces_unavailable(void) {
   2495 	struct interface_info *ip;
   2496 	int i;
   2497 	struct ipv6_pool *p;
   2498 
   2499 	ip = interfaces;
   2500 	while (ip != NULL) {
   2501 		for (i=0; i<ip->v6address_count; i++) {
   2502 			p = NULL;
   2503 			if (find_ipv6_pool(&p, D6O_IA_NA, &ip->v6addresses[i])
   2504 							== ISC_R_SUCCESS) {
   2505 				mark_lease_unavailable(p,
   2506 						       &ip->v6addresses[i]);
   2507 				ipv6_pool_dereference(&p, MDL);
   2508 			}
   2509 			if (find_ipv6_pool(&p, D6O_IA_TA, &ip->v6addresses[i])
   2510 							== ISC_R_SUCCESS) {
   2511 				mark_lease_unavailable(p,
   2512 						       &ip->v6addresses[i]);
   2513 				ipv6_pool_dereference(&p, MDL);
   2514 			}
   2515 		}
   2516 		ip = ip->next;
   2517 	}
   2518 }
   2519 
   2520 /*!
   2521  * \brief Create a new IPv6 pond structure.
   2522  *
   2523  * Allocate space for a new ipv6_pond structure and return a reference
   2524  * to it, includes setting the reference count to 1.
   2525  *
   2526  * \param pond = space for returning a referenced pointer to the pond.
   2527  *		 This must point to a space that has been initialzied
   2528  *		 to NULL by the caller.
   2529  *
   2530  * \return
   2531  * ISC_R_SUCCESS     = The pond was successfully created, pond points to it.
   2532  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
   2533  *		       modified
   2534  * ISC_R_NOMEMORY    = The system wasn't able to allocate memory, pond has
   2535  *		       not been modified.
   2536  */
   2537 isc_result_t
   2538 ipv6_pond_allocate(struct ipv6_pond **pond, const char *file, int line) {
   2539 	struct ipv6_pond *tmp;
   2540 
   2541 	if (pond == NULL) {
   2542 		log_error("%s(%d): NULL pointer reference", file, line);
   2543 		return DHCP_R_INVALIDARG;
   2544 	}
   2545 	if (*pond != NULL) {
   2546 		log_error("%s(%d): non-NULL pointer", file, line);
   2547 		return DHCP_R_INVALIDARG;
   2548 	}
   2549 
   2550 	tmp = dmalloc(sizeof(*tmp), file, line);
   2551 	if (tmp == NULL) {
   2552 		return ISC_R_NOMEMORY;
   2553 	}
   2554 
   2555 	tmp->refcnt = 1;
   2556 
   2557 	*pond = tmp;
   2558 	return ISC_R_SUCCESS;
   2559 }
   2560 
   2561 /*!
   2562  *
   2563  * \brief reference an IPv6 pond structure.
   2564  *
   2565  * This function genreates a reference to an ipv6_pond structure
   2566  * and increments the reference count on the structure.
   2567  *
   2568  * \param[out] pond = space for returning a referenced pointer to the pond.
   2569  *		      This must point to a space that has been initialzied
   2570  *		      to NULL by the caller.
   2571  * \param[in]  src  = A pointer to the pond to reference.  This must not be
   2572  *		      NULL.
   2573  *
   2574  * \return
   2575  * ISC_R_SUCCESS     = The pond was successfully referenced, pond now points
   2576  *		       to src.
   2577  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
   2578  *		       modified.
   2579  */
   2580 isc_result_t
   2581 ipv6_pond_reference(struct ipv6_pond **pond, struct ipv6_pond *src,
   2582 		    const char *file, int line) {
   2583 	if (pond == NULL) {
   2584 		log_error("%s(%d): NULL pointer reference", file, line);
   2585 		return DHCP_R_INVALIDARG;
   2586 	}
   2587 	if (*pond != NULL) {
   2588 		log_error("%s(%d): non-NULL pointer", file, line);
   2589 		return DHCP_R_INVALIDARG;
   2590 	}
   2591 	if (src == NULL) {
   2592 		log_error("%s(%d): NULL pointer reference", file, line);
   2593 		return DHCP_R_INVALIDARG;
   2594 	}
   2595 	*pond = src;
   2596 	src->refcnt++;
   2597 	return ISC_R_SUCCESS;
   2598 }
   2599 
   2600 /*!
   2601  *
   2602  * \brief de-reference an IPv6 pond structure.
   2603  *
   2604  * This function decrements the reference count in an ipv6_pond structure.
   2605  * If this was the last reference then the memory for the structure is
   2606  * freed.
   2607  *
   2608  * \param[in] pond = A pointer to the pointer to the pond that should be
   2609  *		     de-referenced.  On success the pointer to the pond
   2610  *		     is cleared.  It must not be NULL and must not point
   2611  *		     to NULL.
   2612  *
   2613  * \return
   2614  * ISC_R_SUCCESS     = The pond was successfully de-referenced, pond now points
   2615  *		       to NULL
   2616  * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been
   2617  *		       modified.
   2618  */
   2619 
   2620 isc_result_t
   2621 ipv6_pond_dereference(struct ipv6_pond **pond, const char *file, int line) {
   2622 	struct ipv6_pond *tmp;
   2623 
   2624 	if ((pond == NULL) || (*pond == NULL)) {
   2625 		log_error("%s(%d): NULL pointer", file, line);
   2626 		return DHCP_R_INVALIDARG;
   2627 	}
   2628 
   2629 	tmp = *pond;
   2630 	*pond = NULL;
   2631 
   2632 	tmp->refcnt--;
   2633 	if (tmp->refcnt < 0) {
   2634 		log_error("%s(%d): negative refcnt", file, line);
   2635 		tmp->refcnt = 0;
   2636 	}
   2637 	if (tmp->refcnt == 0) {
   2638 		dfree(tmp, file, line);
   2639 	}
   2640 
   2641 	return ISC_R_SUCCESS;
   2642 }
   2643 
   2644 #ifdef EUI_64
   2645 /*
   2646  * Enables/disables EUI-64 address assignment for a pond
   2647  *
   2648  * Excecutes statements down to the pond's scope and sets the pond's
   2649  * use_eui_64 flag accordingly. In addition it iterates over the
   2650  * pond's pools ensuring they are all /64.  Anything else is deemed
   2651  * invalid for EUI-64.  It returns the number of invalid pools
   2652  * detected.  This is done post-parsing as use-eui-64 can be set
   2653  * down to the pool scope and we can't reliably do it until the
   2654  * entire configuration has been parsed.
   2655  */
   2656 int
   2657 set_eui_64(struct ipv6_pond *pond) {
   2658 	int invalid_cnt = 0;
   2659 	struct option_state* options = NULL;
   2660 	struct option_cache *oc = NULL;
   2661 	option_state_allocate(&options, MDL);
   2662 	execute_statements_in_scope(NULL, NULL, NULL, NULL, NULL, options,
   2663 				    &global_scope, pond->group, NULL, NULL);
   2664 
   2665 	pond->use_eui_64 =
   2666 		((oc = lookup_option(&server_universe, options, SV_USE_EUI_64))
   2667 		 &&
   2668 		 (evaluate_boolean_option_cache (NULL, NULL, NULL, NULL,
   2669 						 options, NULL, &global_scope,
   2670 						 oc, MDL)));
   2671 	if (pond->use_eui_64) {
   2672 		// Check all pools are valid
   2673 		int i = 0;
   2674 		struct ipv6_pool* p;
   2675 		while((p = pond->ipv6_pools[i++]) != NULL) {
   2676 			if (p->bits != 64) {
   2677 				log_error("Pool %s/%d cannot use EUI-64,"
   2678 					  " prefix must 64",
   2679 					  pin6_addr(&p->start_addr), p->bits);
   2680 				invalid_cnt++;
   2681 			} else {
   2682 				log_debug("Pool: %s/%d - will use EUI-64",
   2683 					  pin6_addr(&p->start_addr), p->bits);
   2684 			}
   2685 		}
   2686 	}
   2687 
   2688         /* Don't need the options anymore. */
   2689         option_state_dereference(&options, MDL);
   2690 	return (invalid_cnt);
   2691 }
   2692 #endif
   2693 
   2694 /*
   2695  * Emits a log for each pond that has been flagged as being a "jumbo range"
   2696  * A pond is considered a "jumbo range" when the total number of elements
   2697  * exceeds the maximum value of POND_TRACK_MAX (currently maximum value
   2698  * that can be stored by ipv6_pond.num_total).  Since we disable threshold
   2699  * logging for jumbo ranges, we need to report this to the user.  This
   2700  * function allows us to report jumbo ponds after config parsing, so the
   2701  * logs can be seen both on the console (-T) and the log facility (i.e syslog).
   2702  *
   2703  * Note, threshold logging is done at the pond level, so we need emit a list
   2704  * of the addresses ranges of the pools in the pond affected.
   2705  */
   2706 void
   2707 report_jumbo_ranges() {
   2708 	struct shared_network* s;
   2709 	char log_buf[1084];
   2710 #ifdef EUI_64
   2711 	int invalid_cnt = 0;
   2712 #endif
   2713 
   2714 	/* Loop thru all the networks looking for jumbo range ponds */
   2715 	for (s = shared_networks; s; s = s -> next) {
   2716 		struct ipv6_pond* pond = s->ipv6_pond;
   2717 		while (pond) {
   2718 #ifdef EUI_64
   2719 			/* while we're here, set the pond's use_eui_64 flag */
   2720 			invalid_cnt += set_eui_64(pond);
   2721 #endif
   2722 			/* if its a jumbo and has pools(sanity check) */
   2723 			if (pond->jumbo_range == 1 && (pond->ipv6_pools)) {
   2724 				struct ipv6_pool* pool;
   2725 				char *bufptr = log_buf;
   2726 				size_t space_left = sizeof(log_buf) - 1;
   2727 				int i = 0;
   2728 				int used = 0;
   2729 
   2730 				/* Build list containing the start-address/CIDR
   2731 				 * of each pool */
   2732 				*bufptr = '\0';
   2733 				while ((pool = pond->ipv6_pools[i++]) &&
   2734 				        (space_left > (INET6_ADDRSTRLEN + 6))) {
   2735 					/* more than one so add a comma */
   2736 					if (i > 1) {
   2737 						*bufptr++ = ',';
   2738 						*bufptr++ = ' ';
   2739 						*bufptr = '\0';
   2740 						space_left -= 2;
   2741 					}
   2742 
   2743 					/* add the address */
   2744 					inet_ntop(AF_INET6, &pool->start_addr,
   2745 						  bufptr, INET6_ADDRSTRLEN);
   2746 
   2747 					used = strlen(bufptr);
   2748 					bufptr += used;
   2749 					space_left -= used;
   2750 
   2751 					/* add the CIDR */
   2752 					sprintf (bufptr, "/%d",pool->bits);
   2753 					used = strlen(bufptr);
   2754 					bufptr += used;
   2755 					space_left -= used;
   2756 					*bufptr = '\0';
   2757 				}
   2758 
   2759 				log_info("Threshold logging disabled for shared"
   2760 					 " subnet of ranges: %s", log_buf);
   2761 			}
   2762 			pond = pond->next;
   2763 		}
   2764 
   2765 	}
   2766 
   2767 #ifdef EUI_64
   2768 	if (invalid_cnt) {
   2769 		log_fatal ("%d pool(s) are invalid for EUI-64 use",
   2770 			   invalid_cnt);
   2771 	}
   2772 #endif
   2773 }
   2774 
   2775 
   2776 /*
   2777  * \brief Tests that 16-bit hardware type is less than 256
   2778  *
   2779  * XXX: DHCPv6 gives a 16-bit field for the htype.  DHCPv4 gives an
   2780  * 8-bit field.  To change the semantics of the generic 'hardware'
   2781  * structure, we would have to adjust many DHCPv4 sources (from
   2782  * interface to DHCPv4 lease code), and we would have to update the
   2783  * 'hardware' config directive (probably being reverse compatible and
   2784  * providing a new upgrade/replacement primitive).  This is a little
   2785  * too much to change for now.  Hopefully we will revisit this before
   2786  * hardware types exceeding 8 bits are assigned.
   2787  *
   2788  * Uses a static variable to limit log occurence to once per startup
   2789  *
   2790  * \param htype hardware type value to test
   2791  *
   2792  * \return returns 0 if the value is too large
   2793  *
   2794 */
   2795 static int
   2796 htype_bounds_check(uint16_t htype) {
   2797 	static int log_once = 0;
   2798 
   2799 	if (htype & 0xFF00) {
   2800 		if (!log_once) {
   2801 			log_error("Attention: At least one client advertises a "
   2802 			  "hardware type of %d, which exceeds the software "
   2803 			  "limitation of 255.", htype);
   2804 			log_once = 1;
   2805 		}
   2806 
   2807 		return(0);
   2808 	}
   2809 
   2810 	return(1);
   2811 }
   2812 
   2813 /*!
   2814  * \brief Look for hosts by MAC address if it's available
   2815  *
   2816  * Checks the inbound packet against host declarations which specified:
   2817  *
   2818  *      "hardware ethernet <MAC>;"
   2819  *
   2820  * For directly connected clients, the function will use the MAC address
   2821  * contained in packet:haddr if it's populated.  \TODO - While the logic is in
   2822  * place for this search, the socket layer does not yet populate packet:haddr,
   2823  * this is to be done under rt41523.
   2824  *
   2825  * For relayed clients, the function will use the MAC address from the
   2826  * client-linklayer-address option if it has been supplied by the relay
   2827  * directly connected to the client.
   2828  *
   2829  * \param hp[out] - pointer to storage for the host delcaration if found
   2830  * \param packet - received packet
   2831  * \param opt_state - option state to search
   2832  * \param file - source file
   2833  * \param line - line number
   2834  *
   2835  * \return non-zero if a matching host was found, zero otherwise
   2836 */
   2837 static int
   2838 find_hosts_by_haddr6(struct host_decl **hp,
   2839 			 struct packet *packet,
   2840 			 struct option_state *opt_state,
   2841 			 const char *file, int line) {
   2842 	int found = 0;
   2843 	int htype;
   2844 	int hlen;
   2845 
   2846 	/* For directly connected clients, use packet:haddr if populated */
   2847 	if (packet->dhcpv6_container_packet == NULL) {
   2848 		if (packet->haddr) {
   2849 			htype = packet->haddr->hbuf[0];
   2850 			hlen = packet->haddr->hlen - 1,
   2851 			log_debug("find_hosts_by_haddr6: using packet->haddr,"
   2852 				  " type: %d, len: %d", htype, hlen);
   2853 			found = find_hosts_by_haddr (hp, htype,
   2854 						     &packet->haddr->hbuf[1],
   2855 						     hlen, MDL);
   2856 		}
   2857 	} else {
   2858 		/* The first container packet is the from the relay directly
   2859 		 * connected to the client. Per RFC 6939, that is only relay
   2860 		 * that may supply the client linklayer address option. */
   2861 		struct packet *relay_packet = packet->dhcpv6_container_packet;
   2862 		struct option_state *relay_state = relay_packet->options;
   2863 		struct data_string rel_addr;
   2864 		struct option_cache *oc;
   2865 
   2866 		/* Look for the option in the first relay packet */
   2867 		oc = lookup_option(&dhcpv6_universe, relay_state,
   2868 				   D6O_CLIENT_LINKLAYER_ADDR);
   2869 		if (!oc) {
   2870 			/* Not there, so bail */
   2871 			return (0);
   2872 		}
   2873 
   2874 		/* The option is present, fetch the address data */
   2875 		memset(&rel_addr, 0, sizeof(rel_addr));
   2876 		if (!evaluate_option_cache(&rel_addr, relay_packet, NULL, NULL,
   2877 					   relay_state, NULL, &global_scope,
   2878 					   oc, MDL)) {
   2879 			log_error("find_hosts_by_add6:"
   2880 				  "Error evaluating option cache");
   2881 			return (0);
   2882 		}
   2883 
   2884 		/* The relay address data should be:
   2885 		 *   byte 0 - 1 = hardware type
   2886 		 *   bytes 2 - hlen = hardware address
   2887                  * where  hlen ( hardware address len) is option data len - 2 */
   2888 		hlen = rel_addr.len - 2;
   2889 		if (hlen > 0 && hlen <= HARDWARE_ADDR_LEN) {
   2890 			htype = getUShort(rel_addr.data);
   2891 			if (htype_bounds_check(htype)) {
   2892 				/* Looks valid, let's search with it */
   2893 				log_debug("find_hosts_by_haddr6:"
   2894 					  "using relayed haddr"
   2895 					  " type: %d, len: %d", htype, hlen);
   2896 				found = find_hosts_by_haddr (hp, htype,
   2897 							     &rel_addr.data[2],
   2898 							     hlen, MDL);
   2899 			}
   2900 		}
   2901 
   2902 		data_string_forget(&rel_addr, MDL);
   2903         }
   2904 
   2905 	return (found);
   2906 }
   2907 
   2908 /*
   2909  * find_host_by_duid_chaddr() synthesizes a DHCPv4-like 'hardware'
   2910  * parameter from a DHCPv6 supplied DUID (client-identifier option),
   2911  * and may seek to use client or relay supplied hardware addresses.
   2912  */
   2913 static int
   2914 find_hosts_by_duid_chaddr(struct host_decl **host,
   2915 			  const struct data_string *client_id) {
   2916 	int htype, hlen;
   2917 	const unsigned char *chaddr;
   2918 
   2919 	/*
   2920 	 * The DUID-LL and DUID-LLT must have a 2-byte DUID type and 2-byte
   2921 	 * htype.
   2922 	 */
   2923 	if (client_id->len < 4)
   2924 		return 0;
   2925 
   2926 	/*
   2927 	 * The third and fourth octets of the DUID-LL and DUID-LLT
   2928 	 * is the hardware type, but in 16 bits.
   2929 	 */
   2930 	htype = getUShort(client_id->data + 2);
   2931 	hlen = 0;
   2932 	chaddr = NULL;
   2933 
   2934 	/* The first two octets of the DUID identify the type. */
   2935 	switch(getUShort(client_id->data)) {
   2936 	      case DUID_LLT:
   2937 		if (client_id->len > 8) {
   2938 			hlen = client_id->len - 8;
   2939 			chaddr = client_id->data + 8;
   2940 		}
   2941 		break;
   2942 
   2943 	      case DUID_LL:
   2944 		/*
   2945 		 * Note that client_id->len must be greater than or equal
   2946 		 * to four to get to this point in the function.
   2947 		 */
   2948 		hlen = client_id->len - 4;
   2949 		chaddr = client_id->data + 4;
   2950 		break;
   2951 
   2952 	      default:
   2953 		break;
   2954 	}
   2955 
   2956 	if ((hlen == 0) || (hlen > HARDWARE_ADDR_LEN) ||
   2957 	    !htype_bounds_check(htype)) {
   2958 		return (0);
   2959 	}
   2960 
   2961 	return find_hosts_by_haddr(host, htype, chaddr, hlen, MDL);
   2962 }
   2963 
   2964 /*
   2965  * \brief Finds a host record that matches the packet, if any
   2966  *
   2967  * This function centralizes the logic for matching v6 client
   2968  * packets to host declarations.  We check in the following order
   2969  * for matches with:
   2970  *
   2971  * 1. client_id if specified
   2972  * 2. MAC address when explicitly available
   2973  * 3. packet option
   2974  * 4. synthesized hardware address - this is done last as some
   2975  * synthesis methods are not consided to be reliable
   2976  *
   2977  * \param[out] host - pointer to storage for the located host
   2978  * \param packet - inbound client packet
   2979  * \param client_id - client identifier (if one)
   2980  * \param file - source file
   2981  * \param line - source file line number
   2982  * \return non-zero if a host is found, zero otherwise
   2983 */
   2984 int
   2985 find_hosts6(struct host_decl** host, struct packet* packet,
   2986             const struct data_string* client_id, char* file, int line) {
   2987         return (find_hosts_by_uid(host, client_id->data, client_id->len, MDL)
   2988                 || find_hosts_by_haddr6(host, packet, packet->options, MDL)
   2989                 || find_hosts_by_option(host, packet, packet->options, MDL)
   2990                 || find_hosts_by_duid_chaddr(host, client_id));
   2991 }
   2992 
   2993 /* unittest moved to server/tests/mdb6_unittest.c */
   2994