Add a stroke attribute_handler requesting DNS servers given with leftdns
authorMartin Willi <martin@revosec.ch>
Tue, 31 Jul 2012 09:09:19 +0000 (11:09 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 21 Aug 2012 07:38:01 +0000 (09:38 +0200)
src/libcharon/plugins/stroke/Makefile.am
src/libcharon/plugins/stroke/stroke_handler.c [new file with mode: 0644]
src/libcharon/plugins/stroke/stroke_handler.h [new file with mode: 0644]
src/libcharon/plugins/stroke/stroke_socket.c

index e561224..cebcd98 100644 (file)
@@ -21,6 +21,7 @@ libstrongswan_stroke_la_SOURCES = \
        stroke_cred.h stroke_cred.c \
        stroke_ca.h stroke_ca.c \
        stroke_attribute.h stroke_attribute.c \
+       stroke_handler.h stroke_handler.c \
        stroke_list.h stroke_list.c
 
 libstrongswan_stroke_la_LDFLAGS = -module -avoid-version
diff --git a/src/libcharon/plugins/stroke/stroke_handler.c b/src/libcharon/plugins/stroke/stroke_handler.c
new file mode 100644 (file)
index 0000000..e15daf4
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 "stroke_handler.h"
+
+#include <daemon.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_stroke_handler_t private_stroke_handler_t;
+
+/**
+ * Private data of an stroke_handler_t object.
+ */
+struct private_stroke_handler_t {
+
+       /**
+        * Public stroke_handler_t interface.
+        */
+       stroke_handler_t public;
+
+       /**
+        * List of connection specific attributes, as attributes_t
+        */
+       linked_list_t *attrs;
+
+       /**
+        * rwlock to lock access to pools
+        */
+       rwlock_t *lock;
+};
+
+/**
+ * Attributes assigned to a connection
+ */
+typedef struct {
+       /** name of the connection */
+       char *name;
+       /** list of DNS attributes, as host_t */
+       linked_list_t *dns;
+} attributes_t;
+
+/**
+ * Destroy an attributes_t entry
+ */
+static void attributes_destroy(attributes_t *this)
+{
+       this->dns->destroy_offset(this->dns, offsetof(host_t, destroy));
+       free(this->name);
+       free(this);
+}
+
+/**
+ * Filter function to convert host to DNS configuration attributes
+ */
+static bool attr_filter(void *lock, host_t **in,
+                                               configuration_attribute_type_t *type,
+                                               void *dummy, chunk_t *data)
+{
+       host_t *host = *in;
+
+       switch (host->get_family(host))
+       {
+               case AF_INET:
+                       *type = INTERNAL_IP4_DNS;
+                       break;
+               case AF_INET6:
+                       *type = INTERNAL_IP6_DNS;
+                       break;
+               default:
+                       return FALSE;
+       }
+       if (host->is_anyaddr(host))
+       {
+               *data = chunk_empty;
+       }
+       else
+       {
+               *data = host->get_address(host);
+       }
+       return TRUE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t*,
+       private_stroke_handler_t *this, identification_t *server, host_t *vip)
+{
+       ike_sa_t *ike_sa;
+       peer_cfg_t *peer_cfg;
+       enumerator_t *enumerator;
+       attributes_t *attr;
+
+       ike_sa = charon->bus->get_sa(charon->bus);
+       if (ike_sa)
+       {
+               peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+               this->lock->read_lock(this->lock);
+               enumerator = this->attrs->create_enumerator(this->attrs);
+               while (enumerator->enumerate(enumerator, &attr))
+               {
+                       if (streq(attr->name, peer_cfg->get_name(peer_cfg)))
+                       {
+                               enumerator->destroy(enumerator);
+                               return enumerator_create_filter(
+                                                                       attr->dns->create_enumerator(attr->dns),
+                                                                       (void*)attr_filter, this->lock,
+                                                                       (void*)this->lock->unlock);
+                       }
+               }
+               enumerator->destroy(enumerator);
+               this->lock->unlock(this->lock);
+       }
+       return enumerator_create_empty();
+}
+
+METHOD(stroke_handler_t, add_attributes, void,
+       private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+       if (msg->add_conn.me.dns)
+       {
+               enumerator_t *enumerator;
+               attributes_t *attr = NULL;
+               host_t *host;
+               char *token;
+
+               enumerator = enumerator_create_token(msg->add_conn.me.dns, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
+               {
+                       if (streq(token, "%config") || streq(token, "%config4"))
+                       {
+                               host = host_create_any(AF_INET);
+                       }
+                       else if (streq(token, "%config6"))
+                       {
+                               host = host_create_any(AF_INET6);
+                       }
+                       else
+                       {
+                               host = host_create_from_string(token, 0);
+                       }
+                       if (host)
+                       {
+                               if (!attr)
+                               {
+                                       INIT(attr,
+                                               .name = strdup(msg->add_conn.name),
+                                               .dns = linked_list_create(),
+                                       );
+                               }
+                               attr->dns->insert_last(attr->dns, host);
+                       }
+                       else
+                       {
+                               DBG1(DBG_CFG, "ignoring invalid DNS address '%s'", token);
+                       }
+               }
+               enumerator->destroy(enumerator);
+               if (attr)
+               {
+                       this->lock->write_lock(this->lock);
+                       this->attrs->insert_last(this->attrs, attr);
+                       this->lock->unlock(this->lock);
+               }
+       }
+}
+
+METHOD(stroke_handler_t, del_attributes, void,
+       private_stroke_handler_t *this, stroke_msg_t *msg)
+{
+       enumerator_t *enumerator;
+       attributes_t *attr;
+
+       this->lock->write_lock(this->lock);
+       enumerator = this->attrs->create_enumerator(this->attrs);
+       while (enumerator->enumerate(enumerator, &attr))
+       {
+               if (streq(msg->del_conn.name, attr->name))
+               {
+                       this->attrs->remove_at(this->attrs, enumerator);
+                       attributes_destroy(attr);
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+}
+
+METHOD(stroke_handler_t, destroy, void,
+       private_stroke_handler_t *this)
+{
+       this->lock->destroy(this->lock);
+       this->attrs->destroy_function(this->attrs, (void*)attributes_destroy);
+       free(this);
+}
+
+/**
+ * See header
+ */
+stroke_handler_t *stroke_handler_create()
+{
+       private_stroke_handler_t *this;
+
+       INIT(this,
+               .public = {
+                       .handler = {
+                               .handle = (void*)return_false,
+                               .release = (void*)return_false,
+                               .create_attribute_enumerator = _create_attribute_enumerator,
+                       },
+                       .add_attributes = _add_attributes,
+                       .del_attributes = _del_attributes,
+                       .destroy = _destroy,
+               },
+               .attrs = linked_list_create(),
+               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/stroke/stroke_handler.h b/src/libcharon/plugins/stroke/stroke_handler.h
new file mode 100644 (file)
index 0000000..ab76f80
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 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 stroke_handler stroke_handler
+ * @{ @ingroup stroke
+ */
+
+#ifndef STROKE_HANDLER_H_
+#define STROKE_HANDLER_H_
+
+#include <stroke_msg.h>
+#include <attributes/attribute_handler.h>
+
+typedef struct stroke_handler_t stroke_handler_t;
+
+/**
+ * Handler requesting DNS attributes as defined with leftdns option.
+ */
+struct stroke_handler_t {
+
+       /**
+        * Implements the attribute_handler_t interface
+        */
+       attribute_handler_t handler;
+
+       /**
+        * Add connection specific configuration attributes.
+        *
+        * @param msg           stroke message
+        */
+       void (*add_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+       /**
+        * Remove connection specific configuration attributes.
+        *
+        * @param msg           stroke message
+        */
+       void (*del_attributes)(stroke_handler_t *this, stroke_msg_t *msg);
+
+       /**
+        * Destroy a stroke_handler_t.
+        */
+       void (*destroy)(stroke_handler_t *this);
+};
+
+/**
+ * Create a stroke_handler instance.
+ */
+stroke_handler_t *stroke_handler_create();
+
+#endif /** STROKE_HANDLER_H_ @}*/
index 427a5e8..df43e16 100644 (file)
@@ -37,6 +37,7 @@
 #include "stroke_cred.h"
 #include "stroke_ca.h"
 #include "stroke_attribute.h"
+#include "stroke_handler.h"
 #include "stroke_list.h"
 
 /**
@@ -99,6 +100,11 @@ struct private_stroke_socket_t {
        stroke_attribute_t *attribute;
 
        /**
+        * attribute handler (requests only)
+        */
+       stroke_handler_t *handler;
+
+       /**
         * controller to control daemon
         */
        stroke_control_t *control;
@@ -238,6 +244,7 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
 
        this->config->add(this->config, msg);
        this->attribute->add_pool(this->attribute, msg);
+       this->handler->add_attributes(this->handler, msg);
 }
 
 /**
@@ -250,6 +257,7 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
 
        this->config->del(this->config, msg);
        this->attribute->del_pool(this->attribute, msg);
+       this->handler->del_attributes(this->handler, msg);
 }
 
 /**
@@ -789,10 +797,12 @@ METHOD(stroke_socket_t, destroy, void,
        lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
        charon->backends->remove_backend(charon->backends, &this->config->backend);
        hydra->attributes->remove_provider(hydra->attributes, &this->attribute->provider);
+       hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
        this->cred->destroy(this->cred);
        this->ca->destroy(this->ca);
        this->config->destroy(this->config);
        this->attribute->destroy(this->attribute);
+       this->handler->destroy(this->handler);
        this->control->destroy(this->control);
        this->list->destroy(this->list);
        free(this);
@@ -819,6 +829,7 @@ stroke_socket_t *stroke_socket_create()
 
        this->cred = stroke_cred_create();
        this->attribute = stroke_attribute_create();
+       this->handler = stroke_handler_create();
        this->ca = stroke_ca_create(this->cred);
        this->config = stroke_config_create(this->ca, this->cred);
        this->control = stroke_control_create();
@@ -835,6 +846,7 @@ stroke_socket_t *stroke_socket_create()
        lib->credmgr->add_set(lib->credmgr, &this->cred->set);
        charon->backends->add_backend(charon->backends, &this->config->backend);
        hydra->attributes->add_provider(hydra->attributes, &this->attribute->provider);
+       hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
 
        lib->processor->queue_job(lib->processor,
                (job_t*)callback_job_create_with_prio((callback_job_cb_t)receive, this,