diff options
| author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
|---|---|---|
| committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
| commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
| tree | 644b88f8a71896307d71438e9b3af49126ffb22b /net/ipv6/addrconf.c | |
| parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
| parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) | |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'net/ipv6/addrconf.c')
| -rw-r--r-- | net/ipv6/addrconf.c | 493 |
1 files changed, 256 insertions, 237 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1fd0a3d775d2..413054f02aab 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #include <linux/route.h> | 53 | #include <linux/route.h> |
| 54 | #include <linux/inetdevice.h> | 54 | #include <linux/inetdevice.h> |
| 55 | #include <linux/init.h> | 55 | #include <linux/init.h> |
| 56 | #include <linux/slab.h> | ||
| 56 | #ifdef CONFIG_SYSCTL | 57 | #ifdef CONFIG_SYSCTL |
| 57 | #include <linux/sysctl.h> | 58 | #include <linux/sysctl.h> |
| 58 | #endif | 59 | #endif |
| @@ -278,31 +279,31 @@ static void addrconf_mod_timer(struct inet6_ifaddr *ifp, | |||
| 278 | 279 | ||
| 279 | static int snmp6_alloc_dev(struct inet6_dev *idev) | 280 | static int snmp6_alloc_dev(struct inet6_dev *idev) |
| 280 | { | 281 | { |
| 281 | if (snmp_mib_init((void **)idev->stats.ipv6, | 282 | if (snmp_mib_init((void __percpu **)idev->stats.ipv6, |
| 282 | sizeof(struct ipstats_mib)) < 0) | 283 | sizeof(struct ipstats_mib)) < 0) |
| 283 | goto err_ip; | 284 | goto err_ip; |
| 284 | if (snmp_mib_init((void **)idev->stats.icmpv6, | 285 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6, |
| 285 | sizeof(struct icmpv6_mib)) < 0) | 286 | sizeof(struct icmpv6_mib)) < 0) |
| 286 | goto err_icmp; | 287 | goto err_icmp; |
| 287 | if (snmp_mib_init((void **)idev->stats.icmpv6msg, | 288 | if (snmp_mib_init((void __percpu **)idev->stats.icmpv6msg, |
| 288 | sizeof(struct icmpv6msg_mib)) < 0) | 289 | sizeof(struct icmpv6msg_mib)) < 0) |
| 289 | goto err_icmpmsg; | 290 | goto err_icmpmsg; |
| 290 | 291 | ||
| 291 | return 0; | 292 | return 0; |
| 292 | 293 | ||
| 293 | err_icmpmsg: | 294 | err_icmpmsg: |
| 294 | snmp_mib_free((void **)idev->stats.icmpv6); | 295 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
| 295 | err_icmp: | 296 | err_icmp: |
| 296 | snmp_mib_free((void **)idev->stats.ipv6); | 297 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
| 297 | err_ip: | 298 | err_ip: |
| 298 | return -ENOMEM; | 299 | return -ENOMEM; |
| 299 | } | 300 | } |
| 300 | 301 | ||
| 301 | static void snmp6_free_dev(struct inet6_dev *idev) | 302 | static void snmp6_free_dev(struct inet6_dev *idev) |
| 302 | { | 303 | { |
| 303 | snmp_mib_free((void **)idev->stats.icmpv6msg); | 304 | snmp_mib_free((void __percpu **)idev->stats.icmpv6msg); |
| 304 | snmp_mib_free((void **)idev->stats.icmpv6); | 305 | snmp_mib_free((void __percpu **)idev->stats.icmpv6); |
| 305 | snmp_mib_free((void **)idev->stats.ipv6); | 306 | snmp_mib_free((void __percpu **)idev->stats.ipv6); |
| 306 | } | 307 | } |
| 307 | 308 | ||
| 308 | /* Nobody refers to this device, we may destroy it. */ | 309 | /* Nobody refers to this device, we may destroy it. */ |
| @@ -481,9 +482,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
| 481 | struct net_device *dev; | 482 | struct net_device *dev; |
| 482 | struct inet6_dev *idev; | 483 | struct inet6_dev *idev; |
| 483 | 484 | ||
| 484 | read_lock(&dev_base_lock); | 485 | rcu_read_lock(); |
| 485 | for_each_netdev(net, dev) { | 486 | for_each_netdev_rcu(net, dev) { |
| 486 | rcu_read_lock(); | ||
| 487 | idev = __in6_dev_get(dev); | 487 | idev = __in6_dev_get(dev); |
| 488 | if (idev) { | 488 | if (idev) { |
| 489 | int changed = (!idev->cnf.forwarding) ^ (!newf); | 489 | int changed = (!idev->cnf.forwarding) ^ (!newf); |
| @@ -491,9 +491,8 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
| 491 | if (changed) | 491 | if (changed) |
| 492 | dev_forward_change(idev); | 492 | dev_forward_change(idev); |
| 493 | } | 493 | } |
| 494 | rcu_read_unlock(); | ||
| 495 | } | 494 | } |
| 496 | read_unlock(&dev_base_lock); | 495 | rcu_read_unlock(); |
| 497 | } | 496 | } |
| 498 | 497 | ||
| 499 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | 498 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) |
| @@ -504,8 +503,11 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int old) | |||
| 504 | if (p == &net->ipv6.devconf_dflt->forwarding) | 503 | if (p == &net->ipv6.devconf_dflt->forwarding) |
| 505 | return 0; | 504 | return 0; |
| 506 | 505 | ||
| 507 | if (!rtnl_trylock()) | 506 | if (!rtnl_trylock()) { |
| 507 | /* Restore the original values before restarting */ | ||
| 508 | *p = old; | ||
| 508 | return restart_syscall(); | 509 | return restart_syscall(); |
| 510 | } | ||
| 509 | 511 | ||
| 510 | if (p == &net->ipv6.devconf_all->forwarding) { | 512 | if (p == &net->ipv6.devconf_all->forwarding) { |
| 511 | __s32 newf = net->ipv6.devconf_all->forwarding; | 513 | __s32 newf = net->ipv6.devconf_all->forwarding; |
| @@ -991,8 +993,7 @@ struct ipv6_saddr_dst { | |||
| 991 | 993 | ||
| 992 | static inline int ipv6_saddr_preferred(int type) | 994 | static inline int ipv6_saddr_preferred(int type) |
| 993 | { | 995 | { |
| 994 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| | 996 | if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4|IPV6_ADDR_LOOPBACK)) |
| 995 | IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) | ||
| 996 | return 1; | 997 | return 1; |
| 997 | return 0; | 998 | return 0; |
| 998 | } | 999 | } |
| @@ -1137,10 +1138,9 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | |||
| 1137 | hiscore->rule = -1; | 1138 | hiscore->rule = -1; |
| 1138 | hiscore->ifa = NULL; | 1139 | hiscore->ifa = NULL; |
| 1139 | 1140 | ||
| 1140 | read_lock(&dev_base_lock); | ||
| 1141 | rcu_read_lock(); | 1141 | rcu_read_lock(); |
| 1142 | 1142 | ||
| 1143 | for_each_netdev(net, dev) { | 1143 | for_each_netdev_rcu(net, dev) { |
| 1144 | struct inet6_dev *idev; | 1144 | struct inet6_dev *idev; |
| 1145 | 1145 | ||
| 1146 | /* Candidate Source Address (section 4) | 1146 | /* Candidate Source Address (section 4) |
| @@ -1235,7 +1235,6 @@ try_nextdev: | |||
| 1235 | read_unlock_bh(&idev->lock); | 1235 | read_unlock_bh(&idev->lock); |
| 1236 | } | 1236 | } |
| 1237 | rcu_read_unlock(); | 1237 | rcu_read_unlock(); |
| 1238 | read_unlock(&dev_base_lock); | ||
| 1239 | 1238 | ||
| 1240 | if (!hiscore->ifa) | 1239 | if (!hiscore->ifa) |
| 1241 | return -EADDRNOTAVAIL; | 1240 | return -EADDRNOTAVAIL; |
| @@ -1382,6 +1381,8 @@ static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) | |||
| 1382 | if (dad_failed) | 1381 | if (dad_failed) |
| 1383 | ifp->flags |= IFA_F_DADFAILED; | 1382 | ifp->flags |= IFA_F_DADFAILED; |
| 1384 | spin_unlock_bh(&ifp->lock); | 1383 | spin_unlock_bh(&ifp->lock); |
| 1384 | if (dad_failed) | ||
| 1385 | ipv6_ifa_notify(0, ifp); | ||
| 1385 | in6_ifa_put(ifp); | 1386 | in6_ifa_put(ifp); |
| 1386 | #ifdef CONFIG_IPV6_PRIVACY | 1387 | #ifdef CONFIG_IPV6_PRIVACY |
| 1387 | } else if (ifp->flags&IFA_F_TEMPORARY) { | 1388 | } else if (ifp->flags&IFA_F_TEMPORARY) { |
| @@ -2617,7 +2618,7 @@ static void addrconf_bonding_change(struct net_device *dev, unsigned long event) | |||
| 2617 | static int addrconf_ifdown(struct net_device *dev, int how) | 2618 | static int addrconf_ifdown(struct net_device *dev, int how) |
| 2618 | { | 2619 | { |
| 2619 | struct inet6_dev *idev; | 2620 | struct inet6_dev *idev; |
| 2620 | struct inet6_ifaddr *ifa, **bifa; | 2621 | struct inet6_ifaddr *ifa, *keep_list, **bifa; |
| 2621 | struct net *net = dev_net(dev); | 2622 | struct net *net = dev_net(dev); |
| 2622 | int i; | 2623 | int i; |
| 2623 | 2624 | ||
| @@ -2650,11 +2651,12 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2650 | 2651 | ||
| 2651 | write_lock_bh(&addrconf_hash_lock); | 2652 | write_lock_bh(&addrconf_hash_lock); |
| 2652 | while ((ifa = *bifa) != NULL) { | 2653 | while ((ifa = *bifa) != NULL) { |
| 2653 | if (ifa->idev == idev) { | 2654 | if (ifa->idev == idev && |
| 2655 | (how || !(ifa->flags&IFA_F_PERMANENT) || | ||
| 2656 | ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
| 2654 | *bifa = ifa->lst_next; | 2657 | *bifa = ifa->lst_next; |
| 2655 | ifa->lst_next = NULL; | 2658 | ifa->lst_next = NULL; |
| 2656 | addrconf_del_timer(ifa); | 2659 | __in6_ifa_put(ifa); |
| 2657 | in6_ifa_put(ifa); | ||
| 2658 | continue; | 2660 | continue; |
| 2659 | } | 2661 | } |
| 2660 | bifa = &ifa->lst_next; | 2662 | bifa = &ifa->lst_next; |
| @@ -2690,11 +2692,40 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2690 | write_lock_bh(&idev->lock); | 2692 | write_lock_bh(&idev->lock); |
| 2691 | } | 2693 | } |
| 2692 | #endif | 2694 | #endif |
| 2695 | keep_list = NULL; | ||
| 2696 | bifa = &keep_list; | ||
| 2693 | while ((ifa = idev->addr_list) != NULL) { | 2697 | while ((ifa = idev->addr_list) != NULL) { |
| 2694 | idev->addr_list = ifa->if_next; | 2698 | idev->addr_list = ifa->if_next; |
| 2695 | ifa->if_next = NULL; | 2699 | ifa->if_next = NULL; |
| 2696 | ifa->dead = 1; | 2700 | |
| 2697 | addrconf_del_timer(ifa); | 2701 | addrconf_del_timer(ifa); |
| 2702 | |||
| 2703 | /* If just doing link down, and address is permanent | ||
| 2704 | and not link-local, then retain it. */ | ||
| 2705 | if (how == 0 && | ||
| 2706 | (ifa->flags&IFA_F_PERMANENT) && | ||
| 2707 | !(ipv6_addr_type(&ifa->addr) & IPV6_ADDR_LINKLOCAL)) { | ||
| 2708 | |||
| 2709 | /* Move to holding list */ | ||
| 2710 | *bifa = ifa; | ||
| 2711 | bifa = &ifa->if_next; | ||
| 2712 | |||
| 2713 | /* If not doing DAD on this address, just keep it. */ | ||
| 2714 | if ((dev->flags&(IFF_NOARP|IFF_LOOPBACK)) || | ||
| 2715 | idev->cnf.accept_dad <= 0 || | ||
| 2716 | (ifa->flags & IFA_F_NODAD)) | ||
| 2717 | continue; | ||
| 2718 | |||
| 2719 | /* If it was tentative already, no need to notify */ | ||
| 2720 | if (ifa->flags & IFA_F_TENTATIVE) | ||
| 2721 | continue; | ||
| 2722 | |||
| 2723 | /* Flag it for later restoration when link comes up */ | ||
| 2724 | ifa->flags |= IFA_F_TENTATIVE; | ||
| 2725 | in6_ifa_hold(ifa); | ||
| 2726 | } else { | ||
| 2727 | ifa->dead = 1; | ||
| 2728 | } | ||
| 2698 | write_unlock_bh(&idev->lock); | 2729 | write_unlock_bh(&idev->lock); |
| 2699 | 2730 | ||
| 2700 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 2731 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
| @@ -2703,6 +2734,9 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2703 | 2734 | ||
| 2704 | write_lock_bh(&idev->lock); | 2735 | write_lock_bh(&idev->lock); |
| 2705 | } | 2736 | } |
| 2737 | |||
| 2738 | idev->addr_list = keep_list; | ||
| 2739 | |||
| 2706 | write_unlock_bh(&idev->lock); | 2740 | write_unlock_bh(&idev->lock); |
| 2707 | 2741 | ||
| 2708 | /* Step 5: Discard multicast list */ | 2742 | /* Step 5: Discard multicast list */ |
| @@ -2728,28 +2762,29 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2728 | static void addrconf_rs_timer(unsigned long data) | 2762 | static void addrconf_rs_timer(unsigned long data) |
| 2729 | { | 2763 | { |
| 2730 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; | 2764 | struct inet6_ifaddr *ifp = (struct inet6_ifaddr *) data; |
| 2765 | struct inet6_dev *idev = ifp->idev; | ||
| 2731 | 2766 | ||
| 2732 | if (ifp->idev->cnf.forwarding) | 2767 | read_lock(&idev->lock); |
| 2768 | if (idev->dead || !(idev->if_flags & IF_READY)) | ||
| 2733 | goto out; | 2769 | goto out; |
| 2734 | 2770 | ||
| 2735 | if (ifp->idev->if_flags & IF_RA_RCVD) { | 2771 | if (idev->cnf.forwarding) |
| 2736 | /* | 2772 | goto out; |
| 2737 | * Announcement received after solicitation | 2773 | |
| 2738 | * was sent | 2774 | /* Announcement received after solicitation was sent */ |
| 2739 | */ | 2775 | if (idev->if_flags & IF_RA_RCVD) |
| 2740 | goto out; | 2776 | goto out; |
| 2741 | } | ||
| 2742 | 2777 | ||
| 2743 | spin_lock(&ifp->lock); | 2778 | spin_lock(&ifp->lock); |
| 2744 | if (ifp->probes++ < ifp->idev->cnf.rtr_solicits) { | 2779 | if (ifp->probes++ < idev->cnf.rtr_solicits) { |
| 2745 | /* The wait after the last probe can be shorter */ | 2780 | /* The wait after the last probe can be shorter */ |
| 2746 | addrconf_mod_timer(ifp, AC_RS, | 2781 | addrconf_mod_timer(ifp, AC_RS, |
| 2747 | (ifp->probes == ifp->idev->cnf.rtr_solicits) ? | 2782 | (ifp->probes == idev->cnf.rtr_solicits) ? |
| 2748 | ifp->idev->cnf.rtr_solicit_delay : | 2783 | idev->cnf.rtr_solicit_delay : |
| 2749 | ifp->idev->cnf.rtr_solicit_interval); | 2784 | idev->cnf.rtr_solicit_interval); |
| 2750 | spin_unlock(&ifp->lock); | 2785 | spin_unlock(&ifp->lock); |
| 2751 | 2786 | ||
| 2752 | ndisc_send_rs(ifp->idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); | 2787 | ndisc_send_rs(idev->dev, &ifp->addr, &in6addr_linklocal_allrouters); |
| 2753 | } else { | 2788 | } else { |
| 2754 | spin_unlock(&ifp->lock); | 2789 | spin_unlock(&ifp->lock); |
| 2755 | /* | 2790 | /* |
| @@ -2757,10 +2792,11 @@ static void addrconf_rs_timer(unsigned long data) | |||
| 2757 | * assumption any longer. | 2792 | * assumption any longer. |
| 2758 | */ | 2793 | */ |
| 2759 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", | 2794 | printk(KERN_DEBUG "%s: no IPv6 routers present\n", |
| 2760 | ifp->idev->dev->name); | 2795 | idev->dev->name); |
| 2761 | } | 2796 | } |
| 2762 | 2797 | ||
| 2763 | out: | 2798 | out: |
| 2799 | read_unlock(&idev->lock); | ||
| 2764 | in6_ifa_put(ifp); | 2800 | in6_ifa_put(ifp); |
| 2765 | } | 2801 | } |
| 2766 | 2802 | ||
| @@ -2793,14 +2829,14 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2793 | read_lock_bh(&idev->lock); | 2829 | read_lock_bh(&idev->lock); |
| 2794 | if (ifp->dead) | 2830 | if (ifp->dead) |
| 2795 | goto out; | 2831 | goto out; |
| 2796 | spin_lock_bh(&ifp->lock); | ||
| 2797 | 2832 | ||
| 2833 | spin_lock(&ifp->lock); | ||
| 2798 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || | 2834 | if (dev->flags&(IFF_NOARP|IFF_LOOPBACK) || |
| 2799 | idev->cnf.accept_dad < 1 || | 2835 | idev->cnf.accept_dad < 1 || |
| 2800 | !(ifp->flags&IFA_F_TENTATIVE) || | 2836 | !(ifp->flags&IFA_F_TENTATIVE) || |
| 2801 | ifp->flags & IFA_F_NODAD) { | 2837 | ifp->flags & IFA_F_NODAD) { |
| 2802 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2838 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
| 2803 | spin_unlock_bh(&ifp->lock); | 2839 | spin_unlock(&ifp->lock); |
| 2804 | read_unlock_bh(&idev->lock); | 2840 | read_unlock_bh(&idev->lock); |
| 2805 | 2841 | ||
| 2806 | addrconf_dad_completed(ifp); | 2842 | addrconf_dad_completed(ifp); |
| @@ -2808,7 +2844,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2808 | } | 2844 | } |
| 2809 | 2845 | ||
| 2810 | if (!(idev->if_flags & IF_READY)) { | 2846 | if (!(idev->if_flags & IF_READY)) { |
| 2811 | spin_unlock_bh(&ifp->lock); | 2847 | spin_unlock(&ifp->lock); |
| 2812 | read_unlock_bh(&idev->lock); | 2848 | read_unlock_bh(&idev->lock); |
| 2813 | /* | 2849 | /* |
| 2814 | * If the device is not ready: | 2850 | * If the device is not ready: |
| @@ -2828,7 +2864,7 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) | |||
| 2828 | ip6_ins_rt(ifp->rt); | 2864 | ip6_ins_rt(ifp->rt); |
| 2829 | 2865 | ||
| 2830 | addrconf_dad_kick(ifp); | 2866 | addrconf_dad_kick(ifp); |
| 2831 | spin_unlock_bh(&ifp->lock); | 2867 | spin_unlock(&ifp->lock); |
| 2832 | out: | 2868 | out: |
| 2833 | read_unlock_bh(&idev->lock); | 2869 | read_unlock_bh(&idev->lock); |
| 2834 | } | 2870 | } |
| @@ -2839,20 +2875,21 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2839 | struct inet6_dev *idev = ifp->idev; | 2875 | struct inet6_dev *idev = ifp->idev; |
| 2840 | struct in6_addr mcaddr; | 2876 | struct in6_addr mcaddr; |
| 2841 | 2877 | ||
| 2842 | read_lock_bh(&idev->lock); | 2878 | read_lock(&idev->lock); |
| 2843 | if (idev->dead) { | 2879 | if (idev->dead || !(idev->if_flags & IF_READY)) { |
| 2844 | read_unlock_bh(&idev->lock); | 2880 | read_unlock(&idev->lock); |
| 2845 | goto out; | 2881 | goto out; |
| 2846 | } | 2882 | } |
| 2847 | spin_lock_bh(&ifp->lock); | 2883 | |
| 2884 | spin_lock(&ifp->lock); | ||
| 2848 | if (ifp->probes == 0) { | 2885 | if (ifp->probes == 0) { |
| 2849 | /* | 2886 | /* |
| 2850 | * DAD was successful | 2887 | * DAD was successful |
| 2851 | */ | 2888 | */ |
| 2852 | 2889 | ||
| 2853 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); | 2890 | ifp->flags &= ~(IFA_F_TENTATIVE|IFA_F_OPTIMISTIC|IFA_F_DADFAILED); |
| 2854 | spin_unlock_bh(&ifp->lock); | 2891 | spin_unlock(&ifp->lock); |
| 2855 | read_unlock_bh(&idev->lock); | 2892 | read_unlock(&idev->lock); |
| 2856 | 2893 | ||
| 2857 | addrconf_dad_completed(ifp); | 2894 | addrconf_dad_completed(ifp); |
| 2858 | 2895 | ||
| @@ -2861,8 +2898,8 @@ static void addrconf_dad_timer(unsigned long data) | |||
| 2861 | 2898 | ||
| 2862 | ifp->probes--; | 2899 | ifp->probes--; |
| 2863 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); | 2900 | addrconf_mod_timer(ifp, AC_DAD, ifp->idev->nd_parms->retrans_time); |
| 2864 | spin_unlock_bh(&ifp->lock); | 2901 | spin_unlock(&ifp->lock); |
| 2865 | read_unlock_bh(&idev->lock); | 2902 | read_unlock(&idev->lock); |
| 2866 | 2903 | ||
| 2867 | /* send a neighbour solicitation for our addr */ | 2904 | /* send a neighbour solicitation for our addr */ |
| 2868 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); | 2905 | addrconf_addr_solict_mult(&ifp->addr, &mcaddr); |
| @@ -2909,12 +2946,12 @@ static void addrconf_dad_run(struct inet6_dev *idev) { | |||
| 2909 | 2946 | ||
| 2910 | read_lock_bh(&idev->lock); | 2947 | read_lock_bh(&idev->lock); |
| 2911 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { | 2948 | for (ifp = idev->addr_list; ifp; ifp = ifp->if_next) { |
| 2912 | spin_lock_bh(&ifp->lock); | 2949 | spin_lock(&ifp->lock); |
| 2913 | if (!(ifp->flags & IFA_F_TENTATIVE)) { | 2950 | if (!(ifp->flags & IFA_F_TENTATIVE)) { |
| 2914 | spin_unlock_bh(&ifp->lock); | 2951 | spin_unlock(&ifp->lock); |
| 2915 | continue; | 2952 | continue; |
| 2916 | } | 2953 | } |
| 2917 | spin_unlock_bh(&ifp->lock); | 2954 | spin_unlock(&ifp->lock); |
| 2918 | addrconf_dad_kick(ifp); | 2955 | addrconf_dad_kick(ifp); |
| 2919 | } | 2956 | } |
| 2920 | read_unlock_bh(&idev->lock); | 2957 | read_unlock_bh(&idev->lock); |
| @@ -3031,14 +3068,14 @@ static const struct file_operations if6_fops = { | |||
| 3031 | .release = seq_release_net, | 3068 | .release = seq_release_net, |
| 3032 | }; | 3069 | }; |
| 3033 | 3070 | ||
| 3034 | static int if6_proc_net_init(struct net *net) | 3071 | static int __net_init if6_proc_net_init(struct net *net) |
| 3035 | { | 3072 | { |
| 3036 | if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) | 3073 | if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) |
| 3037 | return -ENOMEM; | 3074 | return -ENOMEM; |
| 3038 | return 0; | 3075 | return 0; |
| 3039 | } | 3076 | } |
| 3040 | 3077 | ||
| 3041 | static void if6_proc_net_exit(struct net *net) | 3078 | static void __net_exit if6_proc_net_exit(struct net *net) |
| 3042 | { | 3079 | { |
| 3043 | proc_net_remove(net, "if_inet6"); | 3080 | proc_net_remove(net, "if_inet6"); |
| 3044 | } | 3081 | } |
| @@ -3485,85 +3522,114 @@ enum addr_type_t | |||
| 3485 | ANYCAST_ADDR, | 3522 | ANYCAST_ADDR, |
| 3486 | }; | 3523 | }; |
| 3487 | 3524 | ||
| 3525 | /* called with rcu_read_lock() */ | ||
| 3526 | static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, | ||
| 3527 | struct netlink_callback *cb, enum addr_type_t type, | ||
| 3528 | int s_ip_idx, int *p_ip_idx) | ||
| 3529 | { | ||
| 3530 | struct inet6_ifaddr *ifa; | ||
| 3531 | struct ifmcaddr6 *ifmca; | ||
| 3532 | struct ifacaddr6 *ifaca; | ||
| 3533 | int err = 1; | ||
| 3534 | int ip_idx = *p_ip_idx; | ||
| 3535 | |||
| 3536 | read_lock_bh(&idev->lock); | ||
| 3537 | switch (type) { | ||
| 3538 | case UNICAST_ADDR: | ||
| 3539 | /* unicast address incl. temp addr */ | ||
| 3540 | for (ifa = idev->addr_list; ifa; | ||
| 3541 | ifa = ifa->if_next, ip_idx++) { | ||
| 3542 | if (ip_idx < s_ip_idx) | ||
| 3543 | continue; | ||
| 3544 | err = inet6_fill_ifaddr(skb, ifa, | ||
| 3545 | NETLINK_CB(cb->skb).pid, | ||
| 3546 | cb->nlh->nlmsg_seq, | ||
| 3547 | RTM_NEWADDR, | ||
| 3548 | NLM_F_MULTI); | ||
| 3549 | if (err <= 0) | ||
| 3550 | break; | ||
| 3551 | } | ||
| 3552 | break; | ||
| 3553 | case MULTICAST_ADDR: | ||
| 3554 | /* multicast address */ | ||
| 3555 | for (ifmca = idev->mc_list; ifmca; | ||
| 3556 | ifmca = ifmca->next, ip_idx++) { | ||
| 3557 | if (ip_idx < s_ip_idx) | ||
| 3558 | continue; | ||
| 3559 | err = inet6_fill_ifmcaddr(skb, ifmca, | ||
| 3560 | NETLINK_CB(cb->skb).pid, | ||
| 3561 | cb->nlh->nlmsg_seq, | ||
| 3562 | RTM_GETMULTICAST, | ||
| 3563 | NLM_F_MULTI); | ||
| 3564 | if (err <= 0) | ||
| 3565 | break; | ||
| 3566 | } | ||
| 3567 | break; | ||
| 3568 | case ANYCAST_ADDR: | ||
| 3569 | /* anycast address */ | ||
| 3570 | for (ifaca = idev->ac_list; ifaca; | ||
| 3571 | ifaca = ifaca->aca_next, ip_idx++) { | ||
| 3572 | if (ip_idx < s_ip_idx) | ||
| 3573 | continue; | ||
| 3574 | err = inet6_fill_ifacaddr(skb, ifaca, | ||
| 3575 | NETLINK_CB(cb->skb).pid, | ||
| 3576 | cb->nlh->nlmsg_seq, | ||
| 3577 | RTM_GETANYCAST, | ||
| 3578 | NLM_F_MULTI); | ||
| 3579 | if (err <= 0) | ||
| 3580 | break; | ||
| 3581 | } | ||
| 3582 | break; | ||
| 3583 | default: | ||
| 3584 | break; | ||
| 3585 | } | ||
| 3586 | read_unlock_bh(&idev->lock); | ||
| 3587 | *p_ip_idx = ip_idx; | ||
| 3588 | return err; | ||
| 3589 | } | ||
| 3590 | |||
| 3488 | static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, | 3591 | static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, |
| 3489 | enum addr_type_t type) | 3592 | enum addr_type_t type) |
| 3490 | { | 3593 | { |
| 3594 | struct net *net = sock_net(skb->sk); | ||
| 3595 | int h, s_h; | ||
| 3491 | int idx, ip_idx; | 3596 | int idx, ip_idx; |
| 3492 | int s_idx, s_ip_idx; | 3597 | int s_idx, s_ip_idx; |
| 3493 | int err = 1; | ||
| 3494 | struct net_device *dev; | 3598 | struct net_device *dev; |
| 3495 | struct inet6_dev *idev = NULL; | 3599 | struct inet6_dev *idev; |
| 3496 | struct inet6_ifaddr *ifa; | 3600 | struct hlist_head *head; |
| 3497 | struct ifmcaddr6 *ifmca; | 3601 | struct hlist_node *node; |
| 3498 | struct ifacaddr6 *ifaca; | ||
| 3499 | struct net *net = sock_net(skb->sk); | ||
| 3500 | 3602 | ||
| 3501 | s_idx = cb->args[0]; | 3603 | s_h = cb->args[0]; |
| 3502 | s_ip_idx = ip_idx = cb->args[1]; | 3604 | s_idx = idx = cb->args[1]; |
| 3605 | s_ip_idx = ip_idx = cb->args[2]; | ||
| 3503 | 3606 | ||
| 3504 | idx = 0; | 3607 | rcu_read_lock(); |
| 3505 | for_each_netdev(net, dev) { | 3608 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
| 3506 | if (idx < s_idx) | 3609 | idx = 0; |
| 3507 | goto cont; | 3610 | head = &net->dev_index_head[h]; |
| 3508 | if (idx > s_idx) | 3611 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
| 3509 | s_ip_idx = 0; | 3612 | if (idx < s_idx) |
| 3510 | ip_idx = 0; | 3613 | goto cont; |
| 3511 | if ((idev = in6_dev_get(dev)) == NULL) | 3614 | if (h > s_h || idx > s_idx) |
| 3512 | goto cont; | 3615 | s_ip_idx = 0; |
| 3513 | read_lock_bh(&idev->lock); | 3616 | ip_idx = 0; |
| 3514 | switch (type) { | 3617 | if ((idev = __in6_dev_get(dev)) == NULL) |
| 3515 | case UNICAST_ADDR: | 3618 | goto cont; |
| 3516 | /* unicast address incl. temp addr */ | 3619 | |
| 3517 | for (ifa = idev->addr_list; ifa; | 3620 | if (in6_dump_addrs(idev, skb, cb, type, |
| 3518 | ifa = ifa->if_next, ip_idx++) { | 3621 | s_ip_idx, &ip_idx) <= 0) |
| 3519 | if (ip_idx < s_ip_idx) | 3622 | goto done; |
| 3520 | continue; | ||
| 3521 | err = inet6_fill_ifaddr(skb, ifa, | ||
| 3522 | NETLINK_CB(cb->skb).pid, | ||
| 3523 | cb->nlh->nlmsg_seq, | ||
| 3524 | RTM_NEWADDR, | ||
| 3525 | NLM_F_MULTI); | ||
| 3526 | } | ||
| 3527 | break; | ||
| 3528 | case MULTICAST_ADDR: | ||
| 3529 | /* multicast address */ | ||
| 3530 | for (ifmca = idev->mc_list; ifmca; | ||
| 3531 | ifmca = ifmca->next, ip_idx++) { | ||
| 3532 | if (ip_idx < s_ip_idx) | ||
| 3533 | continue; | ||
| 3534 | err = inet6_fill_ifmcaddr(skb, ifmca, | ||
| 3535 | NETLINK_CB(cb->skb).pid, | ||
| 3536 | cb->nlh->nlmsg_seq, | ||
| 3537 | RTM_GETMULTICAST, | ||
| 3538 | NLM_F_MULTI); | ||
| 3539 | } | ||
| 3540 | break; | ||
| 3541 | case ANYCAST_ADDR: | ||
| 3542 | /* anycast address */ | ||
| 3543 | for (ifaca = idev->ac_list; ifaca; | ||
| 3544 | ifaca = ifaca->aca_next, ip_idx++) { | ||
| 3545 | if (ip_idx < s_ip_idx) | ||
| 3546 | continue; | ||
| 3547 | err = inet6_fill_ifacaddr(skb, ifaca, | ||
| 3548 | NETLINK_CB(cb->skb).pid, | ||
| 3549 | cb->nlh->nlmsg_seq, | ||
| 3550 | RTM_GETANYCAST, | ||
| 3551 | NLM_F_MULTI); | ||
| 3552 | } | ||
| 3553 | break; | ||
| 3554 | default: | ||
| 3555 | break; | ||
| 3556 | } | ||
| 3557 | read_unlock_bh(&idev->lock); | ||
| 3558 | in6_dev_put(idev); | ||
| 3559 | |||
| 3560 | if (err <= 0) | ||
| 3561 | break; | ||
| 3562 | cont: | 3623 | cont: |
| 3563 | idx++; | 3624 | idx++; |
| 3625 | } | ||
| 3564 | } | 3626 | } |
| 3565 | cb->args[0] = idx; | 3627 | done: |
| 3566 | cb->args[1] = ip_idx; | 3628 | rcu_read_unlock(); |
| 3629 | cb->args[0] = h; | ||
| 3630 | cb->args[1] = idx; | ||
| 3631 | cb->args[2] = ip_idx; | ||
| 3632 | |||
| 3567 | return skb->len; | 3633 | return skb->len; |
| 3568 | } | 3634 | } |
| 3569 | 3635 | ||
| @@ -3708,6 +3774,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
| 3708 | #endif | 3774 | #endif |
| 3709 | array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; | 3775 | array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6; |
| 3710 | array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; | 3776 | array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad; |
| 3777 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; | ||
| 3711 | } | 3778 | } |
| 3712 | 3779 | ||
| 3713 | static inline size_t inet6_if_nlmsg_size(void) | 3780 | static inline size_t inet6_if_nlmsg_size(void) |
| @@ -3726,8 +3793,8 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
| 3726 | ); | 3793 | ); |
| 3727 | } | 3794 | } |
| 3728 | 3795 | ||
| 3729 | static inline void __snmp6_fill_stats(u64 *stats, void **mib, int items, | 3796 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, |
| 3730 | int bytes) | 3797 | int items, int bytes) |
| 3731 | { | 3798 | { |
| 3732 | int i; | 3799 | int i; |
| 3733 | int pad = bytes - sizeof(u64) * items; | 3800 | int pad = bytes - sizeof(u64) * items; |
| @@ -3746,10 +3813,10 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | |||
| 3746 | { | 3813 | { |
| 3747 | switch(attrtype) { | 3814 | switch(attrtype) { |
| 3748 | case IFLA_INET6_STATS: | 3815 | case IFLA_INET6_STATS: |
| 3749 | __snmp6_fill_stats(stats, (void **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); | 3816 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.ipv6, IPSTATS_MIB_MAX, bytes); |
| 3750 | break; | 3817 | break; |
| 3751 | case IFLA_INET6_ICMP6STATS: | 3818 | case IFLA_INET6_ICMP6STATS: |
| 3752 | __snmp6_fill_stats(stats, (void **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); | 3819 | __snmp6_fill_stats(stats, (void __percpu **)idev->stats.icmpv6, ICMP6_MIB_MAX, bytes); |
| 3753 | break; | 3820 | break; |
| 3754 | } | 3821 | } |
| 3755 | } | 3822 | } |
| @@ -3826,28 +3893,39 @@ nla_put_failure: | |||
| 3826 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 3893 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
| 3827 | { | 3894 | { |
| 3828 | struct net *net = sock_net(skb->sk); | 3895 | struct net *net = sock_net(skb->sk); |
| 3829 | int idx, err; | 3896 | int h, s_h; |
| 3830 | int s_idx = cb->args[0]; | 3897 | int idx = 0, s_idx; |
| 3831 | struct net_device *dev; | 3898 | struct net_device *dev; |
| 3832 | struct inet6_dev *idev; | 3899 | struct inet6_dev *idev; |
| 3900 | struct hlist_head *head; | ||
| 3901 | struct hlist_node *node; | ||
| 3833 | 3902 | ||
| 3834 | read_lock(&dev_base_lock); | 3903 | s_h = cb->args[0]; |
| 3835 | idx = 0; | 3904 | s_idx = cb->args[1]; |
| 3836 | for_each_netdev(net, dev) { | 3905 | |
| 3837 | if (idx < s_idx) | 3906 | rcu_read_lock(); |
| 3838 | goto cont; | 3907 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
| 3839 | if ((idev = in6_dev_get(dev)) == NULL) | 3908 | idx = 0; |
| 3840 | goto cont; | 3909 | head = &net->dev_index_head[h]; |
| 3841 | err = inet6_fill_ifinfo(skb, idev, NETLINK_CB(cb->skb).pid, | 3910 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
| 3842 | cb->nlh->nlmsg_seq, RTM_NEWLINK, NLM_F_MULTI); | 3911 | if (idx < s_idx) |
| 3843 | in6_dev_put(idev); | 3912 | goto cont; |
| 3844 | if (err <= 0) | 3913 | idev = __in6_dev_get(dev); |
| 3845 | break; | 3914 | if (!idev) |
| 3915 | goto cont; | ||
| 3916 | if (inet6_fill_ifinfo(skb, idev, | ||
| 3917 | NETLINK_CB(cb->skb).pid, | ||
| 3918 | cb->nlh->nlmsg_seq, | ||
| 3919 | RTM_NEWLINK, NLM_F_MULTI) <= 0) | ||
| 3920 | goto out; | ||
| 3846 | cont: | 3921 | cont: |
| 3847 | idx++; | 3922 | idx++; |
| 3923 | } | ||
| 3848 | } | 3924 | } |
| 3849 | read_unlock(&dev_base_lock); | 3925 | out: |
| 3850 | cb->args[0] = idx; | 3926 | rcu_read_unlock(); |
| 3927 | cb->args[1] = idx; | ||
| 3928 | cb->args[0] = h; | ||
| 3851 | 3929 | ||
| 3852 | return skb->len; | 3930 | return skb->len; |
| 3853 | } | 3931 | } |
| @@ -3991,50 +4069,18 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, | |||
| 3991 | { | 4069 | { |
| 3992 | int *valp = ctl->data; | 4070 | int *valp = ctl->data; |
| 3993 | int val = *valp; | 4071 | int val = *valp; |
| 4072 | loff_t pos = *ppos; | ||
| 3994 | int ret; | 4073 | int ret; |
| 3995 | 4074 | ||
| 3996 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4075 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
| 3997 | 4076 | ||
| 3998 | if (write) | 4077 | if (write) |
| 3999 | ret = addrconf_fixup_forwarding(ctl, valp, val); | 4078 | ret = addrconf_fixup_forwarding(ctl, valp, val); |
| 4079 | if (ret) | ||
| 4080 | *ppos = pos; | ||
| 4000 | return ret; | 4081 | return ret; |
| 4001 | } | 4082 | } |
| 4002 | 4083 | ||
| 4003 | static int addrconf_sysctl_forward_strategy(ctl_table *table, | ||
| 4004 | void __user *oldval, | ||
| 4005 | size_t __user *oldlenp, | ||
| 4006 | void __user *newval, size_t newlen) | ||
| 4007 | { | ||
| 4008 | int *valp = table->data; | ||
| 4009 | int val = *valp; | ||
| 4010 | int new; | ||
| 4011 | |||
| 4012 | if (!newval || !newlen) | ||
| 4013 | return 0; | ||
| 4014 | if (newlen != sizeof(int)) | ||
| 4015 | return -EINVAL; | ||
| 4016 | if (get_user(new, (int __user *)newval)) | ||
| 4017 | return -EFAULT; | ||
| 4018 | if (new == *valp) | ||
| 4019 | return 0; | ||
| 4020 | if (oldval && oldlenp) { | ||
| 4021 | size_t len; | ||
| 4022 | if (get_user(len, oldlenp)) | ||
| 4023 | return -EFAULT; | ||
| 4024 | if (len) { | ||
| 4025 | if (len > table->maxlen) | ||
| 4026 | len = table->maxlen; | ||
| 4027 | if (copy_to_user(oldval, valp, len)) | ||
| 4028 | return -EFAULT; | ||
| 4029 | if (put_user(len, oldlenp)) | ||
| 4030 | return -EFAULT; | ||
| 4031 | } | ||
| 4032 | } | ||
| 4033 | |||
| 4034 | *valp = new; | ||
| 4035 | return addrconf_fixup_forwarding(table, valp, val); | ||
| 4036 | } | ||
| 4037 | |||
| 4038 | static void dev_disable_change(struct inet6_dev *idev) | 4084 | static void dev_disable_change(struct inet6_dev *idev) |
| 4039 | { | 4085 | { |
| 4040 | if (!idev || !idev->dev) | 4086 | if (!idev || !idev->dev) |
| @@ -4051,9 +4097,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
| 4051 | struct net_device *dev; | 4097 | struct net_device *dev; |
| 4052 | struct inet6_dev *idev; | 4098 | struct inet6_dev *idev; |
| 4053 | 4099 | ||
| 4054 | read_lock(&dev_base_lock); | 4100 | rcu_read_lock(); |
| 4055 | for_each_netdev(net, dev) { | 4101 | for_each_netdev_rcu(net, dev) { |
| 4056 | rcu_read_lock(); | ||
| 4057 | idev = __in6_dev_get(dev); | 4102 | idev = __in6_dev_get(dev); |
| 4058 | if (idev) { | 4103 | if (idev) { |
| 4059 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); | 4104 | int changed = (!idev->cnf.disable_ipv6) ^ (!newf); |
| @@ -4061,9 +4106,8 @@ static void addrconf_disable_change(struct net *net, __s32 newf) | |||
| 4061 | if (changed) | 4106 | if (changed) |
| 4062 | dev_disable_change(idev); | 4107 | dev_disable_change(idev); |
| 4063 | } | 4108 | } |
| 4064 | rcu_read_unlock(); | ||
| 4065 | } | 4109 | } |
| 4066 | read_unlock(&dev_base_lock); | 4110 | rcu_read_unlock(); |
| 4067 | } | 4111 | } |
| 4068 | 4112 | ||
| 4069 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | 4113 | static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) |
| @@ -4075,8 +4119,11 @@ static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int old) | |||
| 4075 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) | 4119 | if (p == &net->ipv6.devconf_dflt->disable_ipv6) |
| 4076 | return 0; | 4120 | return 0; |
| 4077 | 4121 | ||
| 4078 | if (!rtnl_trylock()) | 4122 | if (!rtnl_trylock()) { |
| 4123 | /* Restore the original values before restarting */ | ||
| 4124 | *p = old; | ||
| 4079 | return restart_syscall(); | 4125 | return restart_syscall(); |
| 4126 | } | ||
| 4080 | 4127 | ||
| 4081 | if (p == &net->ipv6.devconf_all->disable_ipv6) { | 4128 | if (p == &net->ipv6.devconf_all->disable_ipv6) { |
| 4082 | __s32 newf = net->ipv6.devconf_all->disable_ipv6; | 4129 | __s32 newf = net->ipv6.devconf_all->disable_ipv6; |
| @@ -4095,12 +4142,15 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, | |||
| 4095 | { | 4142 | { |
| 4096 | int *valp = ctl->data; | 4143 | int *valp = ctl->data; |
| 4097 | int val = *valp; | 4144 | int val = *valp; |
| 4145 | loff_t pos = *ppos; | ||
| 4098 | int ret; | 4146 | int ret; |
| 4099 | 4147 | ||
| 4100 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); | 4148 | ret = proc_dointvec(ctl, write, buffer, lenp, ppos); |
| 4101 | 4149 | ||
| 4102 | if (write) | 4150 | if (write) |
| 4103 | ret = addrconf_disable_ipv6(ctl, valp, val); | 4151 | ret = addrconf_disable_ipv6(ctl, valp, val); |
| 4152 | if (ret) | ||
| 4153 | *ppos = pos; | ||
| 4104 | return ret; | 4154 | return ret; |
| 4105 | } | 4155 | } |
| 4106 | 4156 | ||
| @@ -4113,16 +4163,13 @@ static struct addrconf_sysctl_table | |||
| 4113 | .sysctl_header = NULL, | 4163 | .sysctl_header = NULL, |
| 4114 | .addrconf_vars = { | 4164 | .addrconf_vars = { |
| 4115 | { | 4165 | { |
| 4116 | .ctl_name = NET_IPV6_FORWARDING, | ||
| 4117 | .procname = "forwarding", | 4166 | .procname = "forwarding", |
| 4118 | .data = &ipv6_devconf.forwarding, | 4167 | .data = &ipv6_devconf.forwarding, |
| 4119 | .maxlen = sizeof(int), | 4168 | .maxlen = sizeof(int), |
| 4120 | .mode = 0644, | 4169 | .mode = 0644, |
| 4121 | .proc_handler = addrconf_sysctl_forward, | 4170 | .proc_handler = addrconf_sysctl_forward, |
| 4122 | .strategy = addrconf_sysctl_forward_strategy, | ||
| 4123 | }, | 4171 | }, |
| 4124 | { | 4172 | { |
| 4125 | .ctl_name = NET_IPV6_HOP_LIMIT, | ||
| 4126 | .procname = "hop_limit", | 4173 | .procname = "hop_limit", |
| 4127 | .data = &ipv6_devconf.hop_limit, | 4174 | .data = &ipv6_devconf.hop_limit, |
| 4128 | .maxlen = sizeof(int), | 4175 | .maxlen = sizeof(int), |
| @@ -4130,7 +4177,6 @@ static struct addrconf_sysctl_table | |||
| 4130 | .proc_handler = proc_dointvec, | 4177 | .proc_handler = proc_dointvec, |
| 4131 | }, | 4178 | }, |
| 4132 | { | 4179 | { |
| 4133 | .ctl_name = NET_IPV6_MTU, | ||
| 4134 | .procname = "mtu", | 4180 | .procname = "mtu", |
| 4135 | .data = &ipv6_devconf.mtu6, | 4181 | .data = &ipv6_devconf.mtu6, |
| 4136 | .maxlen = sizeof(int), | 4182 | .maxlen = sizeof(int), |
| @@ -4138,7 +4184,6 @@ static struct addrconf_sysctl_table | |||
| 4138 | .proc_handler = proc_dointvec, | 4184 | .proc_handler = proc_dointvec, |
| 4139 | }, | 4185 | }, |
| 4140 | { | 4186 | { |
| 4141 | .ctl_name = NET_IPV6_ACCEPT_RA, | ||
| 4142 | .procname = "accept_ra", | 4187 | .procname = "accept_ra", |
| 4143 | .data = &ipv6_devconf.accept_ra, | 4188 | .data = &ipv6_devconf.accept_ra, |
| 4144 | .maxlen = sizeof(int), | 4189 | .maxlen = sizeof(int), |
| @@ -4146,7 +4191,6 @@ static struct addrconf_sysctl_table | |||
| 4146 | .proc_handler = proc_dointvec, | 4191 | .proc_handler = proc_dointvec, |
| 4147 | }, | 4192 | }, |
| 4148 | { | 4193 | { |
| 4149 | .ctl_name = NET_IPV6_ACCEPT_REDIRECTS, | ||
| 4150 | .procname = "accept_redirects", | 4194 | .procname = "accept_redirects", |
| 4151 | .data = &ipv6_devconf.accept_redirects, | 4195 | .data = &ipv6_devconf.accept_redirects, |
| 4152 | .maxlen = sizeof(int), | 4196 | .maxlen = sizeof(int), |
| @@ -4154,7 +4198,6 @@ static struct addrconf_sysctl_table | |||
| 4154 | .proc_handler = proc_dointvec, | 4198 | .proc_handler = proc_dointvec, |
| 4155 | }, | 4199 | }, |
| 4156 | { | 4200 | { |
| 4157 | .ctl_name = NET_IPV6_AUTOCONF, | ||
| 4158 | .procname = "autoconf", | 4201 | .procname = "autoconf", |
| 4159 | .data = &ipv6_devconf.autoconf, | 4202 | .data = &ipv6_devconf.autoconf, |
| 4160 | .maxlen = sizeof(int), | 4203 | .maxlen = sizeof(int), |
| @@ -4162,7 +4205,6 @@ static struct addrconf_sysctl_table | |||
| 4162 | .proc_handler = proc_dointvec, | 4205 | .proc_handler = proc_dointvec, |
| 4163 | }, | 4206 | }, |
| 4164 | { | 4207 | { |
| 4165 | .ctl_name = NET_IPV6_DAD_TRANSMITS, | ||
| 4166 | .procname = "dad_transmits", | 4208 | .procname = "dad_transmits", |
| 4167 | .data = &ipv6_devconf.dad_transmits, | 4209 | .data = &ipv6_devconf.dad_transmits, |
| 4168 | .maxlen = sizeof(int), | 4210 | .maxlen = sizeof(int), |
| @@ -4170,7 +4212,6 @@ static struct addrconf_sysctl_table | |||
| 4170 | .proc_handler = proc_dointvec, | 4212 | .proc_handler = proc_dointvec, |
| 4171 | }, | 4213 | }, |
| 4172 | { | 4214 | { |
| 4173 | .ctl_name = NET_IPV6_RTR_SOLICITS, | ||
| 4174 | .procname = "router_solicitations", | 4215 | .procname = "router_solicitations", |
| 4175 | .data = &ipv6_devconf.rtr_solicits, | 4216 | .data = &ipv6_devconf.rtr_solicits, |
| 4176 | .maxlen = sizeof(int), | 4217 | .maxlen = sizeof(int), |
| @@ -4178,25 +4219,20 @@ static struct addrconf_sysctl_table | |||
| 4178 | .proc_handler = proc_dointvec, | 4219 | .proc_handler = proc_dointvec, |
| 4179 | }, | 4220 | }, |
| 4180 | { | 4221 | { |
| 4181 | .ctl_name = NET_IPV6_RTR_SOLICIT_INTERVAL, | ||
| 4182 | .procname = "router_solicitation_interval", | 4222 | .procname = "router_solicitation_interval", |
| 4183 | .data = &ipv6_devconf.rtr_solicit_interval, | 4223 | .data = &ipv6_devconf.rtr_solicit_interval, |
| 4184 | .maxlen = sizeof(int), | 4224 | .maxlen = sizeof(int), |
| 4185 | .mode = 0644, | 4225 | .mode = 0644, |
| 4186 | .proc_handler = proc_dointvec_jiffies, | 4226 | .proc_handler = proc_dointvec_jiffies, |
| 4187 | .strategy = sysctl_jiffies, | ||
| 4188 | }, | 4227 | }, |
| 4189 | { | 4228 | { |
| 4190 | .ctl_name = NET_IPV6_RTR_SOLICIT_DELAY, | ||
| 4191 | .procname = "router_solicitation_delay", | 4229 | .procname = "router_solicitation_delay", |
| 4192 | .data = &ipv6_devconf.rtr_solicit_delay, | 4230 | .data = &ipv6_devconf.rtr_solicit_delay, |
| 4193 | .maxlen = sizeof(int), | 4231 | .maxlen = sizeof(int), |
| 4194 | .mode = 0644, | 4232 | .mode = 0644, |
| 4195 | .proc_handler = proc_dointvec_jiffies, | 4233 | .proc_handler = proc_dointvec_jiffies, |
| 4196 | .strategy = sysctl_jiffies, | ||
| 4197 | }, | 4234 | }, |
| 4198 | { | 4235 | { |
| 4199 | .ctl_name = NET_IPV6_FORCE_MLD_VERSION, | ||
| 4200 | .procname = "force_mld_version", | 4236 | .procname = "force_mld_version", |
| 4201 | .data = &ipv6_devconf.force_mld_version, | 4237 | .data = &ipv6_devconf.force_mld_version, |
| 4202 | .maxlen = sizeof(int), | 4238 | .maxlen = sizeof(int), |
| @@ -4205,7 +4241,6 @@ static struct addrconf_sysctl_table | |||
| 4205 | }, | 4241 | }, |
| 4206 | #ifdef CONFIG_IPV6_PRIVACY | 4242 | #ifdef CONFIG_IPV6_PRIVACY |
| 4207 | { | 4243 | { |
| 4208 | .ctl_name = NET_IPV6_USE_TEMPADDR, | ||
| 4209 | .procname = "use_tempaddr", | 4244 | .procname = "use_tempaddr", |
| 4210 | .data = &ipv6_devconf.use_tempaddr, | 4245 | .data = &ipv6_devconf.use_tempaddr, |
| 4211 | .maxlen = sizeof(int), | 4246 | .maxlen = sizeof(int), |
| @@ -4213,7 +4248,6 @@ static struct addrconf_sysctl_table | |||
| 4213 | .proc_handler = proc_dointvec, | 4248 | .proc_handler = proc_dointvec, |
| 4214 | }, | 4249 | }, |
| 4215 | { | 4250 | { |
| 4216 | .ctl_name = NET_IPV6_TEMP_VALID_LFT, | ||
| 4217 | .procname = "temp_valid_lft", | 4251 | .procname = "temp_valid_lft", |
| 4218 | .data = &ipv6_devconf.temp_valid_lft, | 4252 | .data = &ipv6_devconf.temp_valid_lft, |
| 4219 | .maxlen = sizeof(int), | 4253 | .maxlen = sizeof(int), |
| @@ -4221,7 +4255,6 @@ static struct addrconf_sysctl_table | |||
| 4221 | .proc_handler = proc_dointvec, | 4255 | .proc_handler = proc_dointvec, |
| 4222 | }, | 4256 | }, |
| 4223 | { | 4257 | { |
| 4224 | .ctl_name = NET_IPV6_TEMP_PREFERED_LFT, | ||
| 4225 | .procname = "temp_prefered_lft", | 4258 | .procname = "temp_prefered_lft", |
| 4226 | .data = &ipv6_devconf.temp_prefered_lft, | 4259 | .data = &ipv6_devconf.temp_prefered_lft, |
| 4227 | .maxlen = sizeof(int), | 4260 | .maxlen = sizeof(int), |
| @@ -4229,7 +4262,6 @@ static struct addrconf_sysctl_table | |||
| 4229 | .proc_handler = proc_dointvec, | 4262 | .proc_handler = proc_dointvec, |
| 4230 | }, | 4263 | }, |
| 4231 | { | 4264 | { |
| 4232 | .ctl_name = NET_IPV6_REGEN_MAX_RETRY, | ||
| 4233 | .procname = "regen_max_retry", | 4265 | .procname = "regen_max_retry", |
| 4234 | .data = &ipv6_devconf.regen_max_retry, | 4266 | .data = &ipv6_devconf.regen_max_retry, |
| 4235 | .maxlen = sizeof(int), | 4267 | .maxlen = sizeof(int), |
| @@ -4237,7 +4269,6 @@ static struct addrconf_sysctl_table | |||
| 4237 | .proc_handler = proc_dointvec, | 4269 | .proc_handler = proc_dointvec, |
| 4238 | }, | 4270 | }, |
| 4239 | { | 4271 | { |
| 4240 | .ctl_name = NET_IPV6_MAX_DESYNC_FACTOR, | ||
| 4241 | .procname = "max_desync_factor", | 4272 | .procname = "max_desync_factor", |
| 4242 | .data = &ipv6_devconf.max_desync_factor, | 4273 | .data = &ipv6_devconf.max_desync_factor, |
| 4243 | .maxlen = sizeof(int), | 4274 | .maxlen = sizeof(int), |
| @@ -4246,7 +4277,6 @@ static struct addrconf_sysctl_table | |||
| 4246 | }, | 4277 | }, |
| 4247 | #endif | 4278 | #endif |
| 4248 | { | 4279 | { |
| 4249 | .ctl_name = NET_IPV6_MAX_ADDRESSES, | ||
| 4250 | .procname = "max_addresses", | 4280 | .procname = "max_addresses", |
| 4251 | .data = &ipv6_devconf.max_addresses, | 4281 | .data = &ipv6_devconf.max_addresses, |
| 4252 | .maxlen = sizeof(int), | 4282 | .maxlen = sizeof(int), |
| @@ -4254,7 +4284,6 @@ static struct addrconf_sysctl_table | |||
| 4254 | .proc_handler = proc_dointvec, | 4284 | .proc_handler = proc_dointvec, |
| 4255 | }, | 4285 | }, |
| 4256 | { | 4286 | { |
| 4257 | .ctl_name = NET_IPV6_ACCEPT_RA_DEFRTR, | ||
| 4258 | .procname = "accept_ra_defrtr", | 4287 | .procname = "accept_ra_defrtr", |
| 4259 | .data = &ipv6_devconf.accept_ra_defrtr, | 4288 | .data = &ipv6_devconf.accept_ra_defrtr, |
| 4260 | .maxlen = sizeof(int), | 4289 | .maxlen = sizeof(int), |
| @@ -4262,7 +4291,6 @@ static struct addrconf_sysctl_table | |||
| 4262 | .proc_handler = proc_dointvec, | 4291 | .proc_handler = proc_dointvec, |
| 4263 | }, | 4292 | }, |
| 4264 | { | 4293 | { |
| 4265 | .ctl_name = NET_IPV6_ACCEPT_RA_PINFO, | ||
| 4266 | .procname = "accept_ra_pinfo", | 4294 | .procname = "accept_ra_pinfo", |
| 4267 | .data = &ipv6_devconf.accept_ra_pinfo, | 4295 | .data = &ipv6_devconf.accept_ra_pinfo, |
| 4268 | .maxlen = sizeof(int), | 4296 | .maxlen = sizeof(int), |
| @@ -4271,7 +4299,6 @@ static struct addrconf_sysctl_table | |||
| 4271 | }, | 4299 | }, |
| 4272 | #ifdef CONFIG_IPV6_ROUTER_PREF | 4300 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| 4273 | { | 4301 | { |
| 4274 | .ctl_name = NET_IPV6_ACCEPT_RA_RTR_PREF, | ||
| 4275 | .procname = "accept_ra_rtr_pref", | 4302 | .procname = "accept_ra_rtr_pref", |
| 4276 | .data = &ipv6_devconf.accept_ra_rtr_pref, | 4303 | .data = &ipv6_devconf.accept_ra_rtr_pref, |
| 4277 | .maxlen = sizeof(int), | 4304 | .maxlen = sizeof(int), |
| @@ -4279,17 +4306,14 @@ static struct addrconf_sysctl_table | |||
| 4279 | .proc_handler = proc_dointvec, | 4306 | .proc_handler = proc_dointvec, |
| 4280 | }, | 4307 | }, |
| 4281 | { | 4308 | { |
| 4282 | .ctl_name = NET_IPV6_RTR_PROBE_INTERVAL, | ||
| 4283 | .procname = "router_probe_interval", | 4309 | .procname = "router_probe_interval", |
| 4284 | .data = &ipv6_devconf.rtr_probe_interval, | 4310 | .data = &ipv6_devconf.rtr_probe_interval, |
| 4285 | .maxlen = sizeof(int), | 4311 | .maxlen = sizeof(int), |
| 4286 | .mode = 0644, | 4312 | .mode = 0644, |
| 4287 | .proc_handler = proc_dointvec_jiffies, | 4313 | .proc_handler = proc_dointvec_jiffies, |
| 4288 | .strategy = sysctl_jiffies, | ||
| 4289 | }, | 4314 | }, |
| 4290 | #ifdef CONFIG_IPV6_ROUTE_INFO | 4315 | #ifdef CONFIG_IPV6_ROUTE_INFO |
| 4291 | { | 4316 | { |
| 4292 | .ctl_name = NET_IPV6_ACCEPT_RA_RT_INFO_MAX_PLEN, | ||
| 4293 | .procname = "accept_ra_rt_info_max_plen", | 4317 | .procname = "accept_ra_rt_info_max_plen", |
| 4294 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, | 4318 | .data = &ipv6_devconf.accept_ra_rt_info_max_plen, |
| 4295 | .maxlen = sizeof(int), | 4319 | .maxlen = sizeof(int), |
| @@ -4299,7 +4323,6 @@ static struct addrconf_sysctl_table | |||
| 4299 | #endif | 4323 | #endif |
| 4300 | #endif | 4324 | #endif |
| 4301 | { | 4325 | { |
| 4302 | .ctl_name = NET_IPV6_PROXY_NDP, | ||
| 4303 | .procname = "proxy_ndp", | 4326 | .procname = "proxy_ndp", |
| 4304 | .data = &ipv6_devconf.proxy_ndp, | 4327 | .data = &ipv6_devconf.proxy_ndp, |
| 4305 | .maxlen = sizeof(int), | 4328 | .maxlen = sizeof(int), |
| @@ -4307,7 +4330,6 @@ static struct addrconf_sysctl_table | |||
| 4307 | .proc_handler = proc_dointvec, | 4330 | .proc_handler = proc_dointvec, |
| 4308 | }, | 4331 | }, |
| 4309 | { | 4332 | { |
| 4310 | .ctl_name = NET_IPV6_ACCEPT_SOURCE_ROUTE, | ||
| 4311 | .procname = "accept_source_route", | 4333 | .procname = "accept_source_route", |
| 4312 | .data = &ipv6_devconf.accept_source_route, | 4334 | .data = &ipv6_devconf.accept_source_route, |
| 4313 | .maxlen = sizeof(int), | 4335 | .maxlen = sizeof(int), |
| @@ -4316,7 +4338,6 @@ static struct addrconf_sysctl_table | |||
| 4316 | }, | 4338 | }, |
| 4317 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD | 4339 | #ifdef CONFIG_IPV6_OPTIMISTIC_DAD |
| 4318 | { | 4340 | { |
| 4319 | .ctl_name = CTL_UNNUMBERED, | ||
| 4320 | .procname = "optimistic_dad", | 4341 | .procname = "optimistic_dad", |
| 4321 | .data = &ipv6_devconf.optimistic_dad, | 4342 | .data = &ipv6_devconf.optimistic_dad, |
| 4322 | .maxlen = sizeof(int), | 4343 | .maxlen = sizeof(int), |
| @@ -4327,7 +4348,6 @@ static struct addrconf_sysctl_table | |||
| 4327 | #endif | 4348 | #endif |
| 4328 | #ifdef CONFIG_IPV6_MROUTE | 4349 | #ifdef CONFIG_IPV6_MROUTE |
| 4329 | { | 4350 | { |
| 4330 | .ctl_name = CTL_UNNUMBERED, | ||
| 4331 | .procname = "mc_forwarding", | 4351 | .procname = "mc_forwarding", |
| 4332 | .data = &ipv6_devconf.mc_forwarding, | 4352 | .data = &ipv6_devconf.mc_forwarding, |
| 4333 | .maxlen = sizeof(int), | 4353 | .maxlen = sizeof(int), |
| @@ -4336,16 +4356,13 @@ static struct addrconf_sysctl_table | |||
| 4336 | }, | 4356 | }, |
| 4337 | #endif | 4357 | #endif |
| 4338 | { | 4358 | { |
| 4339 | .ctl_name = CTL_UNNUMBERED, | ||
| 4340 | .procname = "disable_ipv6", | 4359 | .procname = "disable_ipv6", |
| 4341 | .data = &ipv6_devconf.disable_ipv6, | 4360 | .data = &ipv6_devconf.disable_ipv6, |
| 4342 | .maxlen = sizeof(int), | 4361 | .maxlen = sizeof(int), |
| 4343 | .mode = 0644, | 4362 | .mode = 0644, |
| 4344 | .proc_handler = addrconf_sysctl_disable, | 4363 | .proc_handler = addrconf_sysctl_disable, |
| 4345 | .strategy = sysctl_intvec, | ||
| 4346 | }, | 4364 | }, |
| 4347 | { | 4365 | { |
| 4348 | .ctl_name = CTL_UNNUMBERED, | ||
| 4349 | .procname = "accept_dad", | 4366 | .procname = "accept_dad", |
| 4350 | .data = &ipv6_devconf.accept_dad, | 4367 | .data = &ipv6_devconf.accept_dad, |
| 4351 | .maxlen = sizeof(int), | 4368 | .maxlen = sizeof(int), |
| @@ -4353,13 +4370,20 @@ static struct addrconf_sysctl_table | |||
| 4353 | .proc_handler = proc_dointvec, | 4370 | .proc_handler = proc_dointvec, |
| 4354 | }, | 4371 | }, |
| 4355 | { | 4372 | { |
| 4356 | .ctl_name = 0, /* sentinel */ | 4373 | .procname = "force_tllao", |
| 4374 | .data = &ipv6_devconf.force_tllao, | ||
| 4375 | .maxlen = sizeof(int), | ||
| 4376 | .mode = 0644, | ||
| 4377 | .proc_handler = proc_dointvec | ||
| 4378 | }, | ||
| 4379 | { | ||
| 4380 | /* sentinel */ | ||
| 4357 | } | 4381 | } |
| 4358 | }, | 4382 | }, |
| 4359 | }; | 4383 | }; |
| 4360 | 4384 | ||
| 4361 | static int __addrconf_sysctl_register(struct net *net, char *dev_name, | 4385 | static int __addrconf_sysctl_register(struct net *net, char *dev_name, |
| 4362 | int ctl_name, struct inet6_dev *idev, struct ipv6_devconf *p) | 4386 | struct inet6_dev *idev, struct ipv6_devconf *p) |
| 4363 | { | 4387 | { |
| 4364 | int i; | 4388 | int i; |
| 4365 | struct addrconf_sysctl_table *t; | 4389 | struct addrconf_sysctl_table *t; |
| @@ -4367,9 +4391,9 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
| 4367 | #define ADDRCONF_CTL_PATH_DEV 3 | 4391 | #define ADDRCONF_CTL_PATH_DEV 3 |
| 4368 | 4392 | ||
| 4369 | struct ctl_path addrconf_ctl_path[] = { | 4393 | struct ctl_path addrconf_ctl_path[] = { |
| 4370 | { .procname = "net", .ctl_name = CTL_NET, }, | 4394 | { .procname = "net", }, |
| 4371 | { .procname = "ipv6", .ctl_name = NET_IPV6, }, | 4395 | { .procname = "ipv6", }, |
| 4372 | { .procname = "conf", .ctl_name = NET_IPV6_CONF, }, | 4396 | { .procname = "conf", }, |
| 4373 | { /* to be set */ }, | 4397 | { /* to be set */ }, |
| 4374 | { }, | 4398 | { }, |
| 4375 | }; | 4399 | }; |
| @@ -4395,7 +4419,6 @@ static int __addrconf_sysctl_register(struct net *net, char *dev_name, | |||
| 4395 | goto free; | 4419 | goto free; |
| 4396 | 4420 | ||
| 4397 | addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].procname = t->dev_name; | 4421 | addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].procname = t->dev_name; |
| 4398 | addrconf_ctl_path[ADDRCONF_CTL_PATH_DEV].ctl_name = ctl_name; | ||
| 4399 | 4422 | ||
| 4400 | t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path, | 4423 | t->sysctl_header = register_net_sysctl_table(net, addrconf_ctl_path, |
| 4401 | t->addrconf_vars); | 4424 | t->addrconf_vars); |
| @@ -4429,12 +4452,10 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
| 4429 | 4452 | ||
| 4430 | static void addrconf_sysctl_register(struct inet6_dev *idev) | 4453 | static void addrconf_sysctl_register(struct inet6_dev *idev) |
| 4431 | { | 4454 | { |
| 4432 | neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, | 4455 | neigh_sysctl_register(idev->dev, idev->nd_parms, "ipv6", |
| 4433 | NET_IPV6_NEIGH, "ipv6", | 4456 | &ndisc_ifinfo_sysctl_change); |
| 4434 | &ndisc_ifinfo_sysctl_change, | ||
| 4435 | ndisc_ifinfo_sysctl_strategy); | ||
| 4436 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 4457 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
| 4437 | idev->dev->ifindex, idev, &idev->cnf); | 4458 | idev, &idev->cnf); |
| 4438 | } | 4459 | } |
| 4439 | 4460 | ||
| 4440 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) | 4461 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) |
| @@ -4446,7 +4467,7 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
| 4446 | 4467 | ||
| 4447 | #endif | 4468 | #endif |
| 4448 | 4469 | ||
| 4449 | static int addrconf_init_net(struct net *net) | 4470 | static int __net_init addrconf_init_net(struct net *net) |
| 4450 | { | 4471 | { |
| 4451 | int err; | 4472 | int err; |
| 4452 | struct ipv6_devconf *all, *dflt; | 4473 | struct ipv6_devconf *all, *dflt; |
| @@ -4455,7 +4476,7 @@ static int addrconf_init_net(struct net *net) | |||
| 4455 | all = &ipv6_devconf; | 4476 | all = &ipv6_devconf; |
| 4456 | dflt = &ipv6_devconf_dflt; | 4477 | dflt = &ipv6_devconf_dflt; |
| 4457 | 4478 | ||
| 4458 | if (net != &init_net) { | 4479 | if (!net_eq(net, &init_net)) { |
| 4459 | all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); | 4480 | all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); |
| 4460 | if (all == NULL) | 4481 | if (all == NULL) |
| 4461 | goto err_alloc_all; | 4482 | goto err_alloc_all; |
| @@ -4473,13 +4494,11 @@ static int addrconf_init_net(struct net *net) | |||
| 4473 | net->ipv6.devconf_dflt = dflt; | 4494 | net->ipv6.devconf_dflt = dflt; |
| 4474 | 4495 | ||
| 4475 | #ifdef CONFIG_SYSCTL | 4496 | #ifdef CONFIG_SYSCTL |
| 4476 | err = __addrconf_sysctl_register(net, "all", NET_PROTO_CONF_ALL, | 4497 | err = __addrconf_sysctl_register(net, "all", NULL, all); |
| 4477 | NULL, all); | ||
| 4478 | if (err < 0) | 4498 | if (err < 0) |
| 4479 | goto err_reg_all; | 4499 | goto err_reg_all; |
| 4480 | 4500 | ||
| 4481 | err = __addrconf_sysctl_register(net, "default", NET_PROTO_CONF_DEFAULT, | 4501 | err = __addrconf_sysctl_register(net, "default", NULL, dflt); |
| 4482 | NULL, dflt); | ||
| 4483 | if (err < 0) | 4502 | if (err < 0) |
| 4484 | goto err_reg_dflt; | 4503 | goto err_reg_dflt; |
| 4485 | #endif | 4504 | #endif |
| @@ -4497,13 +4516,13 @@ err_alloc_all: | |||
| 4497 | return err; | 4516 | return err; |
| 4498 | } | 4517 | } |
| 4499 | 4518 | ||
| 4500 | static void addrconf_exit_net(struct net *net) | 4519 | static void __net_exit addrconf_exit_net(struct net *net) |
| 4501 | { | 4520 | { |
| 4502 | #ifdef CONFIG_SYSCTL | 4521 | #ifdef CONFIG_SYSCTL |
| 4503 | __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); | 4522 | __addrconf_sysctl_unregister(net->ipv6.devconf_dflt); |
| 4504 | __addrconf_sysctl_unregister(net->ipv6.devconf_all); | 4523 | __addrconf_sysctl_unregister(net->ipv6.devconf_all); |
| 4505 | #endif | 4524 | #endif |
| 4506 | if (net != &init_net) { | 4525 | if (!net_eq(net, &init_net)) { |
| 4507 | kfree(net->ipv6.devconf_dflt); | 4526 | kfree(net->ipv6.devconf_dflt); |
| 4508 | kfree(net->ipv6.devconf_all); | 4527 | kfree(net->ipv6.devconf_all); |
| 4509 | } | 4528 | } |
