Source: strongswan
Version: 5.0.4-3
Severity: wishlist

Hello Yves-Alexis and Rene, per private email discussion you asked that
I submit feature requests through the BTS.

Please enable the ‘unity’ plugin, including patches from upstream bugs
356¹ and 366².  This plugin allows for strongSwan to interop with Cisco
equipment, particularly the Split-Include, Split-Exclude, and
Split-Local-LAN attributes.  This plugin is marked as stable according
to the PluginList³ wiki and doesn't require any additional build
dependencies.

Without the plugin, I can still connect to this particular Cisco gear
(that's out of my control), but the traffic selector is 0.0.0.0/0 - much
too wide.  With the plugin the traffic selectors are narrowed to a list
of subnets returned by the Split-Include attribute.  However without the
patches, the plugin can only interpret a single subnet.  Patch in bug
356 causes any failure to parse these attributes to revert from selector
0.0.0.0/0 to the selector specified in rightsubnet.

The patch in bug 366 supercedes one of the two patches in bug 356 with
label ‘0001-unity-Allow-UNITY_LOCAL_LAN-to-be-longer-than-8-byte.patch’.

Attached are my modifications to package version 5.0.4-3 in experimental
using quilt.

¹ https://wiki.strongswan.org/issues/356
² https://wiki.strongswan.org/issues/366
³ https://wiki.strongswan.org/projects/strongswan/wiki/PluginList

-- System Information:
Debian Release: 7.1
  APT prefers stable
  APT policy: (500, 'stable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.9-0.bpo.1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) (ignored: LC_ALL 
set to en_US.UTF-8)
Shell: /bin/sh linked to /bin/dash

-- 
Gerald Turner   Email: gtur...@unzane.com   JID: gtur...@unzane.com
GPG: 0xFA8CD6D5  21D9 B2E8 7FE7 F19E 5F7D  4D0C 3FA0 810F FA8C D6D5
diff -urN strongswan-5.0.4.orig/debian/changelog strongswan-5.0.4/debian/changelog
--- strongswan-5.0.4.orig/debian/changelog	2013-05-18 00:26:23.000000000 -0700
+++ strongswan-5.0.4/debian/changelog	2013-07-29 09:52:34.000000000 -0700
@@ -1,3 +1,61 @@
+strongswan (5.0.4-3.6) stable; urgency=low
+
+  * Refreshed patch from http://wiki.strongswan.org/issues/356
+  * Disabled several configuration options that were enabled in 5.0.4-3.2
+    that I am unable to test
+
+ -- Gerald Turner <gtur...@unzane.com>  Mon, 29 Jul 2013 09:51:23 -0700
+
+strongswan (5.0.4-3.5) stable; urgency=low
+
+  * Apply patch from http://wiki.strongswan.org/issues/356
+
+ -- Gerald Turner <gtur...@unzane.com>  Fri, 26 Jul 2013 09:39:11 -0700
+
+strongswan (5.0.4-3.4) stable; urgency=low
+
+  * Apply additional patch from http://wiki.strongswan.org/issues/356
+
+ -- Gerald Turner <gtur...@unzane.com>  Thu, 25 Jul 2013 13:10:57 -0700
+
+strongswan (5.0.4-3.3) stable; urgency=low
+
+  * Disable --with-user to fix various permission errors (e.g. resolvconf
+    doesn't work when run as strongswan user)
+  * Apply patch from http://wiki.strongswan.org/issues/356 to fix bug with
+    unity plugin: apparently Cisco can return more than one subnet in a
+    single attribute
+
+ -- Gerald Turner <gtur...@unzane.com>  Thu, 25 Jul 2013 12:38:33 -0700
+
+strongswan (5.0.4-3.2) stable; urgency=low
+
+  * Install plugins that were enabled (but not installed) in previous
+    build
+  * Enable many more configure flags
+
+ -- Gerald Turner <gtur...@unzane.com>  Fri, 28 Jun 2013 13:48:36 -0700
+
+strongswan (5.0.4-3.1) stable; urgency=low
+
+  * Backport from experimental
+  * Fix dh_install --list-missing (See #692606)
+  * Add ./configure options:
+      --enable-duplicheck
+      --enable-error-notify
+      --enable-ipseckey
+      --enable-lookip
+      --enable-sqlite
+      --enable-systime-fix
+      --enable-unbound
+      --enable-unity
+      --enable-whitelist
+      --with-user=strongswan
+      --with-group=nogroup
+  * Add dependencies on libsqlite3-dev, libunbound-dev, libldns-dev
+
+ -- Gerald Turner <gtur...@unzane.com>  Wed, 19 Jun 2013 14:08:10 -0700
+
 strongswan (5.0.4-3) experimental; urgency=low
 
   * debian/rules, debian/libstrongswan.install:
diff -urN strongswan-5.0.4.orig/debian/control strongswan-5.0.4/debian/control
--- strongswan-5.0.4.orig/debian/control	2013-05-17 23:25:36.000000000 -0700
+++ strongswan-5.0.4/debian/control	2013-07-29 09:53:23.000000000 -0700
@@ -12,7 +12,8 @@
   hardening-wrapper, libfcgi-dev, clearsilver-dev,
   libxml2-dev, libsqlite3-dev, network-manager-dev (>= 0.7) [linux-any], 
   libnm-glib-vpn-dev (>= 0.7) [linux-any], libnm-util-dev (>= 0.7) [linux-any], 
-  gperf, libcap-dev [linux-any]
+  gperf, libcap-dev [linux-any], libmysqlclient-dev, libunbound-dev,
+  libldns-dev
 Homepage: http://www.strongswan.org
 
 Package: strongswan
diff -urN strongswan-5.0.4.orig/debian/libstrongswan.install strongswan-5.0.4/debian/libstrongswan.install
--- strongswan-5.0.4.orig/debian/libstrongswan.install	2013-05-17 23:29:13.000000000 -0700
+++ strongswan-5.0.4/debian/libstrongswan.install	2013-07-29 10:12:25.000000000 -0700
@@ -48,4 +48,16 @@
 usr/lib/ipsec/plugins/libstrongswan-xauth-eap.so
 usr/lib/ipsec/plugins/libstrongswan-xauth-generic.so
 usr/lib/ipsec/plugins/libstrongswan-xauth-pam.so
+usr/lib/ipsec/plugins/libstrongswan-af-alg.so
+usr/lib/ipsec/plugins/libstrongswan-certexpire.so
+usr/lib/ipsec/plugins/libstrongswan-coupling.so
+usr/lib/ipsec/plugins/libstrongswan-duplicheck.so
+usr/lib/ipsec/plugins/libstrongswan-error-notify.so
+usr/lib/ipsec/plugins/libstrongswan-ipseckey.so
+usr/lib/ipsec/plugins/libstrongswan-lookip.so
+usr/lib/ipsec/plugins/libstrongswan-mysql.so
+usr/lib/ipsec/plugins/libstrongswan-sqlite.so
+usr/lib/ipsec/plugins/libstrongswan-unbound.so
+usr/lib/ipsec/plugins/libstrongswan-unity.so
+usr/lib/ipsec/plugins/libstrongswan-whitelist.so
 etc/strongswan.conf
diff -urN strongswan-5.0.4.orig/debian/patches/series strongswan-5.0.4/debian/patches/series
--- strongswan-5.0.4.orig/debian/patches/series	2013-05-17 23:25:36.000000000 -0700
+++ strongswan-5.0.4/debian/patches/series	2013-07-29 09:57:29.000000000 -0700
@@ -1 +1,3 @@
 01_fix-manpages.patch
+unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch
+unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch
diff -urN strongswan-5.0.4.orig/debian/patches/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch strongswan-5.0.4/debian/patches/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch
--- strongswan-5.0.4.orig/debian/patches/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch	1969-12-31 16:00:00.000000000 -0800
+++ strongswan-5.0.4/debian/patches/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch	2013-07-29 09:58:03.000000000 -0700
@@ -0,0 +1,265 @@
+Description: Make unity plugin capable of parsing multiple subnets in a single attribute
+Origin: http://wiki.strongswan.org/issues/366
+Author: Tobias Brunner <tob...@strongswan.org>
+Reviewed-By: Gerald Turner <gtur...@unzane.com>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_handler.c
++++ strongswan-5.0.4/src/libcharon/plugins/unity/unity_handler.c
+@@ -1,4 +1,7 @@
+ /*
++ * Copyright (C) 2013 Tobias Brunner
++ * Hochschule fuer Technik Rapperswil
++ *
+  * Copyright (C) 2012 Martin Willi
+  * Copyright (C) 2012 revosec AG
+  *
+@@ -70,12 +73,8 @@ static traffic_selector_t *create_ts(chu
+ 	chunk_t net, mask;
+ 	int i;
+ 
+-	if (subnet.len != 8)
+-	{
+-		return NULL;
+-	}
+ 	net = chunk_create(subnet.ptr, 4);
+-	mask = chunk_clonea(chunk_skip(subnet, 4));
++	mask = chunk_clonea(chunk_create(subnet.ptr + 4, 4));
+ 	for (i = 0; i < net.len; i++)
+ 	{
+ 		mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i];
+@@ -85,11 +84,37 @@ static traffic_selector_t *create_ts(chu
+ }
+ 
+ /**
+- * Store a subnet to include in tunnels under this IKE_SA
++ * Parse a unity attribute and extract all subnets as traffic selectors
++ */
++static linked_list_t *parse_subnets(chunk_t data)
++{
++	linked_list_t *list = NULL;
++	traffic_selector_t *ts;
++
++	while (data.len >= 8)
++	{	/* the padding is optional */
++		ts = create_ts(data);
++		if (ts)
++		{
++			if (!list)
++			{
++				list = linked_list_create();
++			}
++			list->insert_last(list, ts);
++		}
++		/* skip address, mask and 6 bytes of padding */
++		data = chunk_skip(data, 14);
++	}
++	return list;
++}
++
++/**
++ * Store a list of subnets to include in tunnels under this IKE_SA
+  */
+-static bool add_include(private_unity_handler_t *this, chunk_t subnet)
++static bool add_include(private_unity_handler_t *this, chunk_t data)
+ {
+ 	traffic_selector_t *ts;
++	linked_list_t *list;
+ 	ike_sa_t *ike_sa;
+ 	entry_t *entry;
+ 
+@@ -98,29 +123,34 @@ static bool add_include(private_unity_ha
+ 	{
+ 		return FALSE;
+ 	}
+-	ts = create_ts(subnet);
+-	if (!ts)
++	list = parse_subnets(data);
++	if (!list)
+ 	{
+ 		return FALSE;
+ 	}
+-	INIT(entry,
+-		.sa = ike_sa->get_unique_id(ike_sa),
+-		.ts = ts,
+-	);
+-
+-	this->mutex->lock(this->mutex);
+-	this->include->insert_last(this->include, entry);
+-	this->mutex->unlock(this->mutex);
++	while (list->remove_first(list, (void**)&ts) == SUCCESS)
++	{
++		INIT(entry,
++			.sa = ike_sa->get_unique_id(ike_sa),
++			.ts = ts,
++		);
++
++		this->mutex->lock(this->mutex);
++		this->include->insert_last(this->include, entry);
++		this->mutex->unlock(this->mutex);
++	}
++	list->destroy(list);
+ 	return TRUE;
+ }
+ 
+ /**
+- * Remove a subnet from the inclusion list for this IKE_SA
++ * Remove a list of subnets from the inclusion list for this IKE_SA
+  */
+-static bool remove_include(private_unity_handler_t *this, chunk_t subnet)
++static bool remove_include(private_unity_handler_t *this, chunk_t data)
+ {
+ 	enumerator_t *enumerator;
+ 	traffic_selector_t *ts;
++	linked_list_t *list;
+ 	ike_sa_t *ike_sa;
+ 	entry_t *entry;
+ 
+@@ -129,27 +159,31 @@ static bool remove_include(private_unity
+ 	{
+ 		return FALSE;
+ 	}
+-	ts = create_ts(subnet);
+-	if (!ts)
++	list = parse_subnets(data);
++	if (!list)
+ 	{
+ 		return FALSE;
+ 	}
+ 
+ 	this->mutex->lock(this->mutex);
+-	enumerator = this->include->create_enumerator(this->include);
+-	while (enumerator->enumerate(enumerator, &entry))
++	while (list->remove_first(list, (void**)&ts) == SUCCESS)
+ 	{
+-		if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
+-			ts->equals(ts, entry->ts))
++		enumerator = this->include->create_enumerator(this->include);
++		while (enumerator->enumerate(enumerator, &entry))
+ 		{
+-			this->include->remove_at(this->include, enumerator);
+-			entry_destroy(entry);
+-			break;
++			if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
++				ts->equals(ts, entry->ts))
++			{
++				this->include->remove_at(this->include, enumerator);
++				entry_destroy(entry);
++				break;
++			}
+ 		}
++		enumerator->destroy(enumerator);
++		ts->destroy(ts);
+ 	}
+-	enumerator->destroy(enumerator);
+ 	this->mutex->unlock(this->mutex);
+-	ts->destroy(ts);
++	list->destroy(list);
+ 	return TRUE;
+ }
+ 
+@@ -212,9 +246,10 @@ static job_requeue_t add_exclude_async(e
+ /**
+  * Add a bypass policy for a given subnet
+  */
+-static bool add_exclude(private_unity_handler_t *this, chunk_t subnet)
++static bool add_exclude(private_unity_handler_t *this, chunk_t data)
+ {
+ 	traffic_selector_t *ts;
++	linked_list_t *list;
+ 	ike_sa_t *ike_sa;
+ 	entry_t *entry;
+ 
+@@ -223,48 +258,60 @@ static bool add_exclude(private_unity_ha
+ 	{
+ 		return FALSE;
+ 	}
+-	ts = create_ts(subnet);
+-	if (!ts)
++	list = parse_subnets(data);
++	if (!list)
+ 	{
+ 		return FALSE;
+ 	}
+-	INIT(entry,
+-		.sa = ike_sa->get_unique_id(ike_sa),
+-		.ts = ts,
+-	);
+-
+-	/* we can't install the shunt policy yet, as we don't know the virtual IP.
+-	 * Defer installation using an async callback. */
+-	lib->processor->queue_job(lib->processor, (job_t*)
+-						callback_job_create((void*)add_exclude_async, entry,
+-											(void*)entry_destroy, NULL));
++
++	while (list->remove_first(list, (void**)&ts) == SUCCESS)
++	{
++		INIT(entry,
++			.sa = ike_sa->get_unique_id(ike_sa),
++			.ts = ts,
++		);
++
++		/* we can't install the shunt policy yet, as we don't know the virtual IP.
++		 * Defer installation using an async callback. */
++		lib->processor->queue_job(lib->processor, (job_t*)
++							callback_job_create((void*)add_exclude_async, entry,
++												(void*)entry_destroy, NULL));
++	}
++	list->destroy(list);
+ 	return TRUE;
+ }
+ 
+ /**
+  * Remove a bypass policy for a given subnet
+  */
+-static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet)
++static bool remove_exclude(private_unity_handler_t *this, chunk_t data)
+ {
+ 	traffic_selector_t *ts;
++	linked_list_t *list;
+ 	ike_sa_t *ike_sa;
+ 	char name[128];
++	bool success = TRUE;
+ 
+ 	ike_sa = charon->bus->get_sa(charon->bus);
+ 	if (!ike_sa)
+ 	{
+ 		return FALSE;
+ 	}
+-	ts = create_ts(subnet);
+-	if (!ts)
++	list = parse_subnets(data);
++	if (!list)
+ 	{
+ 		return FALSE;
+ 	}
+-	create_shunt_name(ike_sa, ts, name, sizeof(name));
+-	DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
+-		 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
+-	ts->destroy(ts);
+-	return charon->shunts->uninstall(charon->shunts, name);
++	while (list->remove_first(list, (void**)&ts) == SUCCESS)
++	{
++		create_shunt_name(ike_sa, ts, name, sizeof(name));
++		DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
++			 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
++		ts->destroy(ts);
++		success = charon->shunts->uninstall(charon->shunts, name) && success;
++	}
++	list->destroy(list);
++	return success;
+ }
+ 
+ METHOD(attribute_handler_t, handle, bool,
diff -urN strongswan-5.0.4.orig/debian/patches/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch strongswan-5.0.4/debian/patches/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch
--- strongswan-5.0.4.orig/debian/patches/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch	1969-12-31 16:00:00.000000000 -0800
+++ strongswan-5.0.4/debian/patches/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch	2013-07-26 09:37:55.000000000 -0700
@@ -0,0 +1,97 @@
+Description: Fallback on rigthsubnet if parsing UNITY_SPLIT_INCLUDE attributes fail
+Origin: http://wiki.strongswan.org/issues/356
+Author: Tobias Brunner <tob...@strongswan.org>
+Reviewed-By: Gerald Turner <gtur...@unzane.com>
+
+---
+The information above should follow the Patch Tagging Guidelines, please
+checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
+are templates for supplementary fields that you might want to add:
+
+Origin: <vendor|upstream|other>, <url of original patch>
+Bug: <url in upstream bugtracker>
+Bug-Debian: http://bugs.debian.org/<bugnumber>
+Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
+Forwarded: <no|not-needed|url proving that it has been forwarded>
+Reviewed-By: <name and email of someone who approved the patch>
+Last-Update: <YYYY-MM-DD>
+
+--- strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_narrow.c
++++ strongswan-5.0.4/src/libcharon/plugins/unity/unity_narrow.c
+@@ -36,13 +36,32 @@ struct private_unity_narrow_t {
+ };
+ 
+ /**
++ * Narrow the given received traffic selector with the child configuration and
++ * put them into the given list of TS
++ */
++static void narrow_ts(child_cfg_t *cfg, traffic_selector_t *ts,
++					  linked_list_t *list)
++{
++	linked_list_t *received, *selected;
++
++	received = linked_list_create();
++	received->insert_last(received, ts);
++	selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
++	while (selected->remove_first(selected, (void**)&ts) == SUCCESS)
++	{
++		list->insert_last(list, ts);
++	}
++	selected->destroy(selected);
++	received->destroy(received);
++}
++
++/**
+  * Narrow TS as initiator to Unity Split-Include/Local-LAN
+  */
+ static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
+ 							 child_cfg_t *cfg, linked_list_t *remote)
+ {
+ 	traffic_selector_t *current, *orig = NULL;
+-	linked_list_t *received, *selected;
+ 	enumerator_t *enumerator;
+ 
+ 	enumerator = this->handler->create_include_enumerator(this->handler,
+@@ -56,16 +75,7 @@ static void narrow_initiator(private_uni
+ 				break;
+ 			}
+ 		}
+-		/* narrow received Unity TS with the child configuration */
+-		received = linked_list_create();
+-		received->insert_last(received, current);
+-		selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
+-		while (selected->remove_first(selected, (void**)&current) == SUCCESS)
+-		{
+-			remote->insert_last(remote, current);
+-		}
+-		selected->destroy(selected);
+-		received->destroy(received);
++		narrow_ts(cfg, current, remote);
+ 	}
+ 	enumerator->destroy(enumerator);
+ 	if (orig)
+@@ -75,6 +85,15 @@ static void narrow_initiator(private_uni
+ 			 UNITY_SPLIT_INCLUDE, remote);
+ 		orig->destroy(orig);
+ 	}
++	else
++	{	/* since we originally changed the traffic selector to 0.0.0.0/0 local
++		 * narrowing is not applied if no Split-Include attrs are received */
++		if (remote->remove_first(remote, (void**)&orig) == SUCCESS)
++		{
++			narrow_ts(cfg, orig, remote);
++			orig->destroy(orig);
++		}
++	}
+ }
+ 
+ /**
+@@ -93,6 +112,8 @@ static void narrow_initiator_pre(linked_
+ 											 "255.255.255.255", 65535);
+ 	if (ts)
+ 	{
++		DBG2(DBG_CFG, "changing proposed traffic selectors for other:");
++		DBG2(DBG_CFG, " %R", ts);
+ 		list->insert_last(list, ts);
+ 	}
+ }
diff -urN strongswan-5.0.4.orig/debian/rules strongswan-5.0.4/debian/rules
--- strongswan-5.0.4.orig/debian/rules	2013-05-18 00:17:10.000000000 -0700
+++ strongswan-5.0.4/debian/rules	2013-07-29 09:52:57.000000000 -0700
@@ -18,6 +18,18 @@
 		--enable-test-vectors \
 		--enable-xauth-eap --enable-xauth-pam \
 		--enable-attr-sql \
+		--enable-af-alg \
+		--enable-certexpire \
+		--enable-coupling \
+		--enable-duplicheck \
+		--enable-error-notify \
+		--enable-ipseckey \
+		--enable-lookip \
+		--enable-mysql \
+		--enable-sqlite \
+		--enable-unbound \
+		--enable-unity \
+		--enable-whitelist \
 		--disable-blowfish --disable-des # BSD-Young license
 	#--with-user=strongswan --with-group=nogroup
 	#	--enable-kernel-pfkey --enable-kernel-klips \
@@ -102,7 +114,7 @@
 endif
 
 	# then install the rest, ignoring the above
-	dh_install --fail-missing \
+	dh_install --list-missing \
 		-X\.la -X\.a \
 		-Xmedsrv -Xman3 \
 		-Xlibstrongswan-kernel \
diff -urN strongswan-5.0.4.orig/.pc/applied-patches strongswan-5.0.4/.pc/applied-patches
--- strongswan-5.0.4.orig/.pc/applied-patches	2013-07-29 10:03:30.102395557 -0700
+++ strongswan-5.0.4/.pc/applied-patches	2013-07-29 10:44:06.051232370 -0700
@@ -1 +1,3 @@
 01_fix-manpages.patch
+unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch
+unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch
diff -urN strongswan-5.0.4.orig/.pc/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_handler.c strongswan-5.0.4/.pc/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_handler.c
--- strongswan-5.0.4.orig/.pc/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_handler.c	1969-12-31 16:00:00.000000000 -0800
+++ strongswan-5.0.4/.pc/unity-handle-multi-valued-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_handler.c	2013-04-10 09:10:30.000000000 -0700
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "unity_handler.h"
+
+#include <daemon.h>
+#include <threading/mutex.h>
+#include <collections/linked_list.h>
+#include <processing/jobs/callback_job.h>
+
+typedef struct private_unity_handler_t private_unity_handler_t;
+
+/**
+ * Private data of an unity_handler_t object.
+ */
+struct private_unity_handler_t {
+
+	/**
+	 * Public unity_handler_t interface.
+	 */
+	unity_handler_t public;
+
+	/**
+	 * List of subnets to include, as entry_t
+	 */
+	linked_list_t *include;
+
+	/**
+	 * Mutex for concurrent access to lists
+	 */
+	mutex_t *mutex;
+};
+
+/**
+ * Traffic selector entry for networks to include under a given IKE_SA
+ */
+typedef struct {
+	/** associated IKE_SA, unique ID */
+	u_int32_t sa;
+	/** traffic selector to include/exclude */
+	traffic_selector_t *ts;
+} entry_t;
+
+/**
+ * Clean up an entry
+ */
+static void entry_destroy(entry_t *this)
+{
+	this->ts->destroy(this->ts);
+	free(this);
+}
+
+/**
+ * Create a traffic selector from a unity subnet definition
+ */
+static traffic_selector_t *create_ts(chunk_t subnet)
+{
+	chunk_t net, mask;
+	int i;
+
+	if (subnet.len != 8)
+	{
+		return NULL;
+	}
+	net = chunk_create(subnet.ptr, 4);
+	mask = chunk_clonea(chunk_skip(subnet, 4));
+	for (i = 0; i < net.len; i++)
+	{
+		mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i];
+	}
+	return traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
+											  net, 0, mask, 65535);
+}
+
+/**
+ * Store a subnet to include in tunnels under this IKE_SA
+ */
+static bool add_include(private_unity_handler_t *this, chunk_t subnet)
+{
+	traffic_selector_t *ts;
+	ike_sa_t *ike_sa;
+	entry_t *entry;
+
+	ike_sa = charon->bus->get_sa(charon->bus);
+	if (!ike_sa)
+	{
+		return FALSE;
+	}
+	ts = create_ts(subnet);
+	if (!ts)
+	{
+		return FALSE;
+	}
+	INIT(entry,
+		.sa = ike_sa->get_unique_id(ike_sa),
+		.ts = ts,
+	);
+
+	this->mutex->lock(this->mutex);
+	this->include->insert_last(this->include, entry);
+	this->mutex->unlock(this->mutex);
+	return TRUE;
+}
+
+/**
+ * Remove a subnet from the inclusion list for this IKE_SA
+ */
+static bool remove_include(private_unity_handler_t *this, chunk_t subnet)
+{
+	enumerator_t *enumerator;
+	traffic_selector_t *ts;
+	ike_sa_t *ike_sa;
+	entry_t *entry;
+
+	ike_sa = charon->bus->get_sa(charon->bus);
+	if (!ike_sa)
+	{
+		return FALSE;
+	}
+	ts = create_ts(subnet);
+	if (!ts)
+	{
+		return FALSE;
+	}
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->include->create_enumerator(this->include);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
+			ts->equals(ts, entry->ts))
+		{
+			this->include->remove_at(this->include, enumerator);
+			entry_destroy(entry);
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+	ts->destroy(ts);
+	return TRUE;
+}
+
+/**
+ * Create a unique shunt name for a bypass policy
+ */
+static void create_shunt_name(ike_sa_t *ike_sa, traffic_selector_t *ts,
+							  char *buf, size_t len)
+{
+	snprintf(buf, len, "Unity (%s[%u]: %R)", ike_sa->get_name(ike_sa),
+			 ike_sa->get_unique_id(ike_sa), ts);
+}
+
+/**
+ * Install entry as a shunt policy
+ */
+static job_requeue_t add_exclude_async(entry_t *entry)
+{
+	enumerator_t *enumerator;
+	child_cfg_t *child_cfg;
+	lifetime_cfg_t lft = { .time = { .life = 0 } };
+	ike_sa_t *ike_sa;
+	char name[128];
+	host_t *host;
+
+	ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager,
+													entry->sa, FALSE);
+	if (ike_sa)
+	{
+		create_shunt_name(ike_sa, entry->ts, name, sizeof(name));
+
+		child_cfg = child_cfg_create(name, &lft, NULL, TRUE, MODE_PASS,
+									 ACTION_NONE, ACTION_NONE, ACTION_NONE,
+									 FALSE, 0, 0, NULL, NULL, FALSE);
+		child_cfg->add_traffic_selector(child_cfg, FALSE,
+										entry->ts->clone(entry->ts));
+		host = ike_sa->get_my_host(ike_sa);
+		child_cfg->add_traffic_selector(child_cfg, TRUE,
+				traffic_selector_create_from_subnet(host->clone(host),
+													32, 0, 0, 65535));
+		enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+		while (enumerator->enumerate(enumerator, &host))
+		{
+			child_cfg->add_traffic_selector(child_cfg, TRUE,
+				traffic_selector_create_from_subnet(host->clone(host),
+													32, 0, 0, 65535));
+		}
+		enumerator->destroy(enumerator);
+		charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+
+		charon->shunts->install(charon->shunts, child_cfg);
+		child_cfg->destroy(child_cfg);
+
+		DBG1(DBG_IKE, "installed %N bypass policy for %R",
+			 configuration_attribute_type_names, UNITY_LOCAL_LAN, entry->ts);
+	}
+	return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Add a bypass policy for a given subnet
+ */
+static bool add_exclude(private_unity_handler_t *this, chunk_t subnet)
+{
+	traffic_selector_t *ts;
+	ike_sa_t *ike_sa;
+	entry_t *entry;
+
+	ike_sa = charon->bus->get_sa(charon->bus);
+	if (!ike_sa)
+	{
+		return FALSE;
+	}
+	ts = create_ts(subnet);
+	if (!ts)
+	{
+		return FALSE;
+	}
+	INIT(entry,
+		.sa = ike_sa->get_unique_id(ike_sa),
+		.ts = ts,
+	);
+
+	/* we can't install the shunt policy yet, as we don't know the virtual IP.
+	 * Defer installation using an async callback. */
+	lib->processor->queue_job(lib->processor, (job_t*)
+						callback_job_create((void*)add_exclude_async, entry,
+											(void*)entry_destroy, NULL));
+	return TRUE;
+}
+
+/**
+ * Remove a bypass policy for a given subnet
+ */
+static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet)
+{
+	traffic_selector_t *ts;
+	ike_sa_t *ike_sa;
+	char name[128];
+
+	ike_sa = charon->bus->get_sa(charon->bus);
+	if (!ike_sa)
+	{
+		return FALSE;
+	}
+	ts = create_ts(subnet);
+	if (!ts)
+	{
+		return FALSE;
+	}
+	create_shunt_name(ike_sa, ts, name, sizeof(name));
+	DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
+		 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
+	ts->destroy(ts);
+	return charon->shunts->uninstall(charon->shunts, name);
+}
+
+METHOD(attribute_handler_t, handle, bool,
+	private_unity_handler_t *this, identification_t *id,
+	configuration_attribute_type_t type, chunk_t data)
+{
+	switch (type)
+	{
+		case UNITY_SPLIT_INCLUDE:
+			return add_include(this, data);
+		case UNITY_LOCAL_LAN:
+			return add_exclude(this, data);
+		default:
+			return FALSE;
+	}
+}
+
+METHOD(attribute_handler_t, release, void,
+	private_unity_handler_t *this, identification_t *server,
+	configuration_attribute_type_t type, chunk_t data)
+{
+	switch (type)
+	{
+		case UNITY_SPLIT_INCLUDE:
+			remove_include(this, data);
+			break;
+		case UNITY_LOCAL_LAN:
+			remove_exclude(this, data);
+			break;
+		default:
+			break;
+	}
+}
+
+/**
+ * Configuration attributes to request
+ */
+static configuration_attribute_type_t attributes[] = {
+	UNITY_SPLIT_INCLUDE,
+	UNITY_LOCAL_LAN,
+};
+
+/**
+ * Attribute enumerator implementation
+ */
+typedef struct {
+	/** implements enumerator_t */
+	enumerator_t public;
+	/** position in attributes[] */
+	int i;
+} attribute_enumerator_t;
+
+METHOD(enumerator_t, enumerate_attributes, bool,
+	attribute_enumerator_t *this, configuration_attribute_type_t *type,
+	chunk_t *data)
+{
+	if (this->i < countof(attributes))
+	{
+		*type = attributes[this->i++];
+		*data = chunk_empty;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *,
+	unity_handler_t *this, identification_t *id, linked_list_t *vips)
+{
+	attribute_enumerator_t *enumerator;
+	ike_sa_t *ike_sa;
+
+	ike_sa = charon->bus->get_sa(charon->bus);
+	if (!ike_sa || ike_sa->get_version(ike_sa) != IKEV1 ||
+		!ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
+	{
+		return enumerator_create_empty();
+	}
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_enumerate_attributes,
+			.destroy = (void*)free,
+		},
+	);
+	return &enumerator->public;
+}
+
+typedef struct {
+	/** mutex to unlock */
+	mutex_t *mutex;
+	/** IKE_SA ID to filter for */
+	u_int32_t id;
+} include_filter_t;
+
+/**
+ * Include enumerator filter function
+ */
+static bool include_filter(include_filter_t *data,
+						   entry_t **entry, traffic_selector_t **ts)
+{
+	if ((*entry)->sa == data->id)
+	{
+		*ts = (*entry)->ts;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/**
+ * Destroy include filter data, unlock mutex
+ */
+static void destroy_filter(include_filter_t *data)
+{
+	data->mutex->unlock(data->mutex);
+	free(data);
+}
+
+METHOD(unity_handler_t, create_include_enumerator, enumerator_t*,
+	private_unity_handler_t *this, u_int32_t id)
+{
+	include_filter_t *data;
+
+	INIT(data,
+		.mutex = this->mutex,
+		.id = id,
+	);
+	data->mutex->lock(data->mutex);
+	return enumerator_create_filter(
+					this->include->create_enumerator(this->include),
+					(void*)include_filter, data, (void*)destroy_filter);
+}
+
+METHOD(unity_handler_t, destroy, void,
+	private_unity_handler_t *this)
+{
+	this->include->destroy(this->include);
+	this->mutex->destroy(this->mutex);
+	free(this);
+}
+
+/**
+ * See header
+ */
+unity_handler_t *unity_handler_create()
+{
+	private_unity_handler_t *this;
+
+	INIT(this,
+		.public = {
+			.handler = {
+				.handle = _handle,
+				.release = _release,
+				.create_attribute_enumerator = _create_attribute_enumerator,
+			},
+			.create_include_enumerator = _create_include_enumerator,
+			.destroy = _destroy,
+		},
+		.include = linked_list_create(),
+		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
+	);
+
+	return &this->public;
+}
diff -urN strongswan-5.0.4.orig/.pc/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_narrow.c strongswan-5.0.4/.pc/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_narrow.c
--- strongswan-5.0.4.orig/.pc/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_narrow.c	1969-12-31 16:00:00.000000000 -0800
+++ strongswan-5.0.4/.pc/unity-replicate-default-behavior-if-no-UNITY_SPLIT_INCLUDE.patch/src/libcharon/plugins/unity/unity_narrow.c	2013-04-10 02:10:56.000000000 -0700
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2012 Martin Willi
+ * Copyright (C) 2012 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "unity_narrow.h"
+
+#include <daemon.h>
+
+typedef struct private_unity_narrow_t private_unity_narrow_t;
+
+/**
+ * Private data of an unity_narrow_t object.
+ */
+struct private_unity_narrow_t {
+
+	/**
+	 * Public unity_narrow_t interface.
+	 */
+	unity_narrow_t public;
+
+	/**
+	 * Unity attribute handler
+	 */
+	unity_handler_t *handler;
+};
+
+/**
+ * Narrow TS as initiator to Unity Split-Include/Local-LAN
+ */
+static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
+							 child_cfg_t *cfg, linked_list_t *remote)
+{
+	traffic_selector_t *current, *orig = NULL;
+	linked_list_t *received, *selected;
+	enumerator_t *enumerator;
+
+	enumerator = this->handler->create_include_enumerator(this->handler,
+											ike_sa->get_unique_id(ike_sa));
+	while (enumerator->enumerate(enumerator, &current))
+	{
+		if (orig == NULL)
+		{	/* got one, replace original TS */
+			if (remote->remove_first(remote, (void**)&orig) != SUCCESS)
+			{
+				break;
+			}
+		}
+		/* narrow received Unity TS with the child configuration */
+		received = linked_list_create();
+		received->insert_last(received, current);
+		selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
+		while (selected->remove_first(selected, (void**)&current) == SUCCESS)
+		{
+			remote->insert_last(remote, current);
+		}
+		selected->destroy(selected);
+		received->destroy(received);
+	}
+	enumerator->destroy(enumerator);
+	if (orig)
+	{
+		DBG1(DBG_CFG, "narrowed CHILD_SA to %N %#R",
+			 configuration_attribute_type_names,
+			 UNITY_SPLIT_INCLUDE, remote);
+		orig->destroy(orig);
+	}
+}
+
+/**
+ * As initiator, bump up TS to 0.0.0.0/0 for on-the-wire bits
+ */
+static void narrow_initiator_pre(linked_list_t *list)
+{
+	traffic_selector_t *ts;
+
+	while (list->remove_first(list, (void**)&ts) == SUCCESS)
+	{
+		ts->destroy(ts);
+	}
+	ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
+											 "0.0.0.0", 0,
+											 "255.255.255.255", 65535);
+	if (ts)
+	{
+		list->insert_last(list, ts);
+	}
+}
+
+/**
+ * As responder, narrow down TS to configuration for installation
+ */
+static void narrow_responder_post(child_cfg_t *child_cfg, linked_list_t *local)
+{
+	traffic_selector_t *ts;
+	linked_list_t *configured;
+
+	while (local->remove_first(local, (void**)&ts) == SUCCESS)
+	{
+		ts->destroy(ts);
+	}
+	configured = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+
+	while (configured->remove_first(configured, (void**)&ts) == SUCCESS)
+	{
+		local->insert_last(local, ts);
+	}
+	configured->destroy(configured);
+}
+
+METHOD(listener_t, narrow, bool,
+	private_unity_narrow_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
+	narrow_hook_t type, linked_list_t *local, linked_list_t *remote)
+{
+	if (ike_sa->get_version(ike_sa) == IKEV1 &&
+		ike_sa->supports_extension(ike_sa, EXT_CISCO_UNITY))
+	{
+		switch (type)
+		{
+			case NARROW_INITIATOR_PRE_AUTH:
+				narrow_initiator_pre(remote);
+				break;
+			case NARROW_INITIATOR_POST_AUTH:
+				narrow_initiator(this, ike_sa,
+								 child_sa->get_config(child_sa), remote);
+				break;
+			case NARROW_RESPONDER_POST:
+				narrow_responder_post(child_sa->get_config(child_sa), local);
+				break;
+			default:
+				break;
+		}
+	}
+	return TRUE;
+}
+
+METHOD(unity_narrow_t, destroy, void,
+	private_unity_narrow_t *this)
+{
+	free(this);
+}
+
+/**
+ * See header
+ */
+unity_narrow_t *unity_narrow_create(unity_handler_t *handler)
+{
+	private_unity_narrow_t *this;
+
+	INIT(this,
+		.public = {
+			.listener = {
+				.narrow = _narrow,
+			},
+			.destroy = _destroy,
+		},
+		.handler = handler,
+	);
+
+	return &this->public;
+}
diff -urN strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_handler.c strongswan-5.0.4/src/libcharon/plugins/unity/unity_handler.c
--- strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_handler.c	2013-04-10 09:10:30.000000000 -0700
+++ strongswan-5.0.4/src/libcharon/plugins/unity/unity_handler.c	2013-07-29 10:44:06.000000000 -0700
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2013 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2012 Martin Willi
  * Copyright (C) 2012 revosec AG
  *
@@ -70,12 +73,8 @@
 	chunk_t net, mask;
 	int i;
 
-	if (subnet.len != 8)
-	{
-		return NULL;
-	}
 	net = chunk_create(subnet.ptr, 4);
-	mask = chunk_clonea(chunk_skip(subnet, 4));
+	mask = chunk_clonea(chunk_create(subnet.ptr + 4, 4));
 	for (i = 0; i < net.len; i++)
 	{
 		mask.ptr[i] = (mask.ptr[i] ^ 0xFF) | net.ptr[i];
@@ -85,11 +84,37 @@
 }
 
 /**
- * Store a subnet to include in tunnels under this IKE_SA
+ * Parse a unity attribute and extract all subnets as traffic selectors
+ */
+static linked_list_t *parse_subnets(chunk_t data)
+{
+	linked_list_t *list = NULL;
+	traffic_selector_t *ts;
+
+	while (data.len >= 8)
+	{	/* the padding is optional */
+		ts = create_ts(data);
+		if (ts)
+		{
+			if (!list)
+			{
+				list = linked_list_create();
+			}
+			list->insert_last(list, ts);
+		}
+		/* skip address, mask and 6 bytes of padding */
+		data = chunk_skip(data, 14);
+	}
+	return list;
+}
+
+/**
+ * Store a list of subnets to include in tunnels under this IKE_SA
  */
-static bool add_include(private_unity_handler_t *this, chunk_t subnet)
+static bool add_include(private_unity_handler_t *this, chunk_t data)
 {
 	traffic_selector_t *ts;
+	linked_list_t *list;
 	ike_sa_t *ike_sa;
 	entry_t *entry;
 
@@ -98,29 +123,34 @@
 	{
 		return FALSE;
 	}
-	ts = create_ts(subnet);
-	if (!ts)
+	list = parse_subnets(data);
+	if (!list)
 	{
 		return FALSE;
 	}
-	INIT(entry,
-		.sa = ike_sa->get_unique_id(ike_sa),
-		.ts = ts,
-	);
-
-	this->mutex->lock(this->mutex);
-	this->include->insert_last(this->include, entry);
-	this->mutex->unlock(this->mutex);
+	while (list->remove_first(list, (void**)&ts) == SUCCESS)
+	{
+		INIT(entry,
+			.sa = ike_sa->get_unique_id(ike_sa),
+			.ts = ts,
+		);
+
+		this->mutex->lock(this->mutex);
+		this->include->insert_last(this->include, entry);
+		this->mutex->unlock(this->mutex);
+	}
+	list->destroy(list);
 	return TRUE;
 }
 
 /**
- * Remove a subnet from the inclusion list for this IKE_SA
+ * Remove a list of subnets from the inclusion list for this IKE_SA
  */
-static bool remove_include(private_unity_handler_t *this, chunk_t subnet)
+static bool remove_include(private_unity_handler_t *this, chunk_t data)
 {
 	enumerator_t *enumerator;
 	traffic_selector_t *ts;
+	linked_list_t *list;
 	ike_sa_t *ike_sa;
 	entry_t *entry;
 
@@ -129,27 +159,31 @@
 	{
 		return FALSE;
 	}
-	ts = create_ts(subnet);
-	if (!ts)
+	list = parse_subnets(data);
+	if (!list)
 	{
 		return FALSE;
 	}
 
 	this->mutex->lock(this->mutex);
-	enumerator = this->include->create_enumerator(this->include);
-	while (enumerator->enumerate(enumerator, &entry))
+	while (list->remove_first(list, (void**)&ts) == SUCCESS)
 	{
-		if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
-			ts->equals(ts, entry->ts))
+		enumerator = this->include->create_enumerator(this->include);
+		while (enumerator->enumerate(enumerator, &entry))
 		{
-			this->include->remove_at(this->include, enumerator);
-			entry_destroy(entry);
-			break;
+			if (entry->sa == ike_sa->get_unique_id(ike_sa) &&
+				ts->equals(ts, entry->ts))
+			{
+				this->include->remove_at(this->include, enumerator);
+				entry_destroy(entry);
+				break;
+			}
 		}
+		enumerator->destroy(enumerator);
+		ts->destroy(ts);
 	}
-	enumerator->destroy(enumerator);
 	this->mutex->unlock(this->mutex);
-	ts->destroy(ts);
+	list->destroy(list);
 	return TRUE;
 }
 
@@ -212,9 +246,10 @@
 /**
  * Add a bypass policy for a given subnet
  */
-static bool add_exclude(private_unity_handler_t *this, chunk_t subnet)
+static bool add_exclude(private_unity_handler_t *this, chunk_t data)
 {
 	traffic_selector_t *ts;
+	linked_list_t *list;
 	ike_sa_t *ike_sa;
 	entry_t *entry;
 
@@ -223,48 +258,60 @@
 	{
 		return FALSE;
 	}
-	ts = create_ts(subnet);
-	if (!ts)
+	list = parse_subnets(data);
+	if (!list)
 	{
 		return FALSE;
 	}
-	INIT(entry,
-		.sa = ike_sa->get_unique_id(ike_sa),
-		.ts = ts,
-	);
-
-	/* we can't install the shunt policy yet, as we don't know the virtual IP.
-	 * Defer installation using an async callback. */
-	lib->processor->queue_job(lib->processor, (job_t*)
-						callback_job_create((void*)add_exclude_async, entry,
-											(void*)entry_destroy, NULL));
+
+	while (list->remove_first(list, (void**)&ts) == SUCCESS)
+	{
+		INIT(entry,
+			.sa = ike_sa->get_unique_id(ike_sa),
+			.ts = ts,
+		);
+
+		/* we can't install the shunt policy yet, as we don't know the virtual IP.
+		 * Defer installation using an async callback. */
+		lib->processor->queue_job(lib->processor, (job_t*)
+							callback_job_create((void*)add_exclude_async, entry,
+												(void*)entry_destroy, NULL));
+	}
+	list->destroy(list);
 	return TRUE;
 }
 
 /**
  * Remove a bypass policy for a given subnet
  */
-static bool remove_exclude(private_unity_handler_t *this, chunk_t subnet)
+static bool remove_exclude(private_unity_handler_t *this, chunk_t data)
 {
 	traffic_selector_t *ts;
+	linked_list_t *list;
 	ike_sa_t *ike_sa;
 	char name[128];
+	bool success = TRUE;
 
 	ike_sa = charon->bus->get_sa(charon->bus);
 	if (!ike_sa)
 	{
 		return FALSE;
 	}
-	ts = create_ts(subnet);
-	if (!ts)
+	list = parse_subnets(data);
+	if (!list)
 	{
 		return FALSE;
 	}
-	create_shunt_name(ike_sa, ts, name, sizeof(name));
-	DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
-		 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
-	ts->destroy(ts);
-	return charon->shunts->uninstall(charon->shunts, name);
+	while (list->remove_first(list, (void**)&ts) == SUCCESS)
+	{
+		create_shunt_name(ike_sa, ts, name, sizeof(name));
+		DBG1(DBG_IKE, "uninstalling %N bypass policy for %R",
+			 configuration_attribute_type_names, UNITY_LOCAL_LAN, ts);
+		ts->destroy(ts);
+		success = charon->shunts->uninstall(charon->shunts, name) && success;
+	}
+	list->destroy(list);
+	return success;
 }
 
 METHOD(attribute_handler_t, handle, bool,
diff -urN strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_narrow.c strongswan-5.0.4/src/libcharon/plugins/unity/unity_narrow.c
--- strongswan-5.0.4.orig/src/libcharon/plugins/unity/unity_narrow.c	2013-04-10 02:10:56.000000000 -0700
+++ strongswan-5.0.4/src/libcharon/plugins/unity/unity_narrow.c	2013-07-29 10:44:06.000000000 -0700
@@ -36,13 +36,32 @@
 };
 
 /**
+ * Narrow the given received traffic selector with the child configuration and
+ * put them into the given list of TS
+ */
+static void narrow_ts(child_cfg_t *cfg, traffic_selector_t *ts,
+					  linked_list_t *list)
+{
+	linked_list_t *received, *selected;
+
+	received = linked_list_create();
+	received->insert_last(received, ts);
+	selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
+	while (selected->remove_first(selected, (void**)&ts) == SUCCESS)
+	{
+		list->insert_last(list, ts);
+	}
+	selected->destroy(selected);
+	received->destroy(received);
+}
+
+/**
  * Narrow TS as initiator to Unity Split-Include/Local-LAN
  */
 static void narrow_initiator(private_unity_narrow_t *this, ike_sa_t *ike_sa,
 							 child_cfg_t *cfg, linked_list_t *remote)
 {
 	traffic_selector_t *current, *orig = NULL;
-	linked_list_t *received, *selected;
 	enumerator_t *enumerator;
 
 	enumerator = this->handler->create_include_enumerator(this->handler,
@@ -56,16 +75,7 @@
 				break;
 			}
 		}
-		/* narrow received Unity TS with the child configuration */
-		received = linked_list_create();
-		received->insert_last(received, current);
-		selected = cfg->get_traffic_selectors(cfg, FALSE, received, NULL);
-		while (selected->remove_first(selected, (void**)&current) == SUCCESS)
-		{
-			remote->insert_last(remote, current);
-		}
-		selected->destroy(selected);
-		received->destroy(received);
+		narrow_ts(cfg, current, remote);
 	}
 	enumerator->destroy(enumerator);
 	if (orig)
@@ -75,6 +85,15 @@
 			 UNITY_SPLIT_INCLUDE, remote);
 		orig->destroy(orig);
 	}
+	else
+	{	/* since we originally changed the traffic selector to 0.0.0.0/0 local
+		 * narrowing is not applied if no Split-Include attrs are received */
+		if (remote->remove_first(remote, (void**)&orig) == SUCCESS)
+		{
+			narrow_ts(cfg, orig, remote);
+			orig->destroy(orig);
+		}
+	}
 }
 
 /**
@@ -93,6 +112,8 @@
 											 "255.255.255.255", 65535);
 	if (ts)
 	{
+		DBG2(DBG_CFG, "changing proposed traffic selectors for other:");
+		DBG2(DBG_CFG, " %R", ts);
 		list->insert_last(list, ts);
 	}
 }

Attachment: pgppXSMvLVuQA.pgp
Description: PGP signature

Reply via email to