Commit e843b9e1 authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki Committed by David S. Miller

[IPV6]: ROUTE: Ensure to accept redirects from nexthop for the target.

It is possible to get redirects from nexthop of "more-specific"
routes.
Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 09c884d4
...@@ -1144,59 +1144,63 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r ...@@ -1144,59 +1144,63 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r
void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr,
struct neighbour *neigh, u8 *lladdr, int on_link) struct neighbour *neigh, u8 *lladdr, int on_link)
{ {
struct rt6_info *rt, *nrt; struct rt6_info *rt, *nrt = NULL;
int strict;
/* Locate old route to this destination. */ struct fib6_node *fn;
rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1);
if (rt == NULL)
return;
if (neigh->dev != rt->rt6i_dev)
goto out;
/* /*
* Current route is on-link; redirect is always invalid. * Get the "current" route for this destination and
* * check if the redirect has come from approriate router.
* Seems, previous statement is not true. It could *
* be node, which looks for us as on-link (f.e. proxy ndisc) * RFC 2461 specifies that redirects should only be
* But then router serving it might decide, that we should * accepted if they come from the nexthop to the target.
* know truth 8)8) --ANK (980726). * Due to the way the routes are chosen, this notion
* is a bit fuzzy and one might need to check all possible
* routes.
*/ */
if (!(rt->rt6i_flags&RTF_GATEWAY)) strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL);
goto out;
/* read_lock_bh(&rt6_lock);
* RFC 2461 specifies that redirects should only be fn = fib6_lookup(&ip6_routing_table, dest, NULL);
* accepted if they come from the nexthop to the target. restart:
* Due to the way default routers are chosen, this notion for (rt = fn->leaf; rt; rt = rt->u.next) {
* is a bit fuzzy and one might need to check all default /*
* routers. * Current route is on-link; redirect is always invalid.
*/ *
if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) { * Seems, previous statement is not true. It could
if (rt->rt6i_flags & RTF_DEFAULT) { * be node, which looks for us as on-link (f.e. proxy ndisc)
struct rt6_info *rt1; * But then router serving it might decide, that we should
* know truth 8)8) --ANK (980726).
read_lock(&rt6_lock); */
for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) { if (rt6_check_expired(rt))
if (ipv6_addr_equal(saddr, &rt1->rt6i_gateway)) { continue;
dst_hold(&rt1->u.dst); if (!(rt->rt6i_flags & RTF_GATEWAY))
dst_release(&rt->u.dst); continue;
read_unlock(&rt6_lock); if (neigh->dev != rt->rt6i_dev)
rt = rt1; continue;
goto source_ok; if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway))
} continue;
} break;
read_unlock(&rt6_lock); }
if (rt)
dst_hold(&rt->u.dst);
else if (strict) {
while ((fn = fn->parent) != NULL) {
if (fn->fn_flags & RTN_ROOT)
break;
if (fn->fn_flags & RTN_RTINFO)
goto restart;
} }
}
read_unlock_bh(&rt6_lock);
if (!rt) {
if (net_ratelimit()) if (net_ratelimit())
printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop "
"for redirect target\n"); "for redirect target\n");
goto out; return;
} }
source_ok:
/* /*
* We have finally decided to accept it. * We have finally decided to accept it.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment