--- embedaddon/dhcp/server/mdb6.c 2012/02/21 22:30:18 1.1 +++ embedaddon/dhcp/server/mdb6.c 2012/10/09 09:06:55 1.1.1.1 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2010-2012 by Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2007-2008 by Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and distribute this software for any @@ -15,9 +15,71 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* TODO: assert() */ -/* TODO: simplify functions, as pool is now in iaaddr */ +/*! + * \todo assert() + * \todo simplify functions, as pool is now in iaaddr + */ +/*! \file server/mdb6.c + * + * \page ipv6structures IPv6 Structures Overview + * + * A brief description of the IPv6 structures as reverse engineered. + * + * There are three major data strucutes involved in the database: + * + * - ipv6_pool - this contains information about a pool of addresses or prefixes + * that the server is using. This includes a hash table that + * tracks the active items and a pair of heap tables one for + * active items and one for non-active items. The heap tables + * are used to determine the next items to be modified due to + * timing events (expire mostly). + * - ia_xx - this contains information about a single IA from a request + * normally it will contain one pointer to a lease for the client + * but it may contain more in some circumstances. There are 3 + * hash tables to aid in accessing these one each for NA, TA and PD. + * - iasubopt- the v6 lease structure. These are created dynamically when + * a client asks for something and will eventually be destroyed + * if the client doesn't re-ask for that item. A lease has space + * for backpointers to the IA and to the pool to which it belongs. + * The pool backpointer is always filled, the IA pointer may not be. + * + * In normal use we then have something like this: + * + * \verbatim + * ia hash tables + * ia_na_active +----------------+ + * ia_ta_active +------------+ | pool | + * ia_pd_active | iasubopt |<--| active hash | + * +-----------------+ | aka lease |<--| active heap | + * | ia_xx | | pool ptr |-->| | + * | iasubopt array |<---| iaptr |<--| inactive heap | + * | lease ptr |--->| | | | + * +-----------------+ +------------+ +----------------+ + * \endverbatim + * + * For the pool either the inactive heap will have a pointer + * or both the active heap and the active hash will have pointers. + * + * I think there are several major items to notice. The first is + * that as a lease moves around it will be added to and removed + * from the address hash table in the pool and between the active + * and inactive hash tables. The hash table and the active heap + * are used when the lease is either active or abandoned. The + * inactive heap is used for all other states. In particular a + * lease that has expired or been released will be cleaned + * (DDNS removal etc) and then moved to the inactive heap. After + * some time period (currently 1 hour) it will be freed. + * + * The second is that when a client requests specific addresses, + * either because it previously owned them or if the server supplied + * them as part of a solicit, the server will try to lookup the ia_xx + * associated with the client and find the addresses there. If it + * does find appropriate leases it moves them from the old IA to + * a new IA and eventually replaces the old IA with the new IA + * in the IA hash tables. + * + */ #include "config.h" #include @@ -316,6 +378,8 @@ void ia_remove_iasubopt(struct ia_xx *ia, struct iasubopt *iasubopt, const char *file, int line) { int i, j; + if (ia == NULL || iasubopt == NULL) + return; for (i=0; inum_iasubopt; i++) { if (ia->iasubopt[i] == iasubopt) { @@ -807,15 +871,14 @@ create_lease6(struct ipv6_pool *pool, struct iasubopt } /* - * Avoid reserved interface IDs. - * (cf. draft-krishnan-ipv6-reserved-iids-02.txt) + * Avoid reserved interface IDs. (cf. RFC 5453) */ reserved_iid = ISC_FALSE; - if (memcmp(&tmp.s6_addr[8], &rtany, 8) == 0) { + if (memcmp(&tmp.s6_addr[8], &rtany.s6_addr[8], 8) == 0) { reserved_iid = ISC_TRUE; } if (!reserved_iid && - (memcmp(&tmp.s6_addr[8], &resany, 7) == 0) && + (memcmp(&tmp.s6_addr[8], &resany.s6_addr[8], 7) == 0) && ((tmp.s6_addr[15] & 0x80) == 0x80)) { reserved_iid = ISC_TRUE; } @@ -874,6 +937,145 @@ create_lease6(struct ipv6_pool *pool, struct iasubopt return result; } + +/*! + * + * \brief Cleans up leases when reading from a lease file + * + * This function is only expected to be run when reading leases in from a file. + * It checks to see if a lease already exists for the new leases's address. + * We don't add expired leases to the structures when reading a lease file + * which limits what can happen. We have two variables the owners of the leases + * being the same or different and the new lease being active or non-active: + * Owners active + * same no remove old lease and its connections + * same yes nothing to do, other code will update the structures. + * diff no nothing to do + * diff yes this combination shouldn't happen, we should only have a + * single active lease per address at a time and that lease + * should move to non-active before any other lease can + * become active for that address. + * Currently we delete the previous lease and pass an error + * to the caller who should log an error. + * + * When we remove a lease we remove it from the hash table and active heap + * (remember only active leases are in the structures at this time) for the + * pool, and from the IA's array. If, after we've removed the pointer from + * IA's array to the lease, the IA has no more pointers we remove it from + * the appropriate hash table as well. + * + * \param[in] ia_table = the hash table for the IA + * \param[in] pool = the pool to update + * \param[in] lease = the new lease we want to add + * \param[in] ia = the new ia we are building + * + * \return + * ISC_R_SUCCESS = the incoming lease and any previous lease were in + * an expected state - one of the first 3 options above. + * If necessary the old lease was removed. + * ISC_R_FAILURE = there is already an active lease for the address in + * the incoming lease. This shouldn't happen if it does + * flag an error for the caller to log. + */ + +isc_result_t +cleanup_lease6(ia_hash_t *ia_table, + struct ipv6_pool *pool, + struct iasubopt *lease, + struct ia_xx *ia) { + + struct iasubopt *test_iasubopt, *tmp_iasubopt; + struct ia_xx *old_ia; + isc_result_t status = ISC_R_SUCCESS; + + test_iasubopt = NULL; + old_ia = NULL; + + /* + * Look up the address - if we don't find a lease + * we don't need to do anything. + */ + if (iasubopt_hash_lookup(&test_iasubopt, pool->leases, + &lease->addr, sizeof(lease->addr), + MDL) == 0) { + return (ISC_R_SUCCESS); + } + + if (test_iasubopt->ia == NULL) { + /* no old ia, no work to do */ + iasubopt_dereference(&test_iasubopt, MDL); + return (status); + } + + ia_reference(&old_ia, test_iasubopt->ia, MDL); + + if ((old_ia->iaid_duid.len == ia->iaid_duid.len) && + (memcmp((unsigned char *)ia->iaid_duid.data, + (unsigned char *)old_ia->iaid_duid.data, + ia->iaid_duid.len) == 0)) { + /* same IA */ + if ((lease->state == FTS_ACTIVE) || + (lease->state == FTS_ABANDONED)) { + /* still active, no need to delete */ + goto cleanup; + } + } else { + /* different IA */ + if ((lease->state != FTS_ACTIVE) && + (lease->state != FTS_ABANDONED)) { + /* new lease isn't active, no work */ + goto cleanup; + } + + /* + * We appear to have two active leases, this shouldn't happen. + * Before a second lease can be set to active the first lease + * should be set to inactive (released, expired etc). For now + * delete the previous lease and indicate a failure to the + * caller so it can generate a warning. + * In the future we may try and determine which is the better + * lease to keep. + */ + + status = ISC_R_FAILURE; + } + + /* + * Remove the old lease from the active heap and from the hash table + * then remove the lease from the IA and clean up the IA if necessary. + */ + isc_heap_delete(pool->active_timeouts, test_iasubopt->heap_index); + pool->num_active--; + + iasubopt_hash_delete(pool->leases, &test_iasubopt->addr, + sizeof(test_iasubopt->addr), MDL); + ia_remove_iasubopt(old_ia, test_iasubopt, MDL); + if (old_ia->num_iasubopt <= 0) { + ia_hash_delete(ia_table, + (unsigned char *)old_ia->iaid_duid.data, + old_ia->iaid_duid.len, MDL); + } + + /* + * We derefenrece the subopt here as we've just removed it from + * the hash table in the pool. We need to make a copy as we + * need to derefernece it again later. + */ + tmp_iasubopt = test_iasubopt; + iasubopt_dereference(&tmp_iasubopt, MDL); + + cleanup: + ia_dereference(&old_ia, MDL); + + /* + * Clean up the reference, this is in addition to the deference + * above after removing the entry from the hash table + */ + iasubopt_dereference(&test_iasubopt, MDL); + + return (status); +} + /* * Put a lease in the pool directly. This is intended to be used when * loading leases from the file. @@ -984,6 +1186,38 @@ lease6_exists(const struct ipv6_pool *pool, const stru } } +/*! + * + * \brief Check if address is available to a lease + * + * Determine if the address in the lease is available to that + * lease. Either the address isn't in use or it is in use + * but by that lease. + * + * \param[in] lease = lease to check + * + * \return + * ISC_TRUE = The lease is allowed to use that address + * ISC_FALSE = The lease isn't allowed to use that address + */ +isc_boolean_t +lease6_usable(struct iasubopt *lease) { + struct iasubopt *test_iaaddr; + isc_boolean_t status = ISC_TRUE; + + test_iaaddr = NULL; + if (iasubopt_hash_lookup(&test_iaaddr, lease->ipv6_pool->leases, + (void *)&lease->addr, + sizeof(lease->addr), MDL)) { + if (test_iaaddr != lease) { + status = ISC_FALSE; + } + iasubopt_dereference(&test_iaaddr, MDL); + } + + return (status); +} + /* * Put the lease on our active pool. */ @@ -1005,29 +1239,49 @@ move_lease_to_active(struct ipv6_pool *pool, struct ia return insert_result; } -/* - * Renew an lease in the pool. +/*! + * \brief Renew a lease in the pool. * - * To do this, first set the new hard_lifetime_end_time for the resource, - * and then invoke renew_lease6() on it. + * The hard_lifetime_end_time of the lease should be set to + * the current expiration time. + * The soft_lifetime_end_time of the lease should be set to + * the desired expiration time. * - * WARNING: lease times must only be extended, never reduced!!! + * This routine will compare the two and call the correct + * heap routine to move the lease. If the lease is active + * and the new expiration time is greater (the normal case) + * then we call isc_heap_decreased() as a larger time is a + * lower priority. If the new expiration time is less then + * we call isc_heap_increased(). + * + * If the lease is abandoned then it will be on the active list + * and we will always call isc_heap_increased() as the previous + * expiration would have been all 1s (as close as we can get + * to infinite). + * + * If the lease is moving to active we call that routine + * which will move it from the inactive list to the active list. + * + * \param pool a pool the lease belongs to + * \param lease the lease to be renewed + * + * \return result of the renew operation (ISC_R_SUCCESS if successful, + ISC_R_NOMEMORY when run out of memory) */ isc_result_t renew_lease6(struct ipv6_pool *pool, struct iasubopt *lease) { - /* - * If we're already active, then we can just move our expiration - * time down the heap. - * - * If we're abandoned then we are already on the active list - * but we need to retag the lease and move our expiration - * from infinite to the current value - * - * Otherwise, we have to move from the inactive heap to the - * active heap. - */ + time_t old_end_time = lease->hard_lifetime_end_time; + lease->hard_lifetime_end_time = lease->soft_lifetime_end_time; + lease->soft_lifetime_end_time = 0; + if (lease->state == FTS_ACTIVE) { - isc_heap_decreased(pool->active_timeouts, lease->heap_index); + if (old_end_time <= lease->hard_lifetime_end_time) { + isc_heap_decreased(pool->active_timeouts, + lease->heap_index); + } else { + isc_heap_increased(pool->active_timeouts, + lease->heap_index); + } return ISC_R_SUCCESS; } else if (lease->state == FTS_ABANDONED) { char tmp_addr[INET6_ADDRSTRLEN]; @@ -1153,7 +1407,7 @@ release_lease6(struct ipv6_pool *pool, struct iasubopt * Create a prefix by hashing the input, and using that for * the part subject to allocation. */ -static void +void build_prefix6(struct in6_addr *pref, const struct in6_addr *net_start_pref, int pool_bits, int pref_bits, @@ -1488,6 +1742,13 @@ lease_timeout_support(void *vpool) { } /* + * If appropriate commit and rotate the lease file + * As commit_leases_timed() checks to see if we've done any writes + * we don't bother tracking if this function called write _ia + */ + (void) commit_leases_timed(); + + /* * Do some cleanup of our expired leases. */ cleanup_old_expired(pool); @@ -1686,9 +1947,8 @@ change_leases(struct ia_xx *ia, /* * Renew all leases in an IA from all pools. * - * The new hard_lifetime_end_time should be updated for the addresses/prefixes. - * - * WARNING: lease times must only be extended, never reduced!!! + * The new lifetime should be in the soft_lifetime_end_time + * and will be moved to hard_lifetime_end_time by renew_lease6. */ isc_result_t renew_leases(struct ia_xx *ia) { @@ -1886,662 +2146,4 @@ mark_interfaces_unavailable(void) { } } - -#ifdef UNIT_TEST -#include - -int -main(int argc, char *argv[]) { - struct iasubopt *iaaddr; - struct iasubopt *iaaddr_copy; - u_int32_t iaid; - struct ia_xx *ia_na; - struct ia_xx *ia_na_copy; - int i; - struct in6_addr addr; - struct ipv6_pool *pool; - struct ipv6_pool *pool_copy; - char addr_buf[INET6_ADDRSTRLEN]; - char *uid; - struct data_string ds; - struct iasubopt *expired_iaaddr; - unsigned int attempts; - - /* - * Test 0: Basic iaaddr manipulation. - */ - iaaddr = NULL; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - if (iaaddr->state != FTS_FREE) { - printf("ERROR: bad state %s:%d\n", MDL); - return 1; - } - if (iaaddr->heap_index != -1) { - printf("ERROR: bad heap_index %s:%d\n", MDL); - return 1; - } - iaaddr_copy = NULL; - if (iasubopt_reference(&iaaddr_copy, iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr_copy, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 1: Error iaaddr manipulation. - */ - /* bogus allocate arguments */ - if (iasubopt_allocate(NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - iaaddr = (struct iasubopt *)1; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - - /* bogus reference arguments */ - iaaddr = NULL; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - if (iasubopt_reference(NULL, iaaddr, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - iaaddr_copy = (struct iasubopt *)1; - if (iasubopt_reference(&iaaddr_copy, iaaddr, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - iaaddr_copy = NULL; - if (iasubopt_reference(&iaaddr_copy, NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - - /* bogus dereference arguments */ - if (iasubopt_dereference(NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - iaaddr = NULL; - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 2: Basic ia_na manipulation. - */ - iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - if (memcmp(ia_na->iaid_duid.data, &iaid, sizeof(iaid)) != 0) { - printf("ERROR: bad IAID_DUID %s:%d\n", MDL); - return 1; - } - if (memcmp(ia_na->iaid_duid.data+sizeof(iaid), "TestDUID", 8) != 0) { - printf("ERROR: bad IAID_DUID %s:%d\n", MDL); - return 1; - } - if (ia_na->num_iasubopt != 0) { - printf("ERROR: bad num_iasubopt %s:%d\n", MDL); - return 1; - } - ia_na_copy = NULL; - if (ia_reference(&ia_na_copy, ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_reference() %s:%d\n", MDL); - return 1; - } - iaaddr = NULL; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_add_iasubopt() %s:%d\n", MDL); - return 1; - } - ia_remove_iasubopt(ia_na, iaaddr, MDL); - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - if (ia_dereference(&ia_na_copy, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 3: lots of iaaddr in our ia_na - */ - - /* lots of iaaddr that we delete */ - iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - for (i=0; i<100; i++) { - iaaddr = NULL; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_add_iasubopt() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - } - for (i=0; i<100; i++) { - iaaddr = ia_na->iasubopt[random() % ia_na->num_iasubopt]; - ia_remove_iasubopt(ia_na, iaaddr, MDL); - } - if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* lots of iaaddr, let dereference cleanup */ - iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - for (i=0; i<100; i++) { - iaaddr = NULL; - if (iasubopt_allocate(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_allocate() %s:%d\n", MDL); - return 1; - } - if (ia_add_iasubopt(ia_na, iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_add_iasubopt() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_reference() %s:%d\n", MDL); - return 1; - } - } - if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 4: Errors in ia_na. - */ - /* bogus allocate arguments */ - if (ia_allocate(NULL, 123, "", 0, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - ia_na = (struct ia_na *)1; - if (ia_allocate(&ia_na, 456, "", 0, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - - /* bogus reference arguments */ - iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - if (ia_reference(NULL, ia_na, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_reference() %s:%d\n", MDL); - return 1; - } - ia_na_copy = (struct ia_na *)1; - if (ia_reference(&ia_na_copy, ia_na, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_reference() %s:%d\n", MDL); - return 1; - } - ia_na_copy = NULL; - if (ia_reference(&ia_na_copy, NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_reference() %s:%d\n", MDL); - return 1; - } - if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* bogus dereference arguments */ - if (ia_dereference(NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* bogus remove */ - iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - } - ia_remove_iasubopt(ia_na, NULL, MDL); - if (ia_dereference(&ia_na, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 5: Basic ipv6_pool manipulation. - */ - - /* allocate, reference */ - inet_pton(AF_INET6, "1:2:3:4::", &addr); - pool = NULL; - if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 0) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (pool->bits != 64) { - printf("ERROR: bad bits %s:%d\n", MDL); - return 1; - } - inet_ntop(AF_INET6, &pool->start_addr, addr_buf, sizeof(addr_buf)); - if (strcmp(inet_ntop(AF_INET6, &pool->start_addr, addr_buf, - sizeof(addr_buf)), "1:2:3:4::") != 0) { - printf("ERROR: bad start_addr %s:%d\n", MDL); - return 1; - } - pool_copy = NULL; - if (ipv6_pool_reference(&pool_copy, pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - - /* create_lease6, renew_lease6, expire_lease6 */ - uid = "client0"; - memset(&ds, 0, sizeof(ds)); - ds.len = strlen(uid); - if (!buffer_allocate(&ds.buffer, ds.len, MDL)) { - printf("Out of memory\n"); - return 1; - } - ds.data = ds.buffer->data; - memcpy((char *)ds.data, uid, ds.len); - if (create_lease6(pool, &iaaddr, - &attempts, &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_inactive != 1) { - printf("ERROR: bad num_inactive %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 1) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - expired_iaaddr = NULL; - if (expire_lease6(&expired_iaaddr, pool, 0) != ISC_R_SUCCESS) { - printf("ERROR: expire_lease6() %s:%d\n", MDL); - return 1; - } - if (expired_iaaddr != NULL) { - printf("ERROR: should not have expired a lease %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 1) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) { - printf("ERROR: expire_lease6() %s:%d\n", MDL); - return 1; - } - if (expired_iaaddr == NULL) { - printf("ERROR: should have expired a lease %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&expired_iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 0) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - - /* release_lease6, decline_lease6 */ - if (create_lease6(pool, &iaaddr, &attempts, - &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 1) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (release_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: decline_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 0) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - if (create_lease6(pool, &iaaddr, &attempts, - &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 1) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (decline_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: decline_lease6() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != 1) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - - /* dereference */ - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool_copy, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 6: Error ipv6_pool manipulation - */ - if (ipv6_pool_allocate(NULL, 0, &addr, 64, 128, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - pool = (struct ipv6_pool *)1; - if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_reference(NULL, pool, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - pool_copy = (struct ipv6_pool *)1; - if (ipv6_pool_reference(&pool_copy, pool, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - pool_copy = NULL; - if (ipv6_pool_reference(&pool_copy, NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_reference() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(NULL, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool_copy, MDL) != ISC_R_INVALIDARG) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 7: order of expiration - */ - pool = NULL; - if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - for (i=10; i<100; i+=10) { - if (create_lease6(pool, &iaaddr, &attempts, - &ds, i) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - if (pool->num_active != (i / 10)) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - } - if (pool->num_active != 9) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - for (i=10; i<100; i+=10) { - if (expire_lease6(&expired_iaaddr, - pool, 1000) != ISC_R_SUCCESS) { - printf("ERROR: expire_lease6() %s:%d\n", MDL); - return 1; - } - if (expired_iaaddr == NULL) { - printf("ERROR: should have expired a lease %s:%d\n", - MDL); - return 1; - } - if (pool->num_active != (9 - (i / 10))) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - if (expired_iaaddr->hard_lifetime_end_time != i) { - printf("ERROR: bad hard_lifetime_end_time %s:%d\n", - MDL); - return 1; - } - if (iasubopt_dereference(&expired_iaaddr, MDL) != - ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - } - if (pool->num_active != 0) { - printf("ERROR: bad num_active %s:%d\n", MDL); - return 1; - } - expired_iaaddr = NULL; - if (expire_lease6(&expired_iaaddr, pool, 1000) != ISC_R_SUCCESS) { - printf("ERROR: expire_lease6() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - - /* - * Test 8: small pool - */ - pool = NULL; - addr.s6_addr[14] = 0x81; - if (ipv6_pool_allocate(&pool, 0, &addr, 127, 128, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - if (create_lease6(pool, &iaaddr, &attempts, - &ds, 42) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - if (create_lease6(pool, &iaaddr, &attempts, - &ds, 11) != ISC_R_SUCCESS) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (renew_lease6(pool, iaaddr) != ISC_R_SUCCESS) { - printf("ERROR: renew_lease6() %s:%d\n", MDL); - return 1; - } - if (iasubopt_dereference(&iaaddr, MDL) != ISC_R_SUCCESS) { - printf("ERROR: iasubopt_dereference() %s:%d\n", MDL); - return 1; - } - if (create_lease6(pool, &iaaddr, &attempts, - &ds, 11) != ISC_R_NORESOURCES) { - printf("ERROR: create_lease6() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - addr.s6_addr[14] = 0; - - /* - * Test 9: functions across all pools - */ - pool = NULL; - if (ipv6_pool_allocate(&pool, 0, &addr, 64, 128, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); - return 1; - } - if (add_ipv6_pool(pool) != ISC_R_SUCCESS) { - printf("ERROR: add_ipv6_pool() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - pool = NULL; - if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_SUCCESS) { - printf("ERROR: find_ipv6_pool() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - inet_pton(AF_INET6, "1:2:3:4:ffff:ffff:ffff:ffff", &addr); - pool = NULL; - if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_SUCCESS) { - printf("ERROR: find_ipv6_pool() %s:%d\n", MDL); - return 1; - } - if (ipv6_pool_dereference(&pool, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ipv6_pool_dereference() %s:%d\n", MDL); - return 1; - } - inet_pton(AF_INET6, "1:2:3:5::", &addr); - pool = NULL; - if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_NOTFOUND) { - printf("ERROR: find_ipv6_pool() %s:%d\n", MDL); - return 1; - } - inet_pton(AF_INET6, "1:2:3:3:ffff:ffff:ffff:ffff", &addr); - pool = NULL; - if (find_ipv6_pool(&pool, 0, &addr) != ISC_R_NOTFOUND) { - printf("ERROR: find_ipv6_pool() %s:%d\n", MDL); - return 1; - } - -/* iaid = 666; - ia_na = NULL; - if (ia_allocate(&ia_na, iaid, "TestDUID", 8, MDL) != ISC_R_SUCCESS) { - printf("ERROR: ia_allocate() %s:%d\n", MDL); - return 1; - }*/ - - { - struct in6_addr r; - struct data_string ds; - u_char data[16]; - char buf[64]; - int i, j; - - memset(&ds, 0, sizeof(ds)); - memset(data, 0xaa, sizeof(data)); - ds.len = 16; - ds.data = data; - - inet_pton(AF_INET6, "3ffe:501:ffff:100::", &addr); - for (i = 32; i < 42; i++) - for (j = i + 1; j < 49; j++) { - memset(&r, 0, sizeof(r)); - memset(buf, 0, 64); - build_prefix6(&r, &addr, i, j, &ds); - inet_ntop(AF_INET6, &r, buf, 64); - printf("%d,%d-> %s/%d\n", i, j, buf, j); - } - } - - printf("SUCCESS: all tests passed (ignore any warning messages)\n"); - return 0; -} -#endif +/* unittest moved to server/tests/mdb6_unittest.c */