diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 1087 |
1 files changed, 604 insertions, 483 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index de7a194a64ab..324fac3b6c16 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <linux/route.h> | 53 | #include <linux/route.h> |
| 54 | #include <linux/inetdevice.h> | 54 | #include <linux/inetdevice.h> |
| 55 | #include <linux/init.h> | 55 | #include <linux/init.h> |
| 56 | #include <linux/slab.h> | ||
| 56 | #ifdef CONFIG_SYSCTL | 57 | #ifdef CONFIG_SYSCTL |
| 57 | #include <linux/sysctl.h> | 58 | #include <linux/sysctl.h> |
| 58 | #endif | 59 | #endif |
| @@ -81,7 +82,7 @@ | |||
| 81 | #include <linux/random.h> | 82 | #include <linux/random.h> |
| 82 | #endif | 83 | #endif |
| 83 | 84 | ||
| 84 | #include <asm/uaccess.h> | 85 | #include <linux/uaccess.h> |
| 85 | #include <asm/unaligned.h> | 86 | #include <asm/unaligned.h> |
| 86 | 87 | ||
| 87 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
| @@ -97,7 +98,11 @@ | |||
| 97 | #endif | 98 | #endif |
| 98 | 99 | ||
| 99 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
| 100 | #define TIME_DELTA(a,b) ((unsigned long)((long)(a) - (long)(b))) | 101 | #define TIME_DELTA(a, b) ((unsigned long)((long)(a) - (long)(b))) |
| 102 | |||
| 103 | #define ADDRCONF_TIMER_FUZZ_MINUS (HZ > 50 ? HZ/50 : 1) | ||
| 104 | #define ADDRCONF_TIMER_FUZZ (HZ / 4) | ||
| 105 | #define ADDRCONF_TIMER_FUZZ_MAX (HZ) | ||
| 101 | 106 | ||
| 102 | #ifdef CONFIG_SYSCTL | 107 | #ifdef CONFIG_SYSCTL |
| 103 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 108 | static void addrconf_sysctl_register(struct inet6_dev *idev); |
| @@ -116,8 +121,6 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 116 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 121 | static int __ipv6_regen_rndid(struct inet6_dev *idev); |
| 117 | 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); |
| 118 | static void ipv6_regen_rndid(unsigned long data); | 123 | static void ipv6_regen_rndid(unsigned long data); |
| 119 | |||
| 120 | static int desync_factor = MAX_DESYNC_FACTOR * HZ; | ||
| 121 | #endif | 124 | #endif |
| 122 | 125 | ||
| 123 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); | 126 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev); |
| @@ -126,8 +129,8 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
| 126 | /* | 129 | /* |
| 127 | * Configured unicast address hash table | 130 | * Configured unicast address hash table |
| 128 | */ | 131 | */ |
| 129 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 132 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
| 130 | static DEFINE_RWLOCK(addrconf_hash_lock); | 133 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
| 131 | 134 | ||
| 132 | static void addrconf_verify(unsigned long); | 135 | static void addrconf_verify(unsigned long); |
| 133 | 136 | ||
| @@ -137,8 +140,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); | |||
| 137 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 140 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
| 138 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 141 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
| 139 | 142 | ||
| 140 | static void addrconf_bonding_change(struct net_device *dev, | 143 | static void addrconf_type_change(struct net_device *dev, |
| 141 | unsigned long event); | 144 | unsigned long event); |
| 142 | static int addrconf_ifdown(struct net_device *dev, int how); | 145 | static int addrconf_ifdown(struct net_device *dev, int how); |
| 143 | 146 | ||
| 144 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 147 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
| @@ -151,8 +154,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |||
| 151 | 154 | ||
| 152 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 155 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
| 153 | struct prefix_info *pinfo); | 156 | struct prefix_info *pinfo); |
| 154 | static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 157 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
| 155 | struct net_device *dev); | 158 | struct net_device *dev); |
| 156 | 159 | ||
| 157 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 160 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
| 158 | 161 | ||
| @@ -249,8 +252,7 @@ static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |||
| 249 | __in6_ifa_put(ifp); | 252 | __in6_ifa_put(ifp); |
| 250 | } | 253 | } |
| 251 | 254 | ||
| 252 | enum addrconf_timer_t | 255 | enum addrconf_timer_t { |
| 253 | { | ||
| 254 | AC_NONE, | 256 | AC_NONE, |
| 255 | AC_DAD, | 257 | AC_DAD, |
| 256 | AC_RS, | 258 | AC_RS, |
| @@ -270,7 +272,8 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
| 270 | case AC_RS: | 272 | case AC_RS: |
| 271 | ifp->timer.function = addrconf_rs_timer; | 273 | ifp->timer.function = addrconf_rs_timer; |
| 272 | break; | 274 | break; |
| 273 | default:; | 275 | default: |
| 276 | break; | ||
| 274 | } | 277 | } |
| 275 | ifp->timer.expires = jiffies + when; | 278 | ifp->timer.expires = jiffies + when; |
| 276 | add_timer(&ifp->timer); | 279 | add_timer(&ifp->timer); |
| @@ -278,31 +281,34 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
| 278 | 281 | ||
| 279 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 282 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
| 280 | { | 283 | { |
| 281 | if (snmp_mib_init((void **)idev->stats.ipv6, | 284 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
| 282 | sizeof(struct ipstats_mib)) < 0) | 285 | sizeof(struct ipstats_mib), |
| 286 | __alignof__(struct ipstats_mib)) < 0) | ||
| 283 | goto err_ip; | 287 | goto err_ip; |
| 284 | if (snmp_mib_init((void **)idev->stats.icmpv6, | 288 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
| 285 | sizeof(struct icmpv6_mib)) < 0) | 289 | sizeof(struct icmpv6_mib), |
| 290 | __alignof__(struct icmpv6_mib)) < 0) | ||
| 286 | goto err_icmp; | 291 | goto err_icmp; |
| 287 | if (snmp_mib_init((void **)idev->stats.icmpv6msg, | 292 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
| 288 | sizeof(struct icmpv6msg_mib)) < 0) | 293 | sizeof(struct icmpv6msg_mib), |
| 294 | __alignof__(struct icmpv6msg_mib)) < 0) | ||
| 289 | goto err_icmpmsg; | 295 | goto err_icmpmsg; |
| 290 | 296 | ||
| 291 | return 0; | 297 | return 0; |
| 292 | 298 | ||
| 293 | err_icmpmsg: | 299 | err_icmpmsg: |
| 294 | snmp_mib_free((void **)idev->stats.icmpv6); | 300 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
| 295 | err_icmp: | 301 | err_icmp: |
| 296 | snmp_mib_free((void **)idev->stats.ipv6); | 302 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
| 297 | err_ip: | 303 | err_ip: |
| 298 | return -ENOMEM; | 304 | return -ENOMEM; |
| 299 | } | 305 | } |
| 300 | 306 | ||
| 301 | static void snmp6_free_dev(struct inet6_dev *idev) | 307 | static void snmp6_free_dev(struct inet6_dev *idev) |
| 302 | { | 308 | { |
| 303 | snmp_mib_free((void **)idev->stats.icmpv6msg); | 309 | snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); |
| 304 | snmp_mib_free((void **)idev->stats.icmpv6); | 310 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
| 305 | snmp_mib_free((void **)idev->stats.ipv6); | 311 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
| 306 | } | 312 | } |
| 307 | 313 | ||
| 308 | /* Nobody refers to this device, we may destroy it. */ | 314 | /* Nobody refers to this device, we may destroy it. */ |
| @@ -317,7 +323,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
| 317 | { | 323 | { |
| 318 | struct net_device *dev = idev->dev; | 324 | struct net_device *dev = idev->dev; |
| 319 | 325 | ||
| 320 | WARN_ON(idev->addr_list != NULL); | 326 | WARN_ON(!list_empty(&idev->addr_list)); |
| 321 | WARN_ON(idev->mc_list != NULL); | 327 | WARN_ON(idev->mc_list != NULL); |
| 322 | 328 | ||
| 323 | #ifdef NET_REFCNT_DEBUG | 329 | #ifdef NET_REFCNT_DEBUG |
| @@ -325,7 +331,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
| 325 | #endif | 331 | #endif |
| 326 | dev_put(dev); | 332 | dev_put(dev); |
| 327 | if (!idev->dead) { | 333 | if (!idev->dead) { |
| 328 | printk("Freeing alive inet6 device %p\n", idev); | 334 | pr_warning("Freeing alive inet6 device %p\n", idev); |
| 329 | return; | 335 | return; |
| 330 | } | 336 | } |
| 331 | snmp6_free_dev(idev); | 337 | snmp6_free_dev(idev); |
| @@ -350,6 +356,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 350 | 356 | ||
| 351 | rwlock_init(&ndev->lock); | 357 | rwlock_init(&ndev->lock); |
| 352 | ndev->dev = dev; | 358 | ndev->dev = dev; |
| 359 | INIT_LIST_HEAD(&ndev->addr_list); | ||
| 360 | |||
| 353 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 361 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
| 354 | ndev->cnf.mtu6 = dev->mtu; | 362 | ndev->cnf.mtu6 = dev->mtu; |
| 355 | ndev->cnf.sysctl = NULL; | 363 | ndev->cnf.sysctl = NULL; |
| @@ -401,6 +409,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 401 | #endif | 409 | #endif |
| 402 | 410 | ||
| 403 | #ifdef CONFIG_IPV6_PRIVACY | 411 | #ifdef CONFIG_IPV6_PRIVACY |
| 412 | INIT_LIST_HEAD(&ndev->tempaddr_list); | ||
| 404 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); | 413 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); |
| 405 | if ((dev->flags&IFF_LOOPBACK) || | 414 | if ((dev->flags&IFF_LOOPBACK) || |
| 406 | dev->type == ARPHRD_TUNNEL || | 415 | dev->type == ARPHRD_TUNNEL || |
| @@ -438,8 +447,10 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
| 438 | 447 | ||
| 439 | ASSERT_RTNL(); | 448 | ASSERT_RTNL(); |
| 440 | 449 | ||
| 441 | if ((idev = __in6_dev_get(dev)) == NULL) { | 450 | idev = __in6_dev_get(dev); |
| 442 | if ((idev = ipv6_add_dev(dev)) == NULL) | 451 | if (!idev) { |
| 452 | idev = ipv6_add_dev(dev); | ||
| 453 | if (!idev) | ||
| 443 | return NULL; | 454 | return NULL; |
| 444 | } | 455 | } |
| 445 | 456 | ||
| @@ -465,7 +476,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
| 465 | else | 476 | else |
| 466 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); | 477 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
| 467 | } | 478 | } |
| 468 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 479 | |
| 480 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
| 469 | if (ifa->flags&IFA_F_TENTATIVE) | 481 | if (ifa->flags&IFA_F_TENTATIVE) |
| 470 | continue; | 482 | continue; |
| 471 | if (idev->cnf.forwarding) | 483 | if (idev->cnf.forwarding) |
| @@ -502,8 +514,11 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
| 502 | if (p == &net->ipv6.devconf_dflt->forwarding) | 514 | if (p == &net->ipv6.devconf_dflt->forwarding) |
| 503 | return 0; | 515 | return 0; |
| 504 | 516 | ||
| 505 | if (!rtnl_trylock()) | 517 | if (!rtnl_trylock()) { |
| 518 | /* Restore the original values before restarting */ | ||
| 519 | *p = old; | ||
| 506 | return restart_syscall(); | 520 | return restart_syscall(); |
| 521 | } | ||
| 507 | 522 | ||
| 508 | if (p == &net->ipv6.devconf_all->forwarding) { | 523 | if (p == &net->ipv6.devconf_all->forwarding) { |
| 509 | __s32 newf = net->ipv6.devconf_all->forwarding; | 524 | __s32 newf = net->ipv6.devconf_all->forwarding; |
| @@ -519,12 +534,16 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
| 519 | } | 534 | } |
| 520 | #endif | 535 | #endif |
| 521 | 536 | ||
| 522 | /* Nobody refers to this ifaddr, destroy it */ | 537 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) |
| 538 | { | ||
| 539 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
| 540 | kfree(ifp); | ||
| 541 | } | ||
| 523 | 542 | ||
| 543 | /* Nobody refers to this ifaddr, destroy it */ | ||
| 524 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 544 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
| 525 | { | 545 | { |
| 526 | WARN_ON(ifp->if_next != NULL); | 546 | WARN_ON(!hlist_unhashed(&ifp->addr_lst)); |
| 527 | WARN_ON(ifp->lst_next != NULL); | ||
| 528 | 547 | ||
| 529 | #ifdef NET_REFCNT_DEBUG | 548 | #ifdef NET_REFCNT_DEBUG |
| 530 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); | 549 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); |
| @@ -533,54 +552,46 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
| 533 | in6_dev_put(ifp->idev); | 552 | in6_dev_put(ifp->idev); |
| 534 | 553 | ||
| 535 | if (del_timer(&ifp->timer)) | 554 | if (del_timer(&ifp->timer)) |
| 536 | printk("Timer is still running, when freeing ifa=%p\n", ifp); | 555 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
| 537 | 556 | ||
| 538 | if (!ifp->dead) { | 557 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
| 539 | printk("Freeing alive inet6 address %p\n", ifp); | 558 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
| 540 | return; | 559 | return; |
| 541 | } | 560 | } |
| 542 | dst_release(&ifp->rt->u.dst); | 561 | dst_release(&ifp->rt->dst); |
| 543 | 562 | ||
| 544 | kfree(ifp); | 563 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
| 545 | } | 564 | } |
| 546 | 565 | ||
| 547 | static void | 566 | static void |
| 548 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | 567 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) |
| 549 | { | 568 | { |
| 550 | struct inet6_ifaddr *ifa, **ifap; | 569 | struct list_head *p; |
| 551 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); | 570 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); |
| 552 | 571 | ||
| 553 | /* | 572 | /* |
| 554 | * Each device address list is sorted in order of scope - | 573 | * Each device address list is sorted in order of scope - |
| 555 | * global before linklocal. | 574 | * global before linklocal. |
| 556 | */ | 575 | */ |
| 557 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | 576 | list_for_each(p, &idev->addr_list) { |
| 558 | ifap = &ifa->if_next) { | 577 | struct inet6_ifaddr *ifa |
| 578 | = list_entry(p, struct inet6_ifaddr, if_list); | ||
| 559 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) | 579 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) |
| 560 | break; | 580 | break; |
| 561 | } | 581 | } |
| 562 | 582 | ||
| 563 | ifp->if_next = *ifap; | 583 | list_add_tail(&ifp->if_list, p); |
| 564 | *ifap = ifp; | ||
| 565 | } | 584 | } |
| 566 | 585 | ||
| 567 | /* | 586 | static u32 ipv6_addr_hash(const struct in6_addr *addr) |
| 568 | * Hash function taken from net_alias.c | ||
| 569 | */ | ||
| 570 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
| 571 | { | 587 | { |
| 572 | __u32 word; | ||
| 573 | |||
| 574 | /* | 588 | /* |
| 575 | * We perform the hash function over the last 64 bits of the address | 589 | * We perform the hash function over the last 64 bits of the address |
| 576 | * This will include the IEEE address token on links that support it. | 590 | * This will include the IEEE address token on links that support it. |
| 577 | */ | 591 | */ |
| 578 | 592 | return jhash_2words((__force u32)addr->s6_addr32[2], | |
| 579 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | 593 | (__force u32)addr->s6_addr32[3], 0) |
| 580 | word ^= (word >> 16); | 594 | & (IN6_ADDR_HSIZE - 1); |
| 581 | word ^= (word >> 8); | ||
| 582 | |||
| 583 | return ((word ^ (word >> 4)) & 0x0f); | ||
| 584 | } | 595 | } |
| 585 | 596 | ||
| 586 | /* On success it returns ifp with increased reference count */ | 597 | /* On success it returns ifp with increased reference count */ |
| @@ -591,7 +602,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
| 591 | { | 602 | { |
| 592 | struct inet6_ifaddr *ifa = NULL; | 603 | struct inet6_ifaddr *ifa = NULL; |
| 593 | struct rt6_info *rt; | 604 | struct rt6_info *rt; |
| 594 | int hash; | 605 | unsigned int hash; |
| 595 | int err = 0; | 606 | int err = 0; |
| 596 | int addr_type = ipv6_addr_type(addr); | 607 | int addr_type = ipv6_addr_type(addr); |
| 597 | 608 | ||
| @@ -612,7 +623,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
| 612 | goto out2; | 623 | goto out2; |
| 613 | } | 624 | } |
| 614 | 625 | ||
| 615 | write_lock(&addrconf_hash_lock); | 626 | spin_lock(&addrconf_hash_lock); |
| 616 | 627 | ||
| 617 | /* Ignore adding duplicate addresses on an interface */ | 628 | /* Ignore adding duplicate addresses on an interface */ |
| 618 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | 629 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
| @@ -638,7 +649,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
| 638 | ipv6_addr_copy(&ifa->addr, addr); | 649 | ipv6_addr_copy(&ifa->addr, addr); |
| 639 | 650 | ||
| 640 | spin_lock_init(&ifa->lock); | 651 | spin_lock_init(&ifa->lock); |
| 652 | spin_lock_init(&ifa->state_lock); | ||
| 641 | init_timer(&ifa->timer); | 653 | init_timer(&ifa->timer); |
| 654 | INIT_HLIST_NODE(&ifa->addr_lst); | ||
| 642 | ifa->timer.data = (unsigned long) ifa; | 655 | ifa->timer.data = (unsigned long) ifa; |
| 643 | ifa->scope = scope; | 656 | ifa->scope = scope; |
| 644 | ifa->prefix_len = pfxlen; | 657 | ifa->prefix_len = pfxlen; |
| @@ -665,10 +678,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
| 665 | /* Add to big hash table */ | 678 | /* Add to big hash table */ |
| 666 | hash = ipv6_addr_hash(addr); | 679 | hash = ipv6_addr_hash(addr); |
| 667 | 680 | ||
| 668 | ifa->lst_next = inet6_addr_lst[hash]; | 681 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
| 669 | inet6_addr_lst[hash] = ifa; | 682 | spin_unlock(&addrconf_hash_lock); |
| 670 | in6_ifa_hold(ifa); | ||
| 671 | write_unlock(&addrconf_hash_lock); | ||
| 672 | 683 | ||
| 673 | write_lock(&idev->lock); | 684 | write_lock(&idev->lock); |
| 674 | /* Add to inet6_dev unicast addr list. */ | 685 | /* Add to inet6_dev unicast addr list. */ |
| @@ -676,8 +687,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
| 676 | 687 | ||
| 677 | #ifdef CONFIG_IPV6_PRIVACY | 688 | #ifdef CONFIG_IPV6_PRIVACY |
| 678 | if (ifa->flags&IFA_F_TEMPORARY) { | 689 | if (ifa->flags&IFA_F_TEMPORARY) { |
| 679 | ifa->tmp_next = idev->tempaddr_list; | 690 | list_add(&ifa->tmp_list, &idev->tempaddr_list); |
| 680 | idev->tempaddr_list = ifa; | ||
| 681 | in6_ifa_hold(ifa); | 691 | in6_ifa_hold(ifa); |
| 682 | } | 692 | } |
| 683 | #endif | 693 | #endif |
| @@ -696,7 +706,7 @@ out2: | |||
| 696 | 706 | ||
| 697 | return ifa; | 707 | return ifa; |
| 698 | out: | 708 | out: |
| 699 | write_unlock(&addrconf_hash_lock); | 709 | spin_unlock(&addrconf_hash_lock); |
| 700 | goto out2; | 710 | goto out2; |
| 701 | } | 711 | } |
| 702 | 712 | ||
| @@ -704,52 +714,44 @@ out: | |||
| 704 | 714 | ||
| 705 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) | 715 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) |
| 706 | { | 716 | { |
| 707 | struct inet6_ifaddr *ifa, **ifap; | 717 | struct inet6_ifaddr *ifa, *ifn; |
| 708 | struct inet6_dev *idev = ifp->idev; | 718 | struct inet6_dev *idev = ifp->idev; |
| 719 | int state; | ||
| 709 | int hash; | 720 | int hash; |
| 710 | int deleted = 0, onlink = 0; | 721 | int deleted = 0, onlink = 0; |
| 711 | unsigned long expires = jiffies; | 722 | unsigned long expires = jiffies; |
| 712 | 723 | ||
| 713 | hash = ipv6_addr_hash(&ifp->addr); | 724 | hash = ipv6_addr_hash(&ifp->addr); |
| 714 | 725 | ||
| 715 | ifp->dead = 1; | 726 | spin_lock_bh(&ifp->state_lock); |
| 727 | state = ifp->state; | ||
| 728 | ifp->state = INET6_IFADDR_STATE_DEAD; | ||
| 729 | spin_unlock_bh(&ifp->state_lock); | ||
| 716 | 730 | ||
| 717 | write_lock_bh(&addrconf_hash_lock); | 731 | if (state == INET6_IFADDR_STATE_DEAD) |
| 718 | for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL; | 732 | goto out; |
| 719 | ifap = &ifa->lst_next) { | 733 | |
| 720 | if (ifa == ifp) { | 734 | spin_lock_bh(&addrconf_hash_lock); |
| 721 | *ifap = ifa->lst_next; | 735 | hlist_del_init_rcu(&ifp->addr_lst); |
| 722 | __in6_ifa_put(ifp); | 736 | spin_unlock_bh(&addrconf_hash_lock); |
| 723 | ifa->lst_next = NULL; | ||
| 724 | break; | ||
| 725 | } | ||
| 726 | } | ||
| 727 | write_unlock_bh(&addrconf_hash_lock); | ||
| 728 | 737 | ||
| 729 | write_lock_bh(&idev->lock); | 738 | write_lock_bh(&idev->lock); |
| 730 | #ifdef CONFIG_IPV6_PRIVACY | 739 | #ifdef CONFIG_IPV6_PRIVACY |
| 731 | if (ifp->flags&IFA_F_TEMPORARY) { | 740 | if (ifp->flags&IFA_F_TEMPORARY) { |
| 732 | for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL; | 741 | list_del(&ifp->tmp_list); |
| 733 | ifap = &ifa->tmp_next) { | 742 | if (ifp->ifpub) { |
| 734 | if (ifa == ifp) { | 743 | in6_ifa_put(ifp->ifpub); |
| 735 | *ifap = ifa->tmp_next; | 744 | ifp->ifpub = NULL; |
| 736 | if (ifp->ifpub) { | ||
| 737 | in6_ifa_put(ifp->ifpub); | ||
| 738 | ifp->ifpub = NULL; | ||
| 739 | } | ||
| 740 | __in6_ifa_put(ifp); | ||
| 741 | ifa->tmp_next = NULL; | ||
| 742 | break; | ||
| 743 | } | ||
| 744 | } | 745 | } |
| 746 | __in6_ifa_put(ifp); | ||
| 745 | } | 747 | } |
| 746 | #endif | 748 | #endif |
| 747 | 749 | ||
| 748 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { | 750 | list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) { |
| 749 | if (ifa == ifp) { | 751 | if (ifa == ifp) { |
| 750 | *ifap = ifa->if_next; | 752 | list_del_init(&ifp->if_list); |
| 751 | __in6_ifa_put(ifp); | 753 | __in6_ifa_put(ifp); |
| 752 | ifa->if_next = NULL; | 754 | |
| 753 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 755 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
| 754 | break; | 756 | break; |
| 755 | deleted = 1; | 757 | deleted = 1; |
| @@ -782,7 +784,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
| 782 | } | 784 | } |
| 783 | } | 785 | } |
| 784 | } | 786 | } |
| 785 | ifap = &ifa->if_next; | ||
| 786 | } | 787 | } |
| 787 | write_unlock_bh(&idev->lock); | 788 | write_unlock_bh(&idev->lock); |
| 788 | 789 | ||
| @@ -823,9 +824,10 @@ 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 | ||
| 830 | out: | ||
| 829 | in6_ifa_put(ifp); | 831 | in6_ifa_put(ifp); |
| 830 | } | 832 | } |
| 831 | 833 | ||
| @@ -889,7 +891,8 @@ retry: | |||
| 889 | idev->cnf.temp_valid_lft); | 891 | idev->cnf.temp_valid_lft); |
| 890 | tmp_prefered_lft = min_t(__u32, | 892 | tmp_prefered_lft = min_t(__u32, |
| 891 | ifp->prefered_lft, | 893 | ifp->prefered_lft, |
| 892 | idev->cnf.temp_prefered_lft - desync_factor / HZ); | 894 | idev->cnf.temp_prefered_lft - |
| 895 | idev->cnf.max_desync_factor); | ||
| 893 | tmp_plen = ifp->prefix_len; | 896 | tmp_plen = ifp->prefix_len; |
| 894 | max_addresses = idev->cnf.max_addresses; | 897 | max_addresses = idev->cnf.max_addresses; |
| 895 | tmp_cstamp = ifp->cstamp; | 898 | tmp_cstamp = ifp->cstamp; |
| @@ -989,8 +992,7 @@ struct ipv6_saddr_dst { | |||
| 989 | 992 | ||
| 990 | static inline int ipv6_saddr_preferred(int type) | 993 | static inline int ipv6_saddr_preferred(int type) |
| 991 | { | 994 | { |
| 992 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| | 995 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|IPV6_ADDR_LOOPBACK)) |
| 993 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) | ||
| 994 | return 1; | 996 | return 1; |
| 995 | return 0; | 997 | return 0; |
| 996 | } | 998 | } |
| @@ -1162,7 +1164,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
| 1162 | continue; | 1164 | continue; |
| 1163 | 1165 | ||
| 1164 | read_lock_bh(&idev->lock); | 1166 | read_lock_bh(&idev->lock); |
| 1165 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { | 1167 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { |
| 1166 | int i; | 1168 | int i; |
| 1167 | 1169 | ||
| 1168 | /* | 1170 | /* |
| @@ -1240,7 +1242,6 @@ try_nextdev: | |||
| 1240 | in6_ifa_put(hiscore->ifa); | 1242 | in6_ifa_put(hiscore->ifa); |
| 1241 | return 0; | 1243 | return 0; |
| 1242 | } | 1244 | } |
| 1243 | |||
| 1244 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1245 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
| 1245 | 1246 | ||
| 1246 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1247 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
| @@ -1250,12 +1251,14 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
| 1250 | int err = -EADDRNOTAVAIL; | 1251 | int err = -EADDRNOTAVAIL; |
| 1251 | 1252 | ||
| 1252 | rcu_read_lock(); | 1253 | rcu_read_lock(); |
| 1253 | if ((idev = __in6_dev_get(dev)) != NULL) { | 1254 | idev = __in6_dev_get(dev); |
| 1255 | if (idev) { | ||
| 1254 | struct inet6_ifaddr *ifp; | 1256 | struct inet6_ifaddr *ifp; |
| 1255 | 1257 | ||
| 1256 | read_lock_bh(&idev->lock); | 1258 | read_lock_bh(&idev->lock); |
| 1257 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1259 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
| 1258 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { | 1260 | if (ifp->scope == IFA_LINK && |
| 1261 | !(ifp->flags & banned_flags)) { | ||
| 1259 | ipv6_addr_copy(addr, &ifp->addr); | 1262 | ipv6_addr_copy(addr, &ifp->addr); |
| 1260 | err = 0; | 1263 | err = 0; |
| 1261 | break; | 1264 | break; |
| @@ -1273,7 +1276,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
| 1273 | struct inet6_ifaddr *ifp; | 1276 | struct inet6_ifaddr *ifp; |
| 1274 | 1277 | ||
| 1275 | read_lock_bh(&idev->lock); | 1278 | read_lock_bh(&idev->lock); |
| 1276 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) | 1279 | list_for_each_entry(ifp, &idev->addr_list, if_list) |
| 1277 | cnt++; | 1280 | cnt++; |
| 1278 | read_unlock_bh(&idev->lock); | 1281 | read_unlock_bh(&idev->lock); |
| 1279 | return cnt; | 1282 | return cnt; |
| @@ -1282,41 +1285,44 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
| 1282 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1285 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, |
| 1283 | struct net_device *dev, int strict) | 1286 | struct net_device *dev, int strict) |
| 1284 | { | 1287 | { |
| 1285 | struct inet6_ifaddr * ifp; | 1288 | struct inet6_ifaddr *ifp; |
| 1286 | u8 hash = ipv6_addr_hash(addr); | 1289 | struct hlist_node *node; |
| 1290 | unsigned int hash = ipv6_addr_hash(addr); | ||
| 1287 | 1291 | ||
| 1288 | read_lock_bh(&addrconf_hash_lock); | 1292 | rcu_read_lock_bh(); |
| 1289 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1293 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
| 1290 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1294 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 1291 | continue; | 1295 | continue; |
| 1292 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1296 | if (ipv6_addr_equal(&ifp->addr, addr) && |
| 1293 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1297 | !(ifp->flags&IFA_F_TENTATIVE) && |
| 1294 | if (dev == NULL || ifp->idev->dev == dev || | 1298 | (dev == NULL || ifp->idev->dev == dev || |
| 1295 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) | 1299 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) { |
| 1296 | break; | 1300 | rcu_read_unlock_bh(); |
| 1301 | return 1; | ||
| 1297 | } | 1302 | } |
| 1298 | } | 1303 | } |
| 1299 | read_unlock_bh(&addrconf_hash_lock); | 1304 | |
| 1300 | return ifp != NULL; | 1305 | rcu_read_unlock_bh(); |
| 1306 | return 0; | ||
| 1301 | } | 1307 | } |
| 1302 | EXPORT_SYMBOL(ipv6_chk_addr); | 1308 | EXPORT_SYMBOL(ipv6_chk_addr); |
| 1303 | 1309 | ||
| 1304 | static | 1310 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
| 1305 | int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1311 | struct net_device *dev) |
| 1306 | struct net_device *dev) | ||
| 1307 | { | 1312 | { |
| 1308 | struct inet6_ifaddr * ifp; | 1313 | unsigned int hash = ipv6_addr_hash(addr); |
| 1309 | u8 hash = ipv6_addr_hash(addr); | 1314 | struct inet6_ifaddr *ifp; |
| 1315 | struct hlist_node *node; | ||
| 1310 | 1316 | ||
| 1311 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1317 | hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
| 1312 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1318 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 1313 | continue; | 1319 | continue; |
| 1314 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1320 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
| 1315 | if (dev == NULL || ifp->idev->dev == dev) | 1321 | if (dev == NULL || ifp->idev->dev == dev) |
| 1316 | break; | 1322 | return true; |
| 1317 | } | 1323 | } |
| 1318 | } | 1324 | } |
| 1319 | return ifp != NULL; | 1325 | return false; |
| 1320 | } | 1326 | } |
| 1321 | 1327 | ||
| 1322 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1328 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
| @@ -1330,7 +1336,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
| 1330 | idev = __in6_dev_get(dev); | 1336 | idev = __in6_dev_get(dev); |
| 1331 | if (idev) { | 1337 | if (idev) { |
| 1332 | read_lock_bh(&idev->lock); | 1338 | read_lock_bh(&idev->lock); |
| 1333 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1339 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
| 1334 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | 1340 | onlink = ipv6_prefix_equal(addr, &ifa->addr, |
| 1335 | ifa->prefix_len); | 1341 | ifa->prefix_len); |
| 1336 | if (onlink) | 1342 | if (onlink) |
| @@ -1347,24 +1353,26 @@ EXPORT_SYMBOL(ipv6_chk_prefix); | |||
| 1347 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | 1353 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
| 1348 | struct net_device *dev, int strict) | 1354 | struct net_device *dev, int strict) |
| 1349 | { | 1355 | { |
| 1350 | struct inet6_ifaddr * ifp; | 1356 | struct inet6_ifaddr *ifp, *result = NULL; |
| 1351 | u8 hash = ipv6_addr_hash(addr); | 1357 | unsigned int hash = ipv6_addr_hash(addr); |
| 1358 | struct hlist_node *node; | ||
| 1352 | 1359 | ||
| 1353 | read_lock_bh(&addrconf_hash_lock); | 1360 | rcu_read_lock_bh(); |
| 1354 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1361 | hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
| 1355 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1362 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 1356 | continue; | 1363 | continue; |
| 1357 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1364 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
| 1358 | if (dev == NULL || ifp->idev->dev == dev || | 1365 | if (dev == NULL || ifp->idev->dev == dev || |
| 1359 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { | 1366 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { |
| 1367 | result = ifp; | ||
| 1360 | in6_ifa_hold(ifp); | 1368 | in6_ifa_hold(ifp); |
| 1361 | break; | 1369 | break; |
| 1362 | } | 1370 | } |
| 1363 | } | 1371 | } |
| 1364 | } | 1372 | } |
| 1365 | read_unlock_bh(&addrconf_hash_lock); | 1373 | rcu_read_unlock_bh(); |
| 1366 | 1374 | ||
| 1367 | return ifp; | 1375 | return result; |
| 1368 | } | 1376 | } |
| 1369 | 1377 | ||
| 1370 | /* Gets referenced address, destroys ifaddr */ | 1378 | /* Gets referenced address, destroys ifaddr */ |
| @@ -1378,6 +1386,8 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 1378 | if (dad_failed) | 1386 | if (dad_failed) |
| 1379 | ifp->flags |= IFA_F_DADFAILED; | 1387 | ifp->flags |= IFA_F_DADFAILED; |
| 1380 | spin_unlock_bh(&ifp->lock); | 1388 | spin_unlock_bh(&ifp->lock); |
| 1389 | if (dad_failed) | ||
| 1390 | ipv6_ifa_notify(0, ifp); | ||
| 1381 | in6_ifa_put(ifp); | 1391 | in6_ifa_put(ifp); |
| 1382 | #ifdef CONFIG_IPV6_PRIVACY | 1392 | #ifdef CONFIG_IPV6_PRIVACY |
| 1383 | } else if (ifp->flags&IFA_F_TEMPORARY) { | 1393 | } else if (ifp->flags&IFA_F_TEMPORARY) { |
| @@ -1398,10 +1408,27 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 1398 | ipv6_del_addr(ifp); | 1408 | ipv6_del_addr(ifp); |
| 1399 | } | 1409 | } |
| 1400 | 1410 | ||
| 1411 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | ||
| 1412 | { | ||
| 1413 | int err = -ENOENT; | ||
| 1414 | |||
| 1415 | spin_lock(&ifp->state_lock); | ||
| 1416 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | ||
| 1417 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
| 1418 | err = 0; | ||
| 1419 | } | ||
| 1420 | spin_unlock(&ifp->state_lock); | ||
| 1421 | |||
| 1422 | return err; | ||
| 1423 | } | ||
| 1424 | |||
| 1401 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1425 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
| 1402 | { | 1426 | { |
| 1403 | struct inet6_dev *idev = ifp->idev; | 1427 | struct inet6_dev *idev = ifp->idev; |
| 1404 | 1428 | ||
| 1429 | if (addrconf_dad_end(ifp)) | ||
| 1430 | return; | ||
| 1431 | |||
| 1405 | if (net_ratelimit()) | 1432 | if (net_ratelimit()) |
| 1406 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1433 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
| 1407 | ifp->idev->dev->name, &ifp->addr); | 1434 | ifp->idev->dev->name, &ifp->addr); |
| @@ -1565,7 +1592,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
| 1565 | struct inet6_ifaddr *ifp; | 1592 | struct inet6_ifaddr *ifp; |
| 1566 | 1593 | ||
| 1567 | read_lock_bh(&idev->lock); | 1594 | read_lock_bh(&idev->lock); |
| 1568 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1595 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
| 1569 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1596 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { |
| 1570 | memcpy(eui, ifp->addr.s6_addr+8, 8); | 1597 | memcpy(eui, ifp->addr.s6_addr+8, 8); |
| 1571 | err = 0; | 1598 | err = 0; |
| @@ -1625,7 +1652,8 @@ static void ipv6_regen_rndid(unsigned long data) | |||
| 1625 | 1652 | ||
| 1626 | expires = jiffies + | 1653 | expires = jiffies + |
| 1627 | idev->cnf.temp_prefered_lft * HZ - | 1654 | idev->cnf.temp_prefered_lft * HZ - |
| 1628 | 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; | ||
| 1629 | if (time_before(expires, jiffies)) { | 1657 | if (time_before(expires, jiffies)) { |
| 1630 | printk(KERN_WARNING | 1658 | printk(KERN_WARNING |
| 1631 | "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", |
| @@ -1733,8 +1761,12 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
| 1733 | 1761 | ||
| 1734 | ASSERT_RTNL(); | 1762 | ASSERT_RTNL(); |
| 1735 | 1763 | ||
| 1736 | if ((idev = ipv6_find_idev(dev)) == NULL) | 1764 | idev = ipv6_find_idev(dev); |
| 1737 | return NULL; | 1765 | if (!idev) |
| 1766 | return ERR_PTR(-ENOBUFS); | ||
| 1767 | |||
| 1768 | if (idev->cnf.disable_ipv6) | ||
| 1769 | return ERR_PTR(-EACCES); | ||
| 1738 | 1770 | ||
| 1739 | /* Add default multicast route */ | 1771 | /* Add default multicast route */ |
| 1740 | addrconf_add_mroute(dev); | 1772 | addrconf_add_mroute(dev); |
| @@ -1837,7 +1869,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1837 | dev, expires, flags); | 1869 | dev, expires, flags); |
| 1838 | } | 1870 | } |
| 1839 | if (rt) | 1871 | if (rt) |
| 1840 | dst_release(&rt->u.dst); | 1872 | dst_release(&rt->dst); |
| 1841 | } | 1873 | } |
| 1842 | 1874 | ||
| 1843 | /* Try to figure out our local address for this prefix */ | 1875 | /* Try to figure out our local address for this prefix */ |
| @@ -1966,7 +1998,7 @@ ok: | |||
| 1966 | #ifdef CONFIG_IPV6_PRIVACY | 1998 | #ifdef CONFIG_IPV6_PRIVACY |
| 1967 | read_lock_bh(&in6_dev->lock); | 1999 | read_lock_bh(&in6_dev->lock); |
| 1968 | /* update all temporary addresses in the list */ | 2000 | /* update all temporary addresses in the list */ |
| 1969 | for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) { | 2001 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { |
| 1970 | /* | 2002 | /* |
| 1971 | * When adjusting the lifetimes of an existing | 2003 | * When adjusting the lifetimes of an existing |
| 1972 | * temporary address, only lower the lifetimes. | 2004 | * temporary address, only lower the lifetimes. |
| @@ -2103,8 +2135,9 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
| 2103 | if (!dev) | 2135 | if (!dev) |
| 2104 | return -ENODEV; | 2136 | return -ENODEV; |
| 2105 | 2137 | ||
| 2106 | if ((idev = addrconf_add_dev(dev)) == NULL) | 2138 | idev = addrconf_add_dev(dev); |
| 2107 | return -ENOBUFS; | 2139 | if (IS_ERR(idev)) |
| 2140 | return PTR_ERR(idev); | ||
| 2108 | 2141 | ||
| 2109 | scope = ipv6_addr_scope(pfx); | 2142 | scope = ipv6_addr_scope(pfx); |
| 2110 | 2143 | ||
| @@ -2169,7 +2202,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
| 2169 | return -ENXIO; | 2202 | return -ENXIO; |
| 2170 | 2203 | ||
| 2171 | read_lock_bh(&idev->lock); | 2204 | read_lock_bh(&idev->lock); |
| 2172 | for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { | 2205 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
| 2173 | if (ifp->prefix_len == plen && | 2206 | if (ifp->prefix_len == plen && |
| 2174 | ipv6_addr_equal(pfx, &ifp->addr)) { | 2207 | ipv6_addr_equal(pfx, &ifp->addr)) { |
| 2175 | in6_ifa_hold(ifp); | 2208 | in6_ifa_hold(ifp); |
| @@ -2180,7 +2213,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
| 2180 | /* If the last address is deleted administratively, | 2213 | /* If the last address is deleted administratively, |
| 2181 | disable IPv6 on this interface. | 2214 | disable IPv6 on this interface. |
| 2182 | */ | 2215 | */ |
| 2183 | if (idev->addr_list == NULL) | 2216 | if (list_empty(&idev->addr_list)) |
| 2184 | addrconf_ifdown(idev->dev, 1); | 2217 | addrconf_ifdown(idev->dev, 1); |
| 2185 | return 0; | 2218 | return 0; |
| 2186 | } | 2219 | } |
| @@ -2351,7 +2384,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
| 2351 | } | 2384 | } |
| 2352 | 2385 | ||
| 2353 | idev = addrconf_add_dev(dev); | 2386 | idev = addrconf_add_dev(dev); |
| 2354 | if (idev == NULL) | 2387 | if (IS_ERR(idev)) |
| 2355 | return; | 2388 | return; |
| 2356 | 2389 | ||
| 2357 | memset(&addr, 0, sizeof(struct in6_addr)); | 2390 | memset(&addr, 0, sizeof(struct in6_addr)); |
| @@ -2441,7 +2474,8 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
| 2441 | 2474 | ||
| 2442 | ASSERT_RTNL(); | 2475 | ASSERT_RTNL(); |
| 2443 | 2476 | ||
| 2444 | if ((idev = addrconf_add_dev(dev)) == NULL) { | 2477 | idev = addrconf_add_dev(dev); |
| 2478 | if (IS_ERR(idev)) { | ||
| 2445 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2479 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
| 2446 | return; | 2480 | return; |
| 2447 | } | 2481 | } |
| @@ -2456,7 +2490,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2456 | int run_pending = 0; | 2490 | int run_pending = 0; |
| 2457 | int err; | 2491 | int err; |
| 2458 | 2492 | ||
| 2459 | switch(event) { | 2493 | switch (event) { |
| 2460 | case NETDEV_REGISTER: | 2494 | case NETDEV_REGISTER: |
| 2461 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2495 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
| 2462 | idev = ipv6_add_dev(dev); | 2496 | idev = ipv6_add_dev(dev); |
| @@ -2464,6 +2498,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2464 | return notifier_from_errno(-ENOMEM); | 2498 | return notifier_from_errno(-ENOMEM); |
| 2465 | } | 2499 | } |
| 2466 | break; | 2500 | break; |
| 2501 | |||
| 2467 | case NETDEV_UP: | 2502 | case NETDEV_UP: |
| 2468 | case NETDEV_CHANGE: | 2503 | case NETDEV_CHANGE: |
| 2469 | if (dev->flags & IFF_SLAVE) | 2504 | if (dev->flags & IFF_SLAVE) |
| @@ -2493,10 +2528,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2493 | } | 2528 | } |
| 2494 | 2529 | ||
| 2495 | if (idev) { | 2530 | if (idev) { |
| 2496 | if (idev->if_flags & IF_READY) { | 2531 | if (idev->if_flags & IF_READY) |
| 2497 | /* device is already configured. */ | 2532 | /* device is already configured. */ |
| 2498 | break; | 2533 | break; |
| 2499 | } | ||
| 2500 | idev->if_flags |= IF_READY; | 2534 | idev->if_flags |= IF_READY; |
| 2501 | } | 2535 | } |
| 2502 | 2536 | ||
| @@ -2508,7 +2542,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2508 | run_pending = 1; | 2542 | run_pending = 1; |
| 2509 | } | 2543 | } |
| 2510 | 2544 | ||
| 2511 | switch(dev->type) { | 2545 | switch (dev->type) { |
| 2512 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2546 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
| 2513 | case ARPHRD_SIT: | 2547 | case ARPHRD_SIT: |
| 2514 | addrconf_sit_config(dev); | 2548 | addrconf_sit_config(dev); |
| @@ -2525,25 +2559,30 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2525 | addrconf_dev_config(dev); | 2559 | addrconf_dev_config(dev); |
| 2526 | break; | 2560 | break; |
| 2527 | } | 2561 | } |
| 2562 | |||
| 2528 | if (idev) { | 2563 | if (idev) { |
| 2529 | if (run_pending) | 2564 | if (run_pending) |
| 2530 | addrconf_dad_run(idev); | 2565 | addrconf_dad_run(idev); |
| 2531 | 2566 | ||
| 2532 | /* If the MTU changed during the interface down, when the | 2567 | /* |
| 2533 | interface up, the changed MTU must be reflected in the | 2568 | * If the MTU changed during the interface down, |
| 2534 | idev as well as routers. | 2569 | * when the interface up, the changed MTU must be |
| 2570 | * reflected in the idev as well as routers. | ||
| 2535 | */ | 2571 | */ |
| 2536 | if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) { | 2572 | if (idev->cnf.mtu6 != dev->mtu && |
| 2573 | dev->mtu >= IPV6_MIN_MTU) { | ||
| 2537 | rt6_mtu_change(dev, dev->mtu); | 2574 | rt6_mtu_change(dev, dev->mtu); |
| 2538 | idev->cnf.mtu6 = dev->mtu; | 2575 | idev->cnf.mtu6 = dev->mtu; |
| 2539 | } | 2576 | } |
| 2540 | idev->tstamp = jiffies; | 2577 | idev->tstamp = jiffies; |
| 2541 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2578 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
| 2542 | /* If the changed mtu during down is lower than IPV6_MIN_MTU | 2579 | |
| 2543 | stop IPv6 on this interface. | 2580 | /* |
| 2581 | * If the changed mtu during down is lower than | ||
| 2582 | * IPV6_MIN_MTU stop IPv6 on this interface. | ||
| 2544 | */ | 2583 | */ |
| 2545 | if (dev->mtu < IPV6_MIN_MTU) | 2584 | if (dev->mtu < IPV6_MIN_MTU) |
| 2546 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2585 | addrconf_ifdown(dev, 1); |
| 2547 | } | 2586 | } |
| 2548 | break; | 2587 | break; |
| 2549 | 2588 | ||
| @@ -2560,7 +2599,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2560 | break; | 2599 | break; |
| 2561 | } | 2600 | } |
| 2562 | 2601 | ||
| 2563 | /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ | 2602 | /* |
| 2603 | * MTU falled under IPV6_MIN_MTU. | ||
| 2604 | * Stop IPv6 on this interface. | ||
| 2605 | */ | ||
| 2564 | 2606 | ||
| 2565 | case NETDEV_DOWN: | 2607 | case NETDEV_DOWN: |
| 2566 | case NETDEV_UNREGISTER: | 2608 | case NETDEV_UNREGISTER: |
| @@ -2580,9 +2622,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2580 | return notifier_from_errno(err); | 2622 | return notifier_from_errno(err); |
| 2581 | } | 2623 | } |
| 2582 | break; | 2624 | break; |
| 2583 | case NETDEV_BONDING_OLDTYPE: | 2625 | |
| 2584 | case NETDEV_BONDING_NEWTYPE: | 2626 | case NETDEV_PRE_TYPE_CHANGE: |
| 2585 | addrconf_bonding_change(dev, event); | 2627 | case NETDEV_POST_TYPE_CHANGE: |
| 2628 | addrconf_type_change(dev, event); | ||
| 2586 | break; | 2629 | break; |
| 2587 | } | 2630 | } |
| 2588 | 2631 | ||
| @@ -2594,28 +2637,28 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
| 2594 | */ | 2637 | */ |
| 2595 | static struct notifier_block ipv6_dev_notf = { | 2638 | static struct notifier_block ipv6_dev_notf = { |
| 2596 | .notifier_call = addrconf_notify, | 2639 | .notifier_call = addrconf_notify, |
| 2597 | .priority = 0 | ||
| 2598 | }; | 2640 | }; |
| 2599 | 2641 | ||
| 2600 | static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | 2642 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
| 2601 | { | 2643 | { |
| 2602 | struct inet6_dev *idev; | 2644 | struct inet6_dev *idev; |
| 2603 | ASSERT_RTNL(); | 2645 | ASSERT_RTNL(); |
| 2604 | 2646 | ||
| 2605 | idev = __in6_dev_get(dev); | 2647 | idev = __in6_dev_get(dev); |
| 2606 | 2648 | ||
| 2607 | if (event == NETDEV_BONDING_NEWTYPE) | 2649 | if (event == NETDEV_POST_TYPE_CHANGE) |
| 2608 | ipv6_mc_remap(idev); | 2650 | ipv6_mc_remap(idev); |
| 2609 | else if (event == NETDEV_BONDING_OLDTYPE) | 2651 | else if (event == NETDEV_PRE_TYPE_CHANGE) |
| 2610 | ipv6_mc_unmap(idev); | 2652 | ipv6_mc_unmap(idev); |
| 2611 | } | 2653 | } |
| 2612 | 2654 | ||
| 2613 | static int addrconf_ifdown(struct net_device *dev, int how) | 2655 | static int addrconf_ifdown(struct net_device *dev, int how) |
| 2614 | { | 2656 | { |
| 2615 | struct inet6_dev *idev; | ||
| 2616 | struct inet6_ifaddr *ifa, **bifa; | ||
| 2617 | struct net *net = dev_net(dev); | 2657 | struct net *net = dev_net(dev); |
| 2618 | int i; | 2658 | struct inet6_dev *idev; |
| 2659 | struct inet6_ifaddr *ifa; | ||
| 2660 | LIST_HEAD(keep_list); | ||
| 2661 | int state; | ||
| 2619 | 2662 | ||
| 2620 | ASSERT_RTNL(); | 2663 | ASSERT_RTNL(); |
| 2621 | 2664 | ||
| @@ -2626,8 +2669,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2626 | if (idev == NULL) | 2669 | if (idev == NULL) |
| 2627 | return -ENODEV; | 2670 | return -ENODEV; |
| 2628 | 2671 | ||
| 2629 | /* Step 1: remove reference to ipv6 device from parent device. | 2672 | /* |
| 2630 | Do not dev_put! | 2673 | * Step 1: remove reference to ipv6 device from parent device. |
| 2674 | * Do not dev_put! | ||
| 2631 | */ | 2675 | */ |
| 2632 | if (how) { | 2676 | if (how) { |
| 2633 | idev->dead = 1; | 2677 | idev->dead = 1; |
| @@ -2640,40 +2684,21 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2640 | 2684 | ||
| 2641 | } | 2685 | } |
| 2642 | 2686 | ||
| 2643 | /* Step 2: clear hash table */ | ||
| 2644 | for (i=0; i<IN6_ADDR_HSIZE; i++) { | ||
| 2645 | bifa = &inet6_addr_lst[i]; | ||
| 2646 | |||
| 2647 | write_lock_bh(&addrconf_hash_lock); | ||
| 2648 | while ((ifa = *bifa) != NULL) { | ||
| 2649 | if (ifa->idev == idev) { | ||
| 2650 | *bifa = ifa->lst_next; | ||
| 2651 | ifa->lst_next = NULL; | ||
| 2652 | addrconf_del_timer(ifa); | ||
| 2653 | in6_ifa_put(ifa); | ||
| 2654 | continue; | ||
| 2655 | } | ||
| 2656 | bifa = &ifa->lst_next; | ||
| 2657 | } | ||
| 2658 | write_unlock_bh(&addrconf_hash_lock); | ||
| 2659 | } | ||
| 2660 | |||
| 2661 | write_lock_bh(&idev->lock); | 2687 | write_lock_bh(&idev->lock); |
| 2662 | 2688 | ||
| 2663 | /* Step 3: clear flags for stateless addrconf */ | 2689 | /* Step 2: clear flags for stateless addrconf */ |
| 2664 | if (!how) | 2690 | if (!how) |
| 2665 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2691 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
| 2666 | 2692 | ||
| 2667 | /* Step 4: clear address list */ | ||
| 2668 | #ifdef CONFIG_IPV6_PRIVACY | 2693 | #ifdef CONFIG_IPV6_PRIVACY |
| 2669 | if (how && del_timer(&idev->regen_timer)) | 2694 | if (how && del_timer(&idev->regen_timer)) |
| 2670 | in6_dev_put(idev); | 2695 | in6_dev_put(idev); |
| 2671 | 2696 | ||
| 2672 | /* clear tempaddr list */ | 2697 | /* Step 3: clear tempaddr list */ |
| 2673 | while ((ifa = idev->tempaddr_list) != NULL) { | 2698 | while (!list_empty(&idev->tempaddr_list)) { |
| 2674 | idev->tempaddr_list = ifa->tmp_next; | 2699 | ifa = list_first_entry(&idev->tempaddr_list, |
| 2675 | ifa->tmp_next = NULL; | 2700 | struct inet6_ifaddr, tmp_list); |
| 2676 | ifa->dead = 1; | 2701 | list_del(&ifa->tmp_list); |
| 2677 | write_unlock_bh(&idev->lock); | 2702 | write_unlock_bh(&idev->lock); |
| 2678 | spin_lock_bh(&ifa->lock); | 2703 | spin_lock_bh(&ifa->lock); |
| 2679 | 2704 | ||
| @@ -2686,23 +2711,70 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2686 | write_lock_bh(&idev->lock); | 2711 | write_lock_bh(&idev->lock); |
| 2687 | } | 2712 | } |
| 2688 | #endif | 2713 | #endif |
| 2689 | while ((ifa = idev->addr_list) != NULL) { | 2714 | |
| 2690 | idev->addr_list = ifa->if_next; | 2715 | while (!list_empty(&idev->addr_list)) { |
| 2691 | ifa->if_next = NULL; | 2716 | ifa = list_first_entry(&idev->addr_list, |
| 2692 | ifa->dead = 1; | 2717 | struct inet6_ifaddr, if_list); |
| 2693 | addrconf_del_timer(ifa); | 2718 | addrconf_del_timer(ifa); |
| 2694 | write_unlock_bh(&idev->lock); | 2719 | |
| 2720 | /* If just doing link down, and address is permanent | ||
| 2721 | and not link-local, then retain it. */ | ||
| 2722 | if (!how && | ||
| 2723 | (ifa->flags&IFA_F_PERMANENT) && | ||
| 2724 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
| 2725 | list_move_tail(&ifa->if_list, &keep_list); | ||
| 2726 | |||
| 2727 | /* If not doing DAD on this address, just keep it. */ | ||
| 2728 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
| 2729 | idev->cnf.accept_dad <= 0 || | ||
| 2730 | (ifa->flags & IFA_F_NODAD)) | ||
| 2731 | continue; | ||
| 2732 | |||
| 2733 | /* If it was tentative already, no need to notify */ | ||
| 2734 | if (ifa->flags & IFA_F_TENTATIVE) | ||
| 2735 | continue; | ||
| 2736 | |||
| 2737 | /* Flag it for later restoration when link comes up */ | ||
| 2738 | ifa->flags |= IFA_F_TENTATIVE; | ||
| 2739 | ifa->state = INET6_IFADDR_STATE_DAD; | ||
| 2740 | |||
| 2741 | write_unlock_bh(&idev->lock); | ||
| 2742 | |||
| 2743 | in6_ifa_hold(ifa); | ||
| 2744 | } else { | ||
| 2745 | list_del(&ifa->if_list); | ||
| 2746 | |||
| 2747 | /* clear hash table */ | ||
| 2748 | spin_lock_bh(&addrconf_hash_lock); | ||
| 2749 | hlist_del_init_rcu(&ifa->addr_lst); | ||
| 2750 | spin_unlock_bh(&addrconf_hash_lock); | ||
| 2751 | |||
| 2752 | write_unlock_bh(&idev->lock); | ||
| 2753 | spin_lock_bh(&ifa->state_lock); | ||
| 2754 | state = ifa->state; | ||
| 2755 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
| 2756 | spin_unlock_bh(&ifa->state_lock); | ||
| 2757 | |||
| 2758 | if (state == INET6_IFADDR_STATE_DEAD) | ||
| 2759 | goto put_ifa; | ||
| 2760 | } | ||
| 2695 | 2761 | ||
| 2696 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2762 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
| 2697 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2763 | if (ifa->state == INET6_IFADDR_STATE_DEAD) |
| 2764 | atomic_notifier_call_chain(&inet6addr_chain, | ||
| 2765 | NETDEV_DOWN, ifa); | ||
| 2766 | |||
| 2767 | put_ifa: | ||
| 2698 | in6_ifa_put(ifa); | 2768 | in6_ifa_put(ifa); |
| 2699 | 2769 | ||
| 2700 | write_lock_bh(&idev->lock); | 2770 | write_lock_bh(&idev->lock); |
| 2701 | } | 2771 | } |
| 2772 | |||
| 2773 | list_splice(&keep_list, &idev->addr_list); | ||
| 2774 | |||
| 2702 | write_unlock_bh(&idev->lock); | 2775 | write_unlock_bh(&idev->lock); |
| 2703 | 2776 | ||
| 2704 | /* Step 5: Discard multicast list */ | 2777 | /* Step 5: Discard multicast list */ |
| 2705 | |||
| 2706 | if (how) | 2778 | if (how) |
| 2707 | ipv6_mc_destroy_dev(idev); | 2779 | ipv6_mc_destroy_dev(idev); |
| 2708 | else | 2780 | else |
| @@ -2710,8 +2782,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2710 | 2782 | ||
| 2711 | idev->tstamp = jiffies; | 2783 | idev->tstamp = jiffies; |
| 2712 | 2784 | ||
| 2713 | /* Shot the device (if unregistered) */ | 2785 | /* Last: Shot the device (if unregistered) */ |
| 2714 | |||
| 2715 | if (how) { | 2786 | if (how) { |
| 2716 | addrconf_sysctl_unregister(idev); | 2787 | addrconf_sysctl_unregister(idev); |
| 2717 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2788 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
| @@ -2724,28 +2795,29 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2724 | static void addrconf_rs_timer(unsigned long data) | 2795 | static void addrconf_rs_timer(unsigned long data) |
| 2725 | { | 2796 | { |
| 2726 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2797 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
| 2798 | struct inet6_dev *idev = ifp->idev; | ||
| 2727 | 2799 | ||
| 2728 | if (ifp->idev->cnf.forwarding) | 2800 | read_lock(&idev->lock); |
| 2801 | if (idev->dead || !(idev->if_flags & IF_READY)) | ||
| 2729 | goto out; | 2802 | goto out; |
| 2730 | 2803 | ||
| 2731 | if (ifp->idev->if_flags & IF_RA_RCVD) { | 2804 | if (idev->cnf.forwarding) |
| 2732 | /* | 2805 | goto out; |
| 2733 | * Announcement received after solicitation | 2806 | |
| 2734 | * was sent | 2807 | /* Announcement received after solicitation was sent */ |
| 2735 | */ | 2808 | if (idev->if_flags & IF_RA_RCVD) |
| 2736 | goto out; | 2809 | goto out; |
| 2737 | } | ||
| 2738 | 2810 | ||
| 2739 | spin_lock(&ifp->lock); | 2811 | spin_lock(&ifp->lock); |
| 2740 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2812 | if (ifp->probes++ < idev->cnf.rtr_solicits) { |
| 2741 | /* The wait after the last probe can be shorter */ | 2813 | /* The wait after the last probe can be shorter */ |
| 2742 | addrconf_mod_timer(ifp, AC_RS, | 2814 | addrconf_mod_timer(ifp, AC_RS, |
| 2743 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2815 | (ifp->probes == idev->cnf.rtr_solicits) ? |
| 2744 | ifp->idev->cnf.rtr_solicit_delay : | 2816 | idev->cnf.rtr_solicit_delay : |
| 2745 | ifp->idev->cnf.rtr_solicit_interval); | 2817 | idev->cnf.rtr_solicit_interval); |
| 2746 | spin_unlock(&ifp->lock); | 2818 | spin_unlock(&ifp->lock); |
| 2747 | 2819 | ||
| 2748 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 2820 | ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
| 2749 | } else { | 2821 | } else { |
| 2750 | spin_unlock(&ifp->lock); | 2822 | spin_unlock(&ifp->lock); |
| 2751 | /* | 2823 | /* |
| @@ -2753,10 +2825,11 @@ static void addrconf_rs_timer(unsigned long data) | |||
| 2753 | * assumption any longer. | 2825 | * assumption any longer. |
| 2754 | */ | 2826 | */ |
| 2755 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", | 2827 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", |
| 2756 | ifp->idev->dev->name); | 2828 | idev->dev->name); |
| 2757 | } | 2829 | } |
| 2758 | 2830 | ||
| 2759 | out: | 2831 | out: |
| 2832 | read_unlock(&idev->lock); | ||
| 2760 | in6_ifa_put(ifp); | 2833 | in6_ifa_put(ifp); |
| 2761 | } | 2834 | } |
| 2762 | 2835 | ||
| @@ -2787,16 +2860,16 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2787 | net_srandom(ifp->addr.s6_addr32[3]); | 2860 | net_srandom(ifp->addr.s6_addr32[3]); |
| 2788 | 2861 | ||
| 2789 | read_lock_bh(&idev->lock); | 2862 | read_lock_bh(&idev->lock); |
| 2790 | if (ifp->dead) | 2863 | spin_lock(&ifp->lock); |
| 2864 | if (ifp->state == INET6_IFADDR_STATE_DEAD) | ||
| 2791 | goto out; | 2865 | goto out; |
| 2792 | spin_lock_bh(&ifp->lock); | ||
| 2793 | 2866 | ||
| 2794 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2867 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
| 2795 | idev->cnf.accept_dad < 1 || | 2868 | idev->cnf.accept_dad < 1 || |
| 2796 | !(ifp->flags&IFA_F_TENTATIVE) || | 2869 | !(ifp->flags&IFA_F_TENTATIVE) || |
| 2797 | ifp->flags & IFA_F_NODAD) { | 2870 | ifp->flags & IFA_F_NODAD) { |
| 2798 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2871 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
| 2799 | spin_unlock_bh(&ifp->lock); | 2872 | spin_unlock(&ifp->lock); |
| 2800 | read_unlock_bh(&idev->lock); | 2873 | read_unlock_bh(&idev->lock); |
| 2801 | 2874 | ||
| 2802 | addrconf_dad_completed(ifp); | 2875 | addrconf_dad_completed(ifp); |
| @@ -2804,7 +2877,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2804 | } | 2877 | } |
| 2805 | 2878 | ||
| 2806 | if (!(idev->if_flags & IF_READY)) { | 2879 | if (!(idev->if_flags & IF_READY)) { |
| 2807 | spin_unlock_bh(&ifp->lock); | 2880 | spin_unlock(&ifp->lock); |
| 2808 | read_unlock_bh(&idev->lock); | 2881 | read_unlock_bh(&idev->lock); |
| 2809 | /* | 2882 | /* |
| 2810 | * If the device is not ready: | 2883 | * If the device is not ready: |
| @@ -2820,12 +2893,12 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2820 | * Optimistic nodes can start receiving | 2893 | * Optimistic nodes can start receiving |
| 2821 | * Frames right away | 2894 | * Frames right away |
| 2822 | */ | 2895 | */ |
| 2823 | if(ifp->flags & IFA_F_OPTIMISTIC) | 2896 | if (ifp->flags & IFA_F_OPTIMISTIC) |
| 2824 | ip6_ins_rt(ifp->rt); | 2897 | ip6_ins_rt(ifp->rt); |
| 2825 | 2898 | ||
| 2826 | addrconf_dad_kick(ifp); | 2899 | addrconf_dad_kick(ifp); |
| 2827 | spin_unlock_bh(&ifp->lock); | ||
| 2828 | out: | 2900 | out: |
| 2901 | spin_unlock(&ifp->lock); | ||
| 2829 | read_unlock_bh(&idev->lock); | 2902 | read_unlock_bh(&idev->lock); |
| 2830 | } | 2903 | } |
| 2831 | 2904 | ||
| @@ -2835,20 +2908,30 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2835 | struct inet6_dev *idev = ifp->idev; | 2908 | struct inet6_dev *idev = ifp->idev; |
| 2836 | struct in6_addr mcaddr; | 2909 | struct in6_addr mcaddr; |
| 2837 | 2910 | ||
| 2838 | read_lock_bh(&idev->lock); | 2911 | if (!ifp->probes && addrconf_dad_end(ifp)) |
| 2839 | if (idev->dead) { | 2912 | goto out; |
| 2840 | read_unlock_bh(&idev->lock); | 2913 | |
| 2914 | read_lock(&idev->lock); | ||
| 2915 | if (idev->dead || !(idev->if_flags & IF_READY)) { | ||
| 2916 | read_unlock(&idev->lock); | ||
| 2841 | goto out; | 2917 | goto out; |
| 2842 | } | 2918 | } |
| 2843 | spin_lock_bh(&ifp->lock); | 2919 | |
| 2920 | spin_lock(&ifp->lock); | ||
| 2921 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | ||
| 2922 | spin_unlock(&ifp->lock); | ||
| 2923 | read_unlock(&idev->lock); | ||
| 2924 | goto out; | ||
| 2925 | } | ||
| 2926 | |||
| 2844 | if (ifp->probes == 0) { | 2927 | if (ifp->probes == 0) { |
| 2845 | /* | 2928 | /* |
| 2846 | * DAD was successful | 2929 | * DAD was successful |
| 2847 | */ | 2930 | */ |
| 2848 | 2931 | ||
| 2849 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2932 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
| 2850 | spin_unlock_bh(&ifp->lock); | 2933 | spin_unlock(&ifp->lock); |
| 2851 | read_unlock_bh(&idev->lock); | 2934 | read_unlock(&idev->lock); |
| 2852 | 2935 | ||
| 2853 | addrconf_dad_completed(ifp); | 2936 | addrconf_dad_completed(ifp); |
| 2854 | 2937 | ||
| @@ -2857,8 +2940,8 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2857 | 2940 | ||
| 2858 | ifp->probes--; | 2941 | ifp->probes--; |
| 2859 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 2942 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); |
| 2860 | spin_unlock_bh(&ifp->lock); | 2943 | spin_unlock(&ifp->lock); |
| 2861 | read_unlock_bh(&idev->lock); | 2944 | read_unlock(&idev->lock); |
| 2862 | 2945 | ||
| 2863 | /* send a neighbour solicitation for our addr */ | 2946 | /* send a neighbour solicitation for our addr */ |
| 2864 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2947 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
| @@ -2869,7 +2952,7 @@ out: | |||
| 2869 | 2952 | ||
| 2870 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 2953 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
| 2871 | { | 2954 | { |
| 2872 | struct net_device * dev = ifp->idev->dev; | 2955 | struct net_device *dev = ifp->idev->dev; |
| 2873 | 2956 | ||
| 2874 | /* | 2957 | /* |
| 2875 | * Configure the address for reception. Now it is valid. | 2958 | * Configure the address for reception. Now it is valid. |
| @@ -2900,18 +2983,17 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
| 2900 | } | 2983 | } |
| 2901 | } | 2984 | } |
| 2902 | 2985 | ||
| 2903 | static void addrconf_dad_run(struct inet6_dev *idev) { | 2986 | static void addrconf_dad_run(struct inet6_dev *idev) |
| 2987 | { | ||
| 2904 | struct inet6_ifaddr *ifp; | 2988 | struct inet6_ifaddr *ifp; |
| 2905 | 2989 | ||
| 2906 | read_lock_bh(&idev->lock); | 2990 | read_lock_bh(&idev->lock); |
| 2907 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2991 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
| 2908 | spin_lock_bh(&ifp->lock); | 2992 | spin_lock(&ifp->lock); |
| 2909 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2993 | if (ifp->flags & IFA_F_TENTATIVE && |
| 2910 | spin_unlock_bh(&ifp->lock); | 2994 | ifp->state == INET6_IFADDR_STATE_DAD) |
| 2911 | continue; | 2995 | addrconf_dad_kick(ifp); |
| 2912 | } | 2996 | spin_unlock(&ifp->lock); |
| 2913 | spin_unlock_bh(&ifp->lock); | ||
| 2914 | addrconf_dad_kick(ifp); | ||
| 2915 | } | 2997 | } |
| 2916 | read_unlock_bh(&idev->lock); | 2998 | read_unlock_bh(&idev->lock); |
| 2917 | } | 2999 | } |
| @@ -2929,36 +3011,35 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
| 2929 | struct net *net = seq_file_net(seq); | 3011 | struct net *net = seq_file_net(seq); |
| 2930 | 3012 | ||
| 2931 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 3013 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
| 2932 | ifa = inet6_addr_lst[state->bucket]; | 3014 | struct hlist_node *n; |
| 2933 | 3015 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], | |
| 2934 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) | 3016 | addr_lst) |
| 2935 | ifa = ifa->lst_next; | 3017 | if (net_eq(dev_net(ifa->idev->dev), net)) |
| 2936 | if (ifa) | 3018 | return ifa; |
| 2937 | break; | ||
| 2938 | } | 3019 | } |
| 2939 | return ifa; | 3020 | return NULL; |
| 2940 | } | 3021 | } |
| 2941 | 3022 | ||
| 2942 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 3023 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, |
| 3024 | struct inet6_ifaddr *ifa) | ||
| 2943 | { | 3025 | { |
| 2944 | struct if6_iter_state *state = seq->private; | 3026 | struct if6_iter_state *state = seq->private; |
| 2945 | struct net *net = seq_file_net(seq); | 3027 | struct net *net = seq_file_net(seq); |
| 3028 | struct hlist_node *n = &ifa->addr_lst; | ||
| 2946 | 3029 | ||
| 2947 | ifa = ifa->lst_next; | 3030 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) |
| 2948 | try_again: | 3031 | if (net_eq(dev_net(ifa->idev->dev), net)) |
| 2949 | if (ifa) { | 3032 | return ifa; |
| 2950 | if (!net_eq(dev_net(ifa->idev->dev), net)) { | ||
| 2951 | ifa = ifa->lst_next; | ||
| 2952 | goto try_again; | ||
| 2953 | } | ||
| 2954 | } | ||
| 2955 | 3033 | ||
| 2956 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 3034 | while (++state->bucket < IN6_ADDR_HSIZE) { |
| 2957 | ifa = inet6_addr_lst[state->bucket]; | 3035 | hlist_for_each_entry_rcu_bh(ifa, n, |
| 2958 | goto try_again; | 3036 | &inet6_addr_lst[state->bucket], addr_lst) { |
| 3037 | if (net_eq(dev_net(ifa->idev->dev), net)) | ||
| 3038 | return ifa; | ||
| 3039 | } | ||
| 2959 | } | 3040 | } |
| 2960 | 3041 | ||
| 2961 | return ifa; | 3042 | return NULL; |
| 2962 | } | 3043 | } |
| 2963 | 3044 | ||
| 2964 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | 3045 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) |
| @@ -2966,15 +3047,15 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
| 2966 | struct inet6_ifaddr *ifa = if6_get_first(seq); | 3047 | struct inet6_ifaddr *ifa = if6_get_first(seq); |
| 2967 | 3048 | ||
| 2968 | if (ifa) | 3049 | if (ifa) |
| 2969 | while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) | 3050 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) |
| 2970 | --pos; | 3051 | --pos; |
| 2971 | return pos ? NULL : ifa; | 3052 | return pos ? NULL : ifa; |
| 2972 | } | 3053 | } |
| 2973 | 3054 | ||
| 2974 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3055 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
| 2975 | __acquires(addrconf_hash_lock) | 3056 | __acquires(rcu_bh) |
| 2976 | { | 3057 | { |
| 2977 | read_lock_bh(&addrconf_hash_lock); | 3058 | rcu_read_lock_bh(); |
| 2978 | return if6_get_idx(seq, *pos); | 3059 | return if6_get_idx(seq, *pos); |
| 2979 | } | 3060 | } |
| 2980 | 3061 | ||
| @@ -2988,9 +3069,9 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
| 2988 | } | 3069 | } |
| 2989 | 3070 | ||
| 2990 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3071 | static void if6_seq_stop(struct seq_file *seq, void *v) |
| 2991 | __releases(addrconf_hash_lock) | 3072 | __releases(rcu_bh) |
| 2992 | { | 3073 | { |
| 2993 | read_unlock_bh(&addrconf_hash_lock); | 3074 | rcu_read_unlock_bh(); |
| 2994 | } | 3075 | } |
| 2995 | 3076 | ||
| 2996 | static int if6_seq_show(struct seq_file *seq, void *v) | 3077 | static int if6_seq_show(struct seq_file *seq, void *v) |
| @@ -3027,14 +3108,14 @@ static const struct file_operations if6_fops = { | |||
| 3027 | .release = seq_release_net, | 3108 | .release = seq_release_net, |
| 3028 | }; | 3109 | }; |
| 3029 | 3110 | ||
| 3030 | static int if6_proc_net_init(struct net *net) | 3111 | static int __net_init if6_proc_net_init(struct net *net) |
| 3031 | { | 3112 | { |
| 3032 | if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) | 3113 | if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) |
| 3033 | return -ENOMEM; | 3114 | return -ENOMEM; |
| 3034 | return 0; | 3115 | return 0; |
| 3035 | } | 3116 | } |
| 3036 | 3117 | ||
| 3037 | static void if6_proc_net_exit(struct net *net) | 3118 | static void __net_exit if6_proc_net_exit(struct net *net) |
| 3038 | { | 3119 | { |
| 3039 | proc_net_remove(net, "if_inet6"); | 3120 | proc_net_remove(net, "if_inet6"); |
| 3040 | } | 3121 | } |
| @@ -3060,10 +3141,12 @@ void if6_proc_exit(void) | |||
| 3060 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3141 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) |
| 3061 | { | 3142 | { |
| 3062 | int ret = 0; | 3143 | int ret = 0; |
| 3063 | struct inet6_ifaddr * ifp; | 3144 | struct inet6_ifaddr *ifp = NULL; |
| 3064 | u8 hash = ipv6_addr_hash(addr); | 3145 | struct hlist_node *n; |
| 3065 | read_lock_bh(&addrconf_hash_lock); | 3146 | unsigned int hash = ipv6_addr_hash(addr); |
| 3066 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 3147 | |
| 3148 | rcu_read_lock_bh(); | ||
| 3149 | hlist_for_each_entry_rcu_bh(ifp, n, &inet6_addr_lst[hash], addr_lst) { | ||
| 3067 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3150 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
| 3068 | continue; | 3151 | continue; |
| 3069 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3152 | if (ipv6_addr_equal(&ifp->addr, addr) && |
| @@ -3072,7 +3155,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
| 3072 | break; | 3155 | break; |
| 3073 | } | 3156 | } |
| 3074 | } | 3157 | } |
| 3075 | read_unlock_bh(&addrconf_hash_lock); | 3158 | rcu_read_unlock_bh(); |
| 3076 | return ret; | 3159 | return ret; |
| 3077 | } | 3160 | } |
| 3078 | #endif | 3161 | #endif |
| @@ -3083,43 +3166,35 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
| 3083 | 3166 | ||
| 3084 | static void addrconf_verify(unsigned long foo) | 3167 | static void addrconf_verify(unsigned long foo) |
| 3085 | { | 3168 | { |
| 3169 | unsigned long now, next, next_sec, next_sched; | ||
| 3086 | struct inet6_ifaddr *ifp; | 3170 | struct inet6_ifaddr *ifp; |
| 3087 | unsigned long now, next; | 3171 | struct hlist_node *node; |
| 3088 | int i; | 3172 | int i; |
| 3089 | 3173 | ||
| 3090 | spin_lock_bh(&addrconf_verify_lock); | 3174 | rcu_read_lock_bh(); |
| 3175 | spin_lock(&addrconf_verify_lock); | ||
| 3091 | now = jiffies; | 3176 | now = jiffies; |
| 3092 | next = now + ADDR_CHECK_FREQUENCY; | 3177 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
| 3093 | 3178 | ||
| 3094 | del_timer(&addr_chk_timer); | 3179 | del_timer(&addr_chk_timer); |
| 3095 | 3180 | ||
| 3096 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 3181 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
| 3097 | |||
| 3098 | restart: | 3182 | restart: |
| 3099 | read_lock(&addrconf_hash_lock); | 3183 | hlist_for_each_entry_rcu_bh(ifp, node, |
| 3100 | for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { | 3184 | &inet6_addr_lst[i], addr_lst) { |
| 3101 | unsigned long age; | 3185 | unsigned long age; |
| 3102 | #ifdef CONFIG_IPV6_PRIVACY | ||
| 3103 | unsigned long regen_advance; | ||
| 3104 | #endif | ||
| 3105 | 3186 | ||
| 3106 | if (ifp->flags & IFA_F_PERMANENT) | 3187 | if (ifp->flags & IFA_F_PERMANENT) |
| 3107 | continue; | 3188 | continue; |
| 3108 | 3189 | ||
| 3109 | spin_lock(&ifp->lock); | 3190 | spin_lock(&ifp->lock); |
| 3110 | age = (now - ifp->tstamp) / HZ; | 3191 | /* We try to batch several events at once. */ |
| 3111 | 3192 | age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | |
| 3112 | #ifdef CONFIG_IPV6_PRIVACY | ||
| 3113 | regen_advance = ifp->idev->cnf.regen_max_retry * | ||
| 3114 | ifp->idev->cnf.dad_transmits * | ||
| 3115 | ifp->idev->nd_parms->retrans_time / HZ; | ||
| 3116 | #endif | ||
| 3117 | 3193 | ||
| 3118 | if (ifp->valid_lft != INFINITY_LIFE_TIME && | 3194 | if (ifp->valid_lft != INFINITY_LIFE_TIME && |
| 3119 | age >= ifp->valid_lft) { | 3195 | age >= ifp->valid_lft) { |
| 3120 | spin_unlock(&ifp->lock); | 3196 | spin_unlock(&ifp->lock); |
| 3121 | in6_ifa_hold(ifp); | 3197 | in6_ifa_hold(ifp); |
| 3122 | read_unlock(&addrconf_hash_lock); | ||
| 3123 | ipv6_del_addr(ifp); | 3198 | ipv6_del_addr(ifp); |
| 3124 | goto restart; | 3199 | goto restart; |
| 3125 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { | 3200 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { |
| @@ -3141,7 +3216,6 @@ restart: | |||
| 3141 | 3216 | ||
| 3142 | if (deprecate) { | 3217 | if (deprecate) { |
| 3143 | in6_ifa_hold(ifp); | 3218 | in6_ifa_hold(ifp); |
| 3144 | read_unlock(&addrconf_hash_lock); | ||
| 3145 | 3219 | ||
| 3146 | ipv6_ifa_notify(0, ifp); | 3220 | ipv6_ifa_notify(0, ifp); |
| 3147 | in6_ifa_put(ifp); | 3221 | in6_ifa_put(ifp); |
| @@ -3150,6 +3224,10 @@ restart: | |||
| 3150 | #ifdef CONFIG_IPV6_PRIVACY | 3224 | #ifdef CONFIG_IPV6_PRIVACY |
| 3151 | } else if ((ifp->flags&IFA_F_TEMPORARY) && | 3225 | } else if ((ifp->flags&IFA_F_TEMPORARY) && |
| 3152 | !(ifp->flags&IFA_F_TENTATIVE)) { | 3226 | !(ifp->flags&IFA_F_TENTATIVE)) { |
| 3227 | unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * | ||
| 3228 | ifp->idev->cnf.dad_transmits * | ||
| 3229 | ifp->idev->nd_parms->retrans_time / HZ; | ||
| 3230 | |||
| 3153 | if (age >= ifp->prefered_lft - regen_advance) { | 3231 | if (age >= ifp->prefered_lft - regen_advance) { |
| 3154 | struct inet6_ifaddr *ifpub = ifp->ifpub; | 3232 | struct inet6_ifaddr *ifpub = ifp->ifpub; |
| 3155 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) | 3233 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) |
| @@ -3159,7 +3237,7 @@ restart: | |||
| 3159 | in6_ifa_hold(ifp); | 3237 | in6_ifa_hold(ifp); |
| 3160 | in6_ifa_hold(ifpub); | 3238 | in6_ifa_hold(ifpub); |
| 3161 | spin_unlock(&ifp->lock); | 3239 | spin_unlock(&ifp->lock); |
| 3162 | read_unlock(&addrconf_hash_lock); | 3240 | |
| 3163 | spin_lock(&ifpub->lock); | 3241 | spin_lock(&ifpub->lock); |
| 3164 | ifpub->regen_count = 0; | 3242 | ifpub->regen_count = 0; |
| 3165 | spin_unlock(&ifpub->lock); | 3243 | spin_unlock(&ifpub->lock); |
| @@ -3179,12 +3257,26 @@ restart: | |||
| 3179 | spin_unlock(&ifp->lock); | 3257 | spin_unlock(&ifp->lock); |
| 3180 | } | 3258 | } |
| 3181 | } | 3259 | } |
| 3182 | read_unlock(&addrconf_hash_lock); | ||
| 3183 | } | 3260 | } |
| 3184 | 3261 | ||
| 3185 | addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; | 3262 | next_sec = round_jiffies_up(next); |
| 3263 | next_sched = next; | ||
| 3264 | |||
| 3265 | /* If rounded timeout is accurate enough, accept it. */ | ||
| 3266 | if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) | ||
| 3267 | next_sched = next_sec; | ||
| 3268 | |||
| 3269 | /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ | ||
| 3270 | if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX)) | ||
| 3271 | next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX; | ||
| 3272 | |||
| 3273 | ADBG((KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | ||
| 3274 | now, next, next_sec, next_sched)); | ||
| 3275 | |||
| 3276 | addr_chk_timer.expires = next_sched; | ||
| 3186 | add_timer(&addr_chk_timer); | 3277 | add_timer(&addr_chk_timer); |
| 3187 | spin_unlock_bh(&addrconf_verify_lock); | 3278 | spin_unlock(&addrconf_verify_lock); |
| 3279 | rcu_read_unlock_bh(); | ||
| 3188 | } | 3280 | } |
| 3189 | 3281 | ||
| 3190 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3282 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) |
| @@ -3407,8 +3499,12 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
| 3407 | preferred -= tval; | 3499 | preferred -= tval; |
| 3408 | else | 3500 | else |
| 3409 | preferred = 0; | 3501 | preferred = 0; |
| 3410 | if (valid != INFINITY_LIFE_TIME) | 3502 | if (valid != INFINITY_LIFE_TIME) { |
| 3411 | valid -= tval; | 3503 | if (valid > tval) |
| 3504 | valid -= tval; | ||
| 3505 | else | ||
| 3506 | valid = 0; | ||
| 3507 | } | ||
| 3412 | } | 3508 | } |
| 3413 | } else { | 3509 | } else { |
| 3414 | preferred = INFINITY_LIFE_TIME; | 3510 | preferred = INFINITY_LIFE_TIME; |
| @@ -3474,8 +3570,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
| 3474 | return nlmsg_end(skb, nlh); | 3570 | return nlmsg_end(skb, nlh); |
| 3475 | } | 3571 | } |
| 3476 | 3572 | ||
| 3477 | enum addr_type_t | 3573 | enum addr_type_t { |
| 3478 | { | ||
| 3479 | UNICAST_ADDR, | 3574 | UNICAST_ADDR, |
| 3480 | MULTICAST_ADDR, | 3575 | MULTICAST_ADDR, |
| 3481 | ANYCAST_ADDR, | 3576 | ANYCAST_ADDR, |
| @@ -3486,7 +3581,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
| 3486 | struct netlink_callback *cb, enum addr_type_t type, | 3581 | struct netlink_callback *cb, enum addr_type_t type, |
| 3487 | int s_ip_idx, int *p_ip_idx) | 3582 | int s_ip_idx, int *p_ip_idx) |
| 3488 | { | 3583 | { |
| 3489 | struct inet6_ifaddr *ifa; | ||
| 3490 | struct ifmcaddr6 *ifmca; | 3584 | struct ifmcaddr6 *ifmca; |
| 3491 | struct ifacaddr6 *ifaca; | 3585 | struct ifacaddr6 *ifaca; |
| 3492 | int err = 1; | 3586 | int err = 1; |
| @@ -3494,11 +3588,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
| 3494 | 3588 | ||
| 3495 | read_lock_bh(&idev->lock); | 3589 | read_lock_bh(&idev->lock); |
| 3496 | switch (type) { | 3590 | switch (type) { |
| 3497 | case UNICAST_ADDR: | 3591 | case UNICAST_ADDR: { |
| 3592 | struct inet6_ifaddr *ifa; | ||
| 3593 | |||
| 3498 | /* unicast address incl. temp addr */ | 3594 | /* unicast address incl. temp addr */ |
| 3499 | for (ifa = idev->addr_list; ifa; | 3595 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
| 3500 | ifa = ifa->if_next, ip_idx++) { | 3596 | if (++ip_idx < s_ip_idx) |
| 3501 | if (ip_idx < s_ip_idx) | ||
| 3502 | continue; | 3597 | continue; |
| 3503 | err = inet6_fill_ifaddr(skb, ifa, | 3598 | err = inet6_fill_ifaddr(skb, ifa, |
| 3504 | NETLINK_CB(cb->skb).pid, | 3599 | NETLINK_CB(cb->skb).pid, |
| @@ -3509,6 +3604,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
| 3509 | break; | 3604 | break; |
| 3510 | } | 3605 | } |
| 3511 | break; | 3606 | break; |
| 3607 | } | ||
| 3512 | case MULTICAST_ADDR: | 3608 | case MULTICAST_ADDR: |
| 3513 | /* multicast address */ | 3609 | /* multicast address */ |
| 3514 | for (ifmca = idev->mc_list; ifmca; | 3610 | for (ifmca = idev->mc_list; ifmca; |
| @@ -3570,10 +3666,11 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 3570 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { | 3666 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
| 3571 | if (idx < s_idx) | 3667 | if (idx < s_idx) |
| 3572 | goto cont; | 3668 | goto cont; |
| 3573 | if (idx > s_idx) | 3669 | if (h > s_h || idx > s_idx) |
| 3574 | s_ip_idx = 0; | 3670 | s_ip_idx = 0; |
| 3575 | ip_idx = 0; | 3671 | ip_idx = 0; |
| 3576 | if ((idev = __in6_dev_get(dev)) == NULL) | 3672 | idev = __in6_dev_get(dev); |
| 3673 | if (!idev) | ||
| 3577 | goto cont; | 3674 | goto cont; |
| 3578 | 3675 | ||
| 3579 | if (in6_dump_addrs(idev, skb, cb, type, | 3676 | if (in6_dump_addrs(idev, skb, cb, type, |
| @@ -3640,12 +3737,14 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
| 3640 | if (ifm->ifa_index) | 3737 | if (ifm->ifa_index) |
| 3641 | dev = __dev_get_by_index(net, ifm->ifa_index); | 3738 | dev = __dev_get_by_index(net, ifm->ifa_index); |
| 3642 | 3739 | ||
| 3643 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3740 | ifa = ipv6_get_ifaddr(net, addr, dev, 1); |
| 3741 | if (!ifa) { | ||
| 3644 | err = -EADDRNOTAVAIL; | 3742 | err = -EADDRNOTAVAIL; |
| 3645 | goto errout; | 3743 | goto errout; |
| 3646 | } | 3744 | } |
| 3647 | 3745 | ||
| 3648 | if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { | 3746 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); |
| 3747 | if (!skb) { | ||
| 3649 | err = -ENOBUFS; | 3748 | err = -ENOBUFS; |
| 3650 | goto errout_ifa; | 3749 | goto errout_ifa; |
| 3651 | } | 3750 | } |
| @@ -3752,8 +3851,8 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
| 3752 | ); | 3851 | ); |
| 3753 | } | 3852 | } |
| 3754 | 3853 | ||
| 3755 | static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | 3854 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, |
| 3756 | int bytes) | 3855 | int items, int bytes) |
| 3757 | { | 3856 | { |
| 3758 | int i; | 3857 | int i; |
| 3759 | int pad = bytes - sizeof(u64) * items; | 3858 | int pad = bytes - sizeof(u64) * items; |
| @@ -3767,15 +3866,31 @@ static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | |||
| 3767 | memset(&stats[items], 0, pad); | 3866 | memset(&stats[items], 0, pad); |
| 3768 | } | 3867 | } |
| 3769 | 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 | |||
| 3770 | 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, |
| 3771 | int bytes) | 3885 | int bytes) |
| 3772 | { | 3886 | { |
| 3773 | switch(attrtype) { | 3887 | switch (attrtype) { |
| 3774 | case IFLA_INET6_STATS: | 3888 | case IFLA_INET6_STATS: |
| 3775 | __snmp6_fill_stats(stats, (void **)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)); | ||
| 3776 | break; | 3891 | break; |
| 3777 | case IFLA_INET6_ICMP6STATS: | 3892 | case IFLA_INET6_ICMP6STATS: |
| 3778 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3893 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
| 3779 | break; | 3894 | break; |
| 3780 | } | 3895 | } |
| 3781 | } | 3896 | } |
| @@ -4005,9 +4120,11 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
| 4005 | if (ifp->idev->cnf.forwarding) | 4120 | if (ifp->idev->cnf.forwarding) |
| 4006 | addrconf_leave_anycast(ifp); | 4121 | addrconf_leave_anycast(ifp); |
| 4007 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4122 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
| 4008 | dst_hold(&ifp->rt->u.dst); | 4123 | dst_hold(&ifp->rt->dst); |
| 4009 | if (ip6_del_rt(ifp->rt)) | 4124 | |
| 4010 | dst_free(&ifp->rt->u.dst); | 4125 | if (ifp->state == INET6_IFADDR_STATE_DEAD && |
| 4126 | ip6_del_rt(ifp->rt)) | ||
| 4127 | dst_free(&ifp->rt->dst); | ||
| 4011 | break; | 4128 | break; |
| 4012 | } | 4129 | } |
| 4013 | } | 4130 | } |
| @@ -4028,12 +4145,15 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, | |||
| 4028 | { | 4145 | { |
| 4029 | int *valp = ctl->data; | 4146 | int *valp = ctl->data; |
| 4030 | int val = *valp; | 4147 | int val = *valp; |
| 4148 | loff_t pos = *ppos; | ||
| 4031 | int ret; | 4149 | int ret; |
| 4032 | 4150 | ||
| 4033 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4151 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
| 4034 | 4152 | ||
| 4035 | if (write) | 4153 | if (write) |
| 4036 | ret = addrconf_fixup_forwarding(ctl, valp, val); | 4154 | ret = addrconf_fixup_forwarding(ctl, valp, val); |
| 4155 | if (ret) | ||
| 4156 | *ppos = pos; | ||
| 4037 | return ret; | 4157 | return ret; |
| 4038 | } | 4158 | } |
| 4039 | 4159 | ||
| @@ -4075,8 +4195,11 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | |||
| 4075 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) | 4195 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) |
| 4076 | return 0; | 4196 | return 0; |
| 4077 | 4197 | ||
| 4078 | if (!rtnl_trylock()) | 4198 | if (!rtnl_trylock()) { |
| 4199 | /* Restore the original values before restarting */ | ||
| 4200 | *p = old; | ||
| 4079 | return restart_syscall(); | 4201 | return restart_syscall(); |
| 4202 | } | ||
| 4080 | 4203 | ||
| 4081 | if (p == &net->ipv6.devconf_all->disable_ipv6) { | 4204 | if (p == &net->ipv6.devconf_all->disable_ipv6) { |
| 4082 | __s32 newf = net->ipv6.devconf_all->disable_ipv6; | 4205 | __s32 newf = net->ipv6.devconf_all->disable_ipv6; |
| @@ -4095,12 +4218,15 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, | |||
| 4095 | { | 4218 | { |
| 4096 | int *valp = ctl->data; | 4219 | int *valp = ctl->data; |
| 4097 | int val = *valp; | 4220 | int val = *valp; |
| 4221 | loff_t pos = *ppos; | ||
| 4098 | int ret; | 4222 | int ret; |
| 4099 | 4223 | ||
| 4100 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4224 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
| 4101 | 4225 | ||
| 4102 | if (write) | 4226 | if (write) |
| 4103 | ret = addrconf_disable_ipv6(ctl, valp, val); | 4227 | ret = addrconf_disable_ipv6(ctl, valp, val); |
| 4228 | if (ret) | ||
| 4229 | *ppos = pos; | ||
| 4104 | return ret; | 4230 | return ret; |
| 4105 | } | 4231 | } |
| 4106 | 4232 | ||
| @@ -4113,211 +4239,211 @@ static struct addrconf_sysctl_table | |||
| 4113 | .sysctl_header = NULL, | 4239 | .sysctl_header = NULL, |
| 4114 | .addrconf_vars = { | 4240 | .addrconf_vars = { |
| 4115 | { | 4241 | { |
| 4116 | .procname = "forwarding", | 4242 | .procname = "forwarding", |
| 4117 | .data = &ipv6_devconf.forwarding, | 4243 | .data = &ipv6_devconf.forwarding, |
| 4118 | .maxlen = sizeof(int), | 4244 | .maxlen = sizeof(int), |
| 4119 | .mode = 0644, | 4245 | .mode = 0644, |
| 4120 | .proc_handler = addrconf_sysctl_forward, | 4246 | .proc_handler = addrconf_sysctl_forward, |
| 4121 | }, | 4247 | }, |
| 4122 | { | 4248 | { |
| 4123 | .procname = "hop_limit", | 4249 | .procname = "hop_limit", |
| 4124 | .data = &ipv6_devconf.hop_limit, | 4250 | .data = &ipv6_devconf.hop_limit, |
| 4125 | .maxlen = sizeof(int), | 4251 | .maxlen = sizeof(int), |
| 4126 | .mode = 0644, | 4252 | .mode = 0644, |
| 4127 | .proc_handler = proc_dointvec, | 4253 | .proc_handler = proc_dointvec, |
| 4128 | }, | 4254 | }, |
| 4129 | { | 4255 | { |
| 4130 | .procname = "mtu", | 4256 | .procname = "mtu", |
| 4131 | .data = &ipv6_devconf.mtu6, | 4257 | .data = &ipv6_devconf.mtu6, |
| 4132 | .maxlen = sizeof(int), | 4258 | .maxlen = sizeof(int), |
| 4133 | .mode = 0644, | 4259 | .mode = 0644, |
| 4134 | .proc_handler = proc_dointvec, | 4260 | .proc_handler = proc_dointvec, |
| 4135 | }, | 4261 | }, |
| 4136 | { | 4262 | { |
| 4137 | .procname = "accept_ra", | 4263 | .procname = "accept_ra", |
| 4138 | .data = &ipv6_devconf.accept_ra, | 4264 | .data = &ipv6_devconf.accept_ra, |
| 4139 | .maxlen = sizeof(int), | 4265 | .maxlen = sizeof(int), |
| 4140 | .mode = 0644, | 4266 | .mode = 0644, |
| 4141 | .proc_handler = proc_dointvec, | 4267 | .proc_handler = proc_dointvec, |
| 4142 | }, | 4268 | }, |
| 4143 | { | 4269 | { |
| 4144 | .procname = "accept_redirects", | 4270 | .procname = "accept_redirects", |
| 4145 | .data = &ipv6_devconf.accept_redirects, | 4271 | .data = &ipv6_devconf.accept_redirects, |
| 4146 | .maxlen = sizeof(int), | 4272 | .maxlen = sizeof(int), |
| 4147 | .mode = 0644, | 4273 | .mode = 0644, |
| 4148 | .proc_handler = proc_dointvec, | 4274 | .proc_handler = proc_dointvec, |
| 4149 | }, | 4275 | }, |
| 4150 | { | 4276 | { |
| 4151 | .procname = "autoconf", | 4277 | .procname = "autoconf", |
| 4152 | .data = &ipv6_devconf.autoconf, | 4278 | .data = &ipv6_devconf.autoconf, |
| 4153 | .maxlen = sizeof(int), | 4279 | .maxlen = sizeof(int), |
| 4154 | .mode = 0644, | 4280 | .mode = 0644, |
| 4155 | .proc_handler = proc_dointvec, | 4281 | .proc_handler = proc_dointvec, |
| 4156 | }, | 4282 | }, |
| 4157 | { | 4283 | { |
| 4158 | .procname = "dad_transmits", | 4284 | .procname = "dad_transmits", |
| 4159 | .data = &ipv6_devconf.dad_transmits, | 4285 | .data = &ipv6_devconf.dad_transmits, |
| 4160 | .maxlen = sizeof(int), | 4286 | .maxlen = sizeof(int), |
| 4161 | .mode = 0644, | 4287 | .mode = 0644, |
| 4162 | .proc_handler = proc_dointvec, | 4288 | .proc_handler = proc_dointvec, |
| 4163 | }, | 4289 | }, |
| 4164 | { | 4290 | { |
| 4165 | .procname = "router_solicitations", | 4291 | .procname = "router_solicitations", |
| 4166 | .data = &ipv6_devconf.rtr_solicits, | 4292 | .data = &ipv6_devconf.rtr_solicits, |
| 4167 | .maxlen = sizeof(int), | 4293 | .maxlen = sizeof(int), |
| 4168 | .mode = 0644, | 4294 | .mode = 0644, |
| 4169 | .proc_handler = proc_dointvec, | 4295 | .proc_handler = proc_dointvec, |
| 4170 | }, | 4296 | }, |
| 4171 | { | 4297 | { |
| 4172 | .procname = "router_solicitation_interval", | 4298 | .procname = "router_solicitation_interval", |
| 4173 | .data = &ipv6_devconf.rtr_solicit_interval, | 4299 | .data = &ipv6_devconf.rtr_solicit_interval, |
| 4174 | .maxlen = sizeof(int), | 4300 | .maxlen = sizeof(int), |
| 4175 | .mode = 0644, | 4301 | .mode = 0644, |
| 4176 | .proc_handler = proc_dointvec_jiffies, | 4302 | .proc_handler = proc_dointvec_jiffies, |
| 4177 | }, | 4303 | }, |
| 4178 | { | 4304 | { |
| 4179 | .procname = "router_solicitation_delay", | 4305 | .procname = "router_solicitation_delay", |
| 4180 | .data = &ipv6_devconf.rtr_solicit_delay, | 4306 | .data = &ipv6_devconf.rtr_solicit_delay, |
| 4181 | .maxlen = sizeof(int), | 4307 | .maxlen = sizeof(int), |
| 4182 | .mode = 0644, | 4308 | .mode = 0644, |
| 4183 | .proc_handler = proc_dointvec_jiffies, | 4309 | .proc_handler = proc_dointvec_jiffies, |
| 4184 | }, | 4310 | }, |
| 4185 | { | 4311 | { |
| 4186 | .procname = "force_mld_version", | 4312 | .procname = "force_mld_version", |
| 4187 | .data = &ipv6_devconf.force_mld_version, | 4313 | .data = &ipv6_devconf.force_mld_version, |
| 4188 | .maxlen = sizeof(int), | 4314 | .maxlen = sizeof(int), |
| 4189 | .mode = 0644, | 4315 | .mode = 0644, |
| 4190 | .proc_handler = proc_dointvec, | 4316 | .proc_handler = proc_dointvec, |
| 4191 | }, | 4317 | }, |
| 4192 | #ifdef CONFIG_IPV6_PRIVACY | 4318 | #ifdef CONFIG_IPV6_PRIVACY |
| 4193 | { | 4319 | { |
| 4194 | .procname = "use_tempaddr", | 4320 | .procname = "use_tempaddr", |
| 4195 | .data = &ipv6_devconf.use_tempaddr, | 4321 | .data = &ipv6_devconf.use_tempaddr, |
| 4196 | .maxlen = sizeof(int), | 4322 | .maxlen = sizeof(int), |
| 4197 | .mode = 0644, | 4323 | .mode = 0644, |
| 4198 | .proc_handler = proc_dointvec, | 4324 | .proc_handler = proc_dointvec, |
| 4199 | }, | 4325 | }, |
| 4200 | { | 4326 | { |
| 4201 | .procname = "temp_valid_lft", | 4327 | .procname = "temp_valid_lft", |
| 4202 | .data = &ipv6_devconf.temp_valid_lft, | 4328 | .data = &ipv6_devconf.temp_valid_lft, |
| 4203 | .maxlen = sizeof(int), | 4329 | .maxlen = sizeof(int), |
| 4204 | .mode = 0644, | 4330 | .mode = 0644, |
| 4205 | .proc_handler = proc_dointvec, | 4331 | .proc_handler = proc_dointvec, |
| 4206 | }, | 4332 | }, |
| 4207 | { | 4333 | { |
| 4208 | .procname = "temp_prefered_lft", | 4334 | .procname = "temp_prefered_lft", |
| 4209 | .data = &ipv6_devconf.temp_prefered_lft, | 4335 | .data = &ipv6_devconf.temp_prefered_lft, |
| 4210 | .maxlen = sizeof(int), | 4336 | .maxlen = sizeof(int), |
| 4211 | .mode = 0644, | 4337 | .mode = 0644, |
| 4212 | .proc_handler = proc_dointvec, | 4338 | .proc_handler = proc_dointvec, |
| 4213 | }, | 4339 | }, |
| 4214 | { | 4340 | { |
| 4215 | .procname = "regen_max_retry", | 4341 | .procname = "regen_max_retry", |
| 4216 | .data = &ipv6_devconf.regen_max_retry, | 4342 | .data = &ipv6_devconf.regen_max_retry, |
| 4217 | .maxlen = sizeof(int), | 4343 | .maxlen = sizeof(int), |
| 4218 | .mode = 0644, | 4344 | .mode = 0644, |
| 4219 | .proc_handler = proc_dointvec, | 4345 | .proc_handler = proc_dointvec, |
| 4220 | }, | 4346 | }, |
| 4221 | { | 4347 | { |
| 4222 | .procname = "max_desync_factor", | 4348 | .procname = "max_desync_factor", |
| 4223 | .data = &ipv6_devconf.max_desync_factor, | 4349 | .data = &ipv6_devconf.max_desync_factor, |
| 4224 | .maxlen = sizeof(int), | 4350 | .maxlen = sizeof(int), |
| 4225 | .mode = 0644, | 4351 | .mode = 0644, |
| 4226 | .proc_handler = proc_dointvec, | 4352 | .proc_handler = proc_dointvec, |
| 4227 | }, | 4353 | }, |
| 4228 | #endif | 4354 | #endif |
| 4229 | { | 4355 | { |
| 4230 | .procname = "max_addresses", | 4356 | .procname = "max_addresses", |
| 4231 | .data = &ipv6_devconf.max_addresses, | 4357 | .data = &ipv6_devconf.max_addresses, |
| 4232 | .maxlen = sizeof(int), | 4358 | .maxlen = sizeof(int), |
| 4233 | .mode = 0644, | 4359 | .mode = 0644, |
| 4234 | .proc_handler = proc_dointvec, | 4360 | .proc_handler = proc_dointvec, |
| 4235 | }, | 4361 | }, |
| 4236 | { | 4362 | { |
| 4237 | .procname = "accept_ra_defrtr", | 4363 | .procname = "accept_ra_defrtr", |
| 4238 | .data = &ipv6_devconf.accept_ra_defrtr, | 4364 | .data = &ipv6_devconf.accept_ra_defrtr, |
| 4239 | .maxlen = sizeof(int), | 4365 | .maxlen = sizeof(int), |
| 4240 | .mode = 0644, | 4366 | .mode = 0644, |
| 4241 | .proc_handler = proc_dointvec, | 4367 | .proc_handler = proc_dointvec, |
| 4242 | }, | 4368 | }, |
| 4243 | { | 4369 | { |
| 4244 | .procname = "accept_ra_pinfo", | 4370 | .procname = "accept_ra_pinfo", |
| 4245 | .data = &ipv6_devconf.accept_ra_pinfo, | 4371 | .data = &ipv6_devconf.accept_ra_pinfo, |
| 4246 | .maxlen = sizeof(int), | 4372 | .maxlen = sizeof(int), |
| 4247 | .mode = 0644, | 4373 | .mode = 0644, |
| 4248 | .proc_handler = proc_dointvec, | 4374 | .proc_handler = proc_dointvec, |
| 4249 | }, | 4375 | }, |
| 4250 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4376 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| 4251 | { | 4377 | { |
| 4252 | .procname = "accept_ra_rtr_pref", | 4378 | .procname = "accept_ra_rtr_pref", |
| 4253 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4379 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
| 4254 | .maxlen = sizeof(int), | 4380 | .maxlen = sizeof(int), |
| 4255 | .mode = 0644, | 4381 | .mode = 0644, |
| 4256 | .proc_handler = proc_dointvec, | 4382 | .proc_handler = proc_dointvec, |
| 4257 | }, | 4383 | }, |
| 4258 | { | 4384 | { |
| 4259 | .procname = "router_probe_interval", | 4385 | .procname = "router_probe_interval", |
| 4260 | .data = &ipv6_devconf.rtr_probe_interval, | 4386 | .data = &ipv6_devconf.rtr_probe_interval, |
| 4261 | .maxlen = sizeof(int), | 4387 | .maxlen = sizeof(int), |
| 4262 | .mode = 0644, | 4388 | .mode = 0644, |
| 4263 | .proc_handler = proc_dointvec_jiffies, | 4389 | .proc_handler = proc_dointvec_jiffies, |
| 4264 | }, | 4390 | }, |
| 4265 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4391 | #ifdef CONFIG_IPV6_ROUTE_INFO |
| 4266 | { | 4392 | { |
| 4267 | .procname = "accept_ra_rt_info_max_plen", | 4393 | .procname = "accept_ra_rt_info_max_plen", |
| 4268 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4394 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
| 4269 | .maxlen = sizeof(int), | 4395 | .maxlen = sizeof(int), |
| 4270 | .mode = 0644, | 4396 | .mode = 0644, |
| 4271 | .proc_handler = proc_dointvec, | 4397 | .proc_handler = proc_dointvec, |
| 4272 | }, | 4398 | }, |
| 4273 | #endif | 4399 | #endif |
| 4274 | #endif | 4400 | #endif |
| 4275 | { | 4401 | { |
| 4276 | .procname = "proxy_ndp", | 4402 | .procname = "proxy_ndp", |
| 4277 | .data = &ipv6_devconf.proxy_ndp, | 4403 | .data = &ipv6_devconf.proxy_ndp, |
| 4278 | .maxlen = sizeof(int), | 4404 | .maxlen = sizeof(int), |
| 4279 | .mode = 0644, | 4405 | .mode = 0644, |
| 4280 | .proc_handler = proc_dointvec, | 4406 | .proc_handler = proc_dointvec, |
| 4281 | }, | 4407 | }, |
| 4282 | { | 4408 | { |
| 4283 | .procname = "accept_source_route", | 4409 | .procname = "accept_source_route", |
| 4284 | .data = &ipv6_devconf.accept_source_route, | 4410 | .data = &ipv6_devconf.accept_source_route, |
| 4285 | .maxlen = sizeof(int), | 4411 | .maxlen = sizeof(int), |
| 4286 | .mode = 0644, | 4412 | .mode = 0644, |
| 4287 | .proc_handler = proc_dointvec, | 4413 | .proc_handler = proc_dointvec, |
| 4288 | }, | 4414 | }, |
| 4289 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4415 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
| 4290 | { | 4416 | { |
| 4291 | .procname = "optimistic_dad", | 4417 | .procname = "optimistic_dad", |
| 4292 | .data = &ipv6_devconf.optimistic_dad, | 4418 | .data = &ipv6_devconf.optimistic_dad, |
| 4293 | .maxlen = sizeof(int), | 4419 | .maxlen = sizeof(int), |
| 4294 | .mode = 0644, | 4420 | .mode = 0644, |
| 4295 | .proc_handler = proc_dointvec, | 4421 | .proc_handler = proc_dointvec, |
| 4296 | 4422 | ||
| 4297 | }, | 4423 | }, |
| 4298 | #endif | 4424 | #endif |
| 4299 | #ifdef CONFIG_IPV6_MROUTE | 4425 | #ifdef CONFIG_IPV6_MROUTE |
| 4300 | { | 4426 | { |
| 4301 | .procname = "mc_forwarding", | 4427 | .procname = "mc_forwarding", |
| 4302 | .data = &ipv6_devconf.mc_forwarding, | 4428 | .data = &ipv6_devconf.mc_forwarding, |
| 4303 | .maxlen = sizeof(int), | 4429 | .maxlen = sizeof(int), |
| 4304 | .mode = 0444, | 4430 | .mode = 0444, |
| 4305 | .proc_handler = proc_dointvec, | 4431 | .proc_handler = proc_dointvec, |
| 4306 | }, | 4432 | }, |
| 4307 | #endif | 4433 | #endif |
| 4308 | { | 4434 | { |
| 4309 | .procname = "disable_ipv6", | 4435 | .procname = "disable_ipv6", |
| 4310 | .data = &ipv6_devconf.disable_ipv6, | 4436 | .data = &ipv6_devconf.disable_ipv6, |
| 4311 | .maxlen = sizeof(int), | 4437 | .maxlen = sizeof(int), |
| 4312 | .mode = 0644, | 4438 | .mode = 0644, |
| 4313 | .proc_handler = addrconf_sysctl_disable, | 4439 | .proc_handler = addrconf_sysctl_disable, |
| 4314 | }, | 4440 | }, |
| 4315 | { | 4441 | { |
| 4316 | .procname = "accept_dad", | 4442 | .procname = "accept_dad", |
| 4317 | .data = &ipv6_devconf.accept_dad, | 4443 | .data = &ipv6_devconf.accept_dad, |
| 4318 | .maxlen = sizeof(int), | 4444 | .maxlen = sizeof(int), |
| 4319 | .mode = 0644, | 4445 | .mode = 0644, |
| 4320 | .proc_handler = proc_dointvec, | 4446 | .proc_handler = proc_dointvec, |
| 4321 | }, | 4447 | }, |
| 4322 | { | 4448 | { |
| 4323 | .procname = "force_tllao", | 4449 | .procname = "force_tllao", |
| @@ -4353,8 +4479,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
| 4353 | if (t == NULL) | 4479 | if (t == NULL) |
| 4354 | goto out; | 4480 | goto out; |
| 4355 | 4481 | ||
| 4356 | for (i=0; t->addrconf_vars[i].data; i++) { | 4482 | for (i = 0; t->addrconf_vars[i].data; i++) { |
| 4357 | t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; | 4483 | t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; |
| 4358 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ | 4484 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ |
| 4359 | t->addrconf_vars[i].extra2 = net; | 4485 | t->addrconf_vars[i].extra2 = net; |
| 4360 | } | 4486 | } |
| @@ -4402,8 +4528,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
| 4402 | 4528 | ||
| 4403 | static void addrconf_sysctl_register(struct inet6_dev *idev) | 4529 | static void addrconf_sysctl_register(struct inet6_dev *idev) |
| 4404 | { | 4530 | { |
| 4405 | neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, | 4531 | neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6", |
| 4406 | NET_IPV6_NEIGH, "ipv6", | ||
| 4407 | &ndisc_ifinfo_sysctl_change); | 4532 | &ndisc_ifinfo_sysctl_change); |
| 4408 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 4533 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
| 4409 | idev, &idev->cnf); | 4534 | idev, &idev->cnf); |
| @@ -4418,7 +4543,7 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 4418 | 4543 | ||
| 4419 | #endif | 4544 | #endif |
| 4420 | 4545 | ||
| 4421 | static int addrconf_init_net(struct net *net) | 4546 | static int __net_init addrconf_init_net(struct net *net) |
| 4422 | { | 4547 | { |
| 4423 | int err; | 4548 | int err; |
| 4424 | struct ipv6_devconf *all, *dflt; | 4549 | struct ipv6_devconf *all, *dflt; |
| @@ -4467,7 +4592,7 @@ err_alloc_all: | |||
| 4467 | return err; | 4592 | return err; |
| 4468 | } | 4593 | } |
| 4469 | 4594 | ||
| 4470 | static void addrconf_exit_net(struct net *net) | 4595 | static void __net_exit addrconf_exit_net(struct net *net) |
| 4471 | { | 4596 | { |
| 4472 | #ifdef CONFIG_SYSCTL | 4597 | #ifdef CONFIG_SYSCTL |
| 4473 | __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); | 4598 | __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); |
| @@ -4492,14 +4617,12 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
| 4492 | { | 4617 | { |
| 4493 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4618 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
| 4494 | } | 4619 | } |
| 4495 | |||
| 4496 | EXPORT_SYMBOL(register_inet6addr_notifier); | 4620 | EXPORT_SYMBOL(register_inet6addr_notifier); |
| 4497 | 4621 | ||
| 4498 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4622 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
| 4499 | { | 4623 | { |
| 4500 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4624 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); |
| 4501 | } | 4625 | } |
| 4502 | |||
| 4503 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4626 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
| 4504 | 4627 | ||
| 4505 | /* | 4628 | /* |
| @@ -4508,15 +4631,18 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier); | |||
| 4508 | 4631 | ||
| 4509 | int __init addrconf_init(void) | 4632 | int __init addrconf_init(void) |
| 4510 | { | 4633 | { |
| 4511 | int err; | 4634 | int i, err; |
| 4512 | 4635 | ||
| 4513 | if ((err = ipv6_addr_label_init()) < 0) { | 4636 | err = ipv6_addr_label_init(); |
| 4514 | printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n", | 4637 | if (err < 0) { |
| 4515 | err); | 4638 | printk(KERN_CRIT "IPv6 Addrconf:" |
| 4516 | return err; | 4639 | " cannot initialize default policy table: %d.\n", err); |
| 4640 | goto out; | ||
| 4517 | } | 4641 | } |
| 4518 | 4642 | ||
| 4519 | register_pernet_subsys(&addrconf_ops); | 4643 | err = register_pernet_subsys(&addrconf_ops); |
| 4644 | if (err < 0) | ||
| 4645 | goto out_addrlabel; | ||
| 4520 | 4646 | ||
| 4521 | /* The addrconf netdev notifier requires that loopback_dev | 4647 | /* The addrconf netdev notifier requires that loopback_dev |
| 4522 | * has it's ipv6 private information allocated and setup | 4648 | * has it's ipv6 private information allocated and setup |
| @@ -4543,6 +4669,9 @@ int __init addrconf_init(void) | |||
| 4543 | if (err) | 4669 | if (err) |
| 4544 | goto errlo; | 4670 | goto errlo; |
| 4545 | 4671 | ||
| 4672 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
| 4673 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | ||
| 4674 | |||
| 4546 | register_netdevice_notifier(&ipv6_dev_notf); | 4675 | register_netdevice_notifier(&ipv6_dev_notf); |
| 4547 | 4676 | ||
| 4548 | addrconf_verify(0); | 4677 | addrconf_verify(0); |
| @@ -4565,18 +4694,20 @@ errout: | |||
| 4565 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4694 | unregister_netdevice_notifier(&ipv6_dev_notf); |
| 4566 | errlo: | 4695 | errlo: |
| 4567 | unregister_pernet_subsys(&addrconf_ops); | 4696 | unregister_pernet_subsys(&addrconf_ops); |
| 4568 | 4697 | out_addrlabel: | |
| 4698 | ipv6_addr_label_cleanup(); | ||
| 4699 | out: | ||
| 4569 | return err; | 4700 | return err; |
| 4570 | } | 4701 | } |
| 4571 | 4702 | ||
| 4572 | void addrconf_cleanup(void) | 4703 | void addrconf_cleanup(void) |
| 4573 | { | 4704 | { |
| 4574 | struct inet6_ifaddr *ifa; | ||
| 4575 | struct net_device *dev; | 4705 | struct net_device *dev; |
| 4576 | int i; | 4706 | int i; |
| 4577 | 4707 | ||
| 4578 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4708 | unregister_netdevice_notifier(&ipv6_dev_notf); |
| 4579 | unregister_pernet_subsys(&addrconf_ops); | 4709 | unregister_pernet_subsys(&addrconf_ops); |
| 4710 | ipv6_addr_label_cleanup(); | ||
| 4580 | 4711 | ||
| 4581 | rtnl_lock(); | 4712 | rtnl_lock(); |
| 4582 | 4713 | ||
| @@ -4591,20 +4722,10 @@ void addrconf_cleanup(void) | |||
| 4591 | /* | 4722 | /* |
| 4592 | * Check hash table. | 4723 | * Check hash table. |
| 4593 | */ | 4724 | */ |
| 4594 | write_lock_bh(&addrconf_hash_lock); | 4725 | spin_lock_bh(&addrconf_hash_lock); |
| 4595 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4726 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
| 4596 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4727 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
| 4597 | struct inet6_ifaddr *bifa; | 4728 | spin_unlock_bh(&addrconf_hash_lock); |
| 4598 | |||
| 4599 | bifa = ifa; | ||
| 4600 | ifa = ifa->lst_next; | ||
| 4601 | printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa); | ||
| 4602 | /* Do not free it; something is wrong. | ||
| 4603 | Now we can investigate it with debugger. | ||
| 4604 | */ | ||
| 4605 | } | ||
| 4606 | } | ||
| 4607 | write_unlock_bh(&addrconf_hash_lock); | ||
| 4608 | 4729 | ||
| 4609 | del_timer(&addr_chk_timer); | 4730 | del_timer(&addr_chk_timer); |
| 4610 | rtnl_unlock(); | 4731 | rtnl_unlock(); |
