[PATCH 3.4 119/125] ipv6: fix handling of blackhole and prohibit routes

2016-10-12 Thread lizf
From: Nicolas Dichtel 

3.4.113-rc1 review patch.  If anyone has any objections, please let me know.

--


commit ef2c7d7b59708d54213c7556a82d14de9a7e4475 upstream.

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

v2: wrong patch
v3: add a field fc_type in struct fib6_config to store RTN_* type

Signed-off-by: Nicolas Dichtel 
Signed-off-by: David S. Miller 
Signed-off-by: Zefan Li 
---
 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 49c4cfe..acaab5e 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 28957ba..794cd2a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1399,8 +1399,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 RTN_BLACKHOLE:
+   rt->dst.error = -EINVAL;
+   break;
+   case RTN_PROHIBIT:
+   rt->dst.error = -EACCES;
+   break;
+   default:
+   rt->dst.error = -ENETUNREACH;
+   break;
+   }
goto install_route;
}
 
@@ -2343,8 +2353,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->fc_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)
@@ -2474,8 +2487,19 @@ static int rt6_fill_node(struct net *net,
table = RT6_TABLE_UNSPEC;
rtm->rtm_table = table;
NLA_PUT_U32(skb, RTA_TABLE, table);
-   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))
-- 
1.9.1



[PATCH 3.4 119/125] ipv6: fix handling of blackhole and prohibit routes

2016-10-12 Thread lizf
From: Nicolas Dichtel 

3.4.113-rc1 review patch.  If anyone has any objections, please let me know.

--


commit ef2c7d7b59708d54213c7556a82d14de9a7e4475 upstream.

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

v2: wrong patch
v3: add a field fc_type in struct fib6_config to store RTN_* type

Signed-off-by: Nicolas Dichtel 
Signed-off-by: David S. Miller 
Signed-off-by: Zefan Li 
---
 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 49c4cfe..acaab5e 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 28957ba..794cd2a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1399,8 +1399,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 RTN_BLACKHOLE:
+   rt->dst.error = -EINVAL;
+   break;
+   case RTN_PROHIBIT:
+   rt->dst.error = -EACCES;
+   break;
+   default:
+   rt->dst.error = -ENETUNREACH;
+   break;
+   }
goto install_route;
}
 
@@ -2343,8 +2353,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->fc_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)
@@ -2474,8 +2487,19 @@ static int rt6_fill_node(struct net *net,
table = RT6_TABLE_UNSPEC;
rtm->rtm_table = table;
NLA_PUT_U32(skb, RTA_TABLE, table);
-   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))
-- 
1.9.1