diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 67 |
1 files changed, 47 insertions, 20 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e1a698df5706..ab70a3fbcafa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -121,8 +121,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); |
| 122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | 122 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); |
| 123 | static void ipv6_regen_rndid(unsigned long data); | 123 | static void ipv6_regen_rndid(unsigned long data); |
| 124 | |||
| 125 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | ||
| 126 | #endif | 124 | #endif |
| 127 | 125 | ||
| 128 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); | 126 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); |
| @@ -284,13 +282,16 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
| 284 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 282 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
| 285 | { | 283 | { |
| 286 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, | 284 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
| 287 | sizeof(struct ipstats_mib)) < 0) | 285 | sizeof(struct ipstats_mib), |
| 286 | __alignof__(struct ipstats_mib)) < 0) | ||
| 288 | goto err_ip; | 287 | goto err_ip; |
| 289 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, | 288 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
| 290 | sizeof(struct icmpv6_mib)) < 0) | 289 | sizeof(struct icmpv6_mib), |
| 290 | __alignof__(struct icmpv6_mib)) < 0) | ||
| 291 | goto err_icmp; | 291 | goto err_icmp; |
| 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, | 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
| 293 | sizeof(struct icmpv6msg_mib)) < 0) | 293 | sizeof(struct icmpv6msg_mib), |
| 294 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
| 294 | goto err_icmpmsg; | 295 | goto err_icmpmsg; |
| 295 | 296 | ||
| 296 | return 0; | 297 | return 0; |
| @@ -557,7 +558,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
| 557 | pr_warning("Freeing alive inet6 address %p\n", ifp); | 558 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
| 558 | return; | 559 | return; |
| 559 | } | 560 | } |
| 560 | dst_release(&ifp->rt->u.dst); | 561 | dst_release(&ifp->rt->dst); |
| 561 | 562 | ||
| 562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); | 563 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
| 563 | } | 564 | } |
| @@ -823,7 +824,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 823 | rt->rt6i_flags |= RTF_EXPIRES; | 824 | rt->rt6i_flags |= RTF_EXPIRES; |
| 824 | } | 825 | } |
| 825 | } | 826 | } |
| 826 | dst_release(&rt->u.dst); | 827 | dst_release(&rt->dst); |
| 827 | } | 828 | } |
| 828 | 829 | ||
| 829 | out: | 830 | out: |
| @@ -890,7 +891,8 @@ retry: | |||
| 890 | idev->cnf.temp_valid_lft); | 891 | idev->cnf.temp_valid_lft); |
| 891 | tmp_prefered_lft = min_t(__u32, | 892 | tmp_prefered_lft = min_t(__u32, |
| 892 | ifp->prefered_lft, | 893 | ifp->prefered_lft, |
| 893 | idev->cnf.temp_prefered_lft - desync_factor / HZ); | 894 | idev->cnf.temp_prefered_lft - |
| 895 | idev->cnf.max_desync_factor); | ||
| 894 | tmp_plen = ifp->prefix_len; | 896 | tmp_plen = ifp->prefix_len; |
| 895 | max_addresses = idev->cnf.max_addresses; | 897 | max_addresses = idev->cnf.max_addresses; |
| 896 | tmp_cstamp = ifp->cstamp; | 898 | tmp_cstamp = ifp->cstamp; |
| @@ -1650,7 +1652,8 @@ static void ipv6_regen_rndid(unsigned long data) | |||
| 1650 | 1652 | ||
| 1651 | expires = jiffies + | 1653 | expires = jiffies + |
| 1652 | idev->cnf.temp_prefered_lft * HZ - | 1654 | idev->cnf.temp_prefered_lft * HZ - |
| 1653 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - desync_factor; | 1655 | idev->cnf.regen_max_retry * idev->cnf.dad_transmits * idev->nd_parms->retrans_time - |
| 1656 | idev->cnf.max_desync_factor * HZ; | ||
| 1654 | if (time_before(expires, jiffies)) { | 1657 | if (time_before(expires, jiffies)) { |
| 1655 | printk(KERN_WARNING | 1658 | printk(KERN_WARNING |
| 1656 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", | 1659 | "ipv6_regen_rndid(): too short regeneration interval; timer disabled for %s.\n", |
| @@ -1760,7 +1763,10 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
| 1760 | 1763 | ||
| 1761 | idev = ipv6_find_idev(dev); | 1764 | idev = ipv6_find_idev(dev); |
| 1762 | if (!idev) | 1765 | if (!idev) |
| 1763 | return NULL; | 1766 | return ERR_PTR(-ENOBUFS); |
| 1767 | |||
| 1768 | if (idev->cnf.disable_ipv6) | ||
| 1769 | return ERR_PTR(-EACCES); | ||
| 1764 | 1770 | ||
| 1765 | /* Add default multicast route */ | 1771 | /* Add default multicast route */ |
| 1766 | addrconf_add_mroute(dev); | 1772 | addrconf_add_mroute(dev); |
| @@ -1863,7 +1869,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1863 | dev, expires, flags); | 1869 | dev, expires, flags); |
| 1864 | } | 1870 | } |
| 1865 | if (rt) | 1871 | if (rt) |
| 1866 | dst_release(&rt->u.dst); | 1872 | dst_release(&rt->dst); |
| 1867 | } | 1873 | } |
| 1868 | 1874 | ||
| 1869 | /* Try to figure out our local address for this prefix */ | 1875 | /* Try to figure out our local address for this prefix */ |
| @@ -2129,8 +2135,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
| 2129 | if (!dev) | 2135 | if (!dev) |
| 2130 | return -ENODEV; | 2136 | return -ENODEV; |
| 2131 | 2137 | ||
| 2132 | if ((idev = addrconf_add_dev(dev)) == NULL) | 2138 | idev = addrconf_add_dev(dev); |
| 2133 | return -ENOBUFS; | 2139 | if (IS_ERR(idev)) |
| 2140 | return PTR_ERR(idev); | ||
| 2134 | 2141 | ||
| 2135 | scope = ipv6_addr_scope(pfx); | 2142 | scope = ipv6_addr_scope(pfx); |
| 2136 | 2143 | ||
| @@ -2377,7 +2384,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
| 2377 | } | 2384 | } |
| 2378 | 2385 | ||
| 2379 | idev = addrconf_add_dev(dev); | 2386 | idev = addrconf_add_dev(dev); |
| 2380 | if (idev == NULL) | 2387 | if (IS_ERR(idev)) |
| 2381 | return; | 2388 | return; |
| 2382 | 2389 | ||
| 2383 | memset(&addr, 0, sizeof(struct in6_addr)); | 2390 | memset(&addr, 0, sizeof(struct in6_addr)); |
| @@ -2468,7 +2475,7 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
| 2468 | ASSERT_RTNL(); | 2475 | ASSERT_RTNL(); |
| 2469 | 2476 | ||
| 2470 | idev = addrconf_add_dev(dev); | 2477 | idev = addrconf_add_dev(dev); |
| 2471 | if (!idev) { | 2478 | if (IS_ERR(idev)) { |
| 2472 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2479 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
| 2473 | return; | 2480 | return; |
| 2474 | } | 2481 | } |
| @@ -3492,8 +3499,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
| 3492 | preferred -= tval; | 3499 | preferred -= tval; |
| 3493 | else | 3500 | else |
| 3494 | preferred = 0; | 3501 | preferred = 0; |
| 3495 | if (valid != INFINITY_LIFE_TIME) | 3502 | if (valid != INFINITY_LIFE_TIME) { |
| 3496 | valid -= tval; | 3503 | if (valid > tval) |
| 3504 | valid -= tval; | ||
| 3505 | else | ||
| 3506 | valid = 0; | ||
| 3507 | } | ||
| 3497 | } | 3508 | } |
| 3498 | } else { | 3509 | } else { |
| 3499 | preferred = INFINITY_LIFE_TIME; | 3510 | preferred = INFINITY_LIFE_TIME; |
| @@ -3855,12 +3866,28 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
| 3855 | memset(&stats[items], 0, pad); | 3866 | memset(&stats[items], 0, pad); |
| 3856 | } | 3867 | } |
| 3857 | 3868 | ||
| 3869 | static inline void __snmp6_fill_stats64(u64 *stats, void __percpu **mib, | ||
| 3870 | int items, int bytes, size_t syncpoff) | ||
| 3871 | { | ||
| 3872 | int i; | ||
| 3873 | int pad = bytes - sizeof(u64) * items; | ||
| 3874 | BUG_ON(pad < 0); | ||
| 3875 | |||
| 3876 | /* Use put_unaligned() because stats may not be aligned for u64. */ | ||
| 3877 | put_unaligned(items, &stats[0]); | ||
| 3878 | for (i = 1; i < items; i++) | ||
| 3879 | put_unaligned(snmp_fold_field64(mib, i, syncpoff), &stats[i]); | ||
| 3880 | |||
| 3881 | memset(&stats[items], 0, pad); | ||
| 3882 | } | ||
| 3883 | |||
| 3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3884 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
| 3859 | int bytes) | 3885 | int bytes) |
| 3860 | { | 3886 | { |
| 3861 | switch (attrtype) { | 3887 | switch (attrtype) { |
| 3862 | case IFLA_INET6_STATS: | 3888 | case IFLA_INET6_STATS: |
| 3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3889 | __snmp6_fill_stats64(stats, (void __percpu **)idev->stats.ipv6, |
| 3890 | IPSTATS_MIB_MAX, bytes, offsetof(struct ipstats_mib, syncp)); | ||
| 3864 | break; | 3891 | break; |
| 3865 | case IFLA_INET6_ICMP6STATS: | 3892 | case IFLA_INET6_ICMP6STATS: |
| 3866 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3893 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
| @@ -4093,11 +4120,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
| 4093 | if (ifp->idev->cnf.forwarding) | 4120 | if (ifp->idev->cnf.forwarding) |
| 4094 | addrconf_leave_anycast(ifp); | 4121 | addrconf_leave_anycast(ifp); |
| 4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4122 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
| 4096 | dst_hold(&ifp->rt->u.dst); | 4123 | dst_hold(&ifp->rt->dst); |
| 4097 | 4124 | ||
| 4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | 4125 | if (ifp->state == INET6_IFADDR_STATE_DEAD && |
| 4099 | ip6_del_rt(ifp->rt)) | 4126 | ip6_del_rt(ifp->rt)) |
| 4100 | dst_free(&ifp->rt->u.dst); | 4127 | dst_free(&ifp->rt->dst); |
| 4101 | break; | 4128 | break; |
| 4102 | } | 4129 | } |
| 4103 | } | 4130 | } |
