From dbc91f7c848b7ad1210bb270e7b3efa182e97ac6 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 22 Sep 2009 15:19:43 +0200 Subject: [PATCH] Added support for kernel segment manipulation --- src/charon/plugins/ha_sync/Makefile.am | 1 + src/charon/plugins/ha_sync/ha_sync_kernel.c | 96 +++++++++++++++++++ src/charon/plugins/ha_sync/ha_sync_kernel.h | 59 ++++++++++++ src/charon/plugins/ha_sync/ha_sync_plugin.c | 28 +++++- src/charon/plugins/ha_sync/ha_sync_segments.c | 44 ++------- src/charon/plugins/ha_sync/ha_sync_segments.h | 7 +- 6 files changed, 197 insertions(+), 38 deletions(-) create mode 100644 src/charon/plugins/ha_sync/ha_sync_kernel.c create mode 100644 src/charon/plugins/ha_sync/ha_sync_kernel.h diff --git a/src/charon/plugins/ha_sync/Makefile.am b/src/charon/plugins/ha_sync/Makefile.am index da634c96d1..6c537e10bb 100644 --- a/src/charon/plugins/ha_sync/Makefile.am +++ b/src/charon/plugins/ha_sync/Makefile.am @@ -11,6 +11,7 @@ libstrongswan_ha_sync_la_SOURCES = \ ha_sync_tunnel.h ha_sync_tunnel.c \ ha_sync_dispatcher.h ha_sync_dispatcher.c \ ha_sync_segments.h ha_sync_segments.c \ + ha_sync_kernel.h ha_sync_kernel.c \ ha_sync_ctl.h ha_sync_ctl.c \ ha_sync_ike.h ha_sync_ike.c \ ha_sync_child.h ha_sync_child.c diff --git a/src/charon/plugins/ha_sync/ha_sync_kernel.c b/src/charon/plugins/ha_sync/ha_sync_kernel.c new file mode 100644 index 0000000000..49d09e9552 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_kernel.c @@ -0,0 +1,96 @@ +/* + * 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 . + * + * 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 "ha_sync_kernel.h" + +typedef u_int32_t u32; +typedef u_int8_t u8; + +#include + +typedef struct private_ha_sync_kernel_t private_ha_sync_kernel_t; + +/** + * Private data of an ha_sync_kernel_t object. + */ +struct private_ha_sync_kernel_t { + + /** + * Public ha_sync_kernel_t interface. + */ + ha_sync_kernel_t public; + + /** + * Init value for jhash + */ + u_int initval; + + /** + * Total number of ClusterIP segments + */ + u_int segment_count; + + /** + * mask of active segments + */ + segment_mask_t active; +}; + +/** + * Implementation of ha_sync_kernel_t.in_segment + */ +static bool in_segment(private_ha_sync_kernel_t *this, host_t *host, u_int segment) +{ + if (host->get_family(host) == AF_INET) + { + unsigned long hash; + u_int32_t addr; + + addr = *(u_int32_t*)host->get_address(host).ptr; + hash = jhash_1word(ntohl(addr), this->initval); + + if ((((u_int64_t)hash * this->segment_count) >> 32) + 1 == segment) + { + return TRUE; + } + } + return FALSE; +} + +/** + * Implementation of ha_sync_kernel_t.destroy. + */ +static void destroy(private_ha_sync_kernel_t *this) +{ + free(this); +} + +/** + * See header + */ +ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active, + char *external, char *internal) +{ + private_ha_sync_kernel_t *this = malloc_thing(private_ha_sync_kernel_t); + + this->public.in_segment = (bool(*)(ha_sync_kernel_t*, host_t *host, u_int segment))in_segment; + this->public.destroy = (void(*)(ha_sync_kernel_t*))destroy; + + this->initval = 0; + this->segment_count = count; + + return &this->public; +} + diff --git a/src/charon/plugins/ha_sync/ha_sync_kernel.h b/src/charon/plugins/ha_sync/ha_sync_kernel.h new file mode 100644 index 0000000000..2ca8625932 --- /dev/null +++ b/src/charon/plugins/ha_sync/ha_sync_kernel.h @@ -0,0 +1,59 @@ +/* + * 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 . + * + * 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 ha_sync_kernel ha_sync_kernel + * @{ @ingroup ha_sync + */ + +#ifndef HA_SYNC_KERNEL_H_ +#define HA_SYNC_KERNEL_H_ + +typedef struct ha_sync_kernel_t ha_sync_kernel_t; + +#include "ha_sync_segments.h" + +/** + * HA sync segment kernel configuration interface. + */ +struct ha_sync_kernel_t { + + /** + * Check if a host is in a segment. + * + * @param host host to check + * @param segment segment + * @return TRUE if host belongs to segment + */ + bool (*in_segment)(ha_sync_kernel_t *this, host_t *host, u_int segment); + + /** + * Destroy a ha_sync_kernel_t. + */ + void (*destroy)(ha_sync_kernel_t *this); +}; + +/** + * Create a ha_sync_kernel instance. + * + * @param count total number of segments to use + * @param active bitmask of initially active segments + * @param external external virtual IP the cluster acts as + * @param internal internal virtual IP the cluster uses + */ +ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active, + char *external, char *internal); + +#endif /* HA_SYNC_KERNEL_ @}*/ diff --git a/src/charon/plugins/ha_sync/ha_sync_plugin.c b/src/charon/plugins/ha_sync/ha_sync_plugin.c index 2665b2f570..78cced51bb 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -67,6 +67,11 @@ struct private_ha_sync_plugin_t { */ ha_sync_segments_t *segments; + /** + * Interface to control segments at kernel level + */ + ha_sync_kernel_t *kernel; + /** * Segment control interface via FIFO */ @@ -85,6 +90,7 @@ static void destroy(private_ha_sync_plugin_t *this) this->child->destroy(this->child); this->dispatcher->destroy(this->dispatcher); this->segments->destroy(this->segments); + this->kernel->destroy(this->kernel); this->socket->destroy(this->socket); DESTROY_IF(this->tunnel); free(this); @@ -119,7 +125,7 @@ static segment_mask_t parse_active(char *active) plugin_t *plugin_create() { private_ha_sync_plugin_t *this; - char *local, *remote, *secret; + char *local, *remote, *secret, *external, *internal; segment_mask_t active; u_int count; bool fifo; @@ -128,6 +134,10 @@ plugin_t *plugin_create() "charon.plugins.ha_sync.local", NULL); remote = lib->settings->get_str(lib->settings, "charon.plugins.ha_sync.remote", NULL); + external = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.external", NULL); + internal = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.internal", NULL); secret = lib->settings->get_str(lib->settings, "charon.plugins.ha_sync.secret", NULL); fifo = lib->settings->get_bool(lib->settings, @@ -141,6 +151,11 @@ plugin_t *plugin_create() DBG1(DBG_CFG, "HA sync config misses local/remote address"); return NULL; } + if (!external || !internal) + { + DBG1(DBG_CFG, "HA sync config misses external/internal virtual address"); + return NULL; + } this = malloc_thing(private_ha_sync_plugin_t); @@ -154,7 +169,16 @@ plugin_t *plugin_create() free(this); return NULL; } - this->segments = ha_sync_segments_create(this->socket, count, active); + this->kernel = ha_sync_kernel_create(count, active, external, internal); + if (!this->kernel) + { + this->socket->destroy(this->socket); + free(this); + return NULL; + } + + this->segments = ha_sync_segments_create(this->socket, this->kernel, + count, active); if (secret) { this->tunnel = ha_sync_tunnel_create(secret, local, remote); diff --git a/src/charon/plugins/ha_sync/ha_sync_segments.c b/src/charon/plugins/ha_sync/ha_sync_segments.c index 81f6ace034..d3b2834784 100644 --- a/src/charon/plugins/ha_sync/ha_sync_segments.c +++ b/src/charon/plugins/ha_sync/ha_sync_segments.c @@ -18,11 +18,6 @@ #include #include -typedef u_int32_t u32; -typedef u_int8_t u8; - -#include - typedef struct private_ha_sync_segments_t private_ha_sync_segments_t; /** @@ -41,14 +36,14 @@ struct private_ha_sync_segments_t { ha_sync_socket_t *socket; /** - * read/write lock for segment manipulation + * Interface to control segments at kernel level */ - rwlock_t *lock; + ha_sync_kernel_t *kernel; /** - * Init value for jhash + * read/write lock for segment manipulation */ - u_int initval; + rwlock_t *lock; /** * Total number of ClusterIP segments @@ -61,28 +56,6 @@ struct private_ha_sync_segments_t { segment_mask_t active; }; -/** - * Check if a host address is in the CLUSTERIP segment - */ -static bool in_segment(private_ha_sync_segments_t *this, - host_t *host, u_int segment) -{ - if (host->get_family(host) == AF_INET) - { - unsigned long hash; - u_int32_t addr; - - addr = *(u_int32_t*)host->get_address(host).ptr; - hash = jhash_1word(ntohl(addr), this->initval); - - if ((((u_int64_t)hash * this->segment_count) >> 32) + 1 == segment) - { - return TRUE; - } - } - return FALSE; -} - /** * Log currently active segments */ @@ -152,7 +125,8 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment, { for (i = segment; i < limit; i++) { - if (in_segment(this, ike_sa->get_other_host(ike_sa), i)) + if (this->kernel->in_segment(this->kernel, + ike_sa->get_other_host(ike_sa), i)) { ike_sa->set_state(ike_sa, new); } @@ -254,7 +228,8 @@ static void resync(private_ha_sync_segments_t *this, u_int segment) while (enumerator->enumerate(enumerator, &ike_sa)) { if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED && - in_segment(this, ike_sa->get_other_host(ike_sa), segment)) + this->kernel->in_segment(this->kernel, + ike_sa->get_other_host(ike_sa), segment)) { id = ike_sa->get_id(ike_sa); list->insert_last(list, id->clone(id)); @@ -300,6 +275,7 @@ static void destroy(private_ha_sync_segments_t *this) * See header */ ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket, + ha_sync_kernel_t *kernel, u_int count, segment_mask_t active) { private_ha_sync_segments_t *this = malloc_thing(private_ha_sync_segments_t); @@ -310,8 +286,8 @@ ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket, this->public.destroy = (void(*)(ha_sync_segments_t*))destroy; this->socket = socket; + this->kernel = kernel; this->lock = rwlock_create(RWLOCK_TYPE_DEFAULT); - this->initval = 0; this->active = active; this->segment_count = count; diff --git a/src/charon/plugins/ha_sync/ha_sync_segments.h b/src/charon/plugins/ha_sync/ha_sync_segments.h index 396d2ef812..d1f2fc01ac 100644 --- a/src/charon/plugins/ha_sync/ha_sync_segments.h +++ b/src/charon/plugins/ha_sync/ha_sync_segments.h @@ -21,8 +21,6 @@ #ifndef HA_SYNC_SEGMENTS_H_ #define HA_SYNC_SEGMENTS_H_ -#include "ha_sync_socket.h" - #include typedef struct ha_sync_segments_t ha_sync_segments_t; @@ -39,6 +37,9 @@ typedef u_int16_t segment_mask_t; */ #define SEGMENTS_BIT(segment) (0x01 << (segment - 1)) +#include "ha_sync_socket.h" +#include "ha_sync_kernel.h" + /** * Segmentation of peers into active and passive. */ @@ -82,11 +83,13 @@ struct ha_sync_segments_t { * Create a ha_sync_segments instance. * * @param socket socket to communicate segment (de-)activation + * @param kernel interface to control segments at kernel level * @param count number of segments the cluster uses * @param active bit mask of initially active segments * @return segment object */ ha_sync_segments_t *ha_sync_segments_create(ha_sync_socket_t *socket, + ha_sync_kernel_t *kernel, u_int count, segment_mask_t active); #endif /* HA_SYNC_SEGMENTS_ @}*/ -- 2.47.3