mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
ipv6: fix handling of blackhole and prohibit routes
commit ef2c7d7b59
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 <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Zefan Li <lizefan@huawei.com>
This commit is contained in:
parent
a4ea6252cc
commit
af706acbb5
2 changed files with 29 additions and 4 deletions
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in a new issue