From 5d89d60f1478e931da4bed3e6724f7e1472fd2e9 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Thu, 21 Feb 2008 10:31:25 +0000 Subject: [PATCH] Soft binding side-effects --- RELNOTES | 2 + includes/dhcpd.h | 28 ++++---- server/confpars.c | 9 ++- server/db.c | 15 ++++- server/dhcpv6.c | 163 ++++++++++++++++++---------------------------- server/mdb6.c | 155 +++++++++++++++++++++++++------------------ 6 files changed, 192 insertions(+), 180 deletions(-) diff --git a/RELNOTES b/RELNOTES index 35f6d5e5..8dfa5d9e 100644 --- a/RELNOTES +++ b/RELNOTES @@ -165,6 +165,8 @@ work on other platforms. Please report any problems and suggested fixes to - DHCPv6 released resources are now marked as released by the client. +- 'Soft' bindings have no more side-effects. + Changes since 4.0.0b3 - The reverse dns name for PTR updates on IPv6 addresses has been fixed to diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 9bfdf736..d11ea8ac 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -1333,11 +1333,12 @@ struct iaaddr { u_int8_t plen; /* unused/placeholder */ binding_state_t state; /* state */ struct binding_scope *scope; /* "set var = value;" */ - time_t valid_lifetime_end_time; /* time address expires */ + time_t hard_lifetime_end_time; /* time address expires */ + time_t soft_lifetime_end_time; /* time ephemeral expires */ struct ia_na *ia_na; /* IA for this address */ struct ipv6_pool *ipv6_pool; /* pool for this address */ /* - * For now, just pick an arbitrary time to keep old leases + * For now, just pick an arbitrary time to keep old hard leases * around (value in seconds). */ #define EXPIRED_IPV6_CLEANUP_TIME (60*60) @@ -1388,7 +1389,8 @@ struct iaprefix { u_int8_t plen; /* prefix length */ binding_state_t state; /* state */ struct binding_scope *scope; /* "set var = value;" */ - time_t valid_lifetime_end_time; /* time prefix expires */ + time_t hard_lifetime_end_time; /* time prefix expires */ + time_t soft_lifetime_end_time; /* time ephemeral expires */ struct ia_pd *ia_pd; /* IA for this prefix */ struct ipv6_ppool *ipv6_ppool; /* pool for this prefix */ int heap_index; /* index into heap, or -1 @@ -3315,11 +3317,11 @@ isc_result_t ipv6_ppool_reference(struct ipv6_ppool **ppool, const char *file, int line); isc_result_t ipv6_ppool_dereference(struct ipv6_ppool **ppool, const char *file, int line); -isc_result_t activate_lease6(struct ipv6_pool *pool, - struct iaaddr **addr, - unsigned int *attempts, - const struct data_string *uid, - time_t valid_lifetime_end_time); +isc_result_t create_lease6(struct ipv6_pool *pool, + struct iaaddr **addr, + unsigned int *attempts, + const struct data_string *uid, + time_t soft_lifetime_end_time); isc_result_t add_lease6(struct ipv6_pool *pool, struct iaaddr *addr, time_t valid_lifetime_end_time); @@ -3333,11 +3335,11 @@ isc_boolean_t lease6_exists(const struct ipv6_pool *pool, isc_result_t mark_address_unavailble(struct ipv6_pool *pool, const struct in6_addr *addr); -isc_result_t activate_prefix6(struct ipv6_ppool *ppool, - struct iaprefix **pref, - unsigned int *attempts, - const struct data_string *uid, - time_t valid_lifetime_end_time); +isc_result_t create_prefix6(struct ipv6_ppool *ppool, + struct iaprefix **pref, + unsigned int *attempts, + const struct data_string *uid, + time_t soft_lifetime_end_time); isc_result_t add_prefix6(struct ipv6_ppool *ppool, struct iaprefix *pref, time_t valid_lifetime_end_time); diff --git a/server/confpars.c b/server/confpars.c index a367d61c..2121225f 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -4317,7 +4317,8 @@ parse_ia_na_declaration(struct parse *cfile) { } memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr)); iaaddr->state = state; - iaaddr->valid_lifetime_end_time = end_time; + if (iaaddr->state == FTS_RELEASED) + iaaddr->hard_lifetime_end_time = end_time; if (scope != NULL) { binding_scope_reference(&iaaddr->scope, scope, MDL); @@ -4611,7 +4612,8 @@ parse_ia_ta_declaration(struct parse *cfile) { } memcpy(&iaaddr->addr, iaddr.iabuf, sizeof(iaaddr->addr)); iaaddr->state = state; - iaaddr->valid_lifetime_end_time = end_time; + if (iaaddr->state == FTS_RELEASED) + iaaddr->hard_lifetime_end_time = end_time; if (scope != NULL) { binding_scope_reference(&iaaddr->scope, scope, MDL); @@ -4906,7 +4908,8 @@ parse_ia_pd_declaration(struct parse *cfile) { memcpy(&iapref->pref, iaddr.iabuf, sizeof(iapref->pref)); iapref->plen = plen; iapref->state = state; - iapref->valid_lifetime_end_time = end_time; + if (iapref->state == FTS_RELEASED) + iapref->hard_lifetime_end_time = end_time; if (scope != NULL) { binding_scope_reference(&iapref->scope, scope, MDL); diff --git a/server/db.c b/server/db.c index 0c536465..e2af0a28 100644 --- a/server/db.c +++ b/server/db.c @@ -562,7 +562,13 @@ write_ia(const struct ia_na *ia) { /* Note that from here on out, the \n is prepended to the * next write, rather than appended to the current write. */ - tval = print_time(iaaddr->valid_lifetime_end_time); + if ((iaaddr->state == FTS_ACTIVE) || + (iaaddr->state == FTS_ABANDONED) || + (iaaddr->hard_lifetime_end_time != 0)) { + tval = print_time(iaaddr->hard_lifetime_end_time); + } else { + tval = print_time(iaaddr->soft_lifetime_end_time); + } if (tval == NULL) { goto error_exit; } @@ -665,7 +671,12 @@ write_ia_pd(const struct ia_pd *ia_pd) { /* Note that from here on out, the \n is prepended to the * next write, rather than appended to the current write. */ - tval = print_time(iapref->valid_lifetime_end_time); + if ((iapref->state == FTS_ACTIVE) || + (iapref->state == FTS_ABANDONED)) { + tval = print_time(iapref->hard_lifetime_end_time); + } else { + tval = print_time(iapref->soft_lifetime_end_time); + } if (tval == NULL) { goto error_exit; } diff --git a/server/dhcpv6.c b/server/dhcpv6.c index 52a1b97d..b4f1adbe 100644 --- a/server/dhcpv6.c +++ b/server/dhcpv6.c @@ -979,7 +979,8 @@ try_client_v6_address(struct iaaddr **addr, } (*addr)->addr = tmp_addr; - result = add_lease6(pool, *addr, 0); + /* Default is soft binding for 2 minutes. */ + result = add_lease6(pool, *addr, cur_time + 120); if (result != ISC_R_SUCCESS) { iaaddr_dereference(addr, MDL); } @@ -1038,8 +1039,8 @@ pick_v6_address(struct iaaddr **addr, struct shared_network *shared_network, p = shared_network->ipv6_pools[i]; if (((p->bits & POOL_IS_FOR_TEMP) == 0) && - (activate_lease6(p, addr, &attempts, - client_id, 0) == ISC_R_SUCCESS)) { + (create_lease6(p, addr, &attempts, client_id, + cur_time + 120) == ISC_R_SUCCESS)) { /* * Record the pool used (or next one if there * was a collision). @@ -1123,7 +1124,8 @@ try_client_v6_prefix(struct iaprefix **pref, (*pref)->pref = tmp_pref; (*pref)->plen = tmp_plen; - result = add_prefix6(ppool, *pref, 0); + /* Default is soft binding for 2 minutes. */ + result = add_prefix6(ppool, *pref, cur_time + 120); if (result != ISC_R_SUCCESS) { iaprefix_dereference(pref, MDL); } @@ -1173,8 +1175,8 @@ pick_v6_prefix(struct iaprefix **pref, int plen, continue; } - if (activate_prefix6(p, pref, &attempts, - client_id, 0) == ISC_R_SUCCESS) { + if (create_prefix6(p, pref, &attempts, client_id, + cur_time + 120) == ISC_R_SUCCESS) { log_debug("Picking pool prefix %s/%u", inet_ntop(AF_INET6, &((*pref)->pref), tmp_buf, sizeof(tmp_buf)), @@ -1507,13 +1509,11 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { struct option_state *packet_ia; struct option_cache *oc; struct data_string ia_data, data; - isc_boolean_t lease_in_database; /* Initialize values that will get cleaned up on return. */ packet_ia = NULL; memset(&ia_data, 0, sizeof(ia_data)); memset(&data, 0, sizeof(data)); - lease_in_database = ISC_FALSE; /* * Note that find_client_address() may set reply->lease. */ @@ -1541,7 +1541,7 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { /* Create an IA_NA structure. */ if (ia_na_allocate(&reply->ia_na, iaid, (char *)reply->client_id.data, reply->client_id.len, MDL) != ISC_R_SUCCESS) { - log_error("lease_to_client: no memory for ia_na."); + log_error("reply_process_ia_na: no memory for ia_na."); status = ISC_R_NOMEMORY; goto cleanup; } @@ -1796,11 +1796,15 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { ia_na_dereference(&tmp->ia_na, MDL); ia_na_reference(&tmp->ia_na, reply->ia_na, MDL); + /* Commit 'hard' bindings. */ + tmp->hard_lifetime_end_time = + tmp->soft_lifetime_end_time; + tmp->soft_lifetime_end_time = 0; + renew_lease6(tmp->ipv6_pool, tmp); schedule_lease_timeout(tmp->ipv6_pool); /* - * If this constitutes a 'hard' binding, perform ddns - * updates. + * Perform ddns updates. */ oc = lookup_option(&server_universe, reply->opt_state, SV_DDNS_UPDATES); @@ -1831,23 +1835,6 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { ia_id->len, reply->ia_na, MDL); write_ia(reply->ia_na); - - /* - * Note that we wrote the lease into the database, - * so that we know not to release it when we're done - * with this function. - */ - lease_in_database = ISC_TRUE; - - /* - * If this is a soft binding, we will check to see if we are - * suggesting the existing database entry to the client. - */ - } else if ((status != ISC_R_CANCELED) && !reply->static_lease && - (reply->old_ia != NULL)) { - if (ia_na_equal(reply->old_ia, reply->ia_na)) { - lease_in_database = ISC_TRUE; - } } cleanup: @@ -1863,12 +1850,8 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) { ia_na_dereference(&reply->ia_na, MDL); if (reply->old_ia != NULL) ia_na_dereference(&reply->old_ia, MDL); - if (reply->lease != NULL) { - if (!lease_in_database) { - release_lease6(reply->lease->ipv6_pool, reply->lease); - } + if (reply->lease != NULL) iaaddr_dereference(&reply->lease, MDL); - } if (reply->fixed.data != NULL) data_string_forget(&reply->fixed, MDL); @@ -2245,7 +2228,7 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { /* Create an IA_TA structure. */ if (ia_na_allocate(&reply->ia_ta, iaid, (char *)reply->client_id.data, reply->client_id.len, MDL) != ISC_R_SUCCESS) { - log_error("lease_to_client: no memory for ia_ta."); + log_error("reply_process_ia_ta: no memory for ia_ta."); status = ISC_R_NOMEMORY; goto cleanup; } @@ -2421,6 +2404,11 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { ia_na_dereference(&tmp->ia_na, MDL); ia_na_reference(&tmp->ia_na, reply->ia_ta, MDL); + /* Commit 'hard' bindings. */ + tmp->hard_lifetime_end_time = + tmp->soft_lifetime_end_time; + tmp->soft_lifetime_end_time = 0; + renew_lease6(tmp->ipv6_pool, tmp); schedule_lease_timeout(tmp->ipv6_pool); /* @@ -2472,6 +2460,8 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) { ia_na_dereference(&reply->ia_ta, MDL); if (reply->old_ia != NULL) ia_na_dereference(&reply->old_ia, MDL); + if (reply->lease != NULL) + iaaddr_dereference(&reply->lease, MDL); /* * ISC_R_CANCELED is a status code used by the addr processing to @@ -2516,8 +2506,8 @@ find_client_temporaries(struct reply_state *reply) { /* * Get an address in this temporary pool. */ - status = activate_lease6(p, &reply->lease, &attempts, - &reply->client_id, 0); + status = create_lease6(p, &reply->lease, &attempts, + &reply->client_id, cur_time + 120); if (status != ISC_R_SUCCESS) { log_debug("Unable to get a temporary address."); goto cleanup; @@ -2757,9 +2747,11 @@ reply_process_is_addressed(struct reply_state *reply, struct ia_na *ia, /* Perform dynamic lease related update work. */ if (reply->lease != NULL) { /* Advance (or rewind) the valid lifetime. */ - reply->lease->valid_lifetime_end_time = cur_time + - reply->send_valid; - renew_lease6(reply->lease->ipv6_pool, reply->lease); + if (reply->buf.reply.msg_type == DHCPV6_REPLY) { + reply->lease->soft_lifetime_end_time = + cur_time + reply->send_valid; + /* Wait before renew! */ + } status = ia_na_add_iaaddr(ia, reply->lease, MDL); if (status != ISC_R_SUCCESS) { @@ -2846,8 +2838,8 @@ lease_compare(struct iaaddr *alpha, struct iaaddr *beta) { /* Choose the lease with the longest lifetime (most * likely the most recently allocated). */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) return beta; else return alpha; @@ -2868,8 +2860,13 @@ lease_compare(struct iaaddr *alpha, struct iaaddr *beta) { case FTS_EXPIRED: /* Choose the most recently expired lease. */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) + return beta; + else if ((alpha->hard_lifetime_end_time == + beta->hard_lifetime_end_time) && + (alpha->soft_lifetime_end_time < + beta->soft_lifetime_end_time)) return beta; else return alpha; @@ -2890,8 +2887,8 @@ lease_compare(struct iaaddr *alpha, struct iaaddr *beta) { case FTS_ABANDONED: /* Choose the lease that was abandoned longest ago. */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) return alpha; default: @@ -2918,13 +2915,11 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) { struct option_state *packet_ia; struct option_cache *oc; struct data_string ia_pd_data, data; - isc_boolean_t prefix_in_database; /* Initialize values that will get cleaned up on return. */ packet_ia = NULL; memset(&ia_pd_data, 0, sizeof(ia_pd_data)); memset(&data, 0, sizeof(data)); - prefix_in_database = ISC_FALSE; /* * Note that find_client_prefix() may set reply->prefix. */ @@ -3168,6 +3163,11 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) { ia_pd_dereference(&tmp->ia_pd, MDL); ia_pd_reference(&tmp->ia_pd, reply->ia_pd, MDL); + /* Commit 'hard' bindings. */ + tmp->hard_lifetime_end_time = + tmp->soft_lifetime_end_time; + tmp->soft_lifetime_end_time = 0; + renew_prefix6(tmp->ipv6_ppool, tmp); schedule_prefix_timeout(tmp->ipv6_ppool); } @@ -3186,24 +3186,6 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) { ia_id->len, reply->ia_pd, MDL); write_ia_pd(reply->ia_pd); - - /* - * Note that we wrote the prefix into the database, - * so that we know not to release it when we're done - * with this function. - */ - prefix_in_database = ISC_TRUE; - - /* - * If this is a soft binding, we will check to see if we are - * suggesting the existing database entry to the client. - */ - } else if ((status != ISC_R_CANCELED) && - (reply->static_prefixes == 0) && - (reply->old_ia_pd != NULL)) { - if (ia_pd_equal(reply->old_ia_pd, reply->ia_pd)) { - prefix_in_database = ISC_TRUE; - } } cleanup: @@ -3215,27 +3197,12 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia_pd) { data_string_forget(&ia_pd_data, MDL); if (data.data != NULL) data_string_forget(&data, MDL); + if (reply->ia_pd != NULL) + ia_pd_dereference(&reply->ia_pd, MDL); if (reply->old_ia_pd != NULL) ia_pd_dereference(&reply->old_ia_pd, MDL); if (reply->prefix != NULL) iaprefix_dereference(&reply->prefix, MDL); - if (!prefix_in_database) { - /* - * Cleanup soft bindings, assume: - * reply->static_prefixes == 0 - * reply->ia_pd != NULL - * reply->ia_pd->num_iaprefix != 0 - */ - struct iaprefix *tmp; - int i; - - for (i = 0 ; i < reply->ia_pd->num_iaprefix ; i++) { - tmp = reply->ia_pd->iaprefix[i]; - release_prefix6(tmp->ipv6_ppool, tmp); - } - } - if (reply->ia_pd != NULL) - ia_pd_dereference(&reply->ia_pd, MDL); /* * ISC_R_CANCELED is a status code used by the prefix processing to @@ -3259,11 +3226,9 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) { struct iaddrcidrnet tmp_pref; struct option_cache *oc; struct data_string iapref, data; - isc_boolean_t held_prefix; isc_result_t status = ISC_R_SUCCESS; /* Initializes values that will be cleaned up. */ - held_prefix = ISC_FALSE; memset(&iapref, 0, sizeof(iapref)); memset(&data, 0, sizeof(data)); /* Note that reply->prefix may be set by prefix_is_owned() */ @@ -3353,9 +3318,6 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) { /* status remains success - ignore */ goto cleanup; } - - held_prefix = ISC_TRUE; - /* * RFC3633 section 18.2.3: * @@ -3467,8 +3429,6 @@ reply_process_prefix(struct reply_state *reply, struct option_cache *pref) { data_string_forget(&iapref, MDL); if (data.data != NULL) data_string_forget(&data, MDL); - if (held_prefix && (status != ISC_R_SUCCESS)) - release_prefix6(reply->prefix->ipv6_ppool, reply->prefix); if (reply->prefix != NULL) iaprefix_dereference(&reply->prefix, MDL); @@ -3739,9 +3699,11 @@ reply_process_is_prefixed(struct reply_state *reply, struct ia_pd *ia_pd, /* Perform dynamic prefix related update work. */ if (reply->prefix != NULL) { /* Advance (or rewind) the valid lifetime. */ - reply->prefix->valid_lifetime_end_time = cur_time + - reply->send_valid; - renew_prefix6(reply->prefix->ipv6_ppool, reply->prefix); + if (reply->buf.reply.msg_type == DHCPV6_REPLY) { + reply->prefix->soft_lifetime_end_time = + cur_time + reply->send_valid; + /* Wait before renew! */ + } status = ia_pd_add_iaprefix(ia_pd, reply->prefix, MDL); if (status != ISC_R_SUCCESS) { @@ -3840,8 +3802,8 @@ prefix_compare(struct reply_state *reply, /* Choose the prefix with the longest lifetime (most * likely the most recently allocated). */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) return beta; else return alpha; @@ -3862,8 +3824,13 @@ prefix_compare(struct reply_state *reply, case FTS_EXPIRED: /* Choose the most recently expired prefix. */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) + return beta; + else if ((alpha->hard_lifetime_end_time == + beta->hard_lifetime_end_time) && + (alpha->soft_lifetime_end_time < + beta->soft_lifetime_end_time)) return beta; else return alpha; @@ -3884,8 +3851,8 @@ prefix_compare(struct reply_state *reply, case FTS_ABANDONED: /* Choose the prefix that was abandoned longest ago. */ - if (alpha->valid_lifetime_end_time < - beta->valid_lifetime_end_time) + if (alpha->hard_lifetime_end_time < + beta->hard_lifetime_end_time) return alpha; default: diff --git a/server/mdb6.c b/server/mdb6.c index 3cd3b2b7..0c0a1899 100644 --- a/server/mdb6.c +++ b/server/mdb6.c @@ -782,8 +782,13 @@ lease_older(void *a, void *b) { struct iaaddr *ia = (struct iaaddr *)a; struct iaaddr *ib = (struct iaaddr *)b; - return difftime(ia->valid_lifetime_end_time, - ib->valid_lifetime_end_time) < 0; + if (ia->hard_lifetime_end_time == ib->hard_lifetime_end_time) { + return difftime(ia->soft_lifetime_end_time, + ib->soft_lifetime_end_time) < 0; + } else { + return difftime(ia->hard_lifetime_end_time, + ib->hard_lifetime_end_time) < 0; + } } /* @@ -1108,7 +1113,7 @@ ipv6_ppool_dereference(struct ipv6_ppool **ppool, const char *file, int line) { * the non-network part. */ static void -create_address(struct in6_addr *addr, +build_address6(struct in6_addr *addr, const struct in6_addr *net_start_addr, int net_bits, const struct data_string *input) { MD5_CTX ctx; @@ -1153,7 +1158,7 @@ create_address(struct in6_addr *addr, * Create a temporary address by a variant of RFC 4941 algo. */ static void -create_temporary(struct in6_addr *addr, +build_temporary6(struct in6_addr *addr, const struct in6_addr *net_start_addr, const struct data_string *input) { static u_int8_t history[8]; @@ -1220,9 +1225,9 @@ static struct in6_addr resany; * the long term. */ isc_result_t -activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr, - unsigned int *attempts, - const struct data_string *uid, time_t valid_lifetime_end_time) { +create_lease6(struct ipv6_pool *pool, struct iaaddr **addr, + unsigned int *attempts, + const struct data_string *uid, time_t soft_lifetime_end_time) { struct data_string ds; struct in6_addr tmp; struct iaaddr *test_iaaddr; @@ -1260,13 +1265,13 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr, } /* - * Create an address or a temporary address. + * Build an address or a temporary address. */ if ((pool->bits & POOL_IS_FOR_TEMP) == 0) { - create_address(&tmp, &pool->start_addr, + build_address6(&tmp, &pool->start_addr, pool->bits, &ds); } else { - create_temporary(&tmp, &pool->start_addr, &ds); + build_temporary6(&tmp, &pool->start_addr, &ds); } /* @@ -1328,7 +1333,7 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr, /* * Add the lease to the pool (note state is free, not active?!). */ - result = add_lease6(pool, iaaddr, valid_lifetime_end_time); + result = add_lease6(pool, iaaddr, soft_lifetime_end_time); if (result == ISC_R_SUCCESS) { iaaddr_reference(addr, iaaddr, MDL); } @@ -1351,7 +1356,6 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr, if (iaaddr->state == 0) iaaddr->state = FTS_ACTIVE; - iaaddr->valid_lifetime_end_time = valid_lifetime_end_time; ipv6_pool_reference(&iaaddr->ipv6_pool, pool, MDL); /* @@ -1401,6 +1405,7 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr, iaaddr_reference(&tmp_iaaddr, iaaddr, MDL); if ((tmp_iaaddr->state == FTS_ACTIVE) || (tmp_iaaddr->state == FTS_ABANDONED)) { + tmp_iaaddr->hard_lifetime_end_time = valid_lifetime_end_time; iaaddr_hash_add(pool->addrs, &tmp_iaaddr->addr, sizeof(tmp_iaaddr->addr), iaaddr, MDL); insert_result = isc_heap_insert(pool->active_timeouts, @@ -1408,6 +1413,7 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr, if (insert_result == ISC_R_SUCCESS) pool->num_active++; } else { + tmp_iaaddr->soft_lifetime_end_time = valid_lifetime_end_time; insert_result = isc_heap_insert(pool->inactive_timeouts, tmp_iaaddr); if (insert_result == ISC_R_SUCCESS) @@ -1469,7 +1475,7 @@ move_lease_to_active(struct ipv6_pool *pool, struct iaaddr *addr) { /* * Renew an lease in the pool. * - * To do this, first set the new valid_lifetime_end_time for the address, + * To do this, first set the new hard_lifetime_end_time for the address, * and then invoke renew_lease() on the address. * * WARNING: lease times must only be extended, never reduced!!! @@ -1550,7 +1556,7 @@ expire_lease6(struct iaaddr **addr, struct ipv6_pool *pool, time_t now) { if (pool->num_active > 0) { tmp = (struct iaaddr *)isc_heap_element(pool->active_timeouts, 1); - if (now > tmp->valid_lifetime_end_time) { + if (now > tmp->hard_lifetime_end_time) { result = move_lease_to_inactive(pool, tmp, FTS_EXPIRED); if (result == ISC_R_SUCCESS) { iaaddr_reference(addr, tmp, MDL); @@ -1577,7 +1583,7 @@ decline_lease6(struct ipv6_pool *pool, struct iaaddr *addr) { } } addr->state = FTS_ABANDONED; - addr->valid_lifetime_end_time = MAX_TIME; + addr->hard_lifetime_end_time = MAX_TIME; isc_heap_decreased(pool->active_timeouts, addr->heap_index); return ISC_R_SUCCESS; } @@ -1599,7 +1605,7 @@ release_lease6(struct ipv6_pool *pool, struct iaaddr *addr) { * the part subject to allocation. */ static void -create_prefix(struct in6_addr *pref, +build_prefix6(struct in6_addr *pref, const struct in6_addr *net_start_pref, int pool_bits, int pref_bits, const struct data_string *input) { @@ -1679,10 +1685,10 @@ create_prefix(struct in6_addr *pref, * the long term. */ isc_result_t -activate_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref, - unsigned int *attempts, - const struct data_string *uid, - time_t valid_lifetime_end_time) { +create_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref, + unsigned int *attempts, + const struct data_string *uid, + time_t soft_lifetime_end_time) { struct data_string ds; struct in6_addr tmp; struct iaprefix *test_iapref; @@ -1707,9 +1713,9 @@ activate_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref, } /* - * Create a prefix + * Build a prefix */ - create_prefix(&tmp, &ppool->start_pref, + build_prefix6(&tmp, &ppool->start_pref, (int)ppool->pool_plen, (int)ppool->alloc_plen, &ds); @@ -1757,7 +1763,7 @@ activate_prefix6(struct ipv6_ppool *ppool, struct iaprefix **pref, /* * Add the prefix to the pool (note state is free, not active?!). */ - result = add_prefix6(ppool, iapref, valid_lifetime_end_time); + result = add_prefix6(ppool, iapref, soft_lifetime_end_time); if (result == ISC_R_SUCCESS) { iaprefix_reference(pref, iapref, MDL); } @@ -1780,7 +1786,6 @@ add_prefix6(struct ipv6_ppool *ppool, struct iaprefix *iapref, if (iapref->state == 0) iapref->state = FTS_ACTIVE; - iapref->valid_lifetime_end_time = valid_lifetime_end_time; ipv6_ppool_reference(&iapref->ipv6_ppool, ppool, MDL); /* @@ -1830,6 +1835,7 @@ add_prefix6(struct ipv6_ppool *ppool, struct iaprefix *iapref, iaprefix_reference(&tmp_iapref, iapref, MDL); if ((tmp_iapref->state == FTS_ACTIVE) || (tmp_iapref->state == FTS_ABANDONED)) { + tmp_iapref->hard_lifetime_end_time = valid_lifetime_end_time; iaprefix_hash_add(ppool->prefs, &tmp_iapref->pref, sizeof(tmp_iapref->pref), iapref, MDL); insert_result = isc_heap_insert(ppool->active_timeouts, @@ -1837,6 +1843,7 @@ add_prefix6(struct ipv6_ppool *ppool, struct iaprefix *iapref, if (insert_result == ISC_R_SUCCESS) ppool->num_active++; } else { + tmp_iapref->soft_lifetime_end_time = valid_lifetime_end_time; insert_result = isc_heap_insert(ppool->inactive_timeouts, tmp_iapref); if (insert_result == ISC_R_SUCCESS) @@ -1902,7 +1909,7 @@ move_prefix_to_active(struct ipv6_ppool *ppool, struct iaprefix *pref) { /* * Renew a prefix in the pool. * - * To do this, first set the new valid_lifetime_end_time for the prefix, + * To do this, first set the new hard_lifetime_end_time for the prefix, * and then invoke renew_prefix() on the prefix. * * WARNING: lease times must only be extended, never reduced!!! @@ -1983,7 +1990,7 @@ expire_prefix6(struct iaprefix **pref, struct ipv6_ppool *ppool, time_t now) { if (ppool->num_active > 0) { tmp = (struct iaprefix *) isc_heap_element(ppool->active_timeouts, 1); - if (now > tmp->valid_lifetime_end_time) { + if (now > tmp->hard_lifetime_end_time) { result = move_prefix_to_inactive(ppool, tmp, FTS_EXPIRED); if (result == ISC_R_SUCCESS) { @@ -2107,12 +2114,18 @@ cleanup_old_expired(struct ipv6_pool *pool) { struct ia_na *ia; struct ia_na *ia_active; unsigned char *tmpd; + time_t timeout; while (pool->num_inactive > 0) { tmp = (struct iaaddr *)isc_heap_element(pool->inactive_timeouts, 1); - if (cur_time < - tmp->valid_lifetime_end_time + EXPIRED_IPV6_CLEANUP_TIME) { + if (tmp->hard_lifetime_end_time != 0) { + timeout = tmp->hard_lifetime_end_time; + timeout += EXPIRED_IPV6_CLEANUP_TIME; + } else { + timeout = tmp->soft_lifetime_end_time; + } + if (cur_time < timeout) { break; } @@ -2216,16 +2229,20 @@ schedule_lease_timeout(struct ipv6_pool *pool) { if (pool->num_active > 0) { tmp = (struct iaaddr *)isc_heap_element(pool->active_timeouts, 1); - if (tmp->valid_lifetime_end_time < next_timeout) { - next_timeout = tmp->valid_lifetime_end_time + 1; + if (tmp->hard_lifetime_end_time < next_timeout) { + next_timeout = tmp->hard_lifetime_end_time + 1; } } if (pool->num_inactive > 0) { tmp = (struct iaaddr *)isc_heap_element(pool->inactive_timeouts, 1); - timeout = tmp->valid_lifetime_end_time + - EXPIRED_IPV6_CLEANUP_TIME; + if (tmp->hard_lifetime_end_time != 0) { + timeout = tmp->hard_lifetime_end_time; + timeout += EXPIRED_IPV6_CLEANUP_TIME; + } else { + timeout = tmp->soft_lifetime_end_time + 1; + } if (timeout < next_timeout) { next_timeout = timeout; } @@ -2258,12 +2275,18 @@ cleanup_old_pexpired(struct ipv6_ppool *ppool) { struct ia_pd *ia_pd; struct ia_pd *ia_active; unsigned char *tmpd; + time_t timeout; while (ppool->num_inactive > 0) { tmp = (struct iaprefix *) isc_heap_element(ppool->inactive_timeouts, 1); - if (cur_time < - tmp->valid_lifetime_end_time + EXPIRED_IPV6_CLEANUP_TIME) { + if (tmp->hard_lifetime_end_time != 0) { + timeout = tmp->hard_lifetime_end_time; + timeout += EXPIRED_IPV6_CLEANUP_TIME; + } else { + timeout = tmp->soft_lifetime_end_time; + } + if (cur_time < timeout) { break; } @@ -2351,16 +2374,20 @@ schedule_prefix_timeout(struct ipv6_ppool *ppool) { if (ppool->num_active > 0) { tmp = (struct iaprefix *) isc_heap_element(ppool->active_timeouts, 1); - if (tmp->valid_lifetime_end_time < next_timeout) { - next_timeout = tmp->valid_lifetime_end_time + 1; + if (tmp->hard_lifetime_end_time < next_timeout) { + next_timeout = tmp->hard_lifetime_end_time + 1; } } if (ppool->num_inactive > 0) { tmp = (struct iaprefix *) isc_heap_element(ppool->inactive_timeouts, 1); - timeout = tmp->valid_lifetime_end_time + - EXPIRED_IPV6_CLEANUP_TIME; + if (tmp->hard_lifetime_end_time != 0) { + timeout = tmp->hard_lifetime_end_time; + timeout += EXPIRED_IPV6_CLEANUP_TIME; + } else { + timeout = tmp->soft_lifetime_end_time + 1; + } if (timeout < next_timeout) { next_timeout = timeout; } @@ -2529,7 +2556,7 @@ change_leases(struct ia_na *ia, /* * Renew all leases in an IA from all pools. * - * The new valid_lifetime_end_time should be updated for the addresses. + * The new hard_lifetime_end_time should be updated for the addresses. * * WARNING: lease times must only be extended, never reduced!!! */ @@ -2630,7 +2657,7 @@ change_prefixes(struct ia_pd *ia_pd, /* * Renew all prefixes in an IA_PD from all pools. * - * The new valid_lifetime_end_time should be updated for the addresses. + * The new hard_lifetime_end_time should be updated for the addresses. * * WARNING: lease times must only be extended, never reduced!!! */ @@ -3139,7 +3166,7 @@ main(int argc, char *argv[]) { return 1; } - /* activate_lease6, renew_lease6, expire_lease6 */ + /* create_lease6, renew_lease6, expire_lease6 */ uid = "client0"; memset(&ds, 0, sizeof(ds)); ds.len = strlen(uid); @@ -3149,9 +3176,9 @@ main(int argc, char *argv[]) { } ds.data = ds.buffer->data; memcpy((char *)ds.data, uid, ds.len); - if (activate_lease6(pool, &iaaddr, - &attempts, &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3201,9 +3228,9 @@ main(int argc, char *argv[]) { } /* release_lease6, decline_lease6 */ - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3226,9 +3253,9 @@ main(int argc, char *argv[]) { printf("ERROR: iaaddr_dereference() %s:%d\n", MDL); return 1; } - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, 1) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3306,9 +3333,9 @@ main(int argc, char *argv[]) { return 1; } for (i=10; i<100; i+=10) { - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, i) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3343,8 +3370,8 @@ main(int argc, char *argv[]) { printf("ERROR: bad num_active %s:%d\n", MDL); return 1; } - if (expired_iaaddr->valid_lifetime_end_time != i) { - printf("ERROR: bad valid_lifetime_end_time %s:%d\n", + if (expired_iaaddr->hard_lifetime_end_time != i) { + printf("ERROR: bad hard_lifetime_end_time %s:%d\n", MDL); return 1; } @@ -3376,9 +3403,9 @@ main(int argc, char *argv[]) { printf("ERROR: ipv6_pool_allocate() %s:%d\n", MDL); return 1; } - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, 42) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3389,9 +3416,9 @@ main(int argc, char *argv[]) { printf("ERROR: iaaddr_dereference() %s:%d\n", MDL); return 1; } - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, 11) != ISC_R_SUCCESS) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) { @@ -3402,9 +3429,9 @@ main(int argc, char *argv[]) { printf("ERROR: iaaddr_dereference() %s:%d\n", MDL); return 1; } - if (activate_lease6(pool, &iaaddr, &attempts, - &ds, 11) != ISC_R_NORESOURCES) { - printf("ERROR: activate_lease6() %s:%d\n", MDL); + 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) {