moved updown script invocation to an optional plugin
authorMartin Willi <martin@strongswan.org>
Thu, 16 Oct 2008 11:48:18 +0000 (11:48 -0000)
committerMartin Willi <martin@strongswan.org>
Thu, 16 Oct 2008 11:48:18 +0000 (11:48 -0000)
12 files changed:
configure.in
src/charon/Makefile.am
src/charon/bus/bus.c
src/charon/plugins/updown/Makefile.am [new file with mode: 0644]
src/charon/plugins/updown/updown_plugin.c [new file with mode: 0644]
src/charon/plugins/updown/updown_plugin.h [new file with mode: 0644]
src/charon/sa/child_sa.c
src/charon/sa/child_sa.h
src/charon/sa/ike_sa.c
src/charon/sa/ike_sa_manager.c
src/charon/sa/tasks/child_create.c
src/charon/sa/tasks/ike_mobike.c

index 117dcf3..edd422b 100644 (file)
@@ -569,7 +569,7 @@ AC_ARG_ENABLE(
 
 AC_ARG_ENABLE(
        [updown],
-       AS_HELP_STRING([--disable-updown],[disable installation of firewall scripts. (default is NO).]),
+       AS_HELP_STRING([--disable-updown],[disable updown firewall script plugin. (default is NO).]),
        [if test x$enableval = xyes; then
                updown=true
         else
@@ -874,6 +874,7 @@ AM_CONDITIONAL(USE_NM, test x$nm = xtrue)
 AM_CONDITIONAL(USE_UCI, test x$uci = xtrue)
 AM_CONDITIONAL(USE_SMP, test x$smp = xtrue)
 AM_CONDITIONAL(USE_SQL, test x$sql = xtrue)
+AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue)
 AM_CONDITIONAL(USE_UNIT_TESTS, test x$unittest = xtrue)
 AM_CONDITIONAL(USE_EAP_SIM, test x$eap_sim = xtrue)
 AM_CONDITIONAL(USE_EAP_SIM_FILE, test x$eap_sim_file = xtrue)
@@ -902,7 +903,6 @@ AM_CONDITIONAL(USE_CAPABILITIES, test x$capabilities = xlibcap)
 AM_CONDITIONAL(USE_PLUTO, test x$pluto = xtrue)
 AM_CONDITIONAL(USE_CHARON, test x$charon = xtrue)
 AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue)
-AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue)
 AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue)
 AM_CONDITIONAL(USE_FILE_CONFIG, test x$pluto = xtrue -o x$stroke = xtrue)
 
@@ -966,6 +966,7 @@ AC_OUTPUT(
        src/charon/plugins/nm/Makefile
        src/charon/plugins/uci/Makefile
        src/charon/plugins/stroke/Makefile
+       src/charon/plugins/updown/Makefile
        src/charon/plugins/unit_tester/Makefile
        src/stroke/Makefile
        src/ipsec/Makefile
index 85111af..54a7903 100644 (file)
@@ -169,6 +169,11 @@ if USE_SQL
   PLUGINS += sql
 endif
 
+if USE_UPDOWN
+  SUBDIRS += plugins/updown
+  PLUGINS += updown
+endif
+
 if USE_EAP_IDENTITY
   SUBDIRS += plugins/eap_identity
   PLUGINS += eapidentity
index eb83908..371d431 100644 (file)
@@ -321,6 +321,9 @@ static void log_(private_bus_t *this, debug_t group, level_t level,
        va_end(args);
 }
 
+/**
+ * unregister a listener
+ */
 static void unregister_listener(private_bus_t *this, entry_t *entry,
                                                                enumerator_t *enumerator)
 {
diff --git a/src/charon/plugins/updown/Makefile.am b/src/charon/plugins/updown/Makefile.am
new file mode 100644 (file)
index 0000000..9fc226b
--- /dev/null
@@ -0,0 +1,10 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/charon
+
+AM_CFLAGS = -rdynamic
+
+plugin_LTLIBRARIES = libstrongswan-updown.la
+libstrongswan_updown_la_SOURCES = updown_plugin.h updown_plugin.c 
+libstrongswan_updown_la_LDFLAGS = -module
+
+
diff --git a/src/charon/plugins/updown/updown_plugin.c b/src/charon/plugins/updown/updown_plugin.c
new file mode 100644 (file)
index 0000000..e8fea02
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2008 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.
+ *
+ * $Id$
+ */
+
+#include "updown_plugin.h"
+
+#include <daemon.h>
+#include <config/child_cfg.h>
+
+typedef struct private_updown_plugin_t private_updown_plugin_t;
+
+/**
+ * private data of updown plugin
+ */
+struct private_updown_plugin_t {
+
+       /**
+        * implements plugin interface
+        */
+       updown_plugin_t public;
+       
+       /**
+        * Listener interface, listens to CHILD_SA state changes
+        */
+       listener_t listener;
+};
+
+/**
+ * Run the up/down script
+ */
+static void updown(ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
+{
+       traffic_selector_t *my_ts, *other_ts;
+       enumerator_t *enumerator;
+       child_cfg_t *config;
+       host_t *vip, *me, *other;
+       char *script;
+       
+       config = child_sa->get_config(child_sa);
+       vip = ike_sa->get_virtual_ip(ike_sa, TRUE);
+       script = config->get_updown(config);
+       me = ike_sa->get_my_host(ike_sa);
+       other = ike_sa->get_other_host(ike_sa);
+       
+       if (script == NULL)
+       {
+               return;
+       }
+       
+       enumerator = child_sa->create_policy_enumerator(child_sa);
+       while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
+       {
+               char command[1024];
+               char *my_client, *other_client, *my_client_mask, *other_client_mask;
+               char *pos, *virtual_ip, *iface;
+               FILE *shell;
+
+               /* get subnet/bits from string */
+               asprintf(&my_client, "%R", my_ts);
+               pos = strchr(my_client, '/');
+               *pos = '\0';
+               my_client_mask = pos + 1;
+               pos = strchr(my_client_mask, '[');
+               if (pos)
+               {
+                       *pos = '\0';
+               }
+               asprintf(&other_client, "%R", other_ts);
+               pos = strchr(other_client, '/');
+               *pos = '\0';
+               other_client_mask = pos + 1;
+               pos = strchr(other_client_mask, '[');
+               if (pos)
+               {
+                       *pos = '\0';
+               }
+
+               if (vip)
+               {
+                       asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ", vip);
+               }
+               else
+               {
+                       asprintf(&virtual_ip, "");
+               }
+               
+               iface = charon->kernel_interface->get_interface(
+                                                                                               charon->kernel_interface, me);
+               
+               /* build the command with all env variables.
+                * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
+                */
+               snprintf(command, sizeof(command),
+                                "2>&1 "
+                               "PLUTO_VERSION='1.1' "
+                               "PLUTO_VERB='%s%s%s' "
+                               "PLUTO_CONNECTION='%s' "
+                               "PLUTO_INTERFACE='%s' "
+                               "PLUTO_REQID='%u' "
+                               "PLUTO_ME='%H' "
+                               "PLUTO_MY_ID='%D' "
+                               "PLUTO_MY_CLIENT='%s/%s' "
+                               "PLUTO_MY_CLIENT_NET='%s' "
+                               "PLUTO_MY_CLIENT_MASK='%s' "
+                               "PLUTO_MY_PORT='%u' "
+                               "PLUTO_MY_PROTOCOL='%u' "
+                               "PLUTO_PEER='%H' "
+                               "PLUTO_PEER_ID='%D' "
+                               "PLUTO_PEER_CLIENT='%s/%s' "
+                               "PLUTO_PEER_CLIENT_NET='%s' "
+                               "PLUTO_PEER_CLIENT_MASK='%s' "
+                               "PLUTO_PEER_PORT='%u' "
+                               "PLUTO_PEER_PROTOCOL='%u' "
+                               "%s"
+                               "%s"
+                               "%s",
+                                up ? "up" : "down",
+                                my_ts->is_host(my_ts, me) ? "-host" : "-client",
+                                me->get_family(me) == AF_INET ? "" : "-v6",
+                                config->get_name(config),
+                                iface ? iface : "unknown",
+                                child_sa->get_reqid(child_sa),
+                                me, ike_sa->get_my_id(ike_sa),
+                                my_client, my_client_mask,
+                                my_client, my_client_mask,
+                                my_ts->get_from_port(my_ts),
+                                my_ts->get_protocol(my_ts),
+                                other, ike_sa->get_other_id(ike_sa),
+                                other_client, other_client_mask,
+                                other_client, other_client_mask,
+                                other_ts->get_from_port(other_ts),
+                                other_ts->get_protocol(other_ts),
+                                virtual_ip,
+                                config->get_hostaccess(config) ? "PLUTO_HOST_ACCESS='1' " : "",
+                                script);
+               free(my_client);
+               free(other_client);
+               free(virtual_ip);
+               free(iface);
+               
+               DBG3(DBG_CHD, "running updown script: %s", command);
+               shell = popen(command, "r");
+
+               if (shell == NULL)
+               {
+                       DBG1(DBG_CHD, "could not execute updown script '%s'", script);
+                       return;
+               }
+               
+               while (TRUE)
+               {
+                       char resp[128];
+                       
+                       if (fgets(resp, sizeof(resp), shell) == NULL)
+                       {
+                               if (ferror(shell))
+                               {
+                                       DBG1(DBG_CHD, "error reading output from updown script");
+                                       return;
+                               }
+                               else
+                               {
+                                       break;
+                               }
+                       }
+                       else
+                       {
+                               char *e = resp + strlen(resp);
+                               if (e > resp && e[-1] == '\n')
+                               {       /* trim trailing '\n' */
+                                       e[-1] = '\0';
+                               }
+                               DBG1(DBG_CHD, "updown: %s", resp);
+                       }
+               }
+               pclose(shell);
+       }
+       enumerator->destroy(enumerator);
+}
+
+/**
+ * Listener implementation
+ */
+static bool child_state_change(listener_t *this, ike_sa_t *ike_sa,
+                                                          child_sa_t *child_sa, child_sa_state_t state)
+{
+       child_sa_state_t old;
+       
+       old = child_sa->get_state(child_sa);
+       
+       if ((old == CHILD_INSTALLED && state != CHILD_REKEYING ) ||
+               (old == CHILD_DELETING && state == CHILD_DESTROYING))
+       {
+               updown(ike_sa, child_sa, FALSE);
+       }
+       else if (state == CHILD_INSTALLED)
+       {
+               updown(ike_sa, child_sa, TRUE);
+       }
+       return TRUE;
+}
+
+/**
+ * Implementation of plugin_t.destroy
+ */
+static void destroy(private_updown_plugin_t *this)
+{
+       charon->bus->remove_listener(charon->bus, &this->listener);
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *plugin_create()
+{
+       private_updown_plugin_t *this = malloc_thing(private_updown_plugin_t);
+       
+       this->public.plugin.destroy = (void(*)(plugin_t*))destroy;
+       
+       memset(&this->listener, 0, sizeof(listener_t));
+       this->listener.child_state_change = child_state_change;
+       
+       charon->bus->add_listener(charon->bus, &this->listener);
+       
+       return &this->public.plugin;
+}
+
diff --git a/src/charon/plugins/updown/updown_plugin.h b/src/charon/plugins/updown/updown_plugin.h
new file mode 100644 (file)
index 0000000..4d0a930
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 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.
+ *
+ * $Id$
+ */
+
+/**
+ * @defgroup updown updown
+ * @ingroup cplugins
+ *
+ * @defgroup updown_plugin updown_plugin
+ * @{ @ingroup updown
+ */
+
+#ifndef UPDOWN_PLUGIN_H_
+#define UPDOWN_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct updown_plugin_t updown_plugin_t;
+
+/**
+ * Updown firewall script invocation plugin, compatible to pluto ones.
+ */
+struct updown_plugin_t {
+
+       /**
+        * implements plugin interface
+        */
+       plugin_t plugin;
+};
+
+/**
+ * Create a updown_plugin instance.
+ */
+plugin_t *plugin_create();
+
+#endif /* UPDOWN_PLUGIN_H_ @}*/
index 932828d..d0df545 100644 (file)
@@ -30,6 +30,7 @@ ENUM(child_sa_state_names, CHILD_CREATED, CHILD_DESTROYING,
        "CREATED",
        "ROUTED",
        "INSTALLED",
+       "UPDATING",
        "REKEYING",
        "DELETING",
        "DESTROYING",
@@ -49,8 +50,6 @@ struct private_child_sa_t {
        struct {
                /** address of peer */
                host_t *addr;
-               /** id of peer */
-               identification_t *id;
                /** actual used SPI, 0 if unused */
                u_int32_t spi;
                /** Compression Parameter Index (CPI) used, 0 if unused */
@@ -143,19 +142,9 @@ struct private_child_sa_t {
        ipsec_mode_t mode;
        
        /**
-        * virtual IP assigned to local host
-        */
-       host_t *virtual_ip;
-       
-       /**
         * config used to create this child
         */
        child_cfg_t *config;
-       
-       /**
-        * cached interface name for iptables
-        */
-       char *iface;
 };
 
 typedef struct keylen_entry_t keylen_entry_t;
@@ -404,170 +393,10 @@ static void get_stats(private_child_sa_t *this, ipsec_mode_t *mode,
 }
 
 /**
- * Run the up/down script
- */
-static void updown(private_child_sa_t *this, bool up)
-{
-       traffic_selector_t *my_ts, *other_ts;
-       enumerator_t *enumerator;
-       char *script;
-       
-       script = this->config->get_updown(this->config);
-       
-       if (script == NULL)
-       {
-               return;
-       }
-       
-       enumerator = create_policy_enumerator(this);
-       while (enumerator->enumerate(enumerator, &my_ts, &other_ts))
-       {
-               char command[1024];
-               char *my_client, *other_client, *my_client_mask, *other_client_mask;
-               char *pos, *virtual_ip;
-               FILE *shell;
-
-               /* get subnet/bits from string */
-               asprintf(&my_client, "%R", my_ts);
-               pos = strchr(my_client, '/');
-               *pos = '\0';
-               my_client_mask = pos + 1;
-               pos = strchr(my_client_mask, '[');
-               if (pos)
-               {
-                       *pos = '\0';
-               }
-               asprintf(&other_client, "%R", other_ts);
-               pos = strchr(other_client, '/');
-               *pos = '\0';
-               other_client_mask = pos + 1;
-               pos = strchr(other_client_mask, '[');
-               if (pos)
-               {
-                       *pos = '\0';
-               }
-
-               if (this->virtual_ip)
-               {
-                       asprintf(&virtual_ip, "PLUTO_MY_SOURCEIP='%H' ",
-                                        this->virtual_ip);
-               }
-               else
-               {
-                       asprintf(&virtual_ip, "");
-               }
-
-               /* we cache the iface name, as it may not be available when
-                * the SA gets deleted */
-               if (up)
-               {
-                       free(this->iface); 
-                       this->iface = charon->kernel_interface->get_interface(
-                                                               charon->kernel_interface, this->me.addr);
-               }
-               
-               /* build the command with all env variables.
-                * TODO: PLUTO_PEER_CA and PLUTO_NEXT_HOP are currently missing
-                */
-               snprintf(command, sizeof(command),
-                                "2>&1 "
-                               "PLUTO_VERSION='1.1' "
-                               "PLUTO_VERB='%s%s%s' "
-                               "PLUTO_CONNECTION='%s' "
-                               "PLUTO_INTERFACE='%s' "
-                               "PLUTO_REQID='%u' "
-                               "PLUTO_ME='%H' "
-                               "PLUTO_MY_ID='%D' "
-                               "PLUTO_MY_CLIENT='%s/%s' "
-                               "PLUTO_MY_CLIENT_NET='%s' "
-                               "PLUTO_MY_CLIENT_MASK='%s' "
-                               "PLUTO_MY_PORT='%u' "
-                               "PLUTO_MY_PROTOCOL='%u' "
-                               "PLUTO_PEER='%H' "
-                               "PLUTO_PEER_ID='%D' "
-                               "PLUTO_PEER_CLIENT='%s/%s' "
-                               "PLUTO_PEER_CLIENT_NET='%s' "
-                               "PLUTO_PEER_CLIENT_MASK='%s' "
-                               "PLUTO_PEER_PORT='%u' "
-                               "PLUTO_PEER_PROTOCOL='%u' "
-                               "%s"
-                               "%s"
-                               "%s",
-                                up ? "up" : "down",
-                                my_ts->is_host(my_ts, this->me.addr) ? "-host" : "-client",
-                                this->me.addr->get_family(this->me.addr) == AF_INET ? "" : "-v6",
-                                this->config->get_name(this->config),
-                                this->iface ? this->iface : "unknown",
-                                this->reqid,
-                                this->me.addr,
-                                this->me.id,
-                                my_client, my_client_mask,
-                                my_client, my_client_mask,
-                                my_ts->get_from_port(my_ts),
-                                my_ts->get_protocol(my_ts),
-                                this->other.addr,
-                                this->other.id,
-                                other_client, other_client_mask,
-                                other_client, other_client_mask,
-                                other_ts->get_from_port(other_ts),
-                                other_ts->get_protocol(other_ts),
-                                virtual_ip,
-                                this->config->get_hostaccess(this->config) ?
-                                       "PLUTO_HOST_ACCESS='1' " : "",
-                                script);
-               free(my_client);
-               free(other_client);
-               free(virtual_ip);
-               
-               DBG3(DBG_CHD, "running updown script: %s", command);
-               shell = popen(command, "r");
-
-               if (shell == NULL)
-               {
-                       DBG1(DBG_CHD, "could not execute updown script '%s'", script);
-                       return;
-               }
-               
-               while (TRUE)
-               {
-                       char resp[128];
-                       
-                       if (fgets(resp, sizeof(resp), shell) == NULL)
-                       {
-                               if (ferror(shell))
-                               {
-                                       DBG1(DBG_CHD, "error reading output from updown script");
-                                       return;
-                               }
-                               else
-                               {
-                                       break;
-                               }
-                       }
-                       else
-                       {
-                               char *e = resp + strlen(resp);
-                               if (e > resp && e[-1] == '\n')
-                               {       /* trim trailing '\n' */
-                                       e[-1] = '\0';
-                               }
-                               DBG1(DBG_CHD, "updown: %s", resp);
-                       }
-               }
-               pclose(shell);
-       }
-       enumerator->destroy(enumerator);
-}
-
-/**
  * Implements child_sa_t.set_state
  */
 static void set_state(private_child_sa_t *this, child_sa_state_t state)
 {
-       if (state == CHILD_INSTALLED)
-       {
-               updown(this, TRUE);
-       }
        charon->bus->child_state_change(charon->bus, &this->public, state);
        this->state = state;
 }
@@ -955,27 +784,32 @@ static status_t get_use_time(private_child_sa_t *this,
  * Implementation of child_sa_t.update_hosts.
  */
 static status_t update_hosts(private_child_sa_t *this, 
-                                                        host_t *me, host_t *other, bool encap) 
+                                                        host_t *me, host_t *other, host_t *vip, bool encap) 
 {
+       child_sa_state_t old;
+       
        /* anything changed at all? */
        if (me->equals(me, this->me.addr) && 
                other->equals(other, this->other.addr) && this->encap == encap)
        {
                return SUCCESS;
        }
-       /* run updown script to remove iptables rules */
-       updown(this, FALSE);
+       
+       old = this->state;
+       set_state(this, CHILD_UPDATING);
        
        this->encap = encap;
        
        if (this->ipcomp != IPCOMP_NONE)
        {
                /* update our (initator) IPComp SA */
-               charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->me.cpi)),
-                               IPPROTO_COMP, this->other.addr, this->me.addr, other, me, FALSE);
+               charon->kernel_interface->update_sa(charon->kernel_interface, 
+                                                       htonl(ntohs(this->me.cpi)),     IPPROTO_COMP,
+                                                       this->other.addr, this->me.addr, other, me, FALSE);
                /* update his (responder) IPComp SA */
-               charon->kernel_interface->update_sa(charon->kernel_interface, htonl(ntohs(this->other.cpi)), 
-                               IPPROTO_COMP, this->me.addr, this->other.addr, me, other, FALSE);
+               charon->kernel_interface->update_sa(charon->kernel_interface,
+                                                       htonl(ntohs(this->other.cpi)), IPPROTO_COMP,
+                                                       this->me.addr, this->other.addr, me, other, FALSE);
        }
        
        /* update our (initator) SA */
@@ -1018,12 +852,10 @@ static status_t update_hosts(private_child_sa_t *this,
                        
                        /* we reinstall the virtual IP to handle interface roaming
                         * correctly */
-                       if (this->virtual_ip)
+                       if (vip)
                        {
-                               charon->kernel_interface->del_ip(charon->kernel_interface,
-                                                                                                this->virtual_ip);
-                               charon->kernel_interface->add_ip(charon->kernel_interface,
-                                                                                                this->virtual_ip, me);
+                               charon->kernel_interface->del_ip(charon->kernel_interface, vip);
+                               charon->kernel_interface->add_ip(charon->kernel_interface, vip, me);
                        }
                
                        /* reinstall updated policies */
@@ -1052,21 +884,12 @@ static status_t update_hosts(private_child_sa_t *this,
                this->other.addr = other->clone(other);
        }
        
-       /* install new iptables rules */
-       updown(this, TRUE);
+       set_state(this, old);
        
        return SUCCESS;
 }
 
 /**
- * Implementation of child_sa_t.set_virtual_ip.
- */
-static void set_virtual_ip(private_child_sa_t *this, host_t *ip)
-{
-       this->virtual_ip = ip->clone(ip);
-}
-
-/**
  * Implementation of child_sa_t.activate_ipcomp.
  */
 static void activate_ipcomp(private_child_sa_t *this, ipcomp_transform_t ipcomp,
@@ -1098,11 +921,6 @@ static void destroy(private_child_sa_t *this)
        enumerator_t *enumerator;
        traffic_selector_t *my_ts, *other_ts;
        
-       if (this->state == CHILD_DELETING || this->state == CHILD_INSTALLED)
-       {
-               updown(this, FALSE);
-       }
-       
        set_state(this, CHILD_DESTROYING);
        
        /* delete SAs in the kernel, if they are set up */
@@ -1158,11 +976,7 @@ static void destroy(private_child_sa_t *this)
        this->other_ts->destroy_offset(this->other_ts, offsetof(traffic_selector_t, destroy));
        this->me.addr->destroy(this->me.addr);
        this->other.addr->destroy(this->other.addr);
-       this->me.id->destroy(this->me.id);
-       this->other.id->destroy(this->other.id);
        this->config->destroy(this->config);
-       free(this->iface);
-       DESTROY_IF(this->virtual_ip);
        free(this);
 }
 
@@ -1170,7 +984,6 @@ static void destroy(private_child_sa_t *this)
  * Described in header.
  */
 child_sa_t * child_sa_create(host_t *me, host_t* other,
-                                                        identification_t *my_id, identification_t *other_id,
                                                         child_cfg_t *config, u_int32_t rekey, bool encap)
 {
        static u_int32_t reqid = 0;
@@ -1186,7 +999,7 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->public.alloc = (status_t(*)(child_sa_t*,linked_list_t*))alloc;
        this->public.add = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))add;
        this->public.update = (status_t(*)(child_sa_t*,proposal_t*,ipsec_mode_t,prf_plus_t*))update;
-       this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,bool))update_hosts;
+       this->public.update_hosts = (status_t (*)(child_sa_t*,host_t*,host_t*,host_t*,bool))update_hosts;
        this->public.add_policies = (status_t (*)(child_sa_t*, linked_list_t*,linked_list_t*,ipsec_mode_t,protocol_id_t))add_policies;
        this->public.get_traffic_selectors = (linked_list_t*(*)(child_sa_t*,bool))get_traffic_selectors;
        this->public.create_policy_enumerator = (enumerator_t*(*)(child_sa_t*))create_policy_enumerator;
@@ -1196,14 +1009,11 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->public.get_config = (child_cfg_t*(*)(child_sa_t*))get_config;
        this->public.activate_ipcomp = (void(*)(child_sa_t*,ipcomp_transform_t,u_int16_t))activate_ipcomp;
        this->public.allocate_cpi = (u_int16_t(*)(child_sa_t*))allocate_cpi;
-       this->public.set_virtual_ip = (void(*)(child_sa_t*,host_t*))set_virtual_ip;
        this->public.destroy = (void(*)(child_sa_t*))destroy;
 
        /* private data */
        this->me.addr = me->clone(me);
        this->other.addr = other->clone(other);
-       this->me.id = my_id->clone(my_id);
-       this->other.id = other_id->clone(other_id);
        this->me.spi = 0;
        this->me.cpi = 0;
        this->other.spi = 0;
@@ -1224,10 +1034,9 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
        this->other_ts = linked_list_create();
        this->protocol = PROTO_NONE;
        this->mode = MODE_TUNNEL;
-       this->virtual_ip = NULL;
-       this->iface = NULL;
        this->config = config;
        config->get_ref(config);
        
        return &this->public;
 }
+
index cda1dc7..11c3a0a 100644 (file)
@@ -55,6 +55,11 @@ enum child_sa_state_t {
        CHILD_INSTALLED,
        
        /**
+        * While updating hosts, in update_hosts()
+        */
+       CHILD_UPDATING,
+       
+       /**
         * CHILD_SA which is rekeying
         */
        CHILD_REKEYING,
@@ -207,11 +212,12 @@ struct child_sa_t {
         *
         * @param me            the new local host
         * @param other         the new remote host
+        * @param vip           virtual IP, if any
         * @param                       TRUE to use UDP encapsulation for NAT traversal
         * @return                      SUCCESS or FAILED
         */
        status_t (*update_hosts)(child_sa_t *this, host_t *me, host_t *other,
-                                                        bool encap);
+                                                        host_t *vip, bool encap);
        
        /**
         * Install the policies using some traffic selectors.
@@ -273,16 +279,6 @@ struct child_sa_t {
        child_cfg_t* (*get_config) (child_sa_t *this);
        
        /**
-        * Set the virtual IP used received from IRAS.
-        *
-        * To allow proper setup of firewall rules, the virtual IP is required
-        * for filtering.
-        *
-        * @param ip            own virtual IP
-        */
-       void (*set_virtual_ip) (child_sa_t *this, host_t *ip);
-       
-       /**
         * Activate IPComp by setting the transform ID and CPI values.
         * 
         * @param ipcomp        the IPComp transform to use
@@ -316,8 +312,7 @@ struct child_sa_t {
  * @param encap                        TRUE to enable UDP encapsulation (NAT traversal)
  * @return                             child_sa_t object
  */
-child_sa_t * child_sa_create(host_t *me, host_t *other,
-                                                        identification_t *my_id, identification_t* other_id,
-                                                        child_cfg_t *config, u_int32_t reqid, bool encap);
+child_sa_t * child_sa_create(host_t *me, host_t *other, child_cfg_t *config,
+                                                        u_int32_t reqid, bool encap);
 
 #endif /*CHILD_SA_H_ @} */
index 28241cf..1d45acb 100644 (file)
@@ -927,7 +927,7 @@ static void update_hosts(private_ike_sa_t *this, host_t *me, host_t *other)
                while (iterator->iterate(iterator, (void**)&child_sa))
                {
                        child_sa->update_hosts(child_sa, this->my_host, this->other_host,
-                                                                  has_condition(this, COND_NAT_ANY));
+                                               this->my_virtual_ip, has_condition(this, COND_NAT_ANY));
                }
                iterator->destroy(iterator);
        }
@@ -1285,8 +1285,8 @@ static status_t route(private_ike_sa_t *this, child_cfg_t *child_cfg)
        resolve_hosts(this);
 
        /* install kernel policies */
-       child_sa = child_sa_create(this->my_host, this->other_host, this->my_id,
-                                                          this->other_id, child_cfg, 0, FALSE);
+       child_sa = child_sa_create(this->my_host, this->other_host,
+                                                          child_cfg, 0, FALSE);
        me = this->my_host;
        if (this->my_virtual_ip)
        {
@@ -2481,6 +2481,9 @@ static void destroy(private_ike_sa_t *this)
        
        this->child_sas->destroy_offset(this->child_sas, offsetof(child_sa_t, destroy));
        
+       /* unset SA after here to avoid usage by the listeners */
+       charon->bus->set_sa(charon->bus, NULL);
+       
        this->task_manager->destroy(this->task_manager);
        
        DESTROY_IF(this->crypter_in);
index 1eedddb..4db9d00 100644 (file)
@@ -880,7 +880,6 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
        
        ike_sa_id = ike_sa->get_id(ike_sa);
        DBG2(DBG_MGR, "checkin and destroy IKE_SA");
-       charon->bus->set_sa(charon->bus, NULL);
 
        pthread_mutex_lock(&(this->mutex));
 
@@ -899,6 +898,7 @@ static status_t checkin_and_destroy(private_ike_sa_manager_t *this, ike_sa_t *ik
                DBG2(DBG_MGR, "tried to check-in and delete nonexisting IKE_SA");
                retval = NOT_FOUND;
        }
+       charon->bus->set_sa(charon->bus, NULL);
        
        pthread_mutex_unlock(&(this->mutex));
        return retval;
@@ -981,6 +981,7 @@ static void flush(private_ike_sa_manager_t *this)
        enumerator = this->ike_sa_list->create_enumerator(this->ike_sa_list);
        while (enumerator->enumerate(enumerator, &entry))
        {
+               charon->bus->set_sa(charon->bus, entry->ike_sa);
                entry->ike_sa->delete(entry->ike_sa);
        }
        enumerator->destroy(enumerator);
@@ -990,8 +991,10 @@ static void flush(private_ike_sa_manager_t *this)
        while (this->ike_sa_list->remove_last(this->ike_sa_list,
                                                                                  (void**)&entry) == SUCCESS)
        {
+               charon->bus->set_sa(charon->bus, entry->ike_sa);
                entry_destroy(entry);
        }
+       charon->bus->set_sa(charon->bus, NULL);
        pthread_mutex_unlock(&(this->mutex));
 }
 
index 6c67392..78a06e3 100644 (file)
@@ -260,11 +260,6 @@ static status_t select_and_install(private_child_create_t *this, bool no_dh)
        {
                my_vip = me;
        }
-       else if (this->initiator)
-       {
-               /* to setup firewall rules correctly, CHILD_SA needs the virtual IP */
-               this->child_sa->set_virtual_ip(this->child_sa, my_vip);
-       }
        if (other_vip == NULL)
        {
                other_vip = other;
@@ -639,11 +634,8 @@ static status_t build_i(private_child_create_t *this, message_t *message)
                                                                                                  this->dh_group == MODP_NONE);
        this->mode = this->config->get_mode(this->config);
        
-       this->child_sa = child_sa_create(
-                       this->ike_sa->get_my_host(this->ike_sa),
-                       this->ike_sa->get_other_host(this->ike_sa),
-                       this->ike_sa->get_my_id(this->ike_sa), 
-                       this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
+       this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+                       this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        
        if (this->child_sa->alloc(this->child_sa, this->proposals) != SUCCESS)
@@ -822,11 +814,8 @@ static status_t build_r(private_child_create_t *this, message_t *message)
        }
        iterator->destroy(iterator);
        
-       this->child_sa = child_sa_create(
-                       this->ike_sa->get_my_host(this->ike_sa),
-                       this->ike_sa->get_other_host(this->ike_sa),
-                       this->ike_sa->get_my_id(this->ike_sa),
-                       this->ike_sa->get_other_id(this->ike_sa), this->config, this->reqid,
+       this->child_sa = child_sa_create(this->ike_sa->get_my_host(this->ike_sa),
+                       this->ike_sa->get_other_host(this->ike_sa), this->config, this->reqid,
                        this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        
        if (this->config->use_ipcomp(this->config) &&
index 54b7d0a..b3bffd6 100644 (file)
@@ -254,6 +254,7 @@ static void update_children(private_ike_mobike_t *this)
                child_sa->update_hosts(child_sa,
                                                this->ike_sa->get_my_host(this->ike_sa), 
                                                this->ike_sa->get_other_host(this->ike_sa),
+                                               this->ike_sa->get_virtual_ip(this->ike_sa, TRUE),
                                                this->ike_sa->has_condition(this->ike_sa, COND_NAT_ANY));
        }
        iterator->destroy(iterator);