aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c273
1 files changed, 178 insertions, 95 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 12c97d8aa6bb..9418ca375132 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -442,6 +442,8 @@ static int inet6_netconf_msgsize_devconf(int type)
442 if (type == -1 || type == NETCONFA_MC_FORWARDING) 442 if (type == -1 || type == NETCONFA_MC_FORWARDING)
443 size += nla_total_size(4); 443 size += nla_total_size(4);
444#endif 444#endif
445 if (type == -1 || type == NETCONFA_PROXY_NEIGH)
446 size += nla_total_size(4);
445 447
446 return size; 448 return size;
447} 449}
@@ -475,6 +477,10 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
475 devconf->mc_forwarding) < 0) 477 devconf->mc_forwarding) < 0)
476 goto nla_put_failure; 478 goto nla_put_failure;
477#endif 479#endif
480 if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
481 nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
482 goto nla_put_failure;
483
478 return nlmsg_end(skb, nlh); 484 return nlmsg_end(skb, nlh);
479 485
480nla_put_failure: 486nla_put_failure:
@@ -509,6 +515,7 @@ errout:
509static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { 515static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
510 [NETCONFA_IFINDEX] = { .len = sizeof(int) }, 516 [NETCONFA_IFINDEX] = { .len = sizeof(int) },
511 [NETCONFA_FORWARDING] = { .len = sizeof(int) }, 517 [NETCONFA_FORWARDING] = { .len = sizeof(int) },
518 [NETCONFA_PROXY_NEIGH] = { .len = sizeof(int) },
512}; 519};
513 520
514static int inet6_netconf_get_devconf(struct sk_buff *in_skb, 521static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
@@ -834,6 +841,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
834 goto out; 841 goto out;
835 } 842 }
836 843
844 neigh_parms_data_state_setall(idev->nd_parms);
845
837 ifa->addr = *addr; 846 ifa->addr = *addr;
838 if (peer_addr) 847 if (peer_addr)
839 ifa->peer_addr = *peer_addr; 848 ifa->peer_addr = *peer_addr;
@@ -986,12 +995,9 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
986 * --yoshfuji 995 * --yoshfuji
987 */ 996 */
988 if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) { 997 if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
989 struct in6_addr prefix;
990 struct rt6_info *rt; 998 struct rt6_info *rt;
991 999
992 ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); 1000 rt = addrconf_get_prefix_route(&ifp->addr,
993
994 rt = addrconf_get_prefix_route(&prefix,
995 ifp->prefix_len, 1001 ifp->prefix_len,
996 ifp->idev->dev, 1002 ifp->idev->dev,
997 0, RTF_GATEWAY | RTF_DEFAULT); 1003 0, RTF_GATEWAY | RTF_DEFAULT);
@@ -1024,7 +1030,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
1024 u32 addr_flags; 1030 u32 addr_flags;
1025 unsigned long now = jiffies; 1031 unsigned long now = jiffies;
1026 1032
1027 write_lock(&idev->lock); 1033 write_lock_bh(&idev->lock);
1028 if (ift) { 1034 if (ift) {
1029 spin_lock_bh(&ift->lock); 1035 spin_lock_bh(&ift->lock);
1030 memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8); 1036 memcpy(&addr.s6_addr[8], &ift->addr.s6_addr[8], 8);
@@ -1036,7 +1042,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i
1036retry: 1042retry:
1037 in6_dev_hold(idev); 1043 in6_dev_hold(idev);
1038 if (idev->cnf.use_tempaddr <= 0) { 1044 if (idev->cnf.use_tempaddr <= 0) {
1039 write_unlock(&idev->lock); 1045 write_unlock_bh(&idev->lock);
1040 pr_info("%s: use_tempaddr is disabled\n", __func__); 1046 pr_info("%s: use_tempaddr is disabled\n", __func__);
1041 in6_dev_put(idev); 1047 in6_dev_put(idev);
1042 ret = -1; 1048 ret = -1;
@@ -1046,7 +1052,7 @@ retry:
1046 if (ifp->regen_count++ >= idev->cnf.regen_max_retry) { 1052 if (ifp->regen_count++ >= idev->cnf.regen_max_retry) {
1047 idev->cnf.use_tempaddr = -1; /*XXX*/ 1053 idev->cnf.use_tempaddr = -1; /*XXX*/
1048 spin_unlock_bh(&ifp->lock); 1054 spin_unlock_bh(&ifp->lock);
1049 write_unlock(&idev->lock); 1055 write_unlock_bh(&idev->lock);
1050 pr_warn("%s: regeneration time exceeded - disabled temporary address support\n", 1056 pr_warn("%s: regeneration time exceeded - disabled temporary address support\n",
1051 __func__); 1057 __func__);
1052 in6_dev_put(idev); 1058 in6_dev_put(idev);
@@ -1071,8 +1077,8 @@ retry:
1071 1077
1072 regen_advance = idev->cnf.regen_max_retry * 1078 regen_advance = idev->cnf.regen_max_retry *
1073 idev->cnf.dad_transmits * 1079 idev->cnf.dad_transmits *
1074 idev->nd_parms->retrans_time / HZ; 1080 NEIGH_VAR(idev->nd_parms, RETRANS_TIME) / HZ;
1075 write_unlock(&idev->lock); 1081 write_unlock_bh(&idev->lock);
1076 1082
1077 /* A temporary address is created only if this calculated Preferred 1083 /* A temporary address is created only if this calculated Preferred
1078 * Lifetime is greater than REGEN_ADVANCE time units. In particular, 1084 * Lifetime is greater than REGEN_ADVANCE time units. In particular,
@@ -1099,7 +1105,7 @@ retry:
1099 in6_dev_put(idev); 1105 in6_dev_put(idev);
1100 pr_info("%s: retry temporary address regeneration\n", __func__); 1106 pr_info("%s: retry temporary address regeneration\n", __func__);
1101 tmpaddr = &addr; 1107 tmpaddr = &addr;
1102 write_lock(&idev->lock); 1108 write_lock_bh(&idev->lock);
1103 goto retry; 1109 goto retry;
1104 } 1110 }
1105 1111
@@ -1407,7 +1413,7 @@ try_nextdev:
1407EXPORT_SYMBOL(ipv6_dev_get_saddr); 1413EXPORT_SYMBOL(ipv6_dev_get_saddr);
1408 1414
1409int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, 1415int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
1410 unsigned char banned_flags) 1416 u32 banned_flags)
1411{ 1417{
1412 struct inet6_ifaddr *ifp; 1418 struct inet6_ifaddr *ifp;
1413 int err = -EADDRNOTAVAIL; 1419 int err = -EADDRNOTAVAIL;
@@ -1424,7 +1430,7 @@ int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr,
1424} 1430}
1425 1431
1426int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, 1432int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
1427 unsigned char banned_flags) 1433 u32 banned_flags)
1428{ 1434{
1429 struct inet6_dev *idev; 1435 struct inet6_dev *idev;
1430 int err = -EADDRNOTAVAIL; 1436 int err = -EADDRNOTAVAIL;
@@ -1888,7 +1894,8 @@ static void ipv6_regen_rndid(unsigned long data)
1888 1894
1889 expires = jiffies + 1895 expires = jiffies +
1890 idev->cnf.temp_prefered_lft * HZ - 1896 idev->cnf.temp_prefered_lft * HZ -
1891 idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - 1897 idev->cnf.regen_max_retry * idev->cnf.dad_transmits *
1898 NEIGH_VAR(idev->nd_parms, RETRANS_TIME) -
1892 idev->cnf.max_desync_factor * HZ; 1899 idev->cnf.max_desync_factor * HZ;
1893 if (time_before(expires, jiffies)) { 1900 if (time_before(expires, jiffies)) {
1894 pr_warn("%s: too short regeneration interval; timer disabled for %s\n", 1901 pr_warn("%s: too short regeneration interval; timer disabled for %s\n",
@@ -2016,6 +2023,73 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev)
2016 return idev; 2023 return idev;
2017} 2024}
2018 2025
2026static void manage_tempaddrs(struct inet6_dev *idev,
2027 struct inet6_ifaddr *ifp,
2028 __u32 valid_lft, __u32 prefered_lft,
2029 bool create, unsigned long now)
2030{
2031 u32 flags;
2032 struct inet6_ifaddr *ift;
2033
2034 read_lock_bh(&idev->lock);
2035 /* update all temporary addresses in the list */
2036 list_for_each_entry(ift, &idev->tempaddr_list, tmp_list) {
2037 int age, max_valid, max_prefered;
2038
2039 if (ifp != ift->ifpub)
2040 continue;
2041
2042 /* RFC 4941 section 3.3:
2043 * If a received option will extend the lifetime of a public
2044 * address, the lifetimes of temporary addresses should
2045 * be extended, subject to the overall constraint that no
2046 * temporary addresses should ever remain "valid" or "preferred"
2047 * for a time longer than (TEMP_VALID_LIFETIME) or
2048 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), respectively.
2049 */
2050 age = (now - ift->cstamp) / HZ;
2051 max_valid = idev->cnf.temp_valid_lft - age;
2052 if (max_valid < 0)
2053 max_valid = 0;
2054
2055 max_prefered = idev->cnf.temp_prefered_lft -
2056 idev->cnf.max_desync_factor - age;
2057 if (max_prefered < 0)
2058 max_prefered = 0;
2059
2060 if (valid_lft > max_valid)
2061 valid_lft = max_valid;
2062
2063 if (prefered_lft > max_prefered)
2064 prefered_lft = max_prefered;
2065
2066 spin_lock(&ift->lock);
2067 flags = ift->flags;
2068 ift->valid_lft = valid_lft;
2069 ift->prefered_lft = prefered_lft;
2070 ift->tstamp = now;
2071 if (prefered_lft > 0)
2072 ift->flags &= ~IFA_F_DEPRECATED;
2073
2074 spin_unlock(&ift->lock);
2075 if (!(flags&IFA_F_TENTATIVE))
2076 ipv6_ifa_notify(0, ift);
2077 }
2078
2079 if ((create || list_empty(&idev->tempaddr_list)) &&
2080 idev->cnf.use_tempaddr > 0) {
2081 /* When a new public address is created as described
2082 * in [ADDRCONF], also create a new temporary address.
2083 * Also create a temporary address if it's enabled but
2084 * no temporary address currently exists.
2085 */
2086 read_unlock_bh(&idev->lock);
2087 ipv6_create_tempaddr(ifp, NULL);
2088 } else {
2089 read_unlock_bh(&idev->lock);
2090 }
2091}
2092
2019void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao) 2093void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2020{ 2094{
2021 struct prefix_info *pinfo; 2095 struct prefix_info *pinfo;
@@ -2170,6 +2244,7 @@ ok:
2170 return; 2244 return;
2171 } 2245 }
2172 2246
2247 ifp->flags |= IFA_F_MANAGETEMPADDR;
2173 update_lft = 0; 2248 update_lft = 0;
2174 create = 1; 2249 create = 1;
2175 ifp->cstamp = jiffies; 2250 ifp->cstamp = jiffies;
@@ -2178,9 +2253,8 @@ ok:
2178 } 2253 }
2179 2254
2180 if (ifp) { 2255 if (ifp) {
2181 int flags; 2256 u32 flags;
2182 unsigned long now; 2257 unsigned long now;
2183 struct inet6_ifaddr *ift;
2184 u32 stored_lft; 2258 u32 stored_lft;
2185 2259
2186 /* update lifetime (RFC2462 5.5.3 e) */ 2260 /* update lifetime (RFC2462 5.5.3 e) */
@@ -2221,70 +2295,8 @@ ok:
2221 } else 2295 } else
2222 spin_unlock(&ifp->lock); 2296 spin_unlock(&ifp->lock);
2223 2297
2224 read_lock_bh(&in6_dev->lock); 2298 manage_tempaddrs(in6_dev, ifp, valid_lft, prefered_lft,
2225 /* update all temporary addresses in the list */ 2299 create, now);
2226 list_for_each_entry(ift, &in6_dev->tempaddr_list,
2227 tmp_list) {
2228 int age, max_valid, max_prefered;
2229
2230 if (ifp != ift->ifpub)
2231 continue;
2232
2233 /*
2234 * RFC 4941 section 3.3:
2235 * If a received option will extend the lifetime
2236 * of a public address, the lifetimes of
2237 * temporary addresses should be extended,
2238 * subject to the overall constraint that no
2239 * temporary addresses should ever remain
2240 * "valid" or "preferred" for a time longer than
2241 * (TEMP_VALID_LIFETIME) or
2242 * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR),
2243 * respectively.
2244 */
2245 age = (now - ift->cstamp) / HZ;
2246 max_valid = in6_dev->cnf.temp_valid_lft - age;
2247 if (max_valid < 0)
2248 max_valid = 0;
2249
2250 max_prefered = in6_dev->cnf.temp_prefered_lft -
2251 in6_dev->cnf.max_desync_factor -
2252 age;
2253 if (max_prefered < 0)
2254 max_prefered = 0;
2255
2256 if (valid_lft > max_valid)
2257 valid_lft = max_valid;
2258
2259 if (prefered_lft > max_prefered)
2260 prefered_lft = max_prefered;
2261
2262 spin_lock(&ift->lock);
2263 flags = ift->flags;
2264 ift->valid_lft = valid_lft;
2265 ift->prefered_lft = prefered_lft;
2266 ift->tstamp = now;
2267 if (prefered_lft > 0)
2268 ift->flags &= ~IFA_F_DEPRECATED;
2269
2270 spin_unlock(&ift->lock);
2271 if (!(flags&IFA_F_TENTATIVE))
2272 ipv6_ifa_notify(0, ift);
2273 }
2274
2275 if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) {
2276 /*
2277 * When a new public address is created as
2278 * described in [ADDRCONF], also create a new
2279 * temporary address. Also create a temporary
2280 * address if it's enabled but no temporary
2281 * address currently exists.
2282 */
2283 read_unlock_bh(&in6_dev->lock);
2284 ipv6_create_tempaddr(ifp, NULL);
2285 } else {
2286 read_unlock_bh(&in6_dev->lock);
2287 }
2288 2300
2289 in6_ifa_put(ifp); 2301 in6_ifa_put(ifp);
2290 addrconf_verify(0); 2302 addrconf_verify(0);
@@ -2363,10 +2375,11 @@ err_exit:
2363/* 2375/*
2364 * Manual configuration of address on an interface 2376 * Manual configuration of address on an interface
2365 */ 2377 */
2366static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, 2378static int inet6_addr_add(struct net *net, int ifindex,
2379 const struct in6_addr *pfx,
2367 const struct in6_addr *peer_pfx, 2380 const struct in6_addr *peer_pfx,
2368 unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, 2381 unsigned int plen, __u32 ifa_flags,
2369 __u32 valid_lft) 2382 __u32 prefered_lft, __u32 valid_lft)
2370{ 2383{
2371 struct inet6_ifaddr *ifp; 2384 struct inet6_ifaddr *ifp;
2372 struct inet6_dev *idev; 2385 struct inet6_dev *idev;
@@ -2385,6 +2398,9 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p
2385 if (!valid_lft || prefered_lft > valid_lft) 2398 if (!valid_lft || prefered_lft > valid_lft)
2386 return -EINVAL; 2399 return -EINVAL;
2387 2400
2401 if (ifa_flags & IFA_F_MANAGETEMPADDR && plen != 64)
2402 return -EINVAL;
2403
2388 dev = __dev_get_by_index(net, ifindex); 2404 dev = __dev_get_by_index(net, ifindex);
2389 if (!dev) 2405 if (!dev)
2390 return -ENODEV; 2406 return -ENODEV;
@@ -2425,6 +2441,9 @@ static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *p
2425 * manually configured addresses 2441 * manually configured addresses
2426 */ 2442 */
2427 addrconf_dad_start(ifp); 2443 addrconf_dad_start(ifp);
2444 if (ifa_flags & IFA_F_MANAGETEMPADDR)
2445 manage_tempaddrs(idev, ifp, valid_lft, prefered_lft,
2446 true, jiffies);
2428 in6_ifa_put(ifp); 2447 in6_ifa_put(ifp);
2429 addrconf_verify(0); 2448 addrconf_verify(0);
2430 return 0; 2449 return 0;
@@ -2613,7 +2632,7 @@ static void init_loopback(struct net_device *dev)
2613 if (sp_ifa->rt) 2632 if (sp_ifa->rt)
2614 continue; 2633 continue;
2615 2634
2616 sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); 2635 sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, false);
2617 2636
2618 /* Failure cases are ignored */ 2637 /* Failure cases are ignored */
2619 if (!IS_ERR(sp_rt)) { 2638 if (!IS_ERR(sp_rt)) {
@@ -3176,7 +3195,8 @@ static void addrconf_dad_timer(unsigned long data)
3176 } 3195 }
3177 3196
3178 ifp->dad_probes--; 3197 ifp->dad_probes--;
3179 addrconf_mod_dad_timer(ifp, ifp->idev->nd_parms->retrans_time); 3198 addrconf_mod_dad_timer(ifp,
3199 NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME));
3180 spin_unlock(&ifp->lock); 3200 spin_unlock(&ifp->lock);
3181 write_unlock(&idev->lock); 3201 write_unlock(&idev->lock);
3182 3202
@@ -3356,7 +3376,7 @@ static int if6_seq_show(struct seq_file *seq, void *v)
3356 ifp->idev->dev->ifindex, 3376 ifp->idev->dev->ifindex,
3357 ifp->prefix_len, 3377 ifp->prefix_len,
3358 ifp->scope, 3378 ifp->scope,
3359 ifp->flags, 3379 (u8) ifp->flags,
3360 ifp->idev->dev->name); 3380 ifp->idev->dev->name);
3361 return 0; 3381 return 0;
3362} 3382}
@@ -3497,7 +3517,7 @@ restart:
3497 !(ifp->flags&IFA_F_TENTATIVE)) { 3517 !(ifp->flags&IFA_F_TENTATIVE)) {
3498 unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * 3518 unsigned long regen_advance = ifp->idev->cnf.regen_max_retry *
3499 ifp->idev->cnf.dad_transmits * 3519 ifp->idev->cnf.dad_transmits *
3500 ifp->idev->nd_parms->retrans_time / HZ; 3520 NEIGH_VAR(ifp->idev->nd_parms, RETRANS_TIME) / HZ;
3501 3521
3502 if (age >= ifp->prefered_lft - regen_advance) { 3522 if (age >= ifp->prefered_lft - regen_advance) {
3503 struct inet6_ifaddr *ifpub = ifp->ifpub; 3523 struct inet6_ifaddr *ifpub = ifp->ifpub;
@@ -3572,6 +3592,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
3572 [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) }, 3592 [IFA_ADDRESS] = { .len = sizeof(struct in6_addr) },
3573 [IFA_LOCAL] = { .len = sizeof(struct in6_addr) }, 3593 [IFA_LOCAL] = { .len = sizeof(struct in6_addr) },
3574 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) }, 3594 [IFA_CACHEINFO] = { .len = sizeof(struct ifa_cacheinfo) },
3595 [IFA_FLAGS] = { .len = sizeof(u32) },
3575}; 3596};
3576 3597
3577static int 3598static int
@@ -3595,16 +3616,21 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
3595 return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen); 3616 return inet6_addr_del(net, ifm->ifa_index, pfx, ifm->ifa_prefixlen);
3596} 3617}
3597 3618
3598static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, 3619static int inet6_addr_modify(struct inet6_ifaddr *ifp, u32 ifa_flags,
3599 u32 prefered_lft, u32 valid_lft) 3620 u32 prefered_lft, u32 valid_lft)
3600{ 3621{
3601 u32 flags; 3622 u32 flags;
3602 clock_t expires; 3623 clock_t expires;
3603 unsigned long timeout; 3624 unsigned long timeout;
3625 bool was_managetempaddr;
3604 3626
3605 if (!valid_lft || (prefered_lft > valid_lft)) 3627 if (!valid_lft || (prefered_lft > valid_lft))
3606 return -EINVAL; 3628 return -EINVAL;
3607 3629
3630 if (ifa_flags & IFA_F_MANAGETEMPADDR &&
3631 (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
3632 return -EINVAL;
3633
3608 timeout = addrconf_timeout_fixup(valid_lft, HZ); 3634 timeout = addrconf_timeout_fixup(valid_lft, HZ);
3609 if (addrconf_finite_timeout(timeout)) { 3635 if (addrconf_finite_timeout(timeout)) {
3610 expires = jiffies_to_clock_t(timeout * HZ); 3636 expires = jiffies_to_clock_t(timeout * HZ);
@@ -3624,7 +3650,10 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
3624 } 3650 }
3625 3651
3626 spin_lock_bh(&ifp->lock); 3652 spin_lock_bh(&ifp->lock);
3627 ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD | IFA_F_HOMEADDRESS)) | ifa_flags; 3653 was_managetempaddr = ifp->flags & IFA_F_MANAGETEMPADDR;
3654 ifp->flags &= ~(IFA_F_DEPRECATED | IFA_F_PERMANENT | IFA_F_NODAD |
3655 IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR);
3656 ifp->flags |= ifa_flags;
3628 ifp->tstamp = jiffies; 3657 ifp->tstamp = jiffies;
3629 ifp->valid_lft = valid_lft; 3658 ifp->valid_lft = valid_lft;
3630 ifp->prefered_lft = prefered_lft; 3659 ifp->prefered_lft = prefered_lft;
@@ -3635,6 +3664,14 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
3635 3664
3636 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev, 3665 addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev,
3637 expires, flags); 3666 expires, flags);
3667
3668 if (was_managetempaddr || ifp->flags & IFA_F_MANAGETEMPADDR) {
3669 if (was_managetempaddr && !(ifp->flags & IFA_F_MANAGETEMPADDR))
3670 valid_lft = prefered_lft = 0;
3671 manage_tempaddrs(ifp->idev, ifp, valid_lft, prefered_lft,
3672 !was_managetempaddr, jiffies);
3673 }
3674
3638 addrconf_verify(0); 3675 addrconf_verify(0);
3639 3676
3640 return 0; 3677 return 0;
@@ -3650,7 +3687,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
3650 struct inet6_ifaddr *ifa; 3687 struct inet6_ifaddr *ifa;
3651 struct net_device *dev; 3688 struct net_device *dev;
3652 u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME; 3689 u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
3653 u8 ifa_flags; 3690 u32 ifa_flags;
3654 int err; 3691 int err;
3655 3692
3656 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy); 3693 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
@@ -3677,8 +3714,10 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
3677 if (dev == NULL) 3714 if (dev == NULL)
3678 return -ENODEV; 3715 return -ENODEV;
3679 3716
3717 ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) : ifm->ifa_flags;
3718
3680 /* We ignore other flags so far. */ 3719 /* We ignore other flags so far. */
3681 ifa_flags = ifm->ifa_flags & (IFA_F_NODAD | IFA_F_HOMEADDRESS); 3720 ifa_flags &= IFA_F_NODAD | IFA_F_HOMEADDRESS | IFA_F_MANAGETEMPADDR;
3682 3721
3683 ifa = ipv6_get_ifaddr(net, pfx, dev, 1); 3722 ifa = ipv6_get_ifaddr(net, pfx, dev, 1);
3684 if (ifa == NULL) { 3723 if (ifa == NULL) {
@@ -3702,7 +3741,7 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
3702 return err; 3741 return err;
3703} 3742}
3704 3743
3705static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u8 flags, 3744static void put_ifaddrmsg(struct nlmsghdr *nlh, u8 prefixlen, u32 flags,
3706 u8 scope, int ifindex) 3745 u8 scope, int ifindex)
3707{ 3746{
3708 struct ifaddrmsg *ifm; 3747 struct ifaddrmsg *ifm;
@@ -3745,7 +3784,8 @@ static inline int inet6_ifaddr_msgsize(void)
3745 return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) 3784 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
3746 + nla_total_size(16) /* IFA_LOCAL */ 3785 + nla_total_size(16) /* IFA_LOCAL */
3747 + nla_total_size(16) /* IFA_ADDRESS */ 3786 + nla_total_size(16) /* IFA_ADDRESS */
3748 + nla_total_size(sizeof(struct ifa_cacheinfo)); 3787 + nla_total_size(sizeof(struct ifa_cacheinfo))
3788 + nla_total_size(4) /* IFA_FLAGS */;
3749} 3789}
3750 3790
3751static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3791static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3793,6 +3833,9 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
3793 if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) 3833 if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
3794 goto error; 3834 goto error;
3795 3835
3836 if (nla_put_u32(skb, IFA_FLAGS, ifa->flags) < 0)
3837 goto error;
3838
3796 return nlmsg_end(skb, nlh); 3839 return nlmsg_end(skb, nlh);
3797 3840
3798error: 3841error:
@@ -4196,7 +4239,7 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
4196 ci.max_reasm_len = IPV6_MAXPLEN; 4239 ci.max_reasm_len = IPV6_MAXPLEN;
4197 ci.tstamp = cstamp_delta(idev->tstamp); 4240 ci.tstamp = cstamp_delta(idev->tstamp);
4198 ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time); 4241 ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time);
4199 ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time); 4242 ci.retrans_time = jiffies_to_msecs(NEIGH_VAR(idev->nd_parms, RETRANS_TIME));
4200 if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci)) 4243 if (nla_put(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci))
4201 goto nla_put_failure; 4244 goto nla_put_failure;
4202 nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); 4245 nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32));
@@ -4689,6 +4732,46 @@ int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
4689 return ret; 4732 return ret;
4690} 4733}
4691 4734
4735static
4736int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
4737 void __user *buffer, size_t *lenp, loff_t *ppos)
4738{
4739 int *valp = ctl->data;
4740 int ret;
4741 int old, new;
4742
4743 old = *valp;
4744 ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
4745 new = *valp;
4746
4747 if (write && old != new) {
4748 struct net *net = ctl->extra2;
4749
4750 if (!rtnl_trylock())
4751 return restart_syscall();
4752
4753 if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
4754 inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
4755 NETCONFA_IFINDEX_DEFAULT,
4756 net->ipv6.devconf_dflt);
4757 else if (valp == &net->ipv6.devconf_all->proxy_ndp)
4758 inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
4759 NETCONFA_IFINDEX_ALL,
4760 net->ipv6.devconf_all);
4761 else {
4762 struct inet6_dev *idev = ctl->extra1;
4763
4764 inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
4765 idev->dev->ifindex,
4766 &idev->cnf);
4767 }
4768 rtnl_unlock();
4769 }
4770
4771 return ret;
4772}
4773
4774
4692static struct addrconf_sysctl_table 4775static struct addrconf_sysctl_table
4693{ 4776{
4694 struct ctl_table_header *sysctl_header; 4777 struct ctl_table_header *sysctl_header;
@@ -4875,7 +4958,7 @@ static struct addrconf_sysctl_table
4875 .data = &ipv6_devconf.proxy_ndp, 4958 .data = &ipv6_devconf.proxy_ndp,
4876 .maxlen = sizeof(int), 4959 .maxlen = sizeof(int),
4877 .mode = 0644, 4960 .mode = 0644,
4878 .proc_handler = proc_dointvec, 4961 .proc_handler = addrconf_sysctl_proxy_ndp,
4879 }, 4962 },
4880 { 4963 {
4881 .procname = "accept_source_route", 4964 .procname = "accept_source_route",
@@ -4991,7 +5074,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
4991 5074
4992static void addrconf_sysctl_register(struct inet6_dev *idev) 5075static void addrconf_sysctl_register(struct inet6_dev *idev)
4993{ 5076{
4994 neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6", 5077 neigh_sysctl_register(idev->dev, idev->nd_parms,
4995 &ndisc_ifinfo_sysctl_change); 5078 &ndisc_ifinfo_sysctl_change);
4996 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, 5079 __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name,
4997 idev, &idev->cnf); 5080 idev, &idev->cnf);