aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Steffen <andreas.steffen@strongswan.org>2009-07-17 11:48:35 +0200
committerAndreas Steffen <andreas.steffen@strongswan.org>2009-07-17 11:48:35 +0200
commit7f522b5fd8bef0c287e2db60ed9d1acea13e24cb (patch)
tree544e167e6b2526c19a29c38ec2db383c6a487442
parent07be083b7fdb54144c718f81931e6981ad2c7550 (diff)
downloadstrongswan-7f522b5fd8bef0c287e2db60ed9d1acea13e24cb.tar.bz2
strongswan-7f522b5fd8bef0c287e2db60ed9d1acea13e24cb.tar.xz
check for an existing lease over all assigned pools first
-rw-r--r--src/charon/plugins/sql/sql_attribute.c79
1 files changed, 55 insertions, 24 deletions
diff --git a/src/charon/plugins/sql/sql_attribute.c b/src/charon/plugins/sql/sql_attribute.c
index fa728eab6..d358c3b12 100644
--- a/src/charon/plugins/sql/sql_attribute.c
+++ b/src/charon/plugins/sql/sql_attribute.c
@@ -92,25 +92,18 @@ static u_int get_pool(private_sql_attribute_t *this, char *name, u_int *timeout)
}
/**
- * Lookup a lease
+ * Look up an existing lease
*/
-static host_t *get_address(private_sql_attribute_t *this, char *name,
- u_int pool, u_int timeout, u_int identity)
+static host_t* check_lease(private_sql_attribute_t *this, char *name,
+ u_int pool, u_int identity)
{
- enumerator_t *e;
- u_int id;
- chunk_t address;
- host_t *host;
- time_t now = time(NULL);
-
- /* We check for leases for that identity first and for other expired
- * leases afterwards. We select an address as a candidate, but double
- * check if it is still valid in the update. This allows us to work
- * without locking. */
-
- /* check for an existing lease for that identity */
while (TRUE)
{
+ u_int id;
+ chunk_t address;
+ enumerator_t *e;
+ time_t now = time(NULL);
+
e = this->db->query(this->db,
"SELECT id, address FROM addresses "
"WHERE pool = ? AND identity = ? AND released != 0 LIMIT 1",
@@ -122,11 +115,14 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
}
address = chunk_clonea(address);
e->destroy(e);
+
if (this->db->execute(this->db, NULL,
"UPDATE addresses SET acquired = ?, released = 0 "
"WHERE id = ? AND identity = ? AND released != 0",
DB_UINT, now, DB_UINT, id, DB_UINT, identity) > 0)
{
+ host_t *host;
+
host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
@@ -136,10 +132,23 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
}
}
}
-
- /* check for an available address */
+ return NULL;
+}
+
+/**
+ * We check for unallocated addresses or expired leases. First we select an
+ * address as a candidate, but double check later on if it is still available
+ * during the update operation. This allows us to work without locking.
+ */
+static host_t* get_lease(private_sql_attribute_t *this, char *name,
+ u_int pool, u_int timeout, u_int identity)
+{
while (TRUE)
{
+ u_int id;
+ chunk_t address;
+ enumerator_t *e;
+ time_t now = time(NULL);
int hits;
if (timeout)
@@ -187,6 +196,8 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
}
if (hits > 0)
{
+ host_t *host;
+
host = host_create_from_chunk(AF_UNSPEC, address, 0);
if (host)
{
@@ -197,30 +208,50 @@ static host_t *get_address(private_sql_attribute_t *this, char *name,
}
}
DBG1(DBG_CFG, "no available address found in pool '%s'", name);
- return 0;
+ return NULL;
}
/**
* Implementation of attribute_provider_t.acquire_address
*/
static host_t* acquire_address(private_sql_attribute_t *this,
- char *name, identification_t *id,
+ char *names, identification_t *id,
host_t *requested)
{
- enumerator_t *enumerator;
- u_int pool, timeout, identity;
host_t *address = NULL;
-
+ u_int identity, pool, timeout;
+
identity = get_identity(this, id);
if (identity)
{
- enumerator = enumerator_create_token(name, ",", " ");
+ char *name;
+ enumerator_t *enumerator;
+
+ /* in a first step check for an existing lease over all pools */
+ enumerator = enumerator_create_token(names, ",", " ");
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ pool = get_pool(this, name, &timeout);
+ if (pool)
+ {
+ address = check_lease(this, name, pool, identity);
+ if (address)
+ {
+ enumerator->destroy(enumerator);
+ return address;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* in a second step get an unallocated address or expired lease */
+ enumerator = enumerator_create_token(names, ",", " ");
while (enumerator->enumerate(enumerator, &name))
{
pool = get_pool(this, name, &timeout);
if (pool)
{
- address = get_address(this, name, pool, timeout, identity);
+ address = get_lease(this, name, pool, timeout, identity);
if (address)
{
break;