aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/conftest/Makefile.am3
-rw-r--r--src/conftest/actions.c339
-rw-r--r--src/conftest/actions.h42
-rw-r--r--src/conftest/conftest.c2
-rw-r--r--src/conftest/conftest.h6
5 files changed, 391 insertions, 1 deletions
diff --git a/src/conftest/Makefile.am b/src/conftest/Makefile.am
index ce009e4c7..a841201df 100644
--- a/src/conftest/Makefile.am
+++ b/src/conftest/Makefile.am
@@ -2,7 +2,8 @@ ipsec_PROGRAMS = conftest
AM_CFLAGS = -rdynamic
-conftest_SOURCES = conftest.c conftest.h config.c config.h hooks/hook.h
+conftest_SOURCES = conftest.c conftest.h config.c config.h hooks/hook.h \
+ actions.c actions.h
INCLUDES = \
-I$(top_srcdir)/src/libstrongswan \
diff --git a/src/conftest/actions.c b/src/conftest/actions.c
new file mode 100644
index 000000000..92b523fbf
--- /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");
+ return JOB_REQUEUE_NONE;
+ }
+ enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ 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 (strcaseeq(actions[i].name, action))
+ {
+ 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;
+}
diff --git a/src/conftest/actions.h b/src/conftest/actions.h
new file mode 100644
index 000000000..2e1cbbacd
--- /dev/null
+++ b/src/conftest/actions.h
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup actions actions
+ * @{ @ingroup conftest
+ */
+
+#ifndef ACTIONS_H_
+#define ACTIONS_H_
+
+typedef struct actions_t actions_t;
+
+/**
+ * actionss to trigger based on configuration.
+ */
+struct actions_t {
+
+ /**
+ * Destroy a actions_t.
+ */
+ void (*destroy)(actions_t *this);
+};
+
+/**
+ * Create a actions instance.
+ */
+actions_t *actions_create();
+
+#endif /** ACTIONS_H_ @}*/
diff --git a/src/conftest/conftest.c b/src/conftest/conftest.c
index 6efd063b1..604fe2615 100644
--- a/src/conftest/conftest.c
+++ b/src/conftest/conftest.c
@@ -255,6 +255,7 @@ static void cleanup()
DESTROY_IF(conftest->test);
lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
conftest->creds->destroy(conftest->creds);
+ DESTROY_IF(conftest->actions);
while (conftest->hooks->remove_last(conftest->hooks,
(void**)&hook) == SUCCESS)
{
@@ -378,6 +379,7 @@ int main(int argc, char *argv[])
charon->backends->add_backend(charon->backends, &conftest->config->backend);
conftest->config->load(conftest->config, conftest->suite);
conftest->config->load(conftest->config, conftest->test);
+ conftest->actions = actions_create();
/* set up thread specific handlers */
action.sa_handler = segv_handler;
diff --git a/src/conftest/conftest.h b/src/conftest/conftest.h
index 5fa2e376b..2d32e6ce3 100644
--- a/src/conftest/conftest.h
+++ b/src/conftest/conftest.h
@@ -26,6 +26,7 @@
#include <credentials/sets/mem_cred.h>
#include "config.h"
+#include "actions.h"
typedef struct conftest_t conftest_t;
@@ -68,6 +69,11 @@ struct conftest_t {
* Loaded hooks
*/
linked_list_t *hooks;
+
+ /**
+ * Action handling
+ */
+ actions_t *actions;
};
/**