diff mbox

[RFC,v2] ipv6: fix handling of blackhole and prohibit routes

Message ID 1346844858-3210-1-git-send-email-nicolas.dichtel@6wind.com
State Superseded, archived
Delegated to: David Miller
Headers show

Commit Message

Nicolas Dichtel Sept. 5, 2012, 11:34 a.m. UTC
When adding a blackhole or a prohibit route, they were handling like classic
routes. Moreover, it was only possible to add this kind of routes by specifying
an interface.

Bug already reported here:
  http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=498498

Before the patch:
  $ ip route add blackhole 2001::1/128
  RTNETLINK answers: No such device
  $ ip route add blackhole 2001::1/128 dev eth0
  $ ip -6 route | grep 2001
  2001::1 dev eth0  metric 1024

After:
  $ ip route add blackhole 2001::1/128
  $ ip -6 route | grep 2001
  blackhole 2001::1 dev lo  metric 1024  error -22

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/net/ip6_fib.h |  1 +
 net/ipv6/route.c      | 32 ++++++++++++++++++++++++++++----
 2 files changed, 29 insertions(+), 4 deletions(-)

Comments

Nicolas Dichtel Sept. 5, 2012, 10:03 a.m. UTC | #1
Please, forget this patch, it's a wrong version.
Sorry for that.


Regards,
Nicolas

Le 05/09/2012 13:34, Nicolas Dichtel a écrit :
> When adding a blackhole or a prohibit route, they were handling like classic
> routes. Moreover, it was only possible to add this kind of routes by specifying
> an interface.
>
> Bug already reported here:
>    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=498498
>
> Before the patch:
>    $ ip route add blackhole 2001::1/128
>    RTNETLINK answers: No such device
>    $ ip route add blackhole 2001::1/128 dev eth0
>    $ ip -6 route | grep 2001
>    2001::1 dev eth0  metric 1024
>
> After:
>    $ ip route add blackhole 2001::1/128
>    $ ip -6 route | grep 2001
>    blackhole 2001::1 dev lo  metric 1024  error -22
>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
>   include/net/ip6_fib.h |  1 +
>   net/ipv6/route.c      | 32 ++++++++++++++++++++++++++++----
>   2 files changed, 29 insertions(+), 4 deletions(-)
>
> diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
> index 0fedbd8..cd64cf3 100644
> --- a/include/net/ip6_fib.h
> +++ b/include/net/ip6_fib.h
> @@ -37,6 +37,7 @@ struct fib6_config {
>   	int		fc_ifindex;
>   	u32		fc_flags;
>   	u32		fc_protocol;
> +	u32		fc_type;	/* only 8 bits are used */
>
>   	struct in6_addr	fc_dst;
>   	struct in6_addr	fc_src;
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 8e80fd2..5642fb5 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1463,8 +1463,18 @@ int ip6_route_add(struct fib6_config *cfg)
>   		}
>   		rt->dst.output = ip6_pkt_discard_out;
>   		rt->dst.input = ip6_pkt_discard;
> -		rt->dst.error = -ENETUNREACH;
>   		rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
> +		switch (cfg->fc_type) {
> +		case RTM_BLACKHOLE:
> +			rt->dst.error = -EINVAL;
> +			break;
> +		case RTM_PROHIBIT:
> +			rt->dst.error = -EACCES;
> +			break;
> +		default:
> +			rt->dst.error = -ENETUNREACH;
> +			break;
> +		}
>   		goto install_route;
>   	}
>
> @@ -2261,8 +2271,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
>   	cfg->fc_src_len = rtm->rtm_src_len;
>   	cfg->fc_flags = RTF_UP;
>   	cfg->fc_protocol = rtm->rtm_protocol;
> +	cfg->type = rtm->rtm_type;
>
> -	if (rtm->rtm_type == RTN_UNREACHABLE)
> +	if (rtm->rtm_type == RTN_UNREACHABLE ||
> +	    rtm->rtm_type == RTN_BLACKHOLE ||
> +	    rtm->rtm_type == RTN_PROHIBIT)
>   		cfg->fc_flags |= RTF_REJECT;
>
>   	if (rtm->rtm_type == RTN_LOCAL)
> @@ -2391,8 +2404,19 @@ static int rt6_fill_node(struct net *net,
>   	rtm->rtm_table = table;
>   	if (nla_put_u32(skb, RTA_TABLE, table))
>   		goto nla_put_failure;
> -	if (rt->rt6i_flags & RTF_REJECT)
> -		rtm->rtm_type = RTN_UNREACHABLE;
> +	if (rt->rt6i_flags & RTF_REJECT) {
> +		switch (rt->dst.error) {
> +		case -EINVAL:
> +			rtm->rtm_type = RTN_BLACKHOLE;
> +			break;
> +		case -EACCES:
> +			rtm->rtm_type = RTN_PROHIBIT;
> +			break;
> +		default:
> +			rtm->rtm_type = RTN_UNREACHABLE;
> +			break;
> +		}
> +	}
>   	else if (rt->rt6i_flags & RTF_LOCAL)
>   		rtm->rtm_type = RTN_LOCAL;
>   	else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
>
diff mbox

Patch

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 0fedbd8..cd64cf3 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -37,6 +37,7 @@  struct fib6_config {
 	int		fc_ifindex;
 	u32		fc_flags;
 	u32		fc_protocol;
+	u32		fc_type;	/* only 8 bits are used */
 
 	struct in6_addr	fc_dst;
 	struct in6_addr	fc_src;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8e80fd2..5642fb5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1463,8 +1463,18 @@  int ip6_route_add(struct fib6_config *cfg)
 		}
 		rt->dst.output = ip6_pkt_discard_out;
 		rt->dst.input = ip6_pkt_discard;
-		rt->dst.error = -ENETUNREACH;
 		rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
+		switch (cfg->fc_type) {
+		case RTM_BLACKHOLE:
+			rt->dst.error = -EINVAL;
+			break;
+		case RTM_PROHIBIT:
+			rt->dst.error = -EACCES;
+			break;
+		default:
+			rt->dst.error = -ENETUNREACH;
+			break;
+		}
 		goto install_route;
 	}
 
@@ -2261,8 +2271,11 @@  static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 	cfg->fc_src_len = rtm->rtm_src_len;
 	cfg->fc_flags = RTF_UP;
 	cfg->fc_protocol = rtm->rtm_protocol;
+	cfg->type = rtm->rtm_type;
 
-	if (rtm->rtm_type == RTN_UNREACHABLE)
+	if (rtm->rtm_type == RTN_UNREACHABLE ||
+	    rtm->rtm_type == RTN_BLACKHOLE ||
+	    rtm->rtm_type == RTN_PROHIBIT)
 		cfg->fc_flags |= RTF_REJECT;
 
 	if (rtm->rtm_type == RTN_LOCAL)
@@ -2391,8 +2404,19 @@  static int rt6_fill_node(struct net *net,
 	rtm->rtm_table = table;
 	if (nla_put_u32(skb, RTA_TABLE, table))
 		goto nla_put_failure;
-	if (rt->rt6i_flags & RTF_REJECT)
-		rtm->rtm_type = RTN_UNREACHABLE;
+	if (rt->rt6i_flags & RTF_REJECT) {
+		switch (rt->dst.error) {
+		case -EINVAL:
+			rtm->rtm_type = RTN_BLACKHOLE;
+			break;
+		case -EACCES:
+			rtm->rtm_type = RTN_PROHIBIT;
+			break;
+		default:
+			rtm->rtm_type = RTN_UNREACHABLE;
+			break;
+		}
+	}
 	else if (rt->rt6i_flags & RTF_LOCAL)
 		rtm->rtm_type = RTN_LOCAL;
 	else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))