diff options
author | Yves-Alexis Perez <corsac@debian.org> | 2013-01-02 14:18:20 +0100 |
---|---|---|
committer | Yves-Alexis Perez <corsac@debian.org> | 2013-01-02 14:18:20 +0100 |
commit | c1343b3278cdf99533b7902744d15969f9d6fdc1 (patch) | |
tree | d5ed3dc5677a59260ec41cd39bb284d3e94c91b3 /src/libhydra/attributes | |
parent | b34738ed08c2227300d554b139e2495ca5da97d6 (diff) | |
download | vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.tar.gz vyos-strongswan-c1343b3278cdf99533b7902744d15969f9d6fdc1.zip |
Imported Upstream version 5.0.1
Diffstat (limited to 'src/libhydra/attributes')
-rw-r--r-- | src/libhydra/attributes/attribute_handler.h | 6 | ||||
-rw-r--r-- | src/libhydra/attributes/attribute_manager.c | 75 | ||||
-rw-r--r-- | src/libhydra/attributes/attribute_manager.h | 23 | ||||
-rw-r--r-- | src/libhydra/attributes/attribute_provider.h | 17 | ||||
-rw-r--r-- | src/libhydra/attributes/mem_pool.c | 208 | ||||
-rw-r--r-- | src/libhydra/attributes/mem_pool.h | 28 |
6 files changed, 224 insertions, 133 deletions
diff --git a/src/libhydra/attributes/attribute_handler.h b/src/libhydra/attributes/attribute_handler.h index d042f47ef..6014ef0fa 100644 --- a/src/libhydra/attributes/attribute_handler.h +++ b/src/libhydra/attributes/attribute_handler.h @@ -22,8 +22,8 @@ #define ATTRIBUTE_HANDLER_H_ #include <chunk.h> -#include <utils/host.h> #include <utils/identification.h> +#include <utils/linked_list.h> #include "attributes.h" @@ -62,11 +62,11 @@ struct attribute_handler_t { * Enumerate attributes to request from a server. * * @param server server identity to request attributes from - * @param vip virtual IP we are requesting, if any + * @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, host_t *vip); + identification_t *server, linked_list_t *vips); }; #endif /** ATTRIBUTE_HANDLER_H_ @}*/ diff --git a/src/libhydra/attributes/attribute_manager.c b/src/libhydra/attributes/attribute_manager.c index 95520531e..000d2e082 100644 --- a/src/libhydra/attributes/attribute_manager.c +++ b/src/libhydra/attributes/attribute_manager.c @@ -51,17 +51,17 @@ struct private_attribute_manager_t { * Data to pass to enumerator filters */ typedef struct { - /** attribute group pool */ - char *pool; + /** attribute group pools */ + linked_list_t *pools; /** server/peer identity */ identification_t *id; - /** requesting/assigned virtual IP */ - host_t *vip; + /** requesting/assigned virtual IPs */ + linked_list_t *vips; } enum_data_t; METHOD(attribute_manager_t, acquire_address, host_t*, - private_attribute_manager_t *this, char *pool, identification_t *id, - host_t *requested) + private_attribute_manager_t *this, linked_list_t *pools, + identification_t *id, host_t *requested) { enumerator_t *enumerator; attribute_provider_t *current; @@ -71,7 +71,7 @@ METHOD(attribute_manager_t, acquire_address, host_t*, enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, ¤t)) { - host = current->acquire_address(current, pool, id, requested); + host = current->acquire_address(current, pools, id, requested); if (host) { break; @@ -80,15 +80,11 @@ METHOD(attribute_manager_t, acquire_address, host_t*, enumerator->destroy(enumerator); this->lock->unlock(this->lock); - if (!host) - { - DBG1(DBG_CFG, "acquiring address from pool '%s' failed", pool); - } return host; } -METHOD(attribute_manager_t, release_address, void, - private_attribute_manager_t *this, char *pool, host_t *address, +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; @@ -99,7 +95,7 @@ METHOD(attribute_manager_t, release_address, void, enumerator = this->providers->create_enumerator(this->providers); while (enumerator->enumerate(enumerator, ¤t)) { - if (current->release_address(current, pool, address, id)) + if (current->release_address(current, pools, address, id)) { found = TRUE; break; @@ -108,10 +104,7 @@ METHOD(attribute_manager_t, release_address, void, enumerator->destroy(enumerator); this->lock->unlock(this->lock); - if (!found) - { - DBG1(DBG_CFG, "releasing address to pool '%s' failed", pool); - } + return found; } /** @@ -120,19 +113,21 @@ METHOD(attribute_manager_t, release_address, void, static enumerator_t *responder_enum_create(attribute_provider_t *provider, enum_data_t *data) { - return provider->create_attribute_enumerator(provider, data->pool, - data->id, data->vip); + 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, char *pool, identification_t *id, - host_t *vip) + private_attribute_manager_t *this, linked_list_t *pools, + identification_t *id, linked_list_t *vips) { - enum_data_t *data = malloc_thing(enum_data_t); + enum_data_t *data; - data->pool = pool; - data->id = id; - data->vip = vip; + INIT(data, + .pools = pools, + .id = id, + .vips = vips, + ); this->lock->read_lock(this->lock); return enumerator_create_cleaner( enumerator_create_nested( @@ -238,8 +233,8 @@ typedef struct { enumerator_t *inner; /** server ID we want attributes for */ identification_t *id; - /** virtual IP we are requesting along with attriubutes */ - host_t *vip; + /** virtual IPs we are requesting along with attriubutes */ + linked_list_t *vips; } initiator_enumerator_t; /** @@ -259,7 +254,7 @@ static bool initiator_enumerate(initiator_enumerator_t *this, } DESTROY_IF(this->inner); this->inner = this->handler->create_attribute_enumerator(this->handler, - this->id, this->vip); + this->id, this->vips); } /* inject the handler as additional attribute */ *handler = this->handler; @@ -278,20 +273,22 @@ static void initiator_destroy(initiator_enumerator_t *this) } METHOD(attribute_manager_t, create_initiator_enumerator, enumerator_t*, - private_attribute_manager_t *this, identification_t *id, host_t *vip) + private_attribute_manager_t *this, identification_t *id, linked_list_t *vips) { - initiator_enumerator_t *enumerator = malloc_thing(initiator_enumerator_t); + initiator_enumerator_t *enumerator; this->lock->read_lock(this->lock); - enumerator->public.enumerate = (void*)initiator_enumerate; - enumerator->public.destroy = (void*)initiator_destroy; - enumerator->this = this; - enumerator->id = id; - enumerator->vip = vip; - enumerator->outer = this->handlers->create_enumerator(this->handlers); - enumerator->inner = NULL; - enumerator->handler = NULL; + 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; } diff --git a/src/libhydra/attributes/attribute_manager.h b/src/libhydra/attributes/attribute_manager.h index 56afef7c6..99f41772c 100644 --- a/src/libhydra/attributes/attribute_manager.h +++ b/src/libhydra/attributes/attribute_manager.h @@ -39,35 +39,38 @@ struct attribute_manager_t { /** * Acquire a virtual IP address to assign to a peer. * - * @param pool pool name to acquire address from + * @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, - char *pool, identification_t *id, + linked_list_t *pool, identification_t *id, host_t *requested); /** * Release a previously acquired address. * - * @param pool pool name from which the address was acquired + * @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 */ - void (*release_address)(attribute_manager_t *this, - char *pool, host_t *address, identification_t *id); + 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 pool name to get attributes from + * @param pool list of pools names (char*) to query attributes from * @param id peer identity to hand out attributes to - * @param vip virtual IP to assign to peer, if any + * @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, - char *pool, identification_t *id, host_t *vip); + linked_list_t *pool, identification_t *id, + linked_list_t *vips); /** * Register an attribute provider to the manager. @@ -114,11 +117,11 @@ struct attribute_manager_t { * Create an enumerator over attributes to request from server. * * @param id server identity to hand out attributes to - * @param vip virtual IP going to request, if any + * @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, host_t *vip); + identification_t *id, linked_list_t *vips); /** * Register an attribute handler to the manager. diff --git a/src/libhydra/attributes/attribute_provider.h b/src/libhydra/attributes/attribute_provider.h index e4b4e13f3..e5e556fc4 100644 --- a/src/libhydra/attributes/attribute_provider.h +++ b/src/libhydra/attributes/attribute_provider.h @@ -23,6 +23,7 @@ #include <utils/host.h> #include <utils/identification.h> +#include <utils/linked_list.h> typedef struct attribute_provider_t attribute_provider_t; @@ -34,35 +35,37 @@ struct attribute_provider_t { /** * Acquire a virtual IP address to assign to a peer. * - * @param pool name of the pool to acquire address from + * @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, - char *pool, identification_t *id, + linked_list_t *pools, identification_t *id, host_t *requested); /** * Release a previously acquired address. * - * @param pool name of the pool this address was acquired from + * @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, - char *pool, host_t *address, identification_t *id); + linked_list_t *pools, host_t *address, + identification_t *id); /** * Create an enumerator over attributes to hand out to a peer. * - * @param pool pool name to get attributes from + * @param pool list of pools names (char*) to query attributes from * @param id peer ID - * @param vip virtual IP to assign to peer, if any + * @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, - char *pool, identification_t *id, host_t *vip); + linked_list_t *pools, identification_t *id, + linked_list_t *vips); }; #endif /** ATTRIBUTE_PROVIDER_H_ @}*/ diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c index 8af97dc78..1e150c794 100644 --- a/src/libhydra/attributes/mem_pool.c +++ b/src/libhydra/attributes/mem_pool.c @@ -162,6 +162,12 @@ METHOD(mem_pool_t, get_name, const char*, 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) { @@ -206,66 +212,68 @@ METHOD(mem_pool_t, get_offline, u_int, return count; } -METHOD(mem_pool_t, acquire_address, host_t*, - private_mem_pool_t *this, identification_t *id, host_t *requested) +/** + * Get an existing lease for id + */ +static int get_existing(private_mem_pool_t *this, identification_t *id, + host_t *requested) { - uintptr_t offset = 0, current; enumerator_t *enumerator; - entry_t *entry, *old; + uintptr_t current; + entry_t *entry; + int offset = 0; - /* if the pool is empty (e.g. in the %config case) we simply return the - * requested address */ - if (this->size == 0) + entry = this->leases->get(this->leases, id); + if (!entry) { - return requested->clone(requested); + return 0; } - if (!requested->is_anyaddr(requested) && - requested->get_family(requested) != - this->base->get_family(this->base)) + /* check for a valid offline lease, refresh */ + enumerator = entry->offline->create_enumerator(entry->offline); + if (enumerator->enumerate(enumerator, ¤t)) { - DBG1(DBG_CFG, "IP pool address family mismatch"); - return NULL; + entry->offline->remove_at(entry->offline, enumerator); + entry->online->insert_last(entry->online, (void*)current); + offset = current; + } + enumerator->destroy(enumerator); + if (offset) + { + DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id); + return offset; } - this->mutex->lock(this->mutex); - while (TRUE) + /* check for a valid online lease to reassign */ + enumerator = entry->online->create_enumerator(entry->online); + while (enumerator->enumerate(enumerator, ¤t)) { - entry = this->leases->get(this->leases, id); - if (entry) + if (current == host2offset(this, requested)) { - /* check for a valid offline lease, refresh */ - enumerator = entry->offline->create_enumerator(entry->offline); - if (enumerator->enumerate(enumerator, ¤t)) - { - entry->offline->remove_at(entry->offline, enumerator); - entry->online->insert_last(entry->online, (void*)current); - offset = current; - } - enumerator->destroy(enumerator); - if (offset) - { - DBG1(DBG_CFG, "reassigning offline lease to '%Y'", id); - break; - } - /* check for a valid online lease to reassign */ - enumerator = entry->online->create_enumerator(entry->online); - while (enumerator->enumerate(enumerator, ¤t)) - { - if (current == host2offset(this, requested)) - { - offset = current; - break; - } - } - enumerator->destroy(enumerator); - if (offset) - { - DBG1(DBG_CFG, "reassigning online lease to '%Y'", id); - break; - } + offset = current; + break; } - else + } + 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; + uintptr_t offset = 0; + + if (this->unused < this->size) + { + entry = this->leases->get(this->leases, id); + if (!entry) { INIT(entry, .id = id->clone(id), @@ -274,31 +282,88 @@ METHOD(mem_pool_t, acquire_address, host_t*, ); this->leases->put(this->leases, entry->id, entry); } - if (this->unused < this->size) + /* assigning offset, starting by 1 */ + offset = ++this->unused; + entry->online->insert_last(entry->online, (void*)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; + uintptr_t current, offset = 0; + + enumerator = this->leases->create_enumerator(this->leases); + while (enumerator->enumerate(enumerator, NULL, &entry)) + { + if (entry->offline->remove_first(entry->offline, + (void**)¤t) == SUCCESS) { - /* assigning offset, starting by 1 */ - offset = ++this->unused; - entry->online->insert_last(entry->online, (void*)offset); - DBG1(DBG_CFG, "assigning new lease to '%Y'", id); + offset = current; + DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'" + " to '%Y'", entry->id, id); break; } + } + enumerator->destroy(enumerator); - /* no more addresses, replace the first found offline lease */ - enumerator = this->leases->create_enumerator(this->leases); - while (enumerator->enumerate(enumerator, NULL, &old)) - { - if (old->offline->remove_first(old->offline, - (void**)¤t) == SUCCESS) + if (offset) + { + INIT(entry, + .id = id->clone(id), + .online = linked_list_create(), + .offline = linked_list_create(), + ); + entry->online->insert_last(entry->online, (void*)offset); + this->leases->put(this->leases, entry->id, entry); + } + 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) { - offset = current; - entry->online->insert_last(entry->online, (void*)offset); - DBG1(DBG_CFG, "reassigning existing offline lease by '%Y'" - " to '%Y'", old->id, id); - break; + DBG1(DBG_CFG, "pool '%s' is full, unable to assign address", + this->name); } - } - enumerator->destroy(enumerator); - break; + break; + default: + break; } this->mutex->unlock(this->mutex); @@ -306,11 +371,6 @@ METHOD(mem_pool_t, acquire_address, host_t*, { return offset2host(this, offset); } - else - { - DBG1(DBG_CFG, "pool '%s' is full, unable to assign address", - this->name); - } return NULL; } @@ -463,6 +523,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) INIT(this, .public = { .get_name = _get_name, + .get_base = _get_base, .get_size = _get_size, .get_online = _get_online, .get_offline = _get_offline, @@ -480,6 +541,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) if (base) { addr_bits = base->get_family(base) == AF_INET ? 32 : 128; + bits = max(0, min(bits, base->get_family(base) == AF_INET ? 32 : 128)); /* net bits -> host bits */ bits = addr_bits - bits; if (bits > POOL_LIMIT) @@ -493,7 +555,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) if (this->size > 2) { /* do not use first and last addresses of a block */ this->unused++; - this->size--; + this->size -= 2; } this->base = base->clone(base); } diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h index bb963de93..fa4e6485c 100644 --- a/src/libhydra/attributes/mem_pool.h +++ b/src/libhydra/attributes/mem_pool.h @@ -22,11 +22,24 @@ #define MEM_POOL_H typedef struct mem_pool_t mem_pool_t; +typedef enum mem_pool_op_t mem_pool_op_t; #include <utils/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 { @@ -39,6 +52,13 @@ struct mem_pool_t { 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 @@ -62,12 +82,18 @@ struct mem_pool_t { /** * 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 existing TRUE to look for an existing lease, FALSE for a new one * @return the acquired address */ host_t* (*acquire_address)(mem_pool_t *this, identification_t *id, - host_t *requested); + host_t *requested, mem_pool_op_t operation); /** * Release a previously acquired address. |