Avesh Agarwal | 16 May 21:09
Picon
Favicon

[Openswan dev] AES-GCM for ESP with Openswan

Hello,

Current implementation of AES-GCM (Key lengths 128, 192, 256 bits and IV
of 8, 12, 16 bytes as per RFC 4106) for ESP with Openswan has following
issues:

1. AES-GCM for key length 256 for all 3 variants(IV of 8, 12, 16 bytes)
does not work.

2. AES-GCM negotiation for ESP during IKE exchange does not
inter-operate with any other implementation, because Openswan sends
wrong key length values. RFC 4106 defines that key lengths of 128, 192,
256 should be used during IKE exchange, whereas key lengths + 4 bytes
should be calculated as final keys to be sent to kernel for ESP.
However, Openswan sends key length + 4 bytes during IKE exchange and
breaks interop with other implementation.

3. RFC 4106 only allows 3 key lengths of 128, 192 or 256 bits, but
Openswan lets configure any key length which should not happen, and
configuration should be limited to only the specified lengths in the rfc.

The attached patch addresses the above issues and has been created
against the latest upstream release of Openswan. The patch has been
tested for all AES-GCM combinations between 2 openswan nodes and also
with other implementations like strongswan to make sure there is no
issue with interoperability.

I appreciate any feedback on the patch.

--

-- 
(Continue reading)

Roel van Meer | 10 May 10:40
Picon
Favicon

[Openswan dev] klips startup error if secondary ip addres on physical interface

Hi devs,

when I start openswan, I get this error message:
ipsec_setup: Error: either "local" is duplicate, or "secondary" is a garbage.

The commit that caused this is here:
http://git.openswan.org/cgi-bin/cgit/openswan/patch/programs/_startklips/_startklips.in?id=7a6cc9e9f2a4692f1e5da7c78b52fa2f32ced38b

The openswan config is minimal and looks like this:

root <at> test13a:/tmp# cat /etc/ipsec.conf
version 2.0

config setup
 interfaces="ipsec0=eth1"
 virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,\
   v4:172.16.0.0/12,%v4:!10.0.0.0/24,%v4:!10.10.0.0/16
 oe=off
 protostack=klips

The physiscal interface is configured like this:

root <at> test13a:/tmp# ip address show dev eth1
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:40:f4:b4:0a:68 brd ff:ff:ff:ff:ff:ff
    inet 111.222.33.131/28 brd 111.222.33.143 scope global eth1
    inet 111.222.33.135/28 brd 111.222.33.143 scope global secondary eth1:1

With the patch (pristine 2.6.38) the ipsec0 device looks like this after 
startup:
(Continue reading)

Picon
Favicon

[Openswan dev] Openswan 2.4.5 with linux kernel 2.6.26 - any chance?

Hi all,

is there any chance to compile openswan 2.4.5 with linux kernel 2.6.26?

I must use 2.4.5 because there are some strange issues with interoperate to fortigate firewall with openswan 2.6.x. So I can’t use openswan 2.6.x.

Many thanky for any hints!

BR

Siegfried

_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Picon
Favicon

[Openswan dev] Openswan 2.6.35 interop with fortigate 200B

Hi,

does anyone has experiences with fortigate200b firewall? We used openswan 2.4.5 (as client) with fortigate200b (as server). Now we did a update to openswan 2.6.35 and then one issue occurred. After transferring f.e. a file through the vpn tunnel, it stops after 180-200KB. No error messages on pluto or klips. Also a VNC session interrupted after first seconds. Everything is fine on 2.4.5. Any ideas?

Best regards

Siegfried

_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Jagdish Motwani | 17 Apr 10:41
Favicon

[Openswan dev] RFC KLIPS patch for increased throughput on multicore systems

Ref mail: KLIPS tdb_lock as rwlock instead of spinlock?

Please find attached klips patch for increased throughput of single 
tunnel on multicore systems.

This patch is just a RFC and may have side effects. Please report them 
by testing or code review.

In-order to get increased throughput,
         1)Apply the patch
         2)Use Receive Packet Steering to send packets of different 
flows on different cpu's (/sys/class/net/eth0/queues/rx-0/rps_cpus)

Regrads,
Jagdish Motwani
Software Engineer
Elitecore Technologies Pvt. Ltd.
diff --git a/linux/include/openswan/ipsec_proto.h b/linux/include/openswan/ipsec_proto.h
index f40336c..db21b92 100644
--- a/linux/include/openswan/ipsec_proto.h
+++ b/linux/include/openswan/ipsec_proto.h
@@ -41,7 +41,7 @@ extern struct prng ipsec_prng;

 /* ipsec_sa.c */
 extern struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
-extern spinlock_t       tdb_lock;
+extern rwlock_t tdb_lock;
 extern int ipsec_sadb_init(void);
 extern int ipsec_sadb_cleanup(__u8);

diff --git a/linux/net/ipsec/ipsec_proc.c b/linux/net/ipsec/ipsec_proc.c
index ec25a1b..9c3a331 100644
--- a/linux/net/ipsec/ipsec_proc.c
+++ b/linux/net/ipsec/ipsec_proc.c
@@ -464,7 +464,7 @@ ipsec_spi_get_info(char *buffer,
 		    (int)offset,
 		    length);
 	
-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	for (i = 0; i < SADB_HASHMOD; i++) {
 		for (sa_p = ipsec_sadb_hash[i];
@@ -492,7 +492,7 @@ ipsec_spi_get_info(char *buffer,
         }

 done_spi_i:	
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	return len - (offset - begin);
@@ -523,7 +523,7 @@ ipsec_spigrp_get_info(char *buffer,
 		    (int)offset,
 		    length);

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);
 	
 	for (i = 0; i < SADB_HASHMOD; i++) {
 		for (sa_p = ipsec_sadb_hash[i];
@@ -563,7 +563,7 @@ ipsec_spigrp_get_info(char *buffer,
 	}

 done_spigrp_i:	
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	return len - (offset - begin);
@@ -592,7 +592,7 @@ ipsec_saraw_get_info(char *buffer,
 		    (int)offset,
 		    length);
 	
-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	for (sa_p = ipsec_sa_raw; sa_p; sa_p = sa_p->ips_raw) {
 	       
@@ -616,7 +616,7 @@ ipsec_saraw_get_info(char *buffer,
 	}

 done_spi_i:	
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	return len - (offset - begin);
diff --git a/linux/net/ipsec/ipsec_rcv.c b/linux/net/ipsec/ipsec_rcv.c
index 8800a5d..9b6d468 100644
--- a/linux/net/ipsec/ipsec_rcv.c
+++ b/linux/net/ipsec/ipsec_rcv.c
@@ -1980,7 +1980,7 @@ ipsec_rsm(struct ipsec_rcv_state *irs)
 	/*
 	 * make sure nothing is removed from underneath us
 	 */
-	spin_lock_bh(&tdb_lock);
+	read_lock_bh(&tdb_lock);

 	/*
 	 * if we have a valid said,  then we must check it here to ensure it
@@ -2021,7 +2021,7 @@ ipsec_rsm(struct ipsec_rcv_state *irs)
 			 * things are on hold until we return here in the next/new state
 			 * we check our SA is valid when we return
 			 */
-			spin_unlock_bh(&tdb_lock);
+			read_unlock_bh(&tdb_lock);
 			return;
 		} else {
 			/* bad result, force state change to done */
@@ -2036,7 +2036,7 @@ ipsec_rsm(struct ipsec_rcv_state *irs)
 	/*
 	 * all done with anything needing locks
 	 */
-	spin_unlock_bh(&tdb_lock);
+	read_unlock_bh(&tdb_lock);

 	if (irs->lastipsp) {
 		ipsec_sa_put(irs->lastipsp, IPSEC_REFRX);
diff --git a/linux/net/ipsec/ipsec_sa.c b/linux/net/ipsec/ipsec_sa.c
index 7e77f73..ccd2b96 100644
--- a/linux/net/ipsec/ipsec_sa.c
+++ b/linux/net/ipsec/ipsec_sa.c
@@ -83,8 +83,7 @@
 #define SENDERR(_x) do { error = -(_x); goto errlab; } while (0)

 struct ipsec_sa *ipsec_sadb_hash[SADB_HASHMOD];
-DEFINE_SPINLOCK(tdb_lock);
-
+DEFINE_RWLOCK(tdb_lock);
 #ifdef IPSEC_SA_RECOUNT_DEBUG
 struct ipsec_sa *ipsec_sa_raw = NULL;
 #endif
@@ -714,12 +713,12 @@ ipsec_sa_add(struct ipsec_sa *ips)
 	hashval = IPS_HASH(&ips->ips_said);

 	ipsec_sa_get(ips, IPSEC_REFSAADD);
-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);
 	
 	ips->ips_hnext = ipsec_sadb_hash[hashval];
 	ipsec_sadb_hash[hashval] = ips;
 	
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	return error;
 }
@@ -882,7 +881,7 @@ ipsec_sadb_cleanup(__u8 proto)
 		    "cleaning up proto=%d.\n",
 		    proto);

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	for (i = 0; i < SADB_HASHMOD; i++) {
 		ips = ipsec_sadb_hash[i];
@@ -898,7 +897,7 @@ ipsec_sadb_cleanup(__u8 proto)

 /* errlab: */

-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 
 #if IPSEC_SA_REF_CODE
diff --git a/linux/net/ipsec/ipsec_tunnel.c b/linux/net/ipsec/ipsec_tunnel.c
index a375b79..59cd74d 100644
--- a/linux/net/ipsec/ipsec_tunnel.c
+++ b/linux/net/ipsec/ipsec_tunnel.c
@@ -2145,7 +2145,8 @@ ipsec_tunnel_init(struct net_device *dev)
 	dev->mtu		= 0;
 	dev->addr_len		= 0;
 	dev->type		= ARPHRD_VOID; /* ARPHRD_TUNNEL; */ /* ARPHRD_ETHER; */
-	dev->tx_queue_len	= 10;		/* Small queue */
+	dev->tx_queue_len	=  0;        /* No qdisc */
+	dev->features |= NETIF_F_LLTX; /* No tx lock */
 #ifdef IFF_XMIT_DST_RELEASE
 	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
 #endif
diff --git a/linux/net/ipsec/ipsec_xmit.c b/linux/net/ipsec/ipsec_xmit.c
index b9e6a36..46f5126 100644
--- a/linux/net/ipsec/ipsec_xmit.c
+++ b/linux/net/ipsec/ipsec_xmit.c
@@ -2820,7 +2820,7 @@ ipsec_xsm(struct ipsec_xmit_state *ixs)
 	/*
 	 * make sure nothing is removed from underneath us
 	 */
-	spin_lock_bh(&tdb_lock);
+	read_lock_bh(&tdb_lock);

 	/*
 	 * if we have a valid said,  then we must check it here to ensure it
@@ -2865,7 +2865,7 @@ ipsec_xsm(struct ipsec_xmit_state *ixs)
 			 * things are on hold until we return here in the next/new state
 			 * we check our SA is valid when we return
 			 */
-			spin_unlock_bh(&tdb_lock);
+			read_unlock_bh(&tdb_lock);
 			return;
 		} else {
 			/* bad result, force state change to done */
@@ -2880,7 +2880,7 @@ ipsec_xsm(struct ipsec_xmit_state *ixs)
 	/*
 	 * all done with anything needing locks
 	 */
-	spin_unlock_bh(&tdb_lock);
+	read_unlock_bh(&tdb_lock);

 	/*
 	 * let the caller continue with their processing
diff --git a/linux/net/ipsec/pfkey_v2_parser.c b/linux/net/ipsec/pfkey_v2_parser.c
index 6f787e0..5a4364d 100644
--- a/linux/net/ipsec/pfkey_v2_parser.c
+++ b/linux/net/ipsec/pfkey_v2_parser.c
@@ -249,12 +249,12 @@ pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e

 	if(maxspi == minspi) {
 		extr->ips->ips_said.spi = maxspi;
-		spin_lock_bh(&tdb_lock);
+		write_lock_bh(&tdb_lock);
 		ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 		if(ipsq != NULL) {
 			sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa));
 			ipsec_sa_put(ipsq, IPSEC_REFSA);
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_getspi_parse: "
 				    "EMT_GETSPI found an old ipsec_sa for SA: %s, delete it first.\n",
@@ -263,7 +263,7 @@ pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e
 		} else {
 			found_avail = 1;
 		}
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 	} else {
 		int i = 0;
 		__u32 rand_val;
@@ -278,14 +278,14 @@ pfkey_getspi_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e
 					      (rand_val %
 					      (spi_diff + 1)));
 			i++;
-			spin_lock_bh(&tdb_lock);
+			write_lock_bh(&tdb_lock);
 			ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 			if(ipsq == NULL) {
 				found_avail = 1;
 			} else {
 				ipsec_sa_put(ipsq, IPSEC_REFSA);
 			}
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 		}
 	}

@@ -443,11 +443,11 @@ pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e

 	sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa));

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 	if (ipsq == NULL) {
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_update_parse: "
 			    "reserved ipsec_sa for SA: %s not found.  Call K_SADB_GETSPI first or call K_SADB_ADD instead.\n",
@@ -503,7 +503,7 @@ pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e
 		extr->ips->ips_rcvif = NULL;
 		if ((error = pfkey_ipsec_sa_init(extr->ips))) {
 			ipsec_sa_put(ipsq, IPSEC_REFSA);
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_update_parse: "
 				    "not successful for SA: %s, deleting.\n",
@@ -517,7 +517,7 @@ pfkey_update_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e
 		ipsec_sa_put(ipsq, IPSEC_REFSA);
 	}

-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);
 	
 	if(!(pfkey_safe_build(error = pfkey_msg_hdr_build(&extensions_reply[0],
 							  K_SADB_UPDATE,
@@ -719,18 +719,18 @@ pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extr

 	sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa));

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);
 	ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 	if(ipsq != NULL) {
 		ipsec_sa_put(ipsq, IPSEC_REFSA);
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_add_parse: "
 			    "found an old ipsec_sa for SA%s, delete it first.\n",
 			    sa_len ? sa : " (error)");
 		SENDERR(EEXIST);
 	}
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 #ifdef CONFIG_KLIPS_IPV6
 	if (ip_address_family(&extr->ips->ips_said.dst) == AF_INET6 &&
@@ -770,16 +770,16 @@ pfkey_add_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extr
 	}

 	/* attach it to the SAref table */
-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);
 	if((error = ipsec_sa_intern(extr->ips)) != 0) {
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_ERROR(debug_pfkey,
 			    "pfkey_add_parse: "
 			    "failed to intern SA as SAref#%lu\n"
 			    , (unsigned long)extr->ips->ips_ref);
 		SENDERR(-error);
 	}
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	extr->ips->ips_life.ipl_addtime.ipl_count = jiffies / HZ;
 	if(!extr->ips->ips_life.ipl_allocations.ipl_count) {
@@ -953,11 +953,11 @@ pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e

 	sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa));

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 	if (ipsp == NULL) {
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_delete_parse: "
 			    "ipsec_sa not found for SA:%s, could not delete.\n",
@@ -997,7 +997,7 @@ pfkey_delete_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_e
 	/* this should cause ipsec_sa_wipe to get called on the SA/group */
 	ipsec_sa_put(ipsq, IPSEC_REFALLOC);

-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	memset(&sab, 0, sizeof(sab));
 	sab.sa_base.sadb_sa_exttype = K_SADB_EXT_SA;
@@ -1092,11 +1092,11 @@ pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extr

 	sa_len = KLIPS_SATOT(debug_pfkey, &extr->ips->ips_said, 0, sa, sizeof(sa));

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	ipsp = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 	if (ipsp == NULL) {
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
 			    "ipsec_sa not found for SA=%s, could not get.\n",
 			    sa_len ? sa : " (error)");
@@ -1230,14 +1230,14 @@ pfkey_get_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_extr
 #endif
 		     )) {
 		ipsec_sa_put(ipsp, IPSEC_REFSA);
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
 			    "failed to build the get reply message extensions\n");
 		SENDERR(-error);
 	}
 		
 	ipsec_sa_put(ipsp, IPSEC_REFSA);
-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);
 	
 	if((error = pfkey_msg_build(&pfkey_reply, extensions_reply, EXT_BITS_OUT))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_get_parse: "
@@ -1697,11 +1697,11 @@ pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_
 		sa_len2 = KLIPS_SATOT(debug_pfkey, &extr->ips2->ips_said, 0, sa2, sizeof(sa2));
 	}

-	spin_lock_bh(&tdb_lock);
+	write_lock_bh(&tdb_lock);

 	ips1p = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 	if(ips1p == NULL) {
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		KLIPS_ERROR(debug_pfkey,
 			    "klips_debug:pfkey_x_grpsa_parse: "
 			    "reserved ipsec_sa for SA1: %s not found.  Call K_SADB_ADD/UPDATE first.\n",
@@ -1716,7 +1716,7 @@ pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_
 		ips2p = ipsec_sa_getbyid(&(extr->ips2->ips_said), IPSEC_REFSA);
 		if(ips2p == NULL) {
 			ipsec_sa_put(ips1p, IPSEC_REFSA);
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_x_grpsa_parse: "
 				    "reserved ipsec_sa for SA2: %s not found.  Call K_SADB_ADD/UPDATE first.\n",
@@ -1738,7 +1738,7 @@ pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_
 		if(ips1p->ips_next) {
 			ipsec_sa_put(ips1p, IPSEC_REFSA);
 			ipsec_sa_put(ips2p, IPSEC_REFSA);
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_ERROR(debug_pfkey,
 				    "klips_debug:pfkey_x_grpsa_parse: "
 				    "ipsec_sa for SA: %s is already linked.\n",
@@ -1752,7 +1752,7 @@ pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_
 			if(ipsp == ips1p) {
 				ipsec_sa_put(ips1p, IPSEC_REFSA);
 				ipsec_sa_put(ips2p, IPSEC_REFSA);
-				spin_unlock_bh(&tdb_lock);
+				write_unlock_bh(&tdb_lock);
 				KLIPS_ERROR(debug_pfkey,
 					    "klips_debug:pfkey_x_grpsa_parse: "
 					    "ipsec_sa for SA: %s is already linked to %s.\n",
@@ -1799,7 +1799,7 @@ pfkey_x_grpsa_parse(struct sock *sk, struct sadb_ext **extensions, struct pfkey_
 			    sa_len1 ? sa1 : " (error)");
 	}

-	spin_unlock_bh(&tdb_lock);
+	write_unlock_bh(&tdb_lock);

 	/* MCR: not only is this ugly to read, and impossible
 	 *   to debug through, but it's also really inefficient.
@@ -1964,11 +1964,11 @@ pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfke
 		char sa[SATOT_BUF];
 		size_t sa_len;

-		spin_lock_bh(&tdb_lock);
+		write_lock_bh(&tdb_lock);

 		ipsq = ipsec_sa_getbyid(&(extr->ips->ips_said), IPSEC_REFSA);
 		if(ipsq == NULL) {
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_x_addflow_parse: "
 				    "ipsec_sa not found, cannot set incoming policy.\n");
@@ -1982,7 +1982,7 @@ pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfke

 		if(ipsp == NULL) {
 			ipsec_sa_put(ipsq, IPSEC_REFSA);
-			spin_unlock_bh(&tdb_lock);
+			write_unlock_bh(&tdb_lock);
 			KLIPS_PRINT(debug_pfkey,
 				    "klips_debug:pfkey_x_addflow_parse: "
 				    "SA chain does not have an IPIP SA, cannot set incoming policy.\n");
@@ -2000,7 +2000,7 @@ pfkey_x_addflow_parse(struct sock *sk, struct sadb_ext **extensions, struct pfke

 		ipsec_sa_put(ipsq, IPSEC_REFSA);

-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);

 		KLIPS_PRINT(debug_pfkey,
 			    "klips_debug:pfkey_x_addflow_parse: "
@@ -2470,7 +2470,7 @@ pfkey_expire(struct ipsec_sa *ipsp, int hard)
 				  extensions))) {
 		KLIPS_PRINT(debug_pfkey, "klips_debug:pfkey_expire: "
 			    "failed to build the expire message extensions\n");
-		spin_unlock_bh(&tdb_lock);
+		write_unlock_bh(&tdb_lock);
 		goto errlab;
 	}
 	
diff --git a/linux/net/ipsec/prng.c b/linux/net/ipsec/prng.c
index 05a16d0..8c8d7e6 100644
--- a/linux/net/ipsec/prng.c
+++ b/linux/net/ipsec/prng.c
@@ -22,23 +22,21 @@
 #include <linux/interrupt.h>

 /*
- * A horrible locking hack,  we ride on tdb_lock for now since it
- * is basically what we want.  Since all calls into prng_bytes pass in
- * a pointer to ipsec_prng,  there is contention on the data in ipsec_prng
- * as it is not always locked.  TO make sure we never messup the PRNG, just
- * locked it if we don't already have the tdb_lock
+ * TO make sure we never messup the PRNG, just
+ * locked with a new lock prng_lock -- please verify this
  */
+DEFINE_SPINLOCK(prng_lock);

 #define LOCK_PRNG() \
 	int ul = 0; \
-	if (spin_trylock_bh(&tdb_lock)) { \
+	if (spin_trylock_bh(&prng_lock)) { \
 		ul = 1; \
 	} else

 #define UNLOCK_PRNG() \
 	if (ul) { \
 		ul = 0; \
-		spin_unlock_bh(&tdb_lock); \
+		spin_unlock_bh(&prng_lock); \
 	} else

 #else
_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Avesh Agarwal | 11 Apr 22:43
Picon
Favicon

[Openswan dev] ikev2 traffic selector patch

Hello,

I have implemented traffic selector negotiation functionality for ikev2
based on rfc 5996. I am attaching a patch for the same. The current
patch is based on rhel6 openswan version, and I am working on porting it
to latest upstream version. Still I thought to send it to devel mail
list to get some feedback from the developers.

-- 
Thanks and Regards
Avesh

diff -urNp openswan-2.6.32-patched/include/pluto_constants.h openswan-2.6.32-current/include/pluto_constants.h
--- openswan-2.6.32-patched/include/pluto_constants.h	2012-03-27 11:57:45.501034832 -0400
+++ openswan-2.6.32-current/include/pluto_constants.h	2012-04-10 14:06:08.544181078 -0400
 <at>  <at>  -343,7 +343,7  <at>  <at>  enum ikev2_msgtype {
 #define IS_MODE_CFG_ESTABLISHED(s) ((s) == STATE_MODE_CFG_R2)
 #endif
 
-#define IS_PARENT_SA_ESTABLISHED(s) ((s) == STATE_PARENT_I2 || (s) == STATE_PARENT_R1)
+#define IS_PARENT_SA_ESTABLISHED(s) ((s) == STATE_PARENT_I3 || (s) == STATE_PARENT_R2)
 #define IS_CHILD_SA_ESTABLISHED(st) (((st->st_state) == STATE_PARENT_I3 || (st->st_state) == STATE_PARENT_R2 || (st->st_state) == STATE_CHILDSA_DEL) && (st->st_childsa != NULL))
 
 
diff -urNp openswan-2.6.32-patched/programs/pluto/connections.c openswan-2.6.32-current/programs/pluto/connections.c
--- openswan-2.6.32-patched/programs/pluto/connections.c	2012-02-15 13:36:18.775547490 -0500
+++ openswan-2.6.32-current/programs/pluto/connections.c	2012-04-09 00:45:13.766405636 -0400
 <at>  <at>  -1688,6 +1688,65  <at>  <at>  instantiate(struct connection *c, const 
 }
 
 struct connection *
+ikev2_narrow_instantiate(struct connection *c)
+{
+    struct connection *d;
+    int wildcards;
+
+    /*if(!(c->policy & POLICY_IKEV2_ALLOW) && !(c->policy & POLICY_IKEV2_PROPOSE)) {
+    passert(c->kind == CK_TEMPLATE);
+    }
+
+    passert(c->spd.next == NULL);*/
+
+    c->instance_serial++;
+    d = clone_thing(*c, "temporary connection");
+
+    /*if (his_id != NULL)
+    {
+	passert(match_id(his_id, &d->spd.that.id, &wildcards));
+	d->spd.that.id = *his_id;
+	d->spd.that.has_id_wildcards = FALSE;
+    }*/
+
+    unshare_connection_strings(d);
+    unshare_ietfAttrList(&d->spd.this.groups);
+    unshare_ietfAttrList(&d->spd.that.groups);
+
+    d->kind = CK_INSTANCE;
+
+    passert(oriented(*d));
+    /*d->spd.that.host_addr = *him;
+    setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
+    default_end(&d->spd.that, &d->spd.this.host_addr);*/
+
+    /* We cannot guess what our next_hop should be, but if it was
+     * explicitly specified as 0.0.0.0, we set it to be him.
+     * (whack will not allow nexthop to be elided in RW case.)
+     */
+    /*default_end(&d->spd.this, &d->spd.that.host_addr);*/
+    d->spd.next = NULL;
+    d->spd.reqid = gen_reqid();
+
+    /* set internal fields */
+    d->ac_next = connections;
+    connections = d;
+    d->spd.routing = RT_UNROUTED;
+    d->newest_isakmp_sa = SOS_NOBODY;
+    d->newest_ipsec_sa = SOS_NOBODY;
+    d->spd.eroute_owner = SOS_NOBODY;
+
+    /* reset log file info */
+    d->log_file_name = NULL;
+    d->log_file = NULL;
+    d->log_file_err = FALSE;
+
+    connect_to_host_pair(d);
+
+    return d;
+}
+
+struct connection *
 rw_instantiate(struct connection *c
 , const ip_address *him
 , const ip_subnet *his_net
diff -urNp openswan-2.6.32-patched/programs/pluto/connections.h openswan-2.6.32-current/programs/pluto/connections.h
--- openswan-2.6.32-patched/programs/pluto/connections.h	2012-02-15 13:36:18.767547492 -0500
+++ openswan-2.6.32-current/programs/pluto/connections.h	2012-04-09 00:44:35.069896402 -0400
 <at>  <at>  -376,6 +376,7  <at>  <at>  find_connection_for_clients(struct spd_r
  */
 struct gw_info;	/* forward declaration of tag (defined in dnskey.h) */
 struct alg_info;	/* forward declaration of tag (defined in alg_info.h) */
+extern struct connection *ikev2_narrow_instantiate(struct connection *c);
 extern struct connection *rw_instantiate(struct connection *c
 					 , const ip_address *him
 					 , const ip_subnet *his_net
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2.c openswan-2.6.32-current/programs/pluto/ikev2.c
--- openswan-2.6.32-patched/programs/pluto/ikev2.c	2012-03-27 11:57:45.509034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2.c	2012-04-11 14:14:36.194432610 -0400
 <at>  <at>  -747,7 +747,7  <at>  <at>  static void success_v2_state_transition(
 	    fmt_isakmp_sa_established(st, sadetails,sizeof(sadetails));
 	}
 	
-	if (IS_CHILD_SA_ESTABLISHED(st))
+	if (IS_CHILD_SA_ESTABLISHED(st) || IS_PARENT_SA_ESTABLISHED(st->st_state))
 	{
 	    /* log our success */
 	    w = RC_SUCCESS;
 <at>  <at>  -910,16 +910,22  <at>  <at>  void complete_v2_state_transition(struct
     enum state_kind from_state;
     const char *from_state_name;
 
+    /* advance the state */
+    DBG(DBG_CONTROL
+        , DBG_log("complete v2 state transition with %s"
+                  , enum_name(&stfstatus_name, result)));
+
+    /* this occur when IKE SA state is deleted already */
+    if(md->st == NULL) {
+	goto end;
+    }
+
     cur_state = st = md->st;	/* might have changed */
 
     md->result = result;
     TCLCALLOUT("v2AdjustFailure", st, (st ? st->st_connection : NULL), md);
     result = md->result;
 
-    /* advance the state */
-    DBG(DBG_CONTROL
-	, DBG_log("complete v2 state transition with %s"
-		  , enum_name(&stfstatus_name, result)));
 
     switch(result) {
     case STF_IGNORE:
 <at>  <at>  -1009,6 +1015,7  <at>  <at>  void complete_v2_state_transition(struct
 		    , from_state_name
 		    , enum_name(&ipsec_notification_names, md->note)));
     }
+end:;
 }
 
 notification_t
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2_child.c openswan-2.6.32-current/programs/pluto/ikev2_child.c
--- openswan-2.6.32-patched/programs/pluto/ikev2_child.c	2012-02-15 13:36:18.770547493 -0500
+++ openswan-2.6.32-current/programs/pluto/ikev2_child.c	2012-04-11 14:55:58.822981271 -0400
 <at>  <at>  -72,7 +72,7  <at>  <at>  struct traffic_selector ikev2_subnettots
     
     switch(e->client.addr.u.v4.sin_family) {
     case AF_INET:
-	ts.sin_family = AF_INET;
+	ts.sin_family = ID_IPV4_ADDR_RANGE;
 	ts.low   = e->client.addr;
 	ts.low.u.v4.sin_addr.s_addr  &= bitstomask(e->client.maskbits).s_addr;
 	ts.high  = e->client.addr;
 <at>  <at>  -80,7 +80,7  <at>  <at>  struct traffic_selector ikev2_subnettots
 	break;
 
     case AF_INET6:
-	ts.sin_family = AF_INET6;
+	ts.sin_family = ID_IPV6_ADDR_RANGE;
 	v6mask = bitstomask6(e->client.maskbits);
 
 	ts.low   = e->client.addr;
 <at>  <at>  -113,10 +113,61  <at>  <at>  struct traffic_selector ikev2_subnettots
     ts.startport = e->port;
     ts.endport = e->port;
     }
+
+    ts.next = NULL;
 	
     return ts;
 }
 
+void 
+ikev2_store_ts_instate(struct traffic_selector *array_tsi
+		,struct traffic_selector * array_tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct traffic_selector *ts_this
+		, struct traffic_selector *ts_that)
+{
+	unsigned int i;
+	struct traffic_selector *curts, *prevts;
+
+	prevts = NULL;
+	curts = ts_this;
+	for(i=0; i<tsi_n; i++) {
+		if(curts == NULL) {
+		curts = alloc_thing(struct traffic_selector, "struct traffic_selector");
+		}
+
+		*curts = array_tsi[i];
+		curts->next = NULL;
+
+		if(prevts!= NULL) {
+		prevts->next = curts;
+		}
+
+		prevts = curts;
+		curts = curts->next;
+	}
+
+	prevts = NULL;
+	curts = ts_that;   
+
+	for(i=0; i<tsr_n; i++) {
+		if(curts == NULL) {
+		curts = alloc_thing(struct traffic_selector, "struct traffic_selector");
+		}
+
+		*curts = array_tsr[i];
+		curts->next = NULL;
+
+		if(prevts!= NULL) {
+		prevts->next = curts;
+		}
+
+		prevts = curts;
+		curts = curts->next;
+	}
+}
+
 stf_status ikev2_emit_ts(struct msg_digest *md   UNUSED
 			 , pb_stream *outpbs   
 			 , unsigned int np
 <at>  <at>  -127,20 +178,28  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     struct ikev2_ts1 its1;
     pb_stream ts_pbs;
     pb_stream ts_pbs2;
+    struct traffic_selector *tmp=ts;
 
     its.isat_np = np;
     its.isat_critical = ISAKMP_PAYLOAD_NONCRITICAL;
-    its.isat_num = 1;
+
+    its.isat_num = 0;
+    while(tmp!=NULL) {
+	its.isat_num++;
+	tmp = tmp->next;
+    }
 
     if(!out_struct(&its, &ikev2_ts_desc, outpbs, &ts_pbs))
 	return STF_INTERNAL_ERROR;
 
+   while(ts!=NULL) {
+
     switch(ts->sin_family) {
-    case AF_INET:
+    case ID_IPV4_ADDR_RANGE:
 	its1.isat1_type = ID_IPV4_ADDR_RANGE;
 	its1.isat1_sellen = 16;
 	break;
-    case AF_INET6:
+    case ID_IPV6_ADDR_RANGE:
 	its1.isat1_type = ID_IPV6_ADDR_RANGE;
 	its1.isat1_sellen = 40;
 	break;
 <at>  <at>  -160,12 +219,12  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     
     /* now do IP addresses */
     switch(ts->sin_family) {
-    case AF_INET:
+    case ID_IPV4_ADDR_RANGE:
 	if(!out_raw(&ts->low.u.v4.sin_addr.s_addr, 4, &ts_pbs2, "ipv4 low")
 	   ||!out_raw(&ts->high.u.v4.sin_addr.s_addr, 4,&ts_pbs2,"ipv4 high"))
 	    return STF_INTERNAL_ERROR;
 	break;
-    case AF_INET6:
+    case ID_IPV6_ADDR_RANGE:
 	if(!out_raw(&ts->low.u.v6.sin6_addr.s6_addr, 16, &ts_pbs2, "ipv6 low")
 	   ||!out_raw(&ts->high.u.v6.sin6_addr.s6_addr,16,&ts_pbs2,"ipv6 high"))
 	    return STF_INTERNAL_ERROR;
 <at>  <at>  -173,11 +232,56  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     }
 
     close_output_pbs(&ts_pbs2);
+    ts = ts->next;	
+    }
+
     close_output_pbs(&ts_pbs);
     
     return STF_OK;
 }
 
+bool
+ikev2_perfect_match_ts(struct traffic_selector *tsi
+		,struct traffic_selector *tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct connection *c
+		, enum phase1_role role)
+{
+	struct end *ei, *er;
+	struct traffic_selector tmpi, tmpr;
+
+	if(tsi_n > 1 ||  tsi_n > 1) {
+		return FALSE;
+	}
+
+	if(role == INITIATOR) {
+		ei = &c->spd.this;
+		er = &c->spd.that;
+	} else {
+		ei = &c->spd.that;
+		er = &c->spd.this;
+	}
+
+	tmpi = ikev2_subnettots(ei);
+	tmpr = ikev2_subnettots(er);
+
+	if(addrcmp(&tmpi.low, &tsi[0].low) == 0
+		&& addrcmp(&tmpi.high, &tsi[0].high) == 0
+		&& tmpi.startport == tsi[0].startport
+		&& tmpi.endport == tsi[0].endport
+		&& tmpi.ipprotoid == tsi[0].ipprotoid
+		&& addrcmp(&tmpr.low, &tsr[0].low) == 0
+		&& addrcmp(&tmpr.high, &tsr[0].high) == 0
+		&& tmpr.startport == tsr[0].startport
+		&& tmpr.endport == tsr[0].endport
+		&& tmpr.ipprotoid == tsr[0].ipprotoid)
+	{
+		return TRUE;
+	}
+
+	return FALSE;
+}
 
 stf_status ikev2_calc_emit_ts(struct msg_digest *md
 			      , pb_stream *outpbs
 <at>  <at>  -187,10 +291,8  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 {
     struct state *st = md->st;
     struct traffic_selector *ts_i, *ts_r;
-    struct spd_route *sr;
     stf_status ret;
     
-    st->st_childsa = c0;
 
     if(role == INITIATOR) {
 	ts_i = &st->st_ts_this;
 <at>  <at>  -200,7 +302,6  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 	ts_r = &st->st_ts_this;
     }
 
-    for(sr=&c0->spd; sr != NULL; sr = sr->next) {
 	ret = ikev2_emit_ts(md, outpbs, ISAKMP_NEXT_v2TSr
 			    , ts_i, INITIATOR);
 	if(ret!=STF_OK) return ret;
 <at>  <at>  -227,13 +328,85  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 	}
 
 	if(ret!=STF_OK) return ret;
-    }
 
     return STF_OK;
 }
 
+bool 
+ikev2_verify_ts(struct traffic_selector *tsi
+		, struct traffic_selector *tsr
+		, unsigned int ntsi
+		, unsigned int ntsr
+		, struct traffic_selector *this_ts
+		, struct traffic_selector *that_ts
+		, enum phase1_role role)
+{
+	unsigned int i;	
+	struct traffic_selector *tmptsi, *tmptsr;
+
+
+	if(role == INITIATOR) {
+		tmptsi = this_ts;
+		tmptsr = that_ts;	
+	}
+	else {
+		tmptsi = that_ts;
+		tmptsr = this_ts;
+	}
+	
+	for(i = 0; i < ntsi; i++ ) {
+
+		/* verify addresses*/ 
+		if(addrcmp(&tmptsi->low, &tsi[i].low) > 0
+			|| addrcmp(&tmptsi->high, &tsi[i].high) < 0) 
+		{
+			return FALSE;
+		}
+
+		/* verify port */ 
+		if(tmptsi->startport > tsi[i].startport 
+			|| tmptsi->endport < tsi[i].endport)
+		{
+			return FALSE;
+		}
+
+		/* verify protocol */
+		if( tmptsi->ipprotoid !=0 
+			&& tmptsi->ipprotoid != tsi[i].ipprotoid) 
+		{
+			return FALSE;
+		}
+	} 
+
+	for(i = 0; i < ntsr; i++ ) {
+
+		/* verify addresses*/ 
+		if(addrcmp(&tmptsr->low, &tsr[i].low) > 0
+			|| addrcmp(&tmptsr->high, &tsr[i].high) < 0) 
+		{
+			return FALSE;
+		}
+
+		/* verify port */
+		if(tmptsr->startport > tsr[i].startport
+			|| tmptsr->endport < tsr[i].endport)
+		{
+			return FALSE;
+		}
+
+		/* verify protocol */
+
+		if( tmptsr->ipprotoid !=0
+			&& tmptsr->ipprotoid != tsr[i].ipprotoid)
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
 /* return number of traffic selectors found */
-static int 
+int 
 ikev2_parse_ts(struct payload_digest *const ts_pd
 	       , struct traffic_selector *array
 	       , unsigned int array_max)
 <at>  <at>  -250,7 +423,7  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
 	    memset(&array[i], 0, sizeof(*array));
 	    switch(ts1.isat1_type) {
 	    case ID_IPV4_ADDR_RANGE:
-		array[i].sin_family = AF_INET;
+		array[i].sin_family = ID_IPV4_ADDR_RANGE;
 
 		array[i].low.u.v4.sin_family  = AF_INET;
 #ifdef NEED_SIN_LEN
 <at>  <at>  -269,7 +442,7  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
 		break;
 
 	    case ID_IPV6_ADDR_RANGE:
-		array[i].sin_family = AF_INET;
+		array[i].sin_family = ID_IPV6_ADDR_RANGE;
 		array[i].low.u.v6.sin6_family  = AF_INET6;
 #ifdef NEED_SIN_LEN
 		array[i].low.u.v6.sin6_len = sizeof( struct sockaddr_in6);
 <at>  <at>  -301,117 +474,679  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
     return i;
 }
 
-
-static int ikev2_evaluate_connection_fit(struct connection *d
-				  , struct spd_route *sr
-				  , enum phase1_role role
-				  , struct traffic_selector *tsi
-				  , struct traffic_selector *tsr
-				  , unsigned int tsi_n
-				  , unsigned int tsr_n)
+static bool 
+ikev2_narrowing(struct connection *c
+		  , enum phase1_role role
+		  , struct traffic_selector *tsi
+		  , struct traffic_selector *tsr
+		  , unsigned int tsi_n
+		  , unsigned int tsr_n
+		  , struct traffic_selector **narrowed_tsi
+		  , struct traffic_selector **narrowed_tsr
+		  , struct connection **result) 
 {
-    unsigned int tsi_ni, tsr_ni;
-    int bestfit = -1;
-    int best_tsr, best_tsi; 
-    struct end *ei, *er;
-    
-    if(role == INITIATOR) {
-	ei = &sr->this;
-	er = &sr->that;
-    } else {
-	ei = &sr->that;
-	er = &sr->this;
-    }
-	
-    DBG(DBG_CONTROLMORE,
-    {
-	char ei3[SUBNETTOT_BUF];
-	char er3[SUBNETTOT_BUF];
-	subnettot(&ei->client,  0, ei3, sizeof(ei3));
-	subnettot(&er->client,  0, er3, sizeof(er3));
-	DBG_log("  ikev2_eval_conn evaluating "
-		"I=%s:%s:%d/%d R=%s:%d/%d %s"
-		, d->name, ei3, ei->protocol, ei->port
-		, er3, er->protocol, er->port
-		, is_virtual_connection(d) ? "(virt)" : "");
-    }
-    );
-   
-    /* compare tsi/r array to this/that, evaluating how well it fits */
-    for(tsi_ni = 0; tsi_ni < tsi_n; tsi_ni++) {
-	for(tsr_ni=0; tsr_ni<tsr_n; tsr_ni++) {
-	    /* does it fit at all? */
+struct host_pair *hp = NULL;
+struct connection *d;
+unsigned int i; 
+struct end *ei, *er;
+int  bests=0;
+struct connection *bestc=NULL;
+bool specific_first_ts = FALSE;
+
+
+	hp = find_host_pair(&c->spd.this.host_addr
+				, c->spd.this.host_port
+				, &c->spd.that.host_addr
+				, c->spd.that.host_port);
+
+#ifdef DEBUG
+	if (DBGP(DBG_CONTROLMORE))
+	{
+		char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+
+		subnettot(&c->spd.this.client, 0, s2, sizeof(s2));
+		subnettot(&c->spd.that.client, 0, d2, sizeof(d2));
+
+		DBG_log("  checking hostpair %s -> %s is %s"
+			, s2, d2
+			, (hp ? "found" : "not found"));
+	}
+#endif /* DEBUG */
+
+	if(!hp) {
+		return FALSE;
+	}
+
+	/* check if there is any specific first traffic selector */
+	if( addrcmp(&tsi[0].low, &tsi[0].high)==0 && tsi[0].startport == tsi[0].endport &&  tsi[0].ipprotoid!=0 
+		&& addrcmp(&tsr[0].low, &tsr[0].high)==0 && tsr[0].startport ==  tsr[0].endport &&  tsr[0].ipprotoid!=0) {
+		specific_first_ts = TRUE;
+	}
+
+	/*if(!specific_first_ts && (tsi_n >= 2 || tsr_n >= 2) )
+	{
+		return FALSE;
+	}*/
+
+	for (d = hp->connections; d != NULL; d = d->hp_next)
+	{
+		int wildcards, pathlen;  /* XXX */
+		struct traffic_selector tmp,  tmp2;
+		int curs=0;
+		bool found_one_match_tsi = FALSE, found_one_match_tsr = FALSE;
+		
+		if (d->policy & POLICY_GROUP)
+			continue;
+		
+		if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+		      && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+		      && trusted_ca(c->spd.that.ca, d->spd.that.ca, &pathlen)))
+		    continue;
+
+
+		if(ikev2_perfect_match_ts(tsi, tsr, tsi_n, tsr_n, d, role)) {
+			*result = d;
+			return TRUE;
+		}
+
+		if(role == INITIATOR) {
+			ei = &d->spd.this;
+			er = &d->spd.that;
+		} else {
+			ei = &d->spd.that;
+			er = &d->spd.this;
+		}
+
+		tmp = ikev2_subnettots(ei);
+
+
+		for(i=0; i<tsi_n; i++) {
+			
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsi[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsi[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsi[i].high) >= 0) 
+			{
+				tmp2.high = tsi[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			if(addrtypeof(&tmp2.low) != addrtypeof(&tmp2.high)) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsi[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsi[i].startport;
+			}
+
+			if(tmp.endport >= tsi[i].endport )
+			{
+				tmp2.endport=tsi[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsi[i].ipprotoid && tmp.ipprotoid!=tsi[i].ipprotoid ) 
+			{
+				continue;
+			}
+
+			curs++;
+			found_one_match_tsi = TRUE;
+		}
+
+		tmp = ikev2_subnettots(er);
+		for(i=0; i<tsr_n; i++) {
+		
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsr[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsr[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsr[i].high) >= 0) 
+			{
+				tmp2.high = tsr[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			if(addrtypeof(&tmp2.low) != addrtypeof(&tmp2.high)) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsr[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsr[i].startport;
+			}
+
+			if(tmp.endport >= tsr[i].endport )
+			{
+				tmp2.endport=tsr[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsr[i].ipprotoid && tmp.ipprotoid!=tsr[i].ipprotoid ) 
+			{
+				continue;
+			}
+
+			curs++;
+			found_one_match_tsr = TRUE;
 
+		}
+
+		if(curs > bests && found_one_match_tsi && found_one_match_tsr) 
+		{
+		bests = curs;
+		bestc = d;
+
+		}
+	}
+
+	if(bestc == NULL) {
+		return FALSE;
+	}
+
+	/* creating narrowed traffic selector */
+	{
+		struct traffic_selector tmp,  tmp2, *tmp3;
+
+		*result = bestc;
+
+		if(role == INITIATOR) {
+			ei = &bestc->spd.this;
+			er = &bestc->spd.that;
+		} else {
+			ei = &bestc->spd.that;
+			er = &bestc->spd.this;
+		}
+
+
+		tmp = ikev2_subnettots(ei);
+		for(i=0; i<tsi_n; i++) {
+		
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsi[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsi[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsi[i].high) >= 0) 
+			{
+				tmp2.high = tsi[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsi[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsi[i].startport;
+			}
+
+			if(tmp.endport >= tsi[i].endport )
+			{
+				tmp2.endport=tsi[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* as openswan supports only single port, so picking one port*/
+			if( tmp2.startport > 0){
+				tmp2.endport = tmp2.startport;
+			}
+			else if (tmp2.endport < 65535 ){
+				tmp2.startport = tmp2.endport;
+			}
+
+			/* protocol */
+			if( tmp.ipprotoid > 0 && tsi[i].ipprotoid > 0 && tmp.ipprotoid!=tsi[i].ipprotoid) 
+			{
+				continue;
+			}
+			else if(tmp.ipprotoid == 0)
+			{			
+				tmp2.ipprotoid = tsi[i].ipprotoid;
+			} 
+			else 
+			{
+				tmp2.ipprotoid = tmp.ipprotoid;
+			}
+
+			/*setting type */
+			switch(tmp2.low.u.v4.sin_family) {
+			case AF_INET:
+				tmp2.sin_family = ID_IPV4_ADDR_RANGE;
+				break;
+			case AF_INET6:
+				tmp2.sin_family = ID_IPV6_ADDR_RANGE;
+				break;
+			}		
+
+			tmp3 = alloc_thing(struct traffic_selector, "struct traffic_selector");
+			*tmp3 = tmp2;
+			tmp3->next = NULL;
+			
+			if(*narrowed_tsi == NULL)
+			{
+				*narrowed_tsi = tmp3;
+			}
+			else
+			{
+				struct traffic_selector *tmp4 = *narrowed_tsi;
+				while(tmp4->next!=NULL){
+				tmp4 = tmp4->next;
+				}
+				tmp4->next = tmp3;
+				
+			}
+		}
+
+		tmp = ikev2_subnettots(er);
+		for(i=0; i<tsr_n; i++) {
+			
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsr[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsr[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsr[i].high) >= 0) 
+			{
+				tmp2.high = tsr[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsr[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsr[i].startport;
+			}
+
+			if(tmp.endport >= tsr[i].endport )
+			{
+				tmp2.endport=tsr[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* as openswan supports only single port, so picking one port*/
+			if( tmp2.startport > 0){
+				tmp2.endport = tmp2.startport;
+			}
+			else if (tmp2.endport < 65535 ){
+				tmp2.startport = tmp2.endport;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsr[i].ipprotoid && tmp.ipprotoid!=tsr[i].ipprotoid ) 
+			{
+				continue;
+			}
+			else if(tmp.ipprotoid == 0)
+			{			
+				tmp2.ipprotoid = tsr[i].ipprotoid;
+			} 
+			else 
+			{
+				tmp2.ipprotoid = tmp.ipprotoid;
+			}
+
+			/*setting type */
+			switch(tmp2.low.u.v4.sin_family) {
+			case AF_INET:
+				tmp2.sin_family = ID_IPV4_ADDR_RANGE;
+				break;
+			case AF_INET6:
+				tmp2.sin_family = ID_IPV6_ADDR_RANGE;
+				break;
+			}
+
+			tmp3 = alloc_thing(struct traffic_selector, "struct traffic_selector");
+			*tmp3 = tmp2;
+			tmp3->next = NULL;
+			
+			if(*narrowed_tsr == NULL)
+			{
+				*narrowed_tsr = tmp3;
+			}
+			else
+			{
+				struct traffic_selector *tmp4 = *narrowed_tsr;
+				while(tmp4->next!=NULL){
+				tmp4 = tmp4->next;
+				}
+				
+				tmp4->next = tmp3;		
+			}
+
+		}
+	}
+
+	struct traffic_selector *tmp;
+	tmp = *narrowed_tsi;
+	while(tmp!= NULL) {
+		
 	    DBG(DBG_CONTROLMORE,
 	    {
 		char lbi[ADDRTOT_BUF];
 		char hbi[ADDRTOT_BUF];
-		char lbr[ADDRTOT_BUF];
-		char hbr[ADDRTOT_BUF];
-		addrtot(&tsi[tsi_ni].low,  0, lbi, sizeof(lbi));
-		addrtot(&tsi[tsi_ni].high, 0, hbi, sizeof(hbi));
-		addrtot(&tsr[tsr_ni].low,  0, lbr, sizeof(lbr));
-		addrtot(&tsr[tsr_ni].high, 0, hbr, sizeof(hbr));
-		
-		DBG_log("    tsi[%u]=%s/%s tsr[%u]=%s/%s "
-			, tsi_ni, lbi, hbi
-			, tsr_ni, lbr, hbr);
+		addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+		addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+		
+		DBG_log("    tsi=%s/%s, port=%d/%d, protocol=%d"
+			,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
 	    }
 	    );
-	    /* do addresses fit into the policy? */
-	    if(addrinsubnet(&tsi[tsi_ni].low, &ei->client)
-	       && addrinsubnet(&tsi[tsi_ni].high, &ei->client)
-	       && addrinsubnet(&tsr[tsr_ni].low,  &er->client)
-	       && addrinsubnet(&tsr[tsr_ni].high, &er->client))
+
+	tmp=tmp->next;
+	}
+
+	tmp = *narrowed_tsr;
+	while(tmp!= NULL) {
+		
+	    DBG(DBG_CONTROLMORE,
 	    {
-		/*
-		 * now, how good a fit is it? --- sum of bits gives
-		 * how good a fit this is.
-		 */
-		int ts_range1 = ikev2_calc_iprangediff(tsi[tsi_ni].low
-						      , tsi[tsi_ni].high);
-		int maskbits1 = ei->client.maskbits;
-		int fitbits1  = maskbits1 + ts_range1;
-
-		int ts_range2 = ikev2_calc_iprangediff(tsr[tsr_ni].low
-						      , tsr[tsr_ni].high);
-		int maskbits2 = er->client.maskbits;
-		int fitbits2  = maskbits2 + ts_range2;
-		int fitbits = (fitbits1 << 8) + fitbits2;
-
-		/*
-		 * comparing for ports
-		 * for finding better local polcy
-		 */
-
-		if( ei->port && (tsi[tsi_ni].startport == ei->port && tsi[tsi_ni].endport == ei->port)) {
-		fitbits = fitbits << 1;
-		}
+		char lbi[ADDRTOT_BUF];
+		char hbi[ADDRTOT_BUF];
+		addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+		addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+		
+		DBG_log("    tsr=%s/%s, port=%d/%d, protocol=%d"
+			,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+	    }
+	    );
 
-		if( er->port && (tsr[tsr_ni].startport == er->port && tsr[tsr_ni].endport == er->port)) {
-		fitbits = fitbits << 1;
-		}
+	tmp=tmp->next;
+	}
+	return TRUE;
+}
 
-		DBG(DBG_CONTROLMORE,
-		{
-		    DBG_log("      has ts_range1=%u maskbits1=%u ts_range2=%u maskbits2=%u fitbits=%d <> %d"
-			    , ts_range1, maskbits1, ts_range2, maskbits2
-			    , fitbits, bestfit);
-		}
-		);
-
-		if(fitbits > bestfit) {
-		    best_tsi = tsi_ni;
-		    best_tsr = tsr_ni;
-		    bestfit = fitbits;
+struct connection *
+ikev2_create_narrowed_con(struct connection *c
+			, struct traffic_selector *narrowed_tsi
+			, struct traffic_selector *narrowed_tsr
+			, enum phase1_role role)
+{
+	struct connection *narrowed_con=NULL;
+	struct spd_route *tmp_spd=NULL, *tmp_spd1=NULL;
+	struct traffic_selector *tmptsi=NULL, *tmptsr=NULL;
+
+	narrowed_con = ikev2_narrow_instantiate(c);
+	
+	/* setup spds for narrowed connection*/
+	tmp_spd1 = NULL;
+	tmp_spd = &narrowed_con->spd;
+	tmptsi = narrowed_tsi;
+	
+	while(tmptsi != NULL) {
+		ip_subnet tmpsubneti;
+		rangetosubnet(&tmptsi->low, &tmptsi->high, &tmpsubneti);
+		tmptsr = narrowed_tsr;
+
+		while(tmptsr != NULL ) {
+			ip_subnet tmpsubnetr;
+			rangetosubnet(&tmptsr->low, &tmptsr->high, &tmpsubnetr);		
+
+			if(tmp_spd == NULL) {
+				struct spd_route *tmp_spd2 = clone_thing(narrowed_con->spd, "spds from narrowed ts");
+				tmp_spd = tmp_spd2;
+				tmp_spd->next = NULL;
+
+				if(tmp_spd1!= NULL){
+					tmp_spd1->next = tmp_spd;
+				}
+
+				if(tmp_spd != &narrowed_con->spd) {
+				tmp_spd->this.id.name.ptr = NULL;
+				tmp_spd->this.id.name.len = 0;
+                    		tmp_spd->that.id.name.ptr = NULL;
+                    		tmp_spd->that.id.name.len = 0;			
+
+				tmp_spd->this.host_addr_name = NULL;
+				tmp_spd->that.host_addr_name = NULL;
+
+				tmp_spd->this.updown = clone_str(tmp_spd->this.updown, "updown");
+				tmp_spd->that.updown = clone_str(tmp_spd->that.updown, "updown");
+
+				tmp_spd->this.cert_filename = NULL;
+				tmp_spd->that.cert_filename = NULL;
+
+				tmp_spd->this.cert.type = 0;
+				tmp_spd->that.cert.type = 0;
+
+				tmp_spd->this.ca.ptr = NULL;
+				tmp_spd->that.ca.ptr = NULL;
+
+				tmp_spd->this.groups = NULL;
+				tmp_spd->that.groups = NULL;
+
+				tmp_spd->this.virt = NULL;
+				tmp_spd->that.virt = NULL;
+				}
+			}
+
+			if(role == INITIATOR) {
+				tmp_spd->this.client = tmpsubneti;
+				tmp_spd->this.port = tmptsi->startport;
+				tmp_spd->this.protocol = tmptsi->ipprotoid;
+				if( subnetishost(&tmp_spd->this.client) && addrinsubnet(&tmp_spd->this.host_addr, &tmp_spd->this.client)) {
+				tmp_spd->this.has_client = FALSE;
+				}
+				else {
+				tmp_spd->this.has_client = TRUE;
+				}
+				tmp_spd->this.has_client_wildcard =  FALSE;
+				tmp_spd->this.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.host_addr);
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.client.addr);
+
+				tmp_spd->that.client = tmpsubnetr;
+				tmp_spd->that.port = tmptsr->startport;
+				tmp_spd->that.protocol = tmptsr->ipprotoid;
+				if( subnetishost(&tmp_spd->that.client) && addrinsubnet(&tmp_spd->that.host_addr, &tmp_spd->that.client)) {
+				tmp_spd->that.has_client = FALSE;
+				}
+				else {
+				tmp_spd->that.has_client = TRUE;
+				}
+				tmp_spd->that.has_client_wildcard =  FALSE;
+				tmp_spd->that.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.host_addr);
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.client.addr);		
+			}
+			else {
+				tmp_spd->this.client = tmpsubnetr;
+				tmp_spd->this.port = tmptsr->startport;
+				tmp_spd->this.protocol = tmptsr->ipprotoid;
+				if( subnetishost(&tmp_spd->this.client) && addrinsubnet(&tmp_spd->this.host_addr, &tmp_spd->this.client)) {
+				tmp_spd->this.has_client = FALSE;
+				}
+				else {
+				tmp_spd->this.has_client = TRUE;
+				}
+				tmp_spd->this.has_client_wildcard =  FALSE;
+				tmp_spd->this.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.host_addr);
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.client.addr);
+
+				tmp_spd->that.client = tmpsubneti;
+				tmp_spd->that.port = tmptsi->startport;
+				tmp_spd->that.protocol = tmptsi->ipprotoid;
+				if( subnetishost(&tmp_spd->that.client) && addrinsubnet(&tmp_spd->that.host_addr, &tmp_spd->that.client)) {
+				tmp_spd->that.has_client = FALSE;
+				}
+				else {
+				tmp_spd->that.has_client = TRUE;
+				}
+				tmp_spd->that.has_client_wildcard =  FALSE;
+				tmp_spd->that.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.host_addr);
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.client.addr);
+			}
+
+		tmp_spd1 = tmp_spd;
+		tmp_spd = tmp_spd1->next;
+		tmptsr = tmptsr->next;	
 		}
-	    }
+	tmptsi = tmptsi->next;
 	}
-    }
 
-    return bestfit;
+                    char buftest[ADDRTOT_BUF];
+                    tmp_spd = &narrowed_con->spd;
+                    int count_spd=0;
+                    do {
+                        DBG(DBG_CONTROLMORE, DBG_log("spd route number: %d", ++count_spd));
+
+                        /**that info**/
+                	DBG(DBG_CONTROLMORE, DBG_log("that id kind: %d",tmp_spd->that.id.kind));
+                	DBG(DBG_CONTROLMORE, 
+				DBG_log("that id ipaddr: %s", (addrtot(&tmp_spd->that.id.ip_addr, 0, buftest, sizeof(buftest)), buftest)));
+
+                	if (tmp_spd->that.id.name.ptr != NULL) {
+                	DBG(DBG_CONTROLMORE, DBG_dump_chunk("that id name",tmp_spd->that.id.name));
+                	}
+
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("that host_addr: %s", (addrtot(&tmp_spd->that.host_addr, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("that nexthop: %s", (addrtot(&tmp_spd->that.host_nexthop, 0, buftest, sizeof(buftest)), buftest)));
+                        DBG(DBG_CONTROLMORE,
+                	    DBG_log("that srcip: %s", (addrtot(&tmp_spd->that.host_srcip, 0, buftest, sizeof(buftest)), buftest)));
+                        DBG(DBG_CONTROLMORE,
+                	    DBG_log("that client_addr: %s, maskbits:%d", (addrtot(&tmp_spd->that.client.addr, 0, 
+							buftest, sizeof(buftest)), buftest),tmp_spd->that.client.maskbits));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_client: %d", tmp_spd->that.has_client));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_client_wildcard: %d", tmp_spd->that.has_client_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_port_wildcard: %d", tmp_spd->that.has_port_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_id_wildcards: %d", tmp_spd->that.has_id_wildcards));
+
+                	/**this info**/
+                	DBG(DBG_CONTROLMORE, DBG_log("this id kind: %d",tmp_spd->this.id.kind));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this id ipaddr: %s", (addrtot(&tmp_spd->this.id.ip_addr, 0, buftest, sizeof(buftest)), buftest)));
+
+                	if (tmp_spd->this.id.name.ptr != NULL) {
+                	DBG_dump_chunk("this id name",tmp_spd->this.id.name);
+                	}
+
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this host_addr: %s", (addrtot(&tmp_spd->this.host_addr, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this nexthop: %s", (addrtot(&tmp_spd->this.host_nexthop, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this srcip: %s", (addrtot(&tmp_spd->this.host_srcip, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, DBG_log("this client_addr: %s, maskbits:%d", (addrtot(&tmp_spd->this.client.addr, 
+								0, buftest, sizeof(buftest)), buftest),tmp_spd->this.client.maskbits));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_client: %d", tmp_spd->this.has_client));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_client_wildcard: %d", tmp_spd->this.has_client_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_port_wildcard: %d", tmp_spd->this.has_port_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_id_wildcards: %d", tmp_spd->this.has_id_wildcards));
+
+                        tmp_spd = tmp_spd->next;
+		    } while(tmp_spd!=NULL);
+
+	return narrowed_con;
 }
 
+
+
 stf_status ikev2_child_sa_respond(struct msg_digest *md
 				  , enum phase1_role role
 				  , pb_stream *outpbs)
 <at>  <at>  -424,8 +1159,11  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     stf_status ret;
     struct payload_digest *const tsi_pd = md->chain[ISAKMP_NEXT_v2TSi];
     struct payload_digest *const tsr_pd = md->chain[ISAKMP_NEXT_v2TSr];
-    struct traffic_selector tsi[16], tsr[16];
+    struct traffic_selector tsi[16], tsr[16], *narrowed_tsi=NULL, *narrowed_tsr=NULL;
+    struct connection *narrowed_con=NULL, *result=NULL;
     unsigned int tsi_n, tsr_n;
+    bool ts_negotiation_failed = FALSE;
+
 
     st1 = duplicate_state(st);
 
 <at>  <at>  -436,101 +1174,44  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     tsi_n = ikev2_parse_ts(tsi_pd, tsi, 16);
     tsr_n = ikev2_parse_ts(tsr_pd, tsr, 16);
 
-    /*
-     * now walk through all connections and see if this connection
-     * was in fact the best.
-     *
-     * similar to find_client_connection/fc_try.
-     */
-    {
-	struct connection *b = c;
-	struct connection *d;
-	int bestfit, newfit;
-	struct spd_route *sra, *bsr;
-	struct host_pair *hp = NULL;
-
-	bsr = NULL;
-	bestfit = -1;
-	for (sra = &c->spd; sra != NULL; sra = sra->next)
-	{
-	    int bfit=ikev2_evaluate_connection_fit(c,sra,role
-						   ,tsi,tsr,tsi_n,tsr_n);
-	    if(bfit > bestfit) {
-		bestfit = bfit;
-		b = c;
-		bsr = sra;
-	    }
-	}
-
-	for (sra = &c->spd; hp==NULL && sra != NULL; sra = sra->next)
-	{
-	    hp = find_host_pair(&sra->this.host_addr
-				, sra->this.host_port
-				, &sra->that.host_addr
-				, sra->that.host_port);
-
-#ifdef DEBUG
-	    if (DBGP(DBG_CONTROLMORE))
-	    {
-		char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
-		subnettot(&sra->this.client, 0, s2, sizeof(s2));
-		subnettot(&sra->that.client, 0, d2, sizeof(d2));
+    if(ikev2_narrowing(c, role, tsi, tsr, tsi_n, tsr_n, &narrowed_tsi , &narrowed_tsr, &result)){
 
-		DBG_log("  checking hostpair %s -> %s is %s"
-			, s2, d2
-			, (hp ? "found" : "not found"));
-	    }
-#endif /* DEBUG */
-
-	    if(!hp) continue;
-
-	    for (d = hp->connections; d != NULL; d = d->hp_next)
-	    {
-		struct spd_route *sr;
-		int wildcards, pathlen;  /* XXX */
-		
-		if (d->policy & POLICY_GROUP)
-		    continue;
-		
-		if (!(same_id(&c->spd.this.id, &d->spd.this.id)
-		      && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
-		      && trusted_ca(c->spd.that.ca, d->spd.that.ca, &pathlen)))
-		    continue;
+	if(narrowed_tsi == NULL && narrowed_tsr == NULL && result!= NULL) {
+	/*found exact match */
+		narrowed_con = result;
+
+		/*preparing traffic selectors (need to do: free first narrowed_ts here) */
+		st1->st_ts_this= ikev2_subnettots(&result->spd.this);
+		st1->st_ts_that= ikev2_subnettots(&result->spd.that);
+	}
+	else {
+		narrowed_con = ikev2_create_narrowed_con(result, narrowed_tsi, narrowed_tsr, role);
 
-		
-		for (sr = &d->spd; sr != NULL; sr = sr->next) {
-		    newfit=ikev2_evaluate_connection_fit(d,sr,role
-							 ,tsi,tsr,tsi_n,tsr_n);
-		    if(newfit > bestfit) {
-			bestfit = newfit;
-			b=d;
-			bsr = sr;
-		    }
+		/*preparing traffic selectors (need to do: free first narrowed_ts here) */
+		if(role == INITIATOR) {
+		st1->st_ts_this= *narrowed_tsi;
+		st1->st_ts_that= *narrowed_tsr;
 		}
-	    }
-	}
-	
-	/*
-	 * now that we have found the best connection, copy the data into
-	 * the state structure as the tsi/tsr
-	 *
-	 */
-
-	/*better connection*/
-	c=b;
-
-	/* Paul: should we STF_FAIL here instead of checking for NULL */
-	if (bsr != NULL) {
-		st1->st_ts_this = ikev2_subnettots(&bsr->this);
-		st1->st_ts_that = ikev2_subnettots(&bsr->that);
+		else {
+		st1->st_ts_this= *narrowed_tsr;
+		st1->st_ts_that= *narrowed_tsi;
+		}
+
+		pfreeany(narrowed_tsi);
+		pfreeany(narrowed_tsr);
 	}
     }
+    else {
+	ts_negotiation_failed = TRUE;
+    }
+
+    if(narrowed_con!= NULL && !ts_negotiation_failed) {	
+    c = narrowed_con; 
+    }
 
     st1->st_connection = c;
+    st1->st_childsa = NULL;
     insert_state(st1);
-    md->st = st1;
-    md->pst= st;
 
     /* start of SA out */
     {
 <at>  <at>  -538,7 +1219,13  <at>  <at>  stf_status ikev2_child_sa_respond(struct
 	notification_t rn;
 	pb_stream r_sa_pbs;
 
-	r_sa.isasa_np = ISAKMP_NEXT_v2TSi;  
+	if(ts_negotiation_failed) {
+	r_sa.isasa_np = ISAKMP_NEXT_v2N;
+	}
+	else {
+	r_sa.isasa_np = ISAKMP_NEXT_v2TSi;
+	}
+  
 	if (!out_struct(&r_sa, &ikev2_sa_desc, outpbs, &r_sa_pbs))
 	    return STF_INTERNAL_ERROR;
 
 <at>  <at>  -550,6 +1237,21  <at>  <at>  stf_status ikev2_child_sa_respond(struct
 	    return STF_FAIL + rn;
     }
 
+    if(ts_negotiation_failed) {
+	chunk_t child_spi, notifiy_data;
+	memset(&child_spi, 0, sizeof(child_spi));
+	memset(&notifiy_data, 0, sizeof(notifiy_data));
+	ship_v2N (ISAKMP_NEXT_NONE, ISAKMP_PAYLOAD_NONCRITICAL, /*PROTO_ISAKMP*/ 0,
+			&child_spi,
+			TS_UNACCEPTABLE, &notifiy_data, outpbs);
+	change_state(st1, STATE_CHILDSA_DEL);
+	delete_state(st1);
+	return STF_OK;
+    }
+
+    md->st = st1;
+    md->pst= st;
+
     ret = ikev2_calc_emit_ts(md, outpbs, role
 			     , c, c->policy);
     if(ret != STF_OK) return ret;
 <at>  <at>  -590,6 +1292,8  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     if(!install_ipsec_sa(st1, TRUE))
 	return STF_FATAL;
 
+    st1->st_childsa = c;
+
     /* mark the connection as now having an IPsec SA associated with it. */
     st1->st_connection->newest_ipsec_sa = st1->st_serialno;
 
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2.h openswan-2.6.32-current/programs/pluto/ikev2.h
--- openswan-2.6.32-patched/programs/pluto/ikev2.h	2012-03-27 11:57:45.510034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2.h	2012-04-11 14:54:06.491048277 -0400
 <at>  <at>  -119,20 +119,44  <at>  <at>  extern stf_status ikev2_verify_psk_auth(
 				   , unsigned char *idhash
 				   , pb_stream *sig_pbs);
 
+extern int ikev2_parse_ts(struct payload_digest *const ts_pd
+			, struct traffic_selector *array
+			, unsigned int array_max);
+
 extern stf_status ikev2_emit_ipsec_sa(struct msg_digest *md
 				      , pb_stream *outpbs
 				      , unsigned int np
 				      , struct connection *c
 				      , lset_t policy);
 
+extern struct connection *ikev2_create_narrowed_con(struct connection *c
+					, struct traffic_selector *narrowed_tsi
+					, struct traffic_selector *narrowed_tsr
+					, enum phase1_role role);
+
 extern void ikev2_derive_child_keys(struct state *st
 				    , enum phase1_role role);
 
+extern bool
+ikev2_perfect_match_ts(struct traffic_selector *tsi
+		,struct traffic_selector *tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct connection *c
+		, enum phase1_role role);
+
 extern stf_status ikev2_emit_ts(struct msg_digest *md 
 				, pb_stream *outpbs   
 				, unsigned int np
 				, struct traffic_selector *ts
 				, enum phase1_role role);
+extern void 
+ikev2_store_ts_instate(struct traffic_selector *array_tsi
+		,struct traffic_selector * array_tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct traffic_selector *ts_this 
+		, struct traffic_selector *ts_that);
 
 extern stf_status ikev2_calc_emit_ts(struct msg_digest *md
 				     , pb_stream *outpbs
 <at>  <at>  -140,6 +164,14  <at>  <at>  extern stf_status ikev2_calc_emit_ts(str
 				     , struct connection *c0
 				     , lset_t policy);
 
+extern bool ikev2_verify_ts(struct traffic_selector *tsi
+			, struct traffic_selector *tsr
+			, unsigned int tsi_n
+			, unsigned int tsr_n
+			, struct traffic_selector *this_ts
+			, struct traffic_selector *that_ts
+			, enum phase1_role role);
+
 extern stf_status ikev2_child_sa_respond(struct msg_digest *md
 					 , enum phase1_role role
 					 , pb_stream *outpbs);
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2_parent.c openswan-2.6.32-current/programs/pluto/ikev2_parent.c
--- openswan-2.6.32-patched/programs/pluto/ikev2_parent.c	2012-03-27 11:57:45.523034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2_parent.c	2012-04-11 14:59:59.578837143 -0400
 <at>  <at>  -768,7 +768,7  <at>  <at>  ikev2_parent_inI1outR1_tail(struct pluto
 	rn=accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs);
 	if(rn != NOTHING_WRONG) {
 	u_int16_t group_number = htons(st->st_oakley.group->group);
-	dc.ptr = (char *)&group_number;
+	dc.ptr = (u_char *)&group_number;
 	dc.len = 2;
 	SEND_NOTIFICATION_AA(INVALID_KE_PAYLOAD, &dc);
 	delete_state(st);
 <at>  <at>  -1417,7 +1417,7  <at>  <at>  ikev2_parent_inR1outI2_tail(struct pluto
 	 * SA2i, TSi and TSr and (USE_TRANSPORT_MODE notification in transport mode) for it .
 	 */
 	if(c0) {
-		chunk_t child_spi, notifiy_data;
+	    chunk_t child_spi, notifiy_data;
 	    st->st_connection = c0;
 
 	    ikev2_emit_ipsec_sa(md,&e_pbs_cipher,ISAKMP_NEXT_v2TSi,c0, policy);
 <at>  <at>  -1908,6 +1908,8  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
     struct connection *c = st->st_connection;
     unsigned char *idhash_in;
     struct state *pst = st;
+    struct traffic_selector tsi[16], tsr[16];
+    unsigned int tsi_n=0, tsr_n=0;
 
     if(st->st_clonedfrom != 0) {
 	pst = state_with_serialno(st->st_clonedfrom);
 <at>  <at>  -2015,6 +2017,28  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
      */
     change_state(pst, STATE_PARENT_I3);
     c->newest_isakmp_sa = pst->st_serialno;
+
+    {
+	/*check for child sa related errors */
+	/* check for TS_UNACCEPTABLE */
+	struct payload_digest *p;
+
+	for(p = md->chain[ISAKMP_NEXT_v2N]; p != NULL; p = p->next)
+	{
+		if ( p->payload.v2n.isan_type == TS_UNACCEPTABLE ) {
+			/* we can proceed with successful parent SA */
+			if(st->st_clonedfrom != 0) {
+				delete_event(st);
+				pst = state_with_serialno(st->st_clonedfrom);
+				md->st = pst;
+				md->pst = pst;
+				delete_event(st);
+				delete_state(st);
+			}
+			return STF_OK;
+		}  
+	}
+    }
     
     /* authentication good, see if there is a child SA available */
     if(md->chain[ISAKMP_NEXT_v2SA] == NULL
 <at>  <at>  -2025,8 +2049,37  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
 	/*
 	 * Delete previous retransmission event.
 	 */
+	if(st->st_clonedfrom != 0) {
+		pst = state_with_serialno(st->st_clonedfrom);
+		md->st = pst;
+		md->pst = pst;
+		delete_event(st);
+		delete_state(st);
+	}
+	return STF_OK;
+    }
+
+    {
+	struct payload_digest *const tsi_pd = md->chain[ISAKMP_NEXT_v2TSi];
+	struct payload_digest *const tsr_pd = md->chain[ISAKMP_NEXT_v2TSr];
+
+	/* parse traffic selector */
+
+	tsi_n = ikev2_parse_ts(tsi_pd, tsi, 16);
+	tsr_n = ikev2_parse_ts(tsr_pd, tsr, 16);
+
+	/* verify if the received traffic selectors are 
+	 * really same/or a subset of what we sent 
+	 */
+	if(ikev2_verify_ts(tsi, tsr, tsi_n, tsr_n
+			, &st->st_ts_this, &st->st_ts_that
+			, md->role) == FALSE) {
+	/* mistmatch in received selectors */
+	/*only proceeding with parent SA*/
 	delete_event(st);
 	return STF_OK;
+	}
+
     }
 
     {
 <at>  <at>  -2078,15 +2131,100  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
 
     } /*notification block */
 
-	
-    ikev2_derive_child_keys(st, md->role);
+    {
+	/*storing received traffic selectors */
 
-    c->newest_ipsec_sa = st->st_serialno;
+	struct traffic_selector *tmp;
+	unsigned int i=0;
+
+
+	ikev2_store_ts_instate(tsi, tsr, tsi_n, tsr_n, &st->st_ts_this, &st->st_ts_that);
+
+	for(i=0; i< tsi_n; i++) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tsi[i].low,  0, lbi, sizeof(lbi));
+                addrtot(&tsi[i].high, 0, hbi, sizeof(hbi));
+
+                DBG_log("tsi=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tsi[i].startport, tsi[i].endport, tsi[i].ipprotoid);
+            }
+            );
+
+	}
+       
+	for(i=0; i< tsr_n; i++) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tsr[i].low,  0, lbi, sizeof(lbi));
+                addrtot(&tsr[i].high, 0, hbi, sizeof(hbi));
+    
+                DBG_log("tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tsr[i].startport, tsr[i].endport, tsr[i].ipprotoid);
+            }
+            );
+
+	}
+
+
+	tmp = &st->st_ts_this;
+
+        while(tmp!= NULL) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+                addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+
+                DBG_log(" R2  this  tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+            }
+            );
+
+        tmp=tmp->next;
+        }
+
+        tmp = &st->st_ts_that;
+        while(tmp!= NULL) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+                addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+
+                DBG_log(" R2  that  tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+            }
+            );
+
+        tmp=tmp->next;
+        }
+
+	if(!ikev2_perfect_match_ts(tsi, tsr, tsi_n, tsr_n, c, md->role)) {
+		c = ikev2_create_narrowed_con(c, &st->st_ts_this, &st->st_ts_that, md->role);
+		st->st_connection = c;
+	}
+
+    }
+
+    ikev2_derive_child_keys(st, md->role);
 
     /* now install child SAs */
     if(!install_ipsec_sa(st, TRUE))
 	return STF_FATAL;
 
+    st->st_childsa = c;
+    c->newest_ipsec_sa = st->st_serialno;
     /*
      * Delete previous retransmission event.
      */
 <at>  <at>  -2408,7 +2546,6  <at>  <at>  stf_status process_informational_ikev2(s
 				pb_stream del_pbs;
 				struct ikev2_delete v2del_tmp;
 				u_int16_t i, j=0;
-				bool bogus;
 				u_char *spi;
 
 				for(i = 0; i < v2del->isad_nospi; i++ ) 
 <at>  <at>  -2577,6 +2714,8  <at>  <at>  stf_status process_informational_ikev2(s
 					else
 					{
 						change_state(current_st, STATE_IKESA_DEL);
+						md->st = NULL;
+						md->pst = NULL;
 					}
         			delete_state(current_st);
 				current_st = next_st;
 <at>  <at>  -2587,11 +2726,7  <at>  <at>  stf_status process_informational_ikev2(s
 			case PROTO_IPSEC_AH:
 			case PROTO_IPSEC_ESP:
 				{				
-				char spi_buf[1024];
-				//pb_stream del_pbs;
-				struct ikev2_delete v2del_tmp;
 				u_int16_t i;
-				bool bogus;
 				u_char *spi;
 
 				for(i = 0; i < v2del->isad_nospi; i++ ) 
 <at>  <at>  -2671,6 +2806,8  <at>  <at>  stf_status process_informational_ikev2(s
 					else
 					{
 						change_state(current_st, STATE_IKESA_DEL);
+						md->st = NULL;
+						md->pst = NULL;
 					}
         			delete_state(current_st);
 				current_st = next_st;
 <at>  <at>  -2756,8 +2893,6  <at>  <at>  void ikev2_delete_out(struct state *st)
 		role = RESPONDER;
 		}
 
-		//r_hdr.isa_flags  |=  ISAKMP_FLAGS_R;
-
 		if (!out_struct(&r_hdr, &isakmp_hdr_desc, &reply_stream, &rbody))
 		{
 			openswan_log("error initializing hdr for informational message");
diff -urNp openswan-2.6.32-patched/programs/pluto/kernel.c openswan-2.6.32-current/programs/pluto/kernel.c
--- openswan-2.6.32-patched/programs/pluto/kernel.c	2012-02-15 13:36:18.922547577 -0500
+++ openswan-2.6.32-current/programs/pluto/kernel.c	2012-04-11 12:59:13.437176813 -0400
 <at>  <at>  -2021,6 +2021,31  <at>  <at>  setup_half_ipsec_sa(struct state *st, bo
 			      , st->st_connection->policy_label
 #endif
 			      );
+
+	if(st->st_ikev2) {
+	   struct spd_route *sr = &c->spd;
+	   for(sr = sr->next; sr != NULL; sr = sr->next) {
+
+            /* MCR - should be passed a spd_eroute structure here */
+            (void) raw_eroute(&sr->that.host_addr   /* this_host */
+			      , &sr->that.client    /* this_client */
+                              , &sr->this.host_addr /* that_host */
+			      , &sr->this.client    /* that_client */
+                              , inner_spi              /* spi */
+			      , proto                  /* proto */
+                              , sr->this.protocol   /* transport_proto */
+                              , esatype                /* esatype */
+                              , proto_info             /* " */
+			      , 0                      /* lifetime */
+                              , ERO_ADD_INBOUND        /* op */
+			      , "add inbound"        /* opname */
+#ifdef HAVE_LABELED_IPSEC
+			      , st->st_connection->policy_label
+#endif
+			      );
+	   }
+	}
+
         }
     }
 
 <at>  <at>  -2095,6 +2120,7  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
      * first one found.  It may or may not be the only one.
      */
     struct connection *c = st->st_connection;
+    struct spd_route *sr;
     struct {
         unsigned proto;
         struct ipsec_proto_info *info;
 <at>  <at>  -2103,6 +2129,7  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
     bool result;
 
     i = 0;
+
     if (kernel_ops->inbound_eroute && inbound
         && c->spd.eroute_owner == SOS_NOBODY)
     {
 <at>  <at>  -2120,6 +2147,30  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
 			  );
     }
 
+    if(st->st_ikev2) {
+    for(sr = &c->spd.next; sr; sr =sr->next) {
+    if (kernel_ops->inbound_eroute && inbound
+        && sr->eroute_owner == SOS_NOBODY)
+    {
+        (void) raw_eroute(&sr->that.host_addr, &sr->that.client
+                          , &sr->this.host_addr, &sr->this.client
+                          , 256
+			  , IPSEC_PROTO_ANY
+                          , sr->this.protocol
+                          , ET_UNSPEC
+                          , null_proto_info, 0
+                          , ERO_DEL_INBOUND, "delete inbound"
+#ifdef HAVE_LABELED_IPSEC
+			  , c->policy_label
+#endif
+			  );
+    }
+    }
+    }
+
+
+
+
     if (!kernel_ops->grp_sa)
     {
         if (st->st_ah.present)
diff -urNp openswan-2.6.32-patched/programs/pluto/state.c openswan-2.6.32-current/programs/pluto/state.c
--- openswan-2.6.32-patched/programs/pluto/state.c	2012-03-27 11:57:45.531034831 -0400
+++ openswan-2.6.32-current/programs/pluto/state.c	2012-04-11 15:01:27.527784330 -0400
 <at>  <at>  -351,6 +351,19  <at>  <at>  release_whack(struct state *st)
     close_any(st->st_whack_sock);
 }
 
+/* freeing allocated traffic selectors */
+static void delete_ts(struct traffic_selector *ts) {
+	struct traffic_selector *tmp;
+
+	/*first one is not malloced so skiping that*/
+	ts = ts-> next;
+	while(ts!=NULL) {
+		tmp = ts->next;
+		pfreeany(ts);
+		ts = tmp;
+	}
+}
+
 /* delete a state object */
 void
 delete_state(struct state *st)
 <at>  <at>  -511,6 +524,10  <at>  <at>  delete_state(struct state *st)
 	pfreeany(st->st_sec_chunk.ptr);
     }
 
+    /*free selectors if any */
+    delete_ts(&st->st_ts_this);
+    delete_ts(&st->st_ts_that);
+
     freeanychunk(st->st_firstpacket_me);
     freeanychunk(st->st_firstpacket_him);
     freeanychunk(st->st_tpacket);
diff -urNp openswan-2.6.32-patched/programs/pluto/state.h openswan-2.6.32-current/programs/pluto/state.h
--- openswan-2.6.32-patched/programs/pluto/state.h	2012-03-27 11:57:45.532034831 -0400
+++ openswan-2.6.32-current/programs/pluto/state.h	2012-04-10 17:00:05.840320943 -0400
 <at>  <at>  -164,6 +164,7  <at>  <at>  struct traffic_selector {
     u_int16_t endport;
     ip_address low;
     ip_address high;
+    struct traffic_selector *next;
 };
 
 #ifdef HAVE_LABELED_IPSEC
_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Avesh Agarwal | 11 Apr 22:31
Picon
Favicon

[Openswan dev] ikev2 traffic selector patch

Hello,

I have implemented traffic selector negotiation functionality for ikev2
based on rfc 5996. I am attaching a patch for the same. The current
patch is based on rhel6 openswan version, and I am working on porting it
to latest upstream version. Still I thought to send it to devel mail
list to get some feedback from the developers.

-- 
Thanks and Regards
Avesh

diff -urNp openswan-2.6.32-patched/include/pluto_constants.h openswan-2.6.32-current/include/pluto_constants.h
--- openswan-2.6.32-patched/include/pluto_constants.h	2012-03-27 11:57:45.501034832 -0400
+++ openswan-2.6.32-current/include/pluto_constants.h	2012-04-10 14:06:08.544181078 -0400
 <at>  <at>  -343,7 +343,7  <at>  <at>  enum ikev2_msgtype {
 #define IS_MODE_CFG_ESTABLISHED(s) ((s) == STATE_MODE_CFG_R2)
 #endif
 
-#define IS_PARENT_SA_ESTABLISHED(s) ((s) == STATE_PARENT_I2 || (s) == STATE_PARENT_R1)
+#define IS_PARENT_SA_ESTABLISHED(s) ((s) == STATE_PARENT_I3 || (s) == STATE_PARENT_R2)
 #define IS_CHILD_SA_ESTABLISHED(st) (((st->st_state) == STATE_PARENT_I3 || (st->st_state) == STATE_PARENT_R2 || (st->st_state) == STATE_CHILDSA_DEL) && (st->st_childsa != NULL))
 
 
diff -urNp openswan-2.6.32-patched/programs/pluto/connections.c openswan-2.6.32-current/programs/pluto/connections.c
--- openswan-2.6.32-patched/programs/pluto/connections.c	2012-02-15 13:36:18.775547490 -0500
+++ openswan-2.6.32-current/programs/pluto/connections.c	2012-04-09 00:45:13.766405636 -0400
 <at>  <at>  -1688,6 +1688,65  <at>  <at>  instantiate(struct connection *c, const 
 }
 
 struct connection *
+ikev2_narrow_instantiate(struct connection *c)
+{
+    struct connection *d;
+    int wildcards;
+
+    /*if(!(c->policy & POLICY_IKEV2_ALLOW) && !(c->policy & POLICY_IKEV2_PROPOSE)) {
+    passert(c->kind == CK_TEMPLATE);
+    }
+
+    passert(c->spd.next == NULL);*/
+
+    c->instance_serial++;
+    d = clone_thing(*c, "temporary connection");
+
+    /*if (his_id != NULL)
+    {
+	passert(match_id(his_id, &d->spd.that.id, &wildcards));
+	d->spd.that.id = *his_id;
+	d->spd.that.has_id_wildcards = FALSE;
+    }*/
+
+    unshare_connection_strings(d);
+    unshare_ietfAttrList(&d->spd.this.groups);
+    unshare_ietfAttrList(&d->spd.that.groups);
+
+    d->kind = CK_INSTANCE;
+
+    passert(oriented(*d));
+    /*d->spd.that.host_addr = *him;
+    setportof(htons(c->spd.that.port), &d->spd.that.host_addr);
+    default_end(&d->spd.that, &d->spd.this.host_addr);*/
+
+    /* We cannot guess what our next_hop should be, but if it was
+     * explicitly specified as 0.0.0.0, we set it to be him.
+     * (whack will not allow nexthop to be elided in RW case.)
+     */
+    /*default_end(&d->spd.this, &d->spd.that.host_addr);*/
+    d->spd.next = NULL;
+    d->spd.reqid = gen_reqid();
+
+    /* set internal fields */
+    d->ac_next = connections;
+    connections = d;
+    d->spd.routing = RT_UNROUTED;
+    d->newest_isakmp_sa = SOS_NOBODY;
+    d->newest_ipsec_sa = SOS_NOBODY;
+    d->spd.eroute_owner = SOS_NOBODY;
+
+    /* reset log file info */
+    d->log_file_name = NULL;
+    d->log_file = NULL;
+    d->log_file_err = FALSE;
+
+    connect_to_host_pair(d);
+
+    return d;
+}
+
+struct connection *
 rw_instantiate(struct connection *c
 , const ip_address *him
 , const ip_subnet *his_net
diff -urNp openswan-2.6.32-patched/programs/pluto/connections.h openswan-2.6.32-current/programs/pluto/connections.h
--- openswan-2.6.32-patched/programs/pluto/connections.h	2012-02-15 13:36:18.767547492 -0500
+++ openswan-2.6.32-current/programs/pluto/connections.h	2012-04-09 00:44:35.069896402 -0400
 <at>  <at>  -376,6 +376,7  <at>  <at>  find_connection_for_clients(struct spd_r
  */
 struct gw_info;	/* forward declaration of tag (defined in dnskey.h) */
 struct alg_info;	/* forward declaration of tag (defined in alg_info.h) */
+extern struct connection *ikev2_narrow_instantiate(struct connection *c);
 extern struct connection *rw_instantiate(struct connection *c
 					 , const ip_address *him
 					 , const ip_subnet *his_net
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2.c openswan-2.6.32-current/programs/pluto/ikev2.c
--- openswan-2.6.32-patched/programs/pluto/ikev2.c	2012-03-27 11:57:45.509034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2.c	2012-04-11 14:14:36.194432610 -0400
 <at>  <at>  -747,7 +747,7  <at>  <at>  static void success_v2_state_transition(
 	    fmt_isakmp_sa_established(st, sadetails,sizeof(sadetails));
 	}
 	
-	if (IS_CHILD_SA_ESTABLISHED(st))
+	if (IS_CHILD_SA_ESTABLISHED(st) || IS_PARENT_SA_ESTABLISHED(st->st_state))
 	{
 	    /* log our success */
 	    w = RC_SUCCESS;
 <at>  <at>  -910,16 +910,22  <at>  <at>  void complete_v2_state_transition(struct
     enum state_kind from_state;
     const char *from_state_name;
 
+    /* advance the state */
+    DBG(DBG_CONTROL
+        , DBG_log("complete v2 state transition with %s"
+                  , enum_name(&stfstatus_name, result)));
+
+    /* this occur when IKE SA state is deleted already */
+    if(md->st == NULL) {
+	goto end;
+    }
+
     cur_state = st = md->st;	/* might have changed */
 
     md->result = result;
     TCLCALLOUT("v2AdjustFailure", st, (st ? st->st_connection : NULL), md);
     result = md->result;
 
-    /* advance the state */
-    DBG(DBG_CONTROL
-	, DBG_log("complete v2 state transition with %s"
-		  , enum_name(&stfstatus_name, result)));
 
     switch(result) {
     case STF_IGNORE:
 <at>  <at>  -1009,6 +1015,7  <at>  <at>  void complete_v2_state_transition(struct
 		    , from_state_name
 		    , enum_name(&ipsec_notification_names, md->note)));
     }
+end:;
 }
 
 notification_t
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2_child.c openswan-2.6.32-current/programs/pluto/ikev2_child.c
--- openswan-2.6.32-patched/programs/pluto/ikev2_child.c	2012-02-15 13:36:18.770547493 -0500
+++ openswan-2.6.32-current/programs/pluto/ikev2_child.c	2012-04-11 14:55:58.822981271 -0400
 <at>  <at>  -72,7 +72,7  <at>  <at>  struct traffic_selector ikev2_subnettots
     
     switch(e->client.addr.u.v4.sin_family) {
     case AF_INET:
-	ts.sin_family = AF_INET;
+	ts.sin_family = ID_IPV4_ADDR_RANGE;
 	ts.low   = e->client.addr;
 	ts.low.u.v4.sin_addr.s_addr  &= bitstomask(e->client.maskbits).s_addr;
 	ts.high  = e->client.addr;
 <at>  <at>  -80,7 +80,7  <at>  <at>  struct traffic_selector ikev2_subnettots
 	break;
 
     case AF_INET6:
-	ts.sin_family = AF_INET6;
+	ts.sin_family = ID_IPV6_ADDR_RANGE;
 	v6mask = bitstomask6(e->client.maskbits);
 
 	ts.low   = e->client.addr;
 <at>  <at>  -113,10 +113,61  <at>  <at>  struct traffic_selector ikev2_subnettots
     ts.startport = e->port;
     ts.endport = e->port;
     }
+
+    ts.next = NULL;
 	
     return ts;
 }
 
+void 
+ikev2_store_ts_instate(struct traffic_selector *array_tsi
+		,struct traffic_selector * array_tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct traffic_selector *ts_this
+		, struct traffic_selector *ts_that)
+{
+	unsigned int i;
+	struct traffic_selector *curts, *prevts;
+
+	prevts = NULL;
+	curts = ts_this;
+	for(i=0; i<tsi_n; i++) {
+		if(curts == NULL) {
+		curts = alloc_thing(struct traffic_selector, "struct traffic_selector");
+		}
+
+		*curts = array_tsi[i];
+		curts->next = NULL;
+
+		if(prevts!= NULL) {
+		prevts->next = curts;
+		}
+
+		prevts = curts;
+		curts = curts->next;
+	}
+
+	prevts = NULL;
+	curts = ts_that;   
+
+	for(i=0; i<tsr_n; i++) {
+		if(curts == NULL) {
+		curts = alloc_thing(struct traffic_selector, "struct traffic_selector");
+		}
+
+		*curts = array_tsr[i];
+		curts->next = NULL;
+
+		if(prevts!= NULL) {
+		prevts->next = curts;
+		}
+
+		prevts = curts;
+		curts = curts->next;
+	}
+}
+
 stf_status ikev2_emit_ts(struct msg_digest *md   UNUSED
 			 , pb_stream *outpbs   
 			 , unsigned int np
 <at>  <at>  -127,20 +178,28  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     struct ikev2_ts1 its1;
     pb_stream ts_pbs;
     pb_stream ts_pbs2;
+    struct traffic_selector *tmp=ts;
 
     its.isat_np = np;
     its.isat_critical = ISAKMP_PAYLOAD_NONCRITICAL;
-    its.isat_num = 1;
+
+    its.isat_num = 0;
+    while(tmp!=NULL) {
+	its.isat_num++;
+	tmp = tmp->next;
+    }
 
     if(!out_struct(&its, &ikev2_ts_desc, outpbs, &ts_pbs))
 	return STF_INTERNAL_ERROR;
 
+   while(ts!=NULL) {
+
     switch(ts->sin_family) {
-    case AF_INET:
+    case ID_IPV4_ADDR_RANGE:
 	its1.isat1_type = ID_IPV4_ADDR_RANGE;
 	its1.isat1_sellen = 16;
 	break;
-    case AF_INET6:
+    case ID_IPV6_ADDR_RANGE:
 	its1.isat1_type = ID_IPV6_ADDR_RANGE;
 	its1.isat1_sellen = 40;
 	break;
 <at>  <at>  -160,12 +219,12  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     
     /* now do IP addresses */
     switch(ts->sin_family) {
-    case AF_INET:
+    case ID_IPV4_ADDR_RANGE:
 	if(!out_raw(&ts->low.u.v4.sin_addr.s_addr, 4, &ts_pbs2, "ipv4 low")
 	   ||!out_raw(&ts->high.u.v4.sin_addr.s_addr, 4,&ts_pbs2,"ipv4 high"))
 	    return STF_INTERNAL_ERROR;
 	break;
-    case AF_INET6:
+    case ID_IPV6_ADDR_RANGE:
 	if(!out_raw(&ts->low.u.v6.sin6_addr.s6_addr, 16, &ts_pbs2, "ipv6 low")
 	   ||!out_raw(&ts->high.u.v6.sin6_addr.s6_addr,16,&ts_pbs2,"ipv6 high"))
 	    return STF_INTERNAL_ERROR;
 <at>  <at>  -173,11 +232,56  <at>  <at>  stf_status ikev2_emit_ts(struct msg_dige
     }
 
     close_output_pbs(&ts_pbs2);
+    ts = ts->next;	
+    }
+
     close_output_pbs(&ts_pbs);
     
     return STF_OK;
 }
 
+bool
+ikev2_perfect_match_ts(struct traffic_selector *tsi
+		,struct traffic_selector *tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct connection *c
+		, enum phase1_role role)
+{
+	struct end *ei, *er;
+	struct traffic_selector tmpi, tmpr;
+
+	if(tsi_n > 1 ||  tsi_n > 1) {
+		return FALSE;
+	}
+
+	if(role == INITIATOR) {
+		ei = &c->spd.this;
+		er = &c->spd.that;
+	} else {
+		ei = &c->spd.that;
+		er = &c->spd.this;
+	}
+
+	tmpi = ikev2_subnettots(ei);
+	tmpr = ikev2_subnettots(er);
+
+	if(addrcmp(&tmpi.low, &tsi[0].low) == 0
+		&& addrcmp(&tmpi.high, &tsi[0].high) == 0
+		&& tmpi.startport == tsi[0].startport
+		&& tmpi.endport == tsi[0].endport
+		&& tmpi.ipprotoid == tsi[0].ipprotoid
+		&& addrcmp(&tmpr.low, &tsr[0].low) == 0
+		&& addrcmp(&tmpr.high, &tsr[0].high) == 0
+		&& tmpr.startport == tsr[0].startport
+		&& tmpr.endport == tsr[0].endport
+		&& tmpr.ipprotoid == tsr[0].ipprotoid)
+	{
+		return TRUE;
+	}
+
+	return FALSE;
+}
 
 stf_status ikev2_calc_emit_ts(struct msg_digest *md
 			      , pb_stream *outpbs
 <at>  <at>  -187,10 +291,8  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 {
     struct state *st = md->st;
     struct traffic_selector *ts_i, *ts_r;
-    struct spd_route *sr;
     stf_status ret;
     
-    st->st_childsa = c0;
 
     if(role == INITIATOR) {
 	ts_i = &st->st_ts_this;
 <at>  <at>  -200,7 +302,6  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 	ts_r = &st->st_ts_this;
     }
 
-    for(sr=&c0->spd; sr != NULL; sr = sr->next) {
 	ret = ikev2_emit_ts(md, outpbs, ISAKMP_NEXT_v2TSr
 			    , ts_i, INITIATOR);
 	if(ret!=STF_OK) return ret;
 <at>  <at>  -227,13 +328,85  <at>  <at>  stf_status ikev2_calc_emit_ts(struct msg
 	}
 
 	if(ret!=STF_OK) return ret;
-    }
 
     return STF_OK;
 }
 
+bool 
+ikev2_verify_ts(struct traffic_selector *tsi
+		, struct traffic_selector *tsr
+		, unsigned int ntsi
+		, unsigned int ntsr
+		, struct traffic_selector *this_ts
+		, struct traffic_selector *that_ts
+		, enum phase1_role role)
+{
+	unsigned int i;	
+	struct traffic_selector *tmptsi, *tmptsr;
+
+
+	if(role == INITIATOR) {
+		tmptsi = this_ts;
+		tmptsr = that_ts;	
+	}
+	else {
+		tmptsi = that_ts;
+		tmptsr = this_ts;
+	}
+	
+	for(i = 0; i < ntsi; i++ ) {
+
+		/* verify addresses*/ 
+		if(addrcmp(&tmptsi->low, &tsi[i].low) > 0
+			|| addrcmp(&tmptsi->high, &tsi[i].high) < 0) 
+		{
+			return FALSE;
+		}
+
+		/* verify port */ 
+		if(tmptsi->startport > tsi[i].startport 
+			|| tmptsi->endport < tsi[i].endport)
+		{
+			return FALSE;
+		}
+
+		/* verify protocol */
+		if( tmptsi->ipprotoid !=0 
+			&& tmptsi->ipprotoid != tsi[i].ipprotoid) 
+		{
+			return FALSE;
+		}
+	} 
+
+	for(i = 0; i < ntsr; i++ ) {
+
+		/* verify addresses*/ 
+		if(addrcmp(&tmptsr->low, &tsr[i].low) > 0
+			|| addrcmp(&tmptsr->high, &tsr[i].high) < 0) 
+		{
+			return FALSE;
+		}
+
+		/* verify port */
+		if(tmptsr->startport > tsr[i].startport
+			|| tmptsr->endport < tsr[i].endport)
+		{
+			return FALSE;
+		}
+
+		/* verify protocol */
+
+		if( tmptsr->ipprotoid !=0
+			&& tmptsr->ipprotoid != tsr[i].ipprotoid)
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
 /* return number of traffic selectors found */
-static int 
+int 
 ikev2_parse_ts(struct payload_digest *const ts_pd
 	       , struct traffic_selector *array
 	       , unsigned int array_max)
 <at>  <at>  -250,7 +423,7  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
 	    memset(&array[i], 0, sizeof(*array));
 	    switch(ts1.isat1_type) {
 	    case ID_IPV4_ADDR_RANGE:
-		array[i].sin_family = AF_INET;
+		array[i].sin_family = ID_IPV4_ADDR_RANGE;
 
 		array[i].low.u.v4.sin_family  = AF_INET;
 #ifdef NEED_SIN_LEN
 <at>  <at>  -269,7 +442,7  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
 		break;
 
 	    case ID_IPV6_ADDR_RANGE:
-		array[i].sin_family = AF_INET;
+		array[i].sin_family = ID_IPV6_ADDR_RANGE;
 		array[i].low.u.v6.sin6_family  = AF_INET6;
 #ifdef NEED_SIN_LEN
 		array[i].low.u.v6.sin6_len = sizeof( struct sockaddr_in6);
 <at>  <at>  -301,117 +474,679  <at>  <at>  ikev2_parse_ts(struct payload_digest *co
     return i;
 }
 
-
-static int ikev2_evaluate_connection_fit(struct connection *d
-				  , struct spd_route *sr
-				  , enum phase1_role role
-				  , struct traffic_selector *tsi
-				  , struct traffic_selector *tsr
-				  , unsigned int tsi_n
-				  , unsigned int tsr_n)
+static bool 
+ikev2_narrowing(struct connection *c
+		  , enum phase1_role role
+		  , struct traffic_selector *tsi
+		  , struct traffic_selector *tsr
+		  , unsigned int tsi_n
+		  , unsigned int tsr_n
+		  , struct traffic_selector **narrowed_tsi
+		  , struct traffic_selector **narrowed_tsr
+		  , struct connection **result) 
 {
-    unsigned int tsi_ni, tsr_ni;
-    int bestfit = -1;
-    int best_tsr, best_tsi; 
-    struct end *ei, *er;
-    
-    if(role == INITIATOR) {
-	ei = &sr->this;
-	er = &sr->that;
-    } else {
-	ei = &sr->that;
-	er = &sr->this;
-    }
-	
-    DBG(DBG_CONTROLMORE,
-    {
-	char ei3[SUBNETTOT_BUF];
-	char er3[SUBNETTOT_BUF];
-	subnettot(&ei->client,  0, ei3, sizeof(ei3));
-	subnettot(&er->client,  0, er3, sizeof(er3));
-	DBG_log("  ikev2_eval_conn evaluating "
-		"I=%s:%s:%d/%d R=%s:%d/%d %s"
-		, d->name, ei3, ei->protocol, ei->port
-		, er3, er->protocol, er->port
-		, is_virtual_connection(d) ? "(virt)" : "");
-    }
-    );
-   
-    /* compare tsi/r array to this/that, evaluating how well it fits */
-    for(tsi_ni = 0; tsi_ni < tsi_n; tsi_ni++) {
-	for(tsr_ni=0; tsr_ni<tsr_n; tsr_ni++) {
-	    /* does it fit at all? */
+struct host_pair *hp = NULL;
+struct connection *d;
+unsigned int i; 
+struct end *ei, *er;
+int  bests=0;
+struct connection *bestc=NULL;
+bool specific_first_ts = FALSE;
+
+
+	hp = find_host_pair(&c->spd.this.host_addr
+				, c->spd.this.host_port
+				, &c->spd.that.host_addr
+				, c->spd.that.host_port);
+
+#ifdef DEBUG
+	if (DBGP(DBG_CONTROLMORE))
+	{
+		char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
+
+		subnettot(&c->spd.this.client, 0, s2, sizeof(s2));
+		subnettot(&c->spd.that.client, 0, d2, sizeof(d2));
+
+		DBG_log("  checking hostpair %s -> %s is %s"
+			, s2, d2
+			, (hp ? "found" : "not found"));
+	}
+#endif /* DEBUG */
+
+	if(!hp) {
+		return FALSE;
+	}
+
+	/* check if there is any specific first traffic selector */
+	if( addrcmp(&tsi[0].low, &tsi[0].high)==0 && tsi[0].startport == tsi[0].endport &&  tsi[0].ipprotoid!=0 
+		&& addrcmp(&tsr[0].low, &tsr[0].high)==0 && tsr[0].startport ==  tsr[0].endport &&  tsr[0].ipprotoid!=0) {
+		specific_first_ts = TRUE;
+	}
+
+	/*if(!specific_first_ts && (tsi_n >= 2 || tsr_n >= 2) )
+	{
+		return FALSE;
+	}*/
+
+	for (d = hp->connections; d != NULL; d = d->hp_next)
+	{
+		int wildcards, pathlen;  /* XXX */
+		struct traffic_selector tmp,  tmp2;
+		int curs=0;
+		bool found_one_match_tsi = FALSE, found_one_match_tsr = FALSE;
+		
+		if (d->policy & POLICY_GROUP)
+			continue;
+		
+		if (!(same_id(&c->spd.this.id, &d->spd.this.id)
+		      && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
+		      && trusted_ca(c->spd.that.ca, d->spd.that.ca, &pathlen)))
+		    continue;
+
+
+		if(ikev2_perfect_match_ts(tsi, tsr, tsi_n, tsr_n, d, role)) {
+			*result = d;
+			return TRUE;
+		}
+
+		if(role == INITIATOR) {
+			ei = &d->spd.this;
+			er = &d->spd.that;
+		} else {
+			ei = &d->spd.that;
+			er = &d->spd.this;
+		}
+
+		tmp = ikev2_subnettots(ei);
+
+
+		for(i=0; i<tsi_n; i++) {
+			
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsi[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsi[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsi[i].high) >= 0) 
+			{
+				tmp2.high = tsi[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			if(addrtypeof(&tmp2.low) != addrtypeof(&tmp2.high)) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsi[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsi[i].startport;
+			}
+
+			if(tmp.endport >= tsi[i].endport )
+			{
+				tmp2.endport=tsi[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsi[i].ipprotoid && tmp.ipprotoid!=tsi[i].ipprotoid ) 
+			{
+				continue;
+			}
+
+			curs++;
+			found_one_match_tsi = TRUE;
+		}
+
+		tmp = ikev2_subnettots(er);
+		for(i=0; i<tsr_n; i++) {
+		
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsr[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsr[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsr[i].high) >= 0) 
+			{
+				tmp2.high = tsr[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			if(addrtypeof(&tmp2.low) != addrtypeof(&tmp2.high)) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsr[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsr[i].startport;
+			}
+
+			if(tmp.endport >= tsr[i].endport )
+			{
+				tmp2.endport=tsr[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsr[i].ipprotoid && tmp.ipprotoid!=tsr[i].ipprotoid ) 
+			{
+				continue;
+			}
+
+			curs++;
+			found_one_match_tsr = TRUE;
 
+		}
+
+		if(curs > bests && found_one_match_tsi && found_one_match_tsr) 
+		{
+		bests = curs;
+		bestc = d;
+
+		}
+	}
+
+	if(bestc == NULL) {
+		return FALSE;
+	}
+
+	/* creating narrowed traffic selector */
+	{
+		struct traffic_selector tmp,  tmp2, *tmp3;
+
+		*result = bestc;
+
+		if(role == INITIATOR) {
+			ei = &bestc->spd.this;
+			er = &bestc->spd.that;
+		} else {
+			ei = &bestc->spd.that;
+			er = &bestc->spd.this;
+		}
+
+
+		tmp = ikev2_subnettots(ei);
+		for(i=0; i<tsi_n; i++) {
+		
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsi[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsi[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsi[i].high) >= 0) 
+			{
+				tmp2.high = tsi[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsi[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsi[i].startport;
+			}
+
+			if(tmp.endport >= tsi[i].endport )
+			{
+				tmp2.endport=tsi[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* as openswan supports only single port, so picking one port*/
+			if( tmp2.startport > 0){
+				tmp2.endport = tmp2.startport;
+			}
+			else if (tmp2.endport < 65535 ){
+				tmp2.startport = tmp2.endport;
+			}
+
+			/* protocol */
+			if( tmp.ipprotoid > 0 && tsi[i].ipprotoid > 0 && tmp.ipprotoid!=tsi[i].ipprotoid) 
+			{
+				continue;
+			}
+			else if(tmp.ipprotoid == 0)
+			{			
+				tmp2.ipprotoid = tsi[i].ipprotoid;
+			} 
+			else 
+			{
+				tmp2.ipprotoid = tmp.ipprotoid;
+			}
+
+			/*setting type */
+			switch(tmp2.low.u.v4.sin_family) {
+			case AF_INET:
+				tmp2.sin_family = ID_IPV4_ADDR_RANGE;
+				break;
+			case AF_INET6:
+				tmp2.sin_family = ID_IPV6_ADDR_RANGE;
+				break;
+			}		
+
+			tmp3 = alloc_thing(struct traffic_selector, "struct traffic_selector");
+			*tmp3 = tmp2;
+			tmp3->next = NULL;
+			
+			if(*narrowed_tsi == NULL)
+			{
+				*narrowed_tsi = tmp3;
+			}
+			else
+			{
+				struct traffic_selector *tmp4 = *narrowed_tsi;
+				while(tmp4->next!=NULL){
+				tmp4 = tmp4->next;
+				}
+				tmp4->next = tmp3;
+				
+			}
+		}
+
+		tmp = ikev2_subnettots(er);
+		for(i=0; i<tsr_n; i++) {
+			
+			/* ip address */
+			if(addrcmp(&tmp.low, &tsr[i].low) >= 0) 
+			{
+				tmp2.low = tmp.low;
+			}
+			else
+			{
+				tmp2.low = tsr[i].low;
+			}
+
+			if(addrcmp(&tmp.high, &tsr[i].high) >= 0) 
+			{
+				tmp2.high = tsr[i].high;
+			}			
+			else
+			{
+				tmp2.high = tmp.high;
+			}
+
+			if(addrcmp(&tmp2.low, &tmp2.high) > 0) {
+				continue;
+			}
+
+			/* port */
+			if(tmp.startport >= tsr[i].startport ) 
+			{
+				tmp2.startport=tmp.startport;
+			}
+			else 
+			{
+				tmp2.startport=tsr[i].startport;
+			}
+
+			if(tmp.endport >= tsr[i].endport )
+			{
+				tmp2.endport=tsr[i].endport;
+			}
+			else
+			{
+				tmp2.endport=tmp.endport;
+			}
+		
+			if(tmp2.startport >  tmp2.endport) 
+			{
+				continue;
+			}
+
+			/* as openswan supports only single port, so picking one port*/
+			if( tmp2.startport > 0){
+				tmp2.endport = tmp2.startport;
+			}
+			else if (tmp2.endport < 65535 ){
+				tmp2.startport = tmp2.endport;
+			}
+
+			/* protocol */
+			if( !tmp.ipprotoid && !tsr[i].ipprotoid && tmp.ipprotoid!=tsr[i].ipprotoid ) 
+			{
+				continue;
+			}
+			else if(tmp.ipprotoid == 0)
+			{			
+				tmp2.ipprotoid = tsr[i].ipprotoid;
+			} 
+			else 
+			{
+				tmp2.ipprotoid = tmp.ipprotoid;
+			}
+
+			/*setting type */
+			switch(tmp2.low.u.v4.sin_family) {
+			case AF_INET:
+				tmp2.sin_family = ID_IPV4_ADDR_RANGE;
+				break;
+			case AF_INET6:
+				tmp2.sin_family = ID_IPV6_ADDR_RANGE;
+				break;
+			}
+
+			tmp3 = alloc_thing(struct traffic_selector, "struct traffic_selector");
+			*tmp3 = tmp2;
+			tmp3->next = NULL;
+			
+			if(*narrowed_tsr == NULL)
+			{
+				*narrowed_tsr = tmp3;
+			}
+			else
+			{
+				struct traffic_selector *tmp4 = *narrowed_tsr;
+				while(tmp4->next!=NULL){
+				tmp4 = tmp4->next;
+				}
+				
+				tmp4->next = tmp3;		
+			}
+
+		}
+	}
+
+	struct traffic_selector *tmp;
+	tmp = *narrowed_tsi;
+	while(tmp!= NULL) {
+		
 	    DBG(DBG_CONTROLMORE,
 	    {
 		char lbi[ADDRTOT_BUF];
 		char hbi[ADDRTOT_BUF];
-		char lbr[ADDRTOT_BUF];
-		char hbr[ADDRTOT_BUF];
-		addrtot(&tsi[tsi_ni].low,  0, lbi, sizeof(lbi));
-		addrtot(&tsi[tsi_ni].high, 0, hbi, sizeof(hbi));
-		addrtot(&tsr[tsr_ni].low,  0, lbr, sizeof(lbr));
-		addrtot(&tsr[tsr_ni].high, 0, hbr, sizeof(hbr));
-		
-		DBG_log("    tsi[%u]=%s/%s tsr[%u]=%s/%s "
-			, tsi_ni, lbi, hbi
-			, tsr_ni, lbr, hbr);
+		addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+		addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+		
+		DBG_log("    tsi=%s/%s, port=%d/%d, protocol=%d"
+			,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
 	    }
 	    );
-	    /* do addresses fit into the policy? */
-	    if(addrinsubnet(&tsi[tsi_ni].low, &ei->client)
-	       && addrinsubnet(&tsi[tsi_ni].high, &ei->client)
-	       && addrinsubnet(&tsr[tsr_ni].low,  &er->client)
-	       && addrinsubnet(&tsr[tsr_ni].high, &er->client))
+
+	tmp=tmp->next;
+	}
+
+	tmp = *narrowed_tsr;
+	while(tmp!= NULL) {
+		
+	    DBG(DBG_CONTROLMORE,
 	    {
-		/*
-		 * now, how good a fit is it? --- sum of bits gives
-		 * how good a fit this is.
-		 */
-		int ts_range1 = ikev2_calc_iprangediff(tsi[tsi_ni].low
-						      , tsi[tsi_ni].high);
-		int maskbits1 = ei->client.maskbits;
-		int fitbits1  = maskbits1 + ts_range1;
-
-		int ts_range2 = ikev2_calc_iprangediff(tsr[tsr_ni].low
-						      , tsr[tsr_ni].high);
-		int maskbits2 = er->client.maskbits;
-		int fitbits2  = maskbits2 + ts_range2;
-		int fitbits = (fitbits1 << 8) + fitbits2;
-
-		/*
-		 * comparing for ports
-		 * for finding better local polcy
-		 */
-
-		if( ei->port && (tsi[tsi_ni].startport == ei->port && tsi[tsi_ni].endport == ei->port)) {
-		fitbits = fitbits << 1;
-		}
+		char lbi[ADDRTOT_BUF];
+		char hbi[ADDRTOT_BUF];
+		addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+		addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+		
+		DBG_log("    tsr=%s/%s, port=%d/%d, protocol=%d"
+			,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+	    }
+	    );
 
-		if( er->port && (tsr[tsr_ni].startport == er->port && tsr[tsr_ni].endport == er->port)) {
-		fitbits = fitbits << 1;
-		}
+	tmp=tmp->next;
+	}
+	return TRUE;
+}
 
-		DBG(DBG_CONTROLMORE,
-		{
-		    DBG_log("      has ts_range1=%u maskbits1=%u ts_range2=%u maskbits2=%u fitbits=%d <> %d"
-			    , ts_range1, maskbits1, ts_range2, maskbits2
-			    , fitbits, bestfit);
-		}
-		);
-
-		if(fitbits > bestfit) {
-		    best_tsi = tsi_ni;
-		    best_tsr = tsr_ni;
-		    bestfit = fitbits;
+struct connection *
+ikev2_create_narrowed_con(struct connection *c
+			, struct traffic_selector *narrowed_tsi
+			, struct traffic_selector *narrowed_tsr
+			, enum phase1_role role)
+{
+	struct connection *narrowed_con=NULL;
+	struct spd_route *tmp_spd=NULL, *tmp_spd1=NULL;
+	struct traffic_selector *tmptsi=NULL, *tmptsr=NULL;
+
+	narrowed_con = ikev2_narrow_instantiate(c);
+	
+	/* setup spds for narrowed connection*/
+	tmp_spd1 = NULL;
+	tmp_spd = &narrowed_con->spd;
+	tmptsi = narrowed_tsi;
+	
+	while(tmptsi != NULL) {
+		ip_subnet tmpsubneti;
+		rangetosubnet(&tmptsi->low, &tmptsi->high, &tmpsubneti);
+		tmptsr = narrowed_tsr;
+
+		while(tmptsr != NULL ) {
+			ip_subnet tmpsubnetr;
+			rangetosubnet(&tmptsr->low, &tmptsr->high, &tmpsubnetr);		
+
+			if(tmp_spd == NULL) {
+				struct spd_route *tmp_spd2 = clone_thing(narrowed_con->spd, "spds from narrowed ts");
+				tmp_spd = tmp_spd2;
+				tmp_spd->next = NULL;
+
+				if(tmp_spd1!= NULL){
+					tmp_spd1->next = tmp_spd;
+				}
+
+				if(tmp_spd != &narrowed_con->spd) {
+				tmp_spd->this.id.name.ptr = NULL;
+				tmp_spd->this.id.name.len = 0;
+                    		tmp_spd->that.id.name.ptr = NULL;
+                    		tmp_spd->that.id.name.len = 0;			
+
+				tmp_spd->this.host_addr_name = NULL;
+				tmp_spd->that.host_addr_name = NULL;
+
+				tmp_spd->this.updown = clone_str(tmp_spd->this.updown, "updown");
+				tmp_spd->that.updown = clone_str(tmp_spd->that.updown, "updown");
+
+				tmp_spd->this.cert_filename = NULL;
+				tmp_spd->that.cert_filename = NULL;
+
+				tmp_spd->this.cert.type = 0;
+				tmp_spd->that.cert.type = 0;
+
+				tmp_spd->this.ca.ptr = NULL;
+				tmp_spd->that.ca.ptr = NULL;
+
+				tmp_spd->this.groups = NULL;
+				tmp_spd->that.groups = NULL;
+
+				tmp_spd->this.virt = NULL;
+				tmp_spd->that.virt = NULL;
+				}
+			}
+
+			if(role == INITIATOR) {
+				tmp_spd->this.client = tmpsubneti;
+				tmp_spd->this.port = tmptsi->startport;
+				tmp_spd->this.protocol = tmptsi->ipprotoid;
+				if( subnetishost(&tmp_spd->this.client) && addrinsubnet(&tmp_spd->this.host_addr, &tmp_spd->this.client)) {
+				tmp_spd->this.has_client = FALSE;
+				}
+				else {
+				tmp_spd->this.has_client = TRUE;
+				}
+				tmp_spd->this.has_client_wildcard =  FALSE;
+				tmp_spd->this.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.host_addr);
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.client.addr);
+
+				tmp_spd->that.client = tmpsubnetr;
+				tmp_spd->that.port = tmptsr->startport;
+				tmp_spd->that.protocol = tmptsr->ipprotoid;
+				if( subnetishost(&tmp_spd->that.client) && addrinsubnet(&tmp_spd->that.host_addr, &tmp_spd->that.client)) {
+				tmp_spd->that.has_client = FALSE;
+				}
+				else {
+				tmp_spd->that.has_client = TRUE;
+				}
+				tmp_spd->that.has_client_wildcard =  FALSE;
+				tmp_spd->that.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.host_addr);
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.client.addr);		
+			}
+			else {
+				tmp_spd->this.client = tmpsubnetr;
+				tmp_spd->this.port = tmptsr->startport;
+				tmp_spd->this.protocol = tmptsr->ipprotoid;
+				if( subnetishost(&tmp_spd->this.client) && addrinsubnet(&tmp_spd->this.host_addr, &tmp_spd->this.client)) {
+				tmp_spd->this.has_client = FALSE;
+				}
+				else {
+				tmp_spd->this.has_client = TRUE;
+				}
+				tmp_spd->this.has_client_wildcard =  FALSE;
+				tmp_spd->this.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.host_addr);
+				setportof(htons(tmp_spd->this.port), &tmp_spd->this.client.addr);
+
+				tmp_spd->that.client = tmpsubneti;
+				tmp_spd->that.port = tmptsi->startport;
+				tmp_spd->that.protocol = tmptsi->ipprotoid;
+				if( subnetishost(&tmp_spd->that.client) && addrinsubnet(&tmp_spd->that.host_addr, &tmp_spd->that.client)) {
+				tmp_spd->that.has_client = FALSE;
+				}
+				else {
+				tmp_spd->that.has_client = TRUE;
+				}
+				tmp_spd->that.has_client_wildcard =  FALSE;
+				tmp_spd->that.has_port_wildcard = FALSE;
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.host_addr);
+				setportof(htons(tmp_spd->that.port), &tmp_spd->that.client.addr);
+			}
+
+		tmp_spd1 = tmp_spd;
+		tmp_spd = tmp_spd1->next;
+		tmptsr = tmptsr->next;	
 		}
-	    }
+	tmptsi = tmptsi->next;
 	}
-    }
 
-    return bestfit;
+                    char buftest[ADDRTOT_BUF];
+                    tmp_spd = &narrowed_con->spd;
+                    int count_spd=0;
+                    do {
+                        DBG(DBG_CONTROLMORE, DBG_log("spd route number: %d", ++count_spd));
+
+                        /**that info**/
+                	DBG(DBG_CONTROLMORE, DBG_log("that id kind: %d",tmp_spd->that.id.kind));
+                	DBG(DBG_CONTROLMORE, 
+				DBG_log("that id ipaddr: %s", (addrtot(&tmp_spd->that.id.ip_addr, 0, buftest, sizeof(buftest)), buftest)));
+
+                	if (tmp_spd->that.id.name.ptr != NULL) {
+                	DBG(DBG_CONTROLMORE, DBG_dump_chunk("that id name",tmp_spd->that.id.name));
+                	}
+
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("that host_addr: %s", (addrtot(&tmp_spd->that.host_addr, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("that nexthop: %s", (addrtot(&tmp_spd->that.host_nexthop, 0, buftest, sizeof(buftest)), buftest)));
+                        DBG(DBG_CONTROLMORE,
+                	    DBG_log("that srcip: %s", (addrtot(&tmp_spd->that.host_srcip, 0, buftest, sizeof(buftest)), buftest)));
+                        DBG(DBG_CONTROLMORE,
+                	    DBG_log("that client_addr: %s, maskbits:%d", (addrtot(&tmp_spd->that.client.addr, 0, 
+							buftest, sizeof(buftest)), buftest),tmp_spd->that.client.maskbits));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_client: %d", tmp_spd->that.has_client));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_client_wildcard: %d", tmp_spd->that.has_client_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_port_wildcard: %d", tmp_spd->that.has_port_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("that has_id_wildcards: %d", tmp_spd->that.has_id_wildcards));
+
+                	/**this info**/
+                	DBG(DBG_CONTROLMORE, DBG_log("this id kind: %d",tmp_spd->this.id.kind));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this id ipaddr: %s", (addrtot(&tmp_spd->this.id.ip_addr, 0, buftest, sizeof(buftest)), buftest)));
+
+                	if (tmp_spd->this.id.name.ptr != NULL) {
+                	DBG_dump_chunk("this id name",tmp_spd->this.id.name);
+                	}
+
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this host_addr: %s", (addrtot(&tmp_spd->this.host_addr, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this nexthop: %s", (addrtot(&tmp_spd->this.host_nexthop, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, 
+                            DBG_log("this srcip: %s", (addrtot(&tmp_spd->this.host_srcip, 0, buftest, sizeof(buftest)), buftest)));
+                	DBG(DBG_CONTROLMORE, DBG_log("this client_addr: %s, maskbits:%d", (addrtot(&tmp_spd->this.client.addr, 
+								0, buftest, sizeof(buftest)), buftest),tmp_spd->this.client.maskbits));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_client: %d", tmp_spd->this.has_client));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_client_wildcard: %d", tmp_spd->this.has_client_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_port_wildcard: %d", tmp_spd->this.has_port_wildcard));
+                	DBG(DBG_CONTROLMORE, DBG_log("this has_id_wildcards: %d", tmp_spd->this.has_id_wildcards));
+
+                        tmp_spd = tmp_spd->next;
+		    } while(tmp_spd!=NULL);
+
+	return narrowed_con;
 }
 
+
+
 stf_status ikev2_child_sa_respond(struct msg_digest *md
 				  , enum phase1_role role
 				  , pb_stream *outpbs)
 <at>  <at>  -424,8 +1159,11  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     stf_status ret;
     struct payload_digest *const tsi_pd = md->chain[ISAKMP_NEXT_v2TSi];
     struct payload_digest *const tsr_pd = md->chain[ISAKMP_NEXT_v2TSr];
-    struct traffic_selector tsi[16], tsr[16];
+    struct traffic_selector tsi[16], tsr[16], *narrowed_tsi=NULL, *narrowed_tsr=NULL;
+    struct connection *narrowed_con=NULL, *result=NULL;
     unsigned int tsi_n, tsr_n;
+    bool ts_negotiation_failed = FALSE;
+
 
     st1 = duplicate_state(st);
 
 <at>  <at>  -436,101 +1174,44  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     tsi_n = ikev2_parse_ts(tsi_pd, tsi, 16);
     tsr_n = ikev2_parse_ts(tsr_pd, tsr, 16);
 
-    /*
-     * now walk through all connections and see if this connection
-     * was in fact the best.
-     *
-     * similar to find_client_connection/fc_try.
-     */
-    {
-	struct connection *b = c;
-	struct connection *d;
-	int bestfit, newfit;
-	struct spd_route *sra, *bsr;
-	struct host_pair *hp = NULL;
-
-	bsr = NULL;
-	bestfit = -1;
-	for (sra = &c->spd; sra != NULL; sra = sra->next)
-	{
-	    int bfit=ikev2_evaluate_connection_fit(c,sra,role
-						   ,tsi,tsr,tsi_n,tsr_n);
-	    if(bfit > bestfit) {
-		bestfit = bfit;
-		b = c;
-		bsr = sra;
-	    }
-	}
-
-	for (sra = &c->spd; hp==NULL && sra != NULL; sra = sra->next)
-	{
-	    hp = find_host_pair(&sra->this.host_addr
-				, sra->this.host_port
-				, &sra->that.host_addr
-				, sra->that.host_port);
-
-#ifdef DEBUG
-	    if (DBGP(DBG_CONTROLMORE))
-	    {
-		char s2[SUBNETTOT_BUF],d2[SUBNETTOT_BUF];
-
-		subnettot(&sra->this.client, 0, s2, sizeof(s2));
-		subnettot(&sra->that.client, 0, d2, sizeof(d2));
+    if(ikev2_narrowing(c, role, tsi, tsr, tsi_n, tsr_n, &narrowed_tsi , &narrowed_tsr, &result)){
 
-		DBG_log("  checking hostpair %s -> %s is %s"
-			, s2, d2
-			, (hp ? "found" : "not found"));
-	    }
-#endif /* DEBUG */
-
-	    if(!hp) continue;
-
-	    for (d = hp->connections; d != NULL; d = d->hp_next)
-	    {
-		struct spd_route *sr;
-		int wildcards, pathlen;  /* XXX */
-		
-		if (d->policy & POLICY_GROUP)
-		    continue;
-		
-		if (!(same_id(&c->spd.this.id, &d->spd.this.id)
-		      && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
-		      && trusted_ca(c->spd.that.ca, d->spd.that.ca, &pathlen)))
-		    continue;
+	if(narrowed_tsi == NULL && narrowed_tsr == NULL && result!= NULL) {
+	/*found exact match */
+		narrowed_con = result;
+
+		/*preparing traffic selectors (need to do: free first narrowed_ts here) */
+		st1->st_ts_this= ikev2_subnettots(&result->spd.this);
+		st1->st_ts_that= ikev2_subnettots(&result->spd.that);
+	}
+	else {
+		narrowed_con = ikev2_create_narrowed_con(result, narrowed_tsi, narrowed_tsr, role);
 
-		
-		for (sr = &d->spd; sr != NULL; sr = sr->next) {
-		    newfit=ikev2_evaluate_connection_fit(d,sr,role
-							 ,tsi,tsr,tsi_n,tsr_n);
-		    if(newfit > bestfit) {
-			bestfit = newfit;
-			b=d;
-			bsr = sr;
-		    }
+		/*preparing traffic selectors (need to do: free first narrowed_ts here) */
+		if(role == INITIATOR) {
+		st1->st_ts_this= *narrowed_tsi;
+		st1->st_ts_that= *narrowed_tsr;
 		}
-	    }
-	}
-	
-	/*
-	 * now that we have found the best connection, copy the data into
-	 * the state structure as the tsi/tsr
-	 *
-	 */
-
-	/*better connection*/
-	c=b;
-
-	/* Paul: should we STF_FAIL here instead of checking for NULL */
-	if (bsr != NULL) {
-		st1->st_ts_this = ikev2_subnettots(&bsr->this);
-		st1->st_ts_that = ikev2_subnettots(&bsr->that);
+		else {
+		st1->st_ts_this= *narrowed_tsr;
+		st1->st_ts_that= *narrowed_tsi;
+		}
+
+		pfreeany(narrowed_tsi);
+		pfreeany(narrowed_tsr);
 	}
     }
+    else {
+	ts_negotiation_failed = TRUE;
+    }
+
+    if(narrowed_con!= NULL && !ts_negotiation_failed) {	
+    c = narrowed_con; 
+    }
 
     st1->st_connection = c;
+    st1->st_childsa = NULL;
     insert_state(st1);
-    md->st = st1;
-    md->pst= st;
 
     /* start of SA out */
     {
 <at>  <at>  -538,7 +1219,13  <at>  <at>  stf_status ikev2_child_sa_respond(struct
 	notification_t rn;
 	pb_stream r_sa_pbs;
 
-	r_sa.isasa_np = ISAKMP_NEXT_v2TSi;  
+	if(ts_negotiation_failed) {
+	r_sa.isasa_np = ISAKMP_NEXT_v2N;
+	}
+	else {
+	r_sa.isasa_np = ISAKMP_NEXT_v2TSi;
+	}
+  
 	if (!out_struct(&r_sa, &ikev2_sa_desc, outpbs, &r_sa_pbs))
 	    return STF_INTERNAL_ERROR;
 
 <at>  <at>  -550,6 +1237,21  <at>  <at>  stf_status ikev2_child_sa_respond(struct
 	    return STF_FAIL + rn;
     }
 
+    if(ts_negotiation_failed) {
+	chunk_t child_spi, notifiy_data;
+	memset(&child_spi, 0, sizeof(child_spi));
+	memset(&notifiy_data, 0, sizeof(notifiy_data));
+	ship_v2N (ISAKMP_NEXT_NONE, ISAKMP_PAYLOAD_NONCRITICAL, /*PROTO_ISAKMP*/ 0,
+			&child_spi,
+			TS_UNACCEPTABLE, &notifiy_data, outpbs);
+	change_state(st1, STATE_CHILDSA_DEL);
+	delete_state(st1);
+	return STF_OK;
+    }
+
+    md->st = st1;
+    md->pst= st;
+
     ret = ikev2_calc_emit_ts(md, outpbs, role
 			     , c, c->policy);
     if(ret != STF_OK) return ret;
 <at>  <at>  -590,6 +1292,8  <at>  <at>  stf_status ikev2_child_sa_respond(struct
     if(!install_ipsec_sa(st1, TRUE))
 	return STF_FATAL;
 
+    st1->st_childsa = c;
+
     /* mark the connection as now having an IPsec SA associated with it. */
     st1->st_connection->newest_ipsec_sa = st1->st_serialno;
 
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2.h openswan-2.6.32-current/programs/pluto/ikev2.h
--- openswan-2.6.32-patched/programs/pluto/ikev2.h	2012-03-27 11:57:45.510034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2.h	2012-04-11 14:54:06.491048277 -0400
 <at>  <at>  -119,20 +119,44  <at>  <at>  extern stf_status ikev2_verify_psk_auth(
 				   , unsigned char *idhash
 				   , pb_stream *sig_pbs);
 
+extern int ikev2_parse_ts(struct payload_digest *const ts_pd
+			, struct traffic_selector *array
+			, unsigned int array_max);
+
 extern stf_status ikev2_emit_ipsec_sa(struct msg_digest *md
 				      , pb_stream *outpbs
 				      , unsigned int np
 				      , struct connection *c
 				      , lset_t policy);
 
+extern struct connection *ikev2_create_narrowed_con(struct connection *c
+					, struct traffic_selector *narrowed_tsi
+					, struct traffic_selector *narrowed_tsr
+					, enum phase1_role role);
+
 extern void ikev2_derive_child_keys(struct state *st
 				    , enum phase1_role role);
 
+extern bool
+ikev2_perfect_match_ts(struct traffic_selector *tsi
+		,struct traffic_selector *tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct connection *c
+		, enum phase1_role role);
+
 extern stf_status ikev2_emit_ts(struct msg_digest *md 
 				, pb_stream *outpbs   
 				, unsigned int np
 				, struct traffic_selector *ts
 				, enum phase1_role role);
+extern void 
+ikev2_store_ts_instate(struct traffic_selector *array_tsi
+		,struct traffic_selector * array_tsr
+		, unsigned int tsi_n
+		, unsigned int tsr_n
+		, struct traffic_selector *ts_this 
+		, struct traffic_selector *ts_that);
 
 extern stf_status ikev2_calc_emit_ts(struct msg_digest *md
 				     , pb_stream *outpbs
 <at>  <at>  -140,6 +164,14  <at>  <at>  extern stf_status ikev2_calc_emit_ts(str
 				     , struct connection *c0
 				     , lset_t policy);
 
+extern bool ikev2_verify_ts(struct traffic_selector *tsi
+			, struct traffic_selector *tsr
+			, unsigned int tsi_n
+			, unsigned int tsr_n
+			, struct traffic_selector *this_ts
+			, struct traffic_selector *that_ts
+			, enum phase1_role role);
+
 extern stf_status ikev2_child_sa_respond(struct msg_digest *md
 					 , enum phase1_role role
 					 , pb_stream *outpbs);
diff -urNp openswan-2.6.32-patched/programs/pluto/ikev2_parent.c openswan-2.6.32-current/programs/pluto/ikev2_parent.c
--- openswan-2.6.32-patched/programs/pluto/ikev2_parent.c	2012-03-27 11:57:45.523034832 -0400
+++ openswan-2.6.32-current/programs/pluto/ikev2_parent.c	2012-04-11 14:59:59.578837143 -0400
 <at>  <at>  -768,7 +768,7  <at>  <at>  ikev2_parent_inI1outR1_tail(struct pluto
 	rn=accept_KE(&st->st_gi, "Gi", st->st_oakley.group, keyex_pbs);
 	if(rn != NOTHING_WRONG) {
 	u_int16_t group_number = htons(st->st_oakley.group->group);
-	dc.ptr = (char *)&group_number;
+	dc.ptr = (u_char *)&group_number;
 	dc.len = 2;
 	SEND_NOTIFICATION_AA(INVALID_KE_PAYLOAD, &dc);
 	delete_state(st);
 <at>  <at>  -1417,7 +1417,7  <at>  <at>  ikev2_parent_inR1outI2_tail(struct pluto
 	 * SA2i, TSi and TSr and (USE_TRANSPORT_MODE notification in transport mode) for it .
 	 */
 	if(c0) {
-		chunk_t child_spi, notifiy_data;
+	    chunk_t child_spi, notifiy_data;
 	    st->st_connection = c0;
 
 	    ikev2_emit_ipsec_sa(md,&e_pbs_cipher,ISAKMP_NEXT_v2TSi,c0, policy);
 <at>  <at>  -1908,6 +1908,8  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
     struct connection *c = st->st_connection;
     unsigned char *idhash_in;
     struct state *pst = st;
+    struct traffic_selector tsi[16], tsr[16];
+    unsigned int tsi_n=0, tsr_n=0;
 
     if(st->st_clonedfrom != 0) {
 	pst = state_with_serialno(st->st_clonedfrom);
 <at>  <at>  -2015,6 +2017,28  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
      */
     change_state(pst, STATE_PARENT_I3);
     c->newest_isakmp_sa = pst->st_serialno;
+
+    {
+	/*check for child sa related errors */
+	/* check for TS_UNACCEPTABLE */
+	struct payload_digest *p;
+
+	for(p = md->chain[ISAKMP_NEXT_v2N]; p != NULL; p = p->next)
+	{
+		if ( p->payload.v2n.isan_type == TS_UNACCEPTABLE ) {
+			/* we can proceed with successful parent SA */
+			if(st->st_clonedfrom != 0) {
+				delete_event(st);
+				pst = state_with_serialno(st->st_clonedfrom);
+				md->st = pst;
+				md->pst = pst;
+				delete_event(st);
+				delete_state(st);
+			}
+			return STF_OK;
+		}  
+	}
+    }
     
     /* authentication good, see if there is a child SA available */
     if(md->chain[ISAKMP_NEXT_v2SA] == NULL
 <at>  <at>  -2025,8 +2049,37  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
 	/*
 	 * Delete previous retransmission event.
 	 */
+	if(st->st_clonedfrom != 0) {
+		pst = state_with_serialno(st->st_clonedfrom);
+		md->st = pst;
+		md->pst = pst;
+		delete_event(st);
+		delete_state(st);
+	}
+	return STF_OK;
+    }
+
+    {
+	struct payload_digest *const tsi_pd = md->chain[ISAKMP_NEXT_v2TSi];
+	struct payload_digest *const tsr_pd = md->chain[ISAKMP_NEXT_v2TSr];
+
+	/* parse traffic selector */
+
+	tsi_n = ikev2_parse_ts(tsi_pd, tsi, 16);
+	tsr_n = ikev2_parse_ts(tsr_pd, tsr, 16);
+
+	/* verify if the received traffic selectors are 
+	 * really same/or a subset of what we sent 
+	 */
+	if(ikev2_verify_ts(tsi, tsr, tsi_n, tsr_n
+			, &st->st_ts_this, &st->st_ts_that
+			, md->role) == FALSE) {
+	/* mistmatch in received selectors */
+	/*only proceeding with parent SA*/
 	delete_event(st);
 	return STF_OK;
+	}
+
     }
 
     {
 <at>  <at>  -2078,15 +2131,100  <at>  <at>  stf_status ikev2parent_inR2(struct msg_d
 
     } /*notification block */
 
-	
-    ikev2_derive_child_keys(st, md->role);
+    {
+	/*storing received traffic selectors */
 
-    c->newest_ipsec_sa = st->st_serialno;
+	struct traffic_selector *tmp;
+	unsigned int i=0;
+
+
+	ikev2_store_ts_instate(tsi, tsr, tsi_n, tsr_n, &st->st_ts_this, &st->st_ts_that);
+
+	for(i=0; i< tsi_n; i++) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tsi[i].low,  0, lbi, sizeof(lbi));
+                addrtot(&tsi[i].high, 0, hbi, sizeof(hbi));
+
+                DBG_log("tsi=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tsi[i].startport, tsi[i].endport, tsi[i].ipprotoid);
+            }
+            );
+
+	}
+       
+	for(i=0; i< tsr_n; i++) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tsr[i].low,  0, lbi, sizeof(lbi));
+                addrtot(&tsr[i].high, 0, hbi, sizeof(hbi));
+    
+                DBG_log("tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tsr[i].startport, tsr[i].endport, tsr[i].ipprotoid);
+            }
+            );
+
+	}
+
+
+	tmp = &st->st_ts_this;
+
+        while(tmp!= NULL) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+                addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+
+                DBG_log(" R2  this  tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+            }
+            );
+
+        tmp=tmp->next;
+        }
+
+        tmp = &st->st_ts_that;
+        while(tmp!= NULL) {
+
+            DBG(DBG_CONTROLMORE,
+            {
+                char lbi[ADDRTOT_BUF];
+                char hbi[ADDRTOT_BUF];
+                addrtot(&tmp->low,  0, lbi, sizeof(lbi));
+                addrtot(&tmp->high, 0, hbi, sizeof(hbi));
+
+                DBG_log(" R2  that  tsr=%s/%s, port=%d/%d, protocol=%d"
+                        ,  lbi, hbi, tmp->startport, tmp->endport, tmp->ipprotoid);
+            }
+            );
+
+        tmp=tmp->next;
+        }
+
+	if(!ikev2_perfect_match_ts(tsi, tsr, tsi_n, tsr_n, c, md->role)) {
+		c = ikev2_create_narrowed_con(c, &st->st_ts_this, &st->st_ts_that, md->role);
+		st->st_connection = c;
+	}
+
+    }
+
+    ikev2_derive_child_keys(st, md->role);
 
     /* now install child SAs */
     if(!install_ipsec_sa(st, TRUE))
 	return STF_FATAL;
 
+    st->st_childsa = c;
+    c->newest_ipsec_sa = st->st_serialno;
     /*
      * Delete previous retransmission event.
      */
 <at>  <at>  -2408,7 +2546,6  <at>  <at>  stf_status process_informational_ikev2(s
 				pb_stream del_pbs;
 				struct ikev2_delete v2del_tmp;
 				u_int16_t i, j=0;
-				bool bogus;
 				u_char *spi;
 
 				for(i = 0; i < v2del->isad_nospi; i++ ) 
 <at>  <at>  -2577,6 +2714,8  <at>  <at>  stf_status process_informational_ikev2(s
 					else
 					{
 						change_state(current_st, STATE_IKESA_DEL);
+						md->st = NULL;
+						md->pst = NULL;
 					}
         			delete_state(current_st);
 				current_st = next_st;
 <at>  <at>  -2587,11 +2726,7  <at>  <at>  stf_status process_informational_ikev2(s
 			case PROTO_IPSEC_AH:
 			case PROTO_IPSEC_ESP:
 				{				
-				char spi_buf[1024];
-				//pb_stream del_pbs;
-				struct ikev2_delete v2del_tmp;
 				u_int16_t i;
-				bool bogus;
 				u_char *spi;
 
 				for(i = 0; i < v2del->isad_nospi; i++ ) 
 <at>  <at>  -2671,6 +2806,8  <at>  <at>  stf_status process_informational_ikev2(s
 					else
 					{
 						change_state(current_st, STATE_IKESA_DEL);
+						md->st = NULL;
+						md->pst = NULL;
 					}
         			delete_state(current_st);
 				current_st = next_st;
 <at>  <at>  -2756,8 +2893,6  <at>  <at>  void ikev2_delete_out(struct state *st)
 		role = RESPONDER;
 		}
 
-		//r_hdr.isa_flags  |=  ISAKMP_FLAGS_R;
-
 		if (!out_struct(&r_hdr, &isakmp_hdr_desc, &reply_stream, &rbody))
 		{
 			openswan_log("error initializing hdr for informational message");
diff -urNp openswan-2.6.32-patched/programs/pluto/kernel.c openswan-2.6.32-current/programs/pluto/kernel.c
--- openswan-2.6.32-patched/programs/pluto/kernel.c	2012-02-15 13:36:18.922547577 -0500
+++ openswan-2.6.32-current/programs/pluto/kernel.c	2012-04-11 12:59:13.437176813 -0400
 <at>  <at>  -2021,6 +2021,31  <at>  <at>  setup_half_ipsec_sa(struct state *st, bo
 			      , st->st_connection->policy_label
 #endif
 			      );
+
+	if(st->st_ikev2) {
+	   struct spd_route *sr = &c->spd;
+	   for(sr = sr->next; sr != NULL; sr = sr->next) {
+
+            /* MCR - should be passed a spd_eroute structure here */
+            (void) raw_eroute(&sr->that.host_addr   /* this_host */
+			      , &sr->that.client    /* this_client */
+                              , &sr->this.host_addr /* that_host */
+			      , &sr->this.client    /* that_client */
+                              , inner_spi              /* spi */
+			      , proto                  /* proto */
+                              , sr->this.protocol   /* transport_proto */
+                              , esatype                /* esatype */
+                              , proto_info             /* " */
+			      , 0                      /* lifetime */
+                              , ERO_ADD_INBOUND        /* op */
+			      , "add inbound"        /* opname */
+#ifdef HAVE_LABELED_IPSEC
+			      , st->st_connection->policy_label
+#endif
+			      );
+	   }
+	}
+
         }
     }
 
 <at>  <at>  -2095,6 +2120,7  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
      * first one found.  It may or may not be the only one.
      */
     struct connection *c = st->st_connection;
+    struct spd_route *sr;
     struct {
         unsigned proto;
         struct ipsec_proto_info *info;
 <at>  <at>  -2103,6 +2129,7  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
     bool result;
 
     i = 0;
+
     if (kernel_ops->inbound_eroute && inbound
         && c->spd.eroute_owner == SOS_NOBODY)
     {
 <at>  <at>  -2120,6 +2147,30  <at>  <at>  teardown_half_ipsec_sa(struct state *st,
 			  );
     }
 
+    if(st->st_ikev2) {
+    for(sr = &c->spd.next; sr; sr =sr->next) {
+    if (kernel_ops->inbound_eroute && inbound
+        && sr->eroute_owner == SOS_NOBODY)
+    {
+        (void) raw_eroute(&sr->that.host_addr, &sr->that.client
+                          , &sr->this.host_addr, &sr->this.client
+                          , 256
+			  , IPSEC_PROTO_ANY
+                          , sr->this.protocol
+                          , ET_UNSPEC
+                          , null_proto_info, 0
+                          , ERO_DEL_INBOUND, "delete inbound"
+#ifdef HAVE_LABELED_IPSEC
+			  , c->policy_label
+#endif
+			  );
+    }
+    }
+    }
+
+
+
+
     if (!kernel_ops->grp_sa)
     {
         if (st->st_ah.present)
diff -urNp openswan-2.6.32-patched/programs/pluto/state.c openswan-2.6.32-current/programs/pluto/state.c
--- openswan-2.6.32-patched/programs/pluto/state.c	2012-03-27 11:57:45.531034831 -0400
+++ openswan-2.6.32-current/programs/pluto/state.c	2012-04-11 15:01:27.527784330 -0400
 <at>  <at>  -351,6 +351,19  <at>  <at>  release_whack(struct state *st)
     close_any(st->st_whack_sock);
 }
 
+/* freeing allocated traffic selectors */
+static void delete_ts(struct traffic_selector *ts) {
+	struct traffic_selector *tmp;
+
+	/*first one is not malloced so skiping that*/
+	ts = ts-> next;
+	while(ts!=NULL) {
+		tmp = ts->next;
+		pfreeany(ts);
+		ts = tmp;
+	}
+}
+
 /* delete a state object */
 void
 delete_state(struct state *st)
 <at>  <at>  -511,6 +524,10  <at>  <at>  delete_state(struct state *st)
 	pfreeany(st->st_sec_chunk.ptr);
     }
 
+    /*free selectors if any */
+    delete_ts(&st->st_ts_this);
+    delete_ts(&st->st_ts_that);
+
     freeanychunk(st->st_firstpacket_me);
     freeanychunk(st->st_firstpacket_him);
     freeanychunk(st->st_tpacket);
diff -urNp openswan-2.6.32-patched/programs/pluto/state.h openswan-2.6.32-current/programs/pluto/state.h
--- openswan-2.6.32-patched/programs/pluto/state.h	2012-03-27 11:57:45.532034831 -0400
+++ openswan-2.6.32-current/programs/pluto/state.h	2012-04-10 17:00:05.840320943 -0400
 <at>  <at>  -164,6 +164,7  <at>  <at>  struct traffic_selector {
     u_int16_t endport;
     ip_address low;
     ip_address high;
+    struct traffic_selector *next;
 };
 
 #ifdef HAVE_LABELED_IPSEC
_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Steve Lanser | 11 Apr 15:48
Favicon

[Openswan dev] [slanser <at> tallmaple.com: Re: [Openswan - Bug #1342] Pluto 30-second encrypted TCP connection stall with on-demand peering (NETKEY)]

It certianly sounds like the same issue.

I'll get to this after dealing with some of the higher priority IKEv2
issues.  This issue is a much lower priority for us since we largely aviod
the problem by configuring our connections with auto=start.  Packets issued
after a connection is brought up in this fashion are not subject to delay.

I have confirmed, however, that the behavior is still present in 2.6.38.

Steve

On Tue, Apr 10, 2012 at 03:50:32AM -0400, redmine <at> openswan.org wrote:
> 
> Issue #1342 has been updated by Tuomo Soini.
> 
> Target version changed from Openswan 2.x CVS (HEAD) to Openswan 2.6.39
> 
> Can you try the patch file bug1334.bug from bug #1334 if this is the same issue?
> ----------------------------------------
> Bug #1342: Pluto 30-second encrypted TCP connection stall with on-demand peering (NETKEY)
> https://www.openswan.org/issues/1342#change-2693
> 
> Author: Steve Lanser
> Status: New
> Priority: High
> Assignee: 
> Category: Pluto
> Target version: Openswan 2.6.39
> 
> 
> Create a valid connection on two hosts.  Add the connection on each host, but only ask pluto to "route" the
connection on each end, so that it does not come up automatically, but will come up on demand due to the
policy table (via an IPsec "acquire" event).
> 
> Then either ping or start an ssh connection from one host to the other.
> 
> Pluto receives the acquire message and brings up the peering right away, but the first packet that
triggered the acquire is either dropped, or is delayed for about 30 seconds.
> 
> With both ping and with TCP, there is a 30 second delay between the time the connection is established and
delivery of the 
> first encrypted packet from the initiator to the responder, as seen from tcp dump.
> 
> Interestingly, ping reports no packet loss:
> 
> 9 packets transmitted, 9 received, 0% packet loss, time 8003ms
> rtt min/avg/max/mdev = 0.193/0.255/0.321/0.041 ms
> 
> It almost seems like the packet is held in queue for 30 seconds-- it's not yet clear.
> 
> This issue is consistently reproducible on Openswan 2.6.32, and 2.6.38dr2 under NETKEY.
> 
> In contrast KAME's racoon under NETKEY does not have this delay.  Racoon delays for just over a second--
long enough for the first ping request to time out, and it does:
> 
> --- tb11.tallmaple.com ping statistics ---
> 2 packets transmitted, 1 received, 50% packet loss, time 1000ms
> rtt min/avg/max/mdev = 0.254/0.254/0.254/0.000 ms
> 
> But after ~1.1 seconds, the first encrypted packet (presumably a retransmitted ICMP echo request) is
seen, and ping starts responding.  Similarly, with ssh there is a one second delay, then slogin connects,
so under racoon there's not noticeable disruption.
> 
> Finally note that under pluto this delay can be "avoided" by aborting the first connection attempt and
starting a new one, e.g. if you abort the first connection attempt with a CTRL-C and reissue it, the second
one goes through immediately.
> 
> This is our bug ID 14441.
> 
> Test results are attached.  The initiating peer in each case was tb7 (10.2.0.27) and the receiving peer was
tb11 (10.2.0.31).
> 
> slanser <at> tallmaple.com
> 
> 
> -- 
> You have received this notification because you have either subscribed to it, or are involved in it.
> 

----- End forwarded message -----
Jagdish Motwani | 11 Apr 15:42
Favicon

[Openswan dev] KLIPS tdb_lock as rwlock instead of spinlock?

Hi,   
   Can tdb_lock be converted from spinlock to rwlock?

    From what i know, tdb_lock is used to protect sa. 
                                 ipsec_xmit.c &  ipsec_rcv.c just uses them for reading(get) sa.

                                                            
     While experimenting with KLIPS, i converted this tdb_lock to rwlock_t and performed the below given test.

     I got desired results but i am not sure about any side-effects of this conversion.  Please provide your valuable input.


    Test setup details:
                    LAN1 ----------
                                            Test Machine ----------(Ipsec tunnel)---------------- Road warrior           
                    LAN2 ----------


      Test Machine has 8 cores, I  have binded interrupts to only 3 of them:
                            LAN1 -- cpu1
                            LAN2 -- cpu2
                 Roadwarrior -- cpu3

      Traffic flows from LAN1 and LAN2 to Road warrior. (I used iperf to generate traffic: iperf server is at road warrior and clients in LAN1 and LAN2).
 
  
    Changes done:
              1) in ipsec_tunnel.c
                         dev->tx_queue_len   = 0;        /* No qdisc */   (Earlier it was 10)
                         dev->features |= NETIF_F_LLTX; /* No tx lock */
                      
              2)Converted tdb_lock from spinlock_t to rwlock_t
                         Instead of spin_lock_bh used
                                        read_lock_bh in ipsec_xmit.c and ipsec_rcv.c
                                        write_lock_bh elsewhere
       Got throughput:
         Before Change: 225 Mbps    (cpu1 and cpu2  are  not being 100% utilized) 
         After Change:    350 Mbps    (both cpus1 and cpu2 are being 100% utilized)


    Also, One more question: Is there any know side effect of dev->tx_queue_len=0? Why is it 10  by default?

Regards,
Jagdish Motwani
Software Engineer
Elitecore Technologies Pvt. Ltd.
_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Nrupen Chudasma | 28 Mar 14:39
Picon

[Openswan dev] DPD action restart creates segfault in Roadwarrior connection

Hi,

I am using openswan 2.6.24. I have configured one connection at VPN gateway where many road warriors can connect the tunnel from different IPs.
Below is my configuration.

version 2.0      # conforms to second version of ipsec.conf specification

config setup
        nat_traversal=yes
        oe=off
        protostack=netkey


conn ng
        right=%any
        rightsubnet="vhost:%v:0.0.0.0/0"
        left=10.103.6.71
        leftsubnet=10.1.1.0/255.255.255.0
        leftnexthop=10.103.6.1
        auto=add
        x_rightdynamic=yes
        authby=secret
        compress=no
        failureshunt=drop
        dpddelay=15
        dpdtimeout=60
        dpdaction=restart
        pfs=yes
        ike=aes128-md5-modp1024,aes192-md5-modp1024,aes256-md5-modp1024,aes128-sha1-modp1024,aes192-sha1-modp1024,aes256-sha1-modp1024,3des-md5-modp1024,3des-sha1-modp1024,aes128-md5-modp1536,aes192-md5-modp1536,aes256-md5-modp1536,aes128-sha1-modp1536,aes192-sha1-modp1536,aes256-sha1-modp1536,3des-md5-modp1536,3des-sha1-modp1536,aes128-md5-modp2048,aes192-md5-modp2048,aes256-md5-modp2048,aes128-sha1-modp2048,aes192-sha1-modp2048,aes256-sha1-modp2048,3des-md5-modp2048,3des-sha1-modp2048
        esp=aes128-md5,aes192-md5,aes256-md5,aes128-sha1,aes192-sha1,aes256-sha1,3des-md5,3des-sha1


I have kept dpdaction=restart. After successfully establishing the connection, I plug out the road-warrior from network. So when DPD is hit at my VPN gateway, the dpdaction restart is called.
I get the segfault at this place.
The problem is 100% re creatable.

Find the /var/log/messages for this.

Mar 28 18:03:44 netgenie daemon.err ipsec__plutorun: 003 NAT-Traversal: Trying new style NAT-T
Mar 28 18:03:44 netgenie daemon.err ipsec__plutorun: 003 NAT-Traversal: ESPINUDP(1) setup failed for new style NAT-T family IPv4 (errno=19)
Mar 28 18:03:44 netgenie daemon.err ipsec__plutorun: 003 NAT-Traversal: Trying old style NAT-T
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: packet from 10.103.6.93:4500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-00]
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: packet from 10.103.6.93:4500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-02_n] method set to=106
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: packet from 10.103.6.93:4500: received Vendor ID payload [draft-ietf-ipsec-nat-t-ike-03] method set to=108
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: packet from 10.103.6.93:4500: received Vendor ID payload [RFC 3947] method set to=109
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: packet from 10.103.6.93:4500: received Vendor ID payload [Dead Peer Detection]
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: responding to Main Mode from unknown peer 10.103.6.93
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: transition from state STATE_MAIN_R0 to state STATE_MAIN_R1
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: STATE_MAIN_R1: sent MR1, expecting MI2
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): both are NATed
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: transition from state STATE_MAIN_R1 to state STATE_MAIN_R2
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: STATE_MAIN_R2: sent MR2, expecting MI3
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: Main mode peer ID is ID_IPV4_ADDR: '10.1.2.11'
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[1] 10.103.6.93 #1: switched from "ng" to "ng"
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: deleting connection "ng" instance with peer 10.103.6.93 {isakmp=#0/ipsec=#0}
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: transition from state STATE_MAIN_R2 to state STATE_MAIN_R3
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: STATE_MAIN_R3: sent MR3, ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=aes_128 prf=oakley_md5 group=modp1024}
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: Dead Peer Detection (RFC 3706): enabled
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: the peer proposed: 10.1.1.0/24:0/0 -> 10.1.2.11/32:0/0
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: responding to Quick Mode proposal {msgid:341f6228}
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2:     us: 10.1.1.0/24===10.103.6.71<10.103.6.71>[+S=C]---10.103.6.1
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2:   them: 10.103.6.93[10.1.2.11,+S=C]
Mar 28 18:03:53 netgenie authpriv.debug pluto[19074]: | NAT-OA: 32 tunnel: 0 
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: transition from state STATE_QUICK_R0 to state STATE_QUICK_R1
Mar 28 18:03:53 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: STATE_QUICK_R1: sent QR1, inbound IPsec SA installed, expecting QI2
Mar 28 18:03:54 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: Dead Peer Detection (RFC 3706): enabled
Mar 28 18:03:54 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: transition from state STATE_QUICK_R1 to state STATE_QUICK_R2
Mar 28 18:03:54 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #2: STATE_QUICK_R2: IPsec SA established tunnel mode {ESP=>0xd9d12c60 <0xf1bb6bc0 xfrm=AES_128-HMAC_MD5 NATOA=none NATD=10.103.6.93:4500 DPD=enabled}
Mar 28 18:04:42 netgenie authpriv.warn pluto[19074]: ERROR: asynchronous network error report on eth2.2 (sport=4500) for message to 10.103.6.93 port 4500, complainant 10.103.6.71: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Mar 28 18:04:57 netgenie authpriv.warn pluto[19074]: ERROR: asynchronous network error report on eth2.2 (sport=4500) for message to 10.103.6.93 port 4500, complainant 10.103.6.71: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: DPD: No response from peer - declaring peer dead
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: DPD: Restarting Connection
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: rekeying state (STATE_QUICK_R2)
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: rekeying state (STATE_QUICK_R2)
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: ERROR: netlink response for Del SA esp.d9d12c60 <at> 10.103.6.93 included errno 3: No such process
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: ERROR: netlink response for Del SA esp.f1bb6bc0 <at> 10.103.6.71 included errno 3: No such process
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng"[2] 10.103.6.93 #1: deleting connection "ng" instance with peer 10.103.6.93 {isakmp=#1/ipsec=#2}
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: deleting state (STATE_QUICK_R2)
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: ERROR: netlink response for Del SA esp.d9d12c60 <at> 10.103.6.93 included errno 3: No such process
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #2: ERROR: netlink response for Del SA esp.f1bb6bc0 <at> 10.103.6.71 included errno 3: No such process
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: "ng" #1: deleting state (STATE_MAIN_R3)
Mar 28 18:05:09 netgenie authpriv.warn pluto[19074]: DPD: Restarting all connections that share this peer
Mar 28 18:05:09 netgenie daemon.err ipsec__plutorun: Segmentation fault
Mar 28 18:05:09 netgenie daemon.err ipsec__plutorun: !pluto failure!:  exited with error status 139 (signal 11)
Mar 28 18:05:09 netgenie daemon.err ipsec__plutorun: restarting IPsec after pause...
Mar 28 18:05:09 netgenie authpriv.warn pluto[19079]: pluto_crypto_helper: helper (0) is  normal exiting


Regards,
Nrupen

_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev
Nrupen Chudasma | 28 Mar 08:08
Picon

[Openswan dev] BUG 1201: dpd + ddns does not work

Hi,

Yesterday I sent the same comment in the User's list. But I think it would be appropriate to discuss about the bug in dev list.

I have been using openswan 2.6.24 with NETKEY for quite a long time.
I had a requirement for DYNDNS based remote host support for making the connections. As there is support added, I tried with the 2.6.24 version and could not succeed.
I searched out for bug#1201 with the exact reason. So I uprated to version 2.6.33. But the problem is still there. Even I tried latest version i.e. 2.6.38 but the result is same.

According to the RCA done for the bug, "conn->dnshostname" is NULL. The specified solution was to work with ipsec whack.

I tried with that. Please correct me if my approach for the problem is wrong. I have put remote as "ddnstest" and added entry in the /etc/hosts file.
I add one connection with ipsec whack. Initiate the connection. Later I change my remote host's IP and add the according entry in /etc/hosts.
The dpdtimeout happens as the former IP no longer available and thus I get the DPD in which case my action restart triggers the initiation of the connection.
Still my connection is initiated to the same IP as before.

Point me if I am doing something wrong.
Find the details of the steps I have done so far and the logs as below.

root <at> ng:~# ipsec auto --status
000 using kernel interface: netkey
000 interface lo/lo 127.0.0.1
000 interface lo/lo 127.0.0.1
000 interface eth2.2/eth2.2 10.103.7.133
000 interface eth2.2/eth2.2 10.103.7.133
000 interface br-lan/br-lan 10.1.2.1
000 interface br-lan/br-lan 10.1.2.1
000 %myid = (none)
000 debug none
000
000 virtual_private (%priv):
000 - allowed 0 subnets:
000 - disallowed 0 subnets:
000 WARNING: Either virtual_private= is not specified, or there is a syntax
000          error in that line. 'left/rightsubnet=vhost:%priv' will not work!
000 WARNING: Disallowed subnets in virtual_private= is empty. If you have
000          private address space in internal use, it should be excluded!
000
000 algorithm ESP encrypt: id=2, name=ESP_DES, ivlen=8, keysizemin=64, keysizemax=64
000 algorithm ESP encrypt: id=3, name=ESP_3DES, ivlen=8, keysizemin=192, keysizemax=192
000 algorithm ESP encrypt: id=12, name=ESP_AES, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=14, name=ESP_AES_CCM_A, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=15, name=ESP_AES_CCM_B, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=16, name=ESP_AES_CCM_C, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=18, name=ESP_AES_GCM_A, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=19, name=ESP_AES_GCM_B, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP encrypt: id=20, name=ESP_AES_GCM_C, ivlen=8, keysizemin=128, keysizemax=256
000 algorithm ESP auth attr: id=1, name=AUTH_ALGORITHM_HMAC_MD5, keysizemin=128, keysizemax=128
000 algorithm ESP auth attr: id=2, name=AUTH_ALGORITHM_HMAC_SHA1, keysizemin=160, keysizemax=160
000
000 algorithm IKE encrypt: id=0, name=(null), blocksize=16, keydeflen=131
000 algorithm IKE encrypt: id=3, name=OAKLEY_BLOWFISH_CBC, blocksize=8, keydeflen=128
000 algorithm IKE encrypt: id=5, name=OAKLEY_3DES_CBC, blocksize=8, keydeflen=192
000 algorithm IKE encrypt: id=7, name=OAKLEY_AES_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: id=65004, name=OAKLEY_SERPENT_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: id=65005, name=OAKLEY_TWOFISH_CBC, blocksize=16, keydeflen=128
000 algorithm IKE encrypt: id=65289, name=OAKLEY_TWOFISH_CBC_SSH, blocksize=16, keydeflen=128
000 algorithm IKE hash: id=1, name=OAKLEY_MD5, hashsize=16
000 algorithm IKE hash: id=2, name=OAKLEY_SHA1, hashsize=20
000 algorithm IKE hash: id=4, name=OAKLEY_SHA2_256, hashsize=32
000 algorithm IKE hash: id=6, name=OAKLEY_SHA2_512, hashsize=64
000 algorithm IKE dh group: id=2, name=OAKLEY_GROUP_MODP1024, bits=1024
000 algorithm IKE dh group: id=5, name=OAKLEY_GROUP_MODP1536, bits=1536
000 algorithm IKE dh group: id=14, name=OAKLEY_GROUP_MODP2048, bits=2048
000 algorithm IKE dh group: id=15, name=OAKLEY_GROUP_MODP3072, bits=3072
000 algorithm IKE dh group: id=16, name=OAKLEY_GROUP_MODP4096, bits=4096
000 algorithm IKE dh group: id=17, name=OAKLEY_GROUP_MODP6144, bits=6144
000 algorithm IKE dh group: id=18, name=OAKLEY_GROUP_MODP8192, bits=8192
000 algorithm IKE dh group: id=22, name=OAKLEY_GROUP_DH22, bits=1024
000 algorithm IKE dh group: id=23, name=OAKLEY_GROUP_DH23, bits=2048
000 algorithm IKE dh group: id=24, name=OAKLEY_GROUP_DH24, bits=2048
000
000 stats db_ops: {curr_cnt, total_cnt, maxsz} :context={0,2,36} trans={0,2,216} attrs={0,2,288}
000
000
000
root <at> ng:~#
root <at> ng:~#
root <at> ng:~#
root <at> ng:~#
root <at> ng:~#
root <at> ng:~#
root <at> ng:~#
root <at> ng:~# cat /etc/ipsec.conf
version 2.0      # conforms to second version of ipsec.conf specification

config setup
        nat_traversal=yes
        oe=off
        protostack=netkey


conn ngpassthrough
        left=10.1.2.1
        right=0.0.0.0
        leftsubnet=10.1.2.0/255.255.255.0
        rightsubnet=10.1.2.0/255.255.255.0
        authby=never
        type=passthrough
        auto=route

conn ng
        right=ddnstest
        rightsubnet=10.1.1.0/24
        left=10.103.7.133
        leftsubnet=10.1.2.0/255.255.255.0
        leftnexthop=10.103.6.1
        auto=start
        #x_rightdynamic=yes
        authby=secret
        compress=no
        failureshunt=drop
        dpddelay=15
        dpdtimeout=60
        dpdaction=restart
        pfs=yes
        ike=aes128-md5-modp1024,

aes192-md5-modp1024,aes256-md5-modp1024,aes128-sha1-modp1024,aes192-sha1-modp1024,aes256-sha1-modp1024,3des-md5-modp1024,3des-sha1-modp1024,aes128-md5-modp1536,aes192-md5-modp1536,aes256-md5-modp1536,aes128-sha1-modp1536,aes192-sha1-modp1536,aes256-sha1-modp1536,3des-md5-modp1536,3des-sha1-modp1536,aes128-md5-modp2048,aes192-md5-modp2048,aes256-md5-modp2048,aes128-sha1-modp2048,aes192-sha1-modp2048,aes256-sha1-modp2048,3des-md5-modp2048,3des-sha1-modp2048
        esp=aes128-md5,aes192-md5,aes256-md5,aes128-sha1,aes192-sha1,aes256-sha1,3des-md5,3des-sha1

root <at> ng:~# cat /etc/ipsec.secrets
10.103.7.133 ddnstest : PSK "adminadmin"
root <at> ng:~#
root <at> ng:~#
root <at> ng:~# ipsec whack --name test --encrypt --tunnel --pfs --dpddelay 15 --dpdtimeout 60 --dpdaction restart --psk --host 10.
103.7.133 --nexthop 10.103.6.1 --client 10.1.2.0/24 --to --host ddnstest --client 10.1.1.0/24
002 added connection description "test"
root <at> ng:~#
root <at> ng:~# ipsec whack --initiate --name test
002 "test" #11: initiating Main Mode
104 "test" #11: STATE_MAIN_I1: initiate
003 "test" #11: ignoring unknown Vendor ID payload [4f45557d6068416e77737478]
003 "test" #11: received Vendor ID payload [Dead Peer Detection]
003 "test" #11: received Vendor ID payload [RFC 3947] method set to=109
002 "test" #11: enabling possible NAT-traversal with method 4
002 "test" #11: transition from state STATE_MAIN_I1 to state STATE_MAIN_I2
106 "test" #11: STATE_MAIN_I2: sent MI2, expecting MR2
003 "test" #11: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): no NAT detected
002 "test" #11: transition from state STATE_MAIN_I2 to state STATE_MAIN_I3
108 "test" #11: STATE_MAIN_I3: sent MI3, expecting MR3
003 "test" #11: received Vendor ID payload [CAN-IKEv2]
002 "test" #11: Main mode peer ID is ID_IPV4_ADDR: '10.103.6.70'
002 "test" #11: transition from state STATE_MAIN_I3 to state STATE_MAIN_I4
004 "test" #11: STATE_MAIN_I4: ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=aes_128 prf=oakley_sha group=modp2048}
002 "test" #11: Dead Peer Detection (RFC 3706): enabled
002 "test" #12: initiating Quick Mode PSK+ENCRYPT+TUNNEL+PFS+UP {using isakmp#11 msgid:faa36d7a proposal=defaults pfsgroup=OAKLEY_GROUP_MODP2048}
117 "test" #12: STATE_QUICK_I1: initiate
002 "test" #12: Dead Peer Detection (RFC 3706): enabled
002 "test" #12: transition from state STATE_QUICK_I1 to state STATE_QUICK_I2
004 "test" #12: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode {ESP=>0x81cd918c <0xf4534088 xfrm=AES_128-HMAC_SHA1 NATOA=none NATD=none DPD=enabled}
root <at> ng:~#
root <at> ng:~#
root <at> ng:~# vi /etc/hosts

127.0.0.1 localhost.
10.103.6.71 ddnstest





LOGS from /var/log/messages...
Dec  4 17:35:31 ng authpriv.warn pluto[11096]: added connection description "test"

Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: initiating Main Mode
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: ignoring unknown Vendor ID payload [4f45557d6068416e77737478]
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: received Vendor ID payload [Dead Peer Detection]
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: received Vendor ID payload [RFC 3947] method set to=109
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: enabling possible NAT-traversal with method 4
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: transition from state STATE_MAIN_I1 to state STATE_MAIN_I2
Dec  4 17:35:42 ng authpriv.warn pluto[11096]: "test" #11: STATE_MAIN_I2: sent MI2, expecting MR2
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: NAT-Traversal: Result using RFC 3947 (NAT-Traversal): no NAT detected
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: transition from state STATE_MAIN_I2 to state STATE_MAIN_I3
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: STATE_MAIN_I3: sent MI3, expecting MR3
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: received Vendor ID payload [CAN-IKEv2]
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: Main mode peer ID is ID_IPV4_ADDR: '10.103.6.70'
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: transition from state STATE_MAIN_I3 to state STATE_MAIN_I4
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: STATE_MAIN_I4: ISAKMP SA established {auth=OAKLEY_PRESHARED_KEY cipher=aes_128 prf=oakley_sha group=modp2048}
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #11: Dead Peer Detection (RFC 3706): enabled
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #12: initiating Quick Mode PSK+ENCRYPT+TUNNEL+PFS+UP {using isakmp#11 msgid:faa36d7a proposal=defaults pfsgroup=OAKLEY_GROUP_MODP2048}
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #12: Dead Peer Detection (RFC 3706): enabled
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #12: transition from state STATE_QUICK_I1 to state STATE_QUICK_I2
Dec  4 17:35:43 ng authpriv.warn pluto[11096]: "test" #12: STATE_QUICK_I2: sent QI2, IPsec SA established tunnel mode {ESP=>0x81cd918c <0xf4534088 xfrm=AES_128-HMAC_SHA1 NATOA=none NATD=none DPD=enabled}


Dec  4 17:36:16 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.6.71: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]

Dec  4 17:36:31 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.6.71: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:36:46 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:37:01 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #11: DPD: No response from peer - declaring peer dead
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #11: DPD: Restarting Connection
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #12: rekeying state (STATE_QUICK_I2)
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #12: rekeying state (STATE_QUICK_I2)
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #12: ERROR: netlink response for Del SA esp.81cd918c <at> 10.103.6.70 included errno 3: No such process
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #12: ERROR: netlink response for Del SA esp.f4534088 <at> 10.103.7.133 included errno 3: No such process
Dec  4 17:37:13 ng authpriv.warn pluto[11096]: "test" #13: initiating Main Mode to replace #11
Dec  4 17:37:16 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:37:16 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:37:26 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:37:46 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:38:26 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
Dec  4 17:39:06 ng authpriv.warn pluto[11096]: ERROR: asynchronous network error report on eth2.2 (sport=500) for message to 10.103.6.70 port 500, complainant 10.103.7.133: No route to host [errno 148, origin ICMP type 3 code 1 (not authenticated)]
_______________________________________________
Dev mailing list
Dev <at> lists.openswan.org
https://lists.openswan.org/mailman/listinfo/dev

Gmane