diff options
author | Martin Willi <martin@strongswan.org> | 2008-10-16 11:48:18 +0000 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2008-10-16 11:48:18 +0000 |
commit | ad3af574a4b71f7d83e5b871d9dd998ec4068580 (patch) | |
tree | 2c490c5f7efc35cc1190786e634d2cddbc4fa19e | |
parent | e17353fc31fb83852b196edfb52f4e091acbc0e3 (diff) | |
download | strongswan-ad3af574a4b71f7d83e5b871d9dd998ec4068580.tar.bz2 strongswan-ad3af574a4b71f7d83e5b871d9dd998ec4068580.tar.xz |
moved updown script invocation to an optional plugin
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | src/charon/Makefile.am | 5 | ||||
-rw-r--r-- | src/charon/bus/bus.c | 3 | ||||
-rw-r--r-- | src/charon/plugins/updown/Makefile.am | 10 | ||||
-rw-r--r-- | src/charon/plugins/updown/updown_plugin.c | 241 | ||||
-rw-r--r-- | src/charon/plugins/updown/updown_plugin.h | 49 | ||||
-rw-r--r-- | src/charon/sa/child_sa.c | 229 | ||||
-rw-r--r-- | src/charon/sa/child_sa.h | 23 | ||||
-rw-r--r-- | src/charon/sa/ike_sa.c | 9 | ||||
-rw-r--r-- | src/charon/sa/ike_sa_manager.c | 5 | ||||
-rw-r--r-- | src/charon/sa/tasks/child_create.c | 19 | ||||
-rw-r--r-- | src/charon/sa/tasks/ike_mobike.c | 1 |
12 files changed, 354 insertions, 245 deletions
diff --git a/configure.in b/configure.in index 117dcf30a..edd422b52 100644 --- a/configure.in +++ b/configure.in @@ -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 diff --git a/src/charon/Makefile.am b/src/charon/Makefile.am index 85111afdd..54a7903da 100644 --- a/src/charon/Makefile.am +++ b/src/charon/Makefile.am @@ -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 diff --git a/src/charon/bus/bus.c b/src/charon/bus/bus.c index eb8390856..371d431b2 100644 --- a/src/charon/bus/bus.c +++ b/src/charon/bus/bus.c @@ -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 index 000000000..9fc226b5e --- /dev/null +++ b/src/charon/plugins/updown/Makefile.am @@ -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 index 000000000..e8fea0273 --- /dev/null +++ b/src/charon/plugins/updown/updown_plugin.c @@ -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 index 000000000..4d0a930c2 --- /dev/null +++ b/src/charon/plugins/updown/updown_plugin.h @@ -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_ @}*/ diff --git a/src/charon/sa/child_sa.c b/src/charon/sa/child_sa.c index 932828d11..d0df5454b 100644 --- a/src/charon/sa/child_sa.c +++ b/src/charon/sa/child_sa.c @@ -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; } + diff --git a/src/charon/sa/child_sa.h b/src/charon/sa/child_sa.h index cda1dc70a..11c3a0af7 100644 --- a/src/charon/sa/child_sa.h +++ b/src/charon/sa/child_sa.h @@ -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_ @} */ diff --git a/src/charon/sa/ike_sa.c b/src/charon/sa/ike_sa.c index 28241cfb7..1d45acbba 100644 --- a/src/charon/sa/ike_sa.c +++ b/src/charon/sa/ike_sa.c @@ -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); diff --git a/src/charon/sa/ike_sa_manager.c b/src/charon/sa/ike_sa_manager.c index 1eedddb22..4db9d00c3 100644 --- a/src/charon/sa/ike_sa_manager.c +++ b/src/charon/sa/ike_sa_manager.c @@ -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)); } diff --git a/src/charon/sa/tasks/child_create.c b/src/charon/sa/tasks/child_create.c index 6c673927c..78a06e330 100644 --- a/src/charon/sa/tasks/child_create.c +++ b/src/charon/sa/tasks/child_create.c @@ -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) && diff --git a/src/charon/sa/tasks/ike_mobike.c b/src/charon/sa/tasks/ike_mobike.c index 54b7d0a7b..b3bffd670 100644 --- a/src/charon/sa/tasks/ike_mobike.c +++ b/src/charon/sa/tasks/ike_mobike.c @@ -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); |