Read actions from test config, delayed execution
This commit is contained in:
@@ -2,7 +2,8 @@ ipsec_PROGRAMS = conftest
|
|||||||
|
|
||||||
AM_CFLAGS = -rdynamic
|
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 = \
|
INCLUDES = \
|
||||||
-I$(top_srcdir)/src/libstrongswan \
|
-I$(top_srcdir)/src/libstrongswan \
|
||||||
|
|||||||
@@ -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, ¤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 (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;
|
||||||
|
}
|
||||||
@@ -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_ @}*/
|
||||||
@@ -255,6 +255,7 @@ static void cleanup()
|
|||||||
DESTROY_IF(conftest->test);
|
DESTROY_IF(conftest->test);
|
||||||
lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
|
lib->credmgr->remove_set(lib->credmgr, &conftest->creds->set);
|
||||||
conftest->creds->destroy(conftest->creds);
|
conftest->creds->destroy(conftest->creds);
|
||||||
|
DESTROY_IF(conftest->actions);
|
||||||
while (conftest->hooks->remove_last(conftest->hooks,
|
while (conftest->hooks->remove_last(conftest->hooks,
|
||||||
(void**)&hook) == SUCCESS)
|
(void**)&hook) == SUCCESS)
|
||||||
{
|
{
|
||||||
@@ -378,6 +379,7 @@ int main(int argc, char *argv[])
|
|||||||
charon->backends->add_backend(charon->backends, &conftest->config->backend);
|
charon->backends->add_backend(charon->backends, &conftest->config->backend);
|
||||||
conftest->config->load(conftest->config, conftest->suite);
|
conftest->config->load(conftest->config, conftest->suite);
|
||||||
conftest->config->load(conftest->config, conftest->test);
|
conftest->config->load(conftest->config, conftest->test);
|
||||||
|
conftest->actions = actions_create();
|
||||||
|
|
||||||
/* set up thread specific handlers */
|
/* set up thread specific handlers */
|
||||||
action.sa_handler = segv_handler;
|
action.sa_handler = segv_handler;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include <credentials/sets/mem_cred.h>
|
#include <credentials/sets/mem_cred.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "actions.h"
|
||||||
|
|
||||||
typedef struct conftest_t conftest_t;
|
typedef struct conftest_t conftest_t;
|
||||||
|
|
||||||
@@ -68,6 +69,11 @@ struct conftest_t {
|
|||||||
* Loaded hooks
|
* Loaded hooks
|
||||||
*/
|
*/
|
||||||
linked_list_t *hooks;
|
linked_list_t *hooks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action handling
|
||||||
|
*/
|
||||||
|
actions_t *actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user