diff options
Diffstat (limited to 'src/libcharon/attributes')
-rw-r--r-- | src/libcharon/attributes/attribute_handler.h | 76 | ||||
-rw-r--r-- | src/libcharon/attributes/attribute_manager.c | 347 | ||||
-rw-r--r-- | src/libcharon/attributes/attribute_manager.h | 154 | ||||
-rw-r--r-- | src/libcharon/attributes/attribute_provider.h | 71 | ||||
-rw-r--r-- | src/libcharon/attributes/attributes.c | 114 | ||||
-rw-r--r-- | src/libcharon/attributes/attributes.h | 91 | ||||
-rw-r--r-- | src/libcharon/attributes/mem_pool.c | 735 | ||||
-rw-r--r-- | src/libcharon/attributes/mem_pool.h | 154 |
8 files changed, 1742 insertions, 0 deletions
diff --git a/src/libcharon/attributes/attribute_handler.h b/src/libcharon/attributes/attribute_handler.h new file mode 100644 index 000000000..3c14323a3 --- /dev/null +++ b/src/libcharon/attributes/attribute_handler.h @@ -0,0 +1,76 @@ +/* + * 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_ + +typedef struct attribute_handler_t attribute_handler_t; + +#include <sa/ike_sa.h> +#include <utils/chunk.h> +#include <collections/linked_list.h> + +#include "attributes.h" + +/** + * 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 ike_sa IKE_SA under which attribute is 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, ike_sa_t *ike_sa, + 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. + * + * @param ike_sa IKE_SA which releases attribute + * @param type type of configuration attribute to release + * @param data associated attribute data + */ + void (*release)(attribute_handler_t *this, ike_sa_t *ike_sa, + configuration_attribute_type_t type, chunk_t data); + + /** + * Enumerate attributes to request from a server. + * + * @param ike_sa IKE_SA to request attributes for + * @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, + ike_sa_t *ike_sa, 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..2ab7ed118 --- /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; + /** associated IKE_SA */ + ike_sa_t *ike_sa; + /** 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, + ike_sa_t *ike_sa, 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, ike_sa, 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, + ike_sa_t *ike_sa) +{ + 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, ike_sa)) + { + 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->ike_sa, data->vips); +} + +METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*, + private_attribute_manager_t *this, linked_list_t *pools, + ike_sa_t *ike_sa, linked_list_t *vips) +{ + enum_data_t *data; + + INIT(data, + .pools = pools, + .ike_sa = ike_sa, + .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, ike_sa_t *ike_sa, + 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, ike_sa, 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, ike_sa, 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, + ike_sa_t *ike_sa, 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, ike_sa, 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; + /** IKE_SA to request attributes for */ + ike_sa_t *ike_sa; + /** 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->ike_sa, 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, ike_sa_t *ike_sa, 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, + .ike_sa = ike_sa, + .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..6db664968 --- /dev/null +++ b/src/libcharon/attributes/attribute_manager.h @@ -0,0 +1,154 @@ +/* + * 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" + +#include <sa/ike_sa.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 ike_sa associated IKE_SA for which an address is requested + * @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, ike_sa_t *ike_sa, + host_t *requested); + + /** + * Release a previously acquired address. + * + * @param pools list of pool names (char*) to release to + * @param address address to release + * @param ike_sa associated IKE_SA for which an address is released + * @return TRUE if address released to pool + */ + bool (*release_address)(attribute_manager_t *this, + linked_list_t *pools, host_t *address, + ike_sa_t *ike_sa); + + /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param pool list of pools names (char*) to query attributes from + * @param ike_sa associated IKE_SA for which attributes are requested + * @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, ike_sa_t *ike_sa, + 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 ike_sa associated IKE_SA to handle an attribute for + * @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, + ike_sa_t *ike_sa, attribute_handler_t *handler, + configuration_attribute_type_t type, chunk_t data); + + /** + * Release an attribute previously handle()d by a handler. + * + * @param ike_sa associated IKE_SA to release an attribute for + * @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, + ike_sa_t *ike_sa, configuration_attribute_type_t type, + chunk_t data); + + /** + * Create an enumerator over attributes to request from server. + * + * @param ike_sa associated IKE_SA to request attributes for + * @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, + ike_sa_t *ike_sa, 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..57453c2a0 --- /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 <sa/ike_sa.h> +#include <networking/host.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 ike_sa associated IKE_SA to assign address over + * @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, ike_sa_t *ike_sa, + host_t *requested); + /** + * Release a previously acquired address. + * + * @param pools list of pool names (char*) to release to + * @param address address to release + * @param ike_sa IKE_SA to release address for + * @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, + ike_sa_t *ike_sa); + + /** + * Create an enumerator over attributes to hand out to a peer. + * + * @param pool list of pools names (char*) to query attributes from + * @param ike_sa IKE_SA to request attributes for + * @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, ike_sa_t *ike_sa, + 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..279668249 --- /dev/null +++ b/src/libcharon/attributes/mem_pool.c @@ -0,0 +1,735 @@ +/* + * 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; +}; + +/** + * A unique lease address offset, with a hash of the peer host address + */ +typedef struct { + /** lease, as offset */ + u_int offset; + /** hash of remote address, to allow duplicates */ + u_int hash; +} unique_lease_t; + +/** + * Lease entry. + */ +typedef struct { + /* identitiy reference */ + identification_t *id; + /* array of online leases, as unique_lease_t */ + 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(unique_lease_t), 0), + .offline = array_create(sizeof(u_int), 0), + ); + return entry; +} + +/** + * Destroy an entry + */ +static void entry_destroy(entry_t *this) +{ + this->id->destroy(this->id); + array_destroy(this->online); + array_destroy(this->offline); + free(this); +} + +/** + * 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; +} + +/** + * Create a unique hash for a remote address + */ +static u_int hash_addr(host_t *addr) +{ + if (addr) + { + return chunk_hash_inc(addr->get_address(addr), addr->get_port(addr)); + } + return 0; +} + +/** + * Get an existing lease for id + */ +static int get_existing(private_mem_pool_t *this, identification_t *id, + host_t *requested, host_t *peer) +{ + enumerator_t *enumerator; + unique_lease_t *lease, reassign; + 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)) + { + reassign.offset = offset = *current; + reassign.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &reassign); + array_remove_at(entry->offline, enumerator); + } + enumerator->destroy(enumerator); + if (offset) + { + DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id); + return offset; + } + if (!peer) + { + return 0; + } + /* check for a valid online lease to reassign */ + enumerator = array_create_enumerator(entry->online); + while (enumerator->enumerate(enumerator, &lease)) + { + if (lease->offset == host2offset(this, requested) && + lease->hash == hash_addr(peer)) + { + offset = lease->offset; + /* add an additional "online" entry */ + array_insert(entry->online, ARRAY_TAIL, lease); + 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, host_t *peer) +{ + entry_t *entry; + unique_lease_t lease = {}; + + 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 */ + lease.offset = ++this->unused + (this->base_is_network_id ? 1 : 0); + lease.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &lease); + DBG1(DBG_CFG, "assigning new lease to '%Y'", id); + } + return lease.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, + host_t *peer) +{ + enumerator_t *enumerator; + entry_t *entry; + u_int current; + unique_lease_t lease = {}; + + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + if (array_remove(entry->offline, ARRAY_HEAD, ¤t)) + { + lease.offset = current; + DBG1(DBG_CFG, "reassigning existing offline lease by '%Y' " + "to '%Y'", entry->id, id); + } + if (!array_count(entry->online) && !array_count(entry->offline)) + { + this->leases->remove_at(this->leases, enumerator); + entry_destroy(entry); + } + if (lease.offset) + { + break; + } + } + enumerator->destroy(enumerator); + + if (lease.offset) + { + entry = this->leases->get(this->leases, id); + if (!entry) + { + entry = entry_create(id); + this->leases->put(this->leases, entry->id, entry); + } + lease.hash = hash_addr(peer); + array_insert(entry->online, ARRAY_TAIL, &lease); + } + return lease.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, host_t *peer) +{ + 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, peer); + break; + case MEM_POOL_NEW: + offset = get_new(this, id, peer); + break; + case MEM_POOL_REASSIGN: + offset = get_reassigned(this, id, peer); + 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; + unique_lease_t *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 == 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; + unique_lease_t *lease; + + DESTROY_IF(this->addr); + this->addr = NULL; + + while (TRUE) + { + if (this->entry) + { + if (this->online->enumerate(this->online, &lease)) + { + *id = this->entry->id; + *addr = this->addr = offset2host(this->pool, lease->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_destroy(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), + ); + + 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..3ee1dd37d --- /dev/null +++ b/src/libcharon/attributes/mem_pool.h @@ -0,0 +1,154 @@ +/* + * 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). + * + * If the same identity requests a virtual IP that is already assigned to + * it, the peer address and port is used to check if it is the same client + * instance that is connecting. If this is true, the request is considered + * a request for a reauthentication attempt, and the same virtual IP gets + * assigned to the peer. + * + * @param id the id to acquire an address for + * @param requested acquire this address, if possible + * @param operation acquire operation to perform, see above + * @param peer optional remote IKE address and port + * @return the acquired address + */ + host_t* (*acquire_address)(mem_pool_t *this, identification_t *id, + host_t *requested, mem_pool_op_t operation, + host_t *peer); + + /** + * 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_ @} */ |