diff options
Diffstat (limited to 'src/conftest/actions.c')
-rw-r--r-- | src/conftest/actions.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/conftest/actions.c b/src/conftest/actions.c new file mode 100644 index 000000000..e66e9d7f1 --- /dev/null +++ b/src/conftest/actions.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "actions.h" +#include "conftest.h" + +#include <daemon.h> +#include <processing/jobs/callback_job.h> +#include <processing/jobs/rekey_ike_sa_job.h> +#include <processing/jobs/rekey_child_sa_job.h> +#include <processing/jobs/send_dpd_job.h> + +typedef struct private_actions_t private_actions_t; + +/** + * Private data of an actions_t object. + */ +struct private_actions_t { + + /** + * Public actions_t interface. + */ + actions_t public; +}; + +/** + * Initiate a CHILD_SA + */ +static job_requeue_t initiate(char *config) +{ + peer_cfg_t *peer_cfg; + child_cfg_t *child_cfg = NULL, *current; + enumerator_t *enumerator; + + peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, config); + if (!peer_cfg) + { + DBG1(DBG_CFG, "initiating '%s' failed, config not found", config); + return JOB_REQUEUE_NONE; + } + enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(current->get_name(current), config)) + { + child_cfg = current; + child_cfg->get_ref(child_cfg); + break; + } + } + enumerator->destroy(enumerator); + if (child_cfg) + { + DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config); + charon->controller->initiate(charon->controller, peer_cfg, child_cfg, + NULL, NULL); + } + else + { + DBG1(DBG_CFG, "initiating '%s' failed, CHILD_SA config not found", + config); + } + + return JOB_REQUEUE_NONE; +} + +/** + * Rekey an IKE_SA + */ +static job_requeue_t rekey_ike(char *config) +{ + enumerator_t *enumerator; + job_t *job = NULL; + ike_sa_t *ike_sa; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + job = (job_t*)rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), FALSE); + break; + } + } + enumerator->destroy(enumerator); + + if (job) + { + DBG1(DBG_CFG, "starting rekey of IKE_SA '%s'", config); + lib->processor->queue_job(lib->processor, job); + } + else + { + DBG1(DBG_CFG, "rekeying '%s' failed, IKE_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Rekey an CHILD_SA + */ +static job_requeue_t rekey_child(char *config) +{ + enumerator_t *enumerator; + iterator_t *children; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + u_int32_t reqid = 0, spi = 0; + protocol_id_t proto = PROTO_ESP; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (streq(config, child_sa->get_name(child_sa))) + { + reqid = child_sa->get_reqid(child_sa); + proto = child_sa->get_protocol(child_sa); + spi = child_sa->get_spi(child_sa, TRUE); + break; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + if (reqid) + { + DBG1(DBG_CFG, "starting rekey of CHILD_SA '%s'", config); + lib->processor->queue_job(lib->processor, + (job_t*)rekey_child_sa_job_create(reqid, proto, spi)); + } + else + { + DBG1(DBG_CFG, "rekeying '%s' failed, CHILD_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Do a liveness check + */ +static job_requeue_t liveness(char *config) +{ + enumerator_t *enumerator; + job_t *job = NULL; + ike_sa_t *ike_sa; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + job = (job_t*)send_dpd_job_create(ike_sa->get_id(ike_sa)); + break; + } + } + enumerator->destroy(enumerator); + + if (job) + { + DBG1(DBG_CFG, "starting liveness check of IKE_SA '%s'", config); + lib->processor->queue_job(lib->processor, job); + } + else + { + DBG1(DBG_CFG, "liveness check for '%s' failed, IKE_SA not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Close an IKE_SA with all CHILD_SAs + */ +static job_requeue_t close_ike(char *config) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + int id = 0; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (strcaseeq(config, ike_sa->get_name(ike_sa))) + { + id = ike_sa->get_unique_id(ike_sa); + break; + } + } + enumerator->destroy(enumerator); + if (id) + { + DBG1(DBG_CFG, "closing IKE_SA '%s'", config); + charon->controller->terminate_ike(charon->controller, id, NULL, NULL); + } + else + { + DBG1(DBG_CFG, "unable to close IKE_SA '%s', not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Close a CHILD_SAs + */ +static job_requeue_t close_child(char *config) +{ + enumerator_t *enumerator; + iterator_t *children; + ike_sa_t *ike_sa; + child_sa_t *child_sa; + int id = 0; + + enumerator = charon->controller->create_ike_sa_enumerator(charon->controller); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + + children = ike_sa->create_child_sa_iterator(ike_sa); + while (children->iterate(children, (void**)&child_sa)) + { + if (streq(config, child_sa->get_name(child_sa))) + { + id = child_sa->get_reqid(child_sa); + break; + } + } + children->destroy(children); + } + enumerator->destroy(enumerator); + if (id) + { + DBG1(DBG_CFG, "closing CHILD_SA '%s'", config); + charon->controller->terminate_child(charon->controller, id, NULL, NULL); + } + else + { + DBG1(DBG_CFG, "unable to close CHILD_SA '%s', not found", config); + } + return JOB_REQUEUE_NONE; +} + +/** + * Load a single action + */ +static void load_action(settings_t *settings, char *action) +{ + static struct { + char *name; + callback_job_cb_t cb; + } actions[] = { + {"initiate", (void*)initiate}, + {"rekey_ike", (void*)rekey_ike}, + {"rekey_child", (void*)rekey_child}, + {"liveness", (void*)liveness}, + {"close_ike", (void*)close_ike}, + {"close_child", (void*)close_child}, + }; + bool found = FALSE; + int i; + + for (i = 0; i < countof(actions); i++) + { + if (strncaseeq(actions[i].name, action, strlen(actions[i].name))) + { + int delay; + char *config; + + found = TRUE; + delay = settings->get_int(settings, "actions.%s.delay", 0, action); + config = settings->get_str(settings, "actions.%s.config", + NULL, action); + if (!config) + { + DBG1(DBG_CFG, "no config defined for action '%s'", action); + break; + } + lib->scheduler->schedule_job(lib->scheduler, + (job_t*)callback_job_create(actions[i].cb, config, NULL, NULL), + delay); + } + } + if (!found) + { + DBG1(DBG_CFG, "unknown action '%s', skipped", action); + } +} + +/** + * Load configured actions + */ +static void load_actions(settings_t *settings) +{ + enumerator_t *enumerator; + char *action; + + enumerator = settings->create_section_enumerator(settings, "actions"); + while (enumerator->enumerate(enumerator, &action)) + { + load_action(settings, action); + } + enumerator->destroy(enumerator); +} + +METHOD(actions_t, destroy, void, + private_actions_t *this) +{ + free(this); +} + +/** + * See header + */ +actions_t *actions_create() +{ + private_actions_t *this; + + INIT(this, + .public = { + .destroy = _destroy, + }, + ); + + load_actions(conftest->test); + + return &this->public; +} |