Description: Fix traffic selectors passing in Transport Mode
Author: Avesh Agarwal <avagarwa@redhat.com>
Origin: upstream git
Last-Update: 2012-06-28

Index: openswan-debian/programs/pluto/kernel.c
===================================================================
--- openswan-debian.orig/programs/pluto/kernel.c	2012-06-29 19:15:38.633617434 +0200
+++ openswan-debian/programs/pluto/kernel.c	2012-06-29 19:16:46.829617481 +0200
@@ -1438,6 +1438,7 @@
         said_next->dst = &dst.addr;
         said_next->src_client = &src_client;
         said_next->dst_client = &dst_client;
+        said_next->transport_proto = c->spd.this.protocol;
         said_next->spi = ipip_spi;
         said_next->esatype = ET_IPIP;
         said_next->text_said = text_said;
@@ -1530,6 +1531,7 @@
         said_next->dst = &dst.addr;
         said_next->src_client = &src_client;
         said_next->dst_client = &dst_client;
+        said_next->transport_proto = c->spd.this.protocol;
         said_next->spi = ipcomp_spi;
         said_next->esatype = ET_IPCOMP;
         said_next->encalg = compalg;
@@ -1742,6 +1744,7 @@
         said_next->dst = &dst.addr;
         said_next->src_client = &src_client;
         said_next->dst_client = &dst_client;
+        said_next->transport_proto = c->spd.this.protocol;
         said_next->spi = esp_spi;
         said_next->esatype = ET_ESP;
         said_next->replay_window = kernel_ops->replay_window;
@@ -1882,6 +1885,7 @@
         said_next->dst = &dst.addr;
         said_next->src_client = &src_client;
         said_next->dst_client = &dst_client;
+        said_next->transport_proto = c->spd.this.protocol;
         said_next->spi = ah_spi;
         said_next->esatype = ET_AH;
         said_next->replay_window = kernel_ops->replay_window;
Index: openswan-debian/programs/pluto/kernel.h
===================================================================
--- openswan-debian.orig/programs/pluto/kernel.h	2012-06-29 19:15:38.633617434 +0200
+++ openswan-debian/programs/pluto/kernel.h	2012-06-29 19:16:46.829617481 +0200
@@ -79,6 +79,7 @@
 
 	ipsec_spi_t spi;
 	unsigned proto;
+	unsigned int transport_proto;
 	enum eroute_type esatype;
 	unsigned replay_window;
 	unsigned reqid;
Index: openswan-debian/programs/pluto/kernel_netlink.c
===================================================================
--- openswan-debian.orig/programs/pluto/kernel_netlink.c	2012-06-29 19:16:40.513617529 +0200
+++ openswan-debian/programs/pluto/kernel_netlink.c	2012-06-29 19:16:46.829617481 +0200
@@ -817,6 +817,44 @@
     else
     {
 	req.p.mode = XFRM_MODE_TRANSPORT;
+
+	req.p.sel.sport = portof(&sa->src_client->addr);
+	req.p.sel.dport = portof(&sa->dst_client->addr);
+
+	/* As per RFC 4301/5996, icmp type is put in the most significant 8 bits
+	* and icmp code is in the least significant 8 bits of port field. 
+	* Although Openswan does not have any configuration options for 
+	* icmp type/code values, it is possible to specify icmp type and code 
+	* using protoport option. For example, icmp echo request (type 8/code 0) 
+	* needs to be encoded as 0x0800 in the port field and can be specified 
+	* as left/rightprotoport=icmp/2048. Now with NETKEY, icmp type and code
+	* need to be passed as source and destination ports, respectively.
+	* therefore, this code extracts upper 8 bits and lower 8 bits and puts
+	* into source and destination ports before passing to NETKEY. */
+
+
+	if( 1 == sa->transport_proto /*icmp*/ || 58 == sa->transport_proto /*ipv6-icmp*/) {
+
+	u_int16_t icmp_type;
+	u_int16_t icmp_code;
+
+	icmp_type = ntohs(req.p.sel.sport) >> 8;
+	icmp_code = ntohs(req.p.sel.sport) & 0xFF;
+
+	req.p.sel.sport = htons(icmp_type);
+	req.p.sel.dport = htons(icmp_code);
+
+	}
+
+	req.p.sel.sport_mask = (req.p.sel.sport) ? ~0:0;
+	req.p.sel.dport_mask = (req.p.sel.dport) ? ~0:0;
+	ip2xfrm(&sa->src_client->addr, &req.p.sel.saddr);
+	ip2xfrm(&sa->dst_client->addr, &req.p.sel.daddr);
+	req.p.sel.prefixlen_s = sa->src_client->maskbits;
+	req.p.sel.prefixlen_d = sa->dst_client->maskbits;
+	req.p.sel.proto = sa->transport_proto;
+	req.p.sel.family = sa->src_client->addr.u.v4.sin_family;
+
     }
 
     req.p.replay_window = sa->replay_window > 32 ? 32 : sa->replay_window; 
