aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ip6mr.c
diff options
context:
space:
mode:
authorBenjamin Thery <benjamin.thery@bull.net>2008-12-10 19:29:48 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-10 19:29:48 -0500
commit8b90fc7e5b43aaef941044a4785a42439015b539 (patch)
tree8a04eaf58a725db5bafb6c5e3a1bc67764558ad0 /net/ipv6/ip6mr.c
parent950d5704e5daa1f90bcd75b99163491e7b249169 (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>
Diffstat (limited to 'net/ipv6/ip6mr.c')
-rw-r--r--net/ipv6/ip6mr.c107
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
92struct ipmr_mfc_iter { 92struct 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
98static struct mfc6_cache *ipmr_mfc_seq_idx(struct ipmr_mfc_iter *it, loff_t pos) 99static 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
129struct ipmr_vif_iter { 132struct ipmr_vif_iter {
133 struct seq_net_private p;
130 int ct; 134 int ct;
131}; 135};
132 136
133static struct mif_device *ip6mr_vif_seq_idx(struct ipmr_vif_iter *iter, 137static 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,
145static void *ip6mr_vif_seq_start(struct seq_file *seq, loff_t *pos) 150static 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
153static void *ip6mr_vif_seq_next(struct seq_file *seq, void *v, loff_t *pos) 160static 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
175static int ip6mr_vif_seq_show(struct seq_file *seq, void *v) 183static 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
201static int ip6mr_vif_open(struct inode *inode, struct file *file) 211static 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
207static struct file_operations ip6mr_vif_fops = { 217static 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
215static void *ipmr_mfc_seq_start(struct seq_file *seq, loff_t *pos) 225static 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
221static void *ipmr_mfc_seq_next(struct seq_file *seq, void *v, loff_t *pos) 233static 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)
262static void ipmr_mfc_seq_stop(struct seq_file *seq, void *v) 275static 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
272static int ipmr_mfc_seq_show(struct seq_file *seq, void *v) 286static 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
320static int ipmr_mfc_open(struct inode *inode, struct file *file) 335static 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
326static struct file_operations ip6mr_mfc_fops = { 341static 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
1012proc_cache_fail:
1013 proc_net_remove(net, "ip6_mr_vif");
1014proc_vif_fail:
1015 kfree(net->ipv6.mfc6_cache_array);
1016#endif
988fail_mfc6_cache: 1017fail_mfc6_cache:
989 kfree(net->ipv6.vif6_table); 1018 kfree(net->ipv6.vif6_table);
990fail: 1019fail:
@@ -993,6 +1022,10 @@ fail:
993 1022
994static void __net_exit ip6mr_net_exit(struct net *net) 1023static 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
1034proc_cache_fail:
1035 proc_net_remove(&init_net, "ip6_mr_vif");
1036proc_vif_fail:
1037 unregister_netdevice_notifier(&ip6_mr_notifier);
1038#endif
1039reg_notif_fail: 1058reg_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
1047void ip6_mr_cleanup(void) 1066void 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);