vici: Add a control backend, currently to initiate connections by name

This commit is contained in:
Martin Willi 2014-02-10 17:10:54 +01:00
parent ecc4b51048
commit 5f95657c65
4 changed files with 275 additions and 0 deletions

View File

@ -19,6 +19,7 @@ libstrongswan_vici_la_SOURCES = \
vici_builder.h vici_builder.c \
vici_dispatcher.h vici_dispatcher.c \
vici_query.h vici_query.c \
vici_control.h vici_control.c \
vici_plugin.h vici_plugin.c
libstrongswan_vici_la_LDFLAGS = -module -avoid-version

View File

@ -0,0 +1,219 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 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 "vici_control.h"
#include "vici_builder.h"
#include <inttypes.h>
#include <daemon.h>
typedef struct private_vici_control_t private_vici_control_t;
/**
* Private data of an vici_control_t object.
*/
struct private_vici_control_t {
/**
* Public vici_control_t interface.
*/
vici_control_t public;
/**
* Dispatcher
*/
vici_dispatcher_t *dispatcher;
};
/**
* Log callback helper data
*/
typedef struct {
/** dispatcher to send log messages over */
vici_dispatcher_t *dispatcher;
/** connection ID to send messages to */
u_int id;
/** loglevel */
level_t level;
} log_info_t;
/**
* Log using vici event messages
*/
static bool log_vici(log_info_t *info, debug_t group, level_t level,
ike_sa_t *ike_sa, char *text)
{
if (level <= info->level)
{
vici_message_t *message;
vici_builder_t *builder;
builder = vici_builder_create();
builder->add_kv(builder, "group", "%N", debug_names, group);
builder->add_kv(builder, "level", "%d", level);
if (ike_sa)
{
builder->add_kv(builder, "ikesa-name", "%s",
ike_sa->get_name(ike_sa));
builder->add_kv(builder, "ikesa-uniqueid", "%u",
ike_sa->get_unique_id(ike_sa));
}
builder->add_kv(builder, "msg", "%s", text);
message = builder->finalize(builder);
if (message)
{
info->dispatcher->raise_event(info->dispatcher, "control-log",
info->id, message);
}
}
return TRUE;
}
/**
* Send a (error) reply message
*/
static vici_message_t* send_reply(private_vici_control_t *this, char *fmt, ...)
{
vici_builder_t *builder;
va_list args;
builder = vici_builder_create();
builder->add_kv(builder, "success", fmt ? "no" : "yes");
if (fmt)
{
va_start(args, fmt);
builder->vadd_kv(builder, "errmsg", fmt, args);
va_end(args);
}
return builder->finalize(builder);
}
/**
* Get the child_cfg having name from peer_cfg
*/
static child_cfg_t* get_child_from_peer(peer_cfg_t *peer_cfg, char *name)
{
child_cfg_t *current, *found = NULL;
enumerator_t *enumerator;
enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
while (enumerator->enumerate(enumerator, &current))
{
if (streq(current->get_name(current), name))
{
found = current;
found->get_ref(found);
break;
}
}
enumerator->destroy(enumerator);
return found;
}
CALLBACK(initiate, vici_message_t*,
private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
{
child_cfg_t *child_cfg = NULL;
peer_cfg_t *peer_cfg;
enumerator_t *enumerator;
char *child;
u_int timeout;
log_info_t log = {
.dispatcher = this->dispatcher,
.id = id,
};
child = request->get_str(request, NULL, "child");
timeout = request->get_int(request, 0, "timeout");
log.level = request->get_int(request, 1, "loglevel");
if (!child)
{
return send_reply(this, "missing configuration name");
}
enumerator = charon->backends->create_peer_cfg_enumerator(charon->backends,
NULL, NULL, NULL, NULL, IKE_ANY);
while (enumerator->enumerate(enumerator, &peer_cfg))
{
child_cfg = get_child_from_peer(peer_cfg, child);
if (child_cfg)
{
peer_cfg->get_ref(peer_cfg);
break;
}
}
enumerator->destroy(enumerator);
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))
{
case SUCCESS:
return send_reply(this, NULL);
case OUT_OF_RES:
return send_reply(this, "CHILD_SA '%s' not established after %dms",
child, timeout);
case FAILED:
default:
return send_reply(this, "establishing CHILD_SA '%s' failed", child);
}
}
static void manage_command(private_vici_control_t *this,
char *name, vici_command_cb_t cb, bool reg)
{
this->dispatcher->manage_command(this->dispatcher, name,
reg ? cb : NULL, this);
}
/**
* (Un-)register dispatcher functions
*/
static void manage_commands(private_vici_control_t *this, bool reg)
{
manage_command(this, "initiate", initiate, reg);
this->dispatcher->manage_event(this->dispatcher, "control-log", reg);
}
METHOD(vici_control_t, destroy, void,
private_vici_control_t *this)
{
manage_commands(this, FALSE);
free(this);
}
/**
* See header
*/
vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher)
{
private_vici_control_t *this;
INIT(this,
.public = {
.destroy = _destroy,
},
.dispatcher = dispatcher,
);
manage_commands(this, TRUE);
return &this->public;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 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 vici_control vici_control
* @{ @ingroup vici
*/
#include "vici_dispatcher.h"
#ifndef VICI_CONTROL_H_
#define VICI_CONTROL_H_
typedef struct vici_control_t vici_control_t;
/**
* Control helper, provides initiate/terminate and other commands.
*/
struct vici_control_t {
/**
* Destroy a vici_control_t.
*/
void (*destroy)(vici_control_t *this);
};
/**
* Create a vici_control instance.
*
* @param dispatcher dispatcher to receive requests from
* @return query handler
*/
vici_control_t *vici_control_create(vici_dispatcher_t *dispatcher);
#endif /** VICI_CONTROL_H_ @}*/

View File

@ -16,6 +16,7 @@
#include "vici_plugin.h"
#include "vici_dispatcher.h"
#include "vici_query.h"
#include "vici_control.h"
#include <library.h>
#include <daemon.h>
@ -41,6 +42,11 @@ struct private_vici_plugin_t {
* Query commands
*/
vici_query_t *query;
/**
* Control commands
*/
vici_control_t *control;
};
METHOD(plugin_t, get_name, char*,
@ -65,12 +71,14 @@ static bool register_vici(private_vici_plugin_t *this,
if (this->dispatcher)
{
this->query = vici_query_create(this->dispatcher);
this->control = vici_control_create(this->dispatcher);
return TRUE;
}
return FALSE;
}
else
{
this->control->destroy(this->control);
this->query->destroy(this->query);
this->dispatcher->destroy(this->dispatcher);
}