diff options
author | Shawn Routhier <sar@isc.org> | 2013-08-27 14:20:09 -0700 |
---|---|---|
committer | Shawn Routhier <sar@isc.org> | 2013-08-27 14:20:09 -0700 |
commit | 01fa619fab2bb6310001e4557fc6c08c595b7691 (patch) | |
tree | 004d5fa1bfdc4ddb754b14719570625f98424c61 /server/mdb6.c | |
parent | a7341359cc45bf965e3b11e0b22a4a06f335d6a7 (diff) | |
download | isc-dhcp-01fa619fab2bb6310001e4557fc6c08c595b7691.tar.gz |
-n [master]
26510
Add support for classes in the IPv6 code
Diffstat (limited to 'server/mdb6.c')
-rw-r--r-- | server/mdb6.c | 308 |
1 files changed, 280 insertions, 28 deletions
diff --git a/server/mdb6.c b/server/mdb6.c index b98db428..419e58e3 100644 --- a/server/mdb6.c +++ b/server/mdb6.c @@ -25,23 +25,109 @@ * * A brief description of the IPv6 structures as reverse engineered. * - * There are three major data strucutes involved in the database: + * There are four major data structures in the lease configuraion. + * + * - shared_network - The shared network is the outer enclosing scope for a + * network region that shares a broadcast domain. It is + * composed of one or more subnets all of which are valid + * in the given region. The share network may be + * explicitly defined or implicitly created if there is + * only a subnet statement. This structrure is shared + * with v4. Each shared network statment or naked subnet + * will map to one of these structures + * + * - subnet - The subnet structure mostly specifies the address range + * that could be valid in a given region. This structute + * doesn't include the addresses that the server can delegate + * those are in the ipv6_pool. This structure is also shared + * with v4. Each subnet statement will map to one of these + * structures. + * + * - ipv6_pond - The pond structure is a grouping of the address and prefix + * information via the pointers to the ipv6_pool and the + * allowability of this pool for given clinets via the permit + * lists and the valid TIMEs. This is equivilent to the v4 + * pool structure and would have been named ip6_pool except + * that the name was already in use. Generally each pool6 + * statement will map to one of these structures. In addition + * there may be one or for each group of naked range6 and + * prefix6 statements within a shared network that share + * the same group of statements. * * - 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). + * 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). + * + * The linkages then look like this: + * \verbatim + *+--------------+ +-------------+ + *|Shared Network| | ipv6_pond | + *| group | | group | + *| | | permit info | + *| | | next ----> + *| ponds ---->| | + *| |<---- shared | + *| Subnets | | pools | + *+-----|--------+ +------|------+ + * | ^ | ^ + * | | v | + * | | +-----------|-+ + * | | | ipv6_pool | | + * | | | type | | + * | | | ipv6_pond | + * | | | | + * | | | next ----> + * | | | | + * | | | subnet | + * | | +-----|-------+ + * | | | + * | | v + * | | +-------------+ + * | | | subnet | + * | +---------- shared | + * +----------->| | + * | group | + * +-------------+ + * + * The shared network contains a list of all the subnets that are on a broadcast + * doamin. These can be used to determine if an address makes sense in a given + * domain, but the subnets do not contain the addresses the server can delegate. + * Those are stored in the ponds and pools. + * + * In the simple case to find an acceptable address the server would first find + * the shared network the client is on based on either the interface used to + * receive the request or the relay agent's information. From the shared + * network the server will walk through it's list of ponds. For each pond it + * will evaluate the permit information against the (already done) classification. + * If it finds an acceptable pond it will then walk through the pools for that + * pond. The server first checks the type of the pool (NA, TA and PD) agaisnt the + * request and if they match it attemps to find an address within that pool. On + * success the address is used, on failure the server steps to the next pool and + * if necessary to the next pond. + * + * When the server is successful in finding an address it will execute any + * statements assocaited with the pond, then the subnet, then the shared + * network the group field is for in the above picture). + * + * In configurations that don't include either a shared network or a pool6 + * statement (or both) the missing pieces are created. + * + * + * There are three major data structuress involved in the lease database: + * + * - ipv6_pool - see above * - 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. + * - 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: * @@ -523,11 +609,27 @@ lease_index_changed(void *iasubopt, unsigned int new_heap_index) { } -/* - * Create a new IPv6 lease pool structure. +/*! * - * - pool must be a pointer to a (struct ipv6_pool *) pointer previously - * initialized to NULL + * \brief Create a new IPv6 lease pool structure + * + * Allocate space for a new ipv6_pool structure and return a reference + * to it, includes setting the reference count to 1. + * + * \param pool = space for returning a referenced pointer to the pool. + * This must point to a space that has been initialzied + * to NULL by the caller. + * \param[in] type = The type of the pool NA, TA or PD + * \param[in] start_addr = The first address in the range for the pool + * \param[in] bits = The contiguous bits of the pool + + * + * \return + * ISC_R_SUCCESS = The pool was successfully created, pool points to it. + * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been + * modified + * ISC_R_NOMEMORY = The system wasn't able to allocate memory, pool has + * not been modified. */ isc_result_t ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type, @@ -576,11 +678,24 @@ ipv6_pool_allocate(struct ipv6_pool **pool, u_int16_t type, return ISC_R_SUCCESS; } -/* - * Reference an IPv6 pool structure. +/*! * - * - pool must be a pointer to a (struct pool *) pointer previously - * initialized to NULL + * \brief reference an IPv6 pool structure. + * + * This function genreates a reference to an ipv6_pool structure + * and increments the reference count on the structure. + * + * \param[out] pool = space for returning a referenced pointer to the pool. + * This must point to a space that has been initialzied + * to NULL by the caller. + * \param[in] src = A pointer to the pool to reference. This must not be + * NULL. + * + * \return + * ISC_R_SUCCESS = The pool was successfully referenced, pool now points + * to src. + * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been + * modified. */ isc_result_t ipv6_pool_reference(struct ipv6_pool **pool, struct ipv6_pool *src, @@ -634,12 +749,24 @@ dereference_heap_entry(void *value, void *dummy) { iasubopt_dereference(&iasubopt, MDL); } - -/* - * Dereference an IPv6 pool structure. +/*! * - * If it is the last reference, then the memory for the - * structure is freed. + * \brief de-reference an IPv6 pool structure. + * + * This function decrements the reference count in an ipv6_pool structure. + * If this was the last reference then the memory for the structure is + * freed. + * + * \param[in] pool = A pointer to the pointer to the pool that should be + * de-referenced. On success the pointer to the pool + * is cleared. It must not be NULL and must not point + * to NULL. + * + * \return + * ISC_R_SUCCESS = The pool was successfully de-referenced, pool now points + * to NULL + * DHCP_R_INVALIDARG = One of the arugments was invalid, pool has not been + * modified. */ isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line) { @@ -804,7 +931,7 @@ static struct in6_addr resany; /* * Create a lease for the given address and client duid. * - * - pool must be a pointer to a (struct pool *) pointer previously + * - pool must be a pointer to a (struct ipv6_pool *) pointer previously * initialized to NULL * * Right now we simply hash the DUID, and if we get a collision, we hash @@ -1255,6 +1382,7 @@ move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) { } /*! + * * \brief Renew a lease in the pool. * * The hard_lifetime_end_time of the lease should be set to @@ -1277,8 +1405,8 @@ move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) { * 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 + * \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) @@ -1518,7 +1646,7 @@ build_prefix6(struct in6_addr *pref, /* * Create a lease for the given prefix and client duid. * - * - pool must be a pointer to a (struct pool *) pointer previously + * - pool must be a pointer to a (struct ipv6_pool *) pointer previously * initialized to NULL * * Right now we simply hash the DUID, and if we get a collision, we hash @@ -2190,4 +2318,128 @@ mark_interfaces_unavailable(void) { } } +/*! + * \brief Create a new IPv6 pond structure. + * + * Allocate space for a new ipv6_pond structure and return a reference + * to it, includes setting the reference count to 1. + * + * \param pond = space for returning a referenced pointer to the pond. + * This must point to a space that has been initialzied + * to NULL by the caller. + * + * \return + * ISC_R_SUCCESS = The pond was successfully created, pond points to it. + * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been + * modified + * ISC_R_NOMEMORY = The system wasn't able to allocate memory, pond has + * not been modified. + */ +isc_result_t +ipv6_pond_allocate(struct ipv6_pond **pond, const char *file, int line) { + struct ipv6_pond *tmp; + + if (pond == NULL) { + log_error("%s(%d): NULL pointer reference", file, line); + return DHCP_R_INVALIDARG; + } + if (*pond != NULL) { + log_error("%s(%d): non-NULL pointer", file, line); + return DHCP_R_INVALIDARG; + } + + tmp = dmalloc(sizeof(*tmp), file, line); + if (tmp == NULL) { + return ISC_R_NOMEMORY; + } + + tmp->refcnt = 1; + + *pond = tmp; + return ISC_R_SUCCESS; +} + +/*! + * + * \brief reference an IPv6 pond structure. + * + * This function genreates a reference to an ipv6_pond structure + * and increments the reference count on the structure. + * + * \param[out] pond = space for returning a referenced pointer to the pond. + * This must point to a space that has been initialzied + * to NULL by the caller. + * \param[in] src = A pointer to the pond to reference. This must not be + * NULL. + * + * \return + * ISC_R_SUCCESS = The pond was successfully referenced, pond now points + * to src. + * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been + * modified. + */ +isc_result_t +ipv6_pond_reference(struct ipv6_pond **pond, struct ipv6_pond *src, + const char *file, int line) { + if (pond == NULL) { + log_error("%s(%d): NULL pointer reference", file, line); + return DHCP_R_INVALIDARG; + } + if (*pond != NULL) { + log_error("%s(%d): non-NULL pointer", file, line); + return DHCP_R_INVALIDARG; + } + if (src == NULL) { + log_error("%s(%d): NULL pointer reference", file, line); + return DHCP_R_INVALIDARG; + } + *pond = src; + src->refcnt++; + return ISC_R_SUCCESS; +} + +/*! + * + * \brief de-reference an IPv6 pond structure. + * + * This function decrements the reference count in an ipv6_pond structure. + * If this was the last reference then the memory for the structure is + * freed. + * + * \param[in] pond = A pointer to the pointer to the pond that should be + * de-referenced. On success the pointer to the pond + * is cleared. It must not be NULL and must not point + * to NULL. + * + * \return + * ISC_R_SUCCESS = The pond was successfully de-referenced, pond now points + * to NULL + * DHCP_R_INVALIDARG = One of the arugments was invalid, pond has not been + * modified. + */ + +isc_result_t +ipv6_pond_dereference(struct ipv6_pond **pond, const char *file, int line) { + struct ipv6_pond *tmp; + + if ((pond == NULL) || (*pond == NULL)) { + log_error("%s(%d): NULL pointer", file, line); + return DHCP_R_INVALIDARG; + } + + tmp = *pond; + *pond = NULL; + + tmp->refcnt--; + if (tmp->refcnt < 0) { + log_error("%s(%d): negative refcnt", file, line); + tmp->refcnt = 0; + } + if (tmp->refcnt == 0) { + dfree(tmp, file, line); + } + + return ISC_R_SUCCESS; +} + /* unittest moved to server/tests/mdb6_unittest.c */ |