diff options
Diffstat (limited to 'src/libcharon')
-rw-r--r-- | src/libcharon/plugins/vici/README.md | 12 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_config.c | 71 | ||||
-rw-r--r-- | src/libcharon/plugins/vici/vici_control.c | 38 |
3 files changed, 95 insertions, 26 deletions
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md index f5759870d..b7e2a5e64 100644 --- a/src/libcharon/plugins/vici/README.md +++ b/src/libcharon/plugins/vici/README.md @@ -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> diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c index ea6d2958a..7f7ce61a1 100644 --- a/src/libcharon/plugins/vici/vici_config.c +++ b/src/libcharon/plugins/vici/vici_config.c @@ -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; diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c index 752007c24..87794d24d 100644 --- a/src/libcharon/plugins/vici/vici_control.c +++ b/src/libcharon/plugins/vici/vici_control.c @@ -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"); |