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 2016-11-16 17:59:22 +01:00
parent ed105f45af
commit 7a0fdbab42
10 changed files with 90 additions and 41 deletions

View File

@ -79,7 +79,7 @@ static void bypass_policy_destroy(bypass_policy_t *this)
ts = traffic_selector_create_from_subnet(this->net->clone(this->net),
this->mask, 0, 0, 65535);
DBG1(DBG_IKE, "uninstalling bypass policy for %R", ts);
charon->shunts->uninstall(charon->shunts,
charon->shunts->uninstall(charon->shunts, "bypass-lan",
this->cfg->get_name(this->cfg));
this->cfg->destroy(this->cfg);
ts->destroy(ts);
@ -173,7 +173,7 @@ static job_requeue_t update_bypass(private_bypass_lan_listener_t *this)
cfg = child_cfg_create(name, &child);
cfg->add_traffic_selector(cfg, FALSE, ts->clone(ts));
cfg->add_traffic_selector(cfg, TRUE, ts);
charon->shunts->install(charon->shunts, cfg);
charon->shunts->install(charon->shunts, "bypass-lan", cfg);
DBG1(DBG_IKE, "installed bypass policy for %R", ts);
INIT(found,

View File

@ -641,7 +641,7 @@ static void charon_route(peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
mode = child_cfg->get_mode(child_cfg);
if (mode == MODE_PASS || mode == MODE_DROP)
{
if (charon->shunts->install(charon->shunts, child_cfg))
if (charon->shunts->install(charon->shunts, NULL, child_cfg))
{
fprintf(out, "'%s' shunt %N policy installed\n",
name, ipsec_mode_names, mode);
@ -733,7 +733,7 @@ METHOD(stroke_control_t, unroute, void,
enumerator_t *enumerator;
uint32_t id = 0;
if (charon->shunts->uninstall(charon->shunts, msg->unroute.name))
if (charon->shunts->uninstall(charon->shunts, NULL, msg->unroute.name))
{
fprintf(out, "shunt policy '%s' uninstalled\n", msg->unroute.name);
return;

View File

@ -603,7 +603,7 @@ METHOD(stroke_list_t, status, void,
/* Enumerate shunt policies */
first = TRUE;
enumerator = charon->shunts->create_enumerator(charon->shunts);
while (enumerator->enumerate(enumerator, &child_cfg))
while (enumerator->enumerate(enumerator, NULL, &child_cfg))
{
if (name && !streq(name, child_cfg->get_name(child_cfg)))
{

View File

@ -235,7 +235,7 @@ static job_requeue_t add_exclude_async(entry_t *entry)
enumerator->destroy(enumerator);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
charon->shunts->install(charon->shunts, child_cfg);
charon->shunts->install(charon->shunts, "unity", child_cfg);
child_cfg->destroy(child_cfg);
DBG1(DBG_IKE, "installed %N bypass policy for %R",
@ -310,7 +310,8 @@ static bool remove_exclude(private_unity_handler_t *this, chunk_t data)
DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
ts->destroy(ts);
success = charon->shunts->uninstall(charon->shunts, name) && success;
success = charon->shunts->uninstall(charon->shunts, "unity",
name) && success;
}
list->destroy(list);
return success;

View File

@ -1757,7 +1757,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
{
case MODE_PASS:
case MODE_DROP:
charon->shunts->install(charon->shunts, child_cfg);
charon->shunts->install(charon->shunts, NULL, child_cfg);
break;
default:
charon->traps->install(charon->traps, peer_cfg, child_cfg,
@ -1865,7 +1865,7 @@ static void clear_start_action(private_vici_config_t *this, char *peer_name,
{
case MODE_PASS:
case MODE_DROP:
charon->shunts->uninstall(charon->shunts, name);
charon->shunts->uninstall(charon->shunts, NULL, name);
break;
default:
enumerator = charon->traps->create_enumerator(charon->traps);

View File

@ -565,7 +565,7 @@ CALLBACK(install, vici_message_t*,
{
case MODE_PASS:
case MODE_DROP:
ok = charon->shunts->install(charon->shunts, child_cfg);
ok = charon->shunts->install(charon->shunts, NULL, child_cfg);
break;
default:
ok = charon->traps->install(charon->traps, peer_cfg, child_cfg,
@ -594,7 +594,7 @@ CALLBACK(uninstall, vici_message_t*,
DBG1(DBG_CFG, "vici uninstall '%s'", child);
if (charon->shunts->uninstall(charon->shunts, child))
if (charon->shunts->uninstall(charon->shunts, NULL, child))
{
return send_reply(this, NULL);
}

View File

@ -580,7 +580,7 @@ CALLBACK(list_policies, vici_message_t*,
if (drop || pass)
{
enumerator = charon->shunts->create_enumerator(charon->shunts);
while (enumerator->enumerate(enumerator, &child_cfg))
while (enumerator->enumerate(enumerator, NULL, &child_cfg))
{
if (child && !streq(child, child_cfg->get_name(child_cfg)))
{

View File

@ -68,7 +68,8 @@ METHOD(job_t, execute, job_requeue_t,
mode = child_cfg->get_mode(child_cfg);
if (mode == MODE_PASS || mode == MODE_DROP)
{
charon->shunts->install(charon->shunts, child_cfg);
charon->shunts->install(charon->shunts, NULL,
child_cfg);
}
else
{

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);

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);