aboutsummaryrefslogtreecommitdiffstats
path: root/src/libcharon
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcharon')
-rw-r--r--src/libcharon/Android.mk4
-rw-r--r--src/libcharon/Makefile.am4
-rw-r--r--src/libcharon/attributes/attribute_handler.h72
-rw-r--r--src/libcharon/attributes/attribute_manager.c347
-rw-r--r--src/libcharon/attributes/attribute_manager.h153
-rw-r--r--src/libcharon/attributes/attribute_provider.h71
-rw-r--r--src/libcharon/attributes/attributes.c114
-rw-r--r--src/libcharon/attributes/attributes.h91
-rw-r--r--src/libcharon/attributes/mem_pool.c695
-rw-r--r--src/libcharon/attributes/mem_pool.h146
-rw-r--r--src/libcharon/daemon.c2
-rw-r--r--src/libcharon/daemon.h9
-rw-r--r--src/libcharon/plugins/android_dns/android_dns_plugin.c9
-rw-r--r--src/libcharon/plugins/attr/attr_plugin.c10
-rw-r--r--src/libcharon/plugins/attr/attr_provider.c2
-rw-r--r--src/libcharon/plugins/attr_sql/attr_sql_plugin.c10
-rw-r--r--src/libcharon/plugins/dhcp/dhcp_plugin.c9
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_plugin.c10
-rw-r--r--src/libcharon/plugins/ha/ha_plugin.c10
-rw-r--r--src/libcharon/plugins/osx_attr/osx_attr_plugin.c9
-rw-r--r--src/libcharon/plugins/resolve/resolve_plugin.c10
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c13
-rw-r--r--src/libcharon/plugins/unit_tester/tests/test_pool.c11
-rw-r--r--src/libcharon/plugins/unity/unity_plugin.c17
-rw-r--r--src/libcharon/plugins/updown/updown_plugin.c9
-rw-r--r--src/libcharon/plugins/vici/vici_plugin.c9
-rw-r--r--src/libcharon/sa/ike_sa.c7
-rw-r--r--src/libcharon/sa/ikev1/tasks/mode_config.c27
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_config.c15
-rw-r--r--src/libcharon/tests/Makefile.am1
-rw-r--r--src/libcharon/tests/libcharon_tests.h2
-rw-r--r--src/libcharon/tests/suites/test_mem_pool.c230
32 files changed, 2031 insertions, 97 deletions
diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk
index ab71d4016..cf4ed3d49 100644
--- a/src/libcharon/Android.mk
+++ b/src/libcharon/Android.mk
@@ -3,6 +3,10 @@ include $(CLEAR_VARS)
# copy-n-paste from Makefile.am
libcharon_la_SOURCES := \
+attributes/attributes.c attributes/attributes.h \
+attributes/attribute_provider.h attributes/attribute_handler.h \
+attributes/attribute_manager.c attributes/attribute_manager.h \
+attributes/mem_pool.c attributes/mem_pool.h \
bus/bus.c bus/bus.h \
bus/listeners/listener.h \
bus/listeners/logger.h \
diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am
index 7b9a775f4..e8500dd9f 100644
--- a/src/libcharon/Makefile.am
+++ b/src/libcharon/Makefile.am
@@ -1,6 +1,10 @@
ipseclib_LTLIBRARIES = libcharon.la
libcharon_la_SOURCES = \
+attributes/attributes.c attributes/attributes.h \
+attributes/attribute_provider.h attributes/attribute_handler.h \
+attributes/attribute_manager.c attributes/attribute_manager.h \
+attributes/mem_pool.c attributes/mem_pool.h \
bus/bus.c bus/bus.h \
bus/listeners/listener.h \
bus/listeners/logger.h \
diff --git a/src/libcharon/attributes/attribute_handler.h b/src/libcharon/attributes/attribute_handler.h
new file mode 100644
index 000000000..bc488f6cb
--- /dev/null
+++ b/src/libcharon/attributes/attribute_handler.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 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.
+ */
+
+/**
+ * @defgroup attribute_handler attribute_handler
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_HANDLER_H_
+#define ATTRIBUTE_HANDLER_H_
+
+#include <utils/chunk.h>
+#include <utils/identification.h>
+#include <collections/linked_list.h>
+
+#include "attributes.h"
+
+typedef struct attribute_handler_t attribute_handler_t;
+
+/**
+ * Interface to handle configuration payload attributes.
+ */
+struct attribute_handler_t {
+
+ /**
+ * Handle a configuration attribute.
+ *
+ * After receiving a configuration attriubte, it is passed to each
+ * attribute handler until it is handled.
+ *
+ * @param server server from which the attribute was received
+ * @param type type of configuration attribute to handle
+ * @param data associated attribute data
+ * @return TRUE if attribute handled
+ */
+ bool (*handle)(attribute_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Release an attribute handled during handle().
+ *
+ * A handler that handle()d an attribute gets a call to release() when the
+ * connection gets closed. Depending on the implementation, this is required
+ * to remove the attribute.
+ */
+ void (*release)(attribute_handler_t *this, identification_t *server,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Enumerate attributes to request from a server.
+ *
+ * @param server server identity to request attributes from
+ * @param vips list of virtual IPs (host_t*) we are requesting
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_attribute_enumerator)(attribute_handler_t *this,
+ identification_t *server, linked_list_t *vips);
+};
+
+#endif /** ATTRIBUTE_HANDLER_H_ @}*/
diff --git a/src/libcharon/attributes/attribute_manager.c b/src/libcharon/attributes/attribute_manager.c
new file mode 100644
index 000000000..d166663fc
--- /dev/null
+++ b/src/libcharon/attributes/attribute_manager.c
@@ -0,0 +1,347 @@
+/*
+ * 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 "attribute_manager.h"
+
+#include <utils/debug.h>
+#include <collections/linked_list.h>
+#include <threading/rwlock.h>
+
+typedef struct private_attribute_manager_t private_attribute_manager_t;
+
+/**
+ * private data of attribute_manager
+ */
+struct private_attribute_manager_t {
+
+ /**
+ * public functions
+ */
+ attribute_manager_t public;
+
+ /**
+ * list of registered providers
+ */
+ linked_list_t *providers;
+
+ /**
+ * list of registered handlers
+ */
+ linked_list_t *handlers;
+
+ /**
+ * rwlock provider list
+ */
+ rwlock_t *lock;
+};
+
+/**
+ * Data to pass to enumerator filters
+ */
+typedef struct {
+ /** attribute group pools */
+ linked_list_t *pools;
+ /** server/peer identity */
+ identification_t *id;
+ /** requesting/assigned virtual IPs */
+ linked_list_t *vips;
+} enum_data_t;
+
+METHOD(attribute_manager_t, acquire_address, host_t*,
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, host_t *requested)
+{
+ enumerator_t *enumerator;
+ attribute_provider_t *current;
+ host_t *host = NULL;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ host = current->acquire_address(current, pools, id, requested);
+ if (host)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return host;
+}
+
+METHOD(attribute_manager_t, release_address, bool,
+ private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
+ identification_t *id)
+{
+ enumerator_t *enumerator;
+ attribute_provider_t *current;
+ bool found = FALSE;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->providers->create_enumerator(this->providers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->release_address(current, pools, address, id))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ return found;
+}
+
+/**
+ * inner enumerator constructor for responder attributes
+ */
+static enumerator_t *responder_enum_create(attribute_provider_t *provider,
+ enum_data_t *data)
+{
+ return provider->create_attribute_enumerator(provider, data->pools,
+ data->id, data->vips);
+}
+
+METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
+ private_attribute_manager_t *this, linked_list_t *pools,
+ identification_t *id, linked_list_t *vips)
+{
+ enum_data_t *data;
+
+ INIT(data,
+ .pools = pools,
+ .id = id,
+ .vips = vips,
+ );
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(
+ enumerator_create_nested(
+ this->providers->create_enumerator(this->providers),
+ (void*)responder_enum_create, data, free),
+ (void*)this->lock->unlock, this->lock);
+}
+
+METHOD(attribute_manager_t, add_provider, void,
+ private_attribute_manager_t *this, attribute_provider_t *provider)
+{
+ this->lock->write_lock(this->lock);
+ this->providers->insert_last(this->providers, provider);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(attribute_manager_t, remove_provider, void,
+ private_attribute_manager_t *this, attribute_provider_t *provider)
+{
+ this->lock->write_lock(this->lock);
+ this->providers->remove(this->providers, provider, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(attribute_manager_t, handle, attribute_handler_t*,
+ private_attribute_manager_t *this, identification_t *server,
+ attribute_handler_t *handler, configuration_attribute_type_t type,
+ chunk_t data)
+{
+ enumerator_t *enumerator;
+ attribute_handler_t *current, *handled = NULL;
+
+ this->lock->read_lock(this->lock);
+
+ /* try to find the passed handler */
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == handler && current->handle(current, server, type, data))
+ {
+ handled = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (!handled)
+ { /* handler requesting this attribute not found, try any other */
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current->handle(current, server, type, data))
+ {
+ handled = current;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ }
+ this->lock->unlock(this->lock);
+
+ if (!handled)
+ {
+ DBG1(DBG_CFG, "handling %N attribute failed",
+ configuration_attribute_type_names, type);
+ }
+ return handled;
+}
+
+METHOD(attribute_manager_t, release, void,
+ private_attribute_manager_t *this, attribute_handler_t *handler,
+ identification_t *server, configuration_attribute_type_t type, chunk_t data)
+{
+ enumerator_t *enumerator;
+ attribute_handler_t *current;
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->handlers->create_enumerator(this->handlers);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (current == handler)
+ {
+ current->release(current, server, type, data);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+}
+
+/**
+ * Enumerator implementation to enumerate nested initiator attributes
+ */
+typedef struct {
+ /** implements enumerator_t */
+ enumerator_t public;
+ /** back ref */
+ private_attribute_manager_t *this;
+ /** currently processing handler */
+ attribute_handler_t *handler;
+ /** outer enumerator over handlers */
+ enumerator_t *outer;
+ /** inner enumerator over current handlers attributes */
+ enumerator_t *inner;
+ /** server ID we want attributes for */
+ identification_t *id;
+ /** virtual IPs we are requesting along with attriubutes */
+ linked_list_t *vips;
+} initiator_enumerator_t;
+
+/**
+ * Enumerator implementation for initiator attributes
+ */
+static bool initiator_enumerate(initiator_enumerator_t *this,
+ attribute_handler_t **handler,
+ configuration_attribute_type_t *type,
+ chunk_t *value)
+{
+ /* enumerate inner attributes using outer handler enumerator */
+ while (!this->inner || !this->inner->enumerate(this->inner, type, value))
+ {
+ if (!this->outer->enumerate(this->outer, &this->handler))
+ {
+ return FALSE;
+ }
+ DESTROY_IF(this->inner);
+ this->inner = this->handler->create_attribute_enumerator(this->handler,
+ this->id, this->vips);
+ }
+ /* inject the handler as additional attribute */
+ *handler = this->handler;
+ return TRUE;
+}
+
+/**
+ * Cleanup function of initiator attribute enumerator
+ */
+static void initiator_destroy(initiator_enumerator_t *this)
+{
+ this->this->lock->unlock(this->this->lock);
+ this->outer->destroy(this->outer);
+ DESTROY_IF(this->inner);
+ free(this);
+}
+
+METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
+ private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
+{
+ initiator_enumerator_t *enumerator;
+
+ this->lock->read_lock(this->lock);
+
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)initiator_enumerate,
+ .destroy = (void*)initiator_destroy,
+ },
+ .this = this,
+ .id = id,
+ .vips = vips,
+ .outer = this->handlers->create_enumerator(this->handlers),
+ );
+ return &enumerator->public;
+}
+
+METHOD(attribute_manager_t, add_handler, void,
+ private_attribute_manager_t *this, attribute_handler_t *handler)
+{
+ this->lock->write_lock(this->lock);
+ this->handlers->insert_last(this->handlers, handler);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(attribute_manager_t, remove_handler, void,
+ private_attribute_manager_t *this, attribute_handler_t *handler)
+{
+ this->lock->write_lock(this->lock);
+ this->handlers->remove(this->handlers, handler, NULL);
+ this->lock->unlock(this->lock);
+}
+
+METHOD(attribute_manager_t, destroy, void,
+ private_attribute_manager_t *this)
+{
+ this->providers->destroy(this->providers);
+ this->handlers->destroy(this->handlers);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/*
+ * see header file
+ */
+attribute_manager_t *attribute_manager_create()
+{
+ private_attribute_manager_t *this;
+
+ INIT(this,
+ .public = {
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_responder_enumerator = _create_responder_enumerator,
+ .add_provider = _add_provider,
+ .remove_provider = _remove_provider,
+ .handle = _handle,
+ .release = _release,
+ .create_initiator_enumerator = _create_initiator_enumerator,
+ .add_handler = _add_handler,
+ .remove_handler = _remove_handler,
+ .destroy = _destroy,
+ },
+ .providers = linked_list_create(),
+ .handlers = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ return &this->public;
+}
diff --git a/src/libcharon/attributes/attribute_manager.h b/src/libcharon/attributes/attribute_manager.h
new file mode 100644
index 000000000..99f41772c
--- /dev/null
+++ b/src/libcharon/attributes/attribute_manager.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2008-2009 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.
+ */
+
+/**
+ * @defgroup attribute_manager attribute_manager
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_MANAGER_H_
+#define ATTRIBUTE_MANAGER_H_
+
+#include "attribute_provider.h"
+#include "attribute_handler.h"
+
+typedef struct attribute_manager_t attribute_manager_t;
+
+/**
+ * The attribute manager hands out attributes or handles them.
+ *
+ * The attribute manager manages both, attribute providers and attribute
+ * handlers. Attribute providers are responsible to hand out attributes if
+ * a connecting peer requests them. Handlers handle such attributes if they
+ * are received on the requesting peer.
+ */
+struct attribute_manager_t {
+
+ /**
+ * Acquire a virtual IP address to assign to a peer.
+ *
+ * @param pools list of pool names (char*) to acquire from
+ * @param id peer identity to get address forua
+ * @param requested IP in configuration request
+ * @return allocated address, NULL to serve none
+ */
+ host_t* (*acquire_address)(attribute_manager_t *this,
+ linked_list_t *pool, identification_t *id,
+ host_t *requested);
+
+ /**
+ * Release a previously acquired address.
+ *
+ * @param pools list of pool names (char*) to release to
+ * @param address address to release
+ * @param id peer identity to get address for
+ * @return TRUE if address released to pool
+ */
+ bool (*release_address)(attribute_manager_t *this,
+ linked_list_t *pools, host_t *address,
+ identification_t *id);
+
+ /**
+ * Create an enumerator over attributes to hand out to a peer.
+ *
+ * @param pool list of pools names (char*) to query attributes from
+ * @param id peer identity to hand out attributes to
+ * @param vip list of virtual IPs (host_t*) to assign to peer
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_responder_enumerator)(attribute_manager_t *this,
+ linked_list_t *pool, identification_t *id,
+ linked_list_t *vips);
+
+ /**
+ * Register an attribute provider to the manager.
+ *
+ * @param provider attribute provider to register
+ */
+ void (*add_provider)(attribute_manager_t *this,
+ attribute_provider_t *provider);
+ /**
+ * Unregister an attribute provider from the manager.
+ *
+ * @param provider attribute provider to unregister
+ */
+ void (*remove_provider)(attribute_manager_t *this,
+ attribute_provider_t *provider);
+
+ /**
+ * Handle a configuration attribute by passing them to the handlers.
+ *
+ * @param server server from which the attribute was received
+ * @param handler handler we requested the attribute for, if any
+ * @param type type of configuration attribute
+ * @param data associated attribute data
+ * @return handler which handled this attribute, NULL if none
+ */
+ attribute_handler_t* (*handle)(attribute_manager_t *this,
+ identification_t *server, attribute_handler_t *handler,
+ configuration_attribute_type_t type, chunk_t data);
+
+ /**
+ * Release an attribute previously handle()d by a handler.
+ *
+ * @param handler handler returned by handle() for this attribute
+ * @param server server from which the attribute was received
+ * @param type type of attribute to release
+ * @param data associated attribute data
+ */
+ void (*release)(attribute_manager_t *this, attribute_handler_t *handler,
+ identification_t *server,
+ configuration_attribute_type_t type,
+ chunk_t data);
+
+ /**
+ * Create an enumerator over attributes to request from server.
+ *
+ * @param id server identity to hand out attributes to
+ * @param vip list of virtual IPs (host_t*) going to request
+ * @return enumerator (attribute_handler_t, ca_type_t, chunk_t)
+ */
+ enumerator_t* (*create_initiator_enumerator)(attribute_manager_t *this,
+ identification_t *id, linked_list_t *vips);
+
+ /**
+ * Register an attribute handler to the manager.
+ *
+ * @param handler attribute handler to register
+ */
+ void (*add_handler)(attribute_manager_t *this,
+ attribute_handler_t *handler);
+
+ /**
+ * Unregister an attribute handler from the manager.
+ *
+ * @param handler attribute handler to unregister
+ */
+ void (*remove_handler)(attribute_manager_t *this,
+ attribute_handler_t *handler);
+
+ /**
+ * Destroy a attribute_manager instance.
+ */
+ void (*destroy)(attribute_manager_t *this);
+};
+
+/**
+ * Create a attribute_manager instance.
+ */
+attribute_manager_t *attribute_manager_create();
+
+#endif /** ATTRIBUTE_MANAGER_H_ @}*/
diff --git a/src/libcharon/attributes/attribute_provider.h b/src/libcharon/attributes/attribute_provider.h
new file mode 100644
index 000000000..adfd4a516
--- /dev/null
+++ b/src/libcharon/attributes/attribute_provider.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/**
+ * @defgroup attribute_provider attribute_provider
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTE_PROVIDER_H_
+#define ATTRIBUTE_PROVIDER_H_
+
+#include <networking/host.h>
+#include <utils/identification.h>
+#include <collections/linked_list.h>
+
+typedef struct attribute_provider_t attribute_provider_t;
+
+/**
+ * Interface to provide attributes to peers through attribute manager.
+ */
+struct attribute_provider_t {
+
+ /**
+ * Acquire a virtual IP address to assign to a peer.
+ *
+ * @param pools list of pool names (char*) to acquire from
+ * @param id peer ID
+ * @param requested IP in configuration request
+ * @return allocated address, NULL to serve none
+ */
+ host_t* (*acquire_address)(attribute_provider_t *this,
+ linked_list_t *pools, identification_t *id,
+ host_t *requested);
+ /**
+ * Release a previously acquired address.
+ *
+ * @param pools list of pool names (char*) to release to
+ * @param address address to release
+ * @param id peer ID
+ * @return TRUE if the address has been released by the provider
+ */
+ bool (*release_address)(attribute_provider_t *this,
+ linked_list_t *pools, host_t *address,
+ identification_t *id);
+
+ /**
+ * Create an enumerator over attributes to hand out to a peer.
+ *
+ * @param pool list of pools names (char*) to query attributes from
+ * @param id peer ID
+ * @param vip list of virtual IPs (host_t*) to assign to peer
+ * @return enumerator (configuration_attribute_type_t, chunk_t)
+ */
+ enumerator_t* (*create_attribute_enumerator)(attribute_provider_t *this,
+ linked_list_t *pools, identification_t *id,
+ linked_list_t *vips);
+};
+
+#endif /** ATTRIBUTE_PROVIDER_H_ @}*/
diff --git a/src/libcharon/attributes/attributes.c b/src/libcharon/attributes/attributes.c
new file mode 100644
index 000000000..9fabcf4e4
--- /dev/null
+++ b/src/libcharon/attributes/attributes.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 "attributes.h"
+
+ENUM_BEGIN(configuration_attribute_type_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS,
+ "INTERNAL_IP4_ADDRESS",
+ "INTERNAL_IP4_NETMASK",
+ "INTERNAL_IP4_DNS",
+ "INTERNAL_IP4_NBNS",
+ "INTERNAL_ADDRESS_EXPIRY",
+ "INTERNAL_IP4_DHCP",
+ "APPLICATION_VERSION",
+ "INTERNAL_IP6_ADDRESS",
+ "INTERNAL_IP6_NETMASK",
+ "INTERNAL_IP6_DNS",
+ "INTERNAL_IP6_NBNS",
+ "INTERNAL_IP6_DHCP",
+ "INTERNAL_IP4_SUBNET",
+ "SUPPORTED_ATTRIBUTES",
+ "INTERNAL_IP6_SUBNET",
+ "MIP6_HOME_PREFIX",
+ "INTERNAL_IP6_LINK",
+ "INTERNAL_IP6_PREFIX",
+ "HOME_AGENT_ADDRESS");
+ENUM_NEXT(configuration_attribute_type_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS,
+ "XAUTH_TYPE",
+ "XAUTH_USER_NAME",
+ "XAUTH_USER_PASSWORD",
+ "XAUTH_PASSCODE",
+ "XAUTH_MESSAGE",
+ "XAUTH_CHALLENGE",
+ "XAUTH_DOMAIN",
+ "XAUTH_STATUS",
+ "XAUTH_NEXT_PIN",
+ "XAUTH_ANSWER");
+ENUM_NEXT(configuration_attribute_type_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER,
+ "INTERNAL_IP4_SERVER",
+ "INTERNAL_IP6_SERVER");
+ENUM_NEXT(configuration_attribute_type_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER,
+ "UNITY_BANNER",
+ "UNITY_SAVE_PASSWD",
+ "UNITY_DEF_DOMAIN",
+ "UNITY_SPLITDNS_NAME",
+ "UNITY_SPLIT_INCLUDE",
+ "UNITY_NATT_PORT",
+ "UNITY_LOCAL_LAN",
+ "UNITY_PFS",
+ "UNITY_FW_TYPE",
+ "UNITY_BACKUP_SERVERS",
+ "UNITY_DDNS_HOSTNAME");
+ENUM_END(configuration_attribute_type_names, UNITY_DDNS_HOSTNAME);
+
+ENUM_BEGIN(configuration_attribute_type_short_names, INTERNAL_IP4_ADDRESS, HOME_AGENT_ADDRESS,
+ "ADDR",
+ "MASK",
+ "DNS",
+ "NBNS",
+ "EXP",
+ "DHCP",
+ "VER",
+ "ADDR6",
+ "MASK6",
+ "DNS6",
+ "NBNS6",
+ "DHCP6",
+ "SUBNET",
+ "SUP",
+ "SUBNET6",
+ "MIP6HPFX",
+ "LINK6",
+ "PFX6",
+ "HOA");
+ENUM_NEXT(configuration_attribute_type_short_names, XAUTH_TYPE, XAUTH_ANSWER, HOME_AGENT_ADDRESS,
+ "X_TYPE",
+ "X_USER",
+ "X_PWD",
+ "X_CODE",
+ "X_MSG",
+ "X_CHALL",
+ "X_DOMAIN",
+ "X_STATUS",
+ "X_PIN",
+ "X_ANSWER");
+ENUM_NEXT(configuration_attribute_type_short_names, INTERNAL_IP4_SERVER, INTERNAL_IP6_SERVER, XAUTH_ANSWER,
+ "SRV",
+ "SRV6");
+ENUM_NEXT(configuration_attribute_type_short_names, UNITY_BANNER, UNITY_DDNS_HOSTNAME, INTERNAL_IP6_SERVER,
+ "U_BANNER",
+ "U_SAVEPWD",
+ "U_DEFDOM",
+ "U_SPLITDNS",
+ "U_SPLITINC",
+ "U_NATTPORT",
+ "U_LOCALLAN",
+ "U_PFS",
+ "U_FWTYPE",
+ "U_BKPSRV",
+ "U_DDNSHOST");
+ENUM_END(configuration_attribute_type_short_names, UNITY_DDNS_HOSTNAME);
diff --git a/src/libcharon/attributes/attributes.h b/src/libcharon/attributes/attributes.h
new file mode 100644
index 000000000..5d1e9f9ba
--- /dev/null
+++ b/src/libcharon/attributes/attributes.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2005-2006 Martin Willi
+ * Copyright (C) 2005 Jan Hutter
+ * 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 attributes_g attributes
+ * @{ @ingroup attributes
+ */
+
+#ifndef ATTRIBUTES_H_
+#define ATTRIBUTES_H_
+
+typedef enum configuration_attribute_type_t configuration_attribute_type_t;
+
+#include <utils/utils.h>
+
+/**
+ * Type of the attribute, as in IKEv2 RFC 3.15.1 or IKEv1 ModeConfig.
+ */
+enum configuration_attribute_type_t {
+ INTERNAL_IP4_ADDRESS = 1,
+ INTERNAL_IP4_NETMASK = 2,
+ INTERNAL_IP4_DNS = 3,
+ INTERNAL_IP4_NBNS = 4,
+ INTERNAL_ADDRESS_EXPIRY = 5,
+ INTERNAL_IP4_DHCP = 6,
+ APPLICATION_VERSION = 7,
+ INTERNAL_IP6_ADDRESS = 8,
+ INTERNAL_IP6_NETMASK = 9,
+ INTERNAL_IP6_DNS = 10,
+ INTERNAL_IP6_NBNS = 11,
+ INTERNAL_IP6_DHCP = 12,
+ INTERNAL_IP4_SUBNET = 13,
+ SUPPORTED_ATTRIBUTES = 14,
+ INTERNAL_IP6_SUBNET = 15,
+ MIP6_HOME_PREFIX = 16,
+ INTERNAL_IP6_LINK = 17,
+ INTERNAL_IP6_PREFIX = 18,
+ HOME_AGENT_ADDRESS = 19,
+ /* XAUTH attributes */
+ XAUTH_TYPE = 16520,
+ XAUTH_USER_NAME = 16521,
+ XAUTH_USER_PASSWORD = 16522,
+ XAUTH_PASSCODE = 16523,
+ XAUTH_MESSAGE = 16524,
+ XAUTH_CHALLENGE = 16525,
+ XAUTH_DOMAIN = 16526,
+ XAUTH_STATUS = 16527,
+ XAUTH_NEXT_PIN = 16528,
+ XAUTH_ANSWER = 16529,
+ /* proprietary Microsoft attributes */
+ INTERNAL_IP4_SERVER = 23456,
+ INTERNAL_IP6_SERVER = 23457,
+ /* proprietary Cisco Unity attributes */
+ UNITY_BANNER = 28672,
+ UNITY_SAVE_PASSWD = 28673,
+ UNITY_DEF_DOMAIN = 28674,
+ UNITY_SPLITDNS_NAME = 28675,
+ UNITY_SPLIT_INCLUDE = 28676,
+ UNITY_NATT_PORT = 28677,
+ UNITY_LOCAL_LAN = 28678,
+ UNITY_PFS = 28679,
+ UNITY_FW_TYPE = 28680,
+ UNITY_BACKUP_SERVERS = 28681,
+ UNITY_DDNS_HOSTNAME = 28682
+};
+
+/**
+ * enum names for configuration_attribute_type_t.
+ */
+extern enum_name_t *configuration_attribute_type_names;
+
+/**
+ * Short enum names for configuration_attribute_type_t.
+ */
+extern enum_name_t *configuration_attribute_type_short_names;
+
+
+#endif /** ATTRIBUTES_H_ @}*/
diff --git a/src/libcharon/attributes/mem_pool.c b/src/libcharon/attributes/mem_pool.c
new file mode 100644
index 000000000..f35ffaa9c
--- /dev/null
+++ b/src/libcharon/attributes/mem_pool.c
@@ -0,0 +1,695 @@
+/*
+ * Copyright (C) 2010 Tobias Brunner
+ * Copyright (C) 2008-2010 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 "mem_pool.h"
+
+#include <library.h>
+#include <hydra.h>
+#include <utils/debug.h>
+#include <collections/hashtable.h>
+#include <collections/array.h>
+#include <threading/mutex.h>
+
+#define POOL_LIMIT (sizeof(u_int)*8 - 1)
+
+typedef struct private_mem_pool_t private_mem_pool_t;
+
+/**
+ * private data of mem_pool_t
+ */
+struct private_mem_pool_t {
+ /**
+ * public interface
+ */
+ mem_pool_t public;
+
+ /**
+ * name of the pool
+ */
+ char *name;
+
+ /**
+ * base address of the pool
+ */
+ host_t *base;
+
+ /**
+ * whether base is the network id of the subnet on which the pool is based
+ */
+ bool base_is_network_id;
+
+ /**
+ * size of the pool
+ */
+ u_int size;
+
+ /**
+ * next unused address
+ */
+ u_int unused;
+
+ /**
+ * lease hashtable [identity => entry]
+ */
+ hashtable_t *leases;
+
+ /**
+ * lock to safely access the pool
+ */
+ mutex_t *mutex;
+
+ /**
+ * Do we reassign online leases to the same identity, if requested?
+ */
+ bool reassign_online;
+};
+
+/**
+ * Lease entry.
+ */
+typedef struct {
+ /* identitiy reference */
+ identification_t *id;
+ /* array of online leases, as u_int offset */
+ array_t *online;
+ /* array of offline leases, as u_int offset */
+ array_t *offline;
+} entry_t;
+
+/**
+ * Create a new entry
+ */
+static entry_t* entry_create(identification_t *id)
+{
+ entry_t *entry;
+
+ INIT(entry,
+ .id = id->clone(id),
+ .online = array_create(sizeof(u_int), 0),
+ .offline = array_create(sizeof(u_int), 0),
+ );
+ return entry;
+}
+
+/**
+ * hashtable hash function for identities
+ */
+static u_int id_hash(identification_t *id)
+{
+ return chunk_hash(id->get_encoding(id));
+}
+
+/**
+ * hashtable equals function for identities
+ */
+static bool id_equals(identification_t *a, identification_t *b)
+{
+ return a->equals(a, b);
+}
+
+/**
+ * convert a pool offset to an address
+ */
+static host_t* offset2host(private_mem_pool_t *pool, int offset)
+{
+ chunk_t addr;
+ host_t *host;
+ u_int32_t *pos;
+
+ offset--;
+ if (offset > pool->size)
+ {
+ return NULL;
+ }
+
+ addr = chunk_clone(pool->base->get_address(pool->base));
+ if (pool->base->get_family(pool->base) == AF_INET6)
+ {
+ pos = (u_int32_t*)(addr.ptr + 12);
+ }
+ else
+ {
+ pos = (u_int32_t*)addr.ptr;
+ }
+ *pos = htonl(offset + ntohl(*pos));
+ host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0);
+ free(addr.ptr);
+ return host;
+}
+
+/**
+ * convert a host to a pool offset
+ */
+static int host2offset(private_mem_pool_t *pool, host_t *addr)
+{
+ chunk_t host, base;
+ u_int32_t hosti, basei;
+
+ if (addr->get_family(addr) != pool->base->get_family(pool->base))
+ {
+ return -1;
+ }
+ host = addr->get_address(addr);
+ base = pool->base->get_address(pool->base);
+ if (addr->get_family(addr) == AF_INET6)
+ {
+ /* only look at last /32 block */
+ if (!memeq(host.ptr, base.ptr, 12))
+ {
+ return -1;
+ }
+ host = chunk_skip(host, 12);
+ base = chunk_skip(base, 12);
+ }
+ hosti = ntohl(*(u_int32_t*)(host.ptr));
+ basei = ntohl(*(u_int32_t*)(base.ptr));
+ if (hosti > basei + pool->size)
+ {
+ return -1;
+ }
+ return hosti - basei + 1;
+}
+
+METHOD(mem_pool_t, get_name, const char*,
+ private_mem_pool_t *this)
+{
+ return this->name;
+}
+
+METHOD(mem_pool_t, get_base, host_t*,
+ private_mem_pool_t *this)
+{
+ return this->base;
+}
+
+METHOD(mem_pool_t, get_size, u_int,
+ private_mem_pool_t *this)
+{
+ return this->size;
+}
+
+METHOD(mem_pool_t, get_online, u_int,
+ private_mem_pool_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ u_int count = 0;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ count += array_count(entry->online);
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ return count;
+}
+
+METHOD(mem_pool_t, get_offline, u_int,
+ private_mem_pool_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ u_int count = 0;
+
+ this->mutex->lock(this->mutex);
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ count += array_count(entry->offline);
+ }
+ enumerator->destroy(enumerator);
+ this->mutex->unlock(this->mutex);
+
+ return count;
+}
+
+/**
+ * Get an existing lease for id
+ */
+static int get_existing(private_mem_pool_t *this, identification_t *id,
+ host_t *requested)
+{
+ enumerator_t *enumerator;
+ u_int *current;
+ entry_t *entry;
+ int offset = 0;
+
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
+ {
+ return 0;
+ }
+
+ /* check for a valid offline lease, refresh */
+ enumerator = array_create_enumerator(entry->offline);
+ if (enumerator->enumerate(enumerator, &current))
+ {
+ offset = *current;
+ array_insert(entry->online, ARRAY_TAIL, current);
+ array_remove_at(entry->offline, enumerator);
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
+ return offset;
+ }
+ if (!this->reassign_online)
+ {
+ return 0;
+ }
+ /* check for a valid online lease to reassign */
+ enumerator = array_create_enumerator(entry->online);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (*current == host2offset(this, requested))
+ {
+ offset = *current;
+ /* add an additional "online" entry */
+ array_insert(entry->online, ARRAY_TAIL, current);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ if (offset)
+ {
+ DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a new lease for id
+ */
+static int get_new(private_mem_pool_t *this, identification_t *id)
+{
+ entry_t *entry;
+ u_int offset = 0;
+
+ if (this->unused < this->size)
+ {
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
+ {
+ entry = entry_create(id);
+ this->leases->put(this->leases, entry->id, entry);
+ }
+ /* assigning offset, starting by 1 */
+ offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
+ array_insert(entry->online, ARRAY_TAIL, &offset);
+ DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
+ }
+ return offset;
+}
+
+/**
+ * Get a reassigned lease for id in case the pool is full
+ */
+static int get_reassigned(private_mem_pool_t *this, identification_t *id)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+ u_int current, offset = 0;
+
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ if (array_remove(entry->offline, ARRAY_HEAD, &current))
+ {
+ offset = current;
+ DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
+ " to '%Y'", entry->id, id);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (offset)
+ {
+ entry = this->leases->get(this->leases, id);
+ if (!entry)
+ {
+ entry = entry_create(id);
+ this->leases->put(this->leases, entry->id, entry);
+ }
+ array_insert(entry->online, ARRAY_TAIL, &offset);
+ }
+ return offset;
+}
+
+METHOD(mem_pool_t, acquire_address, host_t*,
+ private_mem_pool_t *this, identification_t *id, host_t *requested,
+ mem_pool_op_t operation)
+{
+ int offset = 0;
+
+ /* if the pool is empty (e.g. in the %config case) we simply return the
+ * requested address */
+ if (this->size == 0)
+ {
+ return requested->clone(requested);
+ }
+
+ if (requested->get_family(requested) !=
+ this->base->get_family(this->base))
+ {
+ return NULL;
+ }
+
+ this->mutex->lock(this->mutex);
+ switch (operation)
+ {
+ case MEM_POOL_EXISTING:
+ offset = get_existing(this, id, requested);
+ break;
+ case MEM_POOL_NEW:
+ offset = get_new(this, id);
+ break;
+ case MEM_POOL_REASSIGN:
+ offset = get_reassigned(this, id);
+ if (!offset)
+ {
+ DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
+ this->name);
+ }
+ break;
+ default:
+ break;
+ }
+ this->mutex->unlock(this->mutex);
+
+ if (offset)
+ {
+ return offset2host(this, offset);
+ }
+ return NULL;
+}
+
+METHOD(mem_pool_t, release_address, bool,
+ private_mem_pool_t *this, host_t *address, identification_t *id)
+{
+ enumerator_t *enumerator;
+ bool found = FALSE, more = FALSE;
+ entry_t *entry;
+ u_int offset, *current;
+
+ if (this->size != 0)
+ {
+ this->mutex->lock(this->mutex);
+ entry = this->leases->get(this->leases, id);
+ if (entry)
+ {
+ offset = host2offset(this, address);
+
+ enumerator = array_create_enumerator(entry->online);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (*current == offset)
+ {
+ if (!found)
+ { /* remove the first entry only */
+ array_remove_at(entry->online, enumerator);
+ found = TRUE;
+ }
+ else
+ { /* but check for more entries */
+ more = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (found && !more)
+ {
+ /* no tunnels are online anymore for this lease, make offline */
+ array_insert(entry->offline, ARRAY_TAIL, &offset);
+ DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ }
+ return found;
+}
+
+/**
+ * lease enumerator
+ */
+typedef struct {
+ /** implemented enumerator interface */
+ enumerator_t public;
+ /** hash-table enumerator */
+ enumerator_t *entries;
+ /** online enumerator */
+ enumerator_t *online;
+ /** offline enumerator */
+ enumerator_t *offline;
+ /** enumerated pool */
+ private_mem_pool_t *pool;
+ /** currently enumerated entry */
+ entry_t *entry;
+ /** currently enumerated lease address */
+ host_t *addr;
+} lease_enumerator_t;
+
+METHOD(enumerator_t, lease_enumerate, bool,
+ lease_enumerator_t *this, identification_t **id, host_t **addr, bool *online)
+{
+ u_int *offset;
+
+ DESTROY_IF(this->addr);
+ this->addr = NULL;
+
+ while (TRUE)
+ {
+ if (this->entry)
+ {
+ if (this->online->enumerate(this->online, &offset))
+ {
+ *id = this->entry->id;
+ *addr = this->addr = offset2host(this->pool, *offset);
+ *online = TRUE;
+ return TRUE;
+ }
+ if (this->offline->enumerate(this->offline, &offset))
+ {
+ *id = this->entry->id;
+ *addr = this->addr = offset2host(this->pool, *offset);
+ *online = FALSE;
+ return TRUE;
+ }
+ this->online->destroy(this->online);
+ this->offline->destroy(this->offline);
+ this->online = this->offline = NULL;
+ }
+ if (!this->entries->enumerate(this->entries, NULL, &this->entry))
+ {
+ return FALSE;
+ }
+ this->online = array_create_enumerator(this->entry->online);
+ this->offline = array_create_enumerator(this->entry->offline);
+ }
+}
+
+METHOD(enumerator_t, lease_enumerator_destroy, void,
+ lease_enumerator_t *this)
+{
+ DESTROY_IF(this->addr);
+ DESTROY_IF(this->online);
+ DESTROY_IF(this->offline);
+ this->entries->destroy(this->entries);
+ this->pool->mutex->unlock(this->pool->mutex);
+ free(this);
+}
+
+METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
+ private_mem_pool_t *this)
+{
+ lease_enumerator_t *enumerator;
+
+ this->mutex->lock(this->mutex);
+ INIT(enumerator,
+ .public = {
+ .enumerate = (void*)_lease_enumerate,
+ .destroy = _lease_enumerator_destroy,
+ },
+ .pool = this,
+ .entries = this->leases->create_enumerator(this->leases),
+ );
+ return &enumerator->public;
+}
+
+METHOD(mem_pool_t, destroy, void,
+ private_mem_pool_t *this)
+{
+ enumerator_t *enumerator;
+ entry_t *entry;
+
+ enumerator = this->leases->create_enumerator(this->leases);
+ while (enumerator->enumerate(enumerator, NULL, &entry))
+ {
+ entry->id->destroy(entry->id);
+ array_destroy(entry->online);
+ array_destroy(entry->offline);
+ free(entry);
+ }
+ enumerator->destroy(enumerator);
+
+ this->leases->destroy(this->leases);
+ this->mutex->destroy(this->mutex);
+ DESTROY_IF(this->base);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * Generic constructor
+ */
+static private_mem_pool_t *create_generic(char *name)
+{
+ private_mem_pool_t *this;
+
+ INIT(this,
+ .public = {
+ .get_name = _get_name,
+ .get_base = _get_base,
+ .get_size = _get_size,
+ .get_online = _get_online,
+ .get_offline = _get_offline,
+ .acquire_address = _acquire_address,
+ .release_address = _release_address,
+ .create_lease_enumerator = _create_lease_enumerator,
+ .destroy = _destroy,
+ },
+ .name = strdup(name),
+ .leases = hashtable_create((hashtable_hash_t)id_hash,
+ (hashtable_equals_t)id_equals, 16),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+ .reassign_online = lib->settings->get_bool(lib->settings,
+ "%s.mem-pool.reassign_online", FALSE, lib->ns),
+ );
+
+ return this;
+}
+
+/**
+ * Check if the given host is the network ID of a subnet, that is, if hostbits
+ * are zero. Since we limit pools to 2^31 addresses we only have to check the
+ * last 4 bytes.
+ */
+static u_int network_id_diff(host_t *host, int hostbits)
+{
+ u_int32_t last;
+ chunk_t addr;
+
+ if (!hostbits)
+ {
+ return 0;
+ }
+ addr = host->get_address(host);
+ last = untoh32(addr.ptr + addr.len - sizeof(last));
+ hostbits = sizeof(last) * 8 - hostbits;
+ return (last << hostbits) >> hostbits;
+}
+
+/**
+ * Described in header
+ */
+mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
+{
+ private_mem_pool_t *this;
+ u_int diff;
+ int addr_bits;
+
+ this = create_generic(name);
+ if (base)
+ {
+ addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
+ bits = max(0, min(bits, addr_bits));
+ /* net bits -> host bits */
+ bits = addr_bits - bits;
+ if (bits > POOL_LIMIT)
+ {
+ bits = POOL_LIMIT;
+ DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
+ base, addr_bits - bits);
+ }
+ this->size = 1 << bits;
+ this->base = base->clone(base);
+
+ if (this->size > 2)
+ {
+ /* if base is the network id we later skip the first address,
+ * otherwise adjust the size to represent the actual number
+ * of assignable addresses */
+ diff = network_id_diff(base, bits);
+ if (!diff)
+ {
+ this->base_is_network_id = TRUE;
+ this->size--;
+ }
+ else
+ {
+ this->size -= diff;
+ }
+ /* skip the last address (broadcast) of the subnet */
+ this->size--;
+ }
+ else if (network_id_diff(base, bits))
+ { /* only serve the second address of the subnet */
+ this->size--;
+ }
+ }
+ return &this->public;
+}
+
+/**
+ * Described in header
+ */
+mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to)
+{
+ private_mem_pool_t *this;
+ chunk_t fromaddr, toaddr;
+ u_int32_t diff;
+
+ fromaddr = from->get_address(from);
+ toaddr = to->get_address(to);
+
+ if (from->get_family(from) != to->get_family(to) ||
+ fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) ||
+ memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0)
+ {
+ DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to);
+ return NULL;
+ }
+ if (fromaddr.len > sizeof(diff) &&
+ !chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)),
+ chunk_create(toaddr.ptr, toaddr.len - sizeof(diff))))
+ {
+ DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to);
+ return NULL;
+ }
+ this = create_generic(name);
+ this->base = from->clone(from);
+ diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) -
+ untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff));
+ this->size = diff + 1;
+
+ return &this->public;
+}
diff --git a/src/libcharon/attributes/mem_pool.h b/src/libcharon/attributes/mem_pool.h
new file mode 100644
index 000000000..7347bb547
--- /dev/null
+++ b/src/libcharon/attributes/mem_pool.h
@@ -0,0 +1,146 @@
+/*
+ * 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 mem_pool mem_pool
+ * @{ @ingroup attributes
+ */
+
+#ifndef MEM_POOL_H
+#define MEM_POOL_H
+
+typedef struct mem_pool_t mem_pool_t;
+typedef enum mem_pool_op_t mem_pool_op_t;
+
+#include <networking/host.h>
+#include <utils/identification.h>
+
+/**
+ * In-memory IP pool acquire operation.
+ */
+enum mem_pool_op_t {
+ /** Check for an exsiting lease */
+ MEM_POOL_EXISTING,
+ /** Get a new lease */
+ MEM_POOL_NEW,
+ /** Replace an existing offline lease of another ID */
+ MEM_POOL_REASSIGN,
+};
+
+/**
+ * An in-memory IP address pool.
+ */
+struct mem_pool_t {
+
+ /**
+ * Get the name of this pool.
+ *
+ * @return the name of this pool
+ */
+ const char* (*get_name)(mem_pool_t *this);
+
+ /**
+ * Get the base (first) address of this pool.
+ *
+ * @return base address, internal host
+ */
+ host_t* (*get_base)(mem_pool_t *this);
+
+ /**
+ * Get the size (i.e. number of addresses) of this pool.
+ *
+ * @return the size of this pool
+ */
+ u_int (*get_size)(mem_pool_t *this);
+
+ /**
+ * Get the number of online leases.
+ *
+ * @return the number of offline leases
+ */
+ u_int (*get_online)(mem_pool_t *this);
+
+ /**
+ * Get the number of offline leases.
+ *
+ * @return the number of online leases
+ */
+ u_int (*get_offline)(mem_pool_t *this);
+
+ /**
+ * Acquire an address for the given id from this pool.
+ *
+ * This call is usually invoked several times: The first time to find an
+ * existing lease (MEM_POOL_EXISTING), if none found a second time to
+ * acquire a new lease (MEM_POOL_NEW), and if the pool is full once again
+ * to assign an existing offline lease (MEM_POOL_REASSIGN).
+ *
+ * @param id the id to acquire an address for
+ * @param requested acquire this address, if possible
+ * @param operation acquire operation to perform, see above
+ * @return the acquired address
+ */
+ host_t* (*acquire_address)(mem_pool_t *this, identification_t *id,
+ host_t *requested, mem_pool_op_t operation);
+
+ /**
+ * Release a previously acquired address.
+ *
+ * @param address the address to release
+ * @param id the id the address was assigned to
+ * @return TRUE, if the lease was found
+ */
+ bool (*release_address)(mem_pool_t *this, host_t *address,
+ identification_t *id);
+
+ /**
+ * Create an enumerator over the leases of this pool.
+ *
+ * Enumerator enumerates over
+ * identification_t *id, host_t *address, bool online
+ *
+ * @return enumerator
+ */
+ enumerator_t* (*create_lease_enumerator)(mem_pool_t *this);
+
+ /**
+ * Destroy a mem_pool_t instance.
+ */
+ void (*destroy)(mem_pool_t *this);
+};
+
+/**
+ * Create an in-memory IP address pool.
+ *
+ * An empty pool just returns the requested address.
+ *
+ * @param name name of this pool
+ * @param base base address of this pool, NULL to create an empty pool
+ * @param bits number of non-network bits in base, as in CIDR notation
+ * @return memory pool instance
+ */
+mem_pool_t *mem_pool_create(char *name, host_t *base, int bits);
+
+/**
+ * Create an in-memory IP address from a range.
+ *
+ * @param name name of this pool
+ * @param from start of ranged pool
+ * @param to end of ranged pool
+ * @return memory pool instance, NULL if range invalid
+ */
+mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to);
+
+#endif /** MEM_POOL_H_ @} */
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index f3859f912..d44cb37eb 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -477,6 +477,7 @@ static void destroy(private_daemon_t *this)
/* make sure the cache is clear before unloading plugins */
lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
lib->plugins->unload(lib->plugins);
+ DESTROY_IF(this->public.attributes);
DESTROY_IF(this->kernel_handler);
DESTROY_IF(this->public.traps);
DESTROY_IF(this->public.shunts);
@@ -644,6 +645,7 @@ private_daemon_t *daemon_create()
.ref = 1,
);
charon = &this->public;
+ this->public.attributes = attribute_manager_create();
this->public.controller = controller_create();
this->public.eap = eap_manager_create();
this->public.xauth = xauth_manager_create();
diff --git a/src/libcharon/daemon.h b/src/libcharon/daemon.h
index 8ec1ec253..d16bf1ddb 100644
--- a/src/libcharon/daemon.h
+++ b/src/libcharon/daemon.h
@@ -19,6 +19,9 @@
/**
* @defgroup libcharon libcharon
*
+ * @defgroup attributes attributes
+ * @ingroup libcharon
+ *
* @defgroup bus bus
* @ingroup libcharon
*
@@ -152,6 +155,7 @@
typedef struct daemon_t daemon_t;
+#include <attributes/attribute_manager.h>
#include <network/sender.h>
#include <network/receiver.h>
#include <network/socket_manager.h>
@@ -246,6 +250,11 @@ struct daemon_t {
receiver_t *receiver;
/**
+ * Manager for IKE configuration attributes
+ */
+ attribute_manager_t *attributes;
+
+ /**
* The signaling bus.
*/
bus_t *bus;
diff --git a/src/libcharon/plugins/android_dns/android_dns_plugin.c b/src/libcharon/plugins/android_dns/android_dns_plugin.c
index b8eb11b57..9b6ec0dba 100644
--- a/src/libcharon/plugins/android_dns/android_dns_plugin.c
+++ b/src/libcharon/plugins/android_dns/android_dns_plugin.c
@@ -16,7 +16,6 @@
#include "android_dns_plugin.h"
#include "android_dns_handler.h"
-#include <hydra.h>
#include <daemon.h>
typedef struct private_android_dns_plugin_t private_android_dns_plugin_t;
@@ -51,13 +50,13 @@ static bool plugin_cb(private_android_dns_plugin_t *this,
{
if (reg)
{
- hydra->attributes->add_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
}
else
{
- hydra->attributes->remove_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
}
return TRUE;
}
diff --git a/src/libcharon/plugins/attr/attr_plugin.c b/src/libcharon/plugins/attr/attr_plugin.c
index 72fcd6dff..9b15c3cc9 100644
--- a/src/libcharon/plugins/attr/attr_plugin.c
+++ b/src/libcharon/plugins/attr/attr_plugin.c
@@ -16,7 +16,7 @@
#include "attr_plugin.h"
#include "attr_provider.h"
-#include <hydra.h>
+#include <daemon.h>
typedef struct private_attr_plugin_t private_attr_plugin_t;
@@ -50,13 +50,13 @@ static bool plugin_cb(private_attr_plugin_t *this,
{
if (reg)
{
- hydra->attributes->add_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->provider->provider);
}
else
{
- hydra->attributes->remove_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->provider->provider);
}
return TRUE;
}
diff --git a/src/libcharon/plugins/attr/attr_provider.c b/src/libcharon/plugins/attr/attr_provider.c
index c1788df94..8a768c5b2 100644
--- a/src/libcharon/plugins/attr/attr_provider.c
+++ b/src/libcharon/plugins/attr/attr_provider.c
@@ -18,7 +18,7 @@
#include <time.h>
-#include <hydra.h>
+#include <daemon.h>
#include <utils/debug.h>
#include <collections/linked_list.h>
#include <threading/rwlock.h>
diff --git a/src/libcharon/plugins/attr_sql/attr_sql_plugin.c b/src/libcharon/plugins/attr_sql/attr_sql_plugin.c
index dde90051a..247cc11c3 100644
--- a/src/libcharon/plugins/attr_sql/attr_sql_plugin.c
+++ b/src/libcharon/plugins/attr_sql/attr_sql_plugin.c
@@ -14,7 +14,7 @@
* for more details.
*/
-#include <hydra.h>
+#include <daemon.h>
#include <utils/debug.h>
#include <plugins/plugin_feature.h>
@@ -75,13 +75,13 @@ static bool open_database(private_attr_sql_plugin_t *this,
return FALSE;
}
this->attribute = sql_attribute_create(this->db);
- hydra->attributes->add_provider(hydra->attributes,
- &this->attribute->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->attribute->provider);
}
else
{
- hydra->attributes->remove_provider(hydra->attributes,
- &this->attribute->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->attribute->provider);
this->attribute->destroy(this->attribute);
this->db->destroy(this->db);
}
diff --git a/src/libcharon/plugins/dhcp/dhcp_plugin.c b/src/libcharon/plugins/dhcp/dhcp_plugin.c
index c36c60d28..642e28afc 100644
--- a/src/libcharon/plugins/dhcp/dhcp_plugin.c
+++ b/src/libcharon/plugins/dhcp/dhcp_plugin.c
@@ -18,7 +18,6 @@
#include "dhcp_plugin.h"
-#include <hydra.h>
#include <daemon.h>
#include <plugins/plugin_feature.h>
@@ -69,13 +68,13 @@ static bool plugin_cb(private_dhcp_plugin_t *this,
return FALSE;
}
this->provider = dhcp_provider_create(this->socket);
- hydra->attributes->add_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->provider->provider);
}
else
{
- hydra->attributes->remove_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->provider->provider);
this->provider->destroy(this->provider);
this->socket->destroy(this->socket);
}
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
index 5d3540861..6a4a0384e 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_plugin.c
@@ -26,7 +26,7 @@
#include <radius_client.h>
#include <radius_config.h>
-#include <hydra.h>
+#include <daemon.h>
#include <threading/rwlock.h>
#include <processing/jobs/callback_job.h>
#include <processing/jobs/delete_ike_sa_job.h>
@@ -218,13 +218,13 @@ static bool plugin_cb(private_eap_radius_plugin_t *this,
{
charon->bus->add_listener(charon->bus, &this->forward->listener);
}
- hydra->attributes->add_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->provider->provider);
}
else
{
- hydra->attributes->remove_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->provider->provider);
if (this->forward)
{
charon->bus->remove_listener(charon->bus, &this->forward->listener);
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
index 493cad5ec..a58377bab 100644
--- a/src/libcharon/plugins/ha/ha_plugin.c
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -25,7 +25,6 @@
#include "ha_attribute.h"
#include <daemon.h>
-#include <hydra.h>
#include <config/child_cfg.h>
typedef struct private_ha_plugin_t private_ha_plugin_t;
@@ -108,13 +107,13 @@ static bool plugin_cb(private_ha_plugin_t *this,
charon->bus->add_listener(charon->bus, &this->segments->listener);
charon->bus->add_listener(charon->bus, &this->ike->listener);
charon->bus->add_listener(charon->bus, &this->child->listener);
- hydra->attributes->add_provider(hydra->attributes,
- &this->attr->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->attr->provider);
}
else
{
- hydra->attributes->remove_provider(hydra->attributes,
- &this->attr->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->attr->provider);
charon->bus->remove_listener(charon->bus, &this->segments->listener);
charon->bus->remove_listener(charon->bus, &this->ike->listener);
charon->bus->remove_listener(charon->bus, &this->child->listener);
@@ -224,4 +223,3 @@ plugin_t *ha_plugin_create()
return &this->public.plugin;
}
-
diff --git a/src/libcharon/plugins/osx_attr/osx_attr_plugin.c b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c
index 380483c23..4be9eda5e 100644
--- a/src/libcharon/plugins/osx_attr/osx_attr_plugin.c
+++ b/src/libcharon/plugins/osx_attr/osx_attr_plugin.c
@@ -16,7 +16,6 @@
#include "osx_attr_plugin.h"
#include "osx_attr_handler.h"
-#include <hydra.h>
#include <daemon.h>
typedef struct private_osx_attr_plugin_t private_osx_attr_plugin_t;
@@ -51,13 +50,13 @@ static bool plugin_cb(private_osx_attr_plugin_t *this,
{
if (reg)
{
- hydra->attributes->add_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
}
else
{
- hydra->attributes->remove_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
}
return TRUE;
}
diff --git a/src/libcharon/plugins/resolve/resolve_plugin.c b/src/libcharon/plugins/resolve/resolve_plugin.c
index 00c025f13..193c5b602 100644
--- a/src/libcharon/plugins/resolve/resolve_plugin.c
+++ b/src/libcharon/plugins/resolve/resolve_plugin.c
@@ -16,7 +16,7 @@
#include "resolve_plugin.h"
#include "resolve_handler.h"
-#include <hydra.h>
+#include <daemon.h>
typedef struct private_resolve_plugin_t private_resolve_plugin_t;
@@ -50,13 +50,13 @@ static bool plugin_cb(private_resolve_plugin_t *this,
{
if (reg)
{
- hydra->attributes->add_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
}
else
{
- hydra->attributes->remove_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
}
return TRUE;
}
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index 54dd56e91..db7e66f14 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -24,7 +24,6 @@
#include <unistd.h>
#include <errno.h>
-#include <hydra.h>
#include <daemon.h>
#include "stroke_config.h"
@@ -747,8 +746,10 @@ METHOD(stroke_socket_t, destroy, void,
lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
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);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->attribute->provider);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
charon->bus->remove_listener(charon->bus, &this->counter->listener);
this->cred->destroy(this->cred);
this->ca->destroy(this->ca);
@@ -790,8 +791,10 @@ stroke_socket_t *stroke_socket_create()
lib->credmgr->add_set(lib->credmgr, &this->ca->set);
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);
+ charon->attributes->add_provider(charon->attributes,
+ &this->attribute->provider);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
charon->bus->add_listener(charon->bus, &this->counter->listener);
max_concurrent = lib->settings->get_int(lib->settings,
diff --git a/src/libcharon/plugins/unit_tester/tests/test_pool.c b/src/libcharon/plugins/unit_tester/tests/test_pool.c
index f36953f3a..da5c22f62 100644
--- a/src/libcharon/plugins/unit_tester/tests/test_pool.c
+++ b/src/libcharon/plugins/unit_tester/tests/test_pool.c
@@ -17,7 +17,7 @@
#include <library.h>
#include <threading/thread.h>
-#include <hydra.h>
+#include <daemon.h>
#define ALLOCS 1000
#define THREADS 20
@@ -44,8 +44,8 @@ static void* testing(void *thread)
/* allocate addresses */
for (i = 0; i < ALLOCS; i++)
{
- addr[i] = hydra->attributes->acquire_address(hydra->attributes,
- pools, id[i], NULL);
+ addr[i] = charon->attributes->acquire_address(charon->attributes,
+ pools, id[i], NULL);
if (!addr[i])
{
pools->destroy(pools);
@@ -56,8 +56,8 @@ static void* testing(void *thread)
/* release addresses */
for (i = 0; i < ALLOCS; i++)
{
- hydra->attributes->release_address(hydra->attributes,
- pools, addr[i], id[i]);
+ charon->attributes->release_address(charon->attributes,
+ pools, addr[i], id[i]);
}
pools->destroy(pools);
@@ -97,4 +97,3 @@ bool test_pool()
}
return TRUE;
}
-
diff --git a/src/libcharon/plugins/unity/unity_plugin.c b/src/libcharon/plugins/unity/unity_plugin.c
index 9e4571d34..b7a3fee2e 100644
--- a/src/libcharon/plugins/unity/unity_plugin.c
+++ b/src/libcharon/plugins/unity/unity_plugin.c
@@ -19,7 +19,6 @@
#include "unity_provider.h"
#include <daemon.h>
-#include <hydra.h>
typedef struct private_unity_plugin_t private_unity_plugin_t;
@@ -63,19 +62,19 @@ static bool plugin_cb(private_unity_plugin_t *this,
{
if (reg)
{
- hydra->attributes->add_handler(hydra->attributes,
- &this->handler->handler);
- hydra->attributes->add_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
+ charon->attributes->add_provider(charon->attributes,
+ &this->provider->provider);
charon->bus->add_listener(charon->bus, &this->narrower->listener);
}
else
{
charon->bus->remove_listener(charon->bus, &this->narrower->listener);
- hydra->attributes->remove_handler(hydra->attributes,
- &this->handler->handler);
- hydra->attributes->remove_provider(hydra->attributes,
- &this->provider->provider);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->provider->provider);
}
return TRUE;
diff --git a/src/libcharon/plugins/updown/updown_plugin.c b/src/libcharon/plugins/updown/updown_plugin.c
index d30267dee..60ecfcce6 100644
--- a/src/libcharon/plugins/updown/updown_plugin.c
+++ b/src/libcharon/plugins/updown/updown_plugin.c
@@ -18,7 +18,6 @@
#include "updown_handler.h"
#include <daemon.h>
-#include <hydra.h>
typedef struct private_updown_plugin_t private_updown_plugin_t;
@@ -61,8 +60,8 @@ static bool plugin_cb(private_updown_plugin_t *this,
"%s.plugins.updown.dns_handler", FALSE, lib->ns))
{
this->handler = updown_handler_create();
- hydra->attributes->add_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->add_handler(charon->attributes,
+ &this->handler->handler);
}
this->listener = updown_listener_create(this->handler);
charon->bus->add_listener(charon->bus, &this->listener->listener);
@@ -74,8 +73,8 @@ static bool plugin_cb(private_updown_plugin_t *this,
if (this->handler)
{
this->handler->destroy(this->handler);
- hydra->attributes->remove_handler(hydra->attributes,
- &this->handler->handler);
+ charon->attributes->remove_handler(charon->attributes,
+ &this->handler->handler);
}
}
return TRUE;
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
index 8881feca9..af8bd283b 100644
--- a/src/libcharon/plugins/vici/vici_plugin.c
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -23,7 +23,6 @@
#include "vici_logger.h"
#include <library.h>
-#include <hydra.h>
#include <daemon.h>
typedef struct private_vici_plugin_t private_vici_plugin_t;
@@ -104,8 +103,8 @@ static bool register_vici(private_vici_plugin_t *this,
charon->backends->add_backend(charon->backends,
&this->config->backend);
- hydra->attributes->add_provider(hydra->attributes,
- &this->attrs->provider);
+ charon->attributes->add_provider(charon->attributes,
+ &this->attrs->provider);
charon->bus->add_logger(charon->bus, &this->logger->logger);
return TRUE;
}
@@ -114,8 +113,8 @@ static bool register_vici(private_vici_plugin_t *this,
else
{
charon->bus->remove_logger(charon->bus, &this->logger->logger);
- hydra->attributes->remove_provider(hydra->attributes,
- &this->attrs->provider);
+ charon->attributes->remove_provider(charon->attributes,
+ &this->attrs->provider);
charon->backends->remove_backend(charon->backends,
&this->config->backend);
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 54f22e61e..6392c1998 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -2346,8 +2346,8 @@ METHOD(ike_sa_t, destroy, void,
{
if (entry.handler)
{
- hydra->attributes->release(hydra->attributes, entry.handler,
- this->other_id, entry.type, entry.data);
+ charon->attributes->release(charon->attributes, entry.handler,
+ this->other_id, entry.type, entry.data);
}
free(entry.data.ptr);
}
@@ -2377,7 +2377,8 @@ METHOD(ike_sa_t, destroy, void,
id = get_other_eap_id(this);
pools = linked_list_create_from_enumerator(
this->peer_cfg->create_pool_enumerator(this->peer_cfg));
- hydra->attributes->release_address(hydra->attributes, pools, vip, id);
+ charon->attributes->release_address(charon->attributes,
+ pools, vip, id);
pools->destroy(pools);
}
vip->destroy(vip);
diff --git a/src/libcharon/sa/ikev1/tasks/mode_config.c b/src/libcharon/sa/ikev1/tasks/mode_config.c
index 94026b9af..66ae69543 100644
--- a/src/libcharon/sa/ikev1/tasks/mode_config.c
+++ b/src/libcharon/sa/ikev1/tasks/mode_config.c
@@ -16,7 +16,6 @@
#include "mode_config.h"
#include <daemon.h>
-#include <hydra.h>
#include <encoding/payloads/cp_payload.h>
typedef struct private_mode_config_t private_mode_config_t;
@@ -136,7 +135,7 @@ static void handle_attribute(private_mode_config_t *this,
enumerator->destroy(enumerator);
/* and pass it to the handle function */
- handler = hydra->attributes->handle(hydra->attributes,
+ handler = charon->attributes->handle(charon->attributes,
this->ike_sa->get_other_id(this->ike_sa), handler,
ca->get_type(ca), ca->get_chunk(ca));
this->ike_sa->add_configuration_attribute(this->ike_sa,
@@ -326,8 +325,8 @@ static status_t build_request(private_mode_config_t *this, message_t *message)
enumerator->destroy(enumerator);
}
- enumerator = hydra->attributes->create_initiator_enumerator(
- hydra->attributes,
+ enumerator = charon->attributes->create_initiator_enumerator(
+ charon->attributes,
this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
@@ -372,12 +371,12 @@ static status_t build_set(private_mode_config_t *this, message_t *message)
{
pools = linked_list_create_with_items(name, NULL);
/* try IPv4, then IPv6 */
- found = hydra->attributes->acquire_address(hydra->attributes,
- pools, id, any4);
+ found = charon->attributes->acquire_address(charon->attributes,
+ pools, id, any4);
if (!found)
{
- found = hydra->attributes->acquire_address(hydra->attributes,
- pools, id, any6);
+ found = charon->attributes->acquire_address(charon->attributes,
+ pools, id, any6);
}
pools->destroy(pools);
if (found)
@@ -398,8 +397,8 @@ static status_t build_set(private_mode_config_t *this, message_t *message)
/* query registered providers for additional attributes to include */
pools = linked_list_create_from_enumerator(
config->create_pool_enumerator(config));
- enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, pools, id, this->vips);
+ enumerator = charon->attributes->create_responder_enumerator(
+ charon->attributes, pools, id, this->vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
add_attribute(this, cp, type, value, NULL);
@@ -489,8 +488,8 @@ static status_t build_reply(private_mode_config_t *this, message_t *message)
/* query all pools until we get an address */
DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
- found = hydra->attributes->acquire_address(hydra->attributes,
- pools, id, requested);
+ found = charon->attributes->acquire_address(charon->attributes,
+ pools, id, requested);
if (found)
{
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
@@ -509,8 +508,8 @@ static status_t build_reply(private_mode_config_t *this, message_t *message)
charon->bus->assign_vips(charon->bus, this->ike_sa, TRUE);
/* query registered providers for additional attributes to include */
- enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, pools, id, vips);
+ enumerator = charon->attributes->create_responder_enumerator(
+ charon->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
cp->add_attribute(cp,
diff --git a/src/libcharon/sa/ikev2/tasks/ike_config.c b/src/libcharon/sa/ikev2/tasks/ike_config.c
index da06e2a36..e0602010e 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_config.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_config.c
@@ -17,7 +17,6 @@
#include "ike_config.h"
#include <daemon.h>
-#include <hydra.h>
#include <encoding/payloads/cp_payload.h>
typedef struct private_ike_config_t private_ike_config_t;
@@ -127,7 +126,7 @@ static void handle_attribute(private_ike_config_t *this,
enumerator->destroy(enumerator);
/* and pass it to the handle function */
- handler = hydra->attributes->handle(hydra->attributes,
+ handler = charon->attributes->handle(charon->attributes,
this->ike_sa->get_other_id(this->ike_sa), handler,
ca->get_type(ca), ca->get_chunk(ca));
this->ike_sa->add_configuration_attribute(this->ike_sa,
@@ -274,8 +273,8 @@ METHOD(task_t, build_i, status_t,
enumerator->destroy(enumerator);
}
- enumerator = hydra->attributes->create_initiator_enumerator(
- hydra->attributes,
+ enumerator = charon->attributes->create_initiator_enumerator(
+ charon->attributes,
this->ike_sa->get_other_id(this->ike_sa), vips);
while (enumerator->enumerate(enumerator, &handler, &type, &data))
{
@@ -352,8 +351,8 @@ METHOD(task_t, build_r, status_t,
/* query all pools until we get an address */
DBG1(DBG_IKE, "peer requested virtual IP %H", requested);
- found = hydra->attributes->acquire_address(hydra->attributes,
- pools, id, requested);
+ found = charon->attributes->acquire_address(charon->attributes,
+ pools, id, requested);
if (found)
{
DBG1(DBG_IKE, "assigning virtual IP %H to peer '%Y'", found, id);
@@ -398,8 +397,8 @@ METHOD(task_t, build_r, status_t,
}
/* query registered providers for additional attributes to include */
- enumerator = hydra->attributes->create_responder_enumerator(
- hydra->attributes, pools, id, vips);
+ enumerator = charon->attributes->create_responder_enumerator(
+ charon->attributes, pools, id, vips);
while (enumerator->enumerate(enumerator, &type, &value))
{
if (!cp)
diff --git a/src/libcharon/tests/Makefile.am b/src/libcharon/tests/Makefile.am
index 317e019c1..c8be28594 100644
--- a/src/libcharon/tests/Makefile.am
+++ b/src/libcharon/tests/Makefile.am
@@ -3,6 +3,7 @@ TESTS = libcharon_tests
check_PROGRAMS = $(TESTS)
libcharon_tests_SOURCES = \
+ suites/test_mem_pool.c \
libcharon_tests.h libcharon_tests.c
libcharon_tests_CFLAGS = \
diff --git a/src/libcharon/tests/libcharon_tests.h b/src/libcharon/tests/libcharon_tests.h
index 05502f18e..dc9681aeb 100644
--- a/src/libcharon/tests/libcharon_tests.h
+++ b/src/libcharon/tests/libcharon_tests.h
@@ -12,3 +12,5 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
+
+TEST_SUITE(mem_pool_suite_create)
diff --git a/src/libcharon/tests/suites/test_mem_pool.c b/src/libcharon/tests/suites/test_mem_pool.c
new file mode 100644
index 000000000..c47a92f78
--- /dev/null
+++ b/src/libcharon/tests/suites/test_mem_pool.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#include "test_suite.h"
+
+#include <attributes/mem_pool.h>
+
+static void assert_host(char *expected, host_t *host)
+{
+ if (!expected)
+ {
+ ck_assert_msg(!host, "not epxecting IP != %+H", host);
+ }
+ else
+ {
+ host_t *verifier;
+ verifier = host_create_from_string(expected, 0);
+ ck_assert_msg(host, "expected IP %+H != NULL", verifier);
+ ck_assert_msg(verifier->ip_equals(verifier, host), "expected IP %+H != "
+ "%+H", verifier, host);;
+ verifier->destroy(verifier);
+ }
+}
+
+static void assert_acquire(mem_pool_t *pool, char *requested, char *expected,
+ mem_pool_op_t operation)
+{
+ identification_t *id;
+ host_t *req, *acquired;
+
+ id = identification_create_from_string("tester");
+ req = host_create_from_string(requested, 0);
+
+ acquired = pool->acquire_address(pool, id, req, operation);
+ assert_host(expected, acquired);
+ DESTROY_IF(acquired);
+
+ req->destroy(req);
+ id->destroy(id);
+}
+
+static void assert_acquires_new(mem_pool_t *pool, char *pattern, int first)
+{
+ char expected[16];
+ int i;
+
+ for (i = 0; i < pool->get_size(pool); i++)
+ {
+ snprintf(expected, sizeof(expected), pattern, first + i);
+ assert_acquire(pool, "0.0.0.0", expected, MEM_POOL_NEW);
+ ck_assert_int_eq(i + 1, pool->get_online(pool));
+ }
+ assert_acquire(pool, "0.0.0.0", NULL, MEM_POOL_NEW);
+}
+
+START_TEST(test_config)
+{
+ mem_pool_t *pool;
+
+ pool = mem_pool_create("test", NULL, 0);
+ ck_assert_int_eq(0, pool->get_size(pool));
+ assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW);
+ assert_acquire(pool, "10.0.1.1", "10.0.1.1", MEM_POOL_NEW);
+ assert_acquire(pool, "0.0.0.0", "0.0.0.0", MEM_POOL_NEW);
+ assert_acquire(pool, "255.255.255.255", "255.255.255.255", MEM_POOL_NEW);
+ ck_assert_int_eq(0, pool->get_online(pool));
+ pool->destroy(pool);
+}
+END_TEST
+
+START_TEST(test_cidr)
+{
+ mem_pool_t *pool;
+ host_t *base;
+
+ base = host_create_from_string("192.168.0.0", 0);
+
+ pool = mem_pool_create("test", base, 32);
+ ck_assert_int_eq(1, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 0);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 31);
+ ck_assert_int_eq(2, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 0);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 30);
+ ck_assert_int_eq(2, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 1);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 29);
+ ck_assert_int_eq(6, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 1);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 24);
+ ck_assert_int_eq(254, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 1);
+ pool->destroy(pool);
+
+ base->destroy(base);
+}
+END_TEST
+
+START_TEST(test_cidr_offset)
+{
+ mem_pool_t *pool;
+ host_t *base;
+
+ base = host_create_from_string("192.168.0.1", 0);
+ pool = mem_pool_create("test", base, 31);
+ ck_assert_int_eq(1, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 1);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 30);
+ ck_assert_int_eq(2, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 1);
+ pool->destroy(pool);
+ base->destroy(base);
+
+ base = host_create_from_string("192.168.0.2", 0);
+ pool = mem_pool_create("test", base, 30);
+ ck_assert_int_eq(1, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 2);
+ pool->destroy(pool);
+
+ pool = mem_pool_create("test", base, 24);
+ ck_assert_int_eq(253, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 2);
+ pool->destroy(pool);
+ base->destroy(base);
+
+ base = host_create_from_string("192.168.0.254", 0);
+ pool = mem_pool_create("test", base, 24);
+ ck_assert_int_eq(1, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 254);
+ pool->destroy(pool);
+ base->destroy(base);
+
+ /* due to size == 0 we get the requested IP back */
+ base = host_create_from_string("192.168.0.255", 0);
+ pool = mem_pool_create("test", base, 24);
+ ck_assert_int_eq(0, pool->get_size(pool));
+ assert_acquire(pool, "192.168.0.1", "192.168.0.1", MEM_POOL_NEW);
+ pool->destroy(pool);
+
+ base->destroy(base);
+}
+END_TEST
+
+START_TEST(test_range)
+{
+ mem_pool_t *pool;
+ host_t *from, *to;
+
+ from = host_create_from_string("192.168.0.0", 0);
+ to = host_create_from_string("192.168.0.0", 0);
+ pool = mem_pool_create_range("test", from, to);
+ ck_assert_int_eq(1, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 0);
+ pool->destroy(pool);
+
+ to->destroy(to);
+ to = host_create_from_string("192.168.0.1", 0);
+ pool = mem_pool_create_range("test", from, to);
+ ck_assert_int_eq(2, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 0);
+ pool->destroy(pool);
+
+ from->destroy(from);
+ from = host_create_from_string("192.168.0.10", 0);
+ pool = mem_pool_create_range("test", from, to);
+ ck_assert(!pool);
+
+ to->destroy(to);
+ to = host_create_from_string("192.168.0.20", 0);
+ pool = mem_pool_create_range("test", from, to);
+ ck_assert_int_eq(11, pool->get_size(pool));
+ assert_acquires_new(pool, "192.168.0.%d", 10);
+ pool->destroy(pool);
+
+ from->destroy(from);
+ from = host_create_from_string("fec::1", 0);
+ to->destroy(to);
+ to = host_create_from_string("fed::1", 0);
+ pool = mem_pool_create_range("test", from, to);
+ ck_assert(!pool);
+
+ from->destroy(from);
+ to->destroy(to);
+}
+END_TEST
+
+Suite *mem_pool_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("mem_pool");
+
+ tc = tcase_create("%config-like pool");
+ tcase_add_test(tc, test_config);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("cidr constructor");
+ tcase_add_test(tc, test_cidr);
+ tcase_add_test(tc, test_cidr_offset);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("range constructor");
+ tcase_add_test(tc, test_range);
+ suite_add_tcase(s, tc);
+
+ return s;
+}