diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e39239e6426e..d0611a5de45f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1713,6 +1713,40 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
1713 | ip6_route_add(&cfg); | 1713 | ip6_route_add(&cfg); |
1714 | } | 1714 | } |
1715 | 1715 | ||
1716 | |||
1717 | static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | ||
1718 | int plen, | ||
1719 | const struct net_device *dev, | ||
1720 | u32 flags, u32 noflags) | ||
1721 | { | ||
1722 | struct fib6_node *fn; | ||
1723 | struct rt6_info *rt = NULL; | ||
1724 | struct fib6_table *table; | ||
1725 | |||
1726 | table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX); | ||
1727 | if (table == NULL) | ||
1728 | return NULL; | ||
1729 | |||
1730 | write_lock_bh(&table->tb6_lock); | ||
1731 | fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0); | ||
1732 | if (!fn) | ||
1733 | goto out; | ||
1734 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | ||
1735 | if (rt->rt6i_dev->ifindex != dev->ifindex) | ||
1736 | continue; | ||
1737 | if ((rt->rt6i_flags & flags) != flags) | ||
1738 | continue; | ||
1739 | if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) | ||
1740 | continue; | ||
1741 | dst_hold(&rt->dst); | ||
1742 | break; | ||
1743 | } | ||
1744 | out: | ||
1745 | write_unlock_bh(&table->tb6_lock); | ||
1746 | return rt; | ||
1747 | } | ||
1748 | |||
1749 | |||
1716 | /* Create "default" multicast route to the interface */ | 1750 | /* Create "default" multicast route to the interface */ |
1717 | 1751 | ||
1718 | static void addrconf_add_mroute(struct net_device *dev) | 1752 | static void addrconf_add_mroute(struct net_device *dev) |
@@ -1842,10 +1876,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1842 | if (addrconf_finite_timeout(rt_expires)) | 1876 | if (addrconf_finite_timeout(rt_expires)) |
1843 | rt_expires *= HZ; | 1877 | rt_expires *= HZ; |
1844 | 1878 | ||
1845 | rt = rt6_lookup(net, &pinfo->prefix, NULL, | 1879 | rt = addrconf_get_prefix_route(&pinfo->prefix, |
1846 | dev->ifindex, 1); | 1880 | pinfo->prefix_len, |
1881 | dev, | ||
1882 | RTF_ADDRCONF | RTF_PREFIX_RT, | ||
1883 | RTF_GATEWAY | RTF_DEFAULT); | ||
1847 | 1884 | ||
1848 | if (rt && addrconf_is_prefix_route(rt)) { | 1885 | if (rt) { |
1849 | /* Autoconf prefix route */ | 1886 | /* Autoconf prefix route */ |
1850 | if (valid_lft == 0) { | 1887 | if (valid_lft == 0) { |
1851 | ip6_del_rt(rt); | 1888 | ip6_del_rt(rt); |