[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 6 Jun 2011 13:34:34 +0200
From: Eric Leblond <eric@...it.org>
To: netdev@...r.kernel.org
Cc: Eric Leblond <eric@...it.org>
Subject: [RFC PATCH] ipv6: basic implementation of reverse path filtering
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@...it.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
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists