trap-manager: Add facility to install externally managed trap policies
This allows managing trap policies outside of the trap manager. We'll use this to create trap policies with generic labels if trap policies can't (or won't) be used (e.g. as responder for roadwarriors).
This commit is contained in:
+120
-31
@@ -106,6 +106,8 @@ typedef struct {
|
||||
child_sa_t *child_sa;
|
||||
/** TRUE in case of wildcard Transport Mode SA */
|
||||
bool wildcard;
|
||||
/** TRUE for CHILD_SAs that are externally managed */
|
||||
bool external;
|
||||
} entry_t;
|
||||
|
||||
/**
|
||||
@@ -125,7 +127,10 @@ typedef struct {
|
||||
*/
|
||||
static void destroy_entry(entry_t *this)
|
||||
{
|
||||
this->child_sa->destroy(this->child_sa);
|
||||
if (!this->external)
|
||||
{
|
||||
this->child_sa->destroy(this->child_sa);
|
||||
}
|
||||
this->peer_cfg->destroy(this->peer_cfg);
|
||||
free(this->name);
|
||||
free(this);
|
||||
@@ -183,6 +188,41 @@ static bool dynamic_remote_ts(child_cfg_t *child)
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the given trap
|
||||
*/
|
||||
static status_t install_trap(child_sa_t *child_sa, linked_list_t *local,
|
||||
linked_list_t *remote)
|
||||
{
|
||||
linked_list_t *my_ts, *other_ts, *proposals;
|
||||
proposal_t *proposal;
|
||||
child_cfg_t *child;
|
||||
protocol_id_t proto = PROTO_ESP;
|
||||
|
||||
child = child_sa->get_config(child_sa);
|
||||
|
||||
my_ts = child->get_traffic_selectors(child, TRUE, NULL, local, FALSE);
|
||||
other_ts = child->get_traffic_selectors(child, FALSE, NULL, remote, FALSE);
|
||||
|
||||
/* we don't know the finally negotiated protocol (ESP|AH), we install
|
||||
* the SA with the protocol of the first proposal */
|
||||
proposals = child->get_proposals(child, TRUE);
|
||||
if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proto = proposal->get_protocol(proposal);
|
||||
}
|
||||
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
|
||||
|
||||
child_sa->set_protocol(child_sa, proto);
|
||||
child_sa->set_mode(child_sa, child->get_mode(child));
|
||||
|
||||
child_sa->set_policies(child_sa, my_ts, other_ts);
|
||||
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
||||
|
||||
return child_sa->install_policies(child_sa);
|
||||
}
|
||||
|
||||
METHOD(trap_manager_t, install, bool,
|
||||
private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child)
|
||||
{
|
||||
@@ -190,12 +230,9 @@ METHOD(trap_manager_t, install, bool,
|
||||
ike_cfg_t *ike_cfg;
|
||||
child_sa_t *child_sa;
|
||||
host_t *me, *other;
|
||||
linked_list_t *my_ts, *other_ts, *list;
|
||||
linked_list_t *local, *remote;
|
||||
enumerator_t *enumerator;
|
||||
status_t status;
|
||||
linked_list_t *proposals;
|
||||
proposal_t *proposal;
|
||||
protocol_id_t proto = PROTO_ESP;
|
||||
bool result = FALSE, wildcard = FALSE;
|
||||
|
||||
/* try to resolve addresses */
|
||||
@@ -254,13 +291,14 @@ METHOD(trap_manager_t, install, bool,
|
||||
enumerator = this->traps->create_enumerator(this->traps);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (streq(entry->name, child->get_name(child)) &&
|
||||
if (!entry->external &&
|
||||
streq(entry->name, child->get_name(child)) &&
|
||||
streq(entry->peer_cfg->get_name(entry->peer_cfg),
|
||||
peer->get_name(peer)))
|
||||
{
|
||||
found = entry;
|
||||
if (entry->child_sa)
|
||||
{ /* replace it with an updated version, if already installed */
|
||||
{ /* replace it with an updated version if already installed */
|
||||
this->traps->remove_at(this->traps, enumerator);
|
||||
}
|
||||
break;
|
||||
@@ -302,28 +340,13 @@ METHOD(trap_manager_t, install, bool,
|
||||
};
|
||||
child_sa = child_sa_create(me, other, child, &child_data);
|
||||
|
||||
list = linked_list_create_with_items(me, NULL);
|
||||
my_ts = child->get_traffic_selectors(child, TRUE, NULL, list, FALSE);
|
||||
list->destroy_offset(list, offsetof(host_t, destroy));
|
||||
local = linked_list_create_with_items(me, NULL);
|
||||
remote = linked_list_create_with_items(other, NULL);
|
||||
|
||||
list = linked_list_create_with_items(other, NULL);
|
||||
other_ts = child->get_traffic_selectors(child, FALSE, NULL, list, FALSE);
|
||||
list->destroy_offset(list, offsetof(host_t, destroy));
|
||||
status = install_trap(child_sa, local, remote);
|
||||
|
||||
/* We don't know the finally negotiated protocol (ESP|AH), we install
|
||||
* the SA with the protocol of the first proposal */
|
||||
proposals = child->get_proposals(child, TRUE);
|
||||
if (proposals->get_first(proposals, (void**)&proposal) == SUCCESS)
|
||||
{
|
||||
proto = proposal->get_protocol(proposal);
|
||||
}
|
||||
proposals->destroy_offset(proposals, offsetof(proposal_t, destroy));
|
||||
child_sa->set_protocol(child_sa, proto);
|
||||
child_sa->set_mode(child_sa, child->get_mode(child));
|
||||
child_sa->set_policies(child_sa, my_ts, other_ts);
|
||||
status = child_sa->install_policies(child_sa);
|
||||
my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
|
||||
other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
|
||||
local->destroy_offset(local, offsetof(host_t, destroy));
|
||||
remote->destroy_offset(remote, offsetof(host_t, destroy));
|
||||
if (status != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_CFG, "installing trap failed");
|
||||
@@ -366,8 +389,71 @@ METHOD(trap_manager_t, uninstall, bool,
|
||||
enumerator = this->traps->create_enumerator(this->traps);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (streq(entry->name, child) &&
|
||||
(!peer || streq(peer, entry->peer_cfg->get_name(entry->peer_cfg))))
|
||||
if (!entry->external &&
|
||||
streq(entry->name, child) &&
|
||||
(!peer || streq(peer, entry->peer_cfg->get_name(entry->peer_cfg))))
|
||||
{
|
||||
this->traps->remove_at(this->traps, enumerator);
|
||||
found = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
destroy_entry(found);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(trap_manager_t, install_external, bool,
|
||||
private_trap_manager_t *this, peer_cfg_t *peer, child_sa_t *child,
|
||||
linked_list_t *local, linked_list_t *remote)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
if (this->installing == INSTALL_DISABLED)
|
||||
{ /* flush() has been called */
|
||||
this->lock->unlock(this->lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
INIT(entry,
|
||||
.name = strdup(child->get_name(child)),
|
||||
.peer_cfg = peer->get_ref(peer),
|
||||
.child_sa = child,
|
||||
.external = TRUE,
|
||||
);
|
||||
this->traps->insert_first(this->traps, entry);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
if (install_trap(child, local, remote) != SUCCESS)
|
||||
{
|
||||
DBG1(DBG_CFG, "installing trap failed");
|
||||
this->lock->write_lock(this->lock);
|
||||
this->traps->remove(this->traps, entry, NULL);
|
||||
this->lock->unlock(this->lock);
|
||||
destroy_entry(entry);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(trap_manager_t, remove_external, bool,
|
||||
private_trap_manager_t *this, child_sa_t *child)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
entry_t *entry, *found = NULL;
|
||||
|
||||
this->lock->write_lock(this->lock);
|
||||
enumerator = this->traps->create_enumerator(this->traps);
|
||||
while (enumerator->enumerate(enumerator, &entry))
|
||||
{
|
||||
if (entry->external && entry->child_sa == child)
|
||||
{
|
||||
this->traps->remove_at(this->traps, enumerator);
|
||||
found = entry;
|
||||
@@ -396,8 +482,9 @@ CALLBACK(trap_filter, bool,
|
||||
|
||||
while (orig->enumerate(orig, &entry))
|
||||
{
|
||||
if (!entry->child_sa)
|
||||
{ /* skip entries that are currently being installed */
|
||||
if (!entry->child_sa || entry->external)
|
||||
{ /* skip entries that are currently being installed or are managed
|
||||
* externally */
|
||||
continue;
|
||||
}
|
||||
if (peer_cfg)
|
||||
@@ -678,6 +765,8 @@ trap_manager_t *trap_manager_create(void)
|
||||
.public = {
|
||||
.install = _install,
|
||||
.uninstall = _uninstall,
|
||||
.install_external = _install_external,
|
||||
.remove_external = _remove_external,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.acquire = _acquire,
|
||||
.flush = _flush,
|
||||
|
||||
Reference in New Issue
Block a user