summaryrefslogtreecommitdiff
path: root/src/libcharon/sa/shunt_manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon/sa/shunt_manager.c')
-rw-r--r--src/libcharon/sa/shunt_manager.c90
1 files changed, 67 insertions, 23 deletions
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 40e291be5..b0162751d 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -36,7 +36,7 @@ struct private_shunt_manager_t {
shunt_manager_t public;
/**
- * Installed shunts, as child_cfg_t
+ * Installed shunts, as entry_t
*/
linked_list_t *shunts;
@@ -57,6 +57,32 @@ struct private_shunt_manager_t {
};
/**
+ * Config entry for a shunt
+ */
+typedef struct {
+ /**
+ * Configured namespace
+ */
+ char *ns;
+
+ /**
+ * Child config
+ */
+ child_cfg_t *cfg;
+
+} entry_t;
+
+/**
+ * Destroy a config entry
+ */
+static void entry_destroy(entry_t *this)
+{
+ this->cfg->destroy(this->cfg);
+ free(this->ns);
+ free(this);
+}
+
+/**
* Install in and out shunt policies in the kernel
*/
static bool install_shunt_policy(child_cfg_t *child)
@@ -162,10 +188,10 @@ static bool install_shunt_policy(child_cfg_t *child)
}
METHOD(shunt_manager_t, install, bool,
- private_shunt_manager_t *this, child_cfg_t *child)
+ private_shunt_manager_t *this, char *ns, child_cfg_t *cfg)
{
enumerator_t *enumerator;
- child_cfg_t *child_cfg;
+ entry_t *entry;
bool found = FALSE, success;
/* check if not already installed */
@@ -176,9 +202,10 @@ METHOD(shunt_manager_t, install, bool,
return FALSE;
}
enumerator = this->shunts->create_enumerator(this->shunts);
- while (enumerator->enumerate(enumerator, &child_cfg))
+ while (enumerator->enumerate(enumerator, &entry))
{
- if (streq(child_cfg->get_name(child_cfg), child->get_name(child)))
+ if (streq(ns, entry->ns) &&
+ streq(cfg->get_name(cfg), entry->cfg->get_name(entry->cfg)))
{
found = TRUE;
break;
@@ -188,21 +215,25 @@ METHOD(shunt_manager_t, install, bool,
if (found)
{
DBG1(DBG_CFG, "shunt %N policy '%s' already installed",
- ipsec_mode_names, child->get_mode(child), child->get_name(child));
+ ipsec_mode_names, cfg->get_mode(cfg), cfg->get_name(cfg));
this->lock->unlock(this->lock);
return TRUE;
}
- this->shunts->insert_last(this->shunts, child->get_ref(child));
+ INIT(entry,
+ .ns = strdupnull(ns),
+ .cfg = cfg->get_ref(cfg),
+ );
+ this->shunts->insert_last(this->shunts, entry);
this->installing++;
this->lock->unlock(this->lock);
- success = install_shunt_policy(child);
+ success = install_shunt_policy(cfg);
this->lock->write_lock(this->lock);
if (!success)
{
- this->shunts->remove(this->shunts, child, NULL);
- child->destroy(child);
+ this->shunts->remove(this->shunts, entry, NULL);
+ entry_destroy(entry);
}
this->installing--;
this->condvar->signal(this->condvar);
@@ -320,19 +351,20 @@ static void uninstall_shunt_policy(child_cfg_t *child)
}
METHOD(shunt_manager_t, uninstall, bool,
- private_shunt_manager_t *this, char *name)
+ private_shunt_manager_t *this, char *ns, char *name)
{
enumerator_t *enumerator;
- child_cfg_t *child, *found = NULL;
+ entry_t *entry, *found = NULL;
this->lock->write_lock(this->lock);
enumerator = this->shunts->create_enumerator(this->shunts);
- while (enumerator->enumerate(enumerator, &child))
+ while (enumerator->enumerate(enumerator, &entry))
{
- if (streq(name, child->get_name(child)))
+ if (streq(ns, entry->ns) &&
+ streq(name, entry->cfg->get_name(entry->cfg)))
{
this->shunts->remove_at(this->shunts, enumerator);
- found = child;
+ found = entry;
break;
}
}
@@ -343,8 +375,19 @@ METHOD(shunt_manager_t, uninstall, bool,
{
return FALSE;
}
- uninstall_shunt_policy(child);
- child->destroy(child);
+ uninstall_shunt_policy(found->cfg);
+ entry_destroy(found);
+ return TRUE;
+}
+
+CALLBACK(filter_entries, bool,
+ void *unused, entry_t **entry, char **ns, void **in, child_cfg_t **cfg)
+{
+ if (ns)
+ {
+ *ns = (*entry)->ns;
+ }
+ *cfg = (*entry)->cfg;
return TRUE;
}
@@ -352,25 +395,26 @@ METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
private_shunt_manager_t *this)
{
this->lock->read_lock(this->lock);
- return enumerator_create_cleaner(
+ return enumerator_create_filter(
this->shunts->create_enumerator(this->shunts),
- (void*)this->lock->unlock, this->lock);
+ (void*)filter_entries, this->lock,
+ (void*)this->lock->unlock);
}
METHOD(shunt_manager_t, flush, void,
private_shunt_manager_t *this)
{
- child_cfg_t *child;
+ entry_t *entry;
this->lock->write_lock(this->lock);
while (this->installing)
{
this->condvar->wait(this->condvar, this->lock);
}
- while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
+ while (this->shunts->remove_last(this->shunts, (void**)&entry) == SUCCESS)
{
- uninstall_shunt_policy(child);
- child->destroy(child);
+ uninstall_shunt_policy(entry->cfg);
+ entry_destroy(entry);
}
this->installing = INSTALL_DISABLED;
this->lock->unlock(this->lock);