diff options
author | Benjamin Thery <benjamin.thery@bull.net> | 2008-12-10 19:29:48 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-10 19:29:48 -0500 |
commit | 8b90fc7e5b43aaef941044a4785a42439015b539 (patch) | |
tree | 8a04eaf58a725db5bafb6c5e3a1bc67764558ad0 | |
parent | 950d5704e5daa1f90bcd75b99163491e7b249169 (diff) |
netns: ip6mr: declare ip6mr /proc/net entries per-namespace
Declare IPv6 multicast forwarding /proc/net entries per-namespace:
/proc/net/ip6_mr_vif
/proc/net/ip6_mr_cache
Changelog
=========
V2:
* In routine ipmr_mfc_seq_idx(), only match entries belonging to current
netns in mfc_unres_queue list.
Signed-off-by: Benjamin Thery <benjamin.thery@bull.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv6/ip6mr.c | 107 |
1 files changed, 61 insertions, 46 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8e693859ea03..d619faf68d98 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -90,19 +90,21 @@ static struct timer_list ipmr_expire_timer; | |||
90 | #ifdef CONFIG_PROC_FS | 90 | #ifdef CONFIG_PROC_FS |
91 | 91 | ||
92 | struct ipmr_mfc_iter { | 92 | struct ipmr_mfc_iter { |
93 | struct seq_net_private p; | ||
93 | struct mfc6_cache **cache; | 94 | struct mfc6_cache **cache; |
94 | int ct; | 95 | int ct; |
95 | }; | 96 | }; |
96 | 97 | ||
97 | 98 | ||
98 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | 99 | static struct mfc6_cache *ipmr_mfc_seq_idx(struct net *net, |
100 | struct ipmr_mfc_iter *it, loff_t pos) | ||
99 | { | 101 | { |
100 | struct mfc6_cache *mfc; | 102 | struct mfc6_cache *mfc; |
101 | 103 | ||
102 | it->cache = init_net.ipv6.mfc6_cache_array; | 104 | it->cache = net->ipv6.mfc6_cache_array; |
103 | read_lock(&mrt_lock); | 105 | read_lock(&mrt_lock); |
104 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) | 106 | for (it->ct = 0; it->ct < MFC6_LINES; it->ct++) |
105 | for (mfc = init_net.ipv6.mfc6_cache_array[it->ct]; | 107 | for (mfc = net->ipv6.mfc6_cache_array[it->ct]; |
106 | mfc; mfc = mfc->next) | 108 | mfc; mfc = mfc->next) |
107 | if (pos-- == 0) | 109 | if (pos-- == 0) |
108 | return mfc; | 110 | return mfc; |
@@ -111,7 +113,8 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | |||
111 | it->cache = &mfc_unres_queue; | 113 | it->cache = &mfc_unres_queue; |
112 | spin_lock_bh(&mfc_unres_lock); | 114 | spin_lock_bh(&mfc_unres_lock); |
113 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) | 115 | for (mfc = mfc_unres_queue; mfc; mfc = mfc->next) |
114 | if (pos-- == 0) | 116 | if (net_eq(mfc6_net(mfc), net) && |
117 | pos-- == 0) | ||
115 | return mfc; | 118 | return mfc; |
116 | spin_unlock_bh(&mfc_unres_lock); | 119 | spin_unlock_bh(&mfc_unres_lock); |
117 | 120 | ||
@@ -127,17 +130,19 @@ static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) | |||
127 | */ | 130 | */ |
128 | 131 | ||
129 | struct ipmr_vif_iter { | 132 | struct ipmr_vif_iter { |
133 | struct seq_net_private p; | ||
130 | int ct; | 134 | int ct; |
131 | }; | 135 | }; |
132 | 136 | ||
133 | static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, | 137 | static struct mif_device *ip6mr_vif_seq_idx(struct net *net, |
138 | struct ipmr_vif_iter *iter, | ||
134 | loff_t pos) | 139 | loff_t pos) |
135 | { | 140 | { |
136 | for (iter->ct = 0; iter->ct < init_net.ipv6.maxvif; ++iter->ct) { | 141 | for (iter->ct = 0; iter->ct < net->ipv6.maxvif; ++iter->ct) { |
137 | if (!MIF_EXISTS(&init_net, iter->ct)) | 142 | if (!MIF_EXISTS(net, iter->ct)) |
138 | continue; | 143 | continue; |
139 | if (pos-- == 0) | 144 | if (pos-- == 0) |
140 | return &init_net.ipv6.vif6_table[iter->ct]; | 145 | return &net->ipv6.vif6_table[iter->ct]; |
141 | } | 146 | } |
142 | return NULL; | 147 | return NULL; |
143 | } | 148 | } |
@@ -145,23 +150,26 @@ static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, | |||
145 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) | 150 | static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) |
146 | __acquires(mrt_lock) | 151 | __acquires(mrt_lock) |
147 | { | 152 | { |
153 | struct net *net = seq_file_net(seq); | ||
154 | |||
148 | read_lock(&mrt_lock); | 155 | read_lock(&mrt_lock); |
149 | return (*pos ? ip6mr_vif_seq_idx(seq->private, *pos - 1) | 156 | return *pos ? ip6mr_vif_seq_idx(net, seq->private, *pos - 1) |
150 | : SEQ_START_TOKEN); | 157 | : SEQ_START_TOKEN; |
151 | } | 158 | } |
152 | 159 | ||
153 | static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 160 | static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
154 | { | 161 | { |
155 | struct ipmr_vif_iter *iter = seq->private; | 162 | struct ipmr_vif_iter *iter = seq->private; |
163 | struct net *net = seq_file_net(seq); | ||
156 | 164 | ||
157 | ++*pos; | 165 | ++*pos; |
158 | if (v == SEQ_START_TOKEN) | 166 | if (v == SEQ_START_TOKEN) |
159 | return ip6mr_vif_seq_idx(iter, 0); | 167 | return ip6mr_vif_seq_idx(net, iter, 0); |
160 | 168 | ||
161 | while (++iter->ct < init_net.ipv6.maxvif) { | 169 | while (++iter->ct < net->ipv6.maxvif) { |
162 | if (!MIF_EXISTS(&init_net, iter->ct)) | 170 | if (!MIF_EXISTS(net, iter->ct)) |
163 | continue; | 171 | continue; |
164 | return &init_net.ipv6.vif6_table[iter->ct]; | 172 | return &net->ipv6.vif6_table[iter->ct]; |
165 | } | 173 | } |
166 | return NULL; | 174 | return NULL; |
167 | } | 175 | } |
@@ -174,6 +182,8 @@ static void ip6mr_vif_seq_stop(struct seq_file *seq, void *v) | |||
174 | 182 | ||
175 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | 183 | static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) |
176 | { | 184 | { |
185 | struct net *net = seq_file_net(seq); | ||
186 | |||
177 | if (v == SEQ_START_TOKEN) { | 187 | if (v == SEQ_START_TOKEN) { |
178 | seq_puts(seq, | 188 | seq_puts(seq, |
179 | "Interface BytesIn PktsIn BytesOut PktsOut Flags\n"); | 189 | "Interface BytesIn PktsIn BytesOut PktsOut Flags\n"); |
@@ -183,7 +193,7 @@ static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) | |||
183 | 193 | ||
184 | seq_printf(seq, | 194 | seq_printf(seq, |
185 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", | 195 | "%2td %-10s %8ld %7ld %8ld %7ld %05X\n", |
186 | vif - init_net.ipv6.vif6_table, | 196 | vif - net->ipv6.vif6_table, |
187 | name, vif->bytes_in, vif->pkt_in, | 197 | name, vif->bytes_in, vif->pkt_in, |
188 | vif->bytes_out, vif->pkt_out, | 198 | vif->bytes_out, vif->pkt_out, |
189 | vif->flags); | 199 | vif->flags); |
@@ -200,8 +210,8 @@ static struct seq_operations ip6mr_vif_seq_ops = { | |||
200 | 210 | ||
201 | static int ip6mr_vif_open(struct inode *inode, struct file *file) | 211 | static int ip6mr_vif_open(struct inode *inode, struct file *file) |
202 | { | 212 | { |
203 | return seq_open_private(file, &ip6mr_vif_seq_ops, | 213 | return seq_open_net(inode, file, &ip6mr_vif_seq_ops, |
204 | sizeof(struct ipmr_vif_iter)); | 214 | sizeof(struct ipmr_vif_iter)); |
205 | } | 215 | } |
206 | 216 | ||
207 | static struct file_operations ip6mr_vif_fops = { | 217 | static struct file_operations ip6mr_vif_fops = { |
@@ -209,24 +219,27 @@ static struct file_operations ip6mr_vif_fops = { | |||
209 | .open = ip6mr_vif_open, | 219 | .open = ip6mr_vif_open, |
210 | .read = seq_read, | 220 | .read = seq_read, |
211 | .llseek = seq_lseek, | 221 | .llseek = seq_lseek, |
212 | .release = seq_release_private, | 222 | .release = seq_release_net, |
213 | }; | 223 | }; |
214 | 224 | ||
215 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) | 225 | static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) |
216 | { | 226 | { |
217 | return (*pos ? ipmr_mfc_seq_idx(seq->private, *pos - 1) | 227 | struct net *net = seq_file_net(seq); |
218 | : SEQ_START_TOKEN); | 228 | |
229 | return *pos ? ipmr_mfc_seq_idx(net, seq->private, *pos - 1) | ||
230 | : SEQ_START_TOKEN; | ||
219 | } | 231 | } |
220 | 232 | ||
221 | static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 233 | static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
222 | { | 234 | { |
223 | struct mfc6_cache *mfc = v; | 235 | struct mfc6_cache *mfc = v; |
224 | struct ipmr_mfc_iter *it = seq->private; | 236 | struct ipmr_mfc_iter *it = seq->private; |
237 | struct net *net = seq_file_net(seq); | ||
225 | 238 | ||
226 | ++*pos; | 239 | ++*pos; |
227 | 240 | ||
228 | if (v == SEQ_START_TOKEN) | 241 | if (v == SEQ_START_TOKEN) |
229 | return ipmr_mfc_seq_idx(seq->private, 0); | 242 | return ipmr_mfc_seq_idx(net, seq->private, 0); |
230 | 243 | ||
231 | if (mfc->next) | 244 | if (mfc->next) |
232 | return mfc->next; | 245 | return mfc->next; |
@@ -234,10 +247,10 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
234 | if (it->cache == &mfc_unres_queue) | 247 | if (it->cache == &mfc_unres_queue) |
235 | goto end_of_list; | 248 | goto end_of_list; |
236 | 249 | ||
237 | BUG_ON(it->cache != init_net.ipv6.mfc6_cache_array); | 250 | BUG_ON(it->cache != net->ipv6.mfc6_cache_array); |
238 | 251 | ||
239 | while (++it->ct < MFC6_LINES) { | 252 | while (++it->ct < MFC6_LINES) { |
240 | mfc = init_net.ipv6.mfc6_cache_array[it->ct]; | 253 | mfc = net->ipv6.mfc6_cache_array[it->ct]; |
241 | if (mfc) | 254 | if (mfc) |
242 | return mfc; | 255 | return mfc; |
243 | } | 256 | } |
@@ -262,16 +275,18 @@ static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
262 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) | 275 | static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) |
263 | { | 276 | { |
264 | struct ipmr_mfc_iter *it = seq->private; | 277 | struct ipmr_mfc_iter *it = seq->private; |
278 | struct net *net = seq_file_net(seq); | ||
265 | 279 | ||
266 | if (it->cache == &mfc_unres_queue) | 280 | if (it->cache == &mfc_unres_queue) |
267 | spin_unlock_bh(&mfc_unres_lock); | 281 | spin_unlock_bh(&mfc_unres_lock); |
268 | else if (it->cache == init_net.ipv6.mfc6_cache_array) | 282 | else if (it->cache == net->ipv6.mfc6_cache_array) |
269 | read_unlock(&mrt_lock); | 283 | read_unlock(&mrt_lock); |
270 | } | 284 | } |
271 | 285 | ||
272 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | 286 | static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) |
273 | { | 287 | { |
274 | int n; | 288 | int n; |
289 | struct net *net = seq_file_net(seq); | ||
275 | 290 | ||
276 | if (v == SEQ_START_TOKEN) { | 291 | if (v == SEQ_START_TOKEN) { |
277 | seq_puts(seq, | 292 | seq_puts(seq, |
@@ -293,7 +308,7 @@ static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) | |||
293 | mfc->mfc_un.res.wrong_if); | 308 | mfc->mfc_un.res.wrong_if); |
294 | for (n = mfc->mfc_un.res.minvif; | 309 | for (n = mfc->mfc_un.res.minvif; |
295 | n < mfc->mfc_un.res.maxvif; n++) { | 310 | n < mfc->mfc_un.res.maxvif; n++) { |
296 | if (MIF_EXISTS(&init_net, n) && | 311 | if (MIF_EXISTS(net, n) && |
297 | mfc->mfc_un.res.ttls[n] < 255) | 312 | mfc->mfc_un.res.ttls[n] < 255) |
298 | seq_printf(seq, | 313 | seq_printf(seq, |
299 | " %2d:%-3d", | 314 | " %2d:%-3d", |
@@ -319,8 +334,8 @@ static struct seq_operations ipmr_mfc_seq_ops = { | |||
319 | 334 | ||
320 | static int ipmr_mfc_open(struct inode *inode, struct file *file) | 335 | static int ipmr_mfc_open(struct inode *inode, struct file *file) |
321 | { | 336 | { |
322 | return seq_open_private(file, &ipmr_mfc_seq_ops, | 337 | return seq_open_net(inode, file, &ipmr_mfc_seq_ops, |
323 | sizeof(struct ipmr_mfc_iter)); | 338 | sizeof(struct ipmr_mfc_iter)); |
324 | } | 339 | } |
325 | 340 | ||
326 | static struct file_operations ip6mr_mfc_fops = { | 341 | static struct file_operations ip6mr_mfc_fops = { |
@@ -328,7 +343,7 @@ static struct file_operations ip6mr_mfc_fops = { | |||
328 | .open = ipmr_mfc_open, | 343 | .open = ipmr_mfc_open, |
329 | .read = seq_read, | 344 | .read = seq_read, |
330 | .llseek = seq_lseek, | 345 | .llseek = seq_lseek, |
331 | .release = seq_release_private, | 346 | .release = seq_release_net, |
332 | }; | 347 | }; |
333 | #endif | 348 | #endif |
334 | 349 | ||
@@ -983,8 +998,22 @@ static int __net_init ip6mr_net_init(struct net *net) | |||
983 | #ifdef CONFIG_IPV6_PIMSM_V2 | 998 | #ifdef CONFIG_IPV6_PIMSM_V2 |
984 | net->ipv6.mroute_reg_vif_num = -1; | 999 | net->ipv6.mroute_reg_vif_num = -1; |
985 | #endif | 1000 | #endif |
1001 | |||
1002 | #ifdef CONFIG_PROC_FS | ||
1003 | err = -ENOMEM; | ||
1004 | if (!proc_net_fops_create(net, "ip6_mr_vif", 0, &ip6mr_vif_fops)) | ||
1005 | goto proc_vif_fail; | ||
1006 | if (!proc_net_fops_create(net, "ip6_mr_cache", 0, &ip6mr_mfc_fops)) | ||
1007 | goto proc_cache_fail; | ||
1008 | #endif | ||
986 | return 0; | 1009 | return 0; |
987 | 1010 | ||
1011 | #ifdef CONFIG_PROC_FS | ||
1012 | proc_cache_fail: | ||
1013 | proc_net_remove(net, "ip6_mr_vif"); | ||
1014 | proc_vif_fail: | ||
1015 | kfree(net->ipv6.mfc6_cache_array); | ||
1016 | #endif | ||
988 | fail_mfc6_cache: | 1017 | fail_mfc6_cache: |
989 | kfree(net->ipv6.vif6_table); | 1018 | kfree(net->ipv6.vif6_table); |
990 | fail: | 1019 | fail: |
@@ -993,6 +1022,10 @@ fail: | |||
993 | 1022 | ||
994 | static void __net_exit ip6mr_net_exit(struct net *net) | 1023 | static void __net_exit ip6mr_net_exit(struct net *net) |
995 | { | 1024 | { |
1025 | #ifdef CONFIG_PROC_FS | ||
1026 | proc_net_remove(net, "ip6_mr_cache"); | ||
1027 | proc_net_remove(net, "ip6_mr_vif"); | ||
1028 | #endif | ||
996 | kfree(net->ipv6.mfc6_cache_array); | 1029 | kfree(net->ipv6.mfc6_cache_array); |
997 | kfree(net->ipv6.vif6_table); | 1030 | kfree(net->ipv6.vif6_table); |
998 | } | 1031 | } |
@@ -1021,21 +1054,7 @@ int __init ip6_mr_init(void) | |||
1021 | err = register_netdevice_notifier(&ip6_mr_notifier); | 1054 | err = register_netdevice_notifier(&ip6_mr_notifier); |
1022 | if (err) | 1055 | if (err) |
1023 | goto reg_notif_fail; | 1056 | goto reg_notif_fail; |
1024 | #ifdef CONFIG_PROC_FS | ||
1025 | err = -ENOMEM; | ||
1026 | if (!proc_net_fops_create(&init_net, "ip6_mr_vif", 0, &ip6mr_vif_fops)) | ||
1027 | goto proc_vif_fail; | ||
1028 | if (!proc_net_fops_create(&init_net, "ip6_mr_cache", | ||
1029 | 0, &ip6mr_mfc_fops)) | ||
1030 | goto proc_cache_fail; | ||
1031 | #endif | ||
1032 | return 0; | 1057 | return 0; |
1033 | #ifdef CONFIG_PROC_FS | ||
1034 | proc_cache_fail: | ||
1035 | proc_net_remove(&init_net, "ip6_mr_vif"); | ||
1036 | proc_vif_fail: | ||
1037 | unregister_netdevice_notifier(&ip6_mr_notifier); | ||
1038 | #endif | ||
1039 | reg_notif_fail: | 1058 | reg_notif_fail: |
1040 | del_timer(&ipmr_expire_timer); | 1059 | del_timer(&ipmr_expire_timer); |
1041 | unregister_pernet_subsys(&ip6mr_net_ops); | 1060 | unregister_pernet_subsys(&ip6mr_net_ops); |
@@ -1046,10 +1065,6 @@ reg_pernet_fail: | |||
1046 | 1065 | ||
1047 | void ip6_mr_cleanup(void) | 1066 | void ip6_mr_cleanup(void) |
1048 | { | 1067 | { |
1049 | #ifdef CONFIG_PROC_FS | ||
1050 | proc_net_remove(&init_net, "ip6_mr_cache"); | ||
1051 | proc_net_remove(&init_net, "ip6_mr_vif"); | ||
1052 | #endif | ||
1053 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1068 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1054 | del_timer(&ipmr_expire_timer); | 1069 | del_timer(&ipmr_expire_timer); |
1055 | unregister_pernet_subsys(&ip6mr_net_ops); | 1070 | unregister_pernet_subsys(&ip6mr_net_ops); |