linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6] netfilter policy routing fixes
@ 2003-07-25 20:52 Harald Welte
  0 siblings, 0 replies; only message in thread
From: Harald Welte @ 2003-07-25 20:52 UTC (permalink / raw)
  To: David Miller; +Cc: Netfilter Development Mailinglist, Linux Kernel Mailinglist

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

Hi Dave!

This is the 2nd of my 2.6 merge of the recent bugfixes (all tested
against 2.4.22-pre7).  You might need to apply them incrementally
(didn't test it in a different order). 

Author: Patrick McHardy <kaber@trash.net>

This patch fixes some issues with iptables REJECT and MIRROR targets
when combined with policy routing / rp_filter.

Please apply,

diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.0-test1-nftest2/net/ipv4/netfilter/ipt_MIRROR.c linux-2.6.0-test1-nftest3/net/ipv4/netfilter/ipt_MIRROR.c
--- linux-2.6.0-test1-nftest2/net/ipv4/netfilter/ipt_MIRROR.c	2003-07-19 16:05:13.000000000 +0200
+++ linux-2.6.0-test1-nftest3/net/ipv4/netfilter/ipt_MIRROR.c	2003-07-19 16:13:56.000000000 +0200
@@ -12,6 +12,9 @@
 	18 Jul 2003 Harald Welte <laforge@netfilter.org>
 		- merge Patrick McHardy's mirror fixes from 2.4.22 to
 		  2.6.0-test1
+	19 Jul 2003 Harald Welte <laforge@netfilter.org>
+		- merge Patrick McHardy's rp_filter fixes from 2.4.22 to
+		  2.6.0-test1
 
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
@@ -43,17 +46,42 @@
 #define DEBUGP(format, args...)
 #endif
 
-static inline struct rtable *route_mirror(struct sk_buff *skb)
+static inline struct rtable *route_mirror(struct sk_buff *skb, int local)
 {
         struct iphdr *iph = skb->nh.iph;
-	struct flowi fl = { .nl_u = { .ip4_u = { .daddr = iph->saddr,
-						 .saddr = iph->daddr,
-						 .tos = RT_TOS(iph->tos) } } };
+	struct dst_entry *odst;
+	struct flowi fl = {};
 	struct rtable *rt;
 
-	/* Backwards */
-	if (ip_route_output_key(&rt, &fl))
-		return NULL;
+	if (local) {
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		fl.nl_u.ip4_u.saddr = iph->daddr;
+		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return NULL;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input(). */
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return NULL;
+
+		odst = skb->dst;
+		if (ip_route_input(skb, iph->saddr, iph->daddr,
+					RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return NULL;
+		}
+		dst_release(&rt->u.dst);
+		rt = (struct rtable *)skb->dst;
+		skb->dst = odst;
+	}
+
+	if (rt->u.dst.error) {
+		dst_release(&rt->u.dst);
+		rt = NULL;
+	}
 
 	return rt;
 }
@@ -123,7 +151,7 @@
 		ip_decrease_ttl((*pskb)->nh.iph);
 	}
 
-	if ((rt = route_mirror(*pskb)) == NULL)
+	if ((rt = route_mirror(*pskb, hooknum == NF_IP_LOCAL_IN)) == NULL)
 		return NF_DROP;
 
 	hh_len = (rt->u.dst.dev->hard_header_len + 15) & ~15;
diff -Nru --exclude .depend --exclude '*.o' --exclude '*.ko' --exclude '*.ver' --exclude '.*.flags' --exclude '*.orig' --exclude '*.rej' --exclude '*.cmd' --exclude '*.mod.c' --exclude '*~' linux-2.6.0-test1-nftest2/net/ipv4/netfilter/ipt_REJECT.c linux-2.6.0-test1-nftest3/net/ipv4/netfilter/ipt_REJECT.c
--- linux-2.6.0-test1-nftest2/net/ipv4/netfilter/ipt_REJECT.c	2003-07-19 14:14:23.000000000 +0200
+++ linux-2.6.0-test1-nftest3/net/ipv4/netfilter/ipt_REJECT.c	2003-07-19 16:13:32.000000000 +0200
@@ -35,6 +35,46 @@
 	}
 }
 
+static inline struct rtable *route_reverse(struct sk_buff *skb, int local)
+{
+	struct iphdr *iph = skb->nh.iph;
+	struct dst_entry *odst;
+	struct flowi fl = {};
+	struct rtable *rt;
+
+	if (local) {
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		fl.nl_u.ip4_u.saddr = iph->daddr;
+		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return NULL;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input. */
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return NULL;
+
+		odst = skb->dst;
+		if (ip_route_input(skb, iph->saddr, iph->daddr,
+		                   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return NULL;
+		}
+		dst_release(&rt->u.dst);
+		rt = (struct rtable *)skb->dst;
+		skb->dst = odst;
+	}
+
+	if (rt->u.dst.error) {
+		dst_release(&rt->u.dst);
+		rt = NULL;
+	}
+
+	return rt;
+}
+
 /* Send RST reply */
 static void send_reset(struct sk_buff *oldskb, int local)
 {
@@ -69,18 +109,9 @@
 			 csum_partial((char *)otcph, otcplen, 0)) != 0)
 		return;
 
-	{
-		struct flowi fl = { .nl_u = { .ip4_u =
-					      { .daddr = oldskb->nh.iph->saddr,
-						.saddr = (local ?
-							  oldskb->nh.iph->daddr :
-							  0),
-						.tos = RT_TOS(oldskb->nh.iph->tos) } } };
-
-	/* Routing: if not headed for us, route won't like source */
-	if (ip_route_output_key(&rt, &fl))
+	if ((rt = route_reverse(oldskb, local)) == NULL)
 		return;
-	}		
+
 	hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
 
 	/* Copy skb (even if skb is about to be dropped, we can't just
--- linux-2.6.0-test1-nftest2/net/core/netfilter.c	2003-07-14 05:33:59.000000000 +0200
+++ linux-2.6.0-test1-nftest3/net/core/netfilter.c	2003-07-19 16:21:26.000000000 +0200
@@ -625,66 +625,62 @@
 {
 	struct iphdr *iph = (*pskb)->nh.iph;
 	struct rtable *rt;
-	struct flowi fl = { .nl_u = { .ip4_u =
-				      { .daddr = iph->daddr,
-					.saddr = iph->saddr,
-					.tos = RT_TOS(iph->tos)|RTO_CONN,
+	struct flowi fl = {};
+	struct dst_entry *odst;
+	unsigned int hh_len;
+
+	/* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
+	 * packets with foreign saddr to appear on the NF_IP_LOCAL_OUT hook.
+	 */
+	if (inet_addr_type(iph->saddr) == RTN_LOCAL) {
+		fl.nl_u.ip4_u.daddr = iph->daddr;
+		fl.nl_u.ip4_u.saddr = iph->saddr;
+		fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
+		fl.oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0;
 #ifdef CONFIG_IP_ROUTE_FWMARK
-					.fwmark = (*pskb)->nfmark
+		fl.nl_u.ip4_u.fwmark = (*pskb)->nfmark;
 #endif
-				      } },
-			    .oif = (*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0,
-			    };
-	struct net_device *dev_src = NULL;
-	int err;
-
-	/* accommodate ip_route_output_slow(), which expects the key src to be
-	   0 or a local address; however some non-standard hacks like
-	   ipt_REJECT.c:send_reset() can cause packets with foreign
-           saddr to be appear on the NF_IP_LOCAL_OUT hook -MB */
-	if(fl.fl4_src && !(dev_src = ip_dev_find(fl.fl4_src)))
-		fl.fl4_src = 0;
-
-	if ((err=ip_route_output_key(&rt, &fl)) != 0) {
-		printk("route_me_harder: ip_route_output_key(dst=%u.%u.%u.%u, src=%u.%u.%u.%u, oif=%d, tos=0x%x, fwmark=0x%lx) error %d\n",
-			NIPQUAD(iph->daddr), NIPQUAD(iph->saddr),
-			(*pskb)->sk ? (*pskb)->sk->sk_bound_dev_if : 0,
-			RT_TOS(iph->tos)|RTO_CONN,
-#ifdef CONFIG_IP_ROUTE_FWMARK
-			(*pskb)->nfmark,
-#else
-			0UL,
-#endif
-			err);
-		goto out;
-	}
-
-	/* Drop old route. */
-	dst_release((*pskb)->dst);
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return -1;
 
-	(*pskb)->dst = &rt->u.dst;
+		/* Drop old route. */
+		dst_release((*pskb)->dst);
+		(*pskb)->dst = &rt->u.dst;
+	} else {
+		/* non-local src, find valid iif to satisfy
+		 * rp-filter when calling ip_route_input. */
+		fl.nl_u.ip4_u.daddr = iph->saddr;
+		if (ip_route_output_key(&rt, &fl) != 0)
+			return -1;
+
+		odst = (*pskb)->dst;
+		if (ip_route_input(*pskb, iph->daddr, iph->saddr,
+				   RT_TOS(iph->tos), rt->u.dst.dev) != 0) {
+			dst_release(&rt->u.dst);
+			return -1;
+		}
+		dst_release(&rt->u.dst);
+		dst_release(odst);
+	}
+	
+	if ((*pskb)->dst->error)
+		return -1;
 
 	/* Change in oif may mean change in hh_len. */
-	if (skb_headroom(*pskb) < (*pskb)->dst->dev->hard_header_len) {
+	hh_len = (*pskb)->dst->dev->hard_header_len;
+	if (skb_headroom(*pskb) < hh_len) {
 		struct sk_buff *nskb;
 
-		nskb = skb_realloc_headroom(*pskb,
-					    (*pskb)->dst->dev->hard_header_len);
-		if (!nskb) {
-			err = -ENOMEM;
-			goto out;
-		}
+		nskb = skb_realloc_headroom(*pskb, hh_len);
+		if (!nskb) 
+			return -1;
 		if ((*pskb)->sk)
 			skb_set_owner_w(nskb, (*pskb)->sk);
 		kfree_skb(*pskb);
 		*pskb = nskb;
 	}
 
-out:
-	if (dev_src)
-		dev_put(dev_src);
-
-	return err;
+	return 0;
 }
 
 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
-- 
- Harald Welte <laforge@netfilter.org>             http://www.netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2003-07-25 20:47 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-25 20:52 [PATCH 2.6] netfilter policy routing fixes Harald Welte

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).