diff options
Diffstat (limited to 'src/charon/plugins/uci')
-rw-r--r-- | src/charon/plugins/uci/Makefile.am | 3 | ||||
-rw-r--r-- | src/charon/plugins/uci/Makefile.in | 8 | ||||
-rw-r--r-- | src/charon/plugins/uci/uci_config.c | 11 | ||||
-rw-r--r-- | src/charon/plugins/uci/uci_control.c | 301 | ||||
-rw-r--r-- | src/charon/plugins/uci/uci_control.h | 43 | ||||
-rw-r--r-- | src/charon/plugins/uci/uci_parser.c | 11 | ||||
-rw-r--r-- | src/charon/plugins/uci/uci_plugin.c | 10 |
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); |