aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2012-09-11 10:41:11 +0200
committerMartin Willi <martin@revosec.ch>2012-09-11 16:18:28 +0200
commit594c58e1118e496eadd284647755b16b74665337 (patch)
tree743e0f33a01beffab57e363fe1e154944c63dd01
parentdc7b79d8a5c8104001bba4c52a8b3716a0cf6d88 (diff)
downloadstrongswan-594c58e1118e496eadd284647755b16b74665337.tar.bz2
strongswan-594c58e1118e496eadd284647755b16b74665337.tar.xz
Pass the full list of pools to acquire_address, enumerate in providers
If the provider has access to the full pool list, it can enumerate them twice, for example to search for existing leases first, and only search for new leases in a second step. Fixes lease enumeration in attr-sql using multiple pools.
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_provider.c28
-rw-r--r--src/libcharon/plugins/ha/ha_attribute.c18
-rw-r--r--src/libcharon/plugins/stroke/stroke_attribute.c20
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_pool.c9
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c26
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_config.c26
-rw-r--r--src/libhydra/attributes/attribute_manager.c6
-rw-r--r--src/libhydra/attributes/attribute_manager.h4
-rw-r--r--src/libhydra/attributes/attribute_provider.h4
-rw-r--r--src/libhydra/plugins/attr_sql/sql_attribute.c41
10 files changed, 109 insertions, 73 deletions
diff --git a/src/libcharon/plugins/dhcp/dhcp_provider.c b/src/libcharon/plugins/dhcp/dhcp_provider.c
index e46cc4d90..eaaad45d1 100644
--- a/src/libcharon/plugins/dhcp/dhcp_provider.c
+++ b/src/libcharon/plugins/dhcp/dhcp_provider.c
@@ -81,18 +81,29 @@ static uintptr_t hash_transaction(dhcp_transaction_t *transaction)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_dhcp_provider_t *this, char *pool,
+ private_dhcp_provider_t *this, linked_list_t *pools,
identification_t *id, host_t *requested)
{
- if (streq(pool, "dhcp") && requested->get_family(requested) == AF_INET)
- {
- dhcp_transaction_t *transaction, *old;
- host_t *vip;
+ dhcp_transaction_t *transaction, *old;
+ enumerator_t *enumerator;
+ char *pool;
+ host_t *vip = NULL;
+ if (requested->get_family(requested) != AF_INET)
+ {
+ return NULL;
+ }
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &pool))
+ {
+ if (!streq(pool, "dhcp"))
+ {
+ continue;
+ }
transaction = this->socket->enroll(this->socket, id);
if (!transaction)
{
- return NULL;
+ continue;
}
vip = transaction->get_address(transaction);
vip = vip->clone(vip);
@@ -101,9 +112,10 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
(void*)hash_transaction(transaction), transaction);
this->mutex->unlock(this->mutex);
DESTROY_IF(old);
- return vip;
+ break;
}
- return NULL;
+ enumerator->destroy(enumerator);
+ return vip;
}
METHOD(attribute_provider_t, release_address, bool,
diff --git a/src/libcharon/plugins/ha/ha_attribute.c b/src/libcharon/plugins/ha/ha_attribute.c
index f18c58b6a..d9f460ade 100644
--- a/src/libcharon/plugins/ha/ha_attribute.c
+++ b/src/libcharon/plugins/ha/ha_attribute.c
@@ -170,22 +170,28 @@ static bool responsible_for(private_ha_attribute_t *this, int bit)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_ha_attribute_t *this, char *name, identification_t *id,
+ private_ha_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
+ enumerator_t *enumerator;
pool_t *pool;
int offset = -1, byte, bit;
host_t *address;
+ char *name;
+ enumerator = pools->create_enumerator(pools);
this->mutex->lock(this->mutex);
- pool = get_pool(this, name);
- if (pool)
+ while (enumerator->enumerate(enumerator, &name))
{
+ pool = get_pool(this, name);
+ if (!pool)
+ {
+ continue;
+ }
if (pool->base->get_family(pool->base) !=
requested->get_family(requested))
{
- this->mutex->unlock(this->mutex);
- return NULL;
+ continue;
}
for (byte = 0; byte < pool->size / 8; byte++)
{
@@ -214,6 +220,8 @@ METHOD(attribute_provider_t, acquire_address, host_t*,
}
}
this->mutex->unlock(this->mutex);
+ enumerator->destroy(enumerator);
+
if (offset != -1)
{
address = offset2host(pool, offset);
diff --git a/src/libcharon/plugins/stroke/stroke_attribute.c b/src/libcharon/plugins/stroke/stroke_attribute.c
index fa58a24e3..99392bfd7 100644
--- a/src/libcharon/plugins/stroke/stroke_attribute.c
+++ b/src/libcharon/plugins/stroke/stroke_attribute.c
@@ -90,19 +90,31 @@ static mem_pool_t *find_pool(private_stroke_attribute_t *this, char *name)
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_stroke_attribute_t *this, char *name, identification_t *id,
+ private_stroke_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
+ enumerator_t *enumerator;
mem_pool_t *pool;
host_t *addr = NULL;
+ char *name;
+ enumerator = pools->create_enumerator(pools);
this->lock->read_lock(this->lock);
- pool = find_pool(this, name);
- if (pool)
+ while (enumerator->enumerate(enumerator, &name))
{
- addr = pool->acquire_address(pool, id, requested);
+ pool = find_pool(this, name);
+ if (pool)
+ {
+ addr = pool->acquire_address(pool, id, requested);
+ if (addr)
+ {
+ break;
+ }
+ }
}
this->lock->unlock(this->lock);
+ enumerator->destroy(enumerator);
+
return addr;
}
diff --git a/src/libcharon/plugins/unit_tester/tests/test_pool.c b/src/libcharon/plugins/unit_tester/tests/test_pool.c
index a68246fff..f67353dff 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_pool.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_pool.c
@@ -27,6 +27,7 @@ static void* testing(void *thread)
int i;
host_t *addr[ALLOCS];
identification_t *id[ALLOCS];
+ linked_list_t *pools;
/* prepare identities */
for (i = 0; i < ALLOCS; i++)
@@ -37,17 +38,23 @@ static void* testing(void *thread)
id[i] = identification_create_from_string(buf);
}
+ pools = linked_list_create();
+ pools->insert_last(pools, "test");
+
/* allocate addresses */
for (i = 0; i < ALLOCS; i++)
{
addr[i] = hydra->attributes->acquire_address(hydra->attributes,
- "test", id[i], NULL);
+ pools, id[i], NULL);
if (!addr[i])
{
+ pools->destroy(pools);
return (void*)FALSE;
}
}
+ pools->destroy(pools);
+
/* release addresses */
for (i = 0; i < ALLOCS; i++)
{
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index a134ad562..6a5bac92a 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -330,29 +330,23 @@ METHOD(task_t, build_r, status_t,
id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
vips = linked_list_create();
- pools = linked_list_create();
+ pools = linked_list_create_from_enumerator(
+ config->create_pool_enumerator(config));
this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &requested))
{
- enumerator_t *poolenum;
- char *pool;
host_t *found = NULL;
/* query all pools until we get an address */
DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
- poolenum = config->create_pool_enumerator(config);
- while (poolenum->enumerate(poolenum, &pool))
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pools, id, requested);
+ if (found)
{
- found = hydra->attributes->acquire_address(hydra->attributes,
- pool, id, requested);
- if (!found)
- {
- continue;
- }
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
if (!cp)
@@ -360,17 +354,9 @@ METHOD(task_t, build_r, status_t,
cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
}
cp->add_attribute(cp, build_vip(found));
- /* use pool to request other attributes */
- if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
- {
- pools->insert_last(pools, pool);
- }
vips->insert_last(vips, found);
- break;
}
- poolenum->destroy(poolenum);
-
- if (!found)
+ else
{
DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
requested, id);
diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index fbfcb0ea9..d624fd170 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -342,29 +342,23 @@ METHOD(task_t, build_r, status_t,
id = this->ike_sa->get_other_eap_id(this->ike_sa);
config = this->ike_sa->get_peer_cfg(this->ike_sa);
vips = linked_list_create();
- pools = linked_list_create();
+ pools = linked_list_create_from_enumerator(
+ config->create_pool_enumerator(config));
this->ike_sa->clear_virtual_ips(this->ike_sa, FALSE);
enumerator = this->vips->create_enumerator(this->vips);
while (enumerator->enumerate(enumerator, &requested))
{
- enumerator_t *poolenum;
- char *pool;
host_t *found = NULL;
/* query all pools until we get an address */
DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
- poolenum = config->create_pool_enumerator(config);
- while (poolenum->enumerate(poolenum, &pool))
+ found = hydra->attributes->acquire_address(hydra->attributes,
+ pools, id, requested);
+ if (found)
{
- found = hydra->attributes->acquire_address(hydra->attributes,
- pool, id, requested);
- if (!found)
- {
- continue;
- }
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
this->ike_sa->add_virtual_ip(this->ike_sa, FALSE, found);
if (!cp)
@@ -372,17 +366,9 @@ METHOD(task_t, build_r, status_t,
cp = cp_payload_create_type(CONFIGURATION, CFG_REPLY);
}
cp->add_attribute(cp, build_vip(found));
- /* use pool to request other attributes */
- if (pools->find_first(pools, NULL, (void**)&pool) == NOT_FOUND)
- {
- pools->insert_last(pools, pool);
- }
vips->insert_last(vips, found);
- break;
}
- poolenum->destroy(poolenum);
-
- if (!found)
+ else
{
DBG1(DBG_IKE, "no virtual IP found for %H requested by '%Y'",
requested, id);
diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c
index 64dc9c7c9..e7a687a50 100644
--- a/src/libhydra/attributes/attribute_manager.c
+++ b/src/libhydra/attributes/attribute_manager.c
@@ -60,8 +60,8 @@ typedef struct {
} enum_data_t;
METHOD(attribute_manager_t, acquire_address, host_t*,
- private_attribute_manager_t *this, char *pool, identification_t *id,
- host_t *requested)
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested)
{
enumerator_t *enumerator;
attribute_provider_t *current;
@@ -71,7 +71,7 @@ METHOD(attribute_manager_t, acquire_address, host_t*,
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
- host = current->acquire_address(current, pool, id, requested);
+ host = current->acquire_address(current, pools, id, requested);
if (host)
{
break;
diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h
index 8bc80ca11..45e5a40f1 100644
--- a/src/libhydra/attributes/attribute_manager.h
+++ b/src/libhydra/attributes/attribute_manager.h
@@ -39,13 +39,13 @@ struct attribute_manager_t {
/**
* Acquire a virtual IP address to assign to a peer.
*
- * @param pool pool name to acquire address from
+ * @param pools list of pool names (char*) to acquire from
* @param id peer identity to get address forua
* @param requested IP in configuration request
* @return allocated address, NULL to serve none
*/
host_t* (*acquire_address)(attribute_manager_t *this,
- char *pool, identification_t *id,
+ linked_list_t *pool, identification_t *id,
host_t *requested);
/**
diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h
index 327135ffe..7d0acdbac 100644
--- a/src/libhydra/attributes/attribute_provider.h
+++ b/src/libhydra/attributes/attribute_provider.h
@@ -35,13 +35,13 @@ struct attribute_provider_t {
/**
* Acquire a virtual IP address to assign to a peer.
*
- * @param pool name of the pool to acquire address from
+ * @param pools list of pool names (char*) to acquire from
* @param id peer ID
* @param requested IP in configuration request
* @return allocated address, NULL to serve none
*/
host_t* (*acquire_address)(attribute_provider_t *this,
- char *pool, identification_t *id,
+ linked_list_t *pools, identification_t *id,
host_t *requested);
/**
* Release a previously acquired address.
diff --git a/src/libhydra/plugins/attr_sql/sql_attribute.c b/src/libhydra/plugins/attr_sql/sql_attribute.c
index 8055be71c..28e59850e 100644
--- a/src/libhydra/plugins/attr_sql/sql_attribute.c
+++ b/src/libhydra/plugins/attr_sql/sql_attribute.c
@@ -233,25 +233,50 @@ static host_t* get_lease(private_sql_attribute_t *this, char *name,
}
METHOD(attribute_provider_t, acquire_address, host_t*,
- private_sql_attribute_t *this, char *name, identification_t *id,
+ private_sql_attribute_t *this, linked_list_t *pools, identification_t *id,
host_t *requested)
{
+ enumerator_t *enumerator;
host_t *address = NULL;
u_int identity, pool, timeout;
+ char *name;
identity = get_identity(this, id);
if (identity)
{
- pool = get_pool(this, name, &timeout);
- if (pool)
+ /* check for an existing lease in all pools */
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
{
- /* check for an existing lease */
- address = check_lease(this, name, pool, identity);
- if (address == NULL)
+ pool = get_pool(this, name, &timeout);
+ if (pool)
{
- /* get an unallocated address or expired lease */
- address = get_lease(this, name, pool, timeout, identity);
+ address = check_lease(this, name, pool, identity);
+ if (address)
+ {
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (!address)
+ {
+ /* get an unallocated address or expired lease */
+ enumerator = pools->create_enumerator(pools);
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = get_pool(this, name, &timeout);
+ if (pool)
+ {
+ address = get_lease(this, name, pool, timeout, identity);
+ if (address)
+ {
+ break;
+ }
+ }
}
+ enumerator->destroy(enumerator);
}
}
return address;