mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 09:57:20 +00:00
Expire old IPv6 leases. Also a number of fixes.
See RT ticket #16849 for details.
This commit is contained in:
parent
8c1752d2ce
commit
d9b43370a4
4
RELNOTES
4
RELNOTES
@ -39,8 +39,6 @@ release, which will be addressed shortly:
|
|||||||
|
|
||||||
- Dynamically allocated leases do not respond to Confirm messages.
|
- Dynamically allocated leases do not respond to Confirm messages.
|
||||||
|
|
||||||
- Old (expired) leases are never cleaned.
|
|
||||||
|
|
||||||
- The client and server can only operate DHCPv4 or DHCPv6 at a time,
|
- The client and server can only operate DHCPv4 or DHCPv6 at a time,
|
||||||
not both, so two instances of the daemons are required with the
|
not both, so two instances of the daemons are required with the
|
||||||
"-6" command line option.
|
"-6" command line option.
|
||||||
@ -52,6 +50,8 @@ the README file.
|
|||||||
|
|
||||||
Changes since 4.0.0-20070413
|
Changes since 4.0.0-20070413
|
||||||
|
|
||||||
|
- Old (expired) leases are now cleaned.
|
||||||
|
|
||||||
- IPv6 subnets now have support for arbitrary allocation ranges via
|
- IPv6 subnets now have support for arbitrary allocation ranges via
|
||||||
a new 'range6' configuration directive.
|
a new 'range6' configuration directive.
|
||||||
|
|
||||||
|
@ -1249,8 +1249,10 @@ typedef unsigned char option_mask [16];
|
|||||||
#define MAX_TIME 0x7fffffff
|
#define MAX_TIME 0x7fffffff
|
||||||
#define MIN_TIME 0
|
#define MIN_TIME 0
|
||||||
|
|
||||||
|
/* these are referenced */
|
||||||
typedef struct hash_table ia_na_hash_t;
|
typedef struct hash_table ia_na_hash_t;
|
||||||
typedef struct hash_table iaaddr_hash_t;
|
typedef struct hash_table iaaddr_hash_t;
|
||||||
|
int num_inactive; /* count of inactive IAADDR */
|
||||||
|
|
||||||
struct iaaddr {
|
struct iaaddr {
|
||||||
int refcnt; /* reference count */
|
int refcnt; /* reference count */
|
||||||
@ -1260,6 +1262,12 @@ struct iaaddr {
|
|||||||
time_t valid_lifetime_end_time; /* time address expires */
|
time_t valid_lifetime_end_time; /* time address expires */
|
||||||
struct ia_na *ia_na; /* IA for this address */
|
struct ia_na *ia_na; /* IA for this address */
|
||||||
struct ipv6_pool *ipv6_pool; /* pool for this address */
|
struct ipv6_pool *ipv6_pool; /* pool for this address */
|
||||||
|
/*
|
||||||
|
* For now, just pick an arbitrary time to keep old leases
|
||||||
|
* around (value in seconds).
|
||||||
|
*/
|
||||||
|
#define EXPIRED_IPV6_CLEANUP_TIME (60*60)
|
||||||
|
|
||||||
int heap_index; /* index into heap, or -1
|
int heap_index; /* index into heap, or -1
|
||||||
(internal use only) */
|
(internal use only) */
|
||||||
};
|
};
|
||||||
@ -3110,6 +3118,7 @@ isc_result_t dhcp_failover_process_update_request_all (dhcp_failover_state_t *,
|
|||||||
failover_message_t *);
|
failover_message_t *);
|
||||||
isc_result_t dhcp_failover_process_update_done (dhcp_failover_state_t *,
|
isc_result_t dhcp_failover_process_update_done (dhcp_failover_state_t *,
|
||||||
failover_message_t *);
|
failover_message_t *);
|
||||||
|
void ia_na_remove_all_iaaddr(struct ia_na *ia_na, const char *file, int line);
|
||||||
void dhcp_failover_recover_done (void *);
|
void dhcp_failover_recover_done (void *);
|
||||||
void failover_print PROTO ((char *, unsigned *, unsigned, const char *));
|
void failover_print PROTO ((char *, unsigned *, unsigned, const char *));
|
||||||
void update_partner PROTO ((struct lease *));
|
void update_partner PROTO ((struct lease *));
|
||||||
@ -3194,10 +3203,11 @@ isc_result_t find_ipv6_pool(struct ipv6_pool **pool,
|
|||||||
isc_boolean_t ipv6_addr_in_pool(const struct in6_addr *addr,
|
isc_boolean_t ipv6_addr_in_pool(const struct in6_addr *addr,
|
||||||
const struct ipv6_pool *pool);
|
const struct ipv6_pool *pool);
|
||||||
|
|
||||||
void expire_leases(time_t now);
|
|
||||||
isc_result_t renew_leases(struct ia_na *ia_na);
|
isc_result_t renew_leases(struct ia_na *ia_na);
|
||||||
isc_result_t release_leases(struct ia_na *ia_na);
|
isc_result_t release_leases(struct ia_na *ia_na);
|
||||||
isc_result_t decline_leases(struct ia_na *ia_na);
|
isc_result_t decline_leases(struct ia_na *ia_na);
|
||||||
|
void schedule_lease_timeout(struct ipv6_pool *pool);
|
||||||
|
void schedule_all_ipv6_lease_timeouts();
|
||||||
|
|
||||||
void mark_hosts_unavailable(void);
|
void mark_hosts_unavailable(void);
|
||||||
void mark_interfaces_unavailable(void);
|
void mark_interfaces_unavailable(void);
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
"$Id: confpars.c,v 1.163 2007/05/08 23:05:21 dhankins Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
|
"$Id: confpars.c,v 1.164 2007/05/18 09:26:58 shane Exp $ Copyright (c) 2004-2006 Internet Systems Consortium. All rights reserved.\n";
|
||||||
#endif /* not lint */
|
#endif /* not lint */
|
||||||
|
|
||||||
#include "dhcpd.h"
|
#include "dhcpd.h"
|
||||||
@ -3805,6 +3805,7 @@ parse_ia_na_declaration(struct parse *cfile) {
|
|||||||
enum dhcp_token token;
|
enum dhcp_token token;
|
||||||
struct ia_na *ia_na;
|
struct ia_na *ia_na;
|
||||||
const char *val;
|
const char *val;
|
||||||
|
struct ia_na *old_ia_na;
|
||||||
int len;
|
int len;
|
||||||
u_int32_t iaid;
|
u_int32_t iaid;
|
||||||
struct iaddr iaddr;
|
struct iaddr iaddr;
|
||||||
@ -3959,23 +3960,42 @@ parse_ia_na_declaration(struct parse *cfile) {
|
|||||||
add_lease6(pool, iaaddr, end_time);
|
add_lease6(pool, iaaddr, end_time);
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case FTS_ABANDONED:
|
case FTS_ABANDONED:
|
||||||
decline_lease6(pool, iaaddr);
|
release_lease6(pool, iaaddr);
|
||||||
break;
|
break;
|
||||||
case FTS_EXPIRED:
|
case FTS_EXPIRED:
|
||||||
decline_lease6(pool, iaaddr);
|
decline_lease6(pool, iaaddr);
|
||||||
iaaddr->state = FTS_EXPIRED;
|
iaaddr->state = FTS_EXPIRED;
|
||||||
break;
|
break;
|
||||||
case FTS_RELEASED:
|
case FTS_RELEASED:
|
||||||
decline_lease6(pool, iaaddr);
|
release_lease6(pool, iaaddr);
|
||||||
iaaddr->state = FTS_RELEASED;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ipv6_pool_dereference(&pool, MDL);
|
ipv6_pool_dereference(&pool, MDL);
|
||||||
iaaddr_dereference(&iaaddr, MDL);
|
iaaddr_dereference(&iaaddr, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ia_na_hash_add(ia_active, (char *)ia_na->iaid_duid.data,
|
/*
|
||||||
ia_na->iaid_duid.len, ia_na, MDL);
|
* If we have an existing record for this IA_NA, remove it.
|
||||||
|
*/
|
||||||
|
old_ia_na = NULL;
|
||||||
|
if (ia_na_hash_lookup(&old_ia_na, ia_active,
|
||||||
|
(char *)ia_na->iaid_duid.data,
|
||||||
|
ia_na->iaid_duid.len, MDL)) {
|
||||||
|
ia_na_hash_delete(ia_active,
|
||||||
|
(char *)ia_na->iaid_duid.data,
|
||||||
|
ia_na->iaid_duid.len, MDL);
|
||||||
|
ia_na_remove_all_iaaddr(old_ia_na, MDL);
|
||||||
|
ia_na_dereference(&old_ia_na, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we have addresses, add this, otherwise don't bother.
|
||||||
|
*/
|
||||||
|
if (ia_na->num_iaaddr > 0) {
|
||||||
|
ia_na_hash_add(ia_active, (char *)ia_na->iaid_duid.data,
|
||||||
|
ia_na->iaid_duid.len, ia_na, MDL);
|
||||||
|
}
|
||||||
|
ia_na_dereference(&ia_na, MDL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
#ifndef lint
|
#ifndef lint
|
||||||
static char ocopyright[] =
|
static char ocopyright[] =
|
||||||
"$Id: dhcpd.c,v 1.122 2007/05/08 23:05:22 dhankins Exp $ Copyright 2004-2006 Internet Systems Consortium.";
|
"$Id: dhcpd.c,v 1.123 2007/05/18 09:26:58 shane Exp $ Copyright 2004-2006 Internet Systems Consortium.";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char copyright[] =
|
static char copyright[] =
|
||||||
@ -952,6 +952,11 @@ void postdb_startup (void)
|
|||||||
/* Initialize the failover listener state. */
|
/* Initialize the failover listener state. */
|
||||||
dhcp_failover_startup ();
|
dhcp_failover_startup ();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin our lease timeout background task.
|
||||||
|
*/
|
||||||
|
schedule_all_ipv6_lease_timeouts();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print usage message. */
|
/* Print usage message. */
|
||||||
|
@ -989,6 +989,7 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
u_int32_t iaid;
|
u_int32_t iaid;
|
||||||
struct ia_na *ia_na;
|
struct ia_na *ia_na;
|
||||||
struct ia_na *existing_ia_na;
|
struct ia_na *existing_ia_na;
|
||||||
|
struct ia_na *old_ia_na;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1548,9 +1549,21 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
* Otherwise save the IA_NA, for the same reason.
|
* Otherwise save the IA_NA, for the same reason.
|
||||||
*/
|
*/
|
||||||
else if (packet->dhcpv6_msg_type != DHCPV6_SOLICIT) {
|
else if (packet->dhcpv6_msg_type != DHCPV6_SOLICIT) {
|
||||||
ia_na_hash_delete(ia_active,
|
/*
|
||||||
(char *)ia_na->iaid_duid.data,
|
* Remove previous version of this IA_NA,
|
||||||
ia_na->iaid_duid.len, MDL);
|
* if one exists.
|
||||||
|
*/
|
||||||
|
struct data_string *d = &ia_na->iaid_duid;
|
||||||
|
old_ia_na = NULL;
|
||||||
|
if (ia_na_hash_lookup(&old_ia_na, ia_active,
|
||||||
|
(char *)d->data,
|
||||||
|
d->len, MDL)) {
|
||||||
|
ia_na_hash_delete(ia_active,
|
||||||
|
(char *)d->data,
|
||||||
|
d->len, MDL);
|
||||||
|
ia_na_dereference(&old_ia_na, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ia_na_add_iaaddr() will reference the
|
* ia_na_add_iaaddr() will reference the
|
||||||
* lease, so we need to dereference the
|
* lease, so we need to dereference the
|
||||||
@ -1570,6 +1583,7 @@ lease_to_client(struct data_string *reply_ret,
|
|||||||
ia_na->iaid_duid.len,
|
ia_na->iaid_duid.len,
|
||||||
ia_na, MDL);
|
ia_na, MDL);
|
||||||
write_ia_na(ia_na);
|
write_ia_na(ia_na);
|
||||||
|
schedule_lease_timeout(lease->ipv6_pool);
|
||||||
|
|
||||||
/* If this constitutes a binding, and we
|
/* If this constitutes a binding, and we
|
||||||
* are performing ddns updates, then give
|
* are performing ddns updates, then give
|
||||||
|
356
server/mdb6.c
356
server/mdb6.c
@ -321,6 +321,8 @@ ia_na_remove_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
|
|||||||
ia_na->iaaddr[j-1] = ia_na->iaaddr[j];
|
ia_na->iaaddr[j-1] = ia_na->iaaddr[j];
|
||||||
}
|
}
|
||||||
/* decrease our total count */
|
/* decrease our total count */
|
||||||
|
/* remove the back-reference in the IAADDR itself */
|
||||||
|
ia_na_dereference(&iaaddr->ia_na, file, line);
|
||||||
ia_na->num_iaaddr--;
|
ia_na->num_iaaddr--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -328,6 +330,19 @@ ia_na_remove_iaaddr(struct ia_na *ia_na, struct iaaddr *iaaddr,
|
|||||||
log_error("%s(%d): IAADDR not in IA_NA", file, line);
|
log_error("%s(%d): IAADDR not in IA_NA", file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
* Remove all addresses from an IA_NA.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ia_na_remove_all_iaaddr(struct ia_na *ia_na, const char *file, int line) {
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
for (i=0; i<ia_na->num_iaaddr; i++) {
|
||||||
|
iaaddr_dereference(&(ia_na->iaaddr[i]), file, line);
|
||||||
|
}
|
||||||
|
ia_na->num_iaaddr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/*
|
/*
|
||||||
* Helper function for lease heaps.
|
* Helper function for lease heaps.
|
||||||
* Makes the top of the heap the oldest lease.
|
* Makes the top of the heap the oldest lease.
|
||||||
@ -572,8 +587,7 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
|
|||||||
struct iaaddr *test_iaaddr;
|
struct iaaddr *test_iaaddr;
|
||||||
struct data_string new_ds;
|
struct data_string new_ds;
|
||||||
struct iaaddr *iaaddr;
|
struct iaaddr *iaaddr;
|
||||||
isc_result_t iaaddr_allocate_result;
|
isc_result_t result;
|
||||||
isc_result_t insert_result;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use the UID as our initial seed for the hash
|
* Use the UID as our initial seed for the hash
|
||||||
@ -616,8 +630,8 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
|
|||||||
return ISC_R_NOMEMORY;
|
return ISC_R_NOMEMORY;
|
||||||
}
|
}
|
||||||
new_ds.data = new_ds.buffer->data;
|
new_ds.data = new_ds.buffer->data;
|
||||||
memcpy((char *)new_ds.data, ds.data, ds.len);
|
memcpy(new_ds.buffer->data, ds.data, ds.len);
|
||||||
memcpy((char *)new_ds.data + ds.len, &tmp, sizeof(tmp));
|
memcpy(new_ds.buffer->data + ds.len, &tmp, sizeof(tmp));
|
||||||
data_string_forget(&ds, MDL);
|
data_string_forget(&ds, MDL);
|
||||||
data_string_copy(&ds, &new_ds, MDL);
|
data_string_copy(&ds, &new_ds, MDL);
|
||||||
data_string_forget(&new_ds, MDL);
|
data_string_forget(&new_ds, MDL);
|
||||||
@ -630,14 +644,21 @@ activate_lease6(struct ipv6_pool *pool, struct iaaddr **addr,
|
|||||||
* to hold it.
|
* to hold it.
|
||||||
*/
|
*/
|
||||||
iaaddr = NULL;
|
iaaddr = NULL;
|
||||||
iaaddr_allocate_result = iaaddr_allocate(&iaaddr, MDL);
|
result = iaaddr_allocate(&iaaddr, MDL);
|
||||||
if (iaaddr_allocate_result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
return iaaddr_allocate_result;
|
return result;
|
||||||
}
|
}
|
||||||
memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
|
memcpy(&iaaddr->addr, &tmp, sizeof(iaaddr->addr));
|
||||||
|
|
||||||
iaaddr_reference(addr, iaaddr, MDL);
|
/*
|
||||||
return add_lease6(pool, iaaddr, valid_lifetime_end_time);
|
* Add the lease to the pool.
|
||||||
|
*/
|
||||||
|
result = add_lease6(pool, iaaddr, valid_lifetime_end_time);
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
iaaddr_reference(addr, iaaddr, MDL);
|
||||||
|
}
|
||||||
|
iaaddr_dereference(&iaaddr, MDL);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -648,24 +669,58 @@ isc_result_t
|
|||||||
add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr,
|
add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr,
|
||||||
time_t valid_lifetime_end_time) {
|
time_t valid_lifetime_end_time) {
|
||||||
isc_result_t insert_result;
|
isc_result_t insert_result;
|
||||||
|
struct iaaddr *test_iaaddr;
|
||||||
|
struct iaaddr *tmp_iaaddr;
|
||||||
|
|
||||||
iaaddr->state = FTS_ACTIVE;
|
iaaddr->state = FTS_ACTIVE;
|
||||||
iaaddr->valid_lifetime_end_time = valid_lifetime_end_time;
|
iaaddr->valid_lifetime_end_time = valid_lifetime_end_time;
|
||||||
ipv6_pool_reference(&iaaddr->ipv6_pool, pool, MDL);
|
ipv6_pool_reference(&iaaddr->ipv6_pool, pool, MDL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this IAADDR is already in our structures, remove the
|
||||||
|
* old one.
|
||||||
|
*/
|
||||||
|
test_iaaddr = NULL;
|
||||||
|
if (iaaddr_hash_lookup(&test_iaaddr, pool->addrs,
|
||||||
|
&iaaddr->addr, sizeof(iaaddr->addr), MDL)) {
|
||||||
|
isc_heap_delete(pool->active_timeouts, test_iaaddr->heap_index);
|
||||||
|
iaaddr_hash_delete(pool->addrs, &test_iaaddr->addr,
|
||||||
|
sizeof(test_iaaddr->addr), MDL);
|
||||||
|
pool->num_active--;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We're going to do a bit of evil trickery here.
|
||||||
|
*
|
||||||
|
* We need to dereference the entry once to remove our
|
||||||
|
* current reference (in test_iaaddr), and then one
|
||||||
|
* more time to remove the reference left when the
|
||||||
|
* address was added to the pool before.
|
||||||
|
*/
|
||||||
|
tmp_iaaddr = test_iaaddr;
|
||||||
|
iaaddr_dereference(&test_iaaddr, MDL);
|
||||||
|
iaaddr_dereference(&tmp_iaaddr, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add IAADDR to our structures.
|
* Add IAADDR to our structures.
|
||||||
*/
|
*/
|
||||||
iaaddr_hash_add(pool->addrs, &iaaddr->addr,
|
tmp_iaaddr = NULL;
|
||||||
sizeof(iaaddr->addr), iaaddr, MDL);
|
iaaddr_reference(&tmp_iaaddr, iaaddr, MDL);
|
||||||
insert_result = isc_heap_insert(pool->active_timeouts, iaaddr);
|
iaaddr_hash_add(pool->addrs, &tmp_iaaddr->addr,
|
||||||
|
sizeof(tmp_iaaddr->addr), iaaddr, MDL);
|
||||||
|
insert_result = isc_heap_insert(pool->active_timeouts, tmp_iaaddr);
|
||||||
if (insert_result != ISC_R_SUCCESS) {
|
if (insert_result != ISC_R_SUCCESS) {
|
||||||
iaaddr_hash_delete(pool->addrs, &iaaddr->addr,
|
iaaddr_hash_delete(pool->addrs, &iaaddr->addr,
|
||||||
sizeof(iaaddr->addr), MDL);
|
sizeof(iaaddr->addr), MDL);
|
||||||
iaaddr_dereference(&iaaddr, MDL);
|
iaaddr_dereference(&tmp_iaaddr, MDL);
|
||||||
return insert_result;
|
return insert_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Note: we intentionally leave tmp_iaaddr referenced; there
|
||||||
|
* is a reference in the heap/hash, after all.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* And we're done.
|
* And we're done.
|
||||||
*/
|
*/
|
||||||
@ -673,6 +728,9 @@ add_lease6(struct ipv6_pool *pool, struct iaaddr *iaaddr,
|
|||||||
return ISC_R_SUCCESS;
|
return ISC_R_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine if an address is present in a pool or not.
|
||||||
|
*/
|
||||||
isc_boolean_t
|
isc_boolean_t
|
||||||
lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
|
lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
|
||||||
struct iaaddr *test_iaaddr;
|
struct iaaddr *test_iaaddr;
|
||||||
@ -687,6 +745,27 @@ lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Put the lease on our active pool.
|
||||||
|
*/
|
||||||
|
static isc_result_t
|
||||||
|
move_lease_to_active(struct ipv6_pool *pool, struct iaaddr *addr) {
|
||||||
|
isc_result_t insert_result;
|
||||||
|
int old_heap_index;
|
||||||
|
|
||||||
|
old_heap_index = addr->heap_index;
|
||||||
|
insert_result = isc_heap_insert(pool->active_timeouts, addr);
|
||||||
|
if (insert_result == ISC_R_SUCCESS) {
|
||||||
|
iaaddr_hash_add(pool->addrs, &addr->addr,
|
||||||
|
sizeof(addr->addr), addr, MDL);
|
||||||
|
isc_heap_delete(pool->inactive_timeouts, old_heap_index);
|
||||||
|
pool->num_active++;
|
||||||
|
pool->num_inactive--;
|
||||||
|
addr->state = FTS_ACTIVE;
|
||||||
|
}
|
||||||
|
return insert_result;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Renew an lease in the pool.
|
* Renew an lease in the pool.
|
||||||
*
|
*
|
||||||
@ -694,58 +773,22 @@ lease6_exists(const struct ipv6_pool *pool, const struct in6_addr *addr) {
|
|||||||
* and then invoke renew_lease() on the address.
|
* and then invoke renew_lease() on the address.
|
||||||
*
|
*
|
||||||
* WARNING: lease times must only be extended, never reduced!!!
|
* WARNING: lease times must only be extended, never reduced!!!
|
||||||
*
|
|
||||||
* We return a isc_result_t so this function can be called the same
|
|
||||||
* as release or decline.
|
|
||||||
*/
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
renew_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
renew_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
||||||
isc_heap_decreased(pool->active_timeouts, addr->heap_index);
|
/*
|
||||||
return ISC_R_SUCCESS;
|
* If we're already active, then we can just move our expiration
|
||||||
}
|
* time down the heap.
|
||||||
|
*
|
||||||
/*
|
* Otherwise, we have to move from the inactive heap to the
|
||||||
* Expire the oldest lease if it's lifetime_end_time is
|
* active heap.
|
||||||
* older than the given time.
|
*/
|
||||||
*
|
if (addr->state == FTS_ACTIVE) {
|
||||||
* - iaaddr must be a pointer to a (struct iaaddr *) pointer previously
|
isc_heap_decreased(pool->active_timeouts, addr->heap_index);
|
||||||
* initialized to NULL
|
return ISC_R_SUCCESS;
|
||||||
*
|
} else {
|
||||||
* On return iaaddr has a reference to the removed entry. It is left
|
return move_lease_to_active(pool, addr);
|
||||||
* pointing to NULL if the oldest lease has not expired.
|
|
||||||
*/
|
|
||||||
isc_result_t
|
|
||||||
expire_lease6(struct iaaddr **addr, struct ipv6_pool *pool, time_t now) {
|
|
||||||
struct iaaddr *tmp;
|
|
||||||
isc_result_t insert_result;
|
|
||||||
|
|
||||||
if (addr == NULL) {
|
|
||||||
log_error("%s(%d): NULL pointer reference", MDL);
|
|
||||||
return ISC_R_INVALIDARG;
|
|
||||||
}
|
}
|
||||||
if (*addr != NULL) {
|
|
||||||
log_error("%s(%d): non-NULL pointer", MDL);
|
|
||||||
return ISC_R_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pool->num_active > 0) {
|
|
||||||
tmp = (struct iaaddr *)isc_heap_element(pool->active_timeouts,
|
|
||||||
1);
|
|
||||||
if (now > tmp->valid_lifetime_end_time) {
|
|
||||||
insert_result = isc_heap_insert(pool->inactive_timeouts,
|
|
||||||
tmp);
|
|
||||||
if (insert_result != ISC_R_SUCCESS) {
|
|
||||||
return insert_result;
|
|
||||||
}
|
|
||||||
iaaddr_hash_delete(pool->addrs,
|
|
||||||
&tmp->addr, sizeof(tmp->addr), MDL);
|
|
||||||
isc_heap_delete(pool->active_timeouts, 1);
|
|
||||||
tmp->state = FTS_EXPIRED;
|
|
||||||
iaaddr_reference(addr, tmp, MDL);
|
|
||||||
pool->num_active--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ISC_R_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -765,16 +808,64 @@ move_lease_to_inactive(struct ipv6_pool *pool, struct iaaddr *addr,
|
|||||||
isc_heap_delete(pool->active_timeouts, old_heap_index);
|
isc_heap_delete(pool->active_timeouts, old_heap_index);
|
||||||
addr->state = state;
|
addr->state = state;
|
||||||
pool->num_active--;
|
pool->num_active--;
|
||||||
|
pool->num_inactive++;
|
||||||
}
|
}
|
||||||
return insert_result;
|
return insert_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expire the oldest lease if it's lifetime_end_time is
|
||||||
|
* older than the given time.
|
||||||
|
*
|
||||||
|
* - iaaddr must be a pointer to a (struct iaaddr *) pointer previously
|
||||||
|
* initialized to NULL
|
||||||
|
*
|
||||||
|
* On return iaaddr has a reference to the removed entry. It is left
|
||||||
|
* pointing to NULL if the oldest lease has not expired.
|
||||||
|
*/
|
||||||
|
isc_result_t
|
||||||
|
expire_lease6(struct iaaddr **addr, struct ipv6_pool *pool, time_t now) {
|
||||||
|
struct iaaddr *tmp;
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
if (addr == NULL) {
|
||||||
|
log_error("%s(%d): NULL pointer reference", MDL);
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
}
|
||||||
|
if (*addr != NULL) {
|
||||||
|
log_error("%s(%d): non-NULL pointer", MDL);
|
||||||
|
return ISC_R_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pool->num_active > 0) {
|
||||||
|
tmp = (struct iaaddr *)isc_heap_element(pool->active_timeouts,
|
||||||
|
1);
|
||||||
|
if (now > tmp->valid_lifetime_end_time) {
|
||||||
|
result = move_lease_to_inactive(pool, tmp, FTS_EXPIRED);
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
iaaddr_reference(addr, tmp, MDL);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For a declined lease, leave it on the "active" pool, but mark
|
* For a declined lease, leave it on the "active" pool, but mark
|
||||||
* it as declined. Give it an infinite (well, really long) life.
|
* it as declined. Give it an infinite (well, really long) life.
|
||||||
*/
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
decline_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
decline_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
||||||
|
isc_result_t result;
|
||||||
|
|
||||||
|
if (addr->state != FTS_ACTIVE) {
|
||||||
|
result = move_lease_to_active(pool, addr);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
addr->state = FTS_ABANDONED;
|
addr->state = FTS_ABANDONED;
|
||||||
addr->valid_lifetime_end_time = MAX_TIME;
|
addr->valid_lifetime_end_time = MAX_TIME;
|
||||||
isc_heap_decreased(pool->active_timeouts, addr->heap_index);
|
isc_heap_decreased(pool->active_timeouts, addr->heap_index);
|
||||||
@ -786,7 +877,11 @@ decline_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
|||||||
*/
|
*/
|
||||||
isc_result_t
|
isc_result_t
|
||||||
release_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
release_lease6(struct ipv6_pool *pool, struct iaaddr *addr) {
|
||||||
return move_lease_to_inactive(pool, addr, FTS_RELEASED);
|
if (addr->state == FTS_ACTIVE) {
|
||||||
|
return move_lease_to_inactive(pool, addr, FTS_RELEASED);
|
||||||
|
} else {
|
||||||
|
return ISC_R_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -835,34 +930,127 @@ add_ipv6_pool(struct ipv6_pool *pool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_old_expired(struct ipv6_pool *pool) {
|
||||||
|
struct iaaddr *tmp;
|
||||||
|
struct ia_na *ia_na;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
isc_heap_delete(pool->inactive_timeouts, tmp->heap_index);
|
||||||
|
pool->num_inactive--;
|
||||||
|
|
||||||
|
ia_na = NULL;
|
||||||
|
ia_na_reference(&ia_na, tmp->ia_na, MDL);
|
||||||
|
ia_na_remove_iaaddr(ia_na, tmp, MDL);
|
||||||
|
iaaddr_dereference(&tmp, MDL);
|
||||||
|
if (ia_na->num_iaaddr <= 0) {
|
||||||
|
ia_na_hash_delete(ia_active,
|
||||||
|
(char *)ia_na->iaid_duid.data,
|
||||||
|
ia_na->iaid_duid.len, MDL);
|
||||||
|
}
|
||||||
|
ia_na_dereference(&ia_na, MDL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lease_timeout_support(void *vpool) {
|
||||||
|
struct ipv6_pool *pool;
|
||||||
|
struct iaaddr *addr;
|
||||||
|
|
||||||
|
pool = (struct ipv6_pool *)vpool;
|
||||||
|
for (;;) {
|
||||||
|
/*
|
||||||
|
* Get the next lease scheduled to expire.
|
||||||
|
*
|
||||||
|
* Note that if there are no leases in the pool,
|
||||||
|
* expire_lease6() will return ISC_R_SUCCESS with
|
||||||
|
* a NULL lease.
|
||||||
|
*/
|
||||||
|
addr = NULL;
|
||||||
|
if (expire_lease6(&addr, pool, cur_time) != ISC_R_SUCCESS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (addr == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look to see if there were ddns updates, and if
|
||||||
|
* so, drop them.
|
||||||
|
*
|
||||||
|
* DH: Do we want to do this on a special 'depref'
|
||||||
|
* timer rather than expiration timer?
|
||||||
|
*/
|
||||||
|
ddns_removals(NULL, addr);
|
||||||
|
|
||||||
|
write_ia_na(addr->ia_na);
|
||||||
|
|
||||||
|
iaaddr_dereference(&addr, MDL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Do some cleanup of our expired leases.
|
||||||
|
*/
|
||||||
|
cleanup_old_expired(pool);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Schedule next round of expirations.
|
||||||
|
*/
|
||||||
|
schedule_lease_timeout(pool);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove all leases that have expired from the active pool.
|
* For a given pool, add a timer that will remove the next
|
||||||
|
* lease to expire.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
expire_leases(time_t now) {
|
schedule_lease_timeout(struct ipv6_pool *pool) {
|
||||||
struct ipv6_pool *pool;
|
struct iaaddr *tmp;
|
||||||
|
time_t timeout;
|
||||||
|
time_t next_timeout;
|
||||||
|
|
||||||
|
next_timeout = MAX_TIME;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (timeout < next_timeout) {
|
||||||
|
next_timeout = timeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (next_timeout < MAX_TIME) {
|
||||||
|
add_timeout(next_timeout, lease_timeout_support, pool,
|
||||||
|
(tvref_t)ipv6_pool_reference,
|
||||||
|
(tvunref_t)ipv6_pool_dereference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Schedule timeouts across all pools.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
schedule_all_ipv6_lease_timeouts(void) {
|
||||||
int i;
|
int i;
|
||||||
struct iaaddr *addr;
|
|
||||||
|
|
||||||
for (i=0; i<num_pools; i++) {
|
for (i=0; i<num_pools; i++) {
|
||||||
pool = pools[i];
|
schedule_lease_timeout(pools[i]);
|
||||||
for (;;) {
|
|
||||||
addr = NULL;
|
|
||||||
if (expire_lease6(&addr, pool, now) != ISC_R_SUCCESS) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (addr == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Look to see if there were ddns updates, and if
|
|
||||||
* so, drop them.
|
|
||||||
*
|
|
||||||
* DH: Do we want to do this on a special 'depref'
|
|
||||||
* timer rather than expiration timer?
|
|
||||||
*/
|
|
||||||
ddns_removals(NULL, addr);
|
|
||||||
iaaddr_dereference(&addr, MDL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user