Do not install iptables rules, they should stay active after shutdown
authorMartin Willi <martin@strongswan.org>
Tue, 29 Sep 2009 14:05:46 +0000 (16:05 +0200)
committerMartin Willi <martin@revosec.ch>
Wed, 7 Apr 2010 11:55:16 +0000 (13:55 +0200)
src/charon/plugins/ha/ha_kernel.c
src/charon/plugins/ha/ha_kernel.h
src/charon/plugins/ha/ha_plugin.c

index f04b417..69e1c9e 100644 (file)
@@ -26,6 +26,8 @@ typedef u_int8_t u8;
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#define CLUSTERIP_DIR "/proc/net/ipt_CLUSTERIP"
+
 typedef struct private_ha_kernel_t private_ha_kernel_t;
 
 /**
@@ -47,11 +49,6 @@ struct private_ha_kernel_t {
         * Total number of ClusterIP segments
         */
        u_int count;
-
-       /**
-        * List of virtual addresses, as host_t*
-        */
-       linked_list_t *virtuals;
 };
 
 /**
@@ -74,38 +71,75 @@ static bool in_segment(private_ha_kernel_t *this, host_t *host, u_int segment)
        }
        return FALSE;
 }
+
 /**
- * Activate/Deactivate a segment
+ * Activate/Deactivate a segment for a given clusterip file
  */
-static void activate_deactivate(private_ha_kernel_t *this,
-                                                               u_int segment, char op)
+static void enable_disable(private_ha_kernel_t *this, u_int segment,
+                                                  char *file, bool enable)
 {
-       enumerator_t *enumerator;
-       host_t *host;
-       char cmd[8], file[256];
+       char cmd[8];
        int fd;
 
-       enumerator = this->virtuals->create_enumerator(this->virtuals);
-       while (enumerator->enumerate(enumerator, &host))
+       snprintf(cmd, sizeof(cmd), "%c%d\n", enable ? '+' : '-', segment);
+
+       fd = open(file, O_WRONLY);
+       if (fd == -1)
        {
-               snprintf(file, sizeof(file), "/proc/net/ipt_CLUSTERIP/%H", host);
-               snprintf(cmd, sizeof(cmd), "%c%d\n", op, segment);
+               DBG1(DBG_CFG, "opening CLUSTERIP file '%s' failed: %s",
+                        file, strerror(errno));
+               return;
+       }
+       if (write(fd, cmd, strlen(cmd) == -1))
+       {
+               DBG1(DBG_CFG, "writing to CLUSTERIP file '%s' failed: %s",
+                        file, strerror(errno));
+       }
+       close(fd);
+}
 
-               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))
+/**
+ * Get the currenlty active segments in the kernel for a clusterip file
+ */
+static segment_mask_t get_active(private_ha_kernel_t *this, char *file)
+{
+       char buf[256];
+       segment_mask_t mask = 0;
+       ssize_t len;
+       int fd;
+
+       fd = open(file, O_RDONLY);
+       if (fd == -1)
+       {
+               DBG1(DBG_CFG, "opening CLUSTERIP file '%s' failed: %s",
+                        file, strerror(errno));
+               return 0;
+       }
+       len = read(fd, buf, sizeof(buf)-1);
+       if (len == -1)
+       {
+               DBG1(DBG_CFG, "reading from CLUSTERIP file '%s' failed: %s",
+                        file, strerror(errno));
+       }
+       else
+       {
+               enumerator_t *enumerator;
+               u_int segment;
+               char *token;
+
+               buf[len] = '\0';
+               enumerator = enumerator_create_token(buf, ",", " ");
+               while (enumerator->enumerate(enumerator, &token))
                {
-                       DBG1(DBG_CFG, "writing to CLUSTERIP file '%s' failed: %s",
-                                file, strerror(errno));
+                       segment = atoi(token);
+                       if (segment)
+                       {
+                               mask |= SEGMENTS_BIT(segment);
+                       }
                }
-               close(fd);
+               enumerator->destroy(enumerator);
        }
-       enumerator->destroy(enumerator);
+       return mask;
 }
 
 /**
@@ -113,7 +147,15 @@ static void activate_deactivate(private_ha_kernel_t *this,
  */
 static void activate(private_ha_kernel_t *this, u_int segment)
 {
-       activate_deactivate(this, segment, '+');
+       enumerator_t *enumerator;
+       char *file;
+
+       enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+       while (enumerator->enumerate(enumerator, NULL, &file, NULL))
+       {
+               enable_disable(this, segment, file, TRUE);
+       }
+       enumerator->destroy(enumerator);
 }
 
 /**
@@ -121,75 +163,37 @@ static void activate(private_ha_kernel_t *this, u_int segment)
  */
 static void deactivate(private_ha_kernel_t *this, u_int segment)
 {
-       activate_deactivate(this, segment, '-');
-}
-
-/**
- * Mangle IPtable rules for virtual addresses
- */
-static bool mangle_rules(private_ha_kernel_t *this, bool add)
-{
        enumerator_t *enumerator;
-       host_t *host;
-       u_char i, mac = 0x20;
-       char *iface, buf[256];
+       char *file;
 
-       enumerator = this->virtuals->create_enumerator(this->virtuals);
-       while (enumerator->enumerate(enumerator, &host))
+       enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+       while (enumerator->enumerate(enumerator, NULL, &file, NULL))
        {
-               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, enable node 1 */
-               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->count);
-               free(iface);
-               if (system(buf) != 0)
-               {
-                       DBG1(DBG_CFG, "installing CLUSTERIP rule '%s' failed", buf);
-               }
+               enable_disable(this, segment, file, FALSE);
        }
        enumerator->destroy(enumerator);
-
-       if (add)
-       {
-               for (i = 2; i <= this->count; i++)
-               {
-                       activate(this, i);
-               }
-       }
-       return TRUE;
 }
 
 /**
- * Parse the list of virtual cluster addresses
+ * Enable all not-yet enabled segments on all clusterip addresses
  */
-static void parse_virtuals(private_ha_kernel_t *this, char *virtual)
+static void activate_all(private_ha_kernel_t *this)
 {
        enumerator_t *enumerator;
-       host_t *host;
+       segment_mask_t active;
+       char *file;
+       int i;
 
-       enumerator = enumerator_create_token(virtual, ",", " ");
-       while (enumerator->enumerate(enumerator, &virtual))
+       enumerator = enumerator_create_directory(CLUSTERIP_DIR);
+       while (enumerator->enumerate(enumerator, NULL, &file, NULL))
        {
-               host = host_create_from_string(virtual, 0);
-               if (host)
-               {
-                       this->virtuals->insert_last(this->virtuals, host);
-               }
-               else
+               active = get_active(this, file);
+               for (i = 1; i <= this->count; i++)
                {
-                       DBG1(DBG_CFG, "virtual cluster address '%s' invalid, ignored",
-                                virtual);
+                       if (!(active & SEGMENTS_BIT(i)))
+                       {
+                               enable_disable(this, i, file, TRUE);
+                       }
                }
        }
        enumerator->destroy(enumerator);
@@ -200,15 +204,13 @@ static void parse_virtuals(private_ha_kernel_t *this, char *virtual)
  */
 static void destroy(private_ha_kernel_t *this)
 {
-       mangle_rules(this, FALSE);
-       this->virtuals->destroy_offset(this->virtuals, offsetof(host_t, destroy));
        free(this);
 }
 
 /**
  * See header
  */
-ha_kernel_t *ha_kernel_create(u_int count, char *virtuals)
+ha_kernel_t *ha_kernel_create(u_int count)
 {
        private_ha_kernel_t *this = malloc_thing(private_ha_kernel_t);
 
@@ -219,15 +221,8 @@ ha_kernel_t *ha_kernel_create(u_int count, char *virtuals)
 
        this->initval = 0;
        this->count = count;
-       this->virtuals = linked_list_create();
 
-       parse_virtuals(this, virtuals);
-
-       if (!mangle_rules(this, TRUE))
-       {
-               destroy(this);
-               return NULL;
-       }
+       activate_all(this);
 
        return &this->public;
 }
index 2e9e18b..b37cc76 100644 (file)
@@ -64,8 +64,7 @@ struct ha_kernel_t {
  *
  * @param count                        total number of segments to use
  * @param active               bitmask of initially active segments
- * @param virtuals             comma separated list of virtual cluster addresses
  */
-ha_kernel_t *ha_kernel_create(u_int count, char *virtuals);
+ha_kernel_t *ha_kernel_create(u_int count);
 
 #endif /* HA_KERNEL_ @}*/
index 65101f8..fb780ca 100644 (file)
@@ -103,7 +103,7 @@ static void destroy(private_ha_plugin_t *this)
 plugin_t *plugin_create()
 {
        private_ha_plugin_t *this;
-       char *local, *remote, *secret, *virtuals;
+       char *local, *remote, *secret;
        u_int count;
        bool fifo;
 
@@ -111,8 +111,6 @@ plugin_t *plugin_create()
                                                                "charon.plugins.ha.local", NULL);
        remote = lib->settings->get_str(lib->settings,
                                                                "charon.plugins.ha.remote", NULL);
-       virtuals = lib->settings->get_str(lib->settings,
-                                                               "charon.plugins.ha.virtuals", "");
        secret = lib->settings->get_str(lib->settings,
                                                                "charon.plugins.ha.secret", NULL);
        fifo = lib->settings->get_bool(lib->settings,
@@ -137,7 +135,7 @@ plugin_t *plugin_create()
                free(this);
                return NULL;
        }
-       this->kernel = ha_kernel_create(count, virtuals);
+       this->kernel = ha_kernel_create(count);
        if (!this->kernel)
        {
                this->socket->destroy(this->socket);