attributes: Move the configuration attributes framework to libcharon

This commit is contained in:
Martin Willi
2015-02-20 13:34:55 +01:00
parent 1f29cd2c5d
commit 751363275f
40 changed files with 119 additions and 129 deletions
-4
View File
@@ -4,10 +4,6 @@ include $(CLEAR_VARS)
# copy-n-paste from Makefile.am
libhydra_la_SOURCES := \
hydra.c hydra.h \
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 \
kernel/kernel_interface.c kernel/kernel_interface.h \
kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
kernel/kernel_net.c kernel/kernel_net.h \
-4
View File
@@ -2,10 +2,6 @@ ipseclib_LTLIBRARIES = libhydra.la
libhydra_la_SOURCES = \
hydra.c hydra.h \
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 \
kernel/kernel_interface.c kernel/kernel_interface.h \
kernel/kernel_ipsec.c kernel/kernel_ipsec.h \
kernel/kernel_net.c kernel/kernel_net.h \
@@ -1,72 +0,0 @@
/*
* 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_ @}*/
-348
View File
@@ -1,348 +0,0 @@
/*
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "attribute_manager.h"
#include <utils/debug.h>
#include <collections/linked_list.h>
#include <threading/rwlock.h>
typedef struct private_attribute_manager_t private_attribute_manager_t;
/**
* private data of attribute_manager
*/
struct private_attribute_manager_t {
/**
* public functions
*/
attribute_manager_t public;
/**
* list of registered providers
*/
linked_list_t *providers;
/**
* list of registered handlers
*/
linked_list_t *handlers;
/**
* rwlock provider list
*/
rwlock_t *lock;
};
/**
* Data to pass to enumerator filters
*/
typedef struct {
/** attribute group pools */
linked_list_t *pools;
/** server/peer identity */
identification_t *id;
/** requesting/assigned virtual IPs */
linked_list_t *vips;
} enum_data_t;
METHOD(attribute_manager_t, acquire_address, host_t*,
private_attribute_manager_t *this, linked_list_t *pools,
identification_t *id, host_t *requested)
{
enumerator_t *enumerator;
attribute_provider_t *current;
host_t *host = NULL;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
host = current->acquire_address(current, pools, id, requested);
if (host)
{
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return host;
}
METHOD(attribute_manager_t, release_address, bool,
private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
identification_t *id)
{
enumerator_t *enumerator;
attribute_provider_t *current;
bool found = FALSE;
this->lock->read_lock(this->lock);
enumerator = this->providers->create_enumerator(this->providers);
while (enumerator->enumerate(enumerator, &current))
{
if (current->release_address(current, pools, address, id))
{
found = TRUE;
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
return found;
}
/**
* inner enumerator constructor for responder attributes
*/
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
enum_data_t *data)
{
return provider->create_attribute_enumerator(provider, data->pools,
data->id, data->vips);
}
METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
private_attribute_manager_t *this, linked_list_t *pools,
identification_t *id, linked_list_t *vips)
{
enum_data_t *data;
INIT(data,
.pools = pools,
.id = id,
.vips = vips,
);
this->lock->read_lock(this->lock);
return enumerator_create_cleaner(
enumerator_create_nested(
this->providers->create_enumerator(this->providers),
(void*)responder_enum_create, data, free),
(void*)this->lock->unlock, this->lock);
}
METHOD(attribute_manager_t, add_provider, void,
private_attribute_manager_t *this, attribute_provider_t *provider)
{
this->lock->write_lock(this->lock);
this->providers->insert_last(this->providers, provider);
this->lock->unlock(this->lock);
}
METHOD(attribute_manager_t, remove_provider, void,
private_attribute_manager_t *this, attribute_provider_t *provider)
{
this->lock->write_lock(this->lock);
this->providers->remove(this->providers, provider, NULL);
this->lock->unlock(this->lock);
}
METHOD(attribute_manager_t, handle, attribute_handler_t*,
private_attribute_manager_t *this, identification_t *server,
attribute_handler_t *handler, configuration_attribute_type_t type,
chunk_t data)
{
enumerator_t *enumerator;
attribute_handler_t *current, *handled = NULL;
this->lock->read_lock(this->lock);
/* try to find the passed handler */
enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current))
{
if (current == handler && current->handle(current, server, type, data))
{
handled = current;
break;
}
}
enumerator->destroy(enumerator);
if (!handled)
{ /* handler requesting this attribute not found, try any other */
enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current))
{
if (current->handle(current, server, type, data))
{
handled = current;
break;
}
}
enumerator->destroy(enumerator);
}
this->lock->unlock(this->lock);
if (!handled)
{
DBG1(DBG_CFG, "handling %N attribute failed",
configuration_attribute_type_names, type);
}
return handled;
}
METHOD(attribute_manager_t, release, void,
private_attribute_manager_t *this, attribute_handler_t *handler,
identification_t *server, configuration_attribute_type_t type, chunk_t data)
{
enumerator_t *enumerator;
attribute_handler_t *current;
this->lock->read_lock(this->lock);
enumerator = this->handlers->create_enumerator(this->handlers);
while (enumerator->enumerate(enumerator, &current))
{
if (current == handler)
{
current->release(current, server, type, data);
break;
}
}
enumerator->destroy(enumerator);
this->lock->unlock(this->lock);
}
/**
* Enumerator implementation to enumerate nested initiator attributes
*/
typedef struct {
/** implements enumerator_t */
enumerator_t public;
/** back ref */
private_attribute_manager_t *this;
/** currently processing handler */
attribute_handler_t *handler;
/** outer enumerator over handlers */
enumerator_t *outer;
/** inner enumerator over current handlers attributes */
enumerator_t *inner;
/** server ID we want attributes for */
identification_t *id;
/** virtual IPs we are requesting along with attriubutes */
linked_list_t *vips;
} initiator_enumerator_t;
/**
* Enumerator implementation for initiator attributes
*/
static bool initiator_enumerate(initiator_enumerator_t *this,
attribute_handler_t **handler,
configuration_attribute_type_t *type,
chunk_t *value)
{
/* enumerate inner attributes using outer handler enumerator */
while (!this->inner || !this->inner->enumerate(this->inner, type, value))
{
if (!this->outer->enumerate(this->outer, &this->handler))
{
return FALSE;
}
DESTROY_IF(this->inner);
this->inner = this->handler->create_attribute_enumerator(this->handler,
this->id, this->vips);
}
/* inject the handler as additional attribute */
*handler = this->handler;
return TRUE;
}
/**
* Cleanup function of initiator attribute enumerator
*/
static void initiator_destroy(initiator_enumerator_t *this)
{
this->this->lock->unlock(this->this->lock);
this->outer->destroy(this->outer);
DESTROY_IF(this->inner);
free(this);
}
METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
{
initiator_enumerator_t *enumerator;
this->lock->read_lock(this->lock);
INIT(enumerator,
.public = {
.enumerate = (void*)initiator_enumerate,
.destroy = (void*)initiator_destroy,
},
.this = this,
.id = id,
.vips = vips,
.outer = this->handlers->create_enumerator(this->handlers),
);
return &enumerator->public;
}
METHOD(attribute_manager_t, add_handler, void,
private_attribute_manager_t *this, attribute_handler_t *handler)
{
this->lock->write_lock(this->lock);
this->handlers->insert_last(this->handlers, handler);
this->lock->unlock(this->lock);
}
METHOD(attribute_manager_t, remove_handler, void,
private_attribute_manager_t *this, attribute_handler_t *handler)
{
this->lock->write_lock(this->lock);
this->handlers->remove(this->handlers, handler, NULL);
this->lock->unlock(this->lock);
}
METHOD(attribute_manager_t, destroy, void,
private_attribute_manager_t *this)
{
this->providers->destroy(this->providers);
this->handlers->destroy(this->handlers);
this->lock->destroy(this->lock);
free(this);
}
/*
* see header file
*/
attribute_manager_t *attribute_manager_create()
{
private_attribute_manager_t *this;
INIT(this,
.public = {
.acquire_address = _acquire_address,
.release_address = _release_address,
.create_responder_enumerator = _create_responder_enumerator,
.add_provider = _add_provider,
.remove_provider = _remove_provider,
.handle = _handle,
.release = _release,
.create_initiator_enumerator = _create_initiator_enumerator,
.add_handler = _add_handler,
.remove_handler = _remove_handler,
.destroy = _destroy,
},
.providers = linked_list_create(),
.handlers = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
return &this->public;
}
-153
View File
@@ -1,153 +0,0 @@
/*
* 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_ @}*/
@@ -1,71 +0,0 @@
/*
* 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_ @}*/
-114
View File
@@ -1,114 +0,0 @@
/*
* 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);
-91
View File
@@ -1,91 +0,0 @@
/*
* 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_ @}*/
-695
View File
@@ -1,695 +0,0 @@
/*
* Copyright (C) 2010 Tobias Brunner
* Copyright (C) 2008-2010 Martin Willi
* Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "mem_pool.h"
#include <library.h>
#include <hydra.h>
#include <utils/debug.h>
#include <collections/hashtable.h>
#include <collections/array.h>
#include <threading/mutex.h>
#define POOL_LIMIT (sizeof(u_int)*8 - 1)
typedef struct private_mem_pool_t private_mem_pool_t;
/**
* private data of mem_pool_t
*/
struct private_mem_pool_t {
/**
* public interface
*/
mem_pool_t public;
/**
* name of the pool
*/
char *name;
/**
* base address of the pool
*/
host_t *base;
/**
* whether base is the network id of the subnet on which the pool is based
*/
bool base_is_network_id;
/**
* size of the pool
*/
u_int size;
/**
* next unused address
*/
u_int unused;
/**
* lease hashtable [identity => entry]
*/
hashtable_t *leases;
/**
* lock to safely access the pool
*/
mutex_t *mutex;
/**
* Do we reassign online leases to the same identity, if requested?
*/
bool reassign_online;
};
/**
* Lease entry.
*/
typedef struct {
/* identitiy reference */
identification_t *id;
/* array of online leases, as u_int offset */
array_t *online;
/* array of offline leases, as u_int offset */
array_t *offline;
} entry_t;
/**
* Create a new entry
*/
static entry_t* entry_create(identification_t *id)
{
entry_t *entry;
INIT(entry,
.id = id->clone(id),
.online = array_create(sizeof(u_int), 0),
.offline = array_create(sizeof(u_int), 0),
);
return entry;
}
/**
* hashtable hash function for identities
*/
static u_int id_hash(identification_t *id)
{
return chunk_hash(id->get_encoding(id));
}
/**
* hashtable equals function for identities
*/
static bool id_equals(identification_t *a, identification_t *b)
{
return a->equals(a, b);
}
/**
* convert a pool offset to an address
*/
static host_t* offset2host(private_mem_pool_t *pool, int offset)
{
chunk_t addr;
host_t *host;
u_int32_t *pos;
offset--;
if (offset > pool->size)
{
return NULL;
}
addr = chunk_clone(pool->base->get_address(pool->base));
if (pool->base->get_family(pool->base) == AF_INET6)
{
pos = (u_int32_t*)(addr.ptr + 12);
}
else
{
pos = (u_int32_t*)addr.ptr;
}
*pos = htonl(offset + ntohl(*pos));
host = host_create_from_chunk(pool->base->get_family(pool->base), addr, 0);
free(addr.ptr);
return host;
}
/**
* convert a host to a pool offset
*/
static int host2offset(private_mem_pool_t *pool, host_t *addr)
{
chunk_t host, base;
u_int32_t hosti, basei;
if (addr->get_family(addr) != pool->base->get_family(pool->base))
{
return -1;
}
host = addr->get_address(addr);
base = pool->base->get_address(pool->base);
if (addr->get_family(addr) == AF_INET6)
{
/* only look at last /32 block */
if (!memeq(host.ptr, base.ptr, 12))
{
return -1;
}
host = chunk_skip(host, 12);
base = chunk_skip(base, 12);
}
hosti = ntohl(*(u_int32_t*)(host.ptr));
basei = ntohl(*(u_int32_t*)(base.ptr));
if (hosti > basei + pool->size)
{
return -1;
}
return hosti - basei + 1;
}
METHOD(mem_pool_t, get_name, const char*,
private_mem_pool_t *this)
{
return this->name;
}
METHOD(mem_pool_t, get_base, host_t*,
private_mem_pool_t *this)
{
return this->base;
}
METHOD(mem_pool_t, get_size, u_int,
private_mem_pool_t *this)
{
return this->size;
}
METHOD(mem_pool_t, get_online, u_int,
private_mem_pool_t *this)
{
enumerator_t *enumerator;
entry_t *entry;
u_int count = 0;
this->mutex->lock(this->mutex);
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
count += array_count(entry->online);
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return count;
}
METHOD(mem_pool_t, get_offline, u_int,
private_mem_pool_t *this)
{
enumerator_t *enumerator;
entry_t *entry;
u_int count = 0;
this->mutex->lock(this->mutex);
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
count += array_count(entry->offline);
}
enumerator->destroy(enumerator);
this->mutex->unlock(this->mutex);
return count;
}
/**
* Get an existing lease for id
*/
static int get_existing(private_mem_pool_t *this, identification_t *id,
host_t *requested)
{
enumerator_t *enumerator;
u_int *current;
entry_t *entry;
int offset = 0;
entry = this->leases->get(this->leases, id);
if (!entry)
{
return 0;
}
/* check for a valid offline lease, refresh */
enumerator = array_create_enumerator(entry->offline);
if (enumerator->enumerate(enumerator, &current))
{
offset = *current;
array_insert(entry->online, ARRAY_TAIL, current);
array_remove_at(entry->offline, enumerator);
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
return offset;
}
if (!this->reassign_online)
{
return 0;
}
/* check for a valid online lease to reassign */
enumerator = array_create_enumerator(entry->online);
while (enumerator->enumerate(enumerator, &current))
{
if (*current == host2offset(this, requested))
{
offset = *current;
/* add an additional "online" entry */
array_insert(entry->online, ARRAY_TAIL, current);
break;
}
}
enumerator->destroy(enumerator);
if (offset)
{
DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
}
return offset;
}
/**
* Get a new lease for id
*/
static int get_new(private_mem_pool_t *this, identification_t *id)
{
entry_t *entry;
u_int offset = 0;
if (this->unused < this->size)
{
entry = this->leases->get(this->leases, id);
if (!entry)
{
entry = entry_create(id);
this->leases->put(this->leases, entry->id, entry);
}
/* assigning offset, starting by 1 */
offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
array_insert(entry->online, ARRAY_TAIL, &offset);
DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
}
return offset;
}
/**
* Get a reassigned lease for id in case the pool is full
*/
static int get_reassigned(private_mem_pool_t *this, identification_t *id)
{
enumerator_t *enumerator;
entry_t *entry;
u_int current, offset = 0;
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
if (array_remove(entry->offline, ARRAY_HEAD, &current))
{
offset = current;
DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
" to '%Y'", entry->id, id);
break;
}
}
enumerator->destroy(enumerator);
if (offset)
{
entry = this->leases->get(this->leases, id);
if (!entry)
{
entry = entry_create(id);
this->leases->put(this->leases, entry->id, entry);
}
array_insert(entry->online, ARRAY_TAIL, &offset);
}
return offset;
}
METHOD(mem_pool_t, acquire_address, host_t*,
private_mem_pool_t *this, identification_t *id, host_t *requested,
mem_pool_op_t operation)
{
int offset = 0;
/* if the pool is empty (e.g. in the %config case) we simply return the
* requested address */
if (this->size == 0)
{
return requested->clone(requested);
}
if (requested->get_family(requested) !=
this->base->get_family(this->base))
{
return NULL;
}
this->mutex->lock(this->mutex);
switch (operation)
{
case MEM_POOL_EXISTING:
offset = get_existing(this, id, requested);
break;
case MEM_POOL_NEW:
offset = get_new(this, id);
break;
case MEM_POOL_REASSIGN:
offset = get_reassigned(this, id);
if (!offset)
{
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
this->name);
}
break;
default:
break;
}
this->mutex->unlock(this->mutex);
if (offset)
{
return offset2host(this, offset);
}
return NULL;
}
METHOD(mem_pool_t, release_address, bool,
private_mem_pool_t *this, host_t *address, identification_t *id)
{
enumerator_t *enumerator;
bool found = FALSE, more = FALSE;
entry_t *entry;
u_int offset, *current;
if (this->size != 0)
{
this->mutex->lock(this->mutex);
entry = this->leases->get(this->leases, id);
if (entry)
{
offset = host2offset(this, address);
enumerator = array_create_enumerator(entry->online);
while (enumerator->enumerate(enumerator, &current))
{
if (*current == offset)
{
if (!found)
{ /* remove the first entry only */
array_remove_at(entry->online, enumerator);
found = TRUE;
}
else
{ /* but check for more entries */
more = TRUE;
break;
}
}
}
enumerator->destroy(enumerator);
if (found && !more)
{
/* no tunnels are online anymore for this lease, make offline */
array_insert(entry->offline, ARRAY_TAIL, &offset);
DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
}
}
this->mutex->unlock(this->mutex);
}
return found;
}
/**
* lease enumerator
*/
typedef struct {
/** implemented enumerator interface */
enumerator_t public;
/** hash-table enumerator */
enumerator_t *entries;
/** online enumerator */
enumerator_t *online;
/** offline enumerator */
enumerator_t *offline;
/** enumerated pool */
private_mem_pool_t *pool;
/** currently enumerated entry */
entry_t *entry;
/** currently enumerated lease address */
host_t *addr;
} lease_enumerator_t;
METHOD(enumerator_t, lease_enumerate, bool,
lease_enumerator_t *this, identification_t **id, host_t **addr, bool *online)
{
u_int *offset;
DESTROY_IF(this->addr);
this->addr = NULL;
while (TRUE)
{
if (this->entry)
{
if (this->online->enumerate(this->online, &offset))
{
*id = this->entry->id;
*addr = this->addr = offset2host(this->pool, *offset);
*online = TRUE;
return TRUE;
}
if (this->offline->enumerate(this->offline, &offset))
{
*id = this->entry->id;
*addr = this->addr = offset2host(this->pool, *offset);
*online = FALSE;
return TRUE;
}
this->online->destroy(this->online);
this->offline->destroy(this->offline);
this->online = this->offline = NULL;
}
if (!this->entries->enumerate(this->entries, NULL, &this->entry))
{
return FALSE;
}
this->online = array_create_enumerator(this->entry->online);
this->offline = array_create_enumerator(this->entry->offline);
}
}
METHOD(enumerator_t, lease_enumerator_destroy, void,
lease_enumerator_t *this)
{
DESTROY_IF(this->addr);
DESTROY_IF(this->online);
DESTROY_IF(this->offline);
this->entries->destroy(this->entries);
this->pool->mutex->unlock(this->pool->mutex);
free(this);
}
METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
private_mem_pool_t *this)
{
lease_enumerator_t *enumerator;
this->mutex->lock(this->mutex);
INIT(enumerator,
.public = {
.enumerate = (void*)_lease_enumerate,
.destroy = _lease_enumerator_destroy,
},
.pool = this,
.entries = this->leases->create_enumerator(this->leases),
);
return &enumerator->public;
}
METHOD(mem_pool_t, destroy, void,
private_mem_pool_t *this)
{
enumerator_t *enumerator;
entry_t *entry;
enumerator = this->leases->create_enumerator(this->leases);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
entry->id->destroy(entry->id);
array_destroy(entry->online);
array_destroy(entry->offline);
free(entry);
}
enumerator->destroy(enumerator);
this->leases->destroy(this->leases);
this->mutex->destroy(this->mutex);
DESTROY_IF(this->base);
free(this->name);
free(this);
}
/**
* Generic constructor
*/
static private_mem_pool_t *create_generic(char *name)
{
private_mem_pool_t *this;
INIT(this,
.public = {
.get_name = _get_name,
.get_base = _get_base,
.get_size = _get_size,
.get_online = _get_online,
.get_offline = _get_offline,
.acquire_address = _acquire_address,
.release_address = _release_address,
.create_lease_enumerator = _create_lease_enumerator,
.destroy = _destroy,
},
.name = strdup(name),
.leases = hashtable_create((hashtable_hash_t)id_hash,
(hashtable_equals_t)id_equals, 16),
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.reassign_online = lib->settings->get_bool(lib->settings,
"%s.mem-pool.reassign_online", FALSE, lib->ns),
);
return this;
}
/**
* Check if the given host is the network ID of a subnet, that is, if hostbits
* are zero. Since we limit pools to 2^31 addresses we only have to check the
* last 4 bytes.
*/
static u_int network_id_diff(host_t *host, int hostbits)
{
u_int32_t last;
chunk_t addr;
if (!hostbits)
{
return 0;
}
addr = host->get_address(host);
last = untoh32(addr.ptr + addr.len - sizeof(last));
hostbits = sizeof(last) * 8 - hostbits;
return (last << hostbits) >> hostbits;
}
/**
* Described in header
*/
mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
{
private_mem_pool_t *this;
u_int diff;
int addr_bits;
this = create_generic(name);
if (base)
{
addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
bits = max(0, min(bits, addr_bits));
/* net bits -> host bits */
bits = addr_bits - bits;
if (bits > POOL_LIMIT)
{
bits = POOL_LIMIT;
DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
base, addr_bits - bits);
}
this->size = 1 << bits;
this->base = base->clone(base);
if (this->size > 2)
{
/* if base is the network id we later skip the first address,
* otherwise adjust the size to represent the actual number
* of assignable addresses */
diff = network_id_diff(base, bits);
if (!diff)
{
this->base_is_network_id = TRUE;
this->size--;
}
else
{
this->size -= diff;
}
/* skip the last address (broadcast) of the subnet */
this->size--;
}
else if (network_id_diff(base, bits))
{ /* only serve the second address of the subnet */
this->size--;
}
}
return &this->public;
}
/**
* Described in header
*/
mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to)
{
private_mem_pool_t *this;
chunk_t fromaddr, toaddr;
u_int32_t diff;
fromaddr = from->get_address(from);
toaddr = to->get_address(to);
if (from->get_family(from) != to->get_family(to) ||
fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) ||
memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0)
{
DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to);
return NULL;
}
if (fromaddr.len > sizeof(diff) &&
!chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)),
chunk_create(toaddr.ptr, toaddr.len - sizeof(diff))))
{
DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to);
return NULL;
}
this = create_generic(name);
this->base = from->clone(from);
diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) -
untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff));
this->size = diff + 1;
return &this->public;
}
-146
View File
@@ -1,146 +0,0 @@
/*
* 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_ @} */
-4
View File
@@ -57,7 +57,6 @@ void libhydra_deinit()
return;
}
this->public.attributes->destroy(this->public.attributes);
this->public.kernel_interface->destroy(this->public.kernel_interface);
free(this);
hydra = NULL;
@@ -78,9 +77,6 @@ bool libhydra_init()
}
INIT(this,
.public = {
.attributes = attribute_manager_create(),
},
.ref = 1,
);
hydra = &this->public;
-9
View File
@@ -16,9 +16,6 @@
/**
* @defgroup libhydra libhydra
*
* @defgroup attributes attributes
* @ingroup libhydra
*
* @defgroup hkernel kernel
* @ingroup libhydra
*
@@ -34,7 +31,6 @@
typedef struct hydra_t hydra_t;
#include <attributes/attribute_manager.h>
#include <kernel/kernel_interface.h>
#include <library.h>
@@ -44,11 +40,6 @@ typedef struct hydra_t hydra_t;
*/
struct hydra_t {
/**
* manager for payload attributes
*/
attribute_manager_t *attributes;
/**
* kernel interface to communicate with kernel
*/
-1
View File
@@ -3,7 +3,6 @@ TESTS = hydra_tests
check_PROGRAMS = $(TESTS)
hydra_tests_SOURCES = \
suites/test_mem_pool.c \
hydra_tests.h hydra_tests.c
hydra_tests_CFLAGS = \
-2
View File
@@ -12,5 +12,3 @@
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
TEST_SUITE(mem_pool_suite_create)
-230
View File
@@ -1,230 +0,0 @@
/*
* 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;
}