Skip to contentSkip to conversation

ip_route_me_harder -> xfrm_lookup

RFC PATCH In review Herbert Xu 4 participants 39 messages Mar 8, 2004 – Mar 24, 2004

Subsystems (7)
lore
Share & tools
lore

Herbert Xu

author maintainer
#0 lore raw

Hi:

I've received a number of reports that the any packets that are modified by the PREROUTING mangle table will not be protected by IPsec.

The reason is that ip_route_me_harder which is called upon the exit of the mangle table does not set the proto field. This means that xfrm_lookup is never called.

The following patch sets the proto field so that the packet can be protected by IPsec.

Cheers,

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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

Index: kernel-2.5/net/core/netfilter.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/core/netfilter.c,v retrieving revision 1.1.1.10

net/core/netfilter.c +1 -0
diff -u -r1.1.1.10 netfilter.c
@@ -639,6 +639,7 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
+		fl.proto = iph->protocol;
 		if (ip_route_output_key(&rt, &fl) != 0)
 			return -1;
 
#1 lore raw

Hi Herbert,

Quoted 11 lines · Herbert Xu

Hi:

I've received a number of reports that the any packets that are modified by the PREROUTING mangle table will not be protected by IPsec.

The reason is that ip_route_me_harder which is called upon the exit of the mangle table does not set the proto field. This means that xfrm_lookup is never called.

The following patch sets the proto field so that the packet can be protected by IPsec.

I have been working on a set of patches for IPsec+Netfilter, the latest set has been posted to netfilter-devel last week. They will go in patch-o-matic for testing soon, but I will post them to netdev later today, so we won't waste time testing patches before Dave is fine with them.

Regards,
Patrick

Quoted 21 lines

Cheers,

------------------------------------------------------------------------

Index: kernel-2.5/net/core/netfilter.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/core/netfilter.c,v retrieving revision 1.1.1.10
diff -u -r1.1.1.10 netfilter.c

net/core/netfilter.c +1 -0
@@ -639,6 +639,7 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
+		fl.proto = iph->protocol;
 		if (ip_route_output_key(&rt, &fl) != 0)
 			return -1;
 
#2 lore raw
Quoted 5 lines · On Mon, 08 Mar 2004 15:46:37 +0100 Patrick McHardy <[email protected]> wrote:
Quoted 4 lines · Herbert Xu

The reason is that ip_route_me_harder which is called upon the exit of the mangle table does not set the proto field. This means that xfrm_lookup is never called.

Quoted 8 lines
Quoted 2 lines

The following patch sets the proto field so that the packet can be protected by IPsec.

I have been working on a set of patches for IPsec+Netfilter, the latest set has been posted to netfilter-devel last week. They will go in patch-o-matic for testing soon, but I will post them to netdev later today, so we won't waste time testing patches before Dave is fine with them.

Regardless, and I look forward to your work, Herbert's patch is absolutely correct so I'm going to apply it for now.

In fact, your work is less likely to be 2.6.4 material I imagine :) So best to get Herbert's simpler fix in for now.

#3 lore raw
Quoted 10 lines · David S. Miller
Quoted 6 lines · On Mon, 08 Mar 2004 15:46:37 +0100 Patrick McHardy <[email protected]> wrote:

I have been working on a set of patches for IPsec+Netfilter, the latest set has been posted to netfilter-devel last week. They will go in patch-o-matic for testing soon, but I will post them to netdev later today, so we won't waste time testing patches before Dave is fine with them.

Quoted 6 lines

Regardless, and I look forward to your work, Herbert's patch is absolutely correct so I'm going to apply it for now.

In fact, your work is less likely to be 2.6.4 material I imagine :) So best to get Herbert's simpler fix in for now.

Sorry for the late reply. You're right of course, Herbert's patch is best for now. The following five mails contain what I've currently got, it's still rough, but I hope you have some suggestions how to avoid some ugly things.

Best regards
Patrick

#4 lore raw

RFC PATCH 1/5 : netfilter+ipsec - nf_reset

In reply to David S. Miller

This patch adds a new function nf_reset to reset netfilter related skb-fields. It has no real relationship to netfilter+ipsec, but it's required for the follow-up patches.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/03/18 03:22:26+01:00 [email protected]
# [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
#

# net/ipv6/sit.c
#   2004/03/18 03:19:58+01:00 [email protected] +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
# net/ipv6/ip6_tunnel.c
#   2004/03/18 03:19:58+01:00 [email protected] +1 -7
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
# net/ipv4/ipip.c
#   2004/03/18 03:19:58+01:00 [email protected] +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
# net/ipv4/ip_input.c
#   2004/03/18 03:19:58+01:00 [email protected] +1 -5
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
# net/ipv4/ip_gre.c
#   2004/03/18 03:19:58+01:00 [email protected] +2 -14
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
# include/linux/skbuff.h
#   2004/03/18 03:19:58+01:00 [email protected] +12 -3
#   [NETFILTER]: Add new function 'nf_reset' to reset netfilter related skb-fields
# 
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	Thu Mar 18 16:45:10 2004
+++ b/include/linux/skbuff.h	Thu Mar 18 16:45:10 2004
@@ -1201,6 +1201,14 @@
 	if (nfct)
 		atomic_inc(&nfct->master->use);
 }
+static inline void nf_reset(struct sk_buff *skb)
+{
+	nf_conntrack_put(skb->nfct);
+	skb->nfct = NULL;
+#ifdef CONFIG_NETFILTER_DEBUG
+	skb->nf_debug = 0;
+#endif
+}

#ifdef CONFIG_BRIDGE_NETFILTER
static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
@@ -1213,9 +1221,10 @@
if (nf_bridge)
atomic_inc(&nf_bridge->use);
}
-#endif
-
-#endif
+#endif /* CONFIG_BRIDGE_NETFILTER */
+#else /* CONFIG_NETFILTER */
+static inline void nf_reset(struct sk_buff *skb) {} +#endif /* CONFIG_NETFILTER */

#endif /* __KERNEL__ */
#endif /* _LINUX_SKBUFF_H */

net/ipv4/ip_gre.c +2 -14
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
@@ -643,13 +643,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipgre_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipgre_lock);
@@ -877,13 +871,7 @@
 		}
 	}
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
net/ipv4/ip_input.c +1 -5
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
@@ -202,17 +202,13 @@
 
 #ifdef CONFIG_NETFILTER_DEBUG
 	nf_debug_ip_local_deliver(skb);
-	skb->nf_debug = 0;
 #endif /*CONFIG_NETFILTER_DEBUG*/
 
 	__skb_pull(skb, ihl);
 
-#ifdef CONFIG_NETFILTER
 	/* Free reference early: we don't need it any more, and it may
            hold ip_conntrack module loaded indefinitely. */
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#endif /*CONFIG_NETFILTER*/
+	nf_reset(skb);
 
         /* Point into the IP datagram, just past the header. */
         skb->h.raw = skb->data;
net/ipv4/ipip.c +2 -14
diff -Nru a/net/ipv4/ipip.c b/net/ipv4/ipip.c
@@ -496,13 +496,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipip_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipip_lock);
@@ -647,13 +641,7 @@
 	if ((iph->ttl = tiph->ttl) == 0)
 		iph->ttl	=	old_iph->ttl;
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
net/ipv6/ip6_tunnel.c +1 -7
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
@@ -715,13 +715,7 @@
 	ipv6h->nexthdr = proto;
 	ipv6_addr_copy(&ipv6h->saddr, &fl.fl6_src);
 	ipv6_addr_copy(&ipv6h->daddr, &fl.fl6_dst);
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 	pkt_len = skb->len;
 	err = NF_HOOK(PF_INET6, NF_IP6_LOCAL_OUT, skb, NULL, 
 		      skb->dst->dev, dst_output);
net/ipv6/sit.c +2 -14
diff -Nru a/net/ipv6/sit.c b/net/ipv6/sit.c
@@ -388,13 +388,7 @@
 		skb->dev = tunnel->dev;
 		dst_release(skb->dst);
 		skb->dst = NULL;
-#ifdef CONFIG_NETFILTER
-		nf_conntrack_put(skb->nfct);
-		skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-		skb->nf_debug = 0;
-#endif
-#endif
+		nf_reset(skb);
 		ipip6_ecn_decapsulate(iph, skb);
 		netif_rx(skb);
 		read_unlock(&ipip6_lock);
@@ -580,13 +574,7 @@
 	if ((iph->ttl = tiph->ttl) == 0)
 		iph->ttl	=	iph6->hop_limit;
 
-#ifdef CONFIG_NETFILTER
-	nf_conntrack_put(skb->nfct);
-	skb->nfct = NULL;
-#ifdef CONFIG_NETFILTER_DEBUG
-	skb->nf_debug = 0;
-#endif
-#endif
+	nf_reset(skb);
 
 	IPTUNNEL_XMIT();
 	tunnel->recursion--;
#5 lore raw

Re: [RFC, PATCH 1/5]: netfilter+ipsec - nf_reset

Quoted 3 lines · On Thu, 18 Mar 2004 17:31:27 +0100 Patrick McHardy <[email protected]> wrote:

This patch adds a new function nf_reset to reset netfilter related skb-fields. It has no real relationship to netfilter+ipsec, but it's required for the follow-up patches.

I like and thus want this cleanup regardless of what happens to the rest of your patches :)

#6 lore raw

RFC PATCH 2/5 : netfilter+ipsec - output hooks

In reply to David S. Miller

This patch adds new output-hooks. Packets with dst->xfrm != NULL traverse the POST_ROUTING hook before dst_output is called. The transformers mark the packets in the control buffer with a new flag IPSKB_XFRM_TRANSFORMED, these packets then traverse the LOCAL_OUT hook when they hit ip_output.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/03/18 14:59:24+01:00 [email protected]
# [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
#

# net/ipv4/xfrm4_tunnel.c
#   2004/03/18 14:59:14+01:00 [email protected] +1 -0
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# net/ipv4/ipcomp.c
#   2004/03/18 14:59:14+01:00 [email protected] +1 -0
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# net/ipv4/ip_output.c
#   2004/03/18 14:59:14+01:00 [email protected] +20 -4
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# net/ipv4/ip_forward.c
#   2004/03/18 14:59:14+01:00 [email protected] +2 -1
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# net/ipv4/esp4.c
#   2004/03/18 14:59:14+01:00 [email protected] +1 -0
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# net/ipv4/ah4.c
#   2004/03/18 14:59:14+01:00 [email protected] +1 -0
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# include/net/ip.h
#   2004/03/18 14:59:14+01:00 [email protected] +1 -0
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
# include/linux/netfilter.h
#   2004/03/18 14:59:14+01:00 [email protected] +9 -4
#   [NETFILTER}: Pass packets to POST_ROUTING hook before encryption and LOCAL_OUT afterwards
# 
diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h
--- a/include/linux/netfilter.h	Thu Mar 18 16:45:22 2004
+++ b/include/linux/netfilter.h	Thu Mar 18 16:45:22 2004
@@ -119,12 +119,14 @@
 /* This is gross, but inline doesn't cut it for avoiding the function
    call in fast path: gcc doesn't inline (needs value tracking?). --RR */
 #ifdef CONFIG_NETFILTER_DEBUG
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		\
+(!(cond)									\
+ ? (okfn)(skb) 								\
+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
 #define NF_HOOK_THRESH nf_hook_slow
 #else
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
-(list_empty(&nf_hooks[(pf)][(hook)])					\
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		\
+(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])				\
  ? (okfn)(skb)								\
  : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))
 #define NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, thresh)	\
@@ -132,6 +134,8 @@
  ? (okfn)(skb)								\
  : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), (thresh)))
 #endif
+#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
+ NF_HOOK_COND((pf), (hook), (skb), (indev), (outdev), (okfn), 1)

int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
struct net_device *indev, struct net_device *outdev,
@@ -164,6 +168,7 @@

#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
+#define NF_HOOK_COND NF_HOOK
#endif /*CONFIG_NETFILTER*/

#endif /*__KERNEL__*/

include/net/ip.h +1 -0
diff -Nru a/include/net/ip.h b/include/net/ip.h
@@ -48,6 +48,7 @@
 #define IPSKB_TRANSLATED	2
 #define IPSKB_FORWARDED		4
 #define IPSKB_XFRM_TUNNEL_SIZE	8
+#define IPSKB_XFRM_TRANSFORMED	16
 };
 
 struct ipcm_cookie
net/ipv4/ah4.c +1 -0
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
@@ -145,6 +145,7 @@
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	return NET_XMIT_BYPASS;
 
 error:
net/ipv4/esp4.c +1 -0
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
@@ -199,6 +199,7 @@
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	return NET_XMIT_BYPASS;
 
 error:
net/ipv4/ip_forward.c +2 -1
diff -Nru a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c
@@ -51,7 +51,8 @@
 	if (unlikely(opt->optlen))
 		ip_forward_options(skb);
 
-	return dst_output(skb);
+	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
+	                    skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
 }
 
 int ip_forward(struct sk_buff *skb)
net/ipv4/ip_output.c +20 -4
diff -Nru a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
@@ -123,6 +123,12 @@
 	return ttl;
 }
 
+static inline int ip_dst_output(struct sk_buff *skb)
+{
+	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
+	                    skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
+}
+
 /* 
  *		Add an ip header to a skbuff and send it out.
  *
@@ -165,7 +171,7 @@
 
 	/* Send it out. */
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       dst_output);
+		       ip_dst_output);
 }
 
 static inline int ip_finish_output2(struct sk_buff *skb)
@@ -283,7 +289,7 @@
 		return ip_finish_output(skb);
 }
 
-int ip_output(struct sk_buff *skb)
+static inline int ip_output2(struct sk_buff *skb)
 {
 	IP_INC_STATS(IpOutRequests);
 
@@ -294,6 +300,16 @@
 		return ip_finish_output(skb);
 }
 
+int ip_output(struct sk_buff *skb)
+{
+	int transformed = IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED;
+
+	if (transformed)
+		nf_reset(skb);
+	return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_OUT, skb, NULL,
+	                    skb->dst->dev, ip_output2, transformed);
+}
+
 int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
 {
 	struct sock *sk = skb->sk;
@@ -387,7 +403,7 @@
 	skb->priority = sk->sk_priority;
 
 	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		       dst_output);
+		       ip_dst_output);
 
 no_route:
 	IP_INC_STATS(IpOutNoRoutes);
@@ -1177,7 +1193,7 @@
 
 	/* Netfilter gets whole the not fragmented skb. */
 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, 
-		      skb->dst->dev, dst_output);
+		      skb->dst->dev, ip_dst_output);
 	if (err) {
 		if (err > 0)
 			err = inet->recverr ? net_xmit_errno(err) : 0;
net/ipv4/ipcomp.c +1 -0
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
@@ -231,6 +231,7 @@
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	err = NET_XMIT_BYPASS;
 
 out_exit:
net/ipv4/xfrm4_tunnel.c +1 -0
diff -Nru a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
@@ -76,6 +76,7 @@
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	return NET_XMIT_BYPASS;
 
 error_nolock:
#7 lore raw

Re: [RFC, PATCH 2/5]: netfilter+ipsec - output hooks

This one isn't going to compile with netfilter disabled, I can tell just by looking at it :-)

The reason is that NF_HOOK_COND is defined to NF_HOOK in that case, and these two macros take a different number of args so the compiler is going to barf.

author maintainer
#8 lore raw

Re: [RFC, PATCH 2/5]: netfilter+ipsec - output hooks

In reply to Patrick McHardy
Quoted 5 lines · Patrick McHardy

This patch adds new output-hooks. Packets with dst->xfrm != NULL traverse the POST_ROUTING hook before dst_output is called. The transformers mark the packets in the control buffer with a new flag IPSKB_XFRM_TRANSFORMED, these packets then traverse the LOCAL_OUT hook when they hit ip_output.

Thank you very much for your patches. This is definitely the biggest show stopper with the current IPsec stack.

I've just got a minor point about this one:

Review line 125

Quoted 10 lines
(quoted diff) +4 -2
@@ -119,12 +119,14 @@
 /* This is gross, but inline doesn't cut it for avoiding the function
    call in fast path: gcc doesn't inline (needs value tracking?). --RR */
 #ifdef CONFIG_NETFILTER_DEBUG
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
- nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN)
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		\
+(!(cond)									\
+ ? (okfn)(skb) 								\
+ : nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN))

Any reason why this is written with a negated cond? I get confused by double negations :)

Review line 129

Quoted 6 lines
(quoted diff) +2 -2
 #define NF_HOOK_THRESH nf_hook_slow
 #else
-#define NF_HOOK(pf, hook, skb, indev, outdev, okfn)			\
-(list_empty(&nf_hooks[(pf)][(hook)])					\
+#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond)		\
+(!(cond) || list_empty(&nf_hooks[(pf)][(hook)])				\

Ditto, what about

((cond) && !list_empty(&nf_hooks[(pf)][(hook)) \
? nf_hook_slow((pf), (hook), (skb), (indev), (outdev), (okfn), INT_MIN) \
: (okfn)(skb))

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#9 lore raw

Re: [RFC, PATCH 2/5]: netfilter+ipsec - output hooks

In reply to Patrick McHardy

Hi

I don't have a full understanding of the code area we are talking about, having only had a peruse of it a while back.

But from my reading of this do I understand that packets that enter a box to be routed (forwarded on) that match a IPSEC transform policy

1) Are seen in mangle prerouting
2) nat prerouting
2) Encrypted
3) mangle Output
4) nat Output

Does this mean they also hit the filter input & output tables aswell or
just the filter forward table.

I would have thought for the whole process the packet (routed/forward packet) would only be seen in the prerouting/forward/postrouting flow. Weather or not it is going to be encrypted shouldn't make a difference I would have thought

Quoted 7 lines · Patrick McHardy

This patch adds new output-hooks. Packets with dst->xfrm != NULL traverse the POST_ROUTING hook before dst_output is called. The transformers mark the packets in the control buffer with a new flag IPSKB_XFRM_TRANSFORMED, these packets then traverse the LOCAL_OUT hook when they hit ip_output.

#10 lore raw

RFC PATCH 3/5 : netfilter+ipsec - input hooks

In reply to David S. Miller

This patch adds new hooks for input, it is the worst of all patches. Packets should traverse PRE_ROUTING+LOCAL_IN before decryption and PRE_ROUTING+LOCAL_IN/FORWARD afterwards. This is tricky because I didn't find an elegant way to determine when decapsulation is done. Currently, packets reposted into the stack don't traverse the hooks at the normal positions but at a later time when we know decapsulation if done:

- if a reposted packet has a non-local destination after input routing decapsulation must be done, it then traverses the PRE_ROUTING hook.

- otherwise, it continues until ip_local_deliver_finish but also skips the LOCAL_IN hook. All xfrm protocol-handlers are marked with xfrm_prot. If the protocol handler of a packet with a secpath pointer is a non-xfrm-protocol the packet was handled by ipsec and is done now, it traverses the PRE_ROUTING and LOCAL_IN hooks then. This catches packets from both tunnel-mode and transport-mode SAs.

Because the hooks are traversed at a later time than usual several not-so-nice things have to be done in the nf_postxfrm_* functions.

I don't see a better way currently, but I'm sure you do ;)

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/03/18 16:41:37+01:00 [email protected]
# [NETFILTER]: post-ipsec input hooks
#

# net/ipv4/xfrm4_tunnel.c
#   2004/03/18 16:41:31+01:00 [email protected] +1 -0
#   [NETFILTER]: post-ipsec input hooks
# 
# net/ipv4/ipcomp.c
#   2004/03/18 16:41:31+01:00 [email protected] +1 -0
#   [NETFILTER]: post-ipsec input hooks
# 
# net/ipv4/ip_input.c
#   2004/03/18 16:41:31+01:00 [email protected] +15 -6
#   [NETFILTER]: post-ipsec input hooks
# 
# net/ipv4/esp4.c
#   2004/03/18 16:41:31+01:00 [email protected] +1 -0
#   [NETFILTER]: post-ipsec input hooks
# 
# net/ipv4/ah4.c
#   2004/03/18 16:41:31+01:00 [email protected] +1 -0
#   [NETFILTER]: post-ipsec input hooks
# 
# net/core/netfilter.c
#   2004/03/18 16:41:31+01:00 [email protected] +50 -3
#   [NETFILTER]: post-ipsec input hooks
# 
# include/net/protocol.h
#   2004/03/18 16:41:31+01:00 [email protected] +1 -0
#   [NETFILTER]: post-ipsec input hooks
# 
# include/linux/netfilter_ipv4.h
#   2004/03/18 16:41:31+01:00 [email protected] +15 -0
#   [NETFILTER]: post-ipsec input hooks
# 
diff -Nru a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
--- a/include/linux/netfilter_ipv4.h	Thu Mar 18 16:45:35 2004
+++ b/include/linux/netfilter_ipv4.h	Thu Mar 18 16:45:35 2004
@@ -83,6 +83,21 @@
    Returns true or false. */
 extern int skb_ip_make_writable(struct sk_buff **pskb,
 				unsigned int writable_len);
+
+#ifdef CONFIG_XFRM
+extern int nf_postxfrm_input(struct sk_buff *skb);
+extern int nf_postxfrm_nonlocal(struct sk_buff *skb);
+#else /* CONFIG_XFRM */
+static inline int nf_postxfrm_input(struct sk_buff *skb)
+{
+	return 0;
+}
+
+static inline int nf_postxfrm_nonlocal(struct sk_buff *skb)
+{
+	return 0;
+}
+#endif /* CONFIG_XFRM */
 #endif /*__KERNEL__*/

#endif /*__LINUX_IP_NETFILTER_H*/

include/net/protocol.h +1 -0
diff -Nru a/include/net/protocol.h b/include/net/protocol.h
@@ -39,6 +39,7 @@
 	int			(*handler)(struct sk_buff *skb);
 	void			(*err_handler)(struct sk_buff *skb, u32 info);
 	int			no_policy;
+	int			xfrm_prot;
 };
 
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
net/core/netfilter.c +50 -3

77 lines not on this page · raw message

net/ipv4/ah4.c +1 -0
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
@@ -344,6 +344,7 @@
 	.handler	=	xfrm4_rcv,
 	.err_handler	=	ah4_err,
 	.no_policy	=	1,
+	.xfrm_prot	=	1,
 };
 
 static int __init ah4_init(void)
net/ipv4/esp4.c +1 -0
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
@@ -577,6 +577,7 @@
 	.handler	=	xfrm4_rcv,
 	.err_handler	=	esp4_err,
 	.no_policy	=	1,
+	.xfrm_prot	=	1,
 };
 
 static int __init esp4_init(void)
net/ipv4/ip_input.c +15 -6
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
@@ -224,6 +224,12 @@
 	resubmit:
 		hash = protocol & (MAX_INET_PROTOS - 1);
 		raw_sk = sk_head(&raw_v4_htable[hash]);
+		ipprot = inet_protos[hash];
+		smp_read_barrier_depends();
+
+		if (skb->sp && !ipprot->xfrm_prot)
+			if (nf_postxfrm_input(skb))
+				goto out;
 
 		/* If there maybe a raw socket we must check - if not we
 		 * don't care less
@@ -231,10 +237,9 @@
 		if (raw_sk)
 			raw_v4_input(skb, skb->nh.iph, hash);
 
-		if ((ipprot = inet_protos[hash]) != NULL) {
+		if (ipprot != NULL) {
 			int ret;
 
-			smp_read_barrier_depends();
 			if (!ipprot->no_policy &&
 			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
 				kfree_skb(skb);
@@ -279,8 +284,8 @@
 			return 0;
 	}
 
-	return NF_HOOK(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
-		       ip_local_deliver_finish);
+	return NF_HOOK_COND(PF_INET, NF_IP_LOCAL_IN, skb, skb->dev, NULL,
+	                    ip_local_deliver_finish, !skb->sp);
 }
 
 static inline int ip_rcv_finish(struct sk_buff *skb)
@@ -346,6 +351,10 @@
 		}
 	}
 
+	if (skb->sp && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL))
+		if (nf_postxfrm_nonlocal(skb))
+			goto drop;
+
 	return dst_input(skb);
 
 inhdr_error:
@@ -418,8 +427,8 @@
 		}
 	}
 
-	return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
-		       ip_rcv_finish);
+	return NF_HOOK_COND(PF_INET, NF_IP_PRE_ROUTING, skb, dev, NULL,
+	                    ip_rcv_finish, !skb->sp);
 
 inhdr_error:
 	IP_INC_STATS_BH(IpInHdrErrors);
net/ipv4/ipcomp.c +1 -0
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
@@ -408,6 +408,7 @@
 	.handler	=	xfrm4_rcv,
 	.err_handler	=	ipcomp4_err,
 	.no_policy	=	1,
+	.xfrm_prot	=	1,
 };
 
 static int __init ipcomp4_init(void)
net/ipv4/xfrm4_tunnel.c +1 -0
diff -Nru a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
@@ -171,6 +171,7 @@
 	.handler	=	ipip_rcv,
 	.err_handler	=	ipip_err,
 	.no_policy	=	1,
+	.xfrm_prot	=	1,
 };
 
 static int __init ipip_init(void)
#11 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

Quoted 4 lines · On Thu, 18 Mar 2004 17:32:14 +0100 Patrick McHardy <[email protected]> wrote:

If the protocol handler of a packet with a secpath pointer is a non-xfrm-protocol the packet was handled by ipsec and is done now, it traverses the PRE_ROUTING and LOCAL_IN hooks then. This catches packets from both tunnel-mode and transport-mode SAs.

Be careful! xfrm4_tunnel handles both uncompressed ipcomp packets _and_ IPIP encapsulator device packets. Yet you will intepret usage of the ipprot as 'xfrm_prot==1' in all cases.

Yes this is ugly... if we added some kind of flag bit-mask to sk_buff, would that allow an easier implementation?

author maintainer
#12 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

Quoted 4 lines · David S. Miller

Be careful! xfrm4_tunnel handles both uncompressed ipcomp packets _and_ IPIP encapsulator device packets. Yet you will intepret usage of the ipprot as 'xfrm_prot==1' in all cases.

Good point.

Quoted 2 lines

Yes this is ugly... if we added some kind of flag bit-mask to sk_buff, would that allow an easier implementation?

I'm not sure if this'll help in the degenerate IPCOMP case. Perhaps we need a way to tell if it is a degenerate IPCOMP tunnel or an IPIP tunnel without actually processing the packet.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#13 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

In reply to David S. Miller
Quoted 8 lines · David S. Miller

Be careful! xfrm4_tunnel handles both uncompressed ipcomp packets _and_ IPIP encapsulator device packets. Yet you will intepret usage of the ipprot as 'xfrm_prot==1' in all cases.

Yes this is ugly... if we added some kind of flag bit-mask to sk_buff, would that allow an easier implementation?

I can't imagine how. Best would be to avoid the xfrm_prot flag completely. Maybe we can add a flag to xfrm_state which indicates that this is the last xfrm specified in the policy ?

author maintainer
#14 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

Quoted 4 lines · Patrick McHardy

I can't imagine how. Best would be to avoid the xfrm_prot flag completely. Maybe we can add a flag to xfrm_state which indicates that this is the last xfrm specified in the policy ?

The same state can be terminal in one policy but not another.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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 maintainer
#15 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

In reply to Patrick McHardy
Quoted 5 lines · Patrick McHardy

diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c

net/ipv4/ip_input.c line 232

Quoted 9 lines
net/ipv4/ip_input.c +6 -0
@@ -224,6 +224,12 @@
 	resubmit:
 		hash = protocol & (MAX_INET_PROTOS - 1);
 		raw_sk = sk_head(&raw_v4_htable[hash]);
+		ipprot = inet_protos[hash];
+		smp_read_barrier_depends();
+
+		if (skb->sp && !ipprot->xfrm_prot)
+			if (nf_postxfrm_input(skb))
+				goto out;

Need to check ipprot != NULL here.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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 maintainer
#16 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

In reply to Patrick McHardy
Quoted 5 lines · Patrick McHardy

diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c

net/ipv4/ip_input.c line 232

Quoted 9 lines
net/ipv4/ip_input.c +6 -0
@@ -224,6 +224,12 @@
 	resubmit:
 		hash = protocol & (MAX_INET_PROTOS - 1);
 		raw_sk = sk_head(&raw_v4_htable[hash]);
+		ipprot = inet_protos[hash];
+		smp_read_barrier_depends();
+
+		if (skb->sp && !ipprot->xfrm_prot)
+			if (nf_postxfrm_input(skb))
+				goto out;

Just an idea: what if we reinject the packet just as we do in tunnel mode?

net/ipv4/ip_input.c line 357

Quoted 8 lines
net/ipv4/ip_input.c +4 -0
@@ -346,6 +351,10 @@
 		}
 	}
 
+	if (skb->sp && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL))
+		if (nf_postxfrm_nonlocal(skb))
+			goto drop;
+

What if the PRE_ROUTING turns it into a local address again?

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#17 lore raw

Re: [RFC, PATCH 3/5]: netfilter+ipsec - input hooks

Quoted 18 lines · Herbert Xu

net/ipv4/ip_input.c line 232

Quoted 13 lines · Patrick McHardy

diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c

net/ipv4/ip_input.c +6 -0
@@ -224,6 +224,12 @@
 	resubmit:
 		hash = protocol & (MAX_INET_PROTOS - 1);
 		raw_sk = sk_head(&raw_v4_htable[hash]);
+		ipprot = inet_protos[hash];
+		smp_read_barrier_depends();
+
+		if (skb->sp && !ipprot->xfrm_prot)
+			if (nf_postxfrm_input(skb))
+				goto out;

Just an idea: what if we reinject the packet just as we do in tunnel mode?

If we also have a possibility to determine when decapsulation is done we could avoid the nf_postxfrm_* hacks. Without that, I don't think it helps.

Quoted 6 lines
Quoted 6 lines
net/ipv4/ip_input.c +0 -0
@@ -346,6 +351,10 @@
 		}
 	}
 
Quoted 7 lines

net/ipv4/ip_input.c line 357

Quoted 4 lines
net/ipv4/ip_input.c +4 -0
+	if (skb->sp && !(((struct rtable *)skb->dst)->rt_flags&RTCF_LOCAL))
+		if (nf_postxfrm_nonlocal(skb))
+			goto drop;
+

What if the PRE_ROUTING turns it into a local address again?

You have good eyes ;) The packet needs to be rerouted in nf_postxfrm_nonlocal and needs to be special-cased in nf_postxfrm_input so it doesn't traverse PRE_ROUTING twice.

Thanks for your other suggestions as well, I'm going to make these changes.

Regards
Patrick

#18 lore raw

RFC PATCH 4/5 : netfilter+ipsec - policy lookup

In reply to David S. Miller

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/03/18 16:43:22+01:00 [email protected]
# [NETFILTER]: Add policy lookups to ip_route_me_harder, make NAT reroute for any change in route/policy key
#

# net/ipv4/netfilter/ip_nat_standalone.c
#   2004/03/18 16:43:16+01:00 [email protected] +72 -8
#   [NETFILTER]: Add policy lookups to ip_route_me_harder, make NAT reroute for any change in route/policy key
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2004/03/18 16:43:16+01:00 [email protected] +1 -0
#   [NETFILTER]: Add policy lookups to ip_route_me_harder, make NAT reroute for any change in route/policy key
# 
# net/core/netfilter.c
#   2004/03/18 16:43:16+01:00 [email protected] +15 -1
#   [NETFILTER]: Add policy lookups to ip_route_me_harder, make NAT reroute for any change in route/policy key
# 
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
--- a/net/core/netfilter.c	Thu Mar 18 16:46:02 2004
+++ b/net/core/netfilter.c	Thu Mar 18 16:46:02 2004
@@ -27,6 +27,7 @@
 #include <net/sock.h>
 #include <net/route.h>
 #include <net/xfrm.h>
+#include <net/ip.h>
 #include <linux/ip.h>

/* In this code, we can be waiting indefinitely for userspace to
@@ -635,7 +636,6 @@
#ifdef CONFIG_IP_ROUTE_FWMARK
fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
#endif
- fl.proto = iph->protocol;
if (ip_route_output_key(&rt, &fl) != 0)
return -1;

@@ -661,6 +661,20 @@

if ((*pskb)->dst->error)
return -1;
+
+#ifdef CONFIG_XFRM
+ if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+ struct xfrm_policy_afinfo *afinfo;
+
+ afinfo = xfrm_policy_get_afinfo(AF_INET);
+ if (afinfo != NULL) {
+ afinfo->decode_session(*pskb, &fl);
+ xfrm_policy_put_afinfo(afinfo);
+ if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
+ return -1;
+ }
+ }
+#endif

/* Change in oif may mean change in hh_len. */ hh_len = (*pskb)->dst->dev->hard_header_len;

net/ipv4/netfilter/ip_conntrack_standalone.c +1 -0
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
@@ -583,6 +583,7 @@
 EXPORT_SYMBOL(ip_conntrack_alter_reply);
 EXPORT_SYMBOL(ip_conntrack_destroyed);
 EXPORT_SYMBOL(ip_conntrack_get);
+EXPORT_SYMBOL(__ip_conntrack_confirm);
 EXPORT_SYMBOL(need_ip_conntrack);
 EXPORT_SYMBOL(ip_conntrack_helper_register);
 EXPORT_SYMBOL(ip_conntrack_helper_unregister);
net/ipv4/netfilter/ip_nat_standalone.c +72 -8

112 lines not on this page · raw message

#19 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 2 lines · On Thu, 18 Mar 2004 17:32:23 +0100 Patrick McHardy <[email protected]> wrote:

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

Why are you deleting that "fl.proto = iph->protocol;" line in net/core/netfilter.c? Is something else going to set it properly?

#20 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 11 lines · David S. Miller
Quoted 2 lines · On Thu, 18 Mar 2004 17:32:23 +0100 Patrick McHardy <[email protected]> wrote:

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

Why are you deleting that "fl.proto = iph->protocol;" line in net/core/netfilter.c? Is something else going to set it properly?

The patch adds a call to decode_session/xfrm_lookup below. This handles packets with local and non-local source, setting fl.proto only handles packets with local source. Also we must check if the packet was already transformed to prevent loops.

Regards
Patrick

author maintainer
#21 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

In reply to Patrick McHardy

Review line 638

Quoted 6 lines · Patrick McHardy
(quoted diff) +0 -1
@@ -635,7 +636,6 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-		fl.proto = iph->protocol;

Better call __ip_route_output_key rather than not setting proto because you'll need proto in xfrm_lookup.

Quoted 12 lines
(quoted diff) +4 -0
 		if (ip_route_output_key(&rt, &fl) != 0)
 			return -1;
 
@@ -661,6 +661,20 @@
 
 	if ((*pskb)->dst->error)
 		return -1;
+
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+		struct xfrm_policy_afinfo *afinfo;

Review line 677

Quoted 10 lines
(quoted diff) +10 -0
+
+		afinfo = xfrm_policy_get_afinfo(AF_INET);
+		if (afinfo != NULL) {
+			afinfo->decode_session(*pskb, &fl);
+			xfrm_policy_put_afinfo(afinfo);
+			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
+				return -1;
+		}
+	}
+#endif

If we can reinject transport packets then we can move this back into the if clause.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#22 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 32 lines · Herbert Xu

Review line 638

Quoted 5 lines · Patrick McHardy
(quoted diff) +0 -1
@@ -635,7 +636,6 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-		fl.proto = iph->protocol;

Better call __ip_route_output_key rather than not setting proto because you'll need proto in xfrm_lookup.

Quoted 19 lines
(quoted diff) +10 -0
 		if (ip_route_output_key(&rt, &fl) != 0)
 			return -1;
 
@@ -661,6 +661,20 @@
 
 	if ((*pskb)->dst->error)
 		return -1;
+
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+		struct xfrm_policy_afinfo *afinfo;
+
+		afinfo = xfrm_policy_get_afinfo(AF_INET);
+		if (afinfo != NULL) {
+			afinfo->decode_session(*pskb, &fl);
+			xfrm_policy_put_afinfo(afinfo);
+			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
Quoted 8 lines

net/ipv4/netfilter/ip_nat_standalone.c line 205

Quoted 4 lines
net/ipv4/netfilter/ip_nat_standalone.c +4 -0
+				return -1;
+		}
+	}
+#endif

If we can reinject transport packets then we can move this back into the if clause.

I don't understand the relationship to transport mode packets. I used an explicit call to xfrm_lookup so packets with non-local source are also handled. We also need to protect against loops, packets which are already transformed should not be transformed again.

Regards
Patrick

author maintainer
#23 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 12 lines · Patrick McHardy
Quoted 11 lines · Herbert Xu

Review line 638

Quoted 5 lines · Patrick McHardy
(quoted diff) +0 -1
@@ -635,7 +636,6 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-		fl.proto = iph->protocol;

Better call __ip_route_output_key rather than not setting proto because you'll need proto in xfrm_lookup.

Right, you're calling decode_session below which is much better.

Quoted 24 lines
Quoted 15 lines
Quoted 15 lines
(quoted diff) +10 -0
@@ -661,6 +661,20 @@
 
 	if ((*pskb)->dst->error)
 		return -1;
+
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+		struct xfrm_policy_afinfo *afinfo;
+
+		afinfo = xfrm_policy_get_afinfo(AF_INET);
+		if (afinfo != NULL) {
+			afinfo->decode_session(*pskb, &fl);
+			xfrm_policy_put_afinfo(afinfo);
+			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) 
 != 0)
Quoted 8 lines

net/ipv4/netfilter/ip_nat_standalone.c line 205

Quoted 4 lines
net/ipv4/netfilter/ip_nat_standalone.c +4 -0
+				return -1;
+		}
+	}
+#endif

If we can reinject transport packets then we can move this back into the if clause.

Quoted 1 line

I don't understand the relationship to transport mode packets. I used an

Actually it was me who was confused. ip_route_me_harder can be called on both incoming/outgoing packets. That's what the if clause is trying to determine. You should only call xfrm_lookup on the outgoing path.

So this should be moved back to the if clause above:

		fl.proto = iph->protocol;
		lookup = __ip_route_output_key;
#ifdef CONFIG_XFRM
		if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
			lookup = ip_route_output_key;
			do_decode
		}
#endif
		if (lookup(&rt, &fl) != 0)
			return -1;
Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#24 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 4 lines · Herbert Xu

Actually it was me who was confused. ip_route_me_harder can be called on both incoming/outgoing packets. That's what the if clause is trying to determine. You should only call xfrm_lookup on the outgoing path.

No, ip_route_me_harder is currently (without the patches) only called for outgoing packets. The if-clause is there because ip_route_output doesn't handle packets with non-local source, and we don't want to set the source to 0 (as was done before) because it prevents policy routing from working properly. That's why we need the xfrm_lookup for both cases.

Regards
Patrick

Quoted 13 lines

So this should be moved back to the if clause above:

		fl.proto = iph->protocol;
		lookup = __ip_route_output_key;
#ifdef CONFIG_XFRM
		if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
			lookup = ip_route_output_key;
			do_decode
		}
#endif
		if (lookup(&rt, &fl) != 0)
			return -1;
author maintainer
#25 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 6 lines · Patrick McHardy
Quoted 4 lines · Herbert Xu

Actually it was me who was confused. ip_route_me_harder can be called on both incoming/outgoing packets. That's what the if clause is trying to determine. You should only call xfrm_lookup on the outgoing path.

Quoted 6 lines

No, ip_route_me_harder is currently (without the patches) only called for outgoing packets. The if-clause is there because ip_route_output doesn't handle packets with non-local source, and we don't want to set the source to 0 (as was done before) because it prevents policy routing from working properly. That's why we need the xfrm_lookup for both cases.

You're right. Sorry for the confusion.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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 maintainer
#26 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

In reply to Patrick McHardy
Quoted 9 lines · Patrick McHardy
(quoted diff) +4 -0
@@ -661,6 +661,20 @@
 
 	if ((*pskb)->dst->error)
 		return -1;
+
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+		struct xfrm_policy_afinfo *afinfo;

Review line 677

Quoted 10 lines
(quoted diff) +10 -0
+
+		afinfo = xfrm_policy_get_afinfo(AF_INET);
+		if (afinfo != NULL) {
+			afinfo->decode_session(*pskb, &fl);
+			xfrm_policy_put_afinfo(afinfo);
+			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
+				return -1;
+		}
+	}
+#endif

BTW, you can xfrm4_route_forward here.

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#27 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 16 lines · Herbert Xu
Quoted 14 lines · Patrick McHardy
(quoted diff) +9 -0
@@ -661,6 +661,20 @@
 
 	if ((*pskb)->dst->error)
 		return -1;
+
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED)) {
+		struct xfrm_policy_afinfo *afinfo;
+
+		afinfo = xfrm_policy_get_afinfo(AF_INET);
+		if (afinfo != NULL) {
+			afinfo->decode_session(*pskb, &fl);
+			xfrm_policy_put_afinfo(afinfo);
Quoted 8 lines

net/ipv4/netfilter/ip_nat_standalone.c line 205

Quoted 5 lines
net/ipv4/netfilter/ip_nat_standalone.c +5 -0
+			if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0) != 0)
+				return -1;
+		}
+	}
+#endif

BTW, you can xfrm4_route_forward here.

Is it correct that __xfrm_route_forward will use NULL for the sock parameter to xfrm_lookup even if the packet is from a local socket ?

Regards
Patrick

author maintainer
#28 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 6 lines · Patrick McHardy
Quoted 2 lines · Herbert Xu

BTW, you can xfrm4_route_forward here.

Is it correct that __xfrm_route_forward will use NULL for the sock parameter to xfrm_lookup even if the packet is from a local socket ?

No that would be wrong as socket policies won't be applied correctly. Forget about that idea :)

Signature · 4 lines
Debian GNU/Linux 3.0 is out! ( http://www.debian.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
#29 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 7 lines · Herbert Xu
Quoted 2 lines · Patrick McHardy

Is it correct that __xfrm_route_forward will use NULL for the sock parameter to xfrm_lookup even if the packet is from a local socket ?

No that would be wrong as socket policies won't be applied correctly. Forget about that idea :)

Thanks anyway, it reminded me to check for !(dst->flags & DST_NOXFRM) before xfrm_lookup, I'm going to change this now.

Regards
Patrick

#30 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

In reply to Patrick McHardy

Hi

Think their might be a problem with this patch.

Potientially a packet could traverse the pre, forward and the post routing, at which point it can be SNAT'ed or MASQ'ed and then re injected into route_me_harder. This potiential could allow packets to be rerouted based on the new src/dst addresses differently to the intail packet but this new packet doesn't traverse any of the chains with the new information.

Alex

Quoted 3 lines · Patrick McHardy

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

#31 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 10 lines · Alexander Samad

Hi

Think their might be a problem with this patch.

Potientially a packet could traverse the pre, forward and the post routing, at which point it can be SNAT'ed or MASQ'ed and then re injected into route_me_harder. This potiential could allow packets to be rerouted based on the new src/dst addresses differently to the intail packet but this new packet doesn't traverse any of the chains with the new information.

This is just as without the patches, SNAT in POST_ROUTING never causes a packet to re-traverse the hooks. There is one minor difference, packets which match a policy after NAT stop traversing the hooks at NF_IP_PRI_NAT_SRC priority. I will fix this this for the final version.

Regards
Patrick

Quoted 11 lines

Alex

Quoted 3 lines · Patrick McHardy

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

#32 lore raw

Re: [RFC, PATCH 4/5]: netfilter+ipsec - policy lookup

Quoted 12 lines · Patrick McHardy
Quoted 10 lines · Alexander Samad

Hi

Think their might be a problem with this patch.

Potientially a packet could traverse the pre, forward and the post routing, at which point it can be SNAT'ed or MASQ'ed and then re injected into route_me_harder. This potiential could allow packets to be rerouted based on the new src/dst addresses differently to the intail packet but this new packet doesn't traverse any of the chains with the new information.

Quoted 4 lines

This is just as without the patches, SNAT in POST_ROUTING never causes a packet to re-traverse the hooks. There is one minor difference, packets which match a policy after NAT stop traversing the hooks at NF_IP_PRI_NAT_SRC priority. I will fix this this for the final version.

Sorry might not have made myself clear, after an SNAT with your patch the packet is re injected into route_me_harder, thus the packet is able to be rerouted (sent out another interface for example)

What this would mean is a packet could meet your iptable rules with is PRE-SNAT details and then actually behave differently once it has been SNAT'ed (and not get checked)

Alex

Quoted 17 lines

Regards
Patrick

Quoted 11 lines

Alex

Quoted 3 lines · Patrick McHardy

This patch adds policy lookups to ip_route_me_harder and makes NAT reroute for any change that affects route/policy lookups.

#33 lore raw

RFC PATCH 5/5 : netfilter+ipsec - policy checks

In reply to David S. Miller

This patch makes xfrm_policy_check locate the correct policy after NAT. For protocols which do policy checks in their receive routines the reference to nfct has to be kept until policy checks are done, the other ones still drop it in ip_local_deliver_finish.

# This is a BitKeeper generated diff -Nru style patch. #
# ChangeSet
# 2004/03/18 16:44:21+01:00 [email protected]
# [NETFILTER]: Make policy checks find correct policy after NAT
#

# net/xfrm/xfrm_policy.c
#   2004/03/18 16:44:12+01:00 [email protected] +2 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# net/ipv4/udp.c
#   2004/03/18 16:44:12+01:00 [email protected] +2 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# net/ipv4/tcp_ipv4.c
#   2004/03/18 16:44:12+01:00 [email protected] +1 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# net/ipv4/raw.c
#   2004/03/18 16:44:12+01:00 [email protected] +1 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# net/ipv4/ip_input.c
#   2004/03/18 16:44:12+01:00 [email protected] +6 -8
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# net/core/netfilter.c
#   2004/03/18 16:44:12+01:00 [email protected] +43 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
# include/linux/netfilter.h
#   2004/03/18 16:44:12+01:00 [email protected] +16 -0
#   [NETFILTER]: Make policy checks find correct policy after NAT
# 
diff -Nru a/include/linux/netfilter.h b/include/linux/netfilter.h
--- a/include/linux/netfilter.h	Thu Mar 18 16:46:27 2004
+++ b/include/linux/netfilter.h	Thu Mar 18 16:46:27 2004
@@ -171,5 +171,21 @@
 #define NF_HOOK_COND NF_HOOK
 #endif /*CONFIG_NETFILTER*/

+#ifdef CONFIG_XFRM
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+struct flowi;
+extern void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl); +
+static inline void
+nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) +{
+ if (family == AF_INET)
+ nf_nat_decode_session4(skb, fl);
+}
+#else /* CONFIG_IP_NF_NAT_NEEDED */
+#define nf_nat_decode_session(skb,fl,family)
+#endif /* CONFIG_IP_NF_NAT_NEEDED */
+#endif /* CONFIG_XFRM */
+
#endif /*__KERNEL__*/
#endif /*__LINUX_NETFILTER_H*/

net/core/netfilter.c +43 -0
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
@@ -739,6 +739,49 @@
 	return NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
 	               nf_postxfrm_done);
 }
+
+#ifdef CONFIG_IP_NF_NAT_NEEDED
+#include <linux/netfilter_ipv4/ip_conntrack.h>
+#include <linux/netfilter_ipv4/ip_nat.h>
+
+void nf_nat_decode_session4(struct sk_buff *skb, struct flowi *fl)
+{
+	struct ip_conntrack *ct;
+	struct ip_conntrack_tuple *t;
+	struct ip_nat_info_manip *m;
+	unsigned int i;
+
+	if (skb->nfct == NULL)
+		return;
+	ct = (struct ip_conntrack *)skb->nfct->master;
+
+	for (i = 0; i < ct->nat.info.num_manips; i++) {
+		m = &ct->nat.info.manips[i];
+		t = &ct->tuplehash[m->direction].tuple;
+
+		switch (m->hooknum) {
+		case NF_IP_PRE_ROUTING:
+			if (m->maniptype != IP_NAT_MANIP_DST)
+				break;
+			fl->fl4_dst = t->dst.ip;
+			if (t->dst.protonum == IPPROTO_TCP ||
+			    t->dst.protonum == IPPROTO_UDP)
+				fl->fl_ip_dport = t->dst.u.tcp.port;
+			break;
+#ifdef CONFIG_IP_NF_NAT_LOCAL
+		case NF_IP_LOCAL_IN:
+			if (m->maniptype != IP_NAT_MANIP_SRC)
+				break;
+			fl->fl4_src = t->src.ip;
+			if (t->dst.protonum == IPPROTO_TCP ||
+			    t->dst.protonum == IPPROTO_UDP)
+				fl->fl_ip_sport = t->src.u.tcp.port;
+			break;
+#endif
+		}
+	}
+}
+#endif /* CONFIG_IP_NF_NAT_NEEDED */
 #endif /* CONFIG_XFRM */
 
 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
net/ipv4/ip_input.c +6 -8
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
@@ -206,10 +206,6 @@
 
 	__skb_pull(skb, ihl);
 
-	/* Free reference early: we don't need it any more, and it may
-           hold ip_conntrack module loaded indefinitely. */
-	nf_reset(skb);
-
         /* Point into the IP datagram, just past the header. */
         skb->h.raw = skb->data;
 
@@ -240,10 +236,12 @@
 		if (ipprot != NULL) {
 			int ret;
 
-			if (!ipprot->no_policy &&
-			    !xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
-				kfree_skb(skb);
-				goto out;
+			if (!ipprot->no_policy) {
+				if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) {
+					kfree_skb(skb);
+					goto out;
+				}
+				nf_reset(skb);
 			}
 			ret = ipprot->handler(skb);
 			if (ret < 0) {
net/ipv4/raw.c +1 -0
diff -Nru a/net/ipv4/raw.c b/net/ipv4/raw.c
@@ -249,6 +249,7 @@
 		kfree_skb(skb);
 		return NET_RX_DROP;
 	}
+	nf_reset(skb);
 
 	skb_push(skb, skb->data - skb->nh.raw);
 
net/ipv4/tcp_ipv4.c +1 -0
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
@@ -1785,6 +1785,7 @@
 
 	if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
 		goto discard_and_relse;
+	nf_reset(skb);
 
 	if (sk_filter(sk, skb, 0))
 		goto discard_and_relse;
net/ipv4/udp.c +2 -0
diff -Nru a/net/ipv4/udp.c b/net/ipv4/udp.c
@@ -1030,6 +1030,7 @@
 		kfree_skb(skb);
 		return -1;
 	}
+	nf_reset(skb);
 
 	if (up->encap_type) {
 		/*
@@ -1195,6 +1196,7 @@
 
 	if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
 		goto drop;
+	nf_reset(skb);
 
 	/* No socket. Drop packet silently, if checksum is wrong */
 	if (udp_checksum_complete(skb))
net/xfrm/xfrm_policy.c +2 -0
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/notifier.h>
 #include <linux/netdevice.h>
+#include <linux/netfilter.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 
@@ -908,6 +909,7 @@
 
 	if (_decode_session(skb, &fl, family) < 0)
 		return 0;
+	nf_nat_decode_session(skb, &fl, family);
 
 	/* First, check used SA against their selectors. */
 	if (skb->sp) {
#34 lore raw

Re: [RFC, PATCH 5/5]: netfilter+ipsec - policy checks

Quoted 4 lines · On Thu, 18 Mar 2004 17:32:39 +0100 Patrick McHardy <[email protected]> wrote:

This patch makes xfrm_policy_check locate the correct policy after NAT. For protocols which do policy checks in their receive routines the reference to nfct has to be kept until policy checks are done, the other ones still drop it in ip_local_deliver_finish.

This patch looks fine to me.

Other than the minor comments I've made the most unhappy I am with the input patch, and you agree it's grotty too. Let's look for a better solution, perhaps with new top-level SKB state, and then we can put all of your work in after you're made the other minor fixes I've asked for as well.

Thanks Patrick.

#35 lore raw

Re: [RFC, PATCH 5/5]: netfilter+ipsec - policy checks

I have applied these to 2.6.4 (debian source) and compiles okay and seems to work okay, ie the NAT + IPSEC

my 2c

Quoted 20 lines · David S. Miller
Quoted 4 lines · On Thu, 18 Mar 2004 17:32:39 +0100 Patrick McHardy <[email protected]> wrote:

This patch makes xfrm_policy_check locate the correct policy after NAT. For protocols which do policy checks in their receive routines the reference to nfct has to be kept until policy checks are done, the other ones still drop it in ip_local_deliver_finish.

This patch looks fine to me.

Other than the minor comments I've made the most unhappy I am with the input patch, and you agree it's grotty too. Let's look for a better solution, perhaps with new top-level SKB state, and then we can put all of your work in after you're made the other minor fixes I've asked for as well.

Thanks Patrick.

#36 lore raw

Re: [RFC, PATCH 5/5]: netfilter+ipsec - policy checks

Quoted 4 lines · Alexander Samad

I have applied these to 2.6.4 (debian source) and compiles okay and seems to work okay, ie the NAT + IPSEC

my 2c

Done some more testing and there seems to be a problem with the NAT table

Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source
destination

   12   720            all  --  *      *       0.0.0.0/0 192.168.5.2
    0     0 DROP       all  --  *      *       169.254.0.0/16 0.0.0.0/0
54378 5744K ACCEPT     all  --  *      *       0.0.0.0/0 0.0.0.0/0           state NEW

Chain POSTROUTING (policy ACCEPT 6 packets, 240 bytes)

 pkts bytes target     prot opt in     out     source destination
    0     0            all  --  *      *       0.0.0.0/0 192.168.5.2
 2872  537K MASQUERADE  all  --  *      eth0    192.168.8.0/22 0.0.0.0/0
    0     0 MASQUERADE  all  --  *      ppp+    192.168.8.0/22 0.0.0.0/0

165K 25M ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state NEW

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)

 pkts bytes target     prot opt in     out     source destination
    0     0            all  --  *      *       0.0.0.0/0 192.168.5.2
 169K   25M ACCEPT     all  --  *      *       0.0.0.0/0 0.0.0.0/0           state NEW

There is an ipsec tunnel out of eth0 setup like

conn abcd

	leftsubnet 192.168.8.0/22
	rightsubnet 192.168.5.0/24

when I ping from 192.168.10.244 through to 192.168.5.2 it doesn't seem to it through to POSTROUTING, the counter in PREROUTING increase.

My initial search for this was why I did not need a rule to stop the MASQ from happening

This is using the 2.6 stack (2.6.4 debain)

Alex

Quoted 22 lines · David S. Miller
Quoted 20 lines
Quoted 4 lines · On Thu, 18 Mar 2004 17:32:39 +0100 Patrick McHardy <[email protected]> wrote:

This patch makes xfrm_policy_check locate the correct policy after NAT. For protocols which do policy checks in their receive routines the reference to nfct has to be kept until policy checks are done, the other ones still drop it in ip_local_deliver_finish.

This patch looks fine to me.

Other than the minor comments I've made the most unhappy I am with the input patch, and you agree it's grotty too. Let's look for a better solution, perhaps with new top-level SKB state, and then we can put all of your work in after you're made the other minor fixes I've asked for as well.

Thanks Patrick.

#37 lore raw

Re: [RFC, PATCH 5/5]: netfilter+ipsec - policy checks

Quoted 3 lines · Alexander Samad

Done some more testing and there seems to be a problem with the NAT table

Thanks for the report, does this patch fix it ?

Regards
Patrick

===== net/ipv4/raw.c 1.44 vs edited =====

net/ipv4/raw.c +7 -1
@@ -257,6 +257,12 @@
 	return 0;
 }
 
+static inline int ip_dst_output(struct sk_buff *skb)
+{
+	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL,
+	                    skb->dst->dev, dst_output, skb->dst->xfrm != NULL);
+}
+
 static int raw_send_hdrinc(struct sock *sk, void *from, int length,
 			struct rtable *rt, 
 			unsigned int flags)
@@ -308,7 +314,7 @@
 	}
 
 	err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,
-		      dst_output);
+		      ip_dst_output);
 	if (err > 0)
 		err = inet->recverr ? net_xmit_errno(err) : 0;
 	if (err)
#38 lore raw

Re: [RFC, PATCH 5/5]: netfilter+ipsec - policy checks

In reply to David S. Miller
Quoted 5 lines · David S. Miller

Other than the minor comments I've made the most unhappy I am with the input patch, and you agree it's grotty too. Let's look for a better solution, perhaps with new top-level SKB state, and then we can put all of your work in after you're made the other minor fixes I've asked for as well.

I'm going to make the changes you suggested. Can you please explain what you imagine with the new top-level skb state ?

Regards
Patrick