I've been looking at adding support for subnets when using transport mode.
In our use case, it will be far more efficient to allow users to specify
    right=192.168.1.128/25
instead of having to create a separate connection config for each host. It
appears that there has been some prior interest and work in this area:
  https://wiki.strongswan.org/issues/196
  https://lists.strongswan.org/pipermail/users/2013-February/004349.html

Timo Teräs posted a set of patches that updated the trap-any support in
April.
  https://lists.strongswan.org/pipermail/dev/2015-April/001344.html

Building on Timo Teräs' patches, I've managed to get this functionality
working in my (limited) testing, and I'm hoping to get some feedback on it.

The first patch file is an updated version of Timo's patches 5 .. 8 (the
ones that were not incorporated into the master branch), based off the
trap-acquire-tracking branch as of July 13
(04f562d83e430fd6b35395def876846923db4b4c).

The second patch file contains the changes I've made to add the subnet
support and fix the issues I found in getting it up and running.

Known caveats:
  * inbound connections using PSK authentication fail, as no matching
config is found
. Outbound connections work, however
  * The subnet parsing is limited to CIDR format for a single range.
          right=192.168.122.15/31 works
          right=192.168.122.14,192.168.122.15 is not parsed

Thanks,

-- Stuart
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 2c0b7b9..471b444 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -434,7 +434,7 @@ static job_requeue_t initiate(private_cmd_connection_t *this)
 	child_cfg = create_child_cfg(this, peer_cfg);
 
 	if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
-									 controller_cb_empty, NULL, 0) != SUCCESS)
+									 NULL, NULL, controller_cb_empty, NULL, 0) != SUCCESS)
 	{
 		terminate(pid);
 	}
diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c
index fc7e899..4f4461a 100644
--- a/src/charon-nm/nm/nm_service.c
+++ b/src/charon-nm/nm/nm_service.c
@@ -579,7 +579,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection,
 	 * Prepare IKE_SA
 	 */
 	ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
-														peer_cfg);
+														peer_cfg, NULL, NULL);
 	if (!ike_sa)
 	{
 		peer_cfg->destroy(peer_cfg);
diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
index 896bb09..46d0cba 100644
--- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c
+++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c
@@ -768,7 +768,7 @@ static job_requeue_t initiate(private_android_service_t *this)
 
 	/* get us an IKE_SA */
 	ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
-														peer_cfg);
+														peer_cfg, NULL, NULL);
 	if (!ike_sa)
 	{
 		peer_cfg->destroy(peer_cfg);
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index fd8349e..2973f51 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -15,6 +15,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "controller.h"
 
 #include <sys/types.h>
@@ -103,6 +125,16 @@ struct interface_listener_t {
 	ike_sa_t *ike_sa;
 
 	/**
+	 * Our host hint.
+	 */
+	host_t *my_host;
+
+	/**
+	 * Other host hint.
+	 */
+	host_t *other_host;
+
+	/**
 	 * unique ID, used for various methods
 	 */
 	u_int32_t id;
@@ -350,9 +382,14 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 	ike_sa_t *ike_sa;
 	interface_listener_t *listener = &job->listener;
 	peer_cfg_t *peer_cfg = listener->peer_cfg;
+	host_t *my_host = listener->my_host;
+	host_t *other_host = listener->other_host;
 
 	ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
-														peer_cfg);
+														peer_cfg, my_host, other_host);
+	DESTROY_IF(my_host);
+	DESTROY_IF(other_host);
+
 	if (!ike_sa)
 	{
 		listener->child_cfg->destroy(listener->child_cfg);
@@ -362,6 +399,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 		listener_done(listener);
 		return JOB_REQUEUE_NONE;
 	}
+
 	listener->lock->lock(listener->lock);
 	listener->ike_sa = ike_sa;
 	listener->lock->unlock(listener->lock);
@@ -391,6 +429,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
 
 METHOD(controller_t, initiate, status_t,
 	private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
+	host_t *my_host, host_t *other_host,
 	controller_cb_t callback, void *param, u_int timeout)
 {
 	interface_job_t *job;
@@ -413,6 +452,8 @@ METHOD(controller_t, initiate, status_t,
 			.status = FAILED,
 			.child_cfg = child_cfg,
 			.peer_cfg = peer_cfg,
+			.my_host = my_host ? my_host->clone(my_host) : NULL,
+			.other_host = other_host ? other_host->clone(other_host) : NULL,
 			.lock = spinlock_create(),
 		},
 		.public = {
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
index 02f4ebb..e70f2b5 100644
--- a/src/libcharon/control/controller.h
+++ b/src/libcharon/control/controller.h
@@ -79,6 +79,8 @@ struct controller_t {
 	 *
 	 * @param peer_cfg		peer_cfg to use for IKE_SA setup
 	 * @param child_cfg		child_cfg to set up CHILD_SA from
+	 * @param my_host		optional address hint for source
+	 * @param other_host	optional address hint for destination
 	 * @param cb			logging callback
 	 * @param param			parameter to include in each call of cb
 	 * @param timeout		timeout in ms to wait for callbacks, 0 to disable
@@ -90,6 +92,7 @@ struct controller_t {
 	 */
 	status_t (*initiate)(controller_t *this,
 						 peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
+						 host_t *my_host, host_t *other_host,
 						 controller_cb_t callback, void *param, u_int timeout);
 
 	/**
diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c
index 2e96f8f..e594a71 100644
--- a/src/libcharon/plugins/maemo/maemo_service.c
+++ b/src/libcharon/plugins/maemo/maemo_service.c
@@ -362,7 +362,7 @@ static gboolean initiate_connection(private_maemo_service_t *this,
 
 	/* get us an IKE_SA */
 	ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
-														peer_cfg);
+														peer_cfg, NULL, NULL);
 	if (!ike_sa)
 	{
 		peer_cfg->destroy(peer_cfg);
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 0084fbf..e5f38b4 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -109,7 +109,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
 	if (msg->output_verbosity < 0)
 	{
 		charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
-									 NULL, NULL, 0);
+									 NULL, NULL, NULL, NULL, 0);
 	}
 	else
 	{
@@ -117,7 +117,8 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
 		status_t status;
 
 		status = charon->controller->initiate(charon->controller,
-							peer_cfg, child_cfg, (controller_cb_t)stroke_log,
+							peer_cfg, child_cfg, NULL, NULL,
+							(controller_cb_t)stroke_log,
 							&info, this->timeout);
 		switch (status)
 		{
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index d232599..3c4e3ec 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -1558,7 +1558,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
 			DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
 			charon->controller->initiate(charon->controller,
 					peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
-					NULL, NULL, 0);
+					NULL, NULL, NULL, NULL, 0);
 			break;
 		case ACTION_ROUTE:
 			DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 01d5036..a99c309 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "vici_control.h"
 #include "vici_builder.h"
 
@@ -159,9 +181,11 @@ static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
 CALLBACK(initiate, vici_message_t*,
 	private_vici_control_t *this, char *name, u_int id, vici_message_t *request)
 {
+	vici_message_t* msg;
 	child_cfg_t *child_cfg = NULL;
 	peer_cfg_t *peer_cfg;
-	char *child;
+	host_t *my_host = NULL, *other_host = NULL;
+	char *child, *my_host_str, *other_host_str;
 	u_int timeout;
 	log_info_t log = {
 		.dispatcher = this->dispatcher,
@@ -171,31 +195,51 @@ CALLBACK(initiate, vici_message_t*,
 	child = request->get_str(request, NULL, "child");
 	timeout = request->get_int(request, 0, "timeout");
 	log.level = request->get_int(request, 1, "loglevel");
+	my_host_str = request->get_str(request, NULL, "my-host");
+	other_host_str = request->get_str(request, NULL, "other-host");
 
 	if (!child)
 	{
 		return send_reply(this, "missing configuration name");
 	}
 
-	DBG1(DBG_CFG, "vici initiate '%s'", child);
+	if (my_host_str)
+	{
+		my_host = host_create_from_string(my_host_str, 0);
+	}
+	if (other_host_str)
+	{
+		other_host = host_create_from_string(other_host_str, 0);
+	}
+
+	DBG1(DBG_CFG, "vici initiate '%s', me %H, other %H", child, my_host, other_host);
 
 	child_cfg = find_child_cfg(child, &peer_cfg);
 	if (!child_cfg)
 	{
-		return send_reply(this, "CHILD_SA config '%s' not found", child);
+		msg = send_reply(this, "CHILD_SA config '%s' not found", child);
+		goto ret;
 	}
 	switch (charon->controller->initiate(charon->controller,
-				peer_cfg, child_cfg, (controller_cb_t)log_vici, &log, timeout))
+				peer_cfg, child_cfg, my_host, other_host,
+				(controller_cb_t)log_vici, &log, timeout))
 	{
 		case SUCCESS:
-			return send_reply(this, NULL);
+			msg = send_reply(this, NULL);
+			break;
 		case OUT_OF_RES:
-			return send_reply(this, "CHILD_SA '%s' not established after %dms",
+			msg = send_reply(this, "CHILD_SA '%s' not established after %dms",
 							  child, timeout);
+			break;
 		case FAILED:
 		default:
-			return send_reply(this, "establishing CHILD_SA '%s' failed", child);
+			msg = send_reply(this, "establishing CHILD_SA '%s' failed", child);
+			break;
 	}
+ret:
+	if (my_host) my_host->destroy(my_host);
+	if (other_host) other_host->destroy(other_host);
+	return msg;
 }
 
 CALLBACK(terminate, vici_message_t*,
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index 981473b..fd42f3b 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -61,7 +61,7 @@ METHOD(job_t, execute, job_requeue_t,
 					charon->controller->initiate(charon->controller,
 												 peer_cfg->get_ref(peer_cfg),
 												 child_cfg->get_ref(child_cfg),
-												 NULL, NULL, 0);
+												 NULL, NULL, NULL, NULL, 0);
 					break;
 				case ACTION_ROUTE:
 					DBG1(DBG_JOB, "start action: route '%s'", name);
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 94cf07c..ddc7090 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #define _GNU_SOURCE
 #include "child_sa.h"
 
@@ -147,6 +169,11 @@ struct private_child_sa_t {
 	bool trap;
 
 	/**
+	 * TRUE if this CHILD_SA should get routed
+	 */
+	bool install_policy;
+
+	/**
 	 * Specifies if UDP encapsulation is enabled (NAT traversal)
 	 */
 	bool encap;
@@ -856,7 +883,20 @@ METHOD(child_sa_t, add_policies, status_t,
 	enumerator->destroy(enumerator);
 	array_sort(this->other_ts, (void*)traffic_selector_cmp, NULL);
 
-	if (this->config->install_policy(this->config))
+	/* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
+	 * entry) we install a trap policy */
+	this->trap = this->state == CHILD_CREATED;
+
+	/* install policy if so requested in config. with the exception
+	 * that transport mode wildcard SAs do not need policy if a trap
+	 * policy exists. */
+	this->install_policy =
+		this->config->install_policy(this->config) &&
+		(this->trap ||
+		 this->mode != MODE_TRANSPORT ||
+		 this->config->get_start_action(this->config) != ACTION_ROUTE);
+
+	if (this->install_policy)
 	{
 		policy_priority_t priority;
 		ipsec_sa_cfg_t my_sa = {
@@ -885,9 +925,6 @@ METHOD(child_sa_t, add_policies, status_t,
 			other_sa.ah.spi = this->other_spi;
 		}
 
-		/* if we're not in state CHILD_INSTALLING (i.e. if there is no SAD
-		 * entry) we install a trap policy */
-		this->trap = this->state == CHILD_CREATED;
 		priority = this->trap ? POLICY_PRIORITY_ROUTED
 							  : POLICY_PRIORITY_DEFAULT;
 
@@ -999,7 +1036,7 @@ METHOD(child_sa_t, update, status_t,
 		}
 	}
 
-	if (this->config->install_policy(this->config) && require_policy_update())
+	if (this->install_policy && require_policy_update())
 	{
 		ipsec_sa_cfg_t my_sa = {
 			.mode = this->mode,
@@ -1115,7 +1152,7 @@ METHOD(child_sa_t, destroy, void,
 
 	set_state(this, CHILD_DESTROYING);
 
-	if (this->config->install_policy(this->config))
+	if (this->install_policy)
 	{
 		/* delete all policies in the kernel */
 		enumerator = create_policy_enumerator(this);
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 3aafa4c..dcd54a1 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1208,6 +1208,10 @@ static void resolve_hosts(private_ike_sa_t *this)
 	else
 	{
 		host = this->ike_cfg->resolve_other(this->ike_cfg, family);
+		if (host->is_anyaddr(host))
+		{
+			host = NULL;
+		}
 	}
 	if (host)
 	{
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 938f784..18ea778 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -16,6 +16,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include <string.h>
 
 #include "ike_sa_manager.h"
@@ -1328,16 +1350,28 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*,
 }
 
 METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
-	private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg)
+	private_ike_sa_manager_t *this, peer_cfg_t *peer_cfg,
+	host_t *my_host, host_t *other_host)
 {
 	enumerator_t *enumerator;
 	entry_t *entry;
-	ike_sa_t *ike_sa = NULL;
+	ike_sa_t *ike_sa;
 	peer_cfg_t *current_peer;
 	ike_cfg_t *current_ike;
 	u_int segment;
+	bool matched = FALSE;
 
-	DBG2(DBG_MGR, "checkout IKE_SA by config");
+	if (my_host && my_host->get_port(my_host) == 0)
+	{
+		my_host->set_port(my_host, IKEV2_UDP_PORT);
+	}
+	if (other_host && other_host->get_port(other_host) == 0)
+	{
+		other_host->set_port(other_host, IKEV2_UDP_PORT);
+	}
+
+	DBG2(DBG_MGR, "checkout IKE_SA by config '%s', me %H, other %H",
+		 peer_cfg->get_name(peer_cfg), my_host, other_host);
 
 	if (!this->reuse_ikesa)
 	{	/* IKE_SA reuse disable by config */
@@ -1358,14 +1392,24 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 			continue;
 		}
 
-		current_peer = entry->ike_sa->get_peer_cfg(entry->ike_sa);
+		ike_sa = entry->ike_sa;
+		if (my_host && !my_host->ip_equals(my_host, ike_sa->get_my_host(ike_sa)))
+		{
+			continue;
+		}
+		if (other_host && !other_host->ip_equals(other_host, ike_sa->get_other_host(ike_sa)))
+		{
+			continue;
+		}
+
+		current_peer = ike_sa->get_peer_cfg(ike_sa);
 		if (current_peer && current_peer->equals(current_peer, peer_cfg))
 		{
 			current_ike = current_peer->get_ike_cfg(current_peer);
 			if (current_ike->equals(current_ike, peer_cfg->get_ike_cfg(peer_cfg)))
 			{
 				entry->checked_out = TRUE;
-				ike_sa = entry->ike_sa;
+				matched = TRUE;
 				DBG2(DBG_MGR, "found existing IKE_SA %u with a '%s' config",
 						ike_sa->get_unique_id(ike_sa),
 						current_peer->get_name(current_peer));
@@ -1375,9 +1419,13 @@ METHOD(ike_sa_manager_t, checkout_by_config, ike_sa_t*,
 	}
 	enumerator->destroy(enumerator);
 
-	if (!ike_sa)
+	if (!matched)
 	{	/* no IKE_SA using such a config, hand out a new */
 		ike_sa = checkout_new(this, peer_cfg->get_ike_version(peer_cfg), TRUE);
+		if (my_host || other_host)
+		{
+			ike_sa->update_hosts(ike_sa, my_host, other_host, TRUE);
+		}
 	}
 	charon->bus->set_sa(charon->bus, ike_sa);
 	return ike_sa;
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index f259d8e..5a69083 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -83,7 +83,8 @@ struct ike_sa_manager_t {
 	ike_sa_t* (*checkout_by_message) (ike_sa_manager_t* this, message_t *message);
 
 	/**
-	 * Checkout an IKE_SA for initiation by a peer_config.
+	 * Checkout an IKE_SA for initiation by a peer_config and optional
+	 * source and remote host addresses.
 	 *
 	 * To initiate, a CHILD_SA may be established within an existing IKE_SA.
 	 * This call checks for an existing IKE_SA by comparing the configuration.
@@ -93,10 +94,13 @@ struct ike_sa_manager_t {
 	 * the found IKE_SA is in the DELETING state.
 	 *
 	 * @param peer_cfg			configuration used to find an existing IKE_SA
+	 * @param my_host			source host address for wildcard peer_cfg
+	 * @param other_host		remote host address for wildcard peer_cfg
 	 * @return					checked out/created IKE_SA
 	 */
 	ike_sa_t* (*checkout_by_config) (ike_sa_manager_t* this,
-									 peer_cfg_t *peer_cfg);
+									 peer_cfg_t *peer_cfg,
+									 host_t *my_host, host_t *other_host);
 
 	/**
 	 * Check for duplicates of the given IKE_SA.
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 7a5ff07..98ee000 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -14,6 +14,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "trap_manager.h"
 
 #include <hydra.h>
@@ -67,6 +89,11 @@ struct private_trap_manager_t {
 	trap_listener_t listener;
 
 	/**
+	 * Whether to ignore traffic selectors from acquires
+	 */
+	bool ignore_acquire_ts;
+
+	/**
 	 * list of acquires we currently handle
 	 */
 	linked_list_t *acquires;
@@ -75,11 +102,6 @@ struct private_trap_manager_t {
 	 * mutex for list of acquires
 	 */
 	mutex_t *mutex;
-
-	/**
-	 * Whether to ignore traffic selectors from acquires
-	 */
-	bool ignore_acquire_ts;
 };
 
 /**
@@ -92,6 +114,8 @@ typedef struct {
 	peer_cfg_t *peer_cfg;
 	/** ref to instantiated CHILD_SA (i.e the trap policy) */
 	child_sa_t *child_sa;
+	/** TRUE in case of wildcard Transport Mode SA */
+	bool wildcard;
 } entry_t;
 
 /**
@@ -102,6 +126,10 @@ typedef struct {
 	ike_sa_t *ike_sa;
 	/** reqid of pending trap policy */
 	u_int32_t reqid;
+	/** source address (wildcard case) */
+	host_t *src;
+	/** destination address (wildcard case) */
+	host_t *dst;
 } acquire_t;
 
 /**
@@ -120,6 +148,8 @@ static void destroy_entry(entry_t *this)
  */
 static void destroy_acquire(acquire_t *this)
 {
+	DESTROY_IF(this->src);
+	DESTROY_IF(this->dst);
 	free(this);
 }
 
@@ -131,6 +161,15 @@ static bool acquire_by_reqid(acquire_t *this, u_int32_t *reqid)
 	return this->reqid == *reqid;
 }
 
+/**
+ * match an acquire entry by destination address
+ */
+static bool acquire_by_acquire(acquire_t *this, acquire_t *that)
+{
+	return this->src && this->src->ip_equals(this->src, that->src) &&
+		   this->dst && this->dst->ip_equals(this->dst, that->dst);
+}
+
 METHOD(trap_manager_t, install, u_int32_t,
 	private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
 	u_int32_t reqid)
@@ -145,29 +184,40 @@ METHOD(trap_manager_t, install, u_int32_t,
 	linked_list_t *proposals;
 	proposal_t *proposal;
 	protocol_id_t proto = PROTO_ESP;
+	bool wildcard = FALSE;
 
 	/* try to resolve addresses */
 	ike_cfg = peer->get_ike_cfg(peer);
 	other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
-	if (!other || other->is_anyaddr(other))
+	if (other && other->is_anyaddr(other) &&
+		child->get_mode(child) == MODE_TRANSPORT)
+	{
+		/* allow wildcard for Transport Mode SAs */
+		me = host_create_any(other->get_family(other));
+		wildcard = TRUE;
+	}
+	else if (!other || other->is_anyaddr(other))
 	{
 		DESTROY_IF(other);
 		DBG1(DBG_CFG, "installing trap failed, remote address unknown");
 		return 0;
 	}
-	me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
-	if (!me || me->is_anyaddr(me))
+	else
 	{
-		DESTROY_IF(me);
-		me = hydra->kernel_interface->get_source_addr(
-									hydra->kernel_interface, other, NULL);
-		if (!me)
+		me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
+		if (!me || me->is_anyaddr(me))
 		{
-			DBG1(DBG_CFG, "installing trap failed, local address unknown");
-			other->destroy(other);
-			return 0;
+			DESTROY_IF(me);
+			me = hydra->kernel_interface->get_source_addr(
+										hydra->kernel_interface, other, NULL);
+			if (!me)
+			{
+				DBG1(DBG_CFG, "installing trap failed, local address unknown");
+				other->destroy(other);
+				return 0;
+			}
+			me->set_port(me, ike_cfg->get_my_port(ike_cfg));
 		}
-		me->set_port(me, ike_cfg->get_my_port(ike_cfg));
 	}
 
 	this->lock->write_lock(this->lock);
@@ -202,6 +252,7 @@ METHOD(trap_manager_t, install, u_int32_t,
 	INIT(entry,
 		.name = strdup(child->get_name(child)),
 		.peer_cfg = peer->get_ref(peer),
+		.wildcard = wildcard,
 	);
 	this->traps->insert_first(this->traps, entry);
 	/* don't hold lock while creating CHILD_SA and installing policies */
@@ -350,6 +401,8 @@ METHOD(trap_manager_t, acquire, void,
 	peer_cfg_t *peer;
 	child_cfg_t *child;
 	ike_sa_t *ike_sa;
+	host_t *src_host, *dst_host;
+	bool wildcard, ignore = FALSE;
 
 	this->lock->read_lock(this->lock);
 	enumerator = this->traps->create_enumerator(this->traps);
@@ -366,15 +419,64 @@ METHOD(trap_manager_t, acquire, void,
 
 	if (!found)
 	{
-		DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d",reqid);
+		DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
 		this->lock->unlock(this->lock);
 		return;
 	}
 	reqid = found->child_sa->get_reqid(found->child_sa);
+	wildcard = found->wildcard;
 
 	this->mutex->lock(this->mutex);
-	if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
-								  (void**)&acquire, &reqid) == SUCCESS)
+	if (wildcard)
+	{	/* for wildcard acquires we check that we don't have a pending acquire
+		* with the same peer */
+		u_int8_t mask;
+
+		src->to_subnet(src, &src_host, &mask);
+		dst->to_subnet(dst, &dst_host, &mask);
+
+		acquire_t match = {
+			.src = src_host,
+			.dst = dst_host,
+		};
+
+		if (this->acquires->find_first(this->acquires, (void*)acquire_by_acquire,
+										(void**)&acquire, &match) == SUCCESS)
+		{
+			src_host->destroy(src_host);
+			dst_host->destroy(dst_host);
+			ignore = TRUE;
+		}
+		else
+		{
+			INIT(acquire,
+				.src = src_host->clone(src_host),
+				.dst = dst_host->clone(dst_host),
+				/* store the original reqid to remove the temporary SA later */
+				.reqid = reqid,
+			);
+			this->acquires->insert_last(this->acquires, acquire);
+			/* we have to allocate a new reqid for each instance */
+			reqid = 0;
+		}
+	}
+	else
+	{
+		if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
+										(void**)&acquire, &reqid) == SUCCESS)
+		{
+			ignore = TRUE;
+		}
+		else
+		{
+			INIT(acquire,
+				.reqid = reqid,
+			);
+			this->acquires->insert_last(this->acquires, acquire);
+		}
+	}
+
+	if (ignore)
 	{
 		DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
 		this->mutex->unlock(this->mutex);
@@ -397,7 +499,11 @@ METHOD(trap_manager_t, acquire, void,
 	this->lock->unlock(this->lock);
 
 	ike_sa = charon->ike_sa_manager->checkout_by_config(
-											charon->ike_sa_manager, peer);
+											charon->ike_sa_manager, peer,
+											src_host, dst_host);
+	DESTROY_IF(src_host);
+	DESTROY_IF(dst_host);
+
 	if (ike_sa)
 	{
 		if (ike_sa->get_peer_cfg(ike_sa) == NULL)
@@ -416,6 +522,9 @@ METHOD(trap_manager_t, acquire, void,
 
 		if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
 		{
+			this->mutex->lock(this->mutex);
+			acquire->ike_sa = ike_sa;
+			this->mutex->unlock(this->mutex);
 			charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
 		}
 		else
@@ -436,6 +545,46 @@ METHOD(trap_manager_t, acquire, void,
 }
 
 /**
+ * If right=%any is used every SA gets its own reqid different from the reqid
+ * of the trap policy.  Before such an SA is installed, that is, whenever
+ * traffic matches the trap policy, the kernel will allocate a temporary SA to
+ * block the traffic and keep track of acquires.  This function deletes such a
+ * temporary SA after the final SA got installed by pretending that an SA was
+ * established for the trap policy (with its reqid) and then deleting that SA
+ * immediately afterwards (the temporary SA can't be deleted directly as it has
+ * no SPI)
+ */
+static void delete_temporary_sa(ike_sa_t *ike_sa, child_sa_t *child_sa,
+								acquire_t *acquire)
+{
+	lifetime_cfg_t lifetime = { .time = { .life = 0 } };
+	mark_t mark = { .value = 0 };
+	host_t *me, *other;
+	u_int32_t spi;
+	rng_t *rng;
+
+	rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
+	if (!rng || !rng->get_bytes(rng, sizeof(spi), (u_int8_t*)&spi))
+	{
+		DBG1(DBG_CFG, "failed to allocate random SPI to delete temporary SA");
+		DESTROY_IF(rng);
+		return;
+	}
+	rng->destroy(rng);
+
+	other = ike_sa->get_other_host(ike_sa);
+	me = ike_sa->get_my_host(ike_sa);
+
+	hydra->kernel_interface->add_sa(hydra->kernel_interface, me, other, spi,
+							IPPROTO_ESP, acquire->reqid, mark, 0, &lifetime,
+							ENCR_NULL, chunk_empty, AUTH_UNDEFINED, chunk_empty,
+							MODE_TRANSPORT, IPCOMP_NONE, 0, 0, TRUE, FALSE, FALSE,
+							FALSE, FALSE, NULL, NULL);
+	hydra->kernel_interface->del_sa(hydra->kernel_interface, me, other, spi,
+									IPPROTO_ESP, 0, mark);
+}
+
+/**
  * Complete the acquire, if successful or failed
  */
 static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
@@ -454,7 +603,15 @@ static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
 		}
 		if (child_sa && child_sa->get_reqid(child_sa) != acquire->reqid)
 		{
-			continue;
+			if (acquire->dst)
+			{	/* since every wildcard acquire results in a separate IKE_SA
+				 * there is no need to compare the destination address */
+				delete_temporary_sa(ike_sa, child_sa, acquire);
+			}
+			else if (child_sa->get_reqid(child_sa) != acquire->reqid)
+			{
+				continue;
+			}
 		}
 		this->acquires->remove_at(this->acquires, enumerator);
 		destroy_acquire(acquire);
diff --git a/src/swanctl/commands/initiate.c b/src/swanctl/commands/initiate.c
index eb7b6ad..7887785 100644
--- a/src/swanctl/commands/initiate.c
+++ b/src/swanctl/commands/initiate.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "command.h"
 
 #include <errno.h>
@@ -37,7 +59,7 @@ static int initiate(vici_conn_t *conn)
 	vici_req_t *req;
 	vici_res_t *res;
 	command_format_options_t format = COMMAND_FORMAT_NONE;
-	char *arg, *child = NULL;
+	char *arg, *child = NULL, *my_host = NULL, *other_host = NULL;
 	int ret = 0, timeout = 0, level = 1;
 
 	while (TRUE)
@@ -61,6 +83,12 @@ static int initiate(vici_conn_t *conn)
 			case 'l':
 				level = atoi(arg);
 				continue;
+			case 'S':
+				my_host = arg;
+				continue;
+			case 'R':
+				other_host = arg;
+				continue;
 			case EOF:
 				break;
 			default:
@@ -80,6 +108,14 @@ static int initiate(vici_conn_t *conn)
 	{
 		vici_add_key_valuef(req, "child", "%s", child);
 	}
+	if (my_host)
+	{
+		vici_add_key_valuef(req, "my-host", "%s", my_host);
+	}
+	if (other_host)
+	{
+		vici_add_key_valuef(req, "other-host", "%s", other_host);
+	}
 	if (timeout)
 	{
 		vici_add_key_valuef(req, "timeout", "%d", timeout * 1000);
@@ -125,6 +161,8 @@ static void __attribute__ ((constructor))reg()
 		{
 			{"help",		'h', 0, "show usage information"},
 			{"child",		'c', 1, "initate a CHILD_SA configuration"},
+			{"source",		'S', 1, "override source address"},
+			{"remote",		'R', 1, "override remote address"},
 			{"timeout",		't', 1, "timeout in seconds before detaching"},
 			{"raw",			'r', 0, "dump raw response message"},
 			{"pretty",		'P', 0, "dump raw response message in pretty print"},
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index 98ee000..6deb4ee 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -170,6 +170,33 @@ static bool acquire_by_acquire(acquire_t *this, acquire_t *that)
 		   this->dst && this->dst->ip_equals(this->dst, that->dst);
 }
 
+/*
+ * derived from host_create_from_subnet, but with different return semantics
+ *  intended to parse a single CIDR formatted subnet string, returning host
+ *  address structure and mask (in bits). 
+ * Returns NULL if no subnet was supplied by the string
+ */
+static
+host_t *trapmanager_host_create_from_subnet(char *string, int *bits)
+{
+	char *pos, buf[64];
+
+	pos = strchr(string, '/');
+	if (pos)
+	{
+		if (pos - string >= sizeof(buf))
+		{
+			return NULL;
+		}
+		strncpy(buf, string, pos - string);
+		buf[pos - string] = '\0';
+		*bits = atoi(pos + 1);
+		return host_create_from_string(buf, 0);
+	} else {
+                return NULL;
+        }
+}
+
 METHOD(trap_manager_t, install, u_int32_t,
 	private_trap_manager_t *this, peer_cfg_t *peer, child_cfg_t *child,
 	u_int32_t reqid)
@@ -177,7 +204,9 @@ METHOD(trap_manager_t, install, u_int32_t,
 	entry_t *entry, *found = NULL;
 	ike_cfg_t *ike_cfg;
 	child_sa_t *child_sa;
-	host_t *me, *other;
+	host_t *me = NULL;
+	host_t *other = NULL;
+	host_t *subnet = NULL;
 	linked_list_t *my_ts, *other_ts, *list;
 	enumerator_t *enumerator;
 	status_t status;
@@ -185,6 +214,7 @@ METHOD(trap_manager_t, install, u_int32_t,
 	proposal_t *proposal;
 	protocol_id_t proto = PROTO_ESP;
 	bool wildcard = FALSE;
+	int bits = 0;
 
 	/* try to resolve addresses */
 	ike_cfg = peer->get_ike_cfg(peer);
@@ -192,9 +222,23 @@ METHOD(trap_manager_t, install, u_int32_t,
 	if (other && other->is_anyaddr(other) &&
 		child->get_mode(child) == MODE_TRANSPORT)
 	{
-		/* allow wildcard for Transport Mode SAs */
-		me = host_create_any(other->get_family(other));
-		wildcard = TRUE;
+                /* allow wildcard for Transport Mode SAs */
+	        subnet = trapmanager_host_create_from_subnet(ike_cfg->get_other_addr(ike_cfg),&bits);
+                if (subnet) {
+		        DBG2(DBG_CFG, "creating subnet trap");
+                        other = subnet;
+		        me = hydra->kernel_interface->get_source_addr(
+								  hydra->kernel_interface, other, NULL);
+
+                        wildcard = TRUE;
+			if (me) {
+			  me->set_port(me, ike_cfg->get_my_port(ike_cfg));
+			}
+                } else {
+                        DBG2(DBG_CFG, "creating trap for any address");
+                        me = host_create_any(other->get_family(other));
+                        wildcard = TRUE;
+                }
 	}
 	else if (!other || other->is_anyaddr(other))
 	{
@@ -213,13 +257,19 @@ METHOD(trap_manager_t, install, u_int32_t,
 			if (!me)
 			{
 				DBG1(DBG_CFG, "installing trap failed, local address unknown");
-				other->destroy(other);
+				if (other) {
+				  other->destroy(other);
+				}
 				return 0;
 			}
 			me->set_port(me, ike_cfg->get_my_port(ike_cfg));
 		}
 	}
 
+	if (!me) {
+	  return SUCCESS;
+	}
+
 	this->lock->write_lock(this->lock);
 	enumerator = this->traps->create_enumerator(this->traps);
 	while (enumerator->enumerate(enumerator, &entry))
@@ -265,9 +315,15 @@ METHOD(trap_manager_t, install, u_int32_t,
 	my_ts = child->get_traffic_selectors(child, TRUE, NULL, list);
 	list->destroy_offset(list, offsetof(host_t, destroy));
 
-	list = linked_list_create_with_items(other, NULL);
-	other_ts = child->get_traffic_selectors(child, FALSE, NULL, list);
-	list->destroy_offset(list, offsetof(host_t, destroy));
+	if (!wildcard || (0 == bits)) {
+	  list = linked_list_create_with_items(other, NULL);
+	  other_ts = child->get_traffic_selectors(child, FALSE, NULL, list);
+	  list->destroy_offset(list, offsetof(host_t, destroy));
+	} else {
+	  traffic_selector_t *subnet_ts = traffic_selector_create_from_subnet(other, bits, 0, 0, 65535);
+	  DBG1(DBG_CFG, "created subnet traffic selector %R",subnet_ts);
+	  other_ts = linked_list_create_with_items(subnet_ts, NULL);
+	}
 
 	/* We don't know the finally negotiated protocol (ESP|AH), we install
 	 * the SA with the protocol of the first proposal */
@@ -400,8 +456,8 @@ METHOD(trap_manager_t, acquire, void,
 	acquire_t *acquire;
 	peer_cfg_t *peer;
 	child_cfg_t *child;
-	ike_sa_t *ike_sa;
-	host_t *src_host, *dst_host;
+	ike_sa_t *ike_sa = NULL;
+	host_t *src_host = NULL, *dst_host = NULL;
 	bool wildcard, ignore = FALSE;
 
 	this->lock->read_lock(this->lock);
@@ -435,6 +491,10 @@ METHOD(trap_manager_t, acquire, void,
 		src->to_subnet(src, &src_host, &mask);
 		dst->to_subnet(dst, &dst_host, &mask);
 
+                /* necessary to ensure that the IKE ports are set correctly */
+		src_host->set_port(src_host,0);
+		dst_host->set_port(dst_host,0);
+
 		acquire_t match = {
 			.src = src_host,
 			.dst = dst_host,
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index f22e07d..67b3710 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1252,8 +1252,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 				 * selector can be installed other traffic would get dropped */
 				break;
 			}
-			if (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS &&
-				dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS)
+			if ((src_ts && (src_ts->get_first(src_ts, (void**)&first_src_ts) == SUCCESS)) &&
+			    (dst_ts && (dst_ts->get_first(dst_ts, (void**)&first_dst_ts) == SUCCESS)))
 			{
 				sa->sel = ts2selector(first_src_ts, first_dst_ts);
 				if (!this->proto_port_transport)
_______________________________________________
Dev mailing list
[email protected]
https://lists.strongswan.org/mailman/listinfo/dev

Reply via email to