diff options
-rw-r--r-- | net/ipv6/addrconf.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index cd90f9a6da33..d7b440343e97 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -2736,6 +2736,7 @@ static void addrconf_dad_run(struct inet6_dev *idev) { | |||
2736 | 2736 | ||
2737 | #ifdef CONFIG_PROC_FS | 2737 | #ifdef CONFIG_PROC_FS |
2738 | struct if6_iter_state { | 2738 | struct if6_iter_state { |
2739 | struct seq_net_private p; | ||
2739 | int bucket; | 2740 | int bucket; |
2740 | }; | 2741 | }; |
2741 | 2742 | ||
@@ -2743,9 +2744,13 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2743 | { | 2744 | { |
2744 | struct inet6_ifaddr *ifa = NULL; | 2745 | struct inet6_ifaddr *ifa = NULL; |
2745 | struct if6_iter_state *state = seq->private; | 2746 | struct if6_iter_state *state = seq->private; |
2747 | struct net *net = state->p.net; | ||
2746 | 2748 | ||
2747 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { | 2749 | for (state->bucket = 0; state->bucket < IN6_ADDR_HSIZE; ++state->bucket) { |
2748 | ifa = inet6_addr_lst[state->bucket]; | 2750 | ifa = inet6_addr_lst[state->bucket]; |
2751 | |||
2752 | while (ifa && ifa->idev->dev->nd_net != net) | ||
2753 | ifa = ifa->lst_next; | ||
2749 | if (ifa) | 2754 | if (ifa) |
2750 | break; | 2755 | break; |
2751 | } | 2756 | } |
@@ -2755,13 +2760,22 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq) | |||
2755 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) | 2760 | static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) |
2756 | { | 2761 | { |
2757 | struct if6_iter_state *state = seq->private; | 2762 | struct if6_iter_state *state = seq->private; |
2763 | struct net *net = state->p.net; | ||
2758 | 2764 | ||
2759 | ifa = ifa->lst_next; | 2765 | ifa = ifa->lst_next; |
2760 | try_again: | 2766 | try_again: |
2767 | if (ifa) { | ||
2768 | if (ifa->idev->dev->nd_net != net) { | ||
2769 | ifa = ifa->lst_next; | ||
2770 | goto try_again; | ||
2771 | } | ||
2772 | } | ||
2773 | |||
2761 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { | 2774 | if (!ifa && ++state->bucket < IN6_ADDR_HSIZE) { |
2762 | ifa = inet6_addr_lst[state->bucket]; | 2775 | ifa = inet6_addr_lst[state->bucket]; |
2763 | goto try_again; | 2776 | goto try_again; |
2764 | } | 2777 | } |
2778 | |||
2765 | return ifa; | 2779 | return ifa; |
2766 | } | 2780 | } |
2767 | 2781 | ||
@@ -2818,8 +2832,8 @@ static const struct seq_operations if6_seq_ops = { | |||
2818 | 2832 | ||
2819 | static int if6_seq_open(struct inode *inode, struct file *file) | 2833 | static int if6_seq_open(struct inode *inode, struct file *file) |
2820 | { | 2834 | { |
2821 | return seq_open_private(file, &if6_seq_ops, | 2835 | return seq_open_net(inode, file, &if6_seq_ops, |
2822 | sizeof(struct if6_iter_state)); | 2836 | sizeof(struct if6_iter_state)); |
2823 | } | 2837 | } |
2824 | 2838 | ||
2825 | static const struct file_operations if6_fops = { | 2839 | static const struct file_operations if6_fops = { |
@@ -2827,19 +2841,34 @@ static const struct file_operations if6_fops = { | |||
2827 | .open = if6_seq_open, | 2841 | .open = if6_seq_open, |
2828 | .read = seq_read, | 2842 | .read = seq_read, |
2829 | .llseek = seq_lseek, | 2843 | .llseek = seq_lseek, |
2830 | .release = seq_release_private, | 2844 | .release = seq_release_net, |
2831 | }; | 2845 | }; |
2832 | 2846 | ||
2833 | int __init if6_proc_init(void) | 2847 | static int if6_proc_net_init(struct net *net) |
2834 | { | 2848 | { |
2835 | if (!proc_net_fops_create(&init_net, "if_inet6", S_IRUGO, &if6_fops)) | 2849 | if (!proc_net_fops_create(net, "if_inet6", S_IRUGO, &if6_fops)) |
2836 | return -ENOMEM; | 2850 | return -ENOMEM; |
2837 | return 0; | 2851 | return 0; |
2838 | } | 2852 | } |
2839 | 2853 | ||
2854 | static void if6_proc_net_exit(struct net *net) | ||
2855 | { | ||
2856 | proc_net_remove(net, "if_inet6"); | ||
2857 | } | ||
2858 | |||
2859 | static struct pernet_operations if6_proc_net_ops = { | ||
2860 | .init = if6_proc_net_init, | ||
2861 | .exit = if6_proc_net_exit, | ||
2862 | }; | ||
2863 | |||
2864 | int __init if6_proc_init(void) | ||
2865 | { | ||
2866 | return register_pernet_subsys(&if6_proc_net_ops); | ||
2867 | } | ||
2868 | |||
2840 | void if6_proc_exit(void) | 2869 | void if6_proc_exit(void) |
2841 | { | 2870 | { |
2842 | proc_net_remove(&init_net, "if_inet6"); | 2871 | unregister_pernet_subsys(&if6_proc_net_ops); |
2843 | } | 2872 | } |
2844 | #endif /* CONFIG_PROC_FS */ | 2873 | #endif /* CONFIG_PROC_FS */ |
2845 | 2874 | ||