diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/charon/plugins/stroke/Makefile.am | 1 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_attribute.c | 318 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_attribute.h | 67 | ||||
-rw-r--r-- | src/charon/plugins/stroke/stroke_socket.c | 12 |
4 files changed, 398 insertions, 0 deletions
diff --git a/src/charon/plugins/stroke/Makefile.am b/src/charon/plugins/stroke/Makefile.am index c7312501b..36e540665 100644 --- a/src/charon/plugins/stroke/Makefile.am +++ b/src/charon/plugins/stroke/Makefile.am @@ -11,6 +11,7 @@ libcharon_stroke_la_SOURCES = stroke_plugin.h stroke_plugin.c \ stroke_control.h stroke_control.c \ stroke_cred.h stroke_cred.c \ stroke_ca.h stroke_ca.c \ + stroke_attribute.h stroke_attribute.c \ stroke_list.h stroke_list.c \ stroke_shared_key.h stroke_shared_key.c diff --git a/src/charon/plugins/stroke/stroke_attribute.c b/src/charon/plugins/stroke/stroke_attribute.c new file mode 100644 index 000000000..9fdd68a50 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_attribute.c @@ -0,0 +1,318 @@ +/* + * 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. + * + * $Id$ + */ + +#include "stroke_attribute.h" + +#include <daemon.h> +#include <utils/linked_list.h> +#include <utils/mutex.h> + +#define POOL_LIMIT 16 + +typedef struct private_stroke_attribute_t private_stroke_attribute_t; + +/** + * private data of stroke_attribute + */ +struct private_stroke_attribute_t { + + /** + * public functions + */ + stroke_attribute_t public; + + /** + * list of pools, contains pool_t + */ + linked_list_t *pools; + + /** + * mutex to lock access to pools + */ + mutex_t *mutex; +}; + +typedef struct { + /** name of the pool */ + char *name; + /** base address of the pool */ + host_t *base; + /** number of entries in the pool */ + int count; + /** array of in-use flags, TODO: use bit fields */ + u_int8_t *in_use; +} pool_t; + +/** + * destroy a pool_t + */ +static void pool_destroy(pool_t *this) +{ + this->base->destroy(this->base); + free(this->name); + free(this->in_use); + free(this); +} + +/** + * find a pool by name + */ +static pool_t *find_pool(private_stroke_attribute_t *this, char *name) +{ + enumerator_t *enumerator; + pool_t *current, *found = NULL; + + enumerator = this->pools->create_enumerator(this->pools); + while (enumerator->enumerate(enumerator, ¤t)) + { + if (streq(name, current->name)) + { + found = current; + break; + } + } + enumerator->destroy(enumerator); + return found; +} + +/** + * convert an pool offset to an address + */ +host_t* offset2host(pool_t *pool, int offset) +{ + chunk_t addr; + host_t *host; + u_int32_t *pos; + + if (offset > pool->count) + { + 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 + */ +int host2offset(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->count) + { + return -1; + } + return hosti - basei; +} + +/** + * Implementation of attribute_provider_t.acquire_address + */ +static host_t* acquire_address(private_stroke_attribute_t *this, + char *name, identification_t *id, + auth_info_t *auth, host_t *requested) +{ + pool_t *pool; + host_t *host = NULL; + int i; + + this->mutex->lock(this->mutex); + pool = find_pool(this, name); + if (pool) + { + if (requested && !requested->is_anyaddr(requested)) + { + i = host2offset(pool, requested); + if (i >= 0 && !pool->in_use[i]) + { + pool->in_use[i] = TRUE; + host = requested->clone(requested); + } + } + if (!host) + { + for (i = 0; i < pool->count; i++) + { + if (!pool->in_use[i]) + { + pool->in_use[i] = TRUE; + host = offset2host(pool, i); + break; + } + } + } + } + this->mutex->unlock(this->mutex); + return host; +} + +/** + * Implementation of attribute_provider_t.release_address + */ +static bool release_address(private_stroke_attribute_t *this, + char *name, host_t *address) +{ + pool_t *pool; + bool found = FALSE; + int i; + + this->mutex->lock(this->mutex); + pool = find_pool(this, name); + if (pool) + { + i = host2offset(pool, address); + if (i >= 0 && pool->in_use[i]) + { + pool->in_use[i] = FALSE; + found =TRUE; + } + } + this->mutex->unlock(this->mutex); + return found; +} + +/** + * Implementation of stroke_attribute_t.add_pool. + */ +static void add_pool(private_stroke_attribute_t *this, stroke_msg_t *msg) +{ + if (msg->add_conn.other.sourceip && msg->add_conn.other.sourceip_size) + { + pool_t *pool; + u_int32_t bits; + int family; + + DBG1(DBG_CFG, "adding virtual IP address pool '%s': %s/%d", + msg->add_conn.name, msg->add_conn.other.sourceip, + msg->add_conn.other.sourceip_size); + + pool = malloc_thing(pool_t); + pool->base = host_create_from_string(msg->add_conn.other.sourceip, 0); + if (!pool->base) + { + free(pool); + DBG1(DBG_CFG, "virtual IP address invalid, discarded"); + return; + } + pool->name = strdup(msg->add_conn.name); + family = pool->base->get_family(pool->base); + bits = (family == AF_INET ? 32 : 128) - msg->add_conn.other.sourceip_size; + if (bits > POOL_LIMIT) + { + bits = POOL_LIMIT; + DBG1(DBG_CFG, "virtual IP pool to large, limiting to %s/%d", + msg->add_conn.other.sourceip, + (family == AF_INET ? 32 : 128) - bits); + } + pool->count = 1 << (bits); + pool->in_use = calloc(pool->count, sizeof(u_int8_t)); + + if (pool->count > 2) + { /* do not use first and last addresses of a block */ + pool->in_use[0] = TRUE; + pool->in_use[pool->count-1] = TRUE; + } + this->mutex->lock(this->mutex); + this->pools->insert_last(this->pools, pool); + this->mutex->unlock(this->mutex); + } +} + +/** + * Implementation of stroke_attribute_t.del_pool. + */ +static void del_pool(private_stroke_attribute_t *this, stroke_msg_t *msg) +{ + enumerator_t *enumerator; + pool_t *pool; + + this->mutex->lock(this->mutex); + enumerator = this->pools->create_enumerator(this->pools); + while (enumerator->enumerate(enumerator, &pool)) + { + if (streq(msg->del_conn.name, pool->name)) + { + this->pools->remove_at(this->pools, enumerator); + pool_destroy(pool); + break; + } + } + enumerator->destroy(enumerator); + this->mutex->unlock(this->mutex); +} + +/** + * Implementation of stroke_attribute_t.destroy + */ +static void destroy(private_stroke_attribute_t *this) +{ + this->mutex->destroy(this->mutex); + this->pools->destroy_function(this->pools, (void*)pool_destroy); + free(this); +} + +/* + * see header file + */ +stroke_attribute_t *stroke_attribute_create() +{ + private_stroke_attribute_t *this = malloc_thing(private_stroke_attribute_t); + + this->public.provider.acquire_address = (host_t*(*)(attribute_provider_t *this, char*, identification_t *,auth_info_t *, host_t *))acquire_address; + this->public.provider.release_address = (bool(*)(attribute_provider_t *this, char*,host_t *))release_address; + this->public.add_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))add_pool; + this->public.del_pool = (void(*)(stroke_attribute_t*, stroke_msg_t *msg))del_pool; + this->public.destroy = (void(*)(stroke_attribute_t*))destroy; + + this->pools = linked_list_create(); + this->mutex = mutex_create(MUTEX_DEFAULT); + + return &this->public; +} + diff --git a/src/charon/plugins/stroke/stroke_attribute.h b/src/charon/plugins/stroke/stroke_attribute.h new file mode 100644 index 000000000..f871d5a13 --- /dev/null +++ b/src/charon/plugins/stroke/stroke_attribute.h @@ -0,0 +1,67 @@ +/* + * 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. + * + * $Id$ + */ + +/** + * @defgroup stroke_attribute stroke_attribute + * @{ @ingroup stroke + */ + +#ifndef STROKE_ATTRIBUTE_H_ +#define STROKE_ATTRIBUTE_H_ + +#include <stroke_msg.h> +#include <config/attributes/attribute_provider.h> + +typedef struct stroke_attribute_t stroke_attribute_t; + +/** + * Stroke IKEv2 cfg attribute provider + */ +struct stroke_attribute_t { + + /** + * Implements attribute provider interface + */ + attribute_provider_t provider; + + /** + * Add a virtual IP address. + * + * @param msg stroke message + * @param end end of stroke message that contains virtual IP. + */ + void (*add_pool)(stroke_attribute_t *this, stroke_msg_t *msg); + + /** + * Remove a virtual IP address. + * + * @param msg stroke message + */ + void (*del_pool)(stroke_attribute_t *this, stroke_msg_t *msg); + + /** + * Destroy a stroke_attribute instance. + */ + void (*destroy)(stroke_attribute_t *this); +}; + +/** + * Create a stroke_attribute instance. + */ +stroke_attribute_t *stroke_attribute_create(); + +#endif /* STROKE_ATTRIBUTE_H_ @}*/ diff --git a/src/charon/plugins/stroke/stroke_socket.c b/src/charon/plugins/stroke/stroke_socket.c index 8ce757acb..9ee5a2410 100644 --- a/src/charon/plugins/stroke/stroke_socket.c +++ b/src/charon/plugins/stroke/stroke_socket.c @@ -33,6 +33,7 @@ #include "stroke_control.h" #include "stroke_cred.h" #include "stroke_ca.h" +#include "stroke_attribute.h" #include "stroke_list.h" typedef struct stroke_job_context_t stroke_job_context_t; @@ -64,6 +65,11 @@ struct private_stroke_socket_t { stroke_config_t *config; /** + * attribute provider + */ + stroke_attribute_t *attribute; + + /** * controller to control daemon */ stroke_control_t *control; @@ -173,6 +179,7 @@ static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg) DBG2(DBG_CFG, " me_peerid=%s", msg->add_conn.ikeme.peerid); this->config->add(this->config, msg); + this->attribute->add_pool(this->attribute, msg); } /** @@ -184,6 +191,7 @@ static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg) DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name); this->config->del(this->config, msg); + this->attribute->del_pool(this->attribute, msg); } /** @@ -542,9 +550,11 @@ static void destroy(private_stroke_socket_t *this) charon->credentials->remove_set(charon->credentials, &this->ca->set); charon->credentials->remove_set(charon->credentials, &this->cred->set); charon->backends->remove_backend(charon->backends, &this->config->backend); + charon->attributes->remove_provider(charon->attributes, &this->attribute->provider); this->cred->destroy(this->cred); this->ca->destroy(this->ca); this->config->destroy(this->config); + this->attribute->destroy(this->attribute); this->control->destroy(this->control); this->list->destroy(this->list); free(this); @@ -566,6 +576,7 @@ stroke_socket_t *stroke_socket_create() } this->cred = stroke_cred_create(); + this->attribute = stroke_attribute_create(); this->ca = stroke_ca_create(this->cred); this->config = stroke_config_create(this->cred); this->control = stroke_control_create(); @@ -574,6 +585,7 @@ stroke_socket_t *stroke_socket_create() charon->credentials->add_set(charon->credentials, &this->ca->set); charon->credentials->add_set(charon->credentials, &this->cred->set); charon->backends->add_backend(charon->backends, &this->config->backend); + charon->attributes->add_provider(charon->attributes, &this->attribute->provider); this->job = callback_job_create((callback_job_cb_t)receive, this, NULL, NULL); |