summaryrefslogtreecommitdiff
path: root/src/charon/plugins/uci
diff options
context:
space:
mode:
Diffstat (limited to 'src/charon/plugins/uci')
-rw-r--r--src/charon/plugins/uci/Makefile.am3
-rw-r--r--src/charon/plugins/uci/Makefile.in8
-rw-r--r--src/charon/plugins/uci/uci_config.c11
-rw-r--r--src/charon/plugins/uci/uci_control.c301
-rw-r--r--src/charon/plugins/uci/uci_control.h43
-rw-r--r--src/charon/plugins/uci/uci_parser.c11
-rw-r--r--src/charon/plugins/uci/uci_plugin.c10
7 files changed, 377 insertions, 10 deletions
diff --git a/src/charon/plugins/uci/Makefile.am b/src/charon/plugins/uci/Makefile.am
index 47a55ae17..0136bf5e9 100644
--- a/src/charon/plugins/uci/Makefile.am
+++ b/src/charon/plugins/uci/Makefile.am
@@ -6,7 +6,8 @@ AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-uci.la
libstrongswan_uci_la_SOURCES = \
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_LIBADD = -luci
diff --git a/src/charon/plugins/uci/Makefile.in b/src/charon/plugins/uci/Makefile.in
index 297f25768..17a1212f3 100644
--- a/src/charon/plugins/uci/Makefile.in
+++ b/src/charon/plugins/uci/Makefile.in
@@ -51,7 +51,7 @@ pluginLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(plugin_LTLIBRARIES)
libstrongswan_uci_la_DEPENDENCIES =
am_libstrongswan_uci_la_OBJECTS = uci_plugin.lo uci_parser.lo \
- uci_config.lo uci_creds.lo
+ uci_config.lo uci_creds.lo uci_control.lo
libstrongswan_uci_la_OBJECTS = $(am_libstrongswan_uci_la_OBJECTS)
libstrongswan_uci_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
@@ -188,6 +188,8 @@ localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
piddir = @piddir@
@@ -212,7 +214,8 @@ AM_CFLAGS = -rdynamic
plugin_LTLIBRARIES = libstrongswan-uci.la
libstrongswan_uci_la_SOURCES = \
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_LIBADD = -luci
@@ -286,6 +289,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_control.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_creds.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_parser.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/uci_plugin.Plo@am__quote@
diff --git a/src/charon/plugins/uci/uci_config.c b/src/charon/plugins/uci/uci_config.c
index cc44eaa9b..c9d54a532 100644
--- a/src/charon/plugins/uci/uci_config.c
+++ b/src/charon/plugins/uci/uci_config.c
@@ -163,6 +163,8 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
char *remote_id, *remote_addr, *remote_net;
child_cfg_t *child_cfg;
ike_cfg_t *ike_cfg;
+ auth_info_t *auth;
+ auth_class_t class;
/* defaults */
name = "unnamed";
@@ -186,13 +188,15 @@ static bool peer_enumerator_enumerate(peer_enumerator_t *this, peer_cfg_t **cfg)
ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE));
this->peer_cfg = peer_cfg_create(
name, 2, ike_cfg, create_id(local_id), create_id(remote_id),
- CERT_SEND_IF_ASKED, UNIQUE_NO, CONF_AUTH_PSK,
- 0, 0, /* EAP method, vendor */
+ CERT_SEND_IF_ASKED, UNIQUE_NO,
1, create_rekey(ike_rekey), 0, /* keytries, rekey, reauth */
1800, 900, /* jitter, overtime */
TRUE, 60, /* mobike, dpddelay */
NULL, NULL, /* vip, pool */
FALSE, NULL, NULL); /* mediation, med by, peer id */
+ auth = this->peer_cfg->get_auth(this->peer_cfg);
+ class = AUTH_CLASS_PSK;
+ auth->add_item(auth, AUTHN_AUTH_CLASS, &class);
child_cfg = child_cfg_create(name,
create_rekey(esp_rekey) + 300, create_rekey(ike_rekey), 300,
NULL, TRUE, MODE_TUNNEL, ACTION_NONE, ACTION_NONE, FALSE);
@@ -352,9 +356,8 @@ 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.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->parser = parser;
-
+
return &this->public;
}
diff --git a/src/charon/plugins/uci/uci_control.c b/src/charon/plugins/uci/uci_control.c
new file mode 100644
index 000000000..2ffdd2b7b
--- /dev/null
+++ b/src/charon/plugins/uci/uci_control.c
@@ -0,0 +1,301 @@
+/*
+ * 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)
+{
+ 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_FAIR;
+}
+
+/**
+ * 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;
+
+ unlink(FIFO_FILE);
+ if (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;
+}
+
diff --git a/src/charon/plugins/uci/uci_control.h b/src/charon/plugins/uci/uci_control.h
new file mode 100644
index 000000000..774c42661
--- /dev/null
+++ b/src/charon/plugins/uci/uci_control.h
@@ -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_@}*/
diff --git a/src/charon/plugins/uci/uci_parser.c b/src/charon/plugins/uci/uci_parser.c
index 796d2993a..8f4acb938 100644
--- a/src/charon/plugins/uci/uci_parser.c
+++ b/src/charon/plugins/uci/uci_parser.c
@@ -76,11 +76,18 @@ static bool section_enumerator_enumerate(section_enumerator_t *this, ...)
va_start(args, this);
- /* name is first parameter */
value = va_arg(args, char**);
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 */
diff --git a/src/charon/plugins/uci/uci_plugin.c b/src/charon/plugins/uci/uci_plugin.c
index 918523826..fd84b224c 100644
--- a/src/charon/plugins/uci/uci_plugin.c
+++ b/src/charon/plugins/uci/uci_plugin.c
@@ -18,6 +18,7 @@
#include "uci_plugin.h"
#include "uci_config.h"
#include "uci_creds.h"
+#include "uci_control.h"
#include <daemon.h>
@@ -52,6 +53,11 @@ struct private_uci_plugin_t {
* UCI parser wrapper
*/
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->creds->destroy(this->creds);
this->parser->destroy(this->parser);
+ this->control->destroy(this->control);
free(this);
}
@@ -75,10 +82,11 @@ plugin_t *plugin_create()
private_uci_plugin_t *this = malloc_thing(private_uci_plugin_t);
this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
-
+
this->parser = uci_parser_create(UCI_PACKAGE);
this->config = uci_config_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->credentials->add_set(charon->credentials, &this->creds->credential_set);