Add a Unity attribute provider that adds Split-Includes for TS
authorMartin Willi <martin@revosec.ch>
Tue, 24 Jul 2012 10:21:25 +0000 (12:21 +0200)
committerMartin Willi <martin@revosec.ch>
Tue, 18 Sep 2012 15:17:47 +0000 (17:17 +0200)
src/libcharon/plugins/unity/Makefile.am
src/libcharon/plugins/unity/unity_plugin.c
src/libcharon/plugins/unity/unity_provider.c [new file with mode: 0644]
src/libcharon/plugins/unity/unity_provider.h [new file with mode: 0644]

index 4c3cb88..b23143f 100644 (file)
@@ -13,6 +13,7 @@ endif
 libstrongswan_unity_la_SOURCES = \
        unity_plugin.h unity_plugin.c \
        unity_handler.h unity_handler.c \
-       unity_narrow.h unity_narrow.c
+       unity_narrow.h unity_narrow.c \
+       unity_provider.h unity_provider.c
 
 libstrongswan_unity_la_LDFLAGS = -module -avoid-version
index 092dfed..9e21bd9 100644 (file)
@@ -16,6 +16,7 @@
 #include "unity_plugin.h"
 #include "unity_handler.h"
 #include "unity_narrow.h"
+#include "unity_provider.h"
 
 #include <daemon.h>
 #include <hydra.h>
@@ -38,6 +39,11 @@ struct private_unity_plugin_t {
        unity_handler_t *handler;
 
        /**
+        * Responder Unity configuration attribute provider
+        */
+       unity_provider_t *provider;
+
+       /**
         * Traffic selector narrower, for Unity Split-Includes
         */
        unity_narrow_t *narrower;
@@ -55,7 +61,10 @@ METHOD(plugin_t, destroy, void,
        charon->bus->remove_listener(charon->bus, &this->narrower->listener);
        this->narrower->destroy(this->narrower);
        hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler);
+       hydra->attributes->remove_provider(hydra->attributes,
+                                                                          &this->provider->provider);
        this->handler->destroy(this->handler);
+       this->provider->destroy(this->provider);
        free(this);
 }
 
@@ -75,8 +84,10 @@ plugin_t *unity_plugin_create()
                        },
                },
                .handler = unity_handler_create(),
+               .provider = unity_provider_create(),
        );
        hydra->attributes->add_handler(hydra->attributes, &this->handler->handler);
+       hydra->attributes->add_provider(hydra->attributes, &this->provider->provider);
 
        this->narrower = unity_narrow_create(this->handler),
        charon->bus->add_listener(charon->bus, &this->narrower->listener);
diff --git a/src/libcharon/plugins/unity/unity_provider.c b/src/libcharon/plugins/unity/unity_provider.c
new file mode 100644 (file)
index 0000000..753cd98
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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 "unity_provider.h"
+
+#include <daemon.h>
+
+typedef struct private_unity_provider_t private_unity_provider_t;
+
+/**
+ * Private data of an unity_provider_t object.
+ */
+struct private_unity_provider_t {
+
+       /**
+        * Public unity_provider_t interface.
+        */
+       unity_provider_t public;
+};
+
+/**
+ * Attribute enumerator for traffic selector list
+ */
+typedef struct {
+       /** Implements enumerator_t */
+       enumerator_t public;
+       /** list of traffic selectors to enumerate */
+       linked_list_t *list;
+       /** currently enumerating subnet */
+       u_char subnet[4];
+       /** currently enumerating subnet mask */
+       u_char mask[4];
+} attribute_enumerator_t;
+
+METHOD(enumerator_t, attribute_enumerate, bool,
+       attribute_enumerator_t *this, configuration_attribute_type_t *type,
+       chunk_t *attr)
+{
+       traffic_selector_t *ts;
+       u_int8_t i, mask;
+       host_t *net;
+
+       while (TRUE)
+       {
+               if (this->list->remove_first(this->list, (void**)&ts) != SUCCESS)
+               {
+                       return FALSE;
+               }
+               if (ts->get_type(ts) == TS_IPV4_ADDR_RANGE &&
+                       ts->to_subnet(ts, &net, &mask))
+               {
+                       ts->destroy(ts);
+                       break;
+               }
+               ts->destroy(ts);
+       }
+
+       memset(this->mask, 0, sizeof(this->mask));
+       for (i = 0; i < sizeof(this->mask); i++)
+       {
+               if (mask < 8)
+               {
+                       this->mask[i] = 0xFF << (8 - mask);
+                       break;
+               }
+               this->mask[i] = 0xFF;
+               mask -= 8;
+       }
+       memcpy(this->subnet, net->get_address(net).ptr, sizeof(this->subnet));
+       net->destroy(net);
+
+       *type = UNITY_SPLIT_INCLUDE;
+       *attr = chunk_create(this->subnet, sizeof(this->subnet) + sizeof(this->mask));
+
+       return TRUE;
+}
+
+METHOD(enumerator_t, attribute_destroy, void,
+       attribute_enumerator_t *this)
+{
+       this->list->destroy_offset(this->list, offsetof(traffic_selector_t, destroy));
+       free(this);
+}
+
+METHOD(attribute_provider_t, create_attribute_enumerator, enumerator_t*,
+       private_unity_provider_t *this, linked_list_t *pools, identification_t *id,
+       linked_list_t *vips)
+{
+       attribute_enumerator_t *attr_enum;
+       enumerator_t *enumerator;
+       linked_list_t *list, *current;
+       traffic_selector_t *ts;
+       ike_sa_t *ike_sa;
+       peer_cfg_t *peer_cfg;
+       child_cfg_t *child_cfg;
+
+       ike_sa = charon->bus->get_sa(charon->bus);
+       if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 ||
+               !vips->get_count(vips))
+       {
+               return NULL;
+       }
+
+       list = linked_list_create();
+       peer_cfg = ike_sa->get_peer_cfg(ike_sa);
+       enumerator = peer_cfg->create_child_cfg_enumerator(peer_cfg);
+       while (enumerator->enumerate(enumerator, &child_cfg))
+       {
+               current = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+               while (current->remove_first(current, (void**)&ts) == SUCCESS)
+               {
+                       list->insert_last(list, ts);
+               }
+               current->destroy(current);
+       }
+       enumerator->destroy(enumerator);
+
+       if (list->get_count(list) == 0)
+       {
+               list->destroy(list);
+               return NULL;
+       }
+       INIT(attr_enum,
+               .public = {
+                       .enumerate = (void*)_attribute_enumerate,
+                       .destroy = _attribute_destroy,
+               },
+               .list = list,
+       );
+       return &attr_enum->public;
+}
+
+METHOD(unity_provider_t, destroy, void,
+       private_unity_provider_t *this)
+{
+       free(this);
+}
+
+/**
+ * See header
+ */
+unity_provider_t *unity_provider_create()
+{
+       private_unity_provider_t *this;
+
+       INIT(this,
+               .public = {
+                       .provider = {
+                               .acquire_address = (void*)return_null,
+                               .release_address = (void*)return_false,
+                               .create_attribute_enumerator = _create_attribute_enumerator,
+                       },
+                       .destroy = _destroy,
+               },
+       );
+
+       return &this->public;
+}
diff --git a/src/libcharon/plugins/unity/unity_provider.h b/src/libcharon/plugins/unity/unity_provider.h
new file mode 100644 (file)
index 0000000..a25df5d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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 unity_provider unity_provider
+ * @{ @ingroup unity
+ */
+
+#ifndef UNITY_PROVIDER_H_
+#define UNITY_PROVIDER_H_
+
+typedef struct unity_provider_t unity_provider_t;
+
+#include <attributes/attribute_provider.h>
+
+/**
+ * Cisco Unity extension attribute provider.
+ */
+struct unity_provider_t {
+
+       /**
+        * Implements attribute_provier_t interface.
+        */
+       attribute_provider_t provider;
+
+       /**
+        * Destroy a unity_provider_t.
+        */
+       void (*destroy)(unity_provider_t *this);
+};
+
+/**
+ * Create a unity_provider instance.
+ */
+unity_provider_t *unity_provider_create();
+
+#endif /** UNITY_PROVIDER_H_ @}*/