aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2008-12-04 16:46:08 +0000
committerTobias Brunner <tobias@strongswan.org>2008-12-04 16:46:08 +0000
commit3fb404d8da1e964f4edb5e2e555b11df1f54a2a1 (patch)
treef754dcbd005c59f9dc1d3ccbf24c75194eec364b /src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
parentffa645069557df1beca1d3671619b0290442a805 (diff)
downloadstrongswan-3fb404d8da1e964f4edb5e2e555b11df1f54a2a1.tar.bz2
strongswan-3fb404d8da1e964f4edb5e2e555b11df1f54a2a1.tar.xz
implemented the policy cache in kernel_netlink_ipsec_t with a hash table instead of a linked list.
Diffstat (limited to 'src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c')
-rw-r--r--src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c95
1 files changed, 54 insertions, 41 deletions
diff --git a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 2abbab477..8c472f2ce 100644
--- a/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/charon/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -39,7 +39,7 @@
#include <daemon.h>
#include <utils/mutex.h>
-#include <utils/linked_list.h>
+#include <utils/hashtable.h>
#include <processing/jobs/callback_job.h>
#include <processing/jobs/acquire_job.h>
#include <processing/jobs/migrate_job.h>
@@ -250,6 +250,24 @@ struct policy_entry_t {
u_int refcount;
};
+/**
+ * Hash function for policy_entry_t objects
+ */
+static u_int policy_hash(policy_entry_t *key)
+{
+ chunk_t chunk = chunk_create((void*)&key->sel, sizeof(struct xfrm_selector));
+ return chunk_hash(chunk);
+}
+
+/**
+ * Equality function for policy_entry_t objects
+ */
+static bool policy_equals(policy_entry_t *key, policy_entry_t *other_key)
+{
+ return memeq(&key->sel, &other_key->sel, sizeof(struct xfrm_selector)) &&
+ key->direction == other_key->direction;
+}
+
typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t;
/**
@@ -267,9 +285,9 @@ struct private_kernel_netlink_ipsec_t {
mutex_t *mutex;
/**
- * List of installed policies (policy_entry_t)
+ * Hash table of installed policies (policy_entry_t)
*/
- linked_list_t *policies;
+ hashtable_t *policies;
/**
* job receiving netlink events
@@ -1396,7 +1414,6 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
ipsec_mode_t mode, u_int16_t ipcomp, u_int16_t cpi,
bool routed)
{
- iterator_t *iterator;
policy_entry_t *current, *policy;
bool found = FALSE;
netlink_buf_t request;
@@ -1411,27 +1428,21 @@ static status_t add_policy(private_kernel_netlink_ipsec_t *this,
/* find the policy, which matches EXACTLY */
this->mutex->lock(this->mutex);
- iterator = this->policies->create_iterator(this->policies, TRUE);
- while (iterator->iterate(iterator, (void**)&current))
+ current = this->policies->get(this->policies, policy);
+ if (current)
{
- if (memeq(&current->sel, &policy->sel, sizeof(struct xfrm_selector)) &&
- policy->direction == current->direction)
- {
- /* use existing policy */
- current->refcount++;
- DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
- "refcount", src_ts, dst_ts,
- policy_dir_names, direction);
- free(policy);
- policy = current;
- found = TRUE;
- break;
- }
+ /* use existing policy */
+ current->refcount++;
+ DBG2(DBG_KNL, "policy %R === %R %N already exists, increasing "
+ "refcount", src_ts, dst_ts,
+ policy_dir_names, direction);
+ free(policy);
+ policy = current;
+ found = TRUE;
}
- iterator->destroy(iterator);
- if (!found)
+ else
{ /* apply the new one, if we have no such policy */
- this->policies->insert_last(this->policies, policy);
+ this->policies->put(this->policies, policy, policy);
policy->refcount = 1;
}
@@ -1659,7 +1670,6 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
netlink_buf_t request;
struct nlmsghdr *hdr;
struct xfrm_userpolicy_id *policy_id;
- enumerator_t *enumerator;
DBG2(DBG_KNL, "deleting policy %R === %R %N", src_ts, dst_ts,
policy_dir_names, direction);
@@ -1671,28 +1681,21 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
/* find the policy */
this->mutex->lock(this->mutex);
- enumerator = this->policies->create_enumerator(this->policies);
- while (enumerator->enumerate(enumerator, &current))
+ current = this->policies->get(this->policies, &policy);
+ if (current)
{
- if (memeq(&current->sel, &policy.sel, sizeof(struct xfrm_selector)) &&
- policy.direction == current->direction)
+ to_delete = current;
+ if (--to_delete->refcount > 0)
{
- to_delete = current;
- if (--to_delete->refcount > 0)
- {
- /* is used by more SAs, keep in kernel */
- DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
- this->mutex->unlock(this->mutex);
- enumerator->destroy(enumerator);
- return SUCCESS;
- }
- /* remove if last reference */
- this->policies->remove_at(this->policies, enumerator);
- break;
+ /* is used by more SAs, keep in kernel */
+ DBG2(DBG_KNL, "policy still used by another CHILD_SA, not removed");
+ this->mutex->unlock(this->mutex);
+ return SUCCESS;
}
+ /* remove if last reference */
+ this->policies->remove(this->policies, to_delete);
}
this->mutex->unlock(this->mutex);
- enumerator->destroy(enumerator);
if (!to_delete)
{
DBG1(DBG_KNL, "deleting policy %R === %R %N failed, not found", src_ts,
@@ -1741,9 +1744,18 @@ static status_t del_policy(private_kernel_netlink_ipsec_t *this,
*/
static void destroy(private_kernel_netlink_ipsec_t *this)
{
+ enumerator_t *enumerator;
+ policy_entry_t *policy;
+
this->job->cancel(this->job);
close(this->socket_xfrm_events);
this->socket_xfrm->destroy(this->socket_xfrm);
+ enumerator = this->policies->create_enumerator(this->policies);
+ while (enumerator->enumerate(enumerator, (void**)&policy))
+ {
+ free(policy);
+ }
+ enumerator->destroy(enumerator);
this->policies->destroy(this->policies);
this->mutex->destroy(this->mutex);
free(this);
@@ -1834,7 +1846,8 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create()
this->public.interface.destroy = (void(*)(kernel_ipsec_t*)) destroy;
/* private members */
- this->policies = linked_list_create();
+ this->policies = hashtable_create((hashtable_hash_t)policy_hash,
+ (hashtable_equals_t)policy_equals, 1);
this->mutex = mutex_create(MUTEX_DEFAULT);
this->install_routes = lib->settings->get_bool(lib->settings,
"charon.install_routes", TRUE);