Skip to contentSkip to conversation

: Redo policy lookups after NAT when necessary

PATCH In review Patrick McHardy 1 participant 1 message Oct 17, 2005

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

PATCH 5/6 : Redo policy lookups after NAT when necessary

[NETFILTER]: Redo policy lookups after NAT when necessary

---
commit 373ca7e8b42cb5abbaf86e41a755363aa4029850
tree b33c60701979f2a795c8d7feef1262b141d7f3a2
parent 9b2748c756fd805c0fe5b37505735e02f06ebb28
author Patrick McHardy <[email protected]> Mon, 17 Oct 2005 01:45:45 +0200 committer Patrick McHardy <[email protected]> Mon, 17 Oct 2005 01:45:45 +0200

 include/net/ip.h                       |    1 +
 include/net/xfrm.h                     |    2 +
 net/ipv4/ip_output.c                   |    6 ++++
 net/ipv4/netfilter.c                   |    9 +++++
 net/ipv4/netfilter/ip_nat_standalone.c |   54 +++++++++++++++++++++++---------
 net/ipv4/xfrm4_output.c                |    1 +
 net/xfrm/xfrm_policy.c                 |    8 ++---
 7 files changed, 61 insertions(+), 20 deletions(-)
include/net/ip.h +1 -0
@@ -45,6 +45,7 @@ struct inet_skb_parm
 #define IPSKB_TRANSLATED	2
 #define IPSKB_FORWARDED		4
 #define IPSKB_XFRM_TUNNEL_SIZE	8
+#define IPSKB_XFRM_TRANSFORMED	16
 };
 
 struct ipcm_cookie
include/net/xfrm.h +1 -1
@@ -644,7 +644,7 @@ static inline int xfrm6_policy_check(str
 	return xfrm_policy_check(sk, dir, skb, AF_INET6);
 }
 
-
+extern int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family);
 extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family);
 
 static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family)
net/ipv4/ip_output.c +6 -0
@@ -167,6 +167,12 @@ static inline int ip_finish_output3(stru
 	struct net_device *dev = dst->dev;
 	int hh_len = LL_RESERVED_SPACE(dev);
 
+#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)
+	/* Policy lookup after SNAT yielded a new policy */
+	if (dst->xfrm != NULL)
+		return __ip_dst_output(skb);
+#endif
+
 	/* Be paranoid, rather than too clever. */
 	if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {
 		struct sk_buff *skb2;
net/ipv4/netfilter.c +9 -0
@@ -13,6 +13,7 @@
 #include <linux/ip.h>
 #include <net/route.h>
 #include <net/xfrm.h>
+#include <net/ip.h>
 
 /* route_me_harder function, used by iptable_nat, iptable_mangle + ip_queue */
 int ip_route_me_harder(struct sk_buff **pskb)
@@ -61,6 +62,14 @@ int ip_route_me_harder(struct sk_buff **
 	if ((*pskb)->dst->error)
 		return -1;
 
+#ifdef CONFIG_XFRM
+	if (!(IPCB(*pskb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+	    xfrm_decode_session(*pskb, &fl, AF_INET) == 0) {
+		if (xfrm_lookup(&(*pskb)->dst, &fl, (*pskb)->sk, 0))
+			return -1;
+	}
+#endif
+
 	/* Change in oif may mean change in hh_len. */
 	hh_len = (*pskb)->dst->dev->hard_header_len;
 	if (skb_headroom(*pskb) < hh_len) {
net/ipv4/netfilter/ip_nat_standalone.c +39 -15

91 lines not on this page · raw message

net/ipv4/xfrm4_output.c +1 -0
@@ -133,6 +133,7 @@ int xfrm4_output(struct sk_buff *skb)
 		err = -EHOSTUNREACH;
 		goto error_nolock;
 	}
+	IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED;
 	nf_reset(skb);
 	err = NET_XMIT_BYPASS;
 
net/xfrm/xfrm_policy.c +4 -4
@@ -906,8 +906,8 @@ xfrm_policy_ok(struct xfrm_tmpl *tmpl, s
 	return start;
 }
 
-static int
-_decode_session(struct sk_buff *skb, struct flowi *fl, unsigned short family)
+int xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
+                        unsigned short family)
 {
 	struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
 
@@ -935,7 +935,7 @@ int __xfrm_policy_check(struct sock *sk,
 	struct xfrm_policy *pol;
 	struct flowi fl;
 
-	if (_decode_session(skb, &fl, family) < 0)
+	if (xfrm_decode_session(skb, &fl, family) < 0)
 		return 0;
 
 	/* First, check used SA against their selectors. */
@@ -1007,7 +1007,7 @@ int __xfrm_route_forward(struct sk_buff 
 {
 	struct flowi fl;
 
-	if (_decode_session(skb, &fl, family) < 0)
+	if (xfrm_decode_session(skb, &fl, family) < 0)
 		return 0;
 
 	return xfrm_lookup(&skb->dst, &fl, NULL, 0) == 0;