diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-21 00:04:44 -0400 |
commit | f8965467f366fd18f01feafb5db10512d7b4422c (patch) | |
tree | 3706a9cd779859271ca61b85c63a1bc3f82d626e /net/ipv6/addrconf.c | |
parent | a26272e5200765691e67d6780e52b32498fdb659 (diff) | |
parent | 2ec8c6bb5d8f3a62a79f463525054bae1e3d4487 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1674 commits)
qlcnic: adding co maintainer
ixgbe: add support for active DA cables
ixgbe: dcb, do not tag tc_prio_control frames
ixgbe: fix ixgbe_tx_is_paused logic
ixgbe: always enable vlan strip/insert when DCB is enabled
ixgbe: remove some redundant code in setting FCoE FIP filter
ixgbe: fix wrong offset to fc_frame_header in ixgbe_fcoe_ddp
ixgbe: fix header len when unsplit packet overflows to data buffer
ipv6: Never schedule DAD timer on dead address
ipv6: Use POSTDAD state
ipv6: Use state_lock to protect ifa state
ipv6: Replace inet6_ifaddr->dead with state
cxgb4: notify upper drivers if the device is already up when they load
cxgb4: keep interrupts available when the ports are brought down
cxgb4: fix initial addition of MAC address
cnic: Return SPQ credit to bnx2x after ring setup and shutdown.
cnic: Convert cnic_local_flags to atomic ops.
can: Fix SJA1000 command register writes on SMP systems
bridge: fix build for CONFIG_SYSFS disabled
ARCNET: Limit com20020 PCI ID matches for SOHARD cards
...
Fix up various conflicts with pcmcia tree drivers/net/
{pcmcia/3c589_cs.c, wireless/orinoco/orinoco_cs.c and
wireless/orinoco/spectrum_cs.c} and feature removal
(Documentation/feature-removal-schedule.txt).
Also fix a non-content conflict due to pm_qos_requirement getting
renamed in the PM tree (now pm_qos_request) in net/mac80211/scan.c
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 886 |
1 files changed, 463 insertions, 423 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 413054f02aab..e1a698df5706 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -82,7 +82,7 @@ | |||
82 | #include <linux/random.h> | 82 | #include <linux/random.h> |
83 | #endif | 83 | #endif |
84 | 84 | ||
85 | #include <asm/uaccess.h> | 85 | #include <linux/uaccess.h> |
86 | #include <asm/unaligned.h> | 86 | #include <asm/unaligned.h> |
87 | 87 | ||
88 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
@@ -98,7 +98,11 @@ | |||
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF | 100 | #define INFINITY_LIFE_TIME 0xFFFFFFFF |
101 | #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) | ||
102 | 106 | ||
103 | #ifdef CONFIG_SYSCTL | 107 | #ifdef CONFIG_SYSCTL |
104 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 108 | static void addrconf_sysctl_register(struct inet6_dev *idev); |
@@ -127,8 +131,8 @@ static int ipv6_count_addresses(struct inet6_dev *idev); | |||
127 | /* | 131 | /* |
128 | * Configured unicast address hash table | 132 | * Configured unicast address hash table |
129 | */ | 133 | */ |
130 | static struct inet6_ifaddr *inet6_addr_lst[IN6_ADDR_HSIZE]; | 134 | static struct hlist_head inet6_addr_lst[IN6_ADDR_HSIZE]; |
131 | static DEFINE_RWLOCK(addrconf_hash_lock); | 135 | static DEFINE_SPINLOCK(addrconf_hash_lock); |
132 | 136 | ||
133 | static void addrconf_verify(unsigned long); | 137 | static void addrconf_verify(unsigned long); |
134 | 138 | ||
@@ -138,8 +142,8 @@ static DEFINE_SPINLOCK(addrconf_verify_lock); | |||
138 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); | 142 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp); |
139 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); | 143 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp); |
140 | 144 | ||
141 | static void addrconf_bonding_change(struct net_device *dev, | 145 | static void addrconf_type_change(struct net_device *dev, |
142 | unsigned long event); | 146 | unsigned long event); |
143 | static int addrconf_ifdown(struct net_device *dev, int how); | 147 | static int addrconf_ifdown(struct net_device *dev, int how); |
144 | 148 | ||
145 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); | 149 | static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags); |
@@ -152,8 +156,8 @@ static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifa); | |||
152 | 156 | ||
153 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 157 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
154 | struct prefix_info *pinfo); | 158 | struct prefix_info *pinfo); |
155 | static int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 159 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
156 | struct net_device *dev); | 160 | struct net_device *dev); |
157 | 161 | ||
158 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); | 162 | static ATOMIC_NOTIFIER_HEAD(inet6addr_chain); |
159 | 163 | ||
@@ -250,8 +254,7 @@ static void addrconf_del_timer(struct inet6_ifaddr *ifp) | |||
250 | __in6_ifa_put(ifp); | 254 | __in6_ifa_put(ifp); |
251 | } | 255 | } |
252 | 256 | ||
253 | enum addrconf_timer_t | 257 | enum addrconf_timer_t { |
254 | { | ||
255 | AC_NONE, | 258 | AC_NONE, |
256 | AC_DAD, | 259 | AC_DAD, |
257 | AC_RS, | 260 | AC_RS, |
@@ -271,7 +274,8 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
271 | case AC_RS: | 274 | case AC_RS: |
272 | ifp->timer.function = addrconf_rs_timer; | 275 | ifp->timer.function = addrconf_rs_timer; |
273 | break; | 276 | break; |
274 | default:; | 277 | default: |
278 | break; | ||
275 | } | 279 | } |
276 | ifp->timer.expires = jiffies + when; | 280 | ifp->timer.expires = jiffies + when; |
277 | add_timer(&ifp->timer); | 281 | add_timer(&ifp->timer); |
@@ -318,7 +322,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
318 | { | 322 | { |
319 | struct net_device *dev = idev->dev; | 323 | struct net_device *dev = idev->dev; |
320 | 324 | ||
321 | WARN_ON(idev->addr_list != NULL); | 325 | WARN_ON(!list_empty(&idev->addr_list)); |
322 | WARN_ON(idev->mc_list != NULL); | 326 | WARN_ON(idev->mc_list != NULL); |
323 | 327 | ||
324 | #ifdef NET_REFCNT_DEBUG | 328 | #ifdef NET_REFCNT_DEBUG |
@@ -326,7 +330,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev) | |||
326 | #endif | 330 | #endif |
327 | dev_put(dev); | 331 | dev_put(dev); |
328 | if (!idev->dead) { | 332 | if (!idev->dead) { |
329 | printk("Freeing alive inet6 device %p\n", idev); | 333 | pr_warning("Freeing alive inet6 device %p\n", idev); |
330 | return; | 334 | return; |
331 | } | 335 | } |
332 | snmp6_free_dev(idev); | 336 | snmp6_free_dev(idev); |
@@ -351,6 +355,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
351 | 355 | ||
352 | rwlock_init(&ndev->lock); | 356 | rwlock_init(&ndev->lock); |
353 | ndev->dev = dev; | 357 | ndev->dev = dev; |
358 | INIT_LIST_HEAD(&ndev->addr_list); | ||
359 | |||
354 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); | 360 | memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); |
355 | ndev->cnf.mtu6 = dev->mtu; | 361 | ndev->cnf.mtu6 = dev->mtu; |
356 | ndev->cnf.sysctl = NULL; | 362 | ndev->cnf.sysctl = NULL; |
@@ -402,6 +408,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
402 | #endif | 408 | #endif |
403 | 409 | ||
404 | #ifdef CONFIG_IPV6_PRIVACY | 410 | #ifdef CONFIG_IPV6_PRIVACY |
411 | INIT_LIST_HEAD(&ndev->tempaddr_list); | ||
405 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); | 412 | setup_timer(&ndev->regen_timer, ipv6_regen_rndid, (unsigned long)ndev); |
406 | if ((dev->flags&IFF_LOOPBACK) || | 413 | if ((dev->flags&IFF_LOOPBACK) || |
407 | dev->type == ARPHRD_TUNNEL || | 414 | dev->type == ARPHRD_TUNNEL || |
@@ -439,8 +446,10 @@ static struct inet6_dev * ipv6_find_idev(struct net_device *dev) | |||
439 | 446 | ||
440 | ASSERT_RTNL(); | 447 | ASSERT_RTNL(); |
441 | 448 | ||
442 | if ((idev = __in6_dev_get(dev)) == NULL) { | 449 | idev = __in6_dev_get(dev); |
443 | if ((idev = ipv6_add_dev(dev)) == NULL) | 450 | if (!idev) { |
451 | idev = ipv6_add_dev(dev); | ||
452 | if (!idev) | ||
444 | return NULL; | 453 | return NULL; |
445 | } | 454 | } |
446 | 455 | ||
@@ -466,7 +475,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
466 | else | 475 | else |
467 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); | 476 | ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); |
468 | } | 477 | } |
469 | for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { | 478 | |
479 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
470 | if (ifa->flags&IFA_F_TENTATIVE) | 480 | if (ifa->flags&IFA_F_TENTATIVE) |
471 | continue; | 481 | continue; |
472 | if (idev->cnf.forwarding) | 482 | if (idev->cnf.forwarding) |
@@ -523,12 +533,16 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
523 | } | 533 | } |
524 | #endif | 534 | #endif |
525 | 535 | ||
526 | /* Nobody refers to this ifaddr, destroy it */ | 536 | static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head) |
537 | { | ||
538 | struct inet6_ifaddr *ifp = container_of(head, struct inet6_ifaddr, rcu); | ||
539 | kfree(ifp); | ||
540 | } | ||
527 | 541 | ||
542 | /* Nobody refers to this ifaddr, destroy it */ | ||
528 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | 543 | void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) |
529 | { | 544 | { |
530 | WARN_ON(ifp->if_next != NULL); | 545 | WARN_ON(!hlist_unhashed(&ifp->addr_lst)); |
531 | WARN_ON(ifp->lst_next != NULL); | ||
532 | 546 | ||
533 | #ifdef NET_REFCNT_DEBUG | 547 | #ifdef NET_REFCNT_DEBUG |
534 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); | 548 | printk(KERN_DEBUG "inet6_ifa_finish_destroy\n"); |
@@ -537,54 +551,46 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) | |||
537 | in6_dev_put(ifp->idev); | 551 | in6_dev_put(ifp->idev); |
538 | 552 | ||
539 | if (del_timer(&ifp->timer)) | 553 | if (del_timer(&ifp->timer)) |
540 | printk("Timer is still running, when freeing ifa=%p\n", ifp); | 554 | pr_notice("Timer is still running, when freeing ifa=%p\n", ifp); |
541 | 555 | ||
542 | if (!ifp->dead) { | 556 | if (ifp->state != INET6_IFADDR_STATE_DEAD) { |
543 | printk("Freeing alive inet6 address %p\n", ifp); | 557 | pr_warning("Freeing alive inet6 address %p\n", ifp); |
544 | return; | 558 | return; |
545 | } | 559 | } |
546 | dst_release(&ifp->rt->u.dst); | 560 | dst_release(&ifp->rt->u.dst); |
547 | 561 | ||
548 | kfree(ifp); | 562 | call_rcu(&ifp->rcu, inet6_ifa_finish_destroy_rcu); |
549 | } | 563 | } |
550 | 564 | ||
551 | static void | 565 | static void |
552 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) | 566 | ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) |
553 | { | 567 | { |
554 | struct inet6_ifaddr *ifa, **ifap; | 568 | struct list_head *p; |
555 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); | 569 | int ifp_scope = ipv6_addr_src_scope(&ifp->addr); |
556 | 570 | ||
557 | /* | 571 | /* |
558 | * Each device address list is sorted in order of scope - | 572 | * Each device address list is sorted in order of scope - |
559 | * global before linklocal. | 573 | * global before linklocal. |
560 | */ | 574 | */ |
561 | for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; | 575 | list_for_each(p, &idev->addr_list) { |
562 | ifap = &ifa->if_next) { | 576 | struct inet6_ifaddr *ifa |
577 | = list_entry(p, struct inet6_ifaddr, if_list); | ||
563 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) | 578 | if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) |
564 | break; | 579 | break; |
565 | } | 580 | } |
566 | 581 | ||
567 | ifp->if_next = *ifap; | 582 | list_add_tail(&ifp->if_list, p); |
568 | *ifap = ifp; | ||
569 | } | 583 | } |
570 | 584 | ||
571 | /* | 585 | static u32 ipv6_addr_hash(const struct in6_addr *addr) |
572 | * Hash function taken from net_alias.c | ||
573 | */ | ||
574 | static u8 ipv6_addr_hash(const struct in6_addr *addr) | ||
575 | { | 586 | { |
576 | __u32 word; | ||
577 | |||
578 | /* | 587 | /* |
579 | * We perform the hash function over the last 64 bits of the address | 588 | * We perform the hash function over the last 64 bits of the address |
580 | * This will include the IEEE address token on links that support it. | 589 | * This will include the IEEE address token on links that support it. |
581 | */ | 590 | */ |
582 | 591 | return jhash_2words((__force u32)addr->s6_addr32[2], | |
583 | word = (__force u32)(addr->s6_addr32[2] ^ addr->s6_addr32[3]); | 592 | (__force u32)addr->s6_addr32[3], 0) |
584 | word ^= (word >> 16); | 593 | & (IN6_ADDR_HSIZE - 1); |
585 | word ^= (word >> 8); | ||
586 | |||
587 | return ((word ^ (word >> 4)) & 0x0f); | ||
588 | } | 594 | } |
589 | 595 | ||
590 | /* On success it returns ifp with increased reference count */ | 596 | /* On success it returns ifp with increased reference count */ |
@@ -595,7 +601,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
595 | { | 601 | { |
596 | struct inet6_ifaddr *ifa = NULL; | 602 | struct inet6_ifaddr *ifa = NULL; |
597 | struct rt6_info *rt; | 603 | struct rt6_info *rt; |
598 | int hash; | 604 | unsigned int hash; |
599 | int err = 0; | 605 | int err = 0; |
600 | int addr_type = ipv6_addr_type(addr); | 606 | int addr_type = ipv6_addr_type(addr); |
601 | 607 | ||
@@ -616,7 +622,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
616 | goto out2; | 622 | goto out2; |
617 | } | 623 | } |
618 | 624 | ||
619 | write_lock(&addrconf_hash_lock); | 625 | spin_lock(&addrconf_hash_lock); |
620 | 626 | ||
621 | /* Ignore adding duplicate addresses on an interface */ | 627 | /* Ignore adding duplicate addresses on an interface */ |
622 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { | 628 | if (ipv6_chk_same_addr(dev_net(idev->dev), addr, idev->dev)) { |
@@ -642,7 +648,9 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
642 | ipv6_addr_copy(&ifa->addr, addr); | 648 | ipv6_addr_copy(&ifa->addr, addr); |
643 | 649 | ||
644 | spin_lock_init(&ifa->lock); | 650 | spin_lock_init(&ifa->lock); |
651 | spin_lock_init(&ifa->state_lock); | ||
645 | init_timer(&ifa->timer); | 652 | init_timer(&ifa->timer); |
653 | INIT_HLIST_NODE(&ifa->addr_lst); | ||
646 | ifa->timer.data = (unsigned long) ifa; | 654 | ifa->timer.data = (unsigned long) ifa; |
647 | ifa->scope = scope; | 655 | ifa->scope = scope; |
648 | ifa->prefix_len = pfxlen; | 656 | ifa->prefix_len = pfxlen; |
@@ -669,10 +677,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
669 | /* Add to big hash table */ | 677 | /* Add to big hash table */ |
670 | hash = ipv6_addr_hash(addr); | 678 | hash = ipv6_addr_hash(addr); |
671 | 679 | ||
672 | ifa->lst_next = inet6_addr_lst[hash]; | 680 | hlist_add_head_rcu(&ifa->addr_lst, &inet6_addr_lst[hash]); |
673 | inet6_addr_lst[hash] = ifa; | 681 | spin_unlock(&addrconf_hash_lock); |
674 | in6_ifa_hold(ifa); | ||
675 | write_unlock(&addrconf_hash_lock); | ||
676 | 682 | ||
677 | write_lock(&idev->lock); | 683 | write_lock(&idev->lock); |
678 | /* Add to inet6_dev unicast addr list. */ | 684 | /* Add to inet6_dev unicast addr list. */ |
@@ -680,8 +686,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, | |||
680 | 686 | ||
681 | #ifdef CONFIG_IPV6_PRIVACY | 687 | #ifdef CONFIG_IPV6_PRIVACY |
682 | if (ifa->flags&IFA_F_TEMPORARY) { | 688 | if (ifa->flags&IFA_F_TEMPORARY) { |
683 | ifa->tmp_next = idev->tempaddr_list; | 689 | list_add(&ifa->tmp_list, &idev->tempaddr_list); |
684 | idev->tempaddr_list = ifa; | ||
685 | in6_ifa_hold(ifa); | 690 | in6_ifa_hold(ifa); |
686 | } | 691 | } |
687 | #endif | 692 | #endif |
@@ -700,7 +705,7 @@ out2: | |||
700 | 705 | ||
701 | return ifa; | 706 | return ifa; |
702 | out: | 707 | out: |
703 | write_unlock(&addrconf_hash_lock); | 708 | spin_unlock(&addrconf_hash_lock); |
704 | goto out2; | 709 | goto out2; |
705 | } | 710 | } |
706 | 711 | ||
@@ -708,52 +713,44 @@ out: | |||
708 | 713 | ||
709 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) | 714 | static void ipv6_del_addr(struct inet6_ifaddr *ifp) |
710 | { | 715 | { |
711 | struct inet6_ifaddr *ifa, **ifap; | 716 | struct inet6_ifaddr *ifa, *ifn; |
712 | struct inet6_dev *idev = ifp->idev; | 717 | struct inet6_dev *idev = ifp->idev; |
718 | int state; | ||
713 | int hash; | 719 | int hash; |
714 | int deleted = 0, onlink = 0; | 720 | int deleted = 0, onlink = 0; |
715 | unsigned long expires = jiffies; | 721 | unsigned long expires = jiffies; |
716 | 722 | ||
717 | hash = ipv6_addr_hash(&ifp->addr); | 723 | hash = ipv6_addr_hash(&ifp->addr); |
718 | 724 | ||
719 | ifp->dead = 1; | 725 | spin_lock_bh(&ifp->state_lock); |
726 | state = ifp->state; | ||
727 | ifp->state = INET6_IFADDR_STATE_DEAD; | ||
728 | spin_unlock_bh(&ifp->state_lock); | ||
720 | 729 | ||
721 | write_lock_bh(&addrconf_hash_lock); | 730 | if (state == INET6_IFADDR_STATE_DEAD) |
722 | for (ifap = &inet6_addr_lst[hash]; (ifa=*ifap) != NULL; | 731 | goto out; |
723 | ifap = &ifa->lst_next) { | 732 | |
724 | if (ifa == ifp) { | 733 | spin_lock_bh(&addrconf_hash_lock); |
725 | *ifap = ifa->lst_next; | 734 | hlist_del_init_rcu(&ifp->addr_lst); |
726 | __in6_ifa_put(ifp); | 735 | spin_unlock_bh(&addrconf_hash_lock); |
727 | ifa->lst_next = NULL; | ||
728 | break; | ||
729 | } | ||
730 | } | ||
731 | write_unlock_bh(&addrconf_hash_lock); | ||
732 | 736 | ||
733 | write_lock_bh(&idev->lock); | 737 | write_lock_bh(&idev->lock); |
734 | #ifdef CONFIG_IPV6_PRIVACY | 738 | #ifdef CONFIG_IPV6_PRIVACY |
735 | if (ifp->flags&IFA_F_TEMPORARY) { | 739 | if (ifp->flags&IFA_F_TEMPORARY) { |
736 | for (ifap = &idev->tempaddr_list; (ifa=*ifap) != NULL; | 740 | list_del(&ifp->tmp_list); |
737 | ifap = &ifa->tmp_next) { | 741 | if (ifp->ifpub) { |
738 | if (ifa == ifp) { | 742 | in6_ifa_put(ifp->ifpub); |
739 | *ifap = ifa->tmp_next; | 743 | ifp->ifpub = NULL; |
740 | if (ifp->ifpub) { | ||
741 | in6_ifa_put(ifp->ifpub); | ||
742 | ifp->ifpub = NULL; | ||
743 | } | ||
744 | __in6_ifa_put(ifp); | ||
745 | ifa->tmp_next = NULL; | ||
746 | break; | ||
747 | } | ||
748 | } | 744 | } |
745 | __in6_ifa_put(ifp); | ||
749 | } | 746 | } |
750 | #endif | 747 | #endif |
751 | 748 | ||
752 | for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { | 749 | list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) { |
753 | if (ifa == ifp) { | 750 | if (ifa == ifp) { |
754 | *ifap = ifa->if_next; | 751 | list_del_init(&ifp->if_list); |
755 | __in6_ifa_put(ifp); | 752 | __in6_ifa_put(ifp); |
756 | ifa->if_next = NULL; | 753 | |
757 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) | 754 | if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) |
758 | break; | 755 | break; |
759 | deleted = 1; | 756 | deleted = 1; |
@@ -786,7 +783,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
786 | } | 783 | } |
787 | } | 784 | } |
788 | } | 785 | } |
789 | ifap = &ifa->if_next; | ||
790 | } | 786 | } |
791 | write_unlock_bh(&idev->lock); | 787 | write_unlock_bh(&idev->lock); |
792 | 788 | ||
@@ -830,6 +826,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
830 | dst_release(&rt->u.dst); | 826 | dst_release(&rt->u.dst); |
831 | } | 827 | } |
832 | 828 | ||
829 | out: | ||
833 | in6_ifa_put(ifp); | 830 | in6_ifa_put(ifp); |
834 | } | 831 | } |
835 | 832 | ||
@@ -1165,7 +1162,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
1165 | continue; | 1162 | continue; |
1166 | 1163 | ||
1167 | read_lock_bh(&idev->lock); | 1164 | read_lock_bh(&idev->lock); |
1168 | for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { | 1165 | list_for_each_entry(score->ifa, &idev->addr_list, if_list) { |
1169 | int i; | 1166 | int i; |
1170 | 1167 | ||
1171 | /* | 1168 | /* |
@@ -1243,7 +1240,6 @@ try_nextdev: | |||
1243 | in6_ifa_put(hiscore->ifa); | 1240 | in6_ifa_put(hiscore->ifa); |
1244 | return 0; | 1241 | return 0; |
1245 | } | 1242 | } |
1246 | |||
1247 | EXPORT_SYMBOL(ipv6_dev_get_saddr); | 1243 | EXPORT_SYMBOL(ipv6_dev_get_saddr); |
1248 | 1244 | ||
1249 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | 1245 | int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, |
@@ -1253,12 +1249,14 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, | |||
1253 | int err = -EADDRNOTAVAIL; | 1249 | int err = -EADDRNOTAVAIL; |
1254 | 1250 | ||
1255 | rcu_read_lock(); | 1251 | rcu_read_lock(); |
1256 | if ((idev = __in6_dev_get(dev)) != NULL) { | 1252 | idev = __in6_dev_get(dev); |
1253 | if (idev) { | ||
1257 | struct inet6_ifaddr *ifp; | 1254 | struct inet6_ifaddr *ifp; |
1258 | 1255 | ||
1259 | read_lock_bh(&idev->lock); | 1256 | read_lock_bh(&idev->lock); |
1260 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1257 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1261 | if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { | 1258 | if (ifp->scope == IFA_LINK && |
1259 | !(ifp->flags & banned_flags)) { | ||
1262 | ipv6_addr_copy(addr, &ifp->addr); | 1260 | ipv6_addr_copy(addr, &ifp->addr); |
1263 | err = 0; | 1261 | err = 0; |
1264 | break; | 1262 | break; |
@@ -1276,7 +1274,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1276 | struct inet6_ifaddr *ifp; | 1274 | struct inet6_ifaddr *ifp; |
1277 | 1275 | ||
1278 | read_lock_bh(&idev->lock); | 1276 | read_lock_bh(&idev->lock); |
1279 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) | 1277 | list_for_each_entry(ifp, &idev->addr_list, if_list) |
1280 | cnt++; | 1278 | cnt++; |
1281 | read_unlock_bh(&idev->lock); | 1279 | read_unlock_bh(&idev->lock); |
1282 | return cnt; | 1280 | return cnt; |
@@ -1285,41 +1283,44 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1285 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1283 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, |
1286 | struct net_device *dev, int strict) | 1284 | struct net_device *dev, int strict) |
1287 | { | 1285 | { |
1288 | struct inet6_ifaddr * ifp; | 1286 | struct inet6_ifaddr *ifp; |
1289 | u8 hash = ipv6_addr_hash(addr); | 1287 | struct hlist_node *node; |
1288 | unsigned int hash = ipv6_addr_hash(addr); | ||
1290 | 1289 | ||
1291 | read_lock_bh(&addrconf_hash_lock); | 1290 | rcu_read_lock_bh(); |
1292 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1291 | hlist_for_each_entry_rcu(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1293 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1292 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1294 | continue; | 1293 | continue; |
1295 | if (ipv6_addr_equal(&ifp->addr, addr) && | 1294 | if (ipv6_addr_equal(&ifp->addr, addr) && |
1296 | !(ifp->flags&IFA_F_TENTATIVE)) { | 1295 | !(ifp->flags&IFA_F_TENTATIVE) && |
1297 | if (dev == NULL || ifp->idev->dev == dev || | 1296 | (dev == NULL || ifp->idev->dev == dev || |
1298 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) | 1297 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict))) { |
1299 | break; | 1298 | rcu_read_unlock_bh(); |
1299 | return 1; | ||
1300 | } | 1300 | } |
1301 | } | 1301 | } |
1302 | read_unlock_bh(&addrconf_hash_lock); | 1302 | |
1303 | return ifp != NULL; | 1303 | rcu_read_unlock_bh(); |
1304 | return 0; | ||
1304 | } | 1305 | } |
1305 | EXPORT_SYMBOL(ipv6_chk_addr); | 1306 | EXPORT_SYMBOL(ipv6_chk_addr); |
1306 | 1307 | ||
1307 | static | 1308 | static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, |
1308 | int ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | 1309 | struct net_device *dev) |
1309 | struct net_device *dev) | ||
1310 | { | 1310 | { |
1311 | struct inet6_ifaddr * ifp; | 1311 | unsigned int hash = ipv6_addr_hash(addr); |
1312 | u8 hash = ipv6_addr_hash(addr); | 1312 | struct inet6_ifaddr *ifp; |
1313 | struct hlist_node *node; | ||
1313 | 1314 | ||
1314 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1315 | hlist_for_each_entry(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1315 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1316 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1316 | continue; | 1317 | continue; |
1317 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1318 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1318 | if (dev == NULL || ifp->idev->dev == dev) | 1319 | if (dev == NULL || ifp->idev->dev == dev) |
1319 | break; | 1320 | return true; |
1320 | } | 1321 | } |
1321 | } | 1322 | } |
1322 | return ifp != NULL; | 1323 | return false; |
1323 | } | 1324 | } |
1324 | 1325 | ||
1325 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1326 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) |
@@ -1333,7 +1334,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | |||
1333 | idev = __in6_dev_get(dev); | 1334 | idev = __in6_dev_get(dev); |
1334 | if (idev) { | 1335 | if (idev) { |
1335 | read_lock_bh(&idev->lock); | 1336 | read_lock_bh(&idev->lock); |
1336 | for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { | 1337 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
1337 | onlink = ipv6_prefix_equal(addr, &ifa->addr, | 1338 | onlink = ipv6_prefix_equal(addr, &ifa->addr, |
1338 | ifa->prefix_len); | 1339 | ifa->prefix_len); |
1339 | if (onlink) | 1340 | if (onlink) |
@@ -1350,24 +1351,26 @@ EXPORT_SYMBOL(ipv6_chk_prefix); | |||
1350 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, | 1351 | struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *addr, |
1351 | struct net_device *dev, int strict) | 1352 | struct net_device *dev, int strict) |
1352 | { | 1353 | { |
1353 | struct inet6_ifaddr * ifp; | 1354 | struct inet6_ifaddr *ifp, *result = NULL; |
1354 | u8 hash = ipv6_addr_hash(addr); | 1355 | unsigned int hash = ipv6_addr_hash(addr); |
1356 | struct hlist_node *node; | ||
1355 | 1357 | ||
1356 | read_lock_bh(&addrconf_hash_lock); | 1358 | rcu_read_lock_bh(); |
1357 | for(ifp = inet6_addr_lst[hash]; ifp; ifp=ifp->lst_next) { | 1359 | hlist_for_each_entry_rcu_bh(ifp, node, &inet6_addr_lst[hash], addr_lst) { |
1358 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 1360 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
1359 | continue; | 1361 | continue; |
1360 | if (ipv6_addr_equal(&ifp->addr, addr)) { | 1362 | if (ipv6_addr_equal(&ifp->addr, addr)) { |
1361 | if (dev == NULL || ifp->idev->dev == dev || | 1363 | if (dev == NULL || ifp->idev->dev == dev || |
1362 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { | 1364 | !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { |
1365 | result = ifp; | ||
1363 | in6_ifa_hold(ifp); | 1366 | in6_ifa_hold(ifp); |
1364 | break; | 1367 | break; |
1365 | } | 1368 | } |
1366 | } | 1369 | } |
1367 | } | 1370 | } |
1368 | read_unlock_bh(&addrconf_hash_lock); | 1371 | rcu_read_unlock_bh(); |
1369 | 1372 | ||
1370 | return ifp; | 1373 | return result; |
1371 | } | 1374 | } |
1372 | 1375 | ||
1373 | /* Gets referenced address, destroys ifaddr */ | 1376 | /* Gets referenced address, destroys ifaddr */ |
@@ -1403,10 +1406,27 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
1403 | ipv6_del_addr(ifp); | 1406 | ipv6_del_addr(ifp); |
1404 | } | 1407 | } |
1405 | 1408 | ||
1409 | static int addrconf_dad_end(struct inet6_ifaddr *ifp) | ||
1410 | { | ||
1411 | int err = -ENOENT; | ||
1412 | |||
1413 | spin_lock(&ifp->state_lock); | ||
1414 | if (ifp->state == INET6_IFADDR_STATE_DAD) { | ||
1415 | ifp->state = INET6_IFADDR_STATE_POSTDAD; | ||
1416 | err = 0; | ||
1417 | } | ||
1418 | spin_unlock(&ifp->state_lock); | ||
1419 | |||
1420 | return err; | ||
1421 | } | ||
1422 | |||
1406 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) | 1423 | void addrconf_dad_failure(struct inet6_ifaddr *ifp) |
1407 | { | 1424 | { |
1408 | struct inet6_dev *idev = ifp->idev; | 1425 | struct inet6_dev *idev = ifp->idev; |
1409 | 1426 | ||
1427 | if (addrconf_dad_end(ifp)) | ||
1428 | return; | ||
1429 | |||
1410 | if (net_ratelimit()) | 1430 | if (net_ratelimit()) |
1411 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", | 1431 | printk(KERN_INFO "%s: IPv6 duplicate address %pI6c detected!\n", |
1412 | ifp->idev->dev->name, &ifp->addr); | 1432 | ifp->idev->dev->name, &ifp->addr); |
@@ -1570,7 +1590,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
1570 | struct inet6_ifaddr *ifp; | 1590 | struct inet6_ifaddr *ifp; |
1571 | 1591 | ||
1572 | read_lock_bh(&idev->lock); | 1592 | read_lock_bh(&idev->lock); |
1573 | for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { | 1593 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
1574 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { | 1594 | if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { |
1575 | memcpy(eui, ifp->addr.s6_addr+8, 8); | 1595 | memcpy(eui, ifp->addr.s6_addr+8, 8); |
1576 | err = 0; | 1596 | err = 0; |
@@ -1738,7 +1758,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
1738 | 1758 | ||
1739 | ASSERT_RTNL(); | 1759 | ASSERT_RTNL(); |
1740 | 1760 | ||
1741 | if ((idev = ipv6_find_idev(dev)) == NULL) | 1761 | idev = ipv6_find_idev(dev); |
1762 | if (!idev) | ||
1742 | return NULL; | 1763 | return NULL; |
1743 | 1764 | ||
1744 | /* Add default multicast route */ | 1765 | /* Add default multicast route */ |
@@ -1971,7 +1992,7 @@ ok: | |||
1971 | #ifdef CONFIG_IPV6_PRIVACY | 1992 | #ifdef CONFIG_IPV6_PRIVACY |
1972 | read_lock_bh(&in6_dev->lock); | 1993 | read_lock_bh(&in6_dev->lock); |
1973 | /* update all temporary addresses in the list */ | 1994 | /* update all temporary addresses in the list */ |
1974 | for (ift=in6_dev->tempaddr_list; ift; ift=ift->tmp_next) { | 1995 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { |
1975 | /* | 1996 | /* |
1976 | * When adjusting the lifetimes of an existing | 1997 | * When adjusting the lifetimes of an existing |
1977 | * temporary address, only lower the lifetimes. | 1998 | * temporary address, only lower the lifetimes. |
@@ -2174,7 +2195,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2174 | return -ENXIO; | 2195 | return -ENXIO; |
2175 | 2196 | ||
2176 | read_lock_bh(&idev->lock); | 2197 | read_lock_bh(&idev->lock); |
2177 | for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { | 2198 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2178 | if (ifp->prefix_len == plen && | 2199 | if (ifp->prefix_len == plen && |
2179 | ipv6_addr_equal(pfx, &ifp->addr)) { | 2200 | ipv6_addr_equal(pfx, &ifp->addr)) { |
2180 | in6_ifa_hold(ifp); | 2201 | in6_ifa_hold(ifp); |
@@ -2185,7 +2206,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2185 | /* If the last address is deleted administratively, | 2206 | /* If the last address is deleted administratively, |
2186 | disable IPv6 on this interface. | 2207 | disable IPv6 on this interface. |
2187 | */ | 2208 | */ |
2188 | if (idev->addr_list == NULL) | 2209 | if (list_empty(&idev->addr_list)) |
2189 | addrconf_ifdown(idev->dev, 1); | 2210 | addrconf_ifdown(idev->dev, 1); |
2190 | return 0; | 2211 | return 0; |
2191 | } | 2212 | } |
@@ -2446,7 +2467,8 @@ static void addrconf_ip6_tnl_config(struct net_device *dev) | |||
2446 | 2467 | ||
2447 | ASSERT_RTNL(); | 2468 | ASSERT_RTNL(); |
2448 | 2469 | ||
2449 | if ((idev = addrconf_add_dev(dev)) == NULL) { | 2470 | idev = addrconf_add_dev(dev); |
2471 | if (!idev) { | ||
2450 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); | 2472 | printk(KERN_DEBUG "init ip6-ip6: add_dev failed\n"); |
2451 | return; | 2473 | return; |
2452 | } | 2474 | } |
@@ -2461,7 +2483,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2461 | int run_pending = 0; | 2483 | int run_pending = 0; |
2462 | int err; | 2484 | int err; |
2463 | 2485 | ||
2464 | switch(event) { | 2486 | switch (event) { |
2465 | case NETDEV_REGISTER: | 2487 | case NETDEV_REGISTER: |
2466 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2488 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2467 | idev = ipv6_add_dev(dev); | 2489 | idev = ipv6_add_dev(dev); |
@@ -2469,6 +2491,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2469 | return notifier_from_errno(-ENOMEM); | 2491 | return notifier_from_errno(-ENOMEM); |
2470 | } | 2492 | } |
2471 | break; | 2493 | break; |
2494 | |||
2472 | case NETDEV_UP: | 2495 | case NETDEV_UP: |
2473 | case NETDEV_CHANGE: | 2496 | case NETDEV_CHANGE: |
2474 | if (dev->flags & IFF_SLAVE) | 2497 | if (dev->flags & IFF_SLAVE) |
@@ -2498,10 +2521,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2498 | } | 2521 | } |
2499 | 2522 | ||
2500 | if (idev) { | 2523 | if (idev) { |
2501 | if (idev->if_flags & IF_READY) { | 2524 | if (idev->if_flags & IF_READY) |
2502 | /* device is already configured. */ | 2525 | /* device is already configured. */ |
2503 | break; | 2526 | break; |
2504 | } | ||
2505 | idev->if_flags |= IF_READY; | 2527 | idev->if_flags |= IF_READY; |
2506 | } | 2528 | } |
2507 | 2529 | ||
@@ -2513,7 +2535,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2513 | run_pending = 1; | 2535 | run_pending = 1; |
2514 | } | 2536 | } |
2515 | 2537 | ||
2516 | switch(dev->type) { | 2538 | switch (dev->type) { |
2517 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) | 2539 | #if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE) |
2518 | case ARPHRD_SIT: | 2540 | case ARPHRD_SIT: |
2519 | addrconf_sit_config(dev); | 2541 | addrconf_sit_config(dev); |
@@ -2530,25 +2552,30 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2530 | addrconf_dev_config(dev); | 2552 | addrconf_dev_config(dev); |
2531 | break; | 2553 | break; |
2532 | } | 2554 | } |
2555 | |||
2533 | if (idev) { | 2556 | if (idev) { |
2534 | if (run_pending) | 2557 | if (run_pending) |
2535 | addrconf_dad_run(idev); | 2558 | addrconf_dad_run(idev); |
2536 | 2559 | ||
2537 | /* If the MTU changed during the interface down, when the | 2560 | /* |
2538 | interface up, the changed MTU must be reflected in the | 2561 | * If the MTU changed during the interface down, |
2539 | idev as well as routers. | 2562 | * when the interface up, the changed MTU must be |
2563 | * reflected in the idev as well as routers. | ||
2540 | */ | 2564 | */ |
2541 | if (idev->cnf.mtu6 != dev->mtu && dev->mtu >= IPV6_MIN_MTU) { | 2565 | if (idev->cnf.mtu6 != dev->mtu && |
2566 | dev->mtu >= IPV6_MIN_MTU) { | ||
2542 | rt6_mtu_change(dev, dev->mtu); | 2567 | rt6_mtu_change(dev, dev->mtu); |
2543 | idev->cnf.mtu6 = dev->mtu; | 2568 | idev->cnf.mtu6 = dev->mtu; |
2544 | } | 2569 | } |
2545 | idev->tstamp = jiffies; | 2570 | idev->tstamp = jiffies; |
2546 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | 2571 | inet6_ifinfo_notify(RTM_NEWLINK, idev); |
2547 | /* If the changed mtu during down is lower than IPV6_MIN_MTU | 2572 | |
2548 | stop IPv6 on this interface. | 2573 | /* |
2574 | * If the changed mtu during down is lower than | ||
2575 | * IPV6_MIN_MTU stop IPv6 on this interface. | ||
2549 | */ | 2576 | */ |
2550 | if (dev->mtu < IPV6_MIN_MTU) | 2577 | if (dev->mtu < IPV6_MIN_MTU) |
2551 | addrconf_ifdown(dev, event != NETDEV_DOWN); | 2578 | addrconf_ifdown(dev, 1); |
2552 | } | 2579 | } |
2553 | break; | 2580 | break; |
2554 | 2581 | ||
@@ -2565,7 +2592,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2565 | break; | 2592 | break; |
2566 | } | 2593 | } |
2567 | 2594 | ||
2568 | /* MTU falled under IPV6_MIN_MTU. Stop IPv6 on this interface. */ | 2595 | /* |
2596 | * MTU falled under IPV6_MIN_MTU. | ||
2597 | * Stop IPv6 on this interface. | ||
2598 | */ | ||
2569 | 2599 | ||
2570 | case NETDEV_DOWN: | 2600 | case NETDEV_DOWN: |
2571 | case NETDEV_UNREGISTER: | 2601 | case NETDEV_UNREGISTER: |
@@ -2585,9 +2615,10 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2585 | return notifier_from_errno(err); | 2615 | return notifier_from_errno(err); |
2586 | } | 2616 | } |
2587 | break; | 2617 | break; |
2588 | case NETDEV_BONDING_OLDTYPE: | 2618 | |
2589 | case NETDEV_BONDING_NEWTYPE: | 2619 | case NETDEV_PRE_TYPE_CHANGE: |
2590 | addrconf_bonding_change(dev, event); | 2620 | case NETDEV_POST_TYPE_CHANGE: |
2621 | addrconf_type_change(dev, event); | ||
2591 | break; | 2622 | break; |
2592 | } | 2623 | } |
2593 | 2624 | ||
@@ -2599,28 +2630,28 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2599 | */ | 2630 | */ |
2600 | static struct notifier_block ipv6_dev_notf = { | 2631 | static struct notifier_block ipv6_dev_notf = { |
2601 | .notifier_call = addrconf_notify, | 2632 | .notifier_call = addrconf_notify, |
2602 | .priority = 0 | ||
2603 | }; | 2633 | }; |
2604 | 2634 | ||
2605 | static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | 2635 | static void addrconf_type_change(struct net_device *dev, unsigned long event) |
2606 | { | 2636 | { |
2607 | struct inet6_dev *idev; | 2637 | struct inet6_dev *idev; |
2608 | ASSERT_RTNL(); | 2638 | ASSERT_RTNL(); |
2609 | 2639 | ||
2610 | idev = __in6_dev_get(dev); | 2640 | idev = __in6_dev_get(dev); |
2611 | 2641 | ||
2612 | if (event == NETDEV_BONDING_NEWTYPE) | 2642 | if (event == NETDEV_POST_TYPE_CHANGE) |
2613 | ipv6_mc_remap(idev); | 2643 | ipv6_mc_remap(idev); |
2614 | else if (event == NETDEV_BONDING_OLDTYPE) | 2644 | else if (event == NETDEV_PRE_TYPE_CHANGE) |
2615 | ipv6_mc_unmap(idev); | 2645 | ipv6_mc_unmap(idev); |
2616 | } | 2646 | } |
2617 | 2647 | ||
2618 | static int addrconf_ifdown(struct net_device *dev, int how) | 2648 | static int addrconf_ifdown(struct net_device *dev, int how) |
2619 | { | 2649 | { |
2620 | struct inet6_dev *idev; | ||
2621 | struct inet6_ifaddr *ifa, *keep_list, **bifa; | ||
2622 | struct net *net = dev_net(dev); | 2650 | struct net *net = dev_net(dev); |
2623 | int i; | 2651 | struct inet6_dev *idev; |
2652 | struct inet6_ifaddr *ifa; | ||
2653 | LIST_HEAD(keep_list); | ||
2654 | int state; | ||
2624 | 2655 | ||
2625 | ASSERT_RTNL(); | 2656 | ASSERT_RTNL(); |
2626 | 2657 | ||
@@ -2631,8 +2662,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2631 | if (idev == NULL) | 2662 | if (idev == NULL) |
2632 | return -ENODEV; | 2663 | return -ENODEV; |
2633 | 2664 | ||
2634 | /* Step 1: remove reference to ipv6 device from parent device. | 2665 | /* |
2635 | Do not dev_put! | 2666 | * Step 1: remove reference to ipv6 device from parent device. |
2667 | * Do not dev_put! | ||
2636 | */ | 2668 | */ |
2637 | if (how) { | 2669 | if (how) { |
2638 | idev->dead = 1; | 2670 | idev->dead = 1; |
@@ -2645,41 +2677,21 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2645 | 2677 | ||
2646 | } | 2678 | } |
2647 | 2679 | ||
2648 | /* Step 2: clear hash table */ | ||
2649 | for (i=0; i<IN6_ADDR_HSIZE; i++) { | ||
2650 | bifa = &inet6_addr_lst[i]; | ||
2651 | |||
2652 | write_lock_bh(&addrconf_hash_lock); | ||
2653 | while ((ifa = *bifa) != NULL) { | ||
2654 | if (ifa->idev == idev && | ||
2655 | (how || !(ifa->flags&IFA_F_PERMANENT) || | ||
2656 | ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
2657 | *bifa = ifa->lst_next; | ||
2658 | ifa->lst_next = NULL; | ||
2659 | __in6_ifa_put(ifa); | ||
2660 | continue; | ||
2661 | } | ||
2662 | bifa = &ifa->lst_next; | ||
2663 | } | ||
2664 | write_unlock_bh(&addrconf_hash_lock); | ||
2665 | } | ||
2666 | |||
2667 | write_lock_bh(&idev->lock); | 2680 | write_lock_bh(&idev->lock); |
2668 | 2681 | ||
2669 | /* Step 3: clear flags for stateless addrconf */ | 2682 | /* Step 2: clear flags for stateless addrconf */ |
2670 | if (!how) | 2683 | if (!how) |
2671 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); | 2684 | idev->if_flags &= ~(IF_RS_SENT|IF_RA_RCVD|IF_READY); |
2672 | 2685 | ||
2673 | /* Step 4: clear address list */ | ||
2674 | #ifdef CONFIG_IPV6_PRIVACY | 2686 | #ifdef CONFIG_IPV6_PRIVACY |
2675 | if (how && del_timer(&idev->regen_timer)) | 2687 | if (how && del_timer(&idev->regen_timer)) |
2676 | in6_dev_put(idev); | 2688 | in6_dev_put(idev); |
2677 | 2689 | ||
2678 | /* clear tempaddr list */ | 2690 | /* Step 3: clear tempaddr list */ |
2679 | while ((ifa = idev->tempaddr_list) != NULL) { | 2691 | while (!list_empty(&idev->tempaddr_list)) { |
2680 | idev->tempaddr_list = ifa->tmp_next; | 2692 | ifa = list_first_entry(&idev->tempaddr_list, |
2681 | ifa->tmp_next = NULL; | 2693 | struct inet6_ifaddr, tmp_list); |
2682 | ifa->dead = 1; | 2694 | list_del(&ifa->tmp_list); |
2683 | write_unlock_bh(&idev->lock); | 2695 | write_unlock_bh(&idev->lock); |
2684 | spin_lock_bh(&ifa->lock); | 2696 | spin_lock_bh(&ifa->lock); |
2685 | 2697 | ||
@@ -2692,23 +2704,18 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2692 | write_lock_bh(&idev->lock); | 2704 | write_lock_bh(&idev->lock); |
2693 | } | 2705 | } |
2694 | #endif | 2706 | #endif |
2695 | keep_list = NULL; | ||
2696 | bifa = &keep_list; | ||
2697 | while ((ifa = idev->addr_list) != NULL) { | ||
2698 | idev->addr_list = ifa->if_next; | ||
2699 | ifa->if_next = NULL; | ||
2700 | 2707 | ||
2708 | while (!list_empty(&idev->addr_list)) { | ||
2709 | ifa = list_first_entry(&idev->addr_list, | ||
2710 | struct inet6_ifaddr, if_list); | ||
2701 | addrconf_del_timer(ifa); | 2711 | addrconf_del_timer(ifa); |
2702 | 2712 | ||
2703 | /* If just doing link down, and address is permanent | 2713 | /* If just doing link down, and address is permanent |
2704 | and not link-local, then retain it. */ | 2714 | and not link-local, then retain it. */ |
2705 | if (how == 0 && | 2715 | if (!how && |
2706 | (ifa->flags&IFA_F_PERMANENT) && | 2716 | (ifa->flags&IFA_F_PERMANENT) && |
2707 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | 2717 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { |
2708 | 2718 | list_move_tail(&ifa->if_list, &keep_list); | |
2709 | /* Move to holding list */ | ||
2710 | *bifa = ifa; | ||
2711 | bifa = &ifa->if_next; | ||
2712 | 2719 | ||
2713 | /* If not doing DAD on this address, just keep it. */ | 2720 | /* If not doing DAD on this address, just keep it. */ |
2714 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | 2721 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || |
@@ -2722,25 +2729,45 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2722 | 2729 | ||
2723 | /* Flag it for later restoration when link comes up */ | 2730 | /* Flag it for later restoration when link comes up */ |
2724 | ifa->flags |= IFA_F_TENTATIVE; | 2731 | ifa->flags |= IFA_F_TENTATIVE; |
2732 | ifa->state = INET6_IFADDR_STATE_DAD; | ||
2733 | |||
2734 | write_unlock_bh(&idev->lock); | ||
2735 | |||
2725 | in6_ifa_hold(ifa); | 2736 | in6_ifa_hold(ifa); |
2726 | } else { | 2737 | } else { |
2727 | ifa->dead = 1; | 2738 | list_del(&ifa->if_list); |
2739 | |||
2740 | /* clear hash table */ | ||
2741 | spin_lock_bh(&addrconf_hash_lock); | ||
2742 | hlist_del_init_rcu(&ifa->addr_lst); | ||
2743 | spin_unlock_bh(&addrconf_hash_lock); | ||
2744 | |||
2745 | write_unlock_bh(&idev->lock); | ||
2746 | spin_lock_bh(&ifa->state_lock); | ||
2747 | state = ifa->state; | ||
2748 | ifa->state = INET6_IFADDR_STATE_DEAD; | ||
2749 | spin_unlock_bh(&ifa->state_lock); | ||
2750 | |||
2751 | if (state == INET6_IFADDR_STATE_DEAD) | ||
2752 | goto put_ifa; | ||
2728 | } | 2753 | } |
2729 | write_unlock_bh(&idev->lock); | ||
2730 | 2754 | ||
2731 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2755 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
2732 | atomic_notifier_call_chain(&inet6addr_chain, NETDEV_DOWN, ifa); | 2756 | if (ifa->state == INET6_IFADDR_STATE_DEAD) |
2757 | atomic_notifier_call_chain(&inet6addr_chain, | ||
2758 | NETDEV_DOWN, ifa); | ||
2759 | |||
2760 | put_ifa: | ||
2733 | in6_ifa_put(ifa); | 2761 | in6_ifa_put(ifa); |
2734 | 2762 | ||
2735 | write_lock_bh(&idev->lock); | 2763 | write_lock_bh(&idev->lock); |
2736 | } | 2764 | } |
2737 | 2765 | ||
2738 | idev->addr_list = keep_list; | 2766 | list_splice(&keep_list, &idev->addr_list); |
2739 | 2767 | ||
2740 | write_unlock_bh(&idev->lock); | 2768 | write_unlock_bh(&idev->lock); |
2741 | 2769 | ||
2742 | /* Step 5: Discard multicast list */ | 2770 | /* Step 5: Discard multicast list */ |
2743 | |||
2744 | if (how) | 2771 | if (how) |
2745 | ipv6_mc_destroy_dev(idev); | 2772 | ipv6_mc_destroy_dev(idev); |
2746 | else | 2773 | else |
@@ -2748,8 +2775,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
2748 | 2775 | ||
2749 | idev->tstamp = jiffies; | 2776 | idev->tstamp = jiffies; |
2750 | 2777 | ||
2751 | /* Shot the device (if unregistered) */ | 2778 | /* Last: Shot the device (if unregistered) */ |
2752 | |||
2753 | if (how) { | 2779 | if (how) { |
2754 | addrconf_sysctl_unregister(idev); | 2780 | addrconf_sysctl_unregister(idev); |
2755 | neigh_parms_release(&nd_tbl, idev->nd_parms); | 2781 | neigh_parms_release(&nd_tbl, idev->nd_parms); |
@@ -2827,10 +2853,10 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2827 | net_srandom(ifp->addr.s6_addr32[3]); | 2853 | net_srandom(ifp->addr.s6_addr32[3]); |
2828 | 2854 | ||
2829 | read_lock_bh(&idev->lock); | 2855 | read_lock_bh(&idev->lock); |
2830 | if (ifp->dead) | 2856 | spin_lock(&ifp->lock); |
2857 | if (ifp->state == INET6_IFADDR_STATE_DEAD) | ||
2831 | goto out; | 2858 | goto out; |
2832 | 2859 | ||
2833 | spin_lock(&ifp->lock); | ||
2834 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2860 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
2835 | idev->cnf.accept_dad < 1 || | 2861 | idev->cnf.accept_dad < 1 || |
2836 | !(ifp->flags&IFA_F_TENTATIVE) || | 2862 | !(ifp->flags&IFA_F_TENTATIVE) || |
@@ -2860,12 +2886,12 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
2860 | * Optimistic nodes can start receiving | 2886 | * Optimistic nodes can start receiving |
2861 | * Frames right away | 2887 | * Frames right away |
2862 | */ | 2888 | */ |
2863 | if(ifp->flags & IFA_F_OPTIMISTIC) | 2889 | if (ifp->flags & IFA_F_OPTIMISTIC) |
2864 | ip6_ins_rt(ifp->rt); | 2890 | ip6_ins_rt(ifp->rt); |
2865 | 2891 | ||
2866 | addrconf_dad_kick(ifp); | 2892 | addrconf_dad_kick(ifp); |
2867 | spin_unlock(&ifp->lock); | ||
2868 | out: | 2893 | out: |
2894 | spin_unlock(&ifp->lock); | ||
2869 | read_unlock_bh(&idev->lock); | 2895 | read_unlock_bh(&idev->lock); |
2870 | } | 2896 | } |
2871 | 2897 | ||
@@ -2875,6 +2901,9 @@ static void addrconf_dad_timer(unsigned long data) | |||
2875 | struct inet6_dev *idev = ifp->idev; | 2901 | struct inet6_dev *idev = ifp->idev; |
2876 | struct in6_addr mcaddr; | 2902 | struct in6_addr mcaddr; |
2877 | 2903 | ||
2904 | if (!ifp->probes && addrconf_dad_end(ifp)) | ||
2905 | goto out; | ||
2906 | |||
2878 | read_lock(&idev->lock); | 2907 | read_lock(&idev->lock); |
2879 | if (idev->dead || !(idev->if_flags & IF_READY)) { | 2908 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
2880 | read_unlock(&idev->lock); | 2909 | read_unlock(&idev->lock); |
@@ -2882,6 +2911,12 @@ static void addrconf_dad_timer(unsigned long data) | |||
2882 | } | 2911 | } |
2883 | 2912 | ||
2884 | spin_lock(&ifp->lock); | 2913 | spin_lock(&ifp->lock); |
2914 | if (ifp->state == INET6_IFADDR_STATE_DEAD) { | ||
2915 | spin_unlock(&ifp->lock); | ||
2916 | read_unlock(&idev->lock); | ||
2917 | goto out; | ||
2918 | } | ||
2919 | |||
2885 | if (ifp->probes == 0) { | 2920 | if (ifp->probes == 0) { |
2886 | /* | 2921 | /* |
2887 | * DAD was successful | 2922 | * DAD was successful |
@@ -2910,7 +2945,7 @@ out: | |||
2910 | 2945 | ||
2911 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | 2946 | static void addrconf_dad_completed(struct inet6_ifaddr *ifp) |
2912 | { | 2947 | { |
2913 | struct net_device * dev = ifp->idev->dev; | 2948 | struct net_device *dev = ifp->idev->dev; |
2914 | 2949 | ||
2915 | /* | 2950 | /* |
2916 | * Configure the address for reception. Now it is valid. | 2951 | * Configure the address for reception. Now it is valid. |
@@ -2941,18 +2976,17 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
2941 | } | 2976 | } |
2942 | } | 2977 | } |
2943 | 2978 | ||
2944 | static void addrconf_dad_run(struct inet6_dev *idev) { | 2979 | static void addrconf_dad_run(struct inet6_dev *idev) |
2980 | { | ||
2945 | struct inet6_ifaddr *ifp; | 2981 | struct inet6_ifaddr *ifp; |
2946 | 2982 | ||
2947 | read_lock_bh(&idev->lock); | 2983 | read_lock_bh(&idev->lock); |
2948 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2984 | list_for_each_entry(ifp, &idev->addr_list, if_list) { |
2949 | spin_lock(&ifp->lock); | 2985 | spin_lock(&ifp->lock); |
2950 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2986 | if (ifp->flags & IFA_F_TENTATIVE && |
2951 | spin_unlock(&ifp->lock); | 2987 | ifp->state == INET6_IFADDR_STATE_DAD) |
2952 | continue; | 2988 | addrconf_dad_kick(ifp); |
2953 | } | ||
2954 | spin_unlock(&ifp->lock); | 2989 | spin_unlock(&ifp->lock); |
2955 | addrconf_dad_kick(ifp); | ||
2956 | } | 2990 | } |
2957 | read_unlock_bh(&idev->lock); | 2991 | read_unlock_bh(&idev->lock); |
2958 | } | 2992 | } |
@@ -2970,36 +3004,35 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2970 | struct net *net = seq_file_net(seq); | 3004 | struct net *net = seq_file_net(seq); |
2971 | 3005 | ||
2972 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 3006 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2973 | ifa = inet6_addr_lst[state->bucket]; | 3007 | struct hlist_node *n; |
2974 | 3008 | hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], | |
2975 | while (ifa && !net_eq(dev_net(ifa->idev->dev), net)) | 3009 | addr_lst) |
2976 | ifa = ifa->lst_next; | 3010 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2977 | if (ifa) | 3011 | return ifa; |
2978 | break; | ||
2979 | } | 3012 | } |
2980 | return ifa; | 3013 | return NULL; |
2981 | } | 3014 | } |
2982 | 3015 | ||
2983 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 3016 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, |
3017 | struct inet6_ifaddr *ifa) | ||
2984 | { | 3018 | { |
2985 | struct if6_iter_state *state = seq->private; | 3019 | struct if6_iter_state *state = seq->private; |
2986 | struct net *net = seq_file_net(seq); | 3020 | struct net *net = seq_file_net(seq); |
3021 | struct hlist_node *n = &ifa->addr_lst; | ||
2987 | 3022 | ||
2988 | ifa = ifa->lst_next; | 3023 | hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) |
2989 | try_again: | 3024 | if (net_eq(dev_net(ifa->idev->dev), net)) |
2990 | if (ifa) { | 3025 | return ifa; |
2991 | if (!net_eq(dev_net(ifa->idev->dev), net)) { | ||
2992 | ifa = ifa->lst_next; | ||
2993 | goto try_again; | ||
2994 | } | ||
2995 | } | ||
2996 | 3026 | ||
2997 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 3027 | while (++state->bucket < IN6_ADDR_HSIZE) { |
2998 | ifa = inet6_addr_lst[state->bucket]; | 3028 | hlist_for_each_entry_rcu_bh(ifa, n, |
2999 | goto try_again; | 3029 | &inet6_addr_lst[state->bucket], addr_lst) { |
3030 | if (net_eq(dev_net(ifa->idev->dev), net)) | ||
3031 | return ifa; | ||
3032 | } | ||
3000 | } | 3033 | } |
3001 | 3034 | ||
3002 | return ifa; | 3035 | return NULL; |
3003 | } | 3036 | } |
3004 | 3037 | ||
3005 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | 3038 | static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) |
@@ -3007,15 +3040,15 @@ static struct inet6_ifaddr *if6_get_idx(struct seq_file *seq, loff_t pos) | |||
3007 | struct inet6_ifaddr *ifa = if6_get_first(seq); | 3040 | struct inet6_ifaddr *ifa = if6_get_first(seq); |
3008 | 3041 | ||
3009 | if (ifa) | 3042 | if (ifa) |
3010 | while(pos && (ifa = if6_get_next(seq, ifa)) != NULL) | 3043 | while (pos && (ifa = if6_get_next(seq, ifa)) != NULL) |
3011 | --pos; | 3044 | --pos; |
3012 | return pos ? NULL : ifa; | 3045 | return pos ? NULL : ifa; |
3013 | } | 3046 | } |
3014 | 3047 | ||
3015 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) | 3048 | static void *if6_seq_start(struct seq_file *seq, loff_t *pos) |
3016 | __acquires(addrconf_hash_lock) | 3049 | __acquires(rcu_bh) |
3017 | { | 3050 | { |
3018 | read_lock_bh(&addrconf_hash_lock); | 3051 | rcu_read_lock_bh(); |
3019 | return if6_get_idx(seq, *pos); | 3052 | return if6_get_idx(seq, *pos); |
3020 | } | 3053 | } |
3021 | 3054 | ||
@@ -3029,9 +3062,9 @@ static void *if6_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3029 | } | 3062 | } |
3030 | 3063 | ||
3031 | static void if6_seq_stop(struct seq_file *seq, void *v) | 3064 | static void if6_seq_stop(struct seq_file *seq, void *v) |
3032 | __releases(addrconf_hash_lock) | 3065 | __releases(rcu_bh) |
3033 | { | 3066 | { |
3034 | read_unlock_bh(&addrconf_hash_lock); | 3067 | rcu_read_unlock_bh(); |
3035 | } | 3068 | } |
3036 | 3069 | ||
3037 | static int if6_seq_show(struct seq_file *seq, void *v) | 3070 | static int if6_seq_show(struct seq_file *seq, void *v) |
@@ -3101,10 +3134,12 @@ void if6_proc_exit(void) | |||
3101 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3134 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) |
3102 | { | 3135 | { |
3103 | int ret = 0; | 3136 | int ret = 0; |
3104 | struct inet6_ifaddr * ifp; | 3137 | struct inet6_ifaddr *ifp = NULL; |
3105 | u8 hash = ipv6_addr_hash(addr); | 3138 | struct hlist_node *n; |
3106 | read_lock_bh(&addrconf_hash_lock); | 3139 | unsigned int hash = ipv6_addr_hash(addr); |
3107 | for (ifp = inet6_addr_lst[hash]; ifp; ifp = ifp->lst_next) { | 3140 | |
3141 | rcu_read_lock_bh(); | ||
3142 | hlist_for_each_entry_rcu_bh(ifp, n, &inet6_addr_lst[hash], addr_lst) { | ||
3108 | if (!net_eq(dev_net(ifp->idev->dev), net)) | 3143 | if (!net_eq(dev_net(ifp->idev->dev), net)) |
3109 | continue; | 3144 | continue; |
3110 | if (ipv6_addr_equal(&ifp->addr, addr) && | 3145 | if (ipv6_addr_equal(&ifp->addr, addr) && |
@@ -3113,7 +3148,7 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3113 | break; | 3148 | break; |
3114 | } | 3149 | } |
3115 | } | 3150 | } |
3116 | read_unlock_bh(&addrconf_hash_lock); | 3151 | rcu_read_unlock_bh(); |
3117 | return ret; | 3152 | return ret; |
3118 | } | 3153 | } |
3119 | #endif | 3154 | #endif |
@@ -3124,43 +3159,35 @@ int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | |||
3124 | 3159 | ||
3125 | static void addrconf_verify(unsigned long foo) | 3160 | static void addrconf_verify(unsigned long foo) |
3126 | { | 3161 | { |
3162 | unsigned long now, next, next_sec, next_sched; | ||
3127 | struct inet6_ifaddr *ifp; | 3163 | struct inet6_ifaddr *ifp; |
3128 | unsigned long now, next; | 3164 | struct hlist_node *node; |
3129 | int i; | 3165 | int i; |
3130 | 3166 | ||
3131 | spin_lock_bh(&addrconf_verify_lock); | 3167 | rcu_read_lock_bh(); |
3168 | spin_lock(&addrconf_verify_lock); | ||
3132 | now = jiffies; | 3169 | now = jiffies; |
3133 | next = now + ADDR_CHECK_FREQUENCY; | 3170 | next = round_jiffies_up(now + ADDR_CHECK_FREQUENCY); |
3134 | 3171 | ||
3135 | del_timer(&addr_chk_timer); | 3172 | del_timer(&addr_chk_timer); |
3136 | 3173 | ||
3137 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 3174 | for (i = 0; i < IN6_ADDR_HSIZE; i++) { |
3138 | |||
3139 | restart: | 3175 | restart: |
3140 | read_lock(&addrconf_hash_lock); | 3176 | hlist_for_each_entry_rcu_bh(ifp, node, |
3141 | for (ifp=inet6_addr_lst[i]; ifp; ifp=ifp->lst_next) { | 3177 | &inet6_addr_lst[i], addr_lst) { |
3142 | unsigned long age; | 3178 | unsigned long age; |
3143 | #ifdef CONFIG_IPV6_PRIVACY | ||
3144 | unsigned long regen_advance; | ||
3145 | #endif | ||
3146 | 3179 | ||
3147 | if (ifp->flags & IFA_F_PERMANENT) | 3180 | if (ifp->flags & IFA_F_PERMANENT) |
3148 | continue; | 3181 | continue; |
3149 | 3182 | ||
3150 | spin_lock(&ifp->lock); | 3183 | spin_lock(&ifp->lock); |
3151 | age = (now - ifp->tstamp) / HZ; | 3184 | /* We try to batch several events at once. */ |
3152 | 3185 | age = (now - ifp->tstamp + ADDRCONF_TIMER_FUZZ_MINUS) / HZ; | |
3153 | #ifdef CONFIG_IPV6_PRIVACY | ||
3154 | regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3155 | ifp->idev->cnf.dad_transmits * | ||
3156 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3157 | #endif | ||
3158 | 3186 | ||
3159 | if (ifp->valid_lft != INFINITY_LIFE_TIME && | 3187 | if (ifp->valid_lft != INFINITY_LIFE_TIME && |
3160 | age >= ifp->valid_lft) { | 3188 | age >= ifp->valid_lft) { |
3161 | spin_unlock(&ifp->lock); | 3189 | spin_unlock(&ifp->lock); |
3162 | in6_ifa_hold(ifp); | 3190 | in6_ifa_hold(ifp); |
3163 | read_unlock(&addrconf_hash_lock); | ||
3164 | ipv6_del_addr(ifp); | 3191 | ipv6_del_addr(ifp); |
3165 | goto restart; | 3192 | goto restart; |
3166 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { | 3193 | } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { |
@@ -3182,7 +3209,6 @@ restart: | |||
3182 | 3209 | ||
3183 | if (deprecate) { | 3210 | if (deprecate) { |
3184 | in6_ifa_hold(ifp); | 3211 | in6_ifa_hold(ifp); |
3185 | read_unlock(&addrconf_hash_lock); | ||
3186 | 3212 | ||
3187 | ipv6_ifa_notify(0, ifp); | 3213 | ipv6_ifa_notify(0, ifp); |
3188 | in6_ifa_put(ifp); | 3214 | in6_ifa_put(ifp); |
@@ -3191,6 +3217,10 @@ restart: | |||
3191 | #ifdef CONFIG_IPV6_PRIVACY | 3217 | #ifdef CONFIG_IPV6_PRIVACY |
3192 | } else if ((ifp->flags&IFA_F_TEMPORARY) && | 3218 | } else if ((ifp->flags&IFA_F_TEMPORARY) && |
3193 | !(ifp->flags&IFA_F_TENTATIVE)) { | 3219 | !(ifp->flags&IFA_F_TENTATIVE)) { |
3220 | unsigned long regen_advance = ifp->idev->cnf.regen_max_retry * | ||
3221 | ifp->idev->cnf.dad_transmits * | ||
3222 | ifp->idev->nd_parms->retrans_time / HZ; | ||
3223 | |||
3194 | if (age >= ifp->prefered_lft - regen_advance) { | 3224 | if (age >= ifp->prefered_lft - regen_advance) { |
3195 | struct inet6_ifaddr *ifpub = ifp->ifpub; | 3225 | struct inet6_ifaddr *ifpub = ifp->ifpub; |
3196 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) | 3226 | if (time_before(ifp->tstamp + ifp->prefered_lft * HZ, next)) |
@@ -3200,7 +3230,7 @@ restart: | |||
3200 | in6_ifa_hold(ifp); | 3230 | in6_ifa_hold(ifp); |
3201 | in6_ifa_hold(ifpub); | 3231 | in6_ifa_hold(ifpub); |
3202 | spin_unlock(&ifp->lock); | 3232 | spin_unlock(&ifp->lock); |
3203 | read_unlock(&addrconf_hash_lock); | 3233 | |
3204 | spin_lock(&ifpub->lock); | 3234 | spin_lock(&ifpub->lock); |
3205 | ifpub->regen_count = 0; | 3235 | ifpub->regen_count = 0; |
3206 | spin_unlock(&ifpub->lock); | 3236 | spin_unlock(&ifpub->lock); |
@@ -3220,12 +3250,26 @@ restart: | |||
3220 | spin_unlock(&ifp->lock); | 3250 | spin_unlock(&ifp->lock); |
3221 | } | 3251 | } |
3222 | } | 3252 | } |
3223 | read_unlock(&addrconf_hash_lock); | ||
3224 | } | 3253 | } |
3225 | 3254 | ||
3226 | addr_chk_timer.expires = time_before(next, jiffies + HZ) ? jiffies + HZ : next; | 3255 | next_sec = round_jiffies_up(next); |
3256 | next_sched = next; | ||
3257 | |||
3258 | /* If rounded timeout is accurate enough, accept it. */ | ||
3259 | if (time_before(next_sec, next + ADDRCONF_TIMER_FUZZ)) | ||
3260 | next_sched = next_sec; | ||
3261 | |||
3262 | /* And minimum interval is ADDRCONF_TIMER_FUZZ_MAX. */ | ||
3263 | if (time_before(next_sched, jiffies + ADDRCONF_TIMER_FUZZ_MAX)) | ||
3264 | next_sched = jiffies + ADDRCONF_TIMER_FUZZ_MAX; | ||
3265 | |||
3266 | ADBG((KERN_DEBUG "now = %lu, schedule = %lu, rounded schedule = %lu => %lu\n", | ||
3267 | now, next, next_sec, next_sched)); | ||
3268 | |||
3269 | addr_chk_timer.expires = next_sched; | ||
3227 | add_timer(&addr_chk_timer); | 3270 | add_timer(&addr_chk_timer); |
3228 | spin_unlock_bh(&addrconf_verify_lock); | 3271 | spin_unlock(&addrconf_verify_lock); |
3272 | rcu_read_unlock_bh(); | ||
3229 | } | 3273 | } |
3230 | 3274 | ||
3231 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) | 3275 | static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local) |
@@ -3515,8 +3559,7 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
3515 | return nlmsg_end(skb, nlh); | 3559 | return nlmsg_end(skb, nlh); |
3516 | } | 3560 | } |
3517 | 3561 | ||
3518 | enum addr_type_t | 3562 | enum addr_type_t { |
3519 | { | ||
3520 | UNICAST_ADDR, | 3563 | UNICAST_ADDR, |
3521 | MULTICAST_ADDR, | 3564 | MULTICAST_ADDR, |
3522 | ANYCAST_ADDR, | 3565 | ANYCAST_ADDR, |
@@ -3527,7 +3570,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3527 | struct netlink_callback *cb, enum addr_type_t type, | 3570 | struct netlink_callback *cb, enum addr_type_t type, |
3528 | int s_ip_idx, int *p_ip_idx) | 3571 | int s_ip_idx, int *p_ip_idx) |
3529 | { | 3572 | { |
3530 | struct inet6_ifaddr *ifa; | ||
3531 | struct ifmcaddr6 *ifmca; | 3573 | struct ifmcaddr6 *ifmca; |
3532 | struct ifacaddr6 *ifaca; | 3574 | struct ifacaddr6 *ifaca; |
3533 | int err = 1; | 3575 | int err = 1; |
@@ -3535,11 +3577,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3535 | 3577 | ||
3536 | read_lock_bh(&idev->lock); | 3578 | read_lock_bh(&idev->lock); |
3537 | switch (type) { | 3579 | switch (type) { |
3538 | case UNICAST_ADDR: | 3580 | case UNICAST_ADDR: { |
3581 | struct inet6_ifaddr *ifa; | ||
3582 | |||
3539 | /* unicast address incl. temp addr */ | 3583 | /* unicast address incl. temp addr */ |
3540 | for (ifa = idev->addr_list; ifa; | 3584 | list_for_each_entry(ifa, &idev->addr_list, if_list) { |
3541 | ifa = ifa->if_next, ip_idx++) { | 3585 | if (++ip_idx < s_ip_idx) |
3542 | if (ip_idx < s_ip_idx) | ||
3543 | continue; | 3586 | continue; |
3544 | err = inet6_fill_ifaddr(skb, ifa, | 3587 | err = inet6_fill_ifaddr(skb, ifa, |
3545 | NETLINK_CB(cb->skb).pid, | 3588 | NETLINK_CB(cb->skb).pid, |
@@ -3550,6 +3593,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | |||
3550 | break; | 3593 | break; |
3551 | } | 3594 | } |
3552 | break; | 3595 | break; |
3596 | } | ||
3553 | case MULTICAST_ADDR: | 3597 | case MULTICAST_ADDR: |
3554 | /* multicast address */ | 3598 | /* multicast address */ |
3555 | for (ifmca = idev->mc_list; ifmca; | 3599 | for (ifmca = idev->mc_list; ifmca; |
@@ -3614,7 +3658,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | |||
3614 | if (h > s_h || idx > s_idx) | 3658 | if (h > s_h || idx > s_idx) |
3615 | s_ip_idx = 0; | 3659 | s_ip_idx = 0; |
3616 | ip_idx = 0; | 3660 | ip_idx = 0; |
3617 | if ((idev = __in6_dev_get(dev)) == NULL) | 3661 | idev = __in6_dev_get(dev); |
3662 | if (!idev) | ||
3618 | goto cont; | 3663 | goto cont; |
3619 | 3664 | ||
3620 | if (in6_dump_addrs(idev, skb, cb, type, | 3665 | if (in6_dump_addrs(idev, skb, cb, type, |
@@ -3681,12 +3726,14 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3681 | if (ifm->ifa_index) | 3726 | if (ifm->ifa_index) |
3682 | dev = __dev_get_by_index(net, ifm->ifa_index); | 3727 | dev = __dev_get_by_index(net, ifm->ifa_index); |
3683 | 3728 | ||
3684 | if ((ifa = ipv6_get_ifaddr(net, addr, dev, 1)) == NULL) { | 3729 | ifa = ipv6_get_ifaddr(net, addr, dev, 1); |
3730 | if (!ifa) { | ||
3685 | err = -EADDRNOTAVAIL; | 3731 | err = -EADDRNOTAVAIL; |
3686 | goto errout; | 3732 | goto errout; |
3687 | } | 3733 | } |
3688 | 3734 | ||
3689 | if ((skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL)) == NULL) { | 3735 | skb = nlmsg_new(inet6_ifaddr_msgsize(), GFP_KERNEL); |
3736 | if (!skb) { | ||
3690 | err = -ENOBUFS; | 3737 | err = -ENOBUFS; |
3691 | goto errout_ifa; | 3738 | goto errout_ifa; |
3692 | } | 3739 | } |
@@ -3811,7 +3858,7 @@ static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | |||
3811 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | 3858 | static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, |
3812 | int bytes) | 3859 | int bytes) |
3813 | { | 3860 | { |
3814 | switch(attrtype) { | 3861 | switch (attrtype) { |
3815 | case IFLA_INET6_STATS: | 3862 | case IFLA_INET6_STATS: |
3816 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3863 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
3817 | break; | 3864 | break; |
@@ -4047,7 +4094,9 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4047 | addrconf_leave_anycast(ifp); | 4094 | addrconf_leave_anycast(ifp); |
4048 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4095 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4049 | dst_hold(&ifp->rt->u.dst); | 4096 | dst_hold(&ifp->rt->u.dst); |
4050 | if (ip6_del_rt(ifp->rt)) | 4097 | |
4098 | if (ifp->state == INET6_IFADDR_STATE_DEAD && | ||
4099 | ip6_del_rt(ifp->rt)) | ||
4051 | dst_free(&ifp->rt->u.dst); | 4100 | dst_free(&ifp->rt->u.dst); |
4052 | break; | 4101 | break; |
4053 | } | 4102 | } |
@@ -4163,211 +4212,211 @@ static struct addrconf_sysctl_table | |||
4163 | .sysctl_header = NULL, | 4212 | .sysctl_header = NULL, |
4164 | .addrconf_vars = { | 4213 | .addrconf_vars = { |
4165 | { | 4214 | { |
4166 | .procname = "forwarding", | 4215 | .procname = "forwarding", |
4167 | .data = &ipv6_devconf.forwarding, | 4216 | .data = &ipv6_devconf.forwarding, |
4168 | .maxlen = sizeof(int), | 4217 | .maxlen = sizeof(int), |
4169 | .mode = 0644, | 4218 | .mode = 0644, |
4170 | .proc_handler = addrconf_sysctl_forward, | 4219 | .proc_handler = addrconf_sysctl_forward, |
4171 | }, | 4220 | }, |
4172 | { | 4221 | { |
4173 | .procname = "hop_limit", | 4222 | .procname = "hop_limit", |
4174 | .data = &ipv6_devconf.hop_limit, | 4223 | .data = &ipv6_devconf.hop_limit, |
4175 | .maxlen = sizeof(int), | 4224 | .maxlen = sizeof(int), |
4176 | .mode = 0644, | 4225 | .mode = 0644, |
4177 | .proc_handler = proc_dointvec, | 4226 | .proc_handler = proc_dointvec, |
4178 | }, | 4227 | }, |
4179 | { | 4228 | { |
4180 | .procname = "mtu", | 4229 | .procname = "mtu", |
4181 | .data = &ipv6_devconf.mtu6, | 4230 | .data = &ipv6_devconf.mtu6, |
4182 | .maxlen = sizeof(int), | 4231 | .maxlen = sizeof(int), |
4183 | .mode = 0644, | 4232 | .mode = 0644, |
4184 | .proc_handler = proc_dointvec, | 4233 | .proc_handler = proc_dointvec, |
4185 | }, | 4234 | }, |
4186 | { | 4235 | { |
4187 | .procname = "accept_ra", | 4236 | .procname = "accept_ra", |
4188 | .data = &ipv6_devconf.accept_ra, | 4237 | .data = &ipv6_devconf.accept_ra, |
4189 | .maxlen = sizeof(int), | 4238 | .maxlen = sizeof(int), |
4190 | .mode = 0644, | 4239 | .mode = 0644, |
4191 | .proc_handler = proc_dointvec, | 4240 | .proc_handler = proc_dointvec, |
4192 | }, | 4241 | }, |
4193 | { | 4242 | { |
4194 | .procname = "accept_redirects", | 4243 | .procname = "accept_redirects", |
4195 | .data = &ipv6_devconf.accept_redirects, | 4244 | .data = &ipv6_devconf.accept_redirects, |
4196 | .maxlen = sizeof(int), | 4245 | .maxlen = sizeof(int), |
4197 | .mode = 0644, | 4246 | .mode = 0644, |
4198 | .proc_handler = proc_dointvec, | 4247 | .proc_handler = proc_dointvec, |
4199 | }, | 4248 | }, |
4200 | { | 4249 | { |
4201 | .procname = "autoconf", | 4250 | .procname = "autoconf", |
4202 | .data = &ipv6_devconf.autoconf, | 4251 | .data = &ipv6_devconf.autoconf, |
4203 | .maxlen = sizeof(int), | 4252 | .maxlen = sizeof(int), |
4204 | .mode = 0644, | 4253 | .mode = 0644, |
4205 | .proc_handler = proc_dointvec, | 4254 | .proc_handler = proc_dointvec, |
4206 | }, | 4255 | }, |
4207 | { | 4256 | { |
4208 | .procname = "dad_transmits", | 4257 | .procname = "dad_transmits", |
4209 | .data = &ipv6_devconf.dad_transmits, | 4258 | .data = &ipv6_devconf.dad_transmits, |
4210 | .maxlen = sizeof(int), | 4259 | .maxlen = sizeof(int), |
4211 | .mode = 0644, | 4260 | .mode = 0644, |
4212 | .proc_handler = proc_dointvec, | 4261 | .proc_handler = proc_dointvec, |
4213 | }, | 4262 | }, |
4214 | { | 4263 | { |
4215 | .procname = "router_solicitations", | 4264 | .procname = "router_solicitations", |
4216 | .data = &ipv6_devconf.rtr_solicits, | 4265 | .data = &ipv6_devconf.rtr_solicits, |
4217 | .maxlen = sizeof(int), | 4266 | .maxlen = sizeof(int), |
4218 | .mode = 0644, | 4267 | .mode = 0644, |
4219 | .proc_handler = proc_dointvec, | 4268 | .proc_handler = proc_dointvec, |
4220 | }, | 4269 | }, |
4221 | { | 4270 | { |
4222 | .procname = "router_solicitation_interval", | 4271 | .procname = "router_solicitation_interval", |
4223 | .data = &ipv6_devconf.rtr_solicit_interval, | 4272 | .data = &ipv6_devconf.rtr_solicit_interval, |
4224 | .maxlen = sizeof(int), | 4273 | .maxlen = sizeof(int), |
4225 | .mode = 0644, | 4274 | .mode = 0644, |
4226 | .proc_handler = proc_dointvec_jiffies, | 4275 | .proc_handler = proc_dointvec_jiffies, |
4227 | }, | 4276 | }, |
4228 | { | 4277 | { |
4229 | .procname = "router_solicitation_delay", | 4278 | .procname = "router_solicitation_delay", |
4230 | .data = &ipv6_devconf.rtr_solicit_delay, | 4279 | .data = &ipv6_devconf.rtr_solicit_delay, |
4231 | .maxlen = sizeof(int), | 4280 | .maxlen = sizeof(int), |
4232 | .mode = 0644, | 4281 | .mode = 0644, |
4233 | .proc_handler = proc_dointvec_jiffies, | 4282 | .proc_handler = proc_dointvec_jiffies, |
4234 | }, | 4283 | }, |
4235 | { | 4284 | { |
4236 | .procname = "force_mld_version", | 4285 | .procname = "force_mld_version", |
4237 | .data = &ipv6_devconf.force_mld_version, | 4286 | .data = &ipv6_devconf.force_mld_version, |
4238 | .maxlen = sizeof(int), | 4287 | .maxlen = sizeof(int), |
4239 | .mode = 0644, | 4288 | .mode = 0644, |
4240 | .proc_handler = proc_dointvec, | 4289 | .proc_handler = proc_dointvec, |
4241 | }, | 4290 | }, |
4242 | #ifdef CONFIG_IPV6_PRIVACY | 4291 | #ifdef CONFIG_IPV6_PRIVACY |
4243 | { | 4292 | { |
4244 | .procname = "use_tempaddr", | 4293 | .procname = "use_tempaddr", |
4245 | .data = &ipv6_devconf.use_tempaddr, | 4294 | .data = &ipv6_devconf.use_tempaddr, |
4246 | .maxlen = sizeof(int), | 4295 | .maxlen = sizeof(int), |
4247 | .mode = 0644, | 4296 | .mode = 0644, |
4248 | .proc_handler = proc_dointvec, | 4297 | .proc_handler = proc_dointvec, |
4249 | }, | 4298 | }, |
4250 | { | 4299 | { |
4251 | .procname = "temp_valid_lft", | 4300 | .procname = "temp_valid_lft", |
4252 | .data = &ipv6_devconf.temp_valid_lft, | 4301 | .data = &ipv6_devconf.temp_valid_lft, |
4253 | .maxlen = sizeof(int), | 4302 | .maxlen = sizeof(int), |
4254 | .mode = 0644, | 4303 | .mode = 0644, |
4255 | .proc_handler = proc_dointvec, | 4304 | .proc_handler = proc_dointvec, |
4256 | }, | 4305 | }, |
4257 | { | 4306 | { |
4258 | .procname = "temp_prefered_lft", | 4307 | .procname = "temp_prefered_lft", |
4259 | .data = &ipv6_devconf.temp_prefered_lft, | 4308 | .data = &ipv6_devconf.temp_prefered_lft, |
4260 | .maxlen = sizeof(int), | 4309 | .maxlen = sizeof(int), |
4261 | .mode = 0644, | 4310 | .mode = 0644, |
4262 | .proc_handler = proc_dointvec, | 4311 | .proc_handler = proc_dointvec, |
4263 | }, | 4312 | }, |
4264 | { | 4313 | { |
4265 | .procname = "regen_max_retry", | 4314 | .procname = "regen_max_retry", |
4266 | .data = &ipv6_devconf.regen_max_retry, | 4315 | .data = &ipv6_devconf.regen_max_retry, |
4267 | .maxlen = sizeof(int), | 4316 | .maxlen = sizeof(int), |
4268 | .mode = 0644, | 4317 | .mode = 0644, |
4269 | .proc_handler = proc_dointvec, | 4318 | .proc_handler = proc_dointvec, |
4270 | }, | 4319 | }, |
4271 | { | 4320 | { |
4272 | .procname = "max_desync_factor", | 4321 | .procname = "max_desync_factor", |
4273 | .data = &ipv6_devconf.max_desync_factor, | 4322 | .data = &ipv6_devconf.max_desync_factor, |
4274 | .maxlen = sizeof(int), | 4323 | .maxlen = sizeof(int), |
4275 | .mode = 0644, | 4324 | .mode = 0644, |
4276 | .proc_handler = proc_dointvec, | 4325 | .proc_handler = proc_dointvec, |
4277 | }, | 4326 | }, |
4278 | #endif | 4327 | #endif |
4279 | { | 4328 | { |
4280 | .procname = "max_addresses", | 4329 | .procname = "max_addresses", |
4281 | .data = &ipv6_devconf.max_addresses, | 4330 | .data = &ipv6_devconf.max_addresses, |
4282 | .maxlen = sizeof(int), | 4331 | .maxlen = sizeof(int), |
4283 | .mode = 0644, | 4332 | .mode = 0644, |
4284 | .proc_handler = proc_dointvec, | 4333 | .proc_handler = proc_dointvec, |
4285 | }, | 4334 | }, |
4286 | { | 4335 | { |
4287 | .procname = "accept_ra_defrtr", | 4336 | .procname = "accept_ra_defrtr", |
4288 | .data = &ipv6_devconf.accept_ra_defrtr, | 4337 | .data = &ipv6_devconf.accept_ra_defrtr, |
4289 | .maxlen = sizeof(int), | 4338 | .maxlen = sizeof(int), |
4290 | .mode = 0644, | 4339 | .mode = 0644, |
4291 | .proc_handler = proc_dointvec, | 4340 | .proc_handler = proc_dointvec, |
4292 | }, | 4341 | }, |
4293 | { | 4342 | { |
4294 | .procname = "accept_ra_pinfo", | 4343 | .procname = "accept_ra_pinfo", |
4295 | .data = &ipv6_devconf.accept_ra_pinfo, | 4344 | .data = &ipv6_devconf.accept_ra_pinfo, |
4296 | .maxlen = sizeof(int), | 4345 | .maxlen = sizeof(int), |
4297 | .mode = 0644, | 4346 | .mode = 0644, |
4298 | .proc_handler = proc_dointvec, | 4347 | .proc_handler = proc_dointvec, |
4299 | }, | 4348 | }, |
4300 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4349 | #ifdef CONFIG_IPV6_ROUTER_PREF |
4301 | { | 4350 | { |
4302 | .procname = "accept_ra_rtr_pref", | 4351 | .procname = "accept_ra_rtr_pref", |
4303 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4352 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
4304 | .maxlen = sizeof(int), | 4353 | .maxlen = sizeof(int), |
4305 | .mode = 0644, | 4354 | .mode = 0644, |
4306 | .proc_handler = proc_dointvec, | 4355 | .proc_handler = proc_dointvec, |
4307 | }, | 4356 | }, |
4308 | { | 4357 | { |
4309 | .procname = "router_probe_interval", | 4358 | .procname = "router_probe_interval", |
4310 | .data = &ipv6_devconf.rtr_probe_interval, | 4359 | .data = &ipv6_devconf.rtr_probe_interval, |
4311 | .maxlen = sizeof(int), | 4360 | .maxlen = sizeof(int), |
4312 | .mode = 0644, | 4361 | .mode = 0644, |
4313 | .proc_handler = proc_dointvec_jiffies, | 4362 | .proc_handler = proc_dointvec_jiffies, |
4314 | }, | 4363 | }, |
4315 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4364 | #ifdef CONFIG_IPV6_ROUTE_INFO |
4316 | { | 4365 | { |
4317 | .procname = "accept_ra_rt_info_max_plen", | 4366 | .procname = "accept_ra_rt_info_max_plen", |
4318 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4367 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
4319 | .maxlen = sizeof(int), | 4368 | .maxlen = sizeof(int), |
4320 | .mode = 0644, | 4369 | .mode = 0644, |
4321 | .proc_handler = proc_dointvec, | 4370 | .proc_handler = proc_dointvec, |
4322 | }, | 4371 | }, |
4323 | #endif | 4372 | #endif |
4324 | #endif | 4373 | #endif |
4325 | { | 4374 | { |
4326 | .procname = "proxy_ndp", | 4375 | .procname = "proxy_ndp", |
4327 | .data = &ipv6_devconf.proxy_ndp, | 4376 | .data = &ipv6_devconf.proxy_ndp, |
4328 | .maxlen = sizeof(int), | 4377 | .maxlen = sizeof(int), |
4329 | .mode = 0644, | 4378 | .mode = 0644, |
4330 | .proc_handler = proc_dointvec, | 4379 | .proc_handler = proc_dointvec, |
4331 | }, | 4380 | }, |
4332 | { | 4381 | { |
4333 | .procname = "accept_source_route", | 4382 | .procname = "accept_source_route", |
4334 | .data = &ipv6_devconf.accept_source_route, | 4383 | .data = &ipv6_devconf.accept_source_route, |
4335 | .maxlen = sizeof(int), | 4384 | .maxlen = sizeof(int), |
4336 | .mode = 0644, | 4385 | .mode = 0644, |
4337 | .proc_handler = proc_dointvec, | 4386 | .proc_handler = proc_dointvec, |
4338 | }, | 4387 | }, |
4339 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4388 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
4340 | { | 4389 | { |
4341 | .procname = "optimistic_dad", | 4390 | .procname = "optimistic_dad", |
4342 | .data = &ipv6_devconf.optimistic_dad, | 4391 | .data = &ipv6_devconf.optimistic_dad, |
4343 | .maxlen = sizeof(int), | 4392 | .maxlen = sizeof(int), |
4344 | .mode = 0644, | 4393 | .mode = 0644, |
4345 | .proc_handler = proc_dointvec, | 4394 | .proc_handler = proc_dointvec, |
4346 | 4395 | ||
4347 | }, | 4396 | }, |
4348 | #endif | 4397 | #endif |
4349 | #ifdef CONFIG_IPV6_MROUTE | 4398 | #ifdef CONFIG_IPV6_MROUTE |
4350 | { | 4399 | { |
4351 | .procname = "mc_forwarding", | 4400 | .procname = "mc_forwarding", |
4352 | .data = &ipv6_devconf.mc_forwarding, | 4401 | .data = &ipv6_devconf.mc_forwarding, |
4353 | .maxlen = sizeof(int), | 4402 | .maxlen = sizeof(int), |
4354 | .mode = 0444, | 4403 | .mode = 0444, |
4355 | .proc_handler = proc_dointvec, | 4404 | .proc_handler = proc_dointvec, |
4356 | }, | 4405 | }, |
4357 | #endif | 4406 | #endif |
4358 | { | 4407 | { |
4359 | .procname = "disable_ipv6", | 4408 | .procname = "disable_ipv6", |
4360 | .data = &ipv6_devconf.disable_ipv6, | 4409 | .data = &ipv6_devconf.disable_ipv6, |
4361 | .maxlen = sizeof(int), | 4410 | .maxlen = sizeof(int), |
4362 | .mode = 0644, | 4411 | .mode = 0644, |
4363 | .proc_handler = addrconf_sysctl_disable, | 4412 | .proc_handler = addrconf_sysctl_disable, |
4364 | }, | 4413 | }, |
4365 | { | 4414 | { |
4366 | .procname = "accept_dad", | 4415 | .procname = "accept_dad", |
4367 | .data = &ipv6_devconf.accept_dad, | 4416 | .data = &ipv6_devconf.accept_dad, |
4368 | .maxlen = sizeof(int), | 4417 | .maxlen = sizeof(int), |
4369 | .mode = 0644, | 4418 | .mode = 0644, |
4370 | .proc_handler = proc_dointvec, | 4419 | .proc_handler = proc_dointvec, |
4371 | }, | 4420 | }, |
4372 | { | 4421 | { |
4373 | .procname = "force_tllao", | 4422 | .procname = "force_tllao", |
@@ -4403,8 +4452,8 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
4403 | if (t == NULL) | 4452 | if (t == NULL) |
4404 | goto out; | 4453 | goto out; |
4405 | 4454 | ||
4406 | for (i=0; t->addrconf_vars[i].data; i++) { | 4455 | for (i = 0; t->addrconf_vars[i].data; i++) { |
4407 | t->addrconf_vars[i].data += (char*)p - (char*)&ipv6_devconf; | 4456 | t->addrconf_vars[i].data += (char *)p - (char *)&ipv6_devconf; |
4408 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ | 4457 | t->addrconf_vars[i].extra1 = idev; /* embedded; no ref */ |
4409 | t->addrconf_vars[i].extra2 = net; | 4458 | t->addrconf_vars[i].extra2 = net; |
4410 | } | 4459 | } |
@@ -4541,14 +4590,12 @@ int register_inet6addr_notifier(struct notifier_block *nb) | |||
4541 | { | 4590 | { |
4542 | return atomic_notifier_chain_register(&inet6addr_chain, nb); | 4591 | return atomic_notifier_chain_register(&inet6addr_chain, nb); |
4543 | } | 4592 | } |
4544 | |||
4545 | EXPORT_SYMBOL(register_inet6addr_notifier); | 4593 | EXPORT_SYMBOL(register_inet6addr_notifier); |
4546 | 4594 | ||
4547 | int unregister_inet6addr_notifier(struct notifier_block *nb) | 4595 | int unregister_inet6addr_notifier(struct notifier_block *nb) |
4548 | { | 4596 | { |
4549 | return atomic_notifier_chain_unregister(&inet6addr_chain,nb); | 4597 | return atomic_notifier_chain_unregister(&inet6addr_chain, nb); |
4550 | } | 4598 | } |
4551 | |||
4552 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4599 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4553 | 4600 | ||
4554 | /* | 4601 | /* |
@@ -4557,11 +4604,12 @@ EXPORT_SYMBOL(unregister_inet6addr_notifier); | |||
4557 | 4604 | ||
4558 | int __init addrconf_init(void) | 4605 | int __init addrconf_init(void) |
4559 | { | 4606 | { |
4560 | int err; | 4607 | int i, err; |
4561 | 4608 | ||
4562 | if ((err = ipv6_addr_label_init()) < 0) { | 4609 | err = ipv6_addr_label_init(); |
4563 | printk(KERN_CRIT "IPv6 Addrconf: cannot initialize default policy table: %d.\n", | 4610 | if (err < 0) { |
4564 | err); | 4611 | printk(KERN_CRIT "IPv6 Addrconf:" |
4612 | " cannot initialize default policy table: %d.\n", err); | ||
4565 | return err; | 4613 | return err; |
4566 | } | 4614 | } |
4567 | 4615 | ||
@@ -4592,6 +4640,9 @@ int __init addrconf_init(void) | |||
4592 | if (err) | 4640 | if (err) |
4593 | goto errlo; | 4641 | goto errlo; |
4594 | 4642 | ||
4643 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | ||
4644 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | ||
4645 | |||
4595 | register_netdevice_notifier(&ipv6_dev_notf); | 4646 | register_netdevice_notifier(&ipv6_dev_notf); |
4596 | 4647 | ||
4597 | addrconf_verify(0); | 4648 | addrconf_verify(0); |
@@ -4620,7 +4671,6 @@ errlo: | |||
4620 | 4671 | ||
4621 | void addrconf_cleanup(void) | 4672 | void addrconf_cleanup(void) |
4622 | { | 4673 | { |
4623 | struct inet6_ifaddr *ifa; | ||
4624 | struct net_device *dev; | 4674 | struct net_device *dev; |
4625 | int i; | 4675 | int i; |
4626 | 4676 | ||
@@ -4640,20 +4690,10 @@ void addrconf_cleanup(void) | |||
4640 | /* | 4690 | /* |
4641 | * Check hash table. | 4691 | * Check hash table. |
4642 | */ | 4692 | */ |
4643 | write_lock_bh(&addrconf_hash_lock); | 4693 | spin_lock_bh(&addrconf_hash_lock); |
4644 | for (i=0; i < IN6_ADDR_HSIZE; i++) { | 4694 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
4645 | for (ifa=inet6_addr_lst[i]; ifa; ) { | 4695 | WARN_ON(!hlist_empty(&inet6_addr_lst[i])); |
4646 | struct inet6_ifaddr *bifa; | 4696 | spin_unlock_bh(&addrconf_hash_lock); |
4647 | |||
4648 | bifa = ifa; | ||
4649 | ifa = ifa->lst_next; | ||
4650 | printk(KERN_DEBUG "bug: IPv6 address leakage detected: ifa=%p\n", bifa); | ||
4651 | /* Do not free it; something is wrong. | ||
4652 | Now we can investigate it with debugger. | ||
4653 | */ | ||
4654 | } | ||
4655 | } | ||
4656 | write_unlock_bh(&addrconf_hash_lock); | ||
4657 | 4697 | ||
4658 | del_timer(&addr_chk_timer); | 4698 | del_timer(&addr_chk_timer); |
4659 | rtnl_unlock(); | 4699 | rtnl_unlock(); |