diff options
author | Martin Willi <martin@strongswan.org> | 2009-09-22 16:51:47 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2010-04-07 13:55:14 +0200 |
commit | 4e248733a8261bb0798dc634f9d689cf6af1777d (patch) | |
tree | f0c48fffd23116f300855e98e8e7704b83ffa159 /src/charon | |
parent | dbc91f7c848b7ad1210bb270e7b3efa182e97ac6 (diff) | |
download | strongswan-4e248733a8261bb0798dc634f9d689cf6af1777d.tar.bz2 strongswan-4e248733a8261bb0798dc634f9d689cf6af1777d.tar.xz |
HA kernel interface can mangle netfilter rules, currently with iptables invocation
Diffstat (limited to 'src/charon')
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_kernel.c | 154 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_kernel.h | 19 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_plugin.c | 15 | ||||
-rw-r--r-- | src/charon/plugins/ha_sync/ha_sync_segments.c | 24 |
4 files changed, 183 insertions, 29 deletions
diff --git a/src/charon/plugins/ha_sync/ha_sync_kernel.c b/src/charon/plugins/ha_sync/ha_sync_kernel.c index 49d09e955..caba2b0be 100644 --- a/src/charon/plugins/ha_sync/ha_sync_kernel.c +++ b/src/charon/plugins/ha_sync/ha_sync_kernel.c @@ -19,6 +19,12 @@ typedef u_int32_t u32; typedef u_int8_t u8; #include <linux/jhash.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> typedef struct private_ha_sync_kernel_t private_ha_sync_kernel_t; @@ -43,15 +49,16 @@ struct private_ha_sync_kernel_t { u_int segment_count; /** - * mask of active segments + * List of virtual addresses, as host_t* */ - segment_mask_t active; + linked_list_t *virtuals; }; /** * Implementation of ha_sync_kernel_t.in_segment */ -static bool in_segment(private_ha_sync_kernel_t *this, host_t *host, u_int segment) +static bool in_segment(private_ha_sync_kernel_t *this, + host_t *host, u_int segment) { if (host->get_family(host) == AF_INET) { @@ -68,12 +75,140 @@ static bool in_segment(private_ha_sync_kernel_t *this, host_t *host, u_int segme } return FALSE; } +/** + * Activate/Deactivate a segment + */ +static void activate_deactivate(private_ha_sync_kernel_t *this, + u_int segment, char op) +{ + enumerator_t *enumerator; + host_t *host; + char cmd[8], file[256]; + int fd; + + enumerator = this->virtuals->create_enumerator(this->virtuals); + while (enumerator->enumerate(enumerator, &host)) + { + snprintf(file, sizeof(file), "/proc/net/ipt_CLUSTERIP/%H", host); + snprintf(cmd, sizeof(cmd), "%c%d\n", op, segment); + + fd = open(file, O_WRONLY); + if (fd == -1) + { + DBG1(DBG_CFG, "opening CLUSTERIP file '%s' failed: %s", + file, strerror(errno)); + continue; + } + if (write(fd, cmd, strlen(cmd) == -1)) + { + DBG1(DBG_CFG, "writing to CLUSTERIP file '%s' failed: %s", + file, strerror(errno)); + } + close(fd); + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of ha_sync_kernel_t.activate + */ +static void activate(private_ha_sync_kernel_t *this, u_int segment) +{ + activate_deactivate(this, segment, '+'); +} + +/** + * Implementation of ha_sync_kernel_t.deactivate + */ +static void deactivate(private_ha_sync_kernel_t *this, u_int segment) +{ + activate_deactivate(this, segment, '-'); +} + +/** + * Mangle IPtable rules for virtual addresses + */ +static bool mangle_rules(private_ha_sync_kernel_t *this, bool add, + segment_mask_t active) +{ + enumerator_t *enumerator; + host_t *host; + u_char i, mac = 0x20; + char *iface, buf[256]; + + enumerator = this->virtuals->create_enumerator(this->virtuals); + while (enumerator->enumerate(enumerator, &host)) + { + iface = charon->kernel_interface->get_interface( + charon->kernel_interface, host); + if (!iface) + { + DBG1(DBG_CFG, "cluster address %H not installed, ignored", host); + this->virtuals->remove_at(this->virtuals, enumerator); + host->destroy(host); + continue; + } + /* iptables insists of a local node specification. We add '1' but drop + * it afterwards. */ + snprintf(buf, sizeof(buf), + "/sbin/iptables -%c INPUT -i %s -d %H -j CLUSTERIP --new " + "--hashmode sourceip --clustermac 01:00:5e:00:00:%2x " + "--total-nodes %d --local-node 1", + add ? 'A' : 'D', iface, host, mac++, this->segment_count); + free(iface); + if (system(buf) != 0) + { + DBG1(DBG_CFG, "installing CLUSTERIP rule '%s' failed", buf); + } + } + enumerator->destroy(enumerator); + + if (add) + { + deactivate(this, 1); + for (i = 0; i < SEGMENTS_MAX; i++) + { + if (active & SEGMENTS_BIT(i)) + { + activate(this, i); + } + } + } + return TRUE; +} + +/** + * Parse the list of virtual cluster addresses + */ +static void parse_virtuals(private_ha_sync_kernel_t *this, char *virtual) +{ + enumerator_t *enumerator; + host_t *host; + + enumerator = enumerator_create_token(virtual, ",", " "); + while (enumerator->enumerate(enumerator, &virtual)) + { + host = host_create_from_string(virtual, 0); + if (host) + { + this->virtuals->insert_last(this->virtuals, host); + } + else + { + DBG1(DBG_CFG, "virtual cluster address '%s' invalid, ignored", + virtual); + } + } + enumerator->destroy(enumerator); +} /** * Implementation of ha_sync_kernel_t.destroy. */ static void destroy(private_ha_sync_kernel_t *this) { + mangle_rules(this, FALSE, 0); + this->virtuals->destroy_offset(this->virtuals, offsetof(host_t, destroy)); free(this); } @@ -81,15 +216,26 @@ static void destroy(private_ha_sync_kernel_t *this) * See header */ ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active, - char *external, char *internal) + char *virtuals) { 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.activate = (void(*)(ha_sync_kernel_t*, u_int segment))activate; + this->public.deactivate = (void(*)(ha_sync_kernel_t*, u_int segment))deactivate; this->public.destroy = (void(*)(ha_sync_kernel_t*))destroy; this->initval = 0; this->segment_count = count; + this->virtuals = linked_list_create(); + + parse_virtuals(this, virtuals); + + if (!mangle_rules(this, TRUE, active)) + { + destroy(this); + return NULL; + } 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 index 2ca862593..87ee02aec 100644 --- a/src/charon/plugins/ha_sync/ha_sync_kernel.h +++ b/src/charon/plugins/ha_sync/ha_sync_kernel.h @@ -40,6 +40,20 @@ struct ha_sync_kernel_t { bool (*in_segment)(ha_sync_kernel_t *this, host_t *host, u_int segment); /** + * Activate a segment at kernel level for all cluster addresses. + * + * @param segment segment to activate + */ + void (*activate)(ha_sync_kernel_t *this, u_int segment); + + /** + * Deactivate a segment at kernel level for all cluster addresses. + * + * @param segment segment to deactivate + */ + void (*deactivate)(ha_sync_kernel_t *this, u_int segment); + + /** * Destroy a ha_sync_kernel_t. */ void (*destroy)(ha_sync_kernel_t *this); @@ -50,10 +64,9 @@ struct ha_sync_kernel_t { * * @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 + * @param virtuals comma separated list of virtual cluster addresses */ ha_sync_kernel_t *ha_sync_kernel_create(u_int count, segment_mask_t active, - char *external, char *internal); + char *virtuals); #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 78cced51b..4fed2e302 100644 --- a/src/charon/plugins/ha_sync/ha_sync_plugin.c +++ b/src/charon/plugins/ha_sync/ha_sync_plugin.c @@ -125,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, *external, *internal; + char *local, *remote, *secret, *virtuals; segment_mask_t active; u_int count; bool fifo; @@ -134,10 +134,8 @@ 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); + virtuals = lib->settings->get_str(lib->settings, + "charon.plugins.ha_sync.virtuals", ""); secret = lib->settings->get_str(lib->settings, "charon.plugins.ha_sync.secret", NULL); fifo = lib->settings->get_bool(lib->settings, @@ -151,11 +149,6 @@ 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); @@ -169,7 +162,7 @@ plugin_t *plugin_create() free(this); return NULL; } - this->kernel = ha_sync_kernel_create(count, active, external, internal); + this->kernel = ha_sync_kernel_create(count, active, virtuals); if (!this->kernel) { this->socket->destroy(this->socket); diff --git a/src/charon/plugins/ha_sync/ha_sync_segments.c b/src/charon/plugins/ha_sync/ha_sync_segments.c index d3b283478..f26490447 100644 --- a/src/charon/plugins/ha_sync/ha_sync_segments.c +++ b/src/charon/plugins/ha_sync/ha_sync_segments.c @@ -107,17 +107,6 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment, { /* or segment_count times for all segments */ limit = this->segment_count; } - for (i = segment; i < limit; i++) - { - if (enable) - { - this->active |= SEGMENTS_BIT(i); - } - else - { - this->active &= ~SEGMENTS_BIT(i); - } - } enumerator = charon->ike_sa_manager->create_enumerator(charon->ike_sa_manager); while (enumerator->enumerate(enumerator, &ike_sa)) { @@ -134,6 +123,19 @@ static void enable_disable(private_ha_sync_segments_t *this, u_int segment, } } enumerator->destroy(enumerator); + for (i = segment; i < limit; i++) + { + if (enable) + { + this->active |= SEGMENTS_BIT(i); + this->kernel->activate(this->kernel, i); + } + else + { + this->active &= ~SEGMENTS_BIT(i); + this->kernel->deactivate(this->kernel, i); + } + } log_segments(this, enable, segment); } |