aboutsummaryrefslogtreecommitdiffstats
path: root/src/charon
diff options
context:
space:
mode:
authorMartin Willi <martin@strongswan.org>2009-09-22 16:51:47 +0200
committerMartin Willi <martin@revosec.ch>2010-04-07 13:55:14 +0200
commit4e248733a8261bb0798dc634f9d689cf6af1777d (patch)
treef0c48fffd23116f300855e98e8e7704b83ffa159 /src/charon
parentdbc91f7c848b7ad1210bb270e7b3efa182e97ac6 (diff)
downloadstrongswan-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.c154
-rw-r--r--src/charon/plugins/ha_sync/ha_sync_kernel.h19
-rw-r--r--src/charon/plugins/ha_sync/ha_sync_plugin.c15
-rw-r--r--src/charon/plugins/ha_sync/ha_sync_segments.c24
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);
}