From 5f95657c657d700ae994aa8690f2b32f2fad68b8 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 10 Feb 2014 17:10:54 +0100 Subject: [PATCH] vici: Add a control backend, currently to initiate connections by name --- src/libcharon/plugins/vici/Makefile.am | 1 + src/libcharon/plugins/vici/vici_control.c | 219 ++++++++++++++++++++++++++++++ src/libcharon/plugins/vici/vici_control.h | 47 +++++++ src/libcharon/plugins/vici/vici_plugin.c | 8 ++ 4 files changed, 275 insertions(+) create mode 100644 src/libcharon/plugins/vici/vici_control.c create mode 100644 src/libcharon/plugins/vici/vici_control.h diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am index df6ecc1..6ec830e 100644 --- a/src/libcharon/plugins/vici/Makefile.am +++ b/src/libcharon/plugins/vici/Makefile.am @@ -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 diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c new file mode 100644 index 0000000..ecf1909 --- /dev/null +++ b/src/libcharon/plugins/vici/vici_control.c @@ -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 . + * + * 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 + +#include + +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, ¤t)) + { + 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; +} diff --git a/src/libcharon/plugins/vici/vici_control.h b/src/libcharon/plugins/vici/vici_control.h new file mode 100644 index 0000000..71a13a0 --- /dev/null +++ b/src/libcharon/plugins/vici/vici_control.h @@ -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 . + * + * 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_ @}*/ diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c index fb016ac..0bceefc 100644 --- a/src/libcharon/plugins/vici/vici_plugin.c +++ b/src/libcharon/plugins/vici/vici_plugin.c @@ -16,6 +16,7 @@ #include "vici_plugin.h" #include "vici_dispatcher.h" #include "vici_query.h" +#include "vici_control.h" #include #include @@ -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); } -- 2.7.4