shunt-manager: Add an optional namespace for each shunt

This will allow us to reuse the names of child configs e.g. when they
are defined in different connections.
This commit is contained in:
Tobias Brunner
2017-02-16 19:24:07 +01:00
parent ed105f45af
commit 7a0fdbab42
10 changed files with 90 additions and 41 deletions
+67 -23
View File
@@ -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;
@@ -56,6 +56,32 @@ struct private_shunt_manager_t {
rwlock_condvar_t *condvar;
};
/**
* 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
*/
@@ -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);
+8 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2015-2016 Tobias Brunner
* Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -36,23 +36,26 @@ struct shunt_manager_t {
/**
* Install a policy as a shunt.
*
* @param child child configuration to install as a shunt
* @param ns optional namespace (e.g. name of a connection or
* plugin), cloned
* @param child child configuration to install as a shunt
* @return TRUE if installed successfully
*/
bool (*install)(shunt_manager_t *this, child_cfg_t *child);
bool (*install)(shunt_manager_t *this, char *ns, child_cfg_t *child);
/**
* Uninstall a shunt policy.
*
* @param ns namespace (same as given during installation)
* @param name name of child configuration to uninstall as a shunt
* @return TRUE if uninstalled successfully
*/
bool (*uninstall)(shunt_manager_t *this, char *name);
bool (*uninstall)(shunt_manager_t *this, char *ns, char *name);
/**
* Create an enumerator over all installed shunts.
*
* @return enumerator over (child_sa_t)
* @return enumerator over (char*, child_cfg_t*)
*/
enumerator_t* (*create_enumerator)(shunt_manager_t *this);