All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel
@ 2006-12-29  5:47 Kazunori MIYAZAWA
  2007-02-10  3:25 ` Masahide NAKAMURA
  0 siblings, 1 reply; 5+ messages in thread
From: Kazunori MIYAZAWA @ 2006-12-29  5:47 UTC (permalink / raw)
  To: Miika Komu, Diego Beltrami, Herbert Xu, David Miller; +Cc: netdev, usagi-core

This is the patch to support IPv6 over IPv4 IPsec

Signed-off-by: Miika Komu <miika@iki.fi>
Signed-off-by: Diego Beltrami <Diego.Beltrami@hiit.fi>
Signed-off-by: Kazunori Miyazawa <miyazawa@linux-ipv6.org>


diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index e23c21d..e54c549 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -23,6 +23,12 @@ static inline void ipip_ecn_decapsulate(
 		IP_ECN_set_ce(inner_iph);
 }
 
+static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
+{
+	if (INET_ECN_is_ce(iph->tos))
+		IP6_ECN_set_ce(skb->nh.ipv6h);
+}
+
 /* Add encapsulation header.
  *
  * The top IP header will be constructed per RFC 2401.  The following fields
@@ -36,6 +42,7 @@ static inline void ipip_ecn_decapsulate(
 static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct dst_entry *dst = skb->dst;
+	struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
 	struct iphdr *iph, *top_iph;
 	int flags;
 
@@ -48,15 +55,27 @@ static int xfrm4_tunnel_output(struct xf
 	top_iph->ihl = 5;
 	top_iph->version = 4;
 
+	flags = x->props.flags;
+
 	/* DS disclosed */
-	top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+	if (xdst->route->ops->family == AF_INET) {
+		top_iph->protocol = IPPROTO_IPIP;
+		top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
+		top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
+			0 : (iph->frag_off & htons(IP_DF));
+	}
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	else {
+		struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
+		top_iph->protocol = IPPROTO_IPV6;
+		top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
+		top_iph->frag_off = 0;
+	}
+#endif
 
-	flags = x->props.flags;
 	if (flags & XFRM_STATE_NOECN)
 		IP_ECN_clear(top_iph);
 
-	top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
-		0 : (iph->frag_off & htons(IP_DF));
 	if (!top_iph->frag_off)
 		__ip_select_ident(top_iph, dst->child, 0);
 
@@ -64,7 +83,6 @@ static int xfrm4_tunnel_output(struct xf
 
 	top_iph->saddr = x->props.saddr.a4;
 	top_iph->daddr = x->id.daddr.a4;
-	top_iph->protocol = IPPROTO_IPIP;
 
 	memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 	return 0;
@@ -75,8 +93,16 @@ static int xfrm4_tunnel_input(struct xfr
 	struct iphdr *iph = skb->nh.iph;
 	int err = -EINVAL;
 
-	if (iph->protocol != IPPROTO_IPIP)
-		goto out;
+	switch(iph->protocol){
+		case IPPROTO_IPIP:
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+		case IPPROTO_IPV6:
+			break;
+#endif
+		default:
+			goto out;
+	}
+
 	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
 		goto out;
 
@@ -84,10 +110,19 @@ static int xfrm4_tunnel_input(struct xfr
 	    (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
 		goto out;
 
-	if (x->props.flags & XFRM_STATE_DECAP_DSCP)
-		ipv4_copy_dscp(iph, skb->h.ipiph);
-	if (!(x->props.flags & XFRM_STATE_NOECN))
-		ipip_ecn_decapsulate(skb);
+	if (iph->protocol == IPPROTO_IPIP) {
+		if (x->props.flags & XFRM_STATE_DECAP_DSCP)
+			ipv4_copy_dscp(iph, skb->h.ipiph);
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip_ecn_decapsulate(skb);
+	}
+#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+	else {
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip6_ecn_decapsulate(iph, skb);
+		skb->protocol = htons(ETH_P_IPV6);
+	}
+#endif
 	skb->mac.raw = memmove(skb->data - skb->mac_len,
 			       skb->mac.raw, skb->mac_len);
 	skb->nh.raw = skb->data;
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 8dffd4d..a1ac537 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -131,13 +131,11 @@ __xfrm6_bundle_create(struct xfrm_policy
 	struct dst_entry *dst, *dst_prev;
 	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
 	struct rt6_info *rt  = rt0;
-	struct in6_addr *remote = &fl->fl6_dst;
-	struct in6_addr *local  = &fl->fl6_src;
 	struct flowi fl_tunnel = {
 		.nl_u = {
 			.ip6_u = {
-				.saddr = *local,
-				.daddr = *remote
+				.saddr = fl->fl6_src,
+				.daddr = fl->fl6_dst,
 			}
 		}
 	};
@@ -153,7 +151,6 @@ __xfrm6_bundle_create(struct xfrm_policy
 	for (i = 0; i < nx; i++) {
 		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
 		struct xfrm_dst *xdst;
-		int tunnel = 0;
 
 		if (unlikely(dst1 == NULL)) {
 			err = -ENOBUFS;
@@ -177,19 +174,27 @@ __xfrm6_bundle_create(struct xfrm_policy
 
 		dst1->next = dst_prev;
 		dst_prev = dst1;
-		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-			remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
-			local  = __xfrm6_bundle_addr_local(xfrm[i], local);
-			tunnel = 1;
-		}
+
 		__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
 		trailer_len += xfrm[i]->props.trailer_len;
 
-		if (tunnel) {
-			ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
-			ipv6_addr_copy(&fl_tunnel.fl6_src, local);
-			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
-					      &fl_tunnel, AF_INET6);
+		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
+			unsigned short encap_family = xfrm[i]->props.family;
+			switch(encap_family) {
+			case AF_INET:
+				fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
+				fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
+				break;
+			case AF_INET6:
+				ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
+				ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
+				break;
+			default:
+				BUG_ON(1);
+			}
+
+ 			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
+					      &fl_tunnel, encap_family);
 			if (err)
 				goto error;
 		} else
@@ -208,6 +213,7 @@ __xfrm6_bundle_create(struct xfrm_policy
 	i = 0;
 	for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
+		struct xfrm_state_afinfo *afinfo;
 
 		dst_prev->xfrm = xfrm[i++];
 		dst_prev->dev = rt->u.dst.dev;
@@ -224,7 +230,17 @@ __xfrm6_bundle_create(struct xfrm_policy
 		/* Copy neighbour for reachability confirmation */
 		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
 		dst_prev->input		= rt->u.dst.input;
-		dst_prev->output	= xfrm6_output;
+		/* XXX: When IPv4 is implemented as module and can be unloaded,
+		 * we should manage reference to xfrm4_output in afinfo->output.
+		 * Miyazawa
+		 */
+		afinfo = xfrm_state_get_afinfo(dst_prev->xfrm->props.family);
+		if (!afinfo) {
+			dst = *dst_p;
+			goto error;
+		};
+		dst_prev->output = afinfo->output;
+		xfrm_state_put_afinfo(afinfo);
 		/* Sheit... I remember I did this right. Apparently,
 		 * it was magically lost, so this code needs audit */
 		x->u.rt6.rt6i_flags    = rt0->rt6i_flags&(RTCF_BROADCAST|RTCF_MULTICAST|RTCF_LOCAL);

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel
  2006-12-29  5:47 [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel Kazunori MIYAZAWA
@ 2007-02-10  3:25 ` Masahide NAKAMURA
  2007-02-10  5:22   ` David Miller
  2007-02-20  3:24   ` Noriaki TAKAMIYA
  0 siblings, 2 replies; 5+ messages in thread
From: Masahide NAKAMURA @ 2007-02-10  3:25 UTC (permalink / raw)
  To: Kazunori MIYAZAWA
  Cc: Miika Komu, Diego Beltrami, Herbert Xu, David Miller, netdev, usagi-core

[-- Attachment #1: Type: text/plain, Size: 3496 bytes --]

Hello,

Kazunori MIYAZAWA wrote:
> This is the patch to support IPv6 over IPv4 IPsec
> 
> Signed-off-by: Miika Komu <miika@iki.fi>
> Signed-off-by: Diego Beltrami <Diego.Beltrami@hiit.fi>
> Signed-off-by: Kazunori Miyazawa <miyazawa@linux-ipv6.org>


This seems to break Mobile IPv6 route optimization (RO).
(This patch is commited as c82f963efe823d3cacaf1f1b7f1a35cc9628b188
 to David's tree.)

Please find my comment below.


> diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
> index 8dffd4d..a1ac537 100644
> --- a/net/ipv6/xfrm6_policy.c
> +++ b/net/ipv6/xfrm6_policy.c
> @@ -131,13 +131,11 @@ __xfrm6_bundle_create(struct xfrm_policy
>  	struct dst_entry *dst, *dst_prev;
>  	struct rt6_info *rt0 = (struct rt6_info*)(*dst_p);
>  	struct rt6_info *rt  = rt0;
> -	struct in6_addr *remote = &fl->fl6_dst;
> -	struct in6_addr *local  = &fl->fl6_src;
>  	struct flowi fl_tunnel = {
>  		.nl_u = {
>  			.ip6_u = {
> -				.saddr = *local,
> -				.daddr = *remote
> +				.saddr = fl->fl6_src,
> +				.daddr = fl->fl6_dst,
>  			}
>  		}
>  	};
> @@ -153,7 +151,6 @@ __xfrm6_bundle_create(struct xfrm_policy
>  	for (i = 0; i < nx; i++) {
>  		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
>  		struct xfrm_dst *xdst;
> -		int tunnel = 0;
>  
>  		if (unlikely(dst1 == NULL)) {
>  			err = -ENOBUFS;
> @@ -177,19 +174,27 @@ __xfrm6_bundle_create(struct xfrm_policy
>  
>  		dst1->next = dst_prev;
>  		dst_prev = dst1;
> -		if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
> -			remote = __xfrm6_bundle_addr_remote(xfrm[i], remote);
> -			local  = __xfrm6_bundle_addr_local(xfrm[i], local);
> -			tunnel = 1;
> -		}
> +
>  		__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
>  		trailer_len += xfrm[i]->props.trailer_len;
>  
> -		if (tunnel) {
> -			ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
> -			ipv6_addr_copy(&fl_tunnel.fl6_src, local);
> -			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
> -					      &fl_tunnel, AF_INET6);
> +		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
> +			unsigned short encap_family = xfrm[i]->props.family;
> +			switch(encap_family) {
> +			case AF_INET:
> +				fl_tunnel.fl4_dst = xfrm[i]->id.daddr.a4;
> +				fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
> +				break;
> +			case AF_INET6:
> +				ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
> +				ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
> +				break;
> +			default:
> +				BUG_ON(1);
> +			}
> +
> + 			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
> +					      &fl_tunnel, encap_family);
>  			if (err)
>  				goto error;
>  		} else


You missed RO mode path when you changed semantics to check the mode
from "xfrm[i]->props.mode != XFRM_MODE_TRANSPORT"
to "xfrm[i]->props.mode == XFRM_MODE_TUNNEL" before
changing address. Your patch also makes two incline functions
__xfrm6_bundle_addr_{remote,local} are used by nobody.

I suggest a fix to add "|| xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION" there
to make it clearer for other developers about RO-is-there than restoring the code.

# FYI, we don't have to fix another side of inter-family IPsec tunneling (xfrm4_policy.c)
# where you have similar patch (IPv4 over IPv6 IPsec tunnel) because the RO
# is used only for the case of "IPv6 flow and IPv6 extension headers".

Please give me comments for the attached patch.
I hope it will be applied (or replaced the original patch with including mine).


Regards,

-- 
Masahide NAKAMURA


[-- Attachment #2: 0001-PATCH-XFRM-IPV6-Fix-outbound-RO-transformation-which-is-broken-by-IPsec-tunnel-patch.txt --]
[-- Type: text/plain, Size: 1937 bytes --]

From ce9f1ac8c8df22b462a15d4609d05ec939930208 Mon Sep 17 00:00:00 2001
From: Masahide NAKAMURA <nakam@linux-ipv6.org>
Date: Sat, 10 Feb 2007 11:48:49 +0900
Subject: [PATCH][XFRM] IPV6: Fix outbound RO transformation which is broken by IPsec tunnel patch.

It seems to miss RO mode path by IPv6 over IPv4 IPsec tunnel patch
when it changed semantics to check the mode from
"xfrm[i]->props.mode != XFRM_MODE_TRANSPORT" to
"xfrm[i]->props.mode == XFRM_MODE_TUNNEL" before changing address.
It also makes two incline functions __xfrm6_bundle_addr_{remote,local}
are used by nobody.

This patch fixes it.

Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
---
 net/ipv6/xfrm6_policy.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 59480e9..54e2fd0 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -178,7 +178,8 @@ __xfrm6_bundle_create(struct xfrm_policy
 		__xfrm6_bundle_len_inc(&header_len, &nfheader_len, xfrm[i]);
 		trailer_len += xfrm[i]->props.trailer_len;
 
-		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL) {
+		if (xfrm[i]->props.mode == XFRM_MODE_TUNNEL ||
+		    xfrm[i]->props.mode == XFRM_MODE_ROUTEOPTIMIZATION) {
 			unsigned short encap_family = xfrm[i]->props.family;
 			switch(encap_family) {
 			case AF_INET:
@@ -186,8 +187,9 @@ __xfrm6_bundle_create(struct xfrm_policy
 				fl_tunnel.fl4_src = xfrm[i]->props.saddr.a4;
 				break;
 			case AF_INET6:
-				ipv6_addr_copy(&fl_tunnel.fl6_dst, (struct in6_addr*)&xfrm[i]->id.daddr.a6);
-				ipv6_addr_copy(&fl_tunnel.fl6_src, (struct in6_addr*)&xfrm[i]->props.saddr.a6);
+				ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
+
+				ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_src));
 				break;
 			default:
 				BUG_ON(1);
-- 
1.4.2


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel
  2007-02-10  3:25 ` Masahide NAKAMURA
@ 2007-02-10  5:22   ` David Miller
  2007-02-20  3:24   ` Noriaki TAKAMIYA
  1 sibling, 0 replies; 5+ messages in thread
From: David Miller @ 2007-02-10  5:22 UTC (permalink / raw)
  To: nakam; +Cc: kazunori, miika, Diego.Beltrami, herbert, netdev, usagi-core

From: Masahide NAKAMURA <nakam@linux-ipv6.org>
Date: Sat, 10 Feb 2007 12:25:33 +0900

> Please give me comments for the attached patch.
> I hope it will be applied (or replaced the original patch with including mine).

Thank you Mashide, I've applied your patch for now.

If anyone wants to provide some corrections, we can make
them on top of Mashide's version of the fix.

Thank you!

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel
  2007-02-10  3:25 ` Masahide NAKAMURA
  2007-02-10  5:22   ` David Miller
@ 2007-02-20  3:24   ` Noriaki TAKAMIYA
  2007-02-20  9:13     ` David Miller
  1 sibling, 1 reply; 5+ messages in thread
From: Noriaki TAKAMIYA @ 2007-02-20  3:24 UTC (permalink / raw)
  To: kazunori, miika, Diego.Beltrami, herbert, davem, netdev,
	usagi-core, nakam

Hi,

  More fix is needed for __xfrm6_bundle_create().

Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Acked-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
  
--------------------------------------------------
  fixed to set fl_tunnel.fl6_src correctly in xfrm6_bundle_create().

---
 net/ipv6/xfrm6_policy.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index b1133f2..d8a585b 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -189,7 +189,7 @@ __xfrm6_bundle_create(struct xfrm_policy
 			case AF_INET6:
 				ipv6_addr_copy(&fl_tunnel.fl6_dst, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_dst));
 
-				ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_remote(xfrm[i], &fl->fl6_src));
+				ipv6_addr_copy(&fl_tunnel.fl6_src, __xfrm6_bundle_addr_local(xfrm[i], &fl->fl6_src));
 				break;
 			default:
 				BUG_ON(1);
-- 
Noriaki TAKAMIYA

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel
  2007-02-20  3:24   ` Noriaki TAKAMIYA
@ 2007-02-20  9:13     ` David Miller
  0 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2007-02-20  9:13 UTC (permalink / raw)
  To: takamiya
  Cc: kazunori, miika, Diego.Beltrami, herbert, netdev, usagi-core, nakam

From: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
Date: Tue, 20 Feb 2007 12:24:32 +0900 (JST)

>   More fix is needed for __xfrm6_bundle_create().
> 
> Signed-off-by: Noriaki TAKAMIYA <takamiya@po.ntts.co.jp>
> Acked-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
>   
> --------------------------------------------------
>   fixed to set fl_tunnel.fl6_src correctly in xfrm6_bundle_create().

Patch applied, thank you very much.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-02-20  9:13 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-29  5:47 [RFC][PATCH][IPSEC][2/3] IPv6 over IPv4 IPsec tunnel Kazunori MIYAZAWA
2007-02-10  3:25 ` Masahide NAKAMURA
2007-02-10  5:22   ` David Miller
2007-02-20  3:24   ` Noriaki TAKAMIYA
2007-02-20  9:13     ` David Miller

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.