extended UCI plugin by a simple control interface using a fifo
This commit is contained in:
@@ -6,7 +6,8 @@ AM_CFLAGS = -rdynamic
|
|||||||
plugin_LTLIBRARIES = libstrongswan-uci.la
|
plugin_LTLIBRARIES = libstrongswan-uci.la
|
||||||
libstrongswan_uci_la_SOURCES = \
|
libstrongswan_uci_la_SOURCES = \
|
||||||
uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \
|
uci_plugin.h uci_plugin.c uci_parser.h uci_parser.c \
|
||||||
uci_config.h uci_config.c uci_creds.h uci_creds.c
|
uci_config.h uci_config.c uci_creds.h uci_creds.c \
|
||||||
|
uci_control.h uci_control.c
|
||||||
libstrongswan_uci_la_LDFLAGS = -module
|
libstrongswan_uci_la_LDFLAGS = -module
|
||||||
libstrongswan_uci_la_LIBADD = -luci
|
libstrongswan_uci_la_LIBADD = -luci
|
||||||
|
|
||||||
|
|||||||
@@ -352,7 +352,6 @@ uci_config_t *uci_config_create(uci_parser_t *parser)
|
|||||||
this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
|
this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
|
||||||
this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
|
this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
|
||||||
this->public.destroy = (void(*)(uci_config_t*))destroy;
|
this->public.destroy = (void(*)(uci_config_t*))destroy;
|
||||||
|
|
||||||
this->parser = parser;
|
this->parser = parser;
|
||||||
|
|
||||||
return &this->public;
|
return &this->public;
|
||||||
|
|||||||
@@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Thomas Kallenberg
|
||||||
|
* Copyright (C) 2008 Martin Willi
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#include "uci_control.h"
|
||||||
|
|
||||||
|
#include <daemon.h>
|
||||||
|
#include <processing/jobs/callback_job.h>
|
||||||
|
|
||||||
|
#define FIFO_FILE "/var/run/charon.fifo"
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct private_uci_control_t private_uci_control_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* private data of uci_control_t
|
||||||
|
*/
|
||||||
|
struct private_uci_control_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public part
|
||||||
|
*/
|
||||||
|
uci_control_t public;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Job
|
||||||
|
*/
|
||||||
|
callback_job_t *job;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write answer to fifo
|
||||||
|
*/
|
||||||
|
static void write_fifo(private_uci_control_t *this, char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
out = fopen(FIFO_FILE, "w");
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
va_start(args, format);
|
||||||
|
vfprintf(out, format, args);
|
||||||
|
va_end(args);
|
||||||
|
fclose(out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "writing to UCI fifo failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print IKE_SA status information
|
||||||
|
*/
|
||||||
|
static void status(private_uci_control_t *this, char *name)
|
||||||
|
{
|
||||||
|
enumerator_t *configs, *sas;
|
||||||
|
iterator_t *children;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
child_sa_t *child_sa;
|
||||||
|
peer_cfg_t *peer_cfg;
|
||||||
|
char buf[2048];
|
||||||
|
FILE *out = NULL;
|
||||||
|
|
||||||
|
configs = charon->backends->create_peer_cfg_enumerator(charon->backends);
|
||||||
|
while (configs->enumerate(configs, &peer_cfg))
|
||||||
|
{
|
||||||
|
if (name && !streq(name, peer_cfg->get_name(peer_cfg)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
sas = charon->controller->create_ike_sa_enumerator(charon->controller);
|
||||||
|
while (sas->enumerate(sas, &ike_sa))
|
||||||
|
{
|
||||||
|
if (!streq(ike_sa->get_name(ike_sa), peer_cfg->get_name(peer_cfg)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!out)
|
||||||
|
{
|
||||||
|
out = fmemopen(buf, sizeof(buf), "w");
|
||||||
|
if (!out)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf(out, "%-8s %-20D %-16H ", ike_sa->get_name(ike_sa),
|
||||||
|
ike_sa->get_other_id(ike_sa), ike_sa->get_other_host(ike_sa));
|
||||||
|
|
||||||
|
children = ike_sa->create_child_sa_iterator(ike_sa);
|
||||||
|
while (children->iterate(children, (void**)&child_sa))
|
||||||
|
{
|
||||||
|
fprintf(out, "%#R",
|
||||||
|
child_sa->get_traffic_selectors(child_sa, FALSE));
|
||||||
|
}
|
||||||
|
children->destroy(children);
|
||||||
|
fprintf(out, "\n");
|
||||||
|
}
|
||||||
|
sas->destroy(sas);
|
||||||
|
}
|
||||||
|
configs->destroy(configs);
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
fclose(out);
|
||||||
|
write_fifo(this, "%s", buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_fifo(this, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiate an IKE_SA
|
||||||
|
*/
|
||||||
|
static void initiate(private_uci_control_t *this, char *name)
|
||||||
|
{
|
||||||
|
peer_cfg_t *peer_cfg;
|
||||||
|
child_cfg_t *child_cfg;
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
|
||||||
|
peer_cfg = charon->backends->get_peer_cfg_by_name(charon->backends, name);
|
||||||
|
if (peer_cfg)
|
||||||
|
{
|
||||||
|
enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
|
||||||
|
if (enumerator->enumerate(enumerator, &child_cfg) &&
|
||||||
|
charon->controller->initiate(charon->controller, peer_cfg,
|
||||||
|
child_cfg->get_ref(child_cfg),
|
||||||
|
controller_cb_empty, NULL) == SUCCESS)
|
||||||
|
{
|
||||||
|
write_fifo(this, "connection '%s' established\n", name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_fifo(this, "establishing connection '%s' failed\n", name);
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_fifo(this, "no connection named '%s' found\n", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* terminate an IKE_SA
|
||||||
|
*/
|
||||||
|
static void terminate(private_uci_control_t *this, char *name)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
ike_sa_t *ike_sa;
|
||||||
|
u_int id;
|
||||||
|
|
||||||
|
enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
|
||||||
|
while (enumerator->enumerate(enumerator, &ike_sa))
|
||||||
|
{
|
||||||
|
if (streq(name, ike_sa->get_name(ike_sa)))
|
||||||
|
{
|
||||||
|
id = ike_sa->get_unique_id(ike_sa);
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
charon->controller->terminate_ike(charon->controller, id,
|
||||||
|
controller_cb_empty, NULL);
|
||||||
|
write_fifo(this, "connection '%s' terminated\n", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
write_fifo(this, "no active connection named '%s'\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dispatch control request
|
||||||
|
*/
|
||||||
|
static void process(private_uci_control_t *this, char *message)
|
||||||
|
{
|
||||||
|
enumerator_t* enumerator;
|
||||||
|
|
||||||
|
enumerator = enumerator_create_token(message, " \n", "");
|
||||||
|
if (enumerator->enumerate(enumerator, &message))
|
||||||
|
{
|
||||||
|
if (streq(message, "status"))
|
||||||
|
{
|
||||||
|
if (enumerator->enumerate(enumerator, &message))
|
||||||
|
{
|
||||||
|
status(this, message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
status(this, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (streq(message, "up") &&
|
||||||
|
enumerator->enumerate(enumerator, &message))
|
||||||
|
{
|
||||||
|
initiate(this, message);
|
||||||
|
}
|
||||||
|
else if (streq(message, "down") &&
|
||||||
|
enumerator->enumerate(enumerator, &message))
|
||||||
|
{
|
||||||
|
terminate(this, message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_fifo(this, "usage: status [<name<] | up <name> | down <name>\n"
|
||||||
|
" status format: name peer-id peer-addr tunnel(s)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read from fifo
|
||||||
|
*/
|
||||||
|
static job_requeue_t receive(private_uci_control_t *this)
|
||||||
|
{
|
||||||
|
while (TRUE)
|
||||||
|
{
|
||||||
|
char message[128];
|
||||||
|
int oldstate, len;
|
||||||
|
FILE *in;
|
||||||
|
|
||||||
|
memset(message, 0, sizeof(message));
|
||||||
|
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
|
||||||
|
in = fopen(FIFO_FILE, "r");
|
||||||
|
pthread_setcancelstate(oldstate, NULL);
|
||||||
|
if (in)
|
||||||
|
{
|
||||||
|
len = fread(message, 1, sizeof(message) - 1, in);
|
||||||
|
fclose(in);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
process(this, message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_DMN, "reading from UCI fifo failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_DMN, "opening UCI fifo failed: %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return JOB_REQUEUE_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of uci_control_t.destroy
|
||||||
|
*/
|
||||||
|
static void destroy(private_uci_control_t *this)
|
||||||
|
{
|
||||||
|
this->job->cancel(this->job);
|
||||||
|
unlink(FIFO_FILE);
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Described in header.
|
||||||
|
*/
|
||||||
|
uci_control_t *uci_control_create()
|
||||||
|
{
|
||||||
|
private_uci_control_t *this = malloc_thing(private_uci_control_t);
|
||||||
|
|
||||||
|
this->public.destroy = (void(*)(uci_control_t*))destroy;
|
||||||
|
|
||||||
|
if (access(FIFO_FILE, F_OK) != 0 &&
|
||||||
|
mkfifo(FIFO_FILE, S_IRUSR|S_IWUSR) != 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_CFG, "creating UCI control fifo '%s' failed: %s",
|
||||||
|
FIFO_FILE, strerror(errno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->job = callback_job_create((callback_job_cb_t)receive,
|
||||||
|
this, NULL, NULL);
|
||||||
|
charon->processor->queue_job(charon->processor, (job_t*)this->job);
|
||||||
|
}
|
||||||
|
return &this->public;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2008 Thomas Kallenberg
|
||||||
|
* Hochschule fuer Technik Rapperswil
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup uci_control_t uci_control
|
||||||
|
* @{ @ingroup uci
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UCI_CONTROL_H_
|
||||||
|
#define UCI_CONTROL_H_
|
||||||
|
|
||||||
|
typedef struct uci_control_t uci_control_t;
|
||||||
|
|
||||||
|
struct uci_control_t {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the controller
|
||||||
|
*/
|
||||||
|
|
||||||
|
void (*destroy)(uci_control_t *this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a UCI based configuration backend.
|
||||||
|
*/
|
||||||
|
|
||||||
|
uci_control_t *uci_control_create();
|
||||||
|
|
||||||
|
#endif /*UCI_CONTROL_H_@}*/
|
||||||
@@ -76,11 +76,18 @@ static bool section_enumerator_enumerate(section_enumerator_t *this, ...)
|
|||||||
|
|
||||||
va_start(args, this);
|
va_start(args, this);
|
||||||
|
|
||||||
/* name is first parameter */
|
|
||||||
value = va_arg(args, char**);
|
value = va_arg(args, char**);
|
||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
*value = uci_to_section(this->current)->type;
|
if (uci_lookup(this->ctx, &element, this->package,
|
||||||
|
this->current->name, "name") == UCI_OK)
|
||||||
|
{ /* use "name" attribute as config name if available ... */
|
||||||
|
*value = uci_to_option(element)->value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ /* ... or the section name becomes config name */
|
||||||
|
*value = uci_to_section(this->current)->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* followed by keyword parameters */
|
/* followed by keyword parameters */
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "uci_plugin.h"
|
#include "uci_plugin.h"
|
||||||
#include "uci_config.h"
|
#include "uci_config.h"
|
||||||
#include "uci_creds.h"
|
#include "uci_creds.h"
|
||||||
|
#include "uci_control.h"
|
||||||
|
|
||||||
#include <daemon.h>
|
#include <daemon.h>
|
||||||
|
|
||||||
@@ -52,6 +53,11 @@ struct private_uci_plugin_t {
|
|||||||
* UCI parser wrapper
|
* UCI parser wrapper
|
||||||
*/
|
*/
|
||||||
uci_parser_t *parser;
|
uci_parser_t *parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UCI control interface
|
||||||
|
*/
|
||||||
|
uci_control_t *control;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,6 +70,7 @@ static void destroy(private_uci_plugin_t *this)
|
|||||||
this->config->destroy(this->config);
|
this->config->destroy(this->config);
|
||||||
this->creds->destroy(this->creds);
|
this->creds->destroy(this->creds);
|
||||||
this->parser->destroy(this->parser);
|
this->parser->destroy(this->parser);
|
||||||
|
this->control->destroy(this->control);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +86,7 @@ plugin_t *plugin_create()
|
|||||||
this->parser = uci_parser_create(UCI_PACKAGE);
|
this->parser = uci_parser_create(UCI_PACKAGE);
|
||||||
this->config = uci_config_create(this->parser);
|
this->config = uci_config_create(this->parser);
|
||||||
this->creds = uci_creds_create(this->parser);
|
this->creds = uci_creds_create(this->parser);
|
||||||
|
this->control = uci_control_create();
|
||||||
charon->backends->add_backend(charon->backends, &this->config->backend);
|
charon->backends->add_backend(charon->backends, &this->config->backend);
|
||||||
charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
|
charon->credentials->add_set(charon->credentials, &this->creds->credential_set);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user