diff options
| -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); |
