diff options
Diffstat (limited to 'src/libcharon')
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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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, ¤t)) + { + 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; +} |