aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bonding/bond_ipv6.c9
-rw-r--r--include/net/if_inet6.h6
-rw-r--r--net/ipv6/addrconf.c78
-rw-r--r--net/sctp/ipv6.c2
4 files changed, 48 insertions, 47 deletions
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
index 6dd64cf3cb76..969ffed86b9f 100644
--- a/drivers/net/bonding/bond_ipv6.c
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -37,7 +37,6 @@
37static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr) 37static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
38{ 38{
39 struct inet6_dev *idev; 39 struct inet6_dev *idev;
40 struct inet6_ifaddr *ifa;
41 40
42 if (!dev) 41 if (!dev)
43 return; 42 return;
@@ -47,10 +46,12 @@ static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
47 return; 46 return;
48 47
49 read_lock_bh(&idev->lock); 48 read_lock_bh(&idev->lock);
50 ifa = idev->addr_list; 49 if (!list_empty(&idev->addr_list)) {
51 if (ifa) 50 struct inet6_ifaddr *ifa
51 = list_first_entry(&idev->addr_list,
52 struct inet6_ifaddr, if_list);
52 ipv6_addr_copy(addr, &ifa->addr); 53 ipv6_addr_copy(addr, &ifa->addr);
53 else 54 } else
54 ipv6_addr_set(addr, 0, 0, 0, 0); 55 ipv6_addr_set(addr, 0, 0, 0, 0);
55 56
56 read_unlock_bh(&idev->lock); 57 read_unlock_bh(&idev->lock);
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 22a00b1d2c38..13f9fc086d54 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -55,7 +55,7 @@ struct inet6_ifaddr {
55 struct rt6_info *rt; 55 struct rt6_info *rt;
56 56
57 struct hlist_node addr_lst; 57 struct hlist_node addr_lst;
58 struct inet6_ifaddr *if_next; /* next addr in inet6_dev */ 58 struct list_head if_list;
59 59
60#ifdef CONFIG_IPV6_PRIVACY 60#ifdef CONFIG_IPV6_PRIVACY
61 struct list_head tmp_list; 61 struct list_head tmp_list;
@@ -152,9 +152,9 @@ struct ipv6_devstat {
152}; 152};
153 153
154struct inet6_dev { 154struct inet6_dev {
155 struct net_device *dev; 155 struct net_device *dev;
156 156
157 struct inet6_ifaddr *addr_list; 157 struct list_head addr_list;
158 158
159 struct ifmcaddr6 *mc_list; 159 struct ifmcaddr6 *mc_list;
160 struct ifmcaddr6 *mc_tomb; 160 struct ifmcaddr6 *mc_tomb;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 1e5e41fe92bc..6dbf0f79b762 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -317,7 +317,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev)
317{ 317{
318 struct net_device *dev = idev->dev; 318 struct net_device *dev = idev->dev;
319 319
320 WARN_ON(idev->addr_list != NULL); 320 WARN_ON(!list_empty(&idev->addr_list));
321 WARN_ON(idev->mc_list != NULL); 321 WARN_ON(idev->mc_list != NULL);
322 322
323#ifdef NET_REFCNT_DEBUG 323#ifdef NET_REFCNT_DEBUG
@@ -350,6 +350,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev)
350 350
351 rwlock_init(&ndev->lock); 351 rwlock_init(&ndev->lock);
352 ndev->dev = dev; 352 ndev->dev = dev;
353 INIT_LIST_HEAD(&ndev->addr_list);
354
353 memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf)); 355 memcpy(&ndev->cnf, dev_net(dev)->ipv6.devconf_dflt, sizeof(ndev->cnf));
354 ndev->cnf.mtu6 = dev->mtu; 356 ndev->cnf.mtu6 = dev->mtu;
355 ndev->cnf.sysctl = NULL; 357 ndev->cnf.sysctl = NULL;
@@ -466,7 +468,8 @@ static void dev_forward_change(struct inet6_dev *idev)
466 else 468 else
467 ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters); 469 ipv6_dev_mc_dec(dev, &in6addr_linklocal_allrouters);
468 } 470 }
469 for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { 471
472 list_for_each_entry(ifa, &idev->addr_list, if_list) {
470 if (ifa->flags&IFA_F_TENTATIVE) 473 if (ifa->flags&IFA_F_TENTATIVE)
471 continue; 474 continue;
472 if (idev->cnf.forwarding) 475 if (idev->cnf.forwarding)
@@ -532,7 +535,6 @@ static void inet6_ifa_finish_destroy_rcu(struct rcu_head *head)
532/* Nobody refers to this ifaddr, destroy it */ 535/* Nobody refers to this ifaddr, destroy it */
533void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) 536void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
534{ 537{
535 WARN_ON(ifp->if_next != NULL);
536 WARN_ON(!hlist_unhashed(&ifp->addr_lst)); 538 WARN_ON(!hlist_unhashed(&ifp->addr_lst));
537 539
538#ifdef NET_REFCNT_DEBUG 540#ifdef NET_REFCNT_DEBUG
@@ -556,21 +558,21 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
556static void 558static void
557ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) 559ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp)
558{ 560{
559 struct inet6_ifaddr *ifa, **ifap; 561 struct list_head *p;
560 int ifp_scope = ipv6_addr_src_scope(&ifp->addr); 562 int ifp_scope = ipv6_addr_src_scope(&ifp->addr);
561 563
562 /* 564 /*
563 * Each device address list is sorted in order of scope - 565 * Each device address list is sorted in order of scope -
564 * global before linklocal. 566 * global before linklocal.
565 */ 567 */
566 for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; 568 list_for_each(p, &idev->addr_list) {
567 ifap = &ifa->if_next) { 569 struct inet6_ifaddr *ifa
570 = list_entry(p, struct inet6_ifaddr, if_list);
568 if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) 571 if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr))
569 break; 572 break;
570 } 573 }
571 574
572 ifp->if_next = *ifap; 575 list_add(&ifp->if_list, p);
573 *ifap = ifp;
574} 576}
575 577
576static u32 ipv6_addr_hash(const struct in6_addr *addr) 578static u32 ipv6_addr_hash(const struct in6_addr *addr)
@@ -703,7 +705,7 @@ out:
703 705
704static void ipv6_del_addr(struct inet6_ifaddr *ifp) 706static void ipv6_del_addr(struct inet6_ifaddr *ifp)
705{ 707{
706 struct inet6_ifaddr *ifa, **ifap; 708 struct inet6_ifaddr *ifa, *ifn;
707 struct inet6_dev *idev = ifp->idev; 709 struct inet6_dev *idev = ifp->idev;
708 int hash; 710 int hash;
709 int deleted = 0, onlink = 0; 711 int deleted = 0, onlink = 0;
@@ -730,11 +732,11 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
730 } 732 }
731#endif 733#endif
732 734
733 for (ifap = &idev->addr_list; (ifa=*ifap) != NULL;) { 735 list_for_each_entry_safe(ifa, ifn, &idev->addr_list, if_list) {
734 if (ifa == ifp) { 736 if (ifa == ifp) {
735 *ifap = ifa->if_next; 737 list_del_init(&ifp->if_list);
736 __in6_ifa_put(ifp); 738 __in6_ifa_put(ifp);
737 ifa->if_next = NULL; 739
738 if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0) 740 if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
739 break; 741 break;
740 deleted = 1; 742 deleted = 1;
@@ -767,7 +769,6 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
767 } 769 }
768 } 770 }
769 } 771 }
770 ifap = &ifa->if_next;
771 } 772 }
772 write_unlock_bh(&idev->lock); 773 write_unlock_bh(&idev->lock);
773 774
@@ -1146,7 +1147,7 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
1146 continue; 1147 continue;
1147 1148
1148 read_lock_bh(&idev->lock); 1149 read_lock_bh(&idev->lock);
1149 for (score->ifa = idev->addr_list; score->ifa; score->ifa = score->ifa->if_next) { 1150 list_for_each_entry(score->ifa, &idev->addr_list, if_list) {
1150 int i; 1151 int i;
1151 1152
1152 /* 1153 /*
@@ -1238,8 +1239,9 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr,
1238 struct inet6_ifaddr *ifp; 1239 struct inet6_ifaddr *ifp;
1239 1240
1240 read_lock_bh(&idev->lock); 1241 read_lock_bh(&idev->lock);
1241 for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { 1242 list_for_each_entry(ifp, &idev->addr_list, if_list) {
1242 if (ifp->scope == IFA_LINK && !(ifp->flags & banned_flags)) { 1243 if (ifp->scope == IFA_LINK &&
1244 !(ifp->flags & banned_flags)) {
1243 ipv6_addr_copy(addr, &ifp->addr); 1245 ipv6_addr_copy(addr, &ifp->addr);
1244 err = 0; 1246 err = 0;
1245 break; 1247 break;
@@ -1257,7 +1259,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev)
1257 struct inet6_ifaddr *ifp; 1259 struct inet6_ifaddr *ifp;
1258 1260
1259 read_lock_bh(&idev->lock); 1261 read_lock_bh(&idev->lock);
1260 for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) 1262 list_for_each_entry(ifp, &idev->addr_list, if_list)
1261 cnt++; 1263 cnt++;
1262 read_unlock_bh(&idev->lock); 1264 read_unlock_bh(&idev->lock);
1263 return cnt; 1265 return cnt;
@@ -1317,7 +1319,7 @@ int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev)
1317 idev = __in6_dev_get(dev); 1319 idev = __in6_dev_get(dev);
1318 if (idev) { 1320 if (idev) {
1319 read_lock_bh(&idev->lock); 1321 read_lock_bh(&idev->lock);
1320 for (ifa = idev->addr_list; ifa; ifa = ifa->if_next) { 1322 list_for_each_entry(ifa, &idev->addr_list, if_list) {
1321 onlink = ipv6_prefix_equal(addr, &ifa->addr, 1323 onlink = ipv6_prefix_equal(addr, &ifa->addr,
1322 ifa->prefix_len); 1324 ifa->prefix_len);
1323 if (onlink) 1325 if (onlink)
@@ -1555,7 +1557,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev)
1555 struct inet6_ifaddr *ifp; 1557 struct inet6_ifaddr *ifp;
1556 1558
1557 read_lock_bh(&idev->lock); 1559 read_lock_bh(&idev->lock);
1558 for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { 1560 list_for_each_entry(ifp, &idev->addr_list, if_list) {
1559 if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { 1561 if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) {
1560 memcpy(eui, ifp->addr.s6_addr+8, 8); 1562 memcpy(eui, ifp->addr.s6_addr+8, 8);
1561 err = 0; 1563 err = 0;
@@ -2159,7 +2161,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
2159 return -ENXIO; 2161 return -ENXIO;
2160 2162
2161 read_lock_bh(&idev->lock); 2163 read_lock_bh(&idev->lock);
2162 for (ifp = idev->addr_list; ifp; ifp=ifp->if_next) { 2164 list_for_each_entry(ifp, &idev->addr_list, if_list) {
2163 if (ifp->prefix_len == plen && 2165 if (ifp->prefix_len == plen &&
2164 ipv6_addr_equal(pfx, &ifp->addr)) { 2166 ipv6_addr_equal(pfx, &ifp->addr)) {
2165 in6_ifa_hold(ifp); 2167 in6_ifa_hold(ifp);
@@ -2170,7 +2172,7 @@ static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx,
2170 /* If the last address is deleted administratively, 2172 /* If the last address is deleted administratively,
2171 disable IPv6 on this interface. 2173 disable IPv6 on this interface.
2172 */ 2174 */
2173 if (idev->addr_list == NULL) 2175 if (list_empty(&idev->addr_list))
2174 addrconf_ifdown(idev->dev, 1); 2176 addrconf_ifdown(idev->dev, 1);
2175 return 0; 2177 return 0;
2176 } 2178 }
@@ -2602,9 +2604,10 @@ static void addrconf_type_change(struct net_device *dev, unsigned long event)
2602 2604
2603static int addrconf_ifdown(struct net_device *dev, int how) 2605static int addrconf_ifdown(struct net_device *dev, int how)
2604{ 2606{
2605 struct inet6_dev *idev;
2606 struct inet6_ifaddr *ifa, *keep_list, **bifa;
2607 struct net *net = dev_net(dev); 2607 struct net *net = dev_net(dev);
2608 struct inet6_dev *idev;
2609 struct inet6_ifaddr *ifa;
2610 LIST_HEAD(keep_list);
2608 2611
2609 ASSERT_RTNL(); 2612 ASSERT_RTNL();
2610 2613
@@ -2658,12 +2661,10 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2658 write_lock_bh(&idev->lock); 2661 write_lock_bh(&idev->lock);
2659 } 2662 }
2660#endif 2663#endif
2661 keep_list = NULL;
2662 bifa = &keep_list;
2663 while ((ifa = idev->addr_list) != NULL) {
2664 idev->addr_list = ifa->if_next;
2665 ifa->if_next = NULL;
2666 2664
2665 while (!list_empty(&idev->addr_list)) {
2666 ifa = list_first_entry(&idev->addr_list,
2667 struct inet6_ifaddr, if_list);
2667 addrconf_del_timer(ifa); 2668 addrconf_del_timer(ifa);
2668 2669
2669 /* If just doing link down, and address is permanent 2670 /* If just doing link down, and address is permanent
@@ -2671,10 +2672,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2671 if (how == 0 && 2672 if (how == 0 &&
2672 (ifa->flags&IFA_F_PERMANENT) && 2673 (ifa->flags&IFA_F_PERMANENT) &&
2673 !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { 2674 !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) {
2674 2675 list_move_tail(&ifa->if_list, &keep_list);
2675 /* Move to holding list */
2676 *bifa = ifa;
2677 bifa = &ifa->if_next;
2678 2676
2679 /* If not doing DAD on this address, just keep it. */ 2677 /* If not doing DAD on this address, just keep it. */
2680 if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || 2678 if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) ||
@@ -2690,6 +2688,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2690 ifa->flags |= IFA_F_TENTATIVE; 2688 ifa->flags |= IFA_F_TENTATIVE;
2691 in6_ifa_hold(ifa); 2689 in6_ifa_hold(ifa);
2692 } else { 2690 } else {
2691 list_del(&ifa->if_list);
2693 ifa->dead = 1; 2692 ifa->dead = 1;
2694 } 2693 }
2695 write_unlock_bh(&idev->lock); 2694 write_unlock_bh(&idev->lock);
@@ -2707,7 +2706,7 @@ static int addrconf_ifdown(struct net_device *dev, int how)
2707 write_lock_bh(&idev->lock); 2706 write_lock_bh(&idev->lock);
2708 } 2707 }
2709 2708
2710 idev->addr_list = keep_list; 2709 list_splice(&keep_list, &idev->addr_list);
2711 2710
2712 write_unlock_bh(&idev->lock); 2711 write_unlock_bh(&idev->lock);
2713 2712
@@ -2917,7 +2916,7 @@ static void addrconf_dad_run(struct inet6_dev *idev) {
2917 struct inet6_ifaddr *ifp; 2916 struct inet6_ifaddr *ifp;
2918 2917
2919 read_lock_bh(&idev->lock); 2918 read_lock_bh(&idev->lock);
2920 for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { 2919 list_for_each_entry(ifp, &idev->addr_list, if_list) {
2921 spin_lock(&ifp->lock); 2920 spin_lock(&ifp->lock);
2922 if (!(ifp->flags & IFA_F_TENTATIVE)) { 2921 if (!(ifp->flags & IFA_F_TENTATIVE)) {
2923 spin_unlock(&ifp->lock); 2922 spin_unlock(&ifp->lock);
@@ -3500,7 +3499,6 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3500 struct netlink_callback *cb, enum addr_type_t type, 3499 struct netlink_callback *cb, enum addr_type_t type,
3501 int s_ip_idx, int *p_ip_idx) 3500 int s_ip_idx, int *p_ip_idx)
3502{ 3501{
3503 struct inet6_ifaddr *ifa;
3504 struct ifmcaddr6 *ifmca; 3502 struct ifmcaddr6 *ifmca;
3505 struct ifacaddr6 *ifaca; 3503 struct ifacaddr6 *ifaca;
3506 int err = 1; 3504 int err = 1;
@@ -3508,11 +3506,12 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3508 3506
3509 read_lock_bh(&idev->lock); 3507 read_lock_bh(&idev->lock);
3510 switch (type) { 3508 switch (type) {
3511 case UNICAST_ADDR: 3509 case UNICAST_ADDR: {
3510 struct inet6_ifaddr *ifa;
3511
3512 /* unicast address incl. temp addr */ 3512 /* unicast address incl. temp addr */
3513 for (ifa = idev->addr_list; ifa; 3513 list_for_each_entry(ifa, &idev->addr_list, if_list) {
3514 ifa = ifa->if_next, ip_idx++) { 3514 if (++ip_idx < s_ip_idx)
3515 if (ip_idx < s_ip_idx)
3516 continue; 3515 continue;
3517 err = inet6_fill_ifaddr(skb, ifa, 3516 err = inet6_fill_ifaddr(skb, ifa,
3518 NETLINK_CB(cb->skb).pid, 3517 NETLINK_CB(cb->skb).pid,
@@ -3523,6 +3522,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3523 break; 3522 break;
3524 } 3523 }
3525 break; 3524 break;
3525 }
3526 case MULTICAST_ADDR: 3526 case MULTICAST_ADDR:
3527 /* multicast address */ 3527 /* multicast address */
3528 for (ifmca = idev->mc_list; ifmca; 3528 for (ifmca = idev->mc_list; ifmca;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 1d7ac70ba39f..240dceba06e5 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -371,7 +371,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
371 } 371 }
372 372
373 read_lock_bh(&in6_dev->lock); 373 read_lock_bh(&in6_dev->lock);
374 for (ifp = in6_dev->addr_list; ifp; ifp = ifp->if_next) { 374 list_for_each_entry(ifp, &in6_dev->addr_list, if_list) {
375 /* Add the address to the local list. */ 375 /* Add the address to the local list. */
376 addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC); 376 addr = t_new(struct sctp_sockaddr_entry, GFP_ATOMIC);
377 if (addr) { 377 if (addr) {