Merge branch 'vici-undo-on-unload'
Undo start actions when unloading connections, and add some misc fixes and extensions to vici connection handling.
This commit is contained in:
commit
bb723f97c7
|
@ -258,7 +258,8 @@ Initiates an SA while streaming _control-log_ events.
|
|||
|
||||
{
|
||||
child = <CHILD_SA configuration name to initiate>
|
||||
timeout = <timeout in seconds before returning>
|
||||
ike = <optional IKE_SA configuraiton name to find child under>
|
||||
timeout = <timeout in ms before returning>
|
||||
init-limits = <whether limits may prevent initiating the CHILD_SA>
|
||||
loglevel = <loglevel to issue "control-log" events for>
|
||||
} => {
|
||||
|
@ -266,6 +267,9 @@ Initiates an SA while streaming _control-log_ events.
|
|||
errmsg = <error string on failure or timeout>
|
||||
}
|
||||
|
||||
The default timeout of 0 waits indefinitely for a result, and a timeout value
|
||||
of -1 returns a result immediately.
|
||||
|
||||
### terminate() ###
|
||||
|
||||
Terminates an SA while streaming _control-log_ events.
|
||||
|
@ -275,19 +279,23 @@ Terminates an SA while streaming _control-log_ events.
|
|||
ike = <terminate an IKE_SA by configuration name>
|
||||
child_id = <terminate a CHILD_SA by its reqid>
|
||||
ike_id = <terminate an IKE_SA by its unique id>
|
||||
timeout = <timeout in seconds before returning>
|
||||
timeout = <timeout in ms before returning>
|
||||
loglevel = <loglevel to issue "control-log" events for>
|
||||
} => {
|
||||
success = <yes or no>
|
||||
errmsg = <error string on failure or timeout>
|
||||
}
|
||||
|
||||
The default timeout of 0 waits indefinitely for a result, and a timeout value
|
||||
of -1 returns a result immediately.
|
||||
|
||||
### install() ###
|
||||
|
||||
Install a trap, drop or bypass policy defined by a CHILD_SA config.
|
||||
|
||||
{
|
||||
child = <CHILD_SA configuration name to install>
|
||||
ike = <optional IKE_SA configuraiton name to find child under>
|
||||
} => {
|
||||
success = <yes or no>
|
||||
errmsg = <error string on failure>
|
||||
|
|
|
@ -1613,14 +1613,14 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
|
|||
/**
|
||||
* Undo start actions associated to a child config
|
||||
*/
|
||||
static void clear_start_action(private_vici_config_t *this,
|
||||
static void clear_start_action(private_vici_config_t *this, char *peer_name,
|
||||
child_cfg_t *child_cfg)
|
||||
{
|
||||
enumerator_t *enumerator, *children;
|
||||
child_sa_t *child_sa;
|
||||
ike_sa_t *ike_sa;
|
||||
u_int32_t id = 0, *del;
|
||||
array_t *ids = NULL;
|
||||
u_int32_t id = 0, others;
|
||||
array_t *ids = NULL, *ikeids = NULL;
|
||||
char *name;
|
||||
|
||||
name = child_cfg->get_name(child_cfg);
|
||||
|
@ -1631,29 +1631,72 @@ static void clear_start_action(private_vici_config_t *this,
|
|||
charon->controller, TRUE);
|
||||
while (enumerator->enumerate(enumerator, &ike_sa))
|
||||
{
|
||||
if (!streq(ike_sa->get_name(ike_sa), peer_name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
others = id = 0;
|
||||
children = ike_sa->create_child_sa_enumerator(ike_sa);
|
||||
while (children->enumerate(children, &child_sa))
|
||||
{
|
||||
if (streq(name, child_sa->get_name(child_sa)))
|
||||
if (child_sa->get_state(child_sa) != CHILD_DELETING)
|
||||
{
|
||||
id = child_sa->get_unique_id(child_sa);
|
||||
array_insert_create(&ids, ARRAY_TAIL, &id);
|
||||
if (streq(name, child_sa->get_name(child_sa)))
|
||||
{
|
||||
id = child_sa->get_unique_id(child_sa);
|
||||
}
|
||||
else
|
||||
{
|
||||
others++;
|
||||
}
|
||||
}
|
||||
}
|
||||
children->destroy(children);
|
||||
|
||||
if (id && !others)
|
||||
{
|
||||
/* found matching children only, delete full IKE_SA */
|
||||
id = ike_sa->get_unique_id(ike_sa);
|
||||
array_insert_create_value(&ikeids, sizeof(id),
|
||||
ARRAY_TAIL, &id);
|
||||
}
|
||||
else
|
||||
{
|
||||
children = ike_sa->create_child_sa_enumerator(ike_sa);
|
||||
while (children->enumerate(children, &child_sa))
|
||||
{
|
||||
if (streq(name, child_sa->get_name(child_sa)))
|
||||
{
|
||||
id = child_sa->get_unique_id(child_sa);
|
||||
array_insert_create_value(&ids, sizeof(id),
|
||||
ARRAY_TAIL, &id);
|
||||
}
|
||||
}
|
||||
children->destroy(children);
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (array_count(ids))
|
||||
{
|
||||
while (array_remove(ids, ARRAY_HEAD, &del))
|
||||
while (array_remove(ids, ARRAY_HEAD, &id))
|
||||
{
|
||||
DBG1(DBG_CFG, "closing '%s' #%u", name, *del);
|
||||
DBG1(DBG_CFG, "closing '%s' #%u", name, id);
|
||||
charon->controller->terminate_child(charon->controller,
|
||||
*del, NULL, NULL, 0);
|
||||
id, NULL, NULL, 0);
|
||||
}
|
||||
array_destroy(ids);
|
||||
}
|
||||
if (array_count(ikeids))
|
||||
{
|
||||
while (array_remove(ikeids, ARRAY_HEAD, &id))
|
||||
{
|
||||
DBG1(DBG_CFG, "closing IKE_SA #%u", id);
|
||||
charon->controller->terminate_ike(charon->controller,
|
||||
id, NULL, NULL, 0);
|
||||
}
|
||||
array_destroy(ikeids);
|
||||
}
|
||||
break;
|
||||
case ACTION_ROUTE:
|
||||
DBG1(DBG_CFG, "uninstalling '%s'", name);
|
||||
|
@ -1714,7 +1757,7 @@ static void clear_start_actions(private_vici_config_t *this,
|
|||
enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
|
||||
while (enumerator->enumerate(enumerator, &child_cfg))
|
||||
{
|
||||
clear_start_action(this, child_cfg);
|
||||
clear_start_action(this, peer_cfg->get_name(peer_cfg), child_cfg);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
@ -1732,7 +1775,7 @@ static void replace_children(private_vici_config_t *this,
|
|||
while (enumerator->enumerate(enumerator, &child))
|
||||
{
|
||||
to->remove_child_cfg(to, enumerator);
|
||||
clear_start_action(this, child);
|
||||
clear_start_action(this, to->get_name(to), child);
|
||||
child->destroy(child);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
@ -1843,9 +1886,8 @@ CALLBACK(config_sn, bool,
|
|||
|
||||
if (peer.local->get_count(peer.local) == 0)
|
||||
{
|
||||
free_peer_data(&peer);
|
||||
peer.request->reply = create_reply("missing local auth config");
|
||||
return FALSE;
|
||||
auth_cfg = auth_cfg_create();
|
||||
peer.local->insert_last(peer.local, auth_cfg);
|
||||
}
|
||||
if (peer.remote->get_count(peer.remote) == 0)
|
||||
{
|
||||
|
@ -2005,6 +2047,7 @@ CALLBACK(unload_conn, vici_message_t*,
|
|||
if (streq(cfg->get_name(cfg), conn_name))
|
||||
{
|
||||
this->conns->remove_at(this->conns, enumerator);
|
||||
clear_start_actions(this, cfg);
|
||||
cfg->destroy(cfg);
|
||||
found = TRUE;
|
||||
break;
|
||||
|
|
|
@ -134,7 +134,7 @@ static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
|
|||
/**
|
||||
* Find a peer/child config from a child config name
|
||||
*/
|
||||
static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
|
||||
static child_cfg_t* find_child_cfg(char *name, char *pname, peer_cfg_t **out)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
peer_cfg_t *peer_cfg;
|
||||
|
@ -144,6 +144,10 @@ static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
|
|||
charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
|
||||
while (enumerator->enumerate(enumerator, &peer_cfg))
|
||||
{
|
||||
if (pname && !streq(pname, peer_cfg->get_name(peer_cfg)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
child_cfg = get_child_from_peer(peer_cfg, name);
|
||||
if (child_cfg)
|
||||
{
|
||||
|
@ -161,15 +165,17 @@ CALLBACK(initiate, vici_message_t*,
|
|||
{
|
||||
child_cfg_t *child_cfg = NULL;
|
||||
peer_cfg_t *peer_cfg;
|
||||
char *child;
|
||||
u_int timeout;
|
||||
char *child, *ike;
|
||||
int timeout;
|
||||
bool limits;
|
||||
controller_cb_t log_cb = NULL;
|
||||
log_info_t log = {
|
||||
.dispatcher = this->dispatcher,
|
||||
.id = id,
|
||||
};
|
||||
|
||||
child = request->get_str(request, NULL, "child");
|
||||
ike = request->get_str(request, NULL, "ike");
|
||||
timeout = request->get_int(request, 0, "timeout");
|
||||
limits = request->get_bool(request, FALSE, "init-limits");
|
||||
log.level = request->get_int(request, 1, "loglevel");
|
||||
|
@ -178,16 +184,20 @@ CALLBACK(initiate, vici_message_t*,
|
|||
{
|
||||
return send_reply(this, "missing configuration name");
|
||||
}
|
||||
if (timeout >= 0)
|
||||
{
|
||||
log_cb = (controller_cb_t)log_vici;
|
||||
}
|
||||
|
||||
DBG1(DBG_CFG, "vici initiate '%s'", child);
|
||||
|
||||
child_cfg = find_child_cfg(child, &peer_cfg);
|
||||
child_cfg = find_child_cfg(child, ike, &peer_cfg);
|
||||
if (!child_cfg)
|
||||
{
|
||||
return send_reply(this, "CHILD_SA config '%s' not found", child);
|
||||
}
|
||||
switch (charon->controller->initiate(charon->controller, peer_cfg,
|
||||
child_cfg, (controller_cb_t)log_vici, &log, timeout, limits))
|
||||
child_cfg, log_cb, &log, timeout, limits))
|
||||
{
|
||||
case SUCCESS:
|
||||
return send_reply(this, NULL);
|
||||
|
@ -208,11 +218,13 @@ CALLBACK(terminate, vici_message_t*,
|
|||
{
|
||||
enumerator_t *enumerator, *isas, *csas;
|
||||
char *child, *ike, *errmsg = NULL;
|
||||
u_int timeout, child_id, ike_id, current, *del, done = 0;
|
||||
u_int child_id, ike_id, current, *del, done = 0;
|
||||
int timeout;
|
||||
ike_sa_t *ike_sa;
|
||||
child_sa_t *child_sa;
|
||||
array_t *ids;
|
||||
vici_builder_t *builder;
|
||||
controller_cb_t log_cb = NULL;
|
||||
log_info_t log = {
|
||||
.dispatcher = this->dispatcher,
|
||||
.id = id,
|
||||
|
@ -247,6 +259,11 @@ CALLBACK(terminate, vici_message_t*,
|
|||
DBG1(DBG_CFG, "vici terminate CHILD_SA '%s'", child);
|
||||
}
|
||||
|
||||
if (timeout >= 0)
|
||||
{
|
||||
log_cb = (controller_cb_t)log_vici;
|
||||
}
|
||||
|
||||
ids = array_create(sizeof(u_int), 0);
|
||||
|
||||
isas = charon->controller->create_ike_sa_enumerator(charon->controller, TRUE);
|
||||
|
@ -296,7 +313,7 @@ CALLBACK(terminate, vici_message_t*,
|
|||
if (child || child_id)
|
||||
{
|
||||
if (charon->controller->terminate_child(charon->controller, *del,
|
||||
(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
|
||||
log_cb, &log, timeout) == SUCCESS)
|
||||
{
|
||||
done++;
|
||||
}
|
||||
|
@ -304,7 +321,7 @@ CALLBACK(terminate, vici_message_t*,
|
|||
else
|
||||
{
|
||||
if (charon->controller->terminate_ike(charon->controller, *del,
|
||||
(controller_cb_t)log_vici, &log, timeout) == SUCCESS)
|
||||
log_cb, &log, timeout) == SUCCESS)
|
||||
{
|
||||
done++;
|
||||
}
|
||||
|
@ -379,10 +396,11 @@ CALLBACK(install, vici_message_t*,
|
|||
{
|
||||
child_cfg_t *child_cfg = NULL;
|
||||
peer_cfg_t *peer_cfg;
|
||||
char *child;
|
||||
char *child, *ike;
|
||||
bool ok;
|
||||
|
||||
child = request->get_str(request, NULL, "child");
|
||||
ike = request->get_str(request, NULL, "ike");
|
||||
if (!child)
|
||||
{
|
||||
return send_reply(this, "missing configuration name");
|
||||
|
@ -390,7 +408,7 @@ CALLBACK(install, vici_message_t*,
|
|||
|
||||
DBG1(DBG_CFG, "vici install '%s'", child);
|
||||
|
||||
child_cfg = find_child_cfg(child, &peer_cfg);
|
||||
child_cfg = find_child_cfg(child, ike, &peer_cfg);
|
||||
if (!child_cfg)
|
||||
{
|
||||
return send_reply(this, "configuration name not found");
|
||||
|
|
|
@ -277,6 +277,16 @@ void array_insert_create(array_t **array, int idx, void *ptr)
|
|||
array_insert(*array, idx, ptr);
|
||||
}
|
||||
|
||||
void array_insert_create_value(array_t **array, u_int esize,
|
||||
int idx, void *val)
|
||||
{
|
||||
if (*array == NULL)
|
||||
{
|
||||
*array = array_create(esize, 0);
|
||||
}
|
||||
array_insert(*array, idx, val);
|
||||
}
|
||||
|
||||
void array_insert_enumerator(array_t *array, int idx, enumerator_t *enumerator)
|
||||
{
|
||||
void *ptr;
|
||||
|
|
|
@ -138,6 +138,21 @@ void array_insert(array_t *array, int idx, void *data);
|
|||
*/
|
||||
void array_insert_create(array_t **array, int idx, void *ptr);
|
||||
|
||||
/**
|
||||
* Create a value based array if it does not exist, insert value.
|
||||
*
|
||||
* This is a convenience function to insert a value and implicitly
|
||||
* create a value based array if array is NULL. Array is set the the newly
|
||||
* created array, if any.
|
||||
*
|
||||
* @param array pointer to array reference, potentially NULL
|
||||
* @param esize element size of this array
|
||||
* @param idx index to insert item at
|
||||
* @param val pointer to value to insert
|
||||
*/
|
||||
void array_insert_create_value(array_t **array, u_int esize,
|
||||
int idx, void *val);
|
||||
|
||||
/**
|
||||
* Insert all items from an enumerator to an array.
|
||||
*
|
||||
|
|
|
@ -491,6 +491,44 @@ START_TEST(test_invoke_offset)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_insert_create)
|
||||
{
|
||||
array_t *array = NULL;
|
||||
uintptr_t x;
|
||||
|
||||
array_insert_create(&array, ARRAY_TAIL, (void*)(uintptr_t)1);
|
||||
array_insert_create(&array, ARRAY_TAIL, (void*)(uintptr_t)2);
|
||||
ck_assert(array != NULL);
|
||||
|
||||
ck_assert(array_get(array, ARRAY_HEAD, &x));
|
||||
ck_assert_int_eq(x, 1);
|
||||
ck_assert(array_get(array, ARRAY_TAIL, &x));
|
||||
ck_assert_int_eq(x, 2);
|
||||
|
||||
array_destroy(array);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_insert_create_value)
|
||||
{
|
||||
array_t *array = NULL;
|
||||
u_int16_t v;
|
||||
|
||||
v = 1;
|
||||
array_insert_create_value(&array, sizeof(v), ARRAY_TAIL, &v);
|
||||
v = 2;
|
||||
array_insert_create_value(&array, sizeof(v), ARRAY_TAIL, &v);
|
||||
ck_assert(array != NULL);
|
||||
|
||||
ck_assert(array_get(array, ARRAY_HEAD, &v));
|
||||
ck_assert_int_eq(v, 1);
|
||||
ck_assert(array_get(array, ARRAY_TAIL, &v));
|
||||
ck_assert_int_eq(v, 2);
|
||||
|
||||
array_destroy(array);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *array_suite_create()
|
||||
{
|
||||
Suite *s;
|
||||
|
@ -528,5 +566,10 @@ Suite *array_suite_create()
|
|||
tcase_add_test(tc, test_invoke_offset);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
tc = tcase_create("insert create");
|
||||
tcase_add_test(tc, test_insert_create);
|
||||
tcase_add_test(tc, test_insert_create_value);
|
||||
suite_add_tcase(s, tc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue