diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 79 |
1 files changed, 42 insertions, 37 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index d6ff12617f36..cd3fb301da38 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1499,6 +1499,33 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1499 | return false; | 1499 | return false; |
1500 | } | 1500 | } |
1501 | 1501 | ||
1502 | /* Compares an address/prefix_len with addresses on device @dev. | ||
1503 | * If one is found it returns true. | ||
1504 | */ | ||
1505 | bool ipv6_chk_custom_prefix(const struct in6_addr *addr, | ||
1506 | const unsigned int prefix_len, struct net_device *dev) | ||
1507 | { | ||
1508 | struct inet6_dev *idev; | ||
1509 | struct inet6_ifaddr *ifa; | ||
1510 | bool ret = false; | ||
1511 | |||
1512 | rcu_read_lock(); | ||
1513 | idev = __in6_dev_get(dev); | ||
1514 | if (idev) { | ||
1515 | read_lock_bh(&idev->lock); | ||
1516 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
1517 | ret = ipv6_prefix_equal(addr, &ifa->addr, prefix_len); | ||
1518 | if (ret) | ||
1519 | break; | ||
1520 | } | ||
1521 | read_unlock_bh(&idev->lock); | ||
1522 | } | ||
1523 | rcu_read_unlock(); | ||
1524 | |||
1525 | return ret; | ||
1526 | } | ||
1527 | EXPORT_SYMBOL(ipv6_chk_custom_prefix); | ||
1528 | |||
1502 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) | 1529 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) |
1503 | { | 1530 | { |
1504 | struct inet6_dev *idev; | 1531 | struct inet6_dev *idev; |
@@ -2193,43 +2220,21 @@ ok: | |||
2193 | else | 2220 | else |
2194 | stored_lft = 0; | 2221 | stored_lft = 0; |
2195 | if (!update_lft && !create && stored_lft) { | 2222 | if (!update_lft && !create && stored_lft) { |
2196 | if (valid_lft > MIN_VALID_LIFETIME || | 2223 | const u32 minimum_lft = min( |
2197 | valid_lft > stored_lft) | 2224 | stored_lft, (u32)MIN_VALID_LIFETIME); |
2198 | update_lft = 1; | 2225 | valid_lft = max(valid_lft, minimum_lft); |
2199 | else if (stored_lft <= MIN_VALID_LIFETIME) { | 2226 | |
2200 | /* valid_lft <= stored_lft is always true */ | 2227 | /* RFC4862 Section 5.5.3e: |
2201 | /* | 2228 | * "Note that the preferred lifetime of the |
2202 | * RFC 4862 Section 5.5.3e: | 2229 | * corresponding address is always reset to |
2203 | * "Note that the preferred lifetime of | 2230 | * the Preferred Lifetime in the received |
2204 | * the corresponding address is always | 2231 | * Prefix Information option, regardless of |
2205 | * reset to the Preferred Lifetime in | 2232 | * whether the valid lifetime is also reset or |
2206 | * the received Prefix Information | 2233 | * ignored." |
2207 | * option, regardless of whether the | 2234 | * |
2208 | * valid lifetime is also reset or | 2235 | * So we should always update prefered_lft here. |
2209 | * ignored." | 2236 | */ |
2210 | * | 2237 | update_lft = 1; |
2211 | * So if the preferred lifetime in | ||
2212 | * this advertisement is different | ||
2213 | * than what we have stored, but the | ||
2214 | * valid lifetime is invalid, just | ||
2215 | * reset prefered_lft. | ||
2216 | * | ||
2217 | * We must set the valid lifetime | ||
2218 | * to the stored lifetime since we'll | ||
2219 | * be updating the timestamp below, | ||
2220 | * else we'll set it back to the | ||
2221 | * minimum. | ||
2222 | */ | ||
2223 | if (prefered_lft != ifp->prefered_lft) { | ||
2224 | valid_lft = stored_lft; | ||
2225 | update_lft = 1; | ||
2226 | } | ||
2227 | } else { | ||
2228 | valid_lft = MIN_VALID_LIFETIME; | ||
2229 | if (valid_lft < prefered_lft) | ||
2230 | prefered_lft = valid_lft; | ||
2231 | update_lft = 1; | ||
2232 | } | ||
2233 | } | 2238 | } |
2234 | 2239 | ||
2235 | if (update_lft) { | 2240 | if (update_lft) { |