netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RFC v2 0/5] netfilter reverse path filter matches
@ 2011-09-12 19:42 Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 1/5] net: ipv4: export fib_table_lookup Florian Westphal
                   ` (5 more replies)
  0 siblings, 6 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev

Version 2 of the ipv4/v6 reverse path filter matches discussed during
nfws 2011.

The ipv4 match (ipt_rpfilter) tries to do exactly what the current
fib_validate_source does.  The main problem with this is that
we need to do an additional fib lookup to get the oif in the match.
[ delaying until FORWARD is invoked is not possible because by
  that point the stack might have already sent icmp errors ].

Patrick McHardy suggested to simply attach the result as the dst, so
ipv4 input path doesn't have to do it again.

This works, but does have a few side effects wrt. route-by-mark and
TPROXY, see patch changelog for details.

The ipv6 version does a pure 'reverse' lookup instead.  This makes
things a lot easier (e.g. when multiple route entries exist), but has
the caveat that a real reply packet might be handled differently due to
policy routing rules.

Userspace part is stored in my iptables repository on
http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/iptables.git (branch 'rpfilter').

Kernel patches are located in the 'xt_rpfilter_5' branch on
http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/nf-next.git
(patches will be sent as followup to this email).

[ in case you are wondering: the earlier xt_rpfilter version was
  removed -- causes too many module  dependency issues and most of the
  code cannot be shared anyway ].

Thanks,
Florian

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [RFC PATCH 1/5] net: ipv4: export fib_table_lookup
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
@ 2011-09-12 19:42 ` Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 2/5] net: ipv4: move ip_rcv route error counter handling into helper function Florian Westphal
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev, Florian Westphal

modules using fib_lookup() fail to link when
CONFIG_IP_MULTIPLE_TABLES is not set.

The reason is that in this case fib_lookup is a static inline
helper that calls fib_table_lookup.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/ipv4/fib_trie.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 58c25ea..e13eb24 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1606,6 +1606,7 @@ found:
 	rcu_read_unlock();
 	return ret;
 }
+EXPORT_SYMBOL_GPL(fib_table_lookup);
 
 /*
  * Remove the leaf and return parent.
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 2/5] net: ipv4: move ip_rcv route error counter handling into helper function
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 1/5] net: ipv4: export fib_table_lookup Florian Westphal
@ 2011-09-12 19:42 ` Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 3/5] netfilter: add ipv4 reverse path filter match Florian Westphal
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev, Florian Westphal

This will avoid code duplication and messing with mib counters
in the planned netfilter reverse path filter match.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/ip.h    |    1 +
 net/ipv4/ip_input.c |   21 ++++++++++++---------
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/include/net/ip.h b/include/net/ip.h
index e9ea7c7..0001633 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -95,6 +95,7 @@ extern int		ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk,
 					      struct ip_options_rcu *opt);
 extern int		ip_rcv(struct sk_buff *skb, struct net_device *dev,
 			       struct packet_type *pt, struct net_device *orig_dev);
+extern void		ip_rcv_inc_route_err_stats(struct net *net, int err);
 extern int		ip_local_deliver(struct sk_buff *skb);
 extern int		ip_mr_input(struct sk_buff *skb);
 extern int		ip_output(struct sk_buff *skb);
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index c8f48ef..43679f4 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -314,6 +314,17 @@ drop:
 	return -1;
 }
 
+void ip_rcv_inc_route_err_stats(struct net *net, int err)
+{
+	if (err == -EHOSTUNREACH)
+		IP_INC_STATS_BH(net, IPSTATS_MIB_INADDRERRORS);
+	else if (err == -ENETUNREACH)
+		IP_INC_STATS_BH(net, IPSTATS_MIB_INNOROUTES);
+	else if (err == -EXDEV)
+		NET_INC_STATS_BH(net, LINUX_MIB_IPRPFILTER);
+}
+EXPORT_SYMBOL_GPL(ip_rcv_inc_route_err_stats);
+
 static int ip_rcv_finish(struct sk_buff *skb)
 {
 	const struct iphdr *iph = ip_hdr(skb);
@@ -327,15 +338,7 @@ static int ip_rcv_finish(struct sk_buff *skb)
 		int err = ip_route_input_noref(skb, iph->daddr, iph->saddr,
 					       iph->tos, skb->dev);
 		if (unlikely(err)) {
-			if (err == -EHOSTUNREACH)
-				IP_INC_STATS_BH(dev_net(skb->dev),
-						IPSTATS_MIB_INADDRERRORS);
-			else if (err == -ENETUNREACH)
-				IP_INC_STATS_BH(dev_net(skb->dev),
-						IPSTATS_MIB_INNOROUTES);
-			else if (err == -EXDEV)
-				NET_INC_STATS_BH(dev_net(skb->dev),
-						 LINUX_MIB_IPRPFILTER);
+			ip_rcv_inc_route_err_stats(dev_net(skb->dev), err);
 			goto drop;
 		}
 	}
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 3/5] netfilter: add ipv4 reverse path filter match
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 1/5] net: ipv4: export fib_table_lookup Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 2/5] net: ipv4: move ip_rcv route error counter handling into helper function Florian Westphal
@ 2011-09-12 19:42 ` Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 4/5] ipv6: add ip6_route_lookup Florian Westphal
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev, Florian Westphal

Tries to mimic behaviour of fib_validate_source.

As fib_validate_source uses the oif as iif when performing reverse
lookup, we would need one additional fib lookup to get oif.

We can't wait until FORWARD chain because by the time FORWARD is invoked
ipv4 forward path may have already sent icmp messages is response
to to-be-discarded-via-rpfilter packets.

To avoid the additional lookup in PREROUTING, Patrick McHardy suggested
to attach the path information directly in the match.

This has a few caveats. Most importantly, when using marks in PREROUTING to
re-route traffic based on the nfmark, -m rpfilter has to be used after the
nfmark has been set; otherwise the nfmark will have no effect (because
the route is already attached to the skb).

Another problem is interaction with -j TPROXY, as this
target sets an nfmark and uses ACCEPT instead of CONTINUE, i.e.
-m rpfilter cannot be used for the initial to-be-intercepted packets.

Also, no result caching so far.

Unlike the current builtin ipv4 rpfilter, packets subject to ipsec
transformation are not automatically excluded; if you want this
combine with policy match.

Packets arriving on loopback interfaces always match.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/linux/netfilter/xt_rpfilter.h |   21 ++++
 net/ipv4/netfilter/Kconfig            |   10 ++
 net/ipv4/netfilter/Makefile           |    1 +
 net/ipv4/netfilter/ipt_rpfilter.c     |  165 +++++++++++++++++++++++++++++++++
 4 files changed, 197 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/netfilter/xt_rpfilter.h
 create mode 100644 net/ipv4/netfilter/ipt_rpfilter.c

diff --git a/include/linux/netfilter/xt_rpfilter.h b/include/linux/netfilter/xt_rpfilter.h
new file mode 100644
index 0000000..8d2d3f8
--- /dev/null
+++ b/include/linux/netfilter/xt_rpfilter.h
@@ -0,0 +1,21 @@
+#ifndef _XT_RPATH_H
+#define _XT_RPATH_H
+
+#include <linux/types.h>
+
+enum {
+	XT_RPFILTER_LOOSE = 1 << 0,
+	XT_RPFILTER_VALID_MARK = 1 << 1,
+	XT_RPFILTER_ACCEPT_LOCAL = 1 << 2,
+#ifdef __KERNEL__
+	XT_RPFILTER_OPTION_MASK = XT_RPFILTER_LOOSE |
+				  XT_RPFILTER_VALID_MARK |
+				  XT_RPFILTER_ACCEPT_LOCAL,
+#endif
+};
+
+struct xt_rpfilter_info {
+	__u8 flags;
+};
+
+#endif
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index 1dfc18a..ef8c1ab 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -82,6 +82,16 @@ config IP_NF_MATCH_ECN
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP_NF_MATCH_RPFILTER
+	tristate '"rpfilter" reverse path filter match support'
+	depends on NETFILTER_ADVANCED
+	---help---
+	  This option allows you to match packets whose replies would
+	  go out via the interface the packet came in.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+	  The module will be called ipt_rpfilter.
+
 config IP_NF_MATCH_TTL
 	tristate '"ttl" match support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index dca2082..123dd88 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
 # matches
 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
 obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o
+obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o
 
 # targets
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c
new file mode 100644
index 0000000..14b5ff5
--- /dev/null
+++ b/net/ipv4/netfilter/ipt_rpfilter.c
@@ -0,0 +1,165 @@
+/*
+ *  Copyright (c) 2011 Florian Westphal <fw@strlen.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ * based on fib_frontend.c; Author: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ip.h>
+#include <net/ip.h>
+#include <net/ip_fib.h>
+#include <net/route.h>
+
+#include <linux/netfilter/xt_rpfilter.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+MODULE_DESCRIPTION("iptables: ipv4 reverse path filter match");
+
+/* don't try to find route from mcast/bcast/zeronet */
+static __be32 rpfilter_get_saddr(__be32 addr)
+{
+	if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) ||
+	    ipv4_is_zeronet(addr))
+		return 0;
+	return addr;
+}
+
+static bool rpfilter_lookup_reverse(struct flowi4 *fl4,
+				const struct net_device *dev, u8 flags)
+{
+	struct fib_result res;
+	bool dev_match;
+	struct net *net = dev_net(dev);
+	int ret __maybe_unused;
+
+	if (fib_lookup(net, fl4, &res))
+		return false;
+
+	if (res.type != RTN_UNICAST) {
+		if (res.type != RTN_LOCAL || !(flags & XT_RPFILTER_ACCEPT_LOCAL))
+			return false;
+	}
+	dev_match = false;
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+	for (ret = 0; ret < res.fi->fib_nhs; ret++) {
+		struct fib_nh *nh = &res.fi->fib_nh[ret];
+
+		if (nh->nh_dev == dev) {
+			dev_match = true;
+			break;
+		}
+	}
+#else
+	if (FIB_RES_DEV(res) == dev)
+		dev_match = true;
+#endif
+	if (dev_match || flags & XT_RPFILTER_LOOSE)
+		return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST;
+	return dev_match;
+}
+
+static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_rpfilter_info *info;
+	const struct iphdr *iph;
+	struct flowi4 flow;
+	struct rtable *rt;
+	int err;
+
+	if (par->in->flags & IFF_LOOPBACK)
+		return true;
+
+	iph = ip_hdr(skb);
+	if (!skb_dst(skb)) {
+		/*
+		 * This match will set skb dst, if it is unset.
+		 * Otherwise, the ipv4 stack would need to perform the same
+		 * lookup again.
+		 */
+		struct sk_buff *pskb;
+		pskb = (struct sk_buff *)skb;
+		err = ip_route_input_noref(pskb, iph->daddr, iph->saddr,
+					iph->tos, skb->dev);
+
+		if (unlikely(err)) {
+			ip_rcv_inc_route_err_stats(dev_net(skb->dev), err);
+			par->hotdrop = true;
+			return false;
+		}
+	}
+
+	info = par->matchinfo;
+	if (ipv4_is_multicast(iph->daddr)) {
+		if (ipv4_is_zeronet(iph->saddr))
+			return ipv4_is_local_multicast(iph->daddr);
+		flow.flowi4_iif = 0;
+		goto validate;
+	}
+
+	rt = skb_rtable(skb);
+	switch (rt->rt_type) {
+	case RTN_BROADCAST:
+		if (ipv4_is_zeronet(iph->saddr))
+			return true;
+		flow.flowi4_iif = 0;
+		break;
+	case RTN_LOCAL:
+		flow.flowi4_iif = dev_net(par->in)->loopback_dev->ifindex;
+		break;
+	default:
+		flow.flowi4_iif = rt->rt_oif;
+		break;
+	}
+
+ validate:
+	flow.daddr = iph->saddr;
+	flow.saddr = rpfilter_get_saddr(iph->daddr);
+	flow.flowi4_oif = 0;
+	flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
+	flow.flowi4_tos = RT_TOS(iph->tos);
+	flow.flowi4_scope = RT_SCOPE_UNIVERSE;
+
+	return rpfilter_lookup_reverse(&flow, par->in, info->flags);
+}
+
+static int rpfilter_check(const struct xt_mtchk_param *par)
+{
+	const struct xt_rpfilter_info *info = par->matchinfo;
+	unsigned int options = ~XT_RPFILTER_OPTION_MASK;
+	if (info->flags & options) {
+		pr_info("unknown options encountered");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct xt_match rpfilter_mt_reg __read_mostly = {
+	.name		= "rpfilter",
+	.family		= NFPROTO_IPV4,
+	.checkentry	= rpfilter_check,
+	.match		= rpfilter_mt,
+	.matchsize	= sizeof(struct xt_rpfilter_info),
+	.hooks		= (1 << NF_INET_PRE_ROUTING),
+	.me		= THIS_MODULE
+};
+
+static int __init rpfilter_mt_init(void)
+{
+	return xt_register_match(&rpfilter_mt_reg);
+}
+
+static void __exit rpfilter_mt_exit(void)
+{
+	xt_unregister_match(&rpfilter_mt_reg);
+}
+
+module_init(rpfilter_mt_init);
+module_exit(rpfilter_mt_exit);
-- 
1.7.3.4

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 4/5] ipv6: add ip6_route_lookup
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
                   ` (2 preceding siblings ...)
  2011-09-12 19:42 ` [RFC PATCH 3/5] netfilter: add ipv4 reverse path filter match Florian Westphal
@ 2011-09-12 19:42 ` Florian Westphal
  2011-09-12 19:42 ` [RFC PATCH 5/5] netfilter: add ipv6 reverse path filter match Florian Westphal
  2011-09-28 21:18 ` [PATCH RFC v2 0/5] netfilter reverse path filter matches Pablo Neira Ayuso
  5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev, Florian Westphal

like rt6_lookup, but allows caller to pass in flowi6 structure.
Will be used by the upcoming ipv6 netfilter reverse path filter
match.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 include/net/ip6_route.h |    2 ++
 net/ipv6/route.c        |    7 +++++++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5e91b72..9c9399c 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -70,6 +70,8 @@ extern void			ip6_route_input(struct sk_buff *skb);
 extern struct dst_entry *	ip6_route_output(struct net *net,
 						 const struct sock *sk,
 						 struct flowi6 *fl6);
+extern struct dst_entry *	ip6_route_lookup(struct net *net,
+						 struct flowi6 *fl6, int flags);
 
 extern int			ip6_route_init(void);
 extern void			ip6_route_cleanup(void);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 216ff31..183722c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -629,6 +629,13 @@ out:
 
 }
 
+struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6,
+				    int flags)
+{
+	return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
+}
+EXPORT_SYMBOL_GPL(ip6_route_lookup);
+
 struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
 			    const struct in6_addr *saddr, int oif, int strict)
 {
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [RFC PATCH 5/5] netfilter: add ipv6 reverse path filter match
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
                   ` (3 preceding siblings ...)
  2011-09-12 19:42 ` [RFC PATCH 4/5] ipv6: add ip6_route_lookup Florian Westphal
@ 2011-09-12 19:42 ` Florian Westphal
  2011-09-28 21:18 ` [PATCH RFC v2 0/5] netfilter reverse path filter matches Pablo Neira Ayuso
  5 siblings, 0 replies; 9+ messages in thread
From: Florian Westphal @ 2011-09-12 19:42 UTC (permalink / raw)
  To: netfilter-devel; +Cc: netdev, Florian Westphal

Differs from the ipv4 version:
The oif is not used as input interface, instead this only
tests if the saddr of the packet is reachable via the
interface the packet arrived on.

This is not merged with the ipv4 match into xt_rpfilter.c
to avoid introduce module dependency issues.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/ipv6/netfilter/Kconfig         |   10 +++
 net/ipv6/netfilter/Makefile        |    1 +
 net/ipv6/netfilter/ip6t_rpfilter.c |  124 ++++++++++++++++++++++++++++++++++++
 3 files changed, 135 insertions(+), 0 deletions(-)
 create mode 100644 net/ipv6/netfilter/ip6t_rpfilter.c

diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4484648..49ec98b 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -125,6 +125,16 @@ config IP6_NF_MATCH_MH
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config IP6_NF_MATCH_RPFILTER
+	tristate '"rpfilter" reverse path filter match support'
+	depends on NETFILTER_ADVANCED
+	---help---
+	  This option allows you to match packets whose replies would
+	  go out via the interface the packet came in.
+
+	  To compile it as a module, choose M here.  If unsure, say N.
+	  The module will be called ip6t_rpfilter.
+
 config IP6_NF_MATCH_RT
 	tristate '"rt" Routing header match support'
 	depends on NETFILTER_ADVANCED
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile
index abfee91..2eaed96 100644
--- a/net/ipv6/netfilter/Makefile
+++ b/net/ipv6/netfilter/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o
 obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o
 obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o
 obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o
+obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
 obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
 
 # targets
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c
new file mode 100644
index 0000000..9fe84e4
--- /dev/null
+++ b/net/ipv6/netfilter/ip6t_rpfilter.c
@@ -0,0 +1,124 @@
+/*
+ *  Copyright (c) 2011 Florian Westphal <fw@strlen.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <net/ip6_fib.h>
+#include <net/ip6_route.h>
+
+#include <linux/netfilter/xt_rpfilter.h>
+#include <linux/netfilter/x_tables.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match");
+
+static bool rpfilter_addr_unicast(const struct in6_addr *addr)
+{
+	int addr_type = ipv6_addr_type(addr);
+	return addr_type & IPV6_ADDR_UNICAST;
+}
+
+static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
+				     const struct net_device *dev, u8 flags)
+{
+	struct rt6_info *rt;
+	struct ipv6hdr *iph = ipv6_hdr(skb);
+	bool ret = false;
+	struct flowi6 fl6 = {
+		.flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK,
+		.flowi6_proto = iph->nexthdr,
+		.daddr = iph->saddr,
+	};
+	int lookup_flags;
+
+	if (rpfilter_addr_unicast(&iph->daddr)) {
+                ipv6_addr_copy(&fl6.saddr, &iph->daddr);
+		lookup_flags = RT6_LOOKUP_F_HAS_SADDR;
+	} else {
+		lookup_flags = 0;
+	}
+
+	fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0;
+	if ((flags & XT_RPFILTER_LOOSE) == 0) {
+		fl6.flowi6_oif = dev->ifindex;
+		lookup_flags |= RT6_LOOKUP_F_IFACE;
+	}
+
+	rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags);
+	if (rt->dst.error)
+		goto out;
+
+	if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST))
+		goto out;
+
+	if (rt->rt6i_flags & RTF_LOCAL) {
+		ret = flags & XT_RPFILTER_ACCEPT_LOCAL;
+		goto out;
+	}
+
+	if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
+		ret = true;
+ out:
+	dst_release(&rt->dst);
+	return ret;
+}
+
+static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par)
+{
+	const struct xt_rpfilter_info *info = par->matchinfo;
+	int saddrtype;
+	struct ipv6hdr *iph;
+
+	if (par->in->flags & IFF_LOOPBACK)
+		return true;
+
+	iph = ipv6_hdr(skb);
+	saddrtype = ipv6_addr_type(&iph->saddr);
+	if (unlikely(saddrtype == IPV6_ADDR_ANY))
+		return true; /* not routable: forward path will drop it */
+
+	return rpfilter_lookup_reverse6(skb, par->in, info->flags);
+}
+
+static int rpfilter_check(const struct xt_mtchk_param *par)
+{
+	const struct xt_rpfilter_info *info = par->matchinfo;
+	unsigned int options = ~XT_RPFILTER_OPTION_MASK;
+
+	if (info->flags & options) {
+		pr_info("unknown options encountered");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct xt_match rpfilter_mt_reg __read_mostly = {
+	.name		= "rpfilter",
+	.family		= NFPROTO_IPV6,
+	.checkentry	= rpfilter_check,
+	.match		= rpfilter_mt,
+	.matchsize	= sizeof(struct xt_rpfilter_info),
+	.hooks		= (1 << NF_INET_PRE_ROUTING),
+	.me		= THIS_MODULE
+};
+
+static int __init rpfilter_mt_init(void)
+{
+	return xt_register_match(&rpfilter_mt_reg);
+}
+
+static void __exit rpfilter_mt_exit(void)
+{
+	xt_unregister_match(&rpfilter_mt_reg);
+}
+
+module_init(rpfilter_mt_init);
+module_exit(rpfilter_mt_exit);
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH RFC v2 0/5] netfilter reverse path filter matches
  2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
                   ` (4 preceding siblings ...)
  2011-09-12 19:42 ` [RFC PATCH 5/5] netfilter: add ipv6 reverse path filter match Florian Westphal
@ 2011-09-28 21:18 ` Pablo Neira Ayuso
  2011-09-28 21:23   ` Florian Westphal
  5 siblings, 1 reply; 9+ messages in thread
From: Pablo Neira Ayuso @ 2011-09-28 21:18 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter-devel, netdev, davem

On Mon, Sep 12, 2011 at 09:42:27PM +0200, Florian Westphal wrote:
> Version 2 of the ipv4/v6 reverse path filter matches discussed during
> nfws 2011.
> 
> The ipv4 match (ipt_rpfilter) tries to do exactly what the current
> fib_validate_source does.  The main problem with this is that
> we need to do an additional fib lookup to get the oif in the match.
> [ delaying until FORWARD is invoked is not possible because by
>   that point the stack might have already sent icmp errors ].
> 
> Patrick McHardy suggested to simply attach the result as the dst, so
> ipv4 input path doesn't have to do it again.
> 
> This works, but does have a few side effects wrt. route-by-mark and
> TPROXY, see patch changelog for details.
> 
> The ipv6 version does a pure 'reverse' lookup instead.  This makes
> things a lot easier (e.g. when multiple route entries exist), but has
> the caveat that a real reply packet might be handled differently due to
> policy routing rules.
> 
> Userspace part is stored in my iptables repository on
> http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/iptables.git (branch 'rpfilter').
> 
> Kernel patches are located in the 'xt_rpfilter_5' branch on
> http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/nf-next.git
> (patches will be sent as followup to this email).
> 
> [ in case you are wondering: the earlier xt_rpfilter version was
>   removed -- causes too many module  dependency issues and most of the
>   code cannot be shared anyway ].

This involves other net changes, I'd like to get an ack from David
before applying this. Or let me know if it's better to follow the
netdev path.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH RFC v2 0/5] netfilter reverse path filter matches
  2011-09-28 21:18 ` [PATCH RFC v2 0/5] netfilter reverse path filter matches Pablo Neira Ayuso
@ 2011-09-28 21:23   ` Florian Westphal
  2011-09-28 22:39     ` David Miller
  0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2011-09-28 21:23 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter-devel, netdev, davem

Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > Kernel patches are located in the 'xt_rpfilter_5' branch on
> > http://git.breakpoint.cc/cgi-bin/gitweb.cgi?p=fw/nf-next.git
> > (patches will be sent as followup to this email).
> > 
> > [ in case you are wondering: the earlier xt_rpfilter version was
> >   removed -- causes too many module  dependency issues and most of the
> >   code cannot be shared anyway ].
> 
> This involves other net changes, I'd like to get an ack from David
> before applying this. Or let me know if it's better to follow the
> netdev path.

Pablo, please do not apply these patches, I have newer versions
available.

David, it would be nice if you could indicate how these patches
should be merged (ie. via net-next or netfilter-next).

[ in case there are objections, I'd like to hear about those too :-) ]

Thanks,
Florian

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH RFC v2 0/5] netfilter reverse path filter matches
  2011-09-28 21:23   ` Florian Westphal
@ 2011-09-28 22:39     ` David Miller
  0 siblings, 0 replies; 9+ messages in thread
From: David Miller @ 2011-09-28 22:39 UTC (permalink / raw)
  To: fw; +Cc: pablo, netfilter-devel, netdev

From: Florian Westphal <fw@strlen.de>
Date: Wed, 28 Sep 2011 23:23:58 +0200

> David, it would be nice if you could indicate how these patches
> should be merged (ie. via net-next or netfilter-next).

I'm fine with them going into netfilter-next, I'll add my ACKs to the
next version you post.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2011-09-28 22:39 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-12 19:42 [PATCH RFC v2 0/5] netfilter reverse path filter matches Florian Westphal
2011-09-12 19:42 ` [RFC PATCH 1/5] net: ipv4: export fib_table_lookup Florian Westphal
2011-09-12 19:42 ` [RFC PATCH 2/5] net: ipv4: move ip_rcv route error counter handling into helper function Florian Westphal
2011-09-12 19:42 ` [RFC PATCH 3/5] netfilter: add ipv4 reverse path filter match Florian Westphal
2011-09-12 19:42 ` [RFC PATCH 4/5] ipv6: add ip6_route_lookup Florian Westphal
2011-09-12 19:42 ` [RFC PATCH 5/5] netfilter: add ipv6 reverse path filter match Florian Westphal
2011-09-28 21:18 ` [PATCH RFC v2 0/5] netfilter reverse path filter matches Pablo Neira Ayuso
2011-09-28 21:23   ` Florian Westphal
2011-09-28 22:39     ` David Miller

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).