Re: [IPSEC] Move hardware headers for decaped packets

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Aug 20, 2003 at 06:26:48PM +1000, herbert wrote:
> 
> Oops I forgot to move the MAC headers for the case where the
> SAs terminate with a transport SA.  Please let me fix that
> before you merge it in.  Thanks.

OK, here is the patch which does that.

Cheers,
-- 
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email:  Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
Index: kernel-source-2.5/include/linux/skbuff.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/linux/skbuff.h,v
retrieving revision 1.4
diff -u -r1.4 skbuff.h
--- kernel-source-2.5/include/linux/skbuff.h	9 Aug 2003 11:29:21 -0000	1.4
+++ kernel-source-2.5/include/linux/skbuff.h	20 Aug 2003 10:48:16 -0000
@@ -201,6 +201,7 @@
 		struct icmphdr	*icmph;
 		struct igmphdr	*igmph;
 		struct iphdr	*ipiph;
+		struct ipv6hdr	*ipv6h;
 		unsigned char	*raw;
 	} h;
 
Index: kernel-source-2.5/net/ipv4/xfrm4_input.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/xfrm4_input.c,v
retrieving revision 1.5
diff -u -r1.5 xfrm4_input.c
--- kernel-source-2.5/net/ipv4/xfrm4_input.c	9 Aug 2003 03:42:54 -0000	1.5
+++ kernel-source-2.5/net/ipv4/xfrm4_input.c	20 Aug 2003 10:37:22 -0000
@@ -9,6 +9,7 @@
  * 	
  */
 
+#include <linux/string.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/xfrm.h>
@@ -18,9 +19,10 @@
 	return xfrm4_rcv_encap(skb, 0);
 }
 
-static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
+static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
 {
-	struct iphdr *inner_iph = skb->nh.iph;
+	struct iphdr *outer_iph = skb->nh.iph;
+	struct iphdr *inner_iph = skb->h.ipiph;
 
 	if (INET_ECN_is_ce(outer_iph->tos) &&
 	    INET_ECN_is_not_ce(inner_iph->tos))
@@ -49,6 +51,9 @@
 	struct xfrm_state *x;
 	int xfrm_nr = 0;
 	int decaps = 0;
+	int hhlen;
+
+	hhlen = skb->nh.raw - skb->mac.raw;
 
 	if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
 		goto drop;
@@ -90,16 +95,7 @@
 
 		xfrm_vec[xfrm_nr++].xvec = x;
 
-		iph = skb->nh.iph;
-
 		if (x->props.mode) {
-			if (iph->protocol != IPPROTO_IPIP)
-				goto drop;
-			skb->nh.raw = skb->data;
-			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip_ecn_decapsulate(iph, skb);
-			iph = skb->nh.iph;
-			memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 			decaps = 1;
 			break;
 		}
@@ -125,7 +121,19 @@
 	memcpy(skb->sp->x+skb->sp->len, xfrm_vec, xfrm_nr*sizeof(struct sec_decap_state));
 	skb->sp->len += xfrm_nr;
 
+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto drop;
+
 	if (decaps) {
+		skb->mac.raw = memmove(skb->data - hhlen, skb->mac.raw, hhlen);
+		if (skb->nh.iph->protocol != IPPROTO_IPIP)
+			goto drop;
+		if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+			goto drop;
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip_ecn_decapsulate(skb);
+		skb->nh.raw = skb->data;
+		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
 		if (!(skb->dev->flags&IFF_LOOPBACK)) {
 			dst_release(skb->dst);
 			skb->dst = NULL;
@@ -133,6 +141,8 @@
 		netif_rx(skb);
 		return 0;
 	} else {
+		skb->mac.raw = memmove(skb->nh.raw - hhlen, skb->mac.raw,
+				       hhlen);
 		return -skb->nh.iph->protocol;
 	}
 
Index: kernel-source-2.5/net/ipv6/xfrm6_input.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/xfrm6_input.c,v
retrieving revision 1.4
diff -u -r1.4 xfrm6_input.c
--- kernel-source-2.5/net/ipv6/xfrm6_input.c	29 Jul 2003 11:11:34 -0000	1.4
+++ kernel-source-2.5/net/ipv6/xfrm6_input.c	20 Aug 2003 10:47:50 -0000
@@ -9,17 +9,20 @@
  *		IPv6 support
  */
 
+#include <linux/string.h>
 #include <net/inet_ecn.h>
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/xfrm.h>
 
-static inline void ipip6_ecn_decapsulate(struct ipv6hdr *iph,
-					 struct sk_buff *skb)
+static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
 {
-	if (INET_ECN_is_ce(ip6_get_dsfield(iph)) &&
-	    INET_ECN_is_not_ce(ip6_get_dsfield(skb->nh.ipv6h)))
-		IP6_ECN_set_ce(skb->nh.ipv6h);
+	struct ipv6hdr *outer_iph = skb->nh.ipv6h;
+	struct ipv6hdr *inner_iph = skb->h.ipv6h;
+
+	if (INET_ECN_is_ce(ip6_get_dsfield(outer_iph)) &&
+	    INET_ECN_is_not_ce(ip6_get_dsfield(inner_iph)))
+		IP6_ECN_set_ce(inner_iph);
 }
 
 int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp)
@@ -33,10 +36,12 @@
 	int decaps = 0;
 	int nexthdr = 0;
 	u8 *prevhdr = NULL;
+	int hhlen;
 
 	ip6_find_1stfragopt(skb, &prevhdr);
 	nexthdr = *prevhdr;
 	*nhoffp = prevhdr - skb->nh.raw;
+	hhlen = skb->nh.raw - skb->mac.raw;
 
 	if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
 		goto drop;
@@ -75,12 +80,6 @@
 		xfrm_vec[xfrm_nr++].xvec = x;
 
 		if (x->props.mode) { /* XXX */
-			if (nexthdr != IPPROTO_IPV6)
-				goto drop;
-			skb->nh.raw = skb->data;
-			if (!(x->props.flags & XFRM_STATE_NOECN))
-				ipip6_ecn_decapsulate(iph, skb);
-			iph = skb->nh.ipv6h;
 			decaps = 1;
 			break;
 		}
@@ -107,7 +106,18 @@
 	skb->sp->len += xfrm_nr;
 	skb->ip_summed = CHECKSUM_NONE;
 
+	if (skb_cloned(skb) && pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+		goto drop;
+
 	if (decaps) {
+		skb->mac.raw = memmove(skb->data - hhlen, skb->mac.raw, hhlen);
+		if (nexthdr != IPPROTO_IPV6)
+			goto drop;
+		if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
+			goto drop;
+		if (!(x->props.flags & XFRM_STATE_NOECN))
+			ipip6_ecn_decapsulate(skb);
+		skb->nh.raw = skb->data;
 		if (!(skb->dev->flags&IFF_LOOPBACK)) {
 			dst_release(skb->dst);
 			skb->dst = NULL;
@@ -115,6 +125,8 @@
 		netif_rx(skb);
 		return -1;
 	} else {
+		skb->mac.raw = memmove(skb->nh.raw - hhlen, skb->mac.raw,
+				       hhlen);
 		return 1;
 	}
 

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux