]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Added support for kernel segment manipulation
authorMartin Willi <martin@strongswan.org>
Tue, 22 Sep 2009 13:19:43 +0000 (15:19 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:14 +0000 (13:55 +0200)
src/charon/plugins/ha_sync/Makefile.am
src/charon/plugins/ha_sync/ha_sync_kernel.c [new file with mode: 0644]
src/charon/plugins/ha_sync/ha_sync_kernel.h [new file with mode: 0644]
src/charon/plugins/ha_sync/ha_sync_plugin.c
src/charon/plugins/ha_sync/ha_sync_segments.c
src/charon/plugins/ha_sync/ha_sync_segments.h

index da634c96d199cdbc73afd7dc24a2715f9502cb1f..6c537e10bb2e06bfd7c420a69c8dadf189a5e6a1 100644 (file)
@@ -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 (file)
index 0000000..49d09e9
--- /dev/null
@@ -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 <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.
+ */
+
+#include "ha_sync_kernel.h"
+
+typedef u_int32_t u32;
+typedef u_int8_t u8;
+
+#include <linux/jhash.h>
+
+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 (file)
index 0000000..2ca8625
--- /dev/null
@@ -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 <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.
+ */
+
+/**
+ * @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_ @}*/
index 2665b2f57067d840550469ff76770e30824c6f26..78cced51bb11f11abf9b740cba2ccd6bf3a4aa1f 100644 (file)
@@ -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);
index 81f6ace034597b86f40363e9a12fb466d54f4c15..d3b2834784ada39dfb68a6c63c76743fe6698b5b 100644 (file)
 #include <utils/mutex.h>
 #include <utils/linked_list.h>
 
-typedef u_int32_t u32;
-typedef u_int8_t u8;
-
-#include <linux/jhash.h>
-
 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;
 
index 396d2ef81239d6ff25afad23da36af7bdba6cd45..d1f2fc01ac33c2ba51e60fea13247685b85b8a6f 100644 (file)
@@ -21,8 +21,6 @@
 #ifndef HA_SYNC_SEGMENTS_H_
 #define HA_SYNC_SEGMENTS_H_
 
-#include "ha_sync_socket.h"
-
 #include <daemon.h>
 
 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_ @}*/