aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-07-24 15:45:39 +0200
committerMartin Willi <martin@revosec.ch>2013-07-26 13:12:22 +0200
commitd882880e87466affbf4e472cae16c8a5405ea8c2 (patch)
treeafb0105c6ed2389be2666b815847a45103317212 /src
parent77ccff82cfb0045aad83d0424498f87ec9f60070 (diff)
downloadstrongswan-d882880e87466affbf4e472cae16c8a5405ea8c2.tar.bz2
strongswan-d882880e87466affbf4e472cae16c8a5405ea8c2.tar.xz
mem-pool: refcount online lease when reassigning it to another tunnel
When we reassign an online lease for the same peer, we have to refcount it. Otherwise we would set it offline if one of the tunnels goes down, but it is actually still in use by a the second tunnel. This can finally lead in assigning the same virtual IP to different peers.
Diffstat (limited to 'src')
-rw-r--r--src/libhydra/attributes/mem_pool.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c
index c82b1d02f..16a5b519c 100644
--- a/src/libhydra/attributes/mem_pool.c
+++ b/src/libhydra/attributes/mem_pool.c
@@ -251,6 +251,8 @@ static int get_existing(private_mem_pool_t *this, identification_t *id,
if (current == host2offset(this, requested))
{
offset = current;
+ /* add an additional "online" entry */
+ entry->online->insert_last(entry->online, (void*)current);
break;
}
}
@@ -377,9 +379,10 @@ METHOD(mem_pool_t, acquire_address, host_t*,
METHOD(mem_pool_t, release_address, bool,
private_mem_pool_t *this, host_t *address, identification_t *id)
{
- bool found = FALSE;
+ enumerator_t *enumerator;
+ bool found = FALSE, more = FALSE;
entry_t *entry;
- uintptr_t offset;
+ uintptr_t offset, current;
if (this->size != 0)
{
@@ -388,11 +391,31 @@ METHOD(mem_pool_t, release_address, bool,
if (entry)
{
offset = host2offset(this, address);
- if (entry->online->remove(entry->online, (void*)offset, NULL) > 0)
+
+ enumerator = entry->online->create_enumerator(entry->online);
+ while (enumerator->enumerate(enumerator, &current))
{
- DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
+ if (current == offset)
+ {
+ if (!found)
+ { /* remove the first entry only */
+ entry->online->remove_at(entry->online, enumerator);
+ found = TRUE;
+ }
+ else
+ { /* but check for more entries */
+ more = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (found && !more)
+ {
+ /* no tunnels are online anymore for this lease, make offline */
entry->offline->insert_last(entry->offline, (void*)offset);
- found = TRUE;
+ DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
}
}
this->mutex->unlock(this->mutex);