Skip to contentSkip to conversation

: Reinject packet instead of calling netfilter directly on input

PATCH In review jamal 2 participants 4 messages Nov 29, 2007 – Dec 9, 2007

Subsystems (4)
lore
Share & tools
lore

jamal

author
#0 lore raw

cover : Reinject packet instead of calling netfilter directly on input

Herbert,

This is a simplified version of one of your earlier patches that never made it in. I liked it so much that i reduced it to this and infact given the cycles today, tested it (with transport and tunnel mode only;->).

We re-inject a decrypted ipsec (other than tunnel mode) back and let it bubble up the network stack. This improves debugability (since sniffers like tcpdump can see the packet) and usability since ingress tc filters can act on it.

Ive broken it down into two: IPv4 and IPV6. If you want to go through the xfrm reinject() method, then I am gonna need more time to resubmit or you be my guest and go for it and i will test it.

cheers,
jamal

maintainer
#1 lore raw
Quoted 6 lines · jamal

Herbert,

This is a simplified version of one of your earlier patches that never made it in. I liked it so much that i reduced it to this and infact given the cycles today, tested it (with transport and tunnel mode only;->).

Sorry for the late response Jamal. I've been too busy to give this issue proper thought. It's still in my mailbox so I will respond to it once things quiten down a little.

Cheers,

Signature · 4 lines
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
author
#2 lore raw
Quoted 3 lines · Herbert Xu

Sorry for the late response Jamal. I've been too busy to give this issue proper thought. It's still in my mailbox so I will respond to it once things quiten down a little.

I totaly empathize - take your time.

The point brought up on v6 extensions needs to be addressed. I thought about it a little - and it is valid as well for ipv4 options; they will be processed twice.
To build up on what Patrick said, I noticed a bit still available in the bag right after skb->nf_trace that i could use to signal "options/extensions already processed".
If people think think this is a sane use of that very lonely bit, I will post patches.
CCing Yoshfuji.

cheers,
jamal

author
#3 lore raw
Quoted 8 lines · jamal

The point brought up on v6 extensions needs to be addressed. I thought about it a little - and it is valid as well for ipv4 options; they will be processed twice.
To build up on what Patrick said, I noticed a bit still available in the bag right after skb->nf_trace that i could use to signal "options/extensions already processed".
If people think think this is a sane use of that very lonely bit, I will post patches.

And the patch included demonstrates the thought (I thought i had sent it to the list on monday; seems only to Yoshfuji). Note, blah is not a proper name, just an emphasis.

cheers,
jama

include/linux/skbuff.h +2 -1
index d39f53e..78ac7d0 100644
@@ -288,7 +288,8 @@ struct sk_buff {
 	__u8			pkt_type:3,
 				fclone:2,
 				ipvs_property:1,
-				nf_trace:1;
+				nf_trace:1,
+				blah:1;
 	__be16			protocol;
 
 	void			(*destructor)(struct sk_buff *skb);
net/core/skbuff.c +1 -0
index 6bfc8c8..da7788f 100644
@@ -437,6 +437,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	new->tc_verd		= old->tc_verd;
 #endif
 #endif
+	new->blah		= old->blah;
 	skb_copy_secmark(new, old);
 }
 
net/ipv4/ip_input.c +2 -1
index 6563139..6e1e4b0 100644
@@ -348,9 +348,10 @@ static int ip_rcv_finish(struct sk_buff *skb)
 	}
 #endif
 
-	if (iph->ihl > 5 && ip_rcv_options(skb))
+	if (iph->ihl > 5 || (!skb->blah && ip_rcv_options(skb)))
 		goto drop;
 
+	skb->blah = 1;
 	rt = (struct rtable*)skb->dst;
 	if (rt->rt_type == RTN_MULTICAST)
 		IP_INC_STATS_BH(IPSTATS_MIB_INMCASTPKTS);
net/ipv4/xfrm4_input.c +14 -9
index 0c377a6..1271668 100644
@@ -50,20 +50,25 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async)
 
 	iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
 
-#ifdef CONFIG_NETFILTER
+	if (async)
+		return xfrm4_rcv_encap_finish(skb);
+
 	__skb_push(skb, skb->data - skb_network_header(skb));
 	iph->tot_len = htons(skb->len);
 	ip_send_check(iph);
 
-	NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
-		xfrm4_rcv_encap_finish);
-	return 0;
-#else
-	if (async)
-		return xfrm4_rcv_encap_finish(skb);
+	dst_release(skb->dst);
+	skb->dst = NULL;
+	{
+		/* make some packet-sock user (eg tcpdump) happy */
+		const unsigned char *old_mac;
+		old_mac = skb_mac_header(skb);
+		skb_set_mac_header(skb, -skb->mac_len);
+		memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	}
 
-	return -iph->protocol;
-#endif
+	netif_rx(skb);
+	return 0;
 }
 
 /* If it's a keepalive packet, then just eat it.
net/ipv6/ip6_input.c +6 -0
index 178aebc..2a573e7 100644
@@ -158,6 +158,9 @@ static int ip6_input_finish(struct sk_buff *skb)
 	u8 hash;
 	struct inet6_dev *idev;
 
+	if (skb->blah)
+		goto ext_parse_done;
+
 	/*
 	 *	Parse extension headers
 	 */
@@ -215,6 +218,9 @@ resubmit:
 		kfree_skb(skb);
 	}
 	rcu_read_unlock();
+
+	skb->blah = 1;
+ext_parse_done:
 	return 0;
 
 discard:
net/ipv6/xfrm6_input.c +14 -9
index e2c3efd..c741fba 100644
@@ -33,19 +33,24 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async)
 	skb_network_header(skb)[IP6CB(skb)->nhoff] =
 		XFRM_MODE_SKB_CB(skb)->protocol;
 
-#ifdef CONFIG_NETFILTER
+	if (async)
+		return ip6_rcv_finish(skb);
+
 	ipv6_hdr(skb)->payload_len = htons(skb->len);
 	__skb_push(skb, skb->data - skb_network_header(skb));
 
-	NF_HOOK(PF_INET6, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,
-		ip6_rcv_finish);
-	return -1;
-#else
-	if (async)
-		return ip6_rcv_finish(skb);
+	dst_release(skb->dst);
+	skb->dst = NULL;
+	{
+		/* make some packet-sock user (eg tcpdump) happy */
+		const unsigned char *old_mac;
+		old_mac = skb_mac_header(skb);
+		skb_set_mac_header(skb, -skb->mac_len);
+		memmove(skb_mac_header(skb), old_mac, skb->mac_len);
+	}
 
-	return 1;
-#endif
+	netif_rx(skb);
+	return 0;
 }
 
 int xfrm6_rcv(struct sk_buff *skb)