attributes: Move the configuration attributes framework to libcharon
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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, ¤t))
|
||||
{
|
||||
host = current->acquire_address(current, pools, id, requested);
|
||||
if (host)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, release_address, bool,
|
||||
private_attribute_manager_t *this, linked_list_t *pools, host_t *address,
|
||||
identification_t *id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
attribute_provider_t *current;
|
||||
bool found = FALSE;
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
enumerator = this->providers->create_enumerator(this->providers);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (current->release_address(current, pools, address, id))
|
||||
{
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* inner enumerator constructor for responder attributes
|
||||
*/
|
||||
static enumerator_t *responder_enum_create(attribute_provider_t *provider,
|
||||
enum_data_t *data)
|
||||
{
|
||||
return provider->create_attribute_enumerator(provider, data->pools,
|
||||
data->id, data->vips);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, create_responder_enumerator, enumerator_t*,
|
||||
private_attribute_manager_t *this, linked_list_t *pools,
|
||||
identification_t *id, linked_list_t *vips)
|
||||
{
|
||||
enum_data_t *data;
|
||||
|
||||
INIT(data,
|
||||
.pools = pools,
|
||||
.id = id,
|
||||
.vips = vips,
|
||||
);
|
||||
this->lock->read_lock(this->lock);
|
||||
return enumerator_create_cleaner(
|
||||
enumerator_create_nested(
|
||||
this->providers->create_enumerator(this->providers),
|
||||
(void*)responder_enum_create, data, free),
|
||||
(void*)this->lock->unlock, this->lock);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, add_provider, void,
|
||||
private_attribute_manager_t *this, attribute_provider_t *provider)
|
||||
{
|
||||
this->lock->write_lock(this->lock);
|
||||
this->providers->insert_last(this->providers, provider);
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, remove_provider, void,
|
||||
private_attribute_manager_t *this, attribute_provider_t *provider)
|
||||
{
|
||||
this->lock->write_lock(this->lock);
|
||||
this->providers->remove(this->providers, provider, NULL);
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, handle, attribute_handler_t*,
|
||||
private_attribute_manager_t *this, identification_t *server,
|
||||
attribute_handler_t *handler, configuration_attribute_type_t type,
|
||||
chunk_t data)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
attribute_handler_t *current, *handled = NULL;
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
|
||||
/* try to find the passed handler */
|
||||
enumerator = this->handlers->create_enumerator(this->handlers);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (current == handler && current->handle(current, server, type, data))
|
||||
{
|
||||
handled = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (!handled)
|
||||
{ /* handler requesting this attribute not found, try any other */
|
||||
enumerator = this->handlers->create_enumerator(this->handlers);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (current->handle(current, server, type, data))
|
||||
{
|
||||
handled = current;
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
this->lock->unlock(this->lock);
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
DBG1(DBG_CFG, "handling %N attribute failed",
|
||||
configuration_attribute_type_names, type);
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, release, void,
|
||||
private_attribute_manager_t *this, attribute_handler_t *handler,
|
||||
identification_t *server, configuration_attribute_type_t type, chunk_t data)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
attribute_handler_t *current;
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
enumerator = this->handlers->create_enumerator(this->handlers);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (current == handler)
|
||||
{
|
||||
current->release(current, server, type, data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerator implementation to enumerate nested initiator attributes
|
||||
*/
|
||||
typedef struct {
|
||||
/** implements enumerator_t */
|
||||
enumerator_t public;
|
||||
/** back ref */
|
||||
private_attribute_manager_t *this;
|
||||
/** currently processing handler */
|
||||
attribute_handler_t *handler;
|
||||
/** outer enumerator over handlers */
|
||||
enumerator_t *outer;
|
||||
/** inner enumerator over current handlers attributes */
|
||||
enumerator_t *inner;
|
||||
/** server ID we want attributes for */
|
||||
identification_t *id;
|
||||
/** virtual IPs we are requesting along with attriubutes */
|
||||
linked_list_t *vips;
|
||||
} initiator_enumerator_t;
|
||||
|
||||
/**
|
||||
* Enumerator implementation for initiator attributes
|
||||
*/
|
||||
static bool initiator_enumerate(initiator_enumerator_t *this,
|
||||
attribute_handler_t **handler,
|
||||
configuration_attribute_type_t *type,
|
||||
chunk_t *value)
|
||||
{
|
||||
/* enumerate inner attributes using outer handler enumerator */
|
||||
while (!this->inner || !this->inner->enumerate(this->inner, type, value))
|
||||
{
|
||||
if (!this->outer->enumerate(this->outer, &this->handler))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
DESTROY_IF(this->inner);
|
||||
this->inner = this->handler->create_attribute_enumerator(this->handler,
|
||||
this->id, this->vips);
|
||||
}
|
||||
/* inject the handler as additional attribute */
|
||||
*handler = this->handler;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup function of initiator attribute enumerator
|
||||
*/
|
||||
static void initiator_destroy(initiator_enumerator_t *this)
|
||||
{
|
||||
this->this->lock->unlock(this->this->lock);
|
||||
this->outer->destroy(this->outer);
|
||||
DESTROY_IF(this->inner);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*,
|
||||
private_attribute_manager_t *this, identification_t *id, linked_list_t *vips)
|
||||
{
|
||||
initiator_enumerator_t *enumerator;
|
||||
|
||||
this->lock->read_lock(this->lock);
|
||||
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = (void*)initiator_enumerate,
|
||||
.destroy = (void*)initiator_destroy,
|
||||
},
|
||||
.this = this,
|
||||
.id = id,
|
||||
.vips = vips,
|
||||
.outer = this->handlers->create_enumerator(this->handlers),
|
||||
);
|
||||
return &enumerator->public;
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, add_handler, void,
|
||||
private_attribute_manager_t *this, attribute_handler_t *handler)
|
||||
{
|
||||
this->lock->write_lock(this->lock);
|
||||
this->handlers->insert_last(this->handlers, handler);
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, remove_handler, void,
|
||||
private_attribute_manager_t *this, attribute_handler_t *handler)
|
||||
{
|
||||
this->lock->write_lock(this->lock);
|
||||
this->handlers->remove(this->handlers, handler, NULL);
|
||||
this->lock->unlock(this->lock);
|
||||
}
|
||||
|
||||
METHOD(attribute_manager_t, destroy, void,
|
||||
private_attribute_manager_t *this)
|
||||
{
|
||||
this->providers->destroy(this->providers);
|
||||
this->handlers->destroy(this->handlers);
|
||||
this->lock->destroy(this->lock);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* see header file
|
||||
*/
|
||||
attribute_manager_t *attribute_manager_create()
|
||||
{
|
||||
private_attribute_manager_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.acquire_address = _acquire_address,
|
||||
.release_address = _release_address,
|
||||
.create_responder_enumerator = _create_responder_enumerator,
|
||||
.add_provider = _add_provider,
|
||||
.remove_provider = _remove_provider,
|
||||
.handle = _handle,
|
||||
.release = _release,
|
||||
.create_initiator_enumerator = _create_initiator_enumerator,
|
||||
.add_handler = _add_handler,
|
||||
.remove_handler = _remove_handler,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.providers = linked_list_create(),
|
||||
.handlers = linked_list_create(),
|
||||
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
@@ -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_ @}*/
|
||||
@@ -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);
|
||||
@@ -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_ @}*/
|
||||
@@ -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, ¤t))
|
||||
{
|
||||
offset = *current;
|
||||
array_insert(entry->online, ARRAY_TAIL, current);
|
||||
array_remove_at(entry->offline, enumerator);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (offset)
|
||||
{
|
||||
DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id);
|
||||
return offset;
|
||||
}
|
||||
if (!this->reassign_online)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/* check for a valid online lease to reassign */
|
||||
enumerator = array_create_enumerator(entry->online);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (*current == host2offset(this, requested))
|
||||
{
|
||||
offset = *current;
|
||||
/* add an additional "online" entry */
|
||||
array_insert(entry->online, ARRAY_TAIL, current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
if (offset)
|
||||
{
|
||||
DBG1(DBG_CFG, "reassigning online lease to '%Y'", id);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new lease for id
|
||||
*/
|
||||
static int get_new(private_mem_pool_t *this, identification_t *id)
|
||||
{
|
||||
entry_t *entry;
|
||||
u_int offset = 0;
|
||||
|
||||
if (this->unused < this->size)
|
||||
{
|
||||
entry = this->leases->get(this->leases, id);
|
||||
if (!entry)
|
||||
{
|
||||
entry = entry_create(id);
|
||||
this->leases->put(this->leases, entry->id, entry);
|
||||
}
|
||||
/* assigning offset, starting by 1 */
|
||||
offset = ++this->unused + (this->base_is_network_id ? 1 : 0);
|
||||
array_insert(entry->online, ARRAY_TAIL, &offset);
|
||||
DBG1(DBG_CFG, "assigning new lease to '%Y'", id);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a reassigned lease for id in case the pool is full
|
||||
*/
|
||||
static int get_reassigned(private_mem_pool_t *this, identification_t *id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
entry_t *entry;
|
||||
u_int current, offset = 0;
|
||||
|
||||
enumerator = this->leases->create_enumerator(this->leases);
|
||||
while (enumerator->enumerate(enumerator, NULL, &entry))
|
||||
{
|
||||
if (array_remove(entry->offline, ARRAY_HEAD, ¤t))
|
||||
{
|
||||
offset = current;
|
||||
DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'"
|
||||
" to '%Y'", entry->id, id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (offset)
|
||||
{
|
||||
entry = this->leases->get(this->leases, id);
|
||||
if (!entry)
|
||||
{
|
||||
entry = entry_create(id);
|
||||
this->leases->put(this->leases, entry->id, entry);
|
||||
}
|
||||
array_insert(entry->online, ARRAY_TAIL, &offset);
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
METHOD(mem_pool_t, acquire_address, host_t*,
|
||||
private_mem_pool_t *this, identification_t *id, host_t *requested,
|
||||
mem_pool_op_t operation)
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
/* if the pool is empty (e.g. in the %config case) we simply return the
|
||||
* requested address */
|
||||
if (this->size == 0)
|
||||
{
|
||||
return requested->clone(requested);
|
||||
}
|
||||
|
||||
if (requested->get_family(requested) !=
|
||||
this->base->get_family(this->base))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
switch (operation)
|
||||
{
|
||||
case MEM_POOL_EXISTING:
|
||||
offset = get_existing(this, id, requested);
|
||||
break;
|
||||
case MEM_POOL_NEW:
|
||||
offset = get_new(this, id);
|
||||
break;
|
||||
case MEM_POOL_REASSIGN:
|
||||
offset = get_reassigned(this, id);
|
||||
if (!offset)
|
||||
{
|
||||
DBG1(DBG_CFG, "pool '%s' is full, unable to assign address",
|
||||
this->name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
|
||||
if (offset)
|
||||
{
|
||||
return offset2host(this, offset);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
METHOD(mem_pool_t, release_address, bool,
|
||||
private_mem_pool_t *this, host_t *address, identification_t *id)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
bool found = FALSE, more = FALSE;
|
||||
entry_t *entry;
|
||||
u_int offset, *current;
|
||||
|
||||
if (this->size != 0)
|
||||
{
|
||||
this->mutex->lock(this->mutex);
|
||||
entry = this->leases->get(this->leases, id);
|
||||
if (entry)
|
||||
{
|
||||
offset = host2offset(this, address);
|
||||
|
||||
enumerator = array_create_enumerator(entry->online);
|
||||
while (enumerator->enumerate(enumerator, ¤t))
|
||||
{
|
||||
if (*current == offset)
|
||||
{
|
||||
if (!found)
|
||||
{ /* remove the first entry only */
|
||||
array_remove_at(entry->online, enumerator);
|
||||
found = TRUE;
|
||||
}
|
||||
else
|
||||
{ /* but check for more entries */
|
||||
more = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
if (found && !more)
|
||||
{
|
||||
/* no tunnels are online anymore for this lease, make offline */
|
||||
array_insert(entry->offline, ARRAY_TAIL, &offset);
|
||||
DBG1(DBG_CFG, "lease %H by '%Y' went offline", address, id);
|
||||
}
|
||||
}
|
||||
this->mutex->unlock(this->mutex);
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
/**
|
||||
* lease enumerator
|
||||
*/
|
||||
typedef struct {
|
||||
/** implemented enumerator interface */
|
||||
enumerator_t public;
|
||||
/** hash-table enumerator */
|
||||
enumerator_t *entries;
|
||||
/** online enumerator */
|
||||
enumerator_t *online;
|
||||
/** offline enumerator */
|
||||
enumerator_t *offline;
|
||||
/** enumerated pool */
|
||||
private_mem_pool_t *pool;
|
||||
/** currently enumerated entry */
|
||||
entry_t *entry;
|
||||
/** currently enumerated lease address */
|
||||
host_t *addr;
|
||||
} lease_enumerator_t;
|
||||
|
||||
METHOD(enumerator_t, lease_enumerate, bool,
|
||||
lease_enumerator_t *this, identification_t **id, host_t **addr, bool *online)
|
||||
{
|
||||
u_int *offset;
|
||||
|
||||
DESTROY_IF(this->addr);
|
||||
this->addr = NULL;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (this->entry)
|
||||
{
|
||||
if (this->online->enumerate(this->online, &offset))
|
||||
{
|
||||
*id = this->entry->id;
|
||||
*addr = this->addr = offset2host(this->pool, *offset);
|
||||
*online = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
if (this->offline->enumerate(this->offline, &offset))
|
||||
{
|
||||
*id = this->entry->id;
|
||||
*addr = this->addr = offset2host(this->pool, *offset);
|
||||
*online = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
this->online->destroy(this->online);
|
||||
this->offline->destroy(this->offline);
|
||||
this->online = this->offline = NULL;
|
||||
}
|
||||
if (!this->entries->enumerate(this->entries, NULL, &this->entry))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->online = array_create_enumerator(this->entry->online);
|
||||
this->offline = array_create_enumerator(this->entry->offline);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(enumerator_t, lease_enumerator_destroy, void,
|
||||
lease_enumerator_t *this)
|
||||
{
|
||||
DESTROY_IF(this->addr);
|
||||
DESTROY_IF(this->online);
|
||||
DESTROY_IF(this->offline);
|
||||
this->entries->destroy(this->entries);
|
||||
this->pool->mutex->unlock(this->pool->mutex);
|
||||
free(this);
|
||||
}
|
||||
|
||||
METHOD(mem_pool_t, create_lease_enumerator, enumerator_t*,
|
||||
private_mem_pool_t *this)
|
||||
{
|
||||
lease_enumerator_t *enumerator;
|
||||
|
||||
this->mutex->lock(this->mutex);
|
||||
INIT(enumerator,
|
||||
.public = {
|
||||
.enumerate = (void*)_lease_enumerate,
|
||||
.destroy = _lease_enumerator_destroy,
|
||||
},
|
||||
.pool = this,
|
||||
.entries = this->leases->create_enumerator(this->leases),
|
||||
);
|
||||
return &enumerator->public;
|
||||
}
|
||||
|
||||
METHOD(mem_pool_t, destroy, void,
|
||||
private_mem_pool_t *this)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
entry_t *entry;
|
||||
|
||||
enumerator = this->leases->create_enumerator(this->leases);
|
||||
while (enumerator->enumerate(enumerator, NULL, &entry))
|
||||
{
|
||||
entry->id->destroy(entry->id);
|
||||
array_destroy(entry->online);
|
||||
array_destroy(entry->offline);
|
||||
free(entry);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->leases->destroy(this->leases);
|
||||
this->mutex->destroy(this->mutex);
|
||||
DESTROY_IF(this->base);
|
||||
free(this->name);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic constructor
|
||||
*/
|
||||
static private_mem_pool_t *create_generic(char *name)
|
||||
{
|
||||
private_mem_pool_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_name = _get_name,
|
||||
.get_base = _get_base,
|
||||
.get_size = _get_size,
|
||||
.get_online = _get_online,
|
||||
.get_offline = _get_offline,
|
||||
.acquire_address = _acquire_address,
|
||||
.release_address = _release_address,
|
||||
.create_lease_enumerator = _create_lease_enumerator,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.name = strdup(name),
|
||||
.leases = hashtable_create((hashtable_hash_t)id_hash,
|
||||
(hashtable_equals_t)id_equals, 16),
|
||||
.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
|
||||
.reassign_online = lib->settings->get_bool(lib->settings,
|
||||
"%s.mem-pool.reassign_online", FALSE, lib->ns),
|
||||
);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given host is the network ID of a subnet, that is, if hostbits
|
||||
* are zero. Since we limit pools to 2^31 addresses we only have to check the
|
||||
* last 4 bytes.
|
||||
*/
|
||||
static u_int network_id_diff(host_t *host, int hostbits)
|
||||
{
|
||||
u_int32_t last;
|
||||
chunk_t addr;
|
||||
|
||||
if (!hostbits)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
addr = host->get_address(host);
|
||||
last = untoh32(addr.ptr + addr.len - sizeof(last));
|
||||
hostbits = sizeof(last) * 8 - hostbits;
|
||||
return (last << hostbits) >> hostbits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header
|
||||
*/
|
||||
mem_pool_t *mem_pool_create(char *name, host_t *base, int bits)
|
||||
{
|
||||
private_mem_pool_t *this;
|
||||
u_int diff;
|
||||
int addr_bits;
|
||||
|
||||
this = create_generic(name);
|
||||
if (base)
|
||||
{
|
||||
addr_bits = base->get_family(base) == AF_INET ? 32 : 128;
|
||||
bits = max(0, min(bits, addr_bits));
|
||||
/* net bits -> host bits */
|
||||
bits = addr_bits - bits;
|
||||
if (bits > POOL_LIMIT)
|
||||
{
|
||||
bits = POOL_LIMIT;
|
||||
DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d",
|
||||
base, addr_bits - bits);
|
||||
}
|
||||
this->size = 1 << bits;
|
||||
this->base = base->clone(base);
|
||||
|
||||
if (this->size > 2)
|
||||
{
|
||||
/* if base is the network id we later skip the first address,
|
||||
* otherwise adjust the size to represent the actual number
|
||||
* of assignable addresses */
|
||||
diff = network_id_diff(base, bits);
|
||||
if (!diff)
|
||||
{
|
||||
this->base_is_network_id = TRUE;
|
||||
this->size--;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->size -= diff;
|
||||
}
|
||||
/* skip the last address (broadcast) of the subnet */
|
||||
this->size--;
|
||||
}
|
||||
else if (network_id_diff(base, bits))
|
||||
{ /* only serve the second address of the subnet */
|
||||
this->size--;
|
||||
}
|
||||
}
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header
|
||||
*/
|
||||
mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to)
|
||||
{
|
||||
private_mem_pool_t *this;
|
||||
chunk_t fromaddr, toaddr;
|
||||
u_int32_t diff;
|
||||
|
||||
fromaddr = from->get_address(from);
|
||||
toaddr = to->get_address(to);
|
||||
|
||||
if (from->get_family(from) != to->get_family(to) ||
|
||||
fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) ||
|
||||
memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0)
|
||||
{
|
||||
DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to);
|
||||
return NULL;
|
||||
}
|
||||
if (fromaddr.len > sizeof(diff) &&
|
||||
!chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)),
|
||||
chunk_create(toaddr.ptr, toaddr.len - sizeof(diff))))
|
||||
{
|
||||
DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to);
|
||||
return NULL;
|
||||
}
|
||||
this = create_generic(name);
|
||||
this->base = from->clone(from);
|
||||
diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) -
|
||||
untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff));
|
||||
this->size = diff + 1;
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
@@ -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_ @} */
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 = \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user