Adding a whack_attribute class which manages in-memory pools in pluto and is very...
authorTobias Brunner <tobias@strongswan.org>
Tue, 30 Mar 2010 17:13:45 +0000 (19:13 +0200)
committerTobias Brunner <tobias@strongswan.org>
Tue, 6 Apr 2010 10:47:39 +0000 (12:47 +0200)
src/pluto/Makefile.am
src/pluto/whack_attribute.c [new file with mode: 0644]
src/pluto/whack_attribute.h [new file with mode: 0644]

index 1d55d01..1ef3cf7 100644 (file)
@@ -46,6 +46,7 @@ state.c state.h \
 timer.c timer.h \
 vendor.c vendor.h \
 virtual.c virtual.h \
+whack_attribute.c whack_attribute.h \
 xauth.c xauth.h \
 x509.c x509.h \
 builder.c builder.h \
diff --git a/src/pluto/whack_attribute.c b/src/pluto/whack_attribute.c
new file mode 100644 (file)
index 0000000..2ccfdb3
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * 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.
+ */
+
+#include "whack_attribute.h"
+
+#include "log.h"
+
+/* these are defined as constants in constant.h but redefined as enum values in
+ * attributes/attributes.h */
+#undef INTERNAL_IP4_SERVER
+#undef INTERNAL_IP6_SERVER
+
+#include <hydra.h>
+#include <attributes/mem_pool.h>
+#include <utils/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_whack_attribute_t private_whack_attribute_t;
+
+/**
+ * private data of whack_attribute
+ */
+struct private_whack_attribute_t {
+
+       /**
+        * public functions
+        */
+       whack_attribute_t public;
+
+       /**
+        * list of pools, contains mem_pool_t
+        */
+       linked_list_t *pools;
+
+       /**
+        * rwlock to lock access to pools
+        */
+       rwlock_t *lock;
+};
+
+/**
+ * global object
+ */
+whack_attribute_t *whack_attr;
+
+/**
+ * compare pools by name
+ */
+static bool pool_match(mem_pool_t *current, char *name)
+{
+       return name && streq(name, current->get_name(current));
+}
+
+/**
+ * find a pool by name
+ */
+static mem_pool_t *find_pool(private_whack_attribute_t *this, char *name)
+{
+       mem_pool_t *found;
+       if (this->pools->find_first(this->pools, (linked_list_match_t)pool_match,
+               (void**)&found, name) == SUCCESS)
+       {
+               return found;
+       }
+       return NULL;
+}
+
+METHOD(attribute_provider_t, acquire_address, host_t*,
+          private_whack_attribute_t *this, char *name, identification_t *id,
+          host_t *requested)
+{
+       mem_pool_t *pool;
+       host_t *addr = NULL;
+       this->lock->read_lock(this->lock);
+       pool = find_pool(this, name);
+       if (pool)
+       {
+               addr = pool->acquire_address(pool, id, requested);
+       }
+       this->lock->unlock(this->lock);
+       return addr;
+}
+
+METHOD(attribute_provider_t, release_address, bool,
+          private_whack_attribute_t *this, char *name, host_t *address,
+          identification_t *id)
+{
+       mem_pool_t *pool;
+       bool found = FALSE;
+       this->lock->read_lock(this->lock);
+       pool = find_pool(this, name);
+       if (pool)
+       {
+               found = pool->release_address(pool, address, id);
+       }
+       this->lock->unlock(this->lock);
+       return found;
+}
+
+METHOD(whack_attribute_t, add_pool, bool,
+          private_whack_attribute_t *this, const char *name,
+          const whack_end_t *right)
+{
+       mem_pool_t *pool;
+       host_t *base = NULL;
+       u_int32_t bits = 0;
+
+       /* named pool */
+       if (right->sourceip_mask <= 0)
+       {
+               return FALSE;
+       }
+
+       /* if %config, add an empty pool, otherwise */
+       if (right->sourceip)
+       {
+               DBG(DBG_CONTROL,
+                       DBG_log("adding virtual IP address pool '%s': %s/%d",
+                                       name, right->sourceip, right->sourceip_mask);
+               );
+               base = host_create_from_string(right->sourceip, 0);
+               if (!base)
+               {
+                       loglog(RC_LOG_SERIOUS, "virtual IP address invalid, discarded");
+                       return FALSE;
+               }
+               bits = right->sourceip_mask;
+       }
+       pool = mem_pool_create((char*)name, base, bits);
+       DESTROY_IF(base);
+
+       this->lock->write_lock(this->lock);
+       this->pools->insert_last(this->pools, pool);
+       this->lock->unlock(this->lock);
+       return TRUE;
+}
+
+METHOD(whack_attribute_t, del_pool, void,
+          private_whack_attribute_t *this, char *name)
+{
+       enumerator_t *enumerator;
+       mem_pool_t *pool;
+
+       this->lock->write_lock(this->lock);
+       enumerator = this->pools->create_enumerator(this->pools);
+       while (enumerator->enumerate(enumerator, &pool))
+       {
+               if (streq(name, pool->get_name(pool)))
+               {
+                       this->pools->remove_at(this->pools, enumerator);
+                       pool->destroy(pool);
+                       break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       this->lock->unlock(this->lock);
+}
+
+/**
+ * Pool enumerator filter function, converts pool_t to name, size, ...
+ */
+static bool pool_filter(void *lock, mem_pool_t **poolp, const char **name,
+                                               void *d1, u_int *size, void *d2, u_int *online,
+                                               void *d3, u_int *offline)
+{
+       mem_pool_t *pool = *poolp;
+       *name = pool->get_name(pool);
+       *size = pool->get_size(pool);
+       *online = pool->get_online(pool);
+       *offline = pool->get_offline(pool);
+       return TRUE;
+}
+
+METHOD(whack_attribute_t, create_pool_enumerator, enumerator_t*,
+          private_whack_attribute_t *this)
+{
+       this->lock->read_lock(this->lock);
+       return enumerator_create_filter(this->pools->create_enumerator(this->pools),
+                                                                       (void*)pool_filter,
+                                                                       this->lock, (void*)this->lock->unlock);
+}
+
+METHOD(whack_attribute_t, create_lease_enumerator, enumerator_t*,
+          private_whack_attribute_t *this, char *name)
+{
+       mem_pool_t *pool;
+       this->lock->read_lock(this->lock);
+       pool = find_pool(this, name);
+       if (!pool)
+       {
+               this->lock->unlock(this->lock);
+               return NULL;
+       }
+       return enumerator_create_cleaner(pool->create_lease_enumerator(pool),
+                                                                        (void*)this->lock->unlock, this->lock);
+}
+
+/**
+ * see header file
+ */
+void whack_attribute_finalize()
+{
+       private_whack_attribute_t *this = (private_whack_attribute_t*)whack_attr;
+       hydra->attributes->remove_provider(hydra->attributes,
+                                                                          &this->public.provider);
+       this->lock->destroy(this->lock);
+       this->pools->destroy_offset(this->pools, offsetof(mem_pool_t, destroy));
+       free(this);
+}
+
+/**
+ * see header file
+ */
+void whack_attribute_initialize()
+{
+       private_whack_attribute_t *this;
+
+       INIT(this,
+               .public = {
+                       .provider = {
+                               .acquire_address = _acquire_address,
+                               .release_address = _release_address,
+                               .create_attribute_enumerator = enumerator_create_empty,
+                       },
+                       .add_pool = _add_pool,
+                       .del_pool = _del_pool,
+                       .create_pool_enumerator = _create_pool_enumerator,
+                       .create_lease_enumerator = _create_lease_enumerator,
+               },
+               .pools = linked_list_create(),
+               .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+       );
+
+       hydra->attributes->add_provider(hydra->attributes, &this->public.provider);
+
+       whack_attr = &this->public;
+}
+
diff --git a/src/pluto/whack_attribute.h b/src/pluto/whack_attribute.h
new file mode 100644 (file)
index 0000000..8e2e36b
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * 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.
+ */
+
+/**
+ * @defgroup whack_attribute
+ * @{ @ingroup pluto
+ */
+
+#ifndef WHACK_ATTRIBUTE_H_
+#define WHACK_ATTRIBUTE_H_
+
+#include <whack.h>
+#include <attributes/attribute_provider.h>
+
+typedef struct whack_attribute_t whack_attribute_t;
+
+/**
+ * Whack attribute provider (basically an in-memory IP address pool)
+ */
+struct whack_attribute_t {
+
+       /**
+        * Implements attribute provider interface
+        */
+       attribute_provider_t provider;
+
+       /**
+        * Add a virtual IP address pool.
+        *
+        * @param name          name of the pool
+        * @param right         "right" end of whack message
+        * @return                      TRUE, if the pool was successfully added
+        */
+       bool (*add_pool)(whack_attribute_t *this, const char *name,
+                                        const whack_end_t *right);
+
+       /**
+        * Remove a virtual IP address pool.
+        *
+        * @param name          name of the pool
+        */
+       void (*del_pool)(whack_attribute_t *this, char *name);
+
+       /**
+        * Create an enumerator over installed pools.
+        *
+        * Enumerator enumerates over
+        * char *pool, u_int size, u_int offline, u_int online.
+        *
+        * @return                      enumerator
+        */
+       enumerator_t* (*create_pool_enumerator)(whack_attribute_t *this);
+
+       /**
+        * Create an enumerator over the leases of a pool.
+        *
+        * Enumerator enumerates over
+        * identification_t *id, host_t *address, bool online
+        *
+        * @param name          name of the pool to enumerate
+        * @return                      enumerator, NULL if pool not found
+        */
+       enumerator_t* (*create_lease_enumerator)(whack_attribute_t *this,
+                                                                                        char *name);
+};
+
+/**
+ * Global object to manage pools. Set between calls to
+ * whack_attribute_initialize() and whack_attribute_finalize().
+ */
+extern whack_attribute_t *whack_attr;
+
+/**
+ * Initialize the whack attribute provider
+ */
+void whack_attribute_initialize();
+
+/**
+ * Finalize the whack attribute provider
+ */
+void whack_attribute_finalize();
+
+#endif /** WHACK_ATTRIBUTE_H_ @}*/