From: Eric Leblond <eric@regit.org>
To: netdev@vger.kernel.org
Cc: Eric Leblond <eric@regit.org>
Subject: [RFC PATCH] ipv6: basic implementation of reverse path filtering
Date: Mon, 6 Jun 2011 13:34:34 +0200 [thread overview]
Message-ID: <1307360074-25473-1-git-send-email-eric@regit.org> (raw)
This patch provides a basic implementation of reverse path filtering
for IPv6. Functionnality can be activatedor desactivated through an
rp_filter entry similar to the IPv4 one.
The functionnality is disabled by default for backward compatibility
but should be enable on all IPv6 routers/firewalls for security reason.
This implementation is heavily based on the patch Denis Semmau proposed
in 2006.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/linux/ipv6.h | 2 ++
include/linux/sysctl.h | 1 +
net/ipv6/addrconf.c | 10 ++++++++++
net/ipv6/ip6_output.c | 32 ++++++++++++++++++++++++++++++++
4 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 0c99776..e61b88d 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -134,6 +134,7 @@ struct ipv6hdr {
*/
struct ipv6_devconf {
__s32 forwarding;
+ __s32 rp_filter;
__s32 hop_limit;
__s32 mtu6;
__s32 accept_ra;
@@ -213,6 +214,7 @@ enum {
DEVCONF_DISABLE_IPV6,
DEVCONF_ACCEPT_DAD,
DEVCONF_FORCE_TLLAO,
+ DEVCONF_RP_FILTER,
DEVCONF_MAX
};
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 11684d9..bdcb7f8 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -568,6 +568,7 @@ enum {
NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN=22,
NET_IPV6_PROXY_NDP=23,
NET_IPV6_ACCEPT_SOURCE_ROUTE=25,
+ NET_IPV6_RP_FILTER=26,
__NET_IPV6_MAX
};
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 498b927..ba1c574 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -196,6 +196,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
.accept_source_route = 0, /* we do not accept RH0 by default. */
.disable_ipv6 = 0,
.accept_dad = 1,
+ .rp_filter = 0,
};
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -230,6 +231,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
.accept_source_route = 0, /* we do not accept RH0 by default. */
.disable_ipv6 = 0,
.accept_dad = 1,
+ .rp_filter = 0,
};
/* IPv6 Wildcard Address and Loopback Address defined by RFC2553 */
@@ -3805,6 +3807,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
+ array[DEVCONF_RP_FILTER] = cnf->rp_filter;
}
static inline size_t inet6_ifla6_size(void)
@@ -4459,6 +4462,13 @@ static struct addrconf_sysctl_table
.proc_handler = proc_dointvec
},
{
+ .procname = "rp_filter",
+ .data = &ipv6_devconf.rp_filter,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
+ {
/* sentinel */
}
},
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 9d4b165..c035494 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -374,6 +374,18 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
return 0;
}
+static int rt6_validate_source(struct sk_buff *skb)
+{
+ struct rt6_info *rt;
+ struct ipv6hdr *hdr = ipv6_hdr(skb);
+ rt = rt6_lookup(dev_net(skb->dev), &hdr->saddr, NULL, 0, 0);
+ if (rt != NULL) {
+ if (rt->rt6i_idev->dev == skb->dev)
+ return 0;
+ }
+ return -1;
+}
+
static inline int ip6_forward_finish(struct sk_buff *skb)
{
return dst_output(skb);
@@ -384,6 +396,7 @@ int ip6_forward(struct sk_buff *skb)
struct dst_entry *dst = skb_dst(skb);
struct ipv6hdr *hdr = ipv6_hdr(skb);
struct inet6_skb_parm *opt = IP6CB(skb);
+ struct inet6_dev *idev = NULL;
struct net *net = dev_net(dst->dev);
u32 mtu;
@@ -401,6 +414,25 @@ int ip6_forward(struct sk_buff *skb)
if (skb->pkt_type != PACKET_HOST)
goto drop;
+ idev = in6_dev_get(skb->dev);
+ if (!idev) {
+ printk(KERN_WARNING "idev error for rp_filter\n");
+ goto error;
+ }
+
+ if (net->ipv6.devconf_all->rp_filter & idev->cnf.rp_filter) {
+ if (rt6_validate_source(skb) < 0) {
+ printk(KERN_WARNING
+ "rp_filter: packet refused on %s, invalid src %pI6 (dst: %pI6)",
+ skb->dev->name,
+ &hdr->saddr,
+ &hdr->daddr
+ );
+ goto drop;
+ }
+
+ }
+
skb_forward_csum(skb);
/*
--
1.7.5.3
next reply other threads:[~2011-06-06 11:58 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-06 11:34 Eric Leblond [this message]
2011-06-06 12:22 ` [RFC PATCH] ipv6: basic implementation of reverse path filtering Eric Dumazet
2011-06-06 17:53 ` [RFC PATCHv2] ipv6: " Eric Leblond
2011-06-06 18:18 ` Eric Dumazet
2011-06-06 19:29 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1307360074-25473-1-git-send-email-eric@regit.org \
--to=eric@regit.org \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).