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.c67
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)
121static int __ipv6_regen_rndid(struct inet6_dev *idev); 121static int __ipv6_regen_rndid(struct inet6_dev *idev);
122static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); 122static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr);
123static void ipv6_regen_rndid(unsigned long data); 123static void ipv6_regen_rndid(unsigned long data);
124
125static int desync_factor = MAX_DESYNC_FACTOR * HZ;
126#endif 124#endif
127 125
128static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); 126static int ipv6_generate_eui64(u8 *eui, struct net_device *dev);
@@ -284,13 +282,16 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp,
284static int snmp6_alloc_dev(struct inet6_dev *idev) 282static 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
829out: 830out:
@@ -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
3869static 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
3858static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, 3884static 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}