Skip to content

Commit

Permalink
ipv6: fix route lookup in addrconf_prefix_rcv()
Browse files Browse the repository at this point in the history
The route lookup to find a previously auto-configured route for a prefixes used
to use rt6_lookup(), with the prefix from the RA used as an address. However,
that kind of lookup ignores routing tables, the prefix length and route flags,
so when there were other matching routes, even in different tables and/or with
a different prefix length, the wrong route would be manipulated.

Now, a new function "addrconf_get_prefix_route()" is used for the route lookup,
which searches in RT6_TABLE_PREFIX and takes the prefix-length and route flags
into account.

Signed-off-by: Andreas Hofmeister <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
andihofmeister authored and davem330 committed Oct 30, 2011
1 parent e6d265e commit 14ef37b
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions net/ipv6/addrconf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1713,6 +1713,40 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
ip6_route_add(&cfg);
}


static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
int plen,
const struct net_device *dev,
u32 flags, u32 noflags)
{
struct fib6_node *fn;
struct rt6_info *rt = NULL;
struct fib6_table *table;

table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX);
if (table == NULL)
return NULL;

write_lock_bh(&table->tb6_lock);
fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0);
if (!fn)
goto out;
for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
if (rt->rt6i_dev->ifindex != dev->ifindex)
continue;
if ((rt->rt6i_flags & flags) != flags)
continue;
if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0))
continue;
dst_hold(&rt->dst);
break;
}
out:
write_unlock_bh(&table->tb6_lock);
return rt;
}


/* Create "default" multicast route to the interface */

static void addrconf_add_mroute(struct net_device *dev)
Expand Down Expand Up @@ -1842,10 +1876,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len)
if (addrconf_finite_timeout(rt_expires))
rt_expires *= HZ;

rt = rt6_lookup(net, &pinfo->prefix, NULL,
dev->ifindex, 1);
rt = addrconf_get_prefix_route(&pinfo->prefix,
pinfo->prefix_len,
dev,
RTF_ADDRCONF | RTF_PREFIX_RT,
RTF_GATEWAY | RTF_DEFAULT);

if (rt && addrconf_is_prefix_route(rt)) {
if (rt) {
/* Autoconf prefix route */
if (valid_lft == 0) {
ip6_del_rt(rt);
Expand Down

0 comments on commit 14ef37b

Please sign in to comment.