aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/addrconf.c41
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
2738struct if6_iter_state { 2738struct 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)
2755static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct inet6_ifaddr *ifa) 2760static 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;
2760try_again: 2766try_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
2819static int if6_seq_open(struct inode *inode, struct file *file) 2833static 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
2825static const struct file_operations if6_fops = { 2839static 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
2833int __init if6_proc_init(void) 2847static 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
2854static void if6_proc_net_exit(struct net *net)
2855{
2856 proc_net_remove(net, "if_inet6");
2857}
2858
2859static struct pernet_operations if6_proc_net_ops = {
2860 .init = if6_proc_net_init,
2861 .exit = if6_proc_net_exit,
2862};
2863
2864int __init if6_proc_init(void)
2865{
2866 return register_pernet_subsys(&if6_proc_net_ops);
2867}
2868
2840void if6_proc_exit(void) 2869void 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