summaryrefslogtreecommitdiff
path: root/src/pluto/whack_attribute.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pluto/whack_attribute.c')
-rw-r--r--src/pluto/whack_attribute.c365
1 files changed, 365 insertions, 0 deletions
diff --git a/src/pluto/whack_attribute.c b/src/pluto/whack_attribute.c
new file mode 100644
index 000000000..6a12f0c09
--- /dev/null
+++ b/src/pluto/whack_attribute.c
@@ -0,0 +1,365 @@
+/*
+ * 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)))
+ {
+ DBG(DBG_CONTROL,
+ DBG_log("deleting virtual IP address pool '%s'", name)
+ );
+ 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;
+
+ if (whack_attr)
+ {
+ 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;
+}
+
+/**
+ * list leases of a single pool
+ */
+static void pool_leases(char *pool, host_t *address,
+ identification_t *identification,
+ u_int size, u_int online, u_int offline)
+{
+
+ enumerator_t *enumerator;
+ identification_t *id;
+ host_t *lease;
+ bool on, found = FALSE;
+
+ whack_log(RC_COMMENT, "Leases in pool '%s', usage: %lu/%lu, %lu online",
+ pool, online + offline, size, online);
+ enumerator = whack_attr->create_lease_enumerator(whack_attr, pool);
+ while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
+ {
+ if ((!address && !identification) ||
+ (address && address->ip_equals(address, lease)) ||
+ (identification && identification->equals(identification, id)))
+ {
+ whack_log(RC_COMMENT, " %15H %s '%Y'",
+ lease, on ? "online" : "offline", id);
+ found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ whack_log(RC_COMMENT, " no matching leases found");
+ }
+}
+
+/**
+ * see header file
+ */
+void list_leases(char *name, char *addr, char *id)
+{
+ identification_t *identification = NULL;
+ host_t *address = NULL;
+ bool found = FALSE;
+ enumerator_t *enumerator;
+ u_int size, online, offline;
+ char *pool;
+
+ if (addr)
+ {
+ address = host_create_from_string(addr, 0);
+ }
+ if (id)
+ {
+ identification = identification_create_from_string(id);
+ }
+
+ enumerator = whack_attr->create_pool_enumerator(whack_attr);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (!name || streq(name, pool))
+ {
+ pool_leases(pool, address, identification, size, online, offline);
+ found = TRUE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!found)
+ {
+ if (name)
+ {
+ whack_log(RC_COMMENT, "pool '%s' not found", name);
+ }
+ else
+ {
+ whack_log(RC_COMMENT, "no pools found");
+ }
+ }
+ DESTROY_IF(identification);
+ DESTROY_IF(address);
+}
+
+/**
+ * see header file
+ */
+void show_pools(const char *name)
+{
+ enumerator_t *enumerator;
+ u_int size, online, offline;
+ char *pool;
+ bool first = TRUE;
+
+ enumerator = whack_attr->create_pool_enumerator(whack_attr);
+ while (enumerator->enumerate(enumerator, &pool, &size, &online, &offline))
+ {
+ if (name && !streq(name, pool))
+ {
+ continue;
+ }
+ if (first)
+ {
+ first = FALSE;
+ whack_log(RC_COMMENT, "Virtual IP pools (size/online/offline):");
+ }
+ whack_log(RC_COMMENT, "\"%s\": %u/%u/%u", pool, size, online, offline);
+ }
+ enumerator->destroy(enumerator);
+}