diff options
Diffstat (limited to 'net/ipv6/proc.c')
-rw-r--r-- | net/ipv6/proc.c | 121 |
1 files changed, 67 insertions, 54 deletions
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 0179b66864f1..07f0b76e7427 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <net/transp_v6.h> | 29 | #include <net/transp_v6.h> |
30 | #include <net/ipv6.h> | 30 | #include <net/ipv6.h> |
31 | 31 | ||
32 | static struct proc_dir_entry *proc_net_devsnmp6; | ||
33 | |||
34 | static int sockstat6_seq_show(struct seq_file *seq, void *v) | 32 | static int sockstat6_seq_show(struct seq_file *seq, void *v) |
35 | { | 33 | { |
36 | struct net *net = seq->private; | 34 | struct net *net = seq->private; |
@@ -48,6 +46,19 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
48 | return 0; | 46 | return 0; |
49 | } | 47 | } |
50 | 48 | ||
49 | static int sockstat6_seq_open(struct inode *inode, struct file *file) | ||
50 | { | ||
51 | return single_open_net(inode, file, sockstat6_seq_show); | ||
52 | } | ||
53 | |||
54 | static const struct file_operations sockstat6_seq_fops = { | ||
55 | .owner = THIS_MODULE, | ||
56 | .open = sockstat6_seq_open, | ||
57 | .read = seq_read, | ||
58 | .llseek = seq_lseek, | ||
59 | .release = single_release_net, | ||
60 | }; | ||
61 | |||
51 | static struct snmp_mib snmp6_ipstats_list[] = { | 62 | static struct snmp_mib snmp6_ipstats_list[] = { |
52 | /* ipv6 mib according to RFC 2465 */ | 63 | /* ipv6 mib according to RFC 2465 */ |
53 | SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES), | 64 | SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES), |
@@ -164,44 +175,52 @@ snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist) | |||
164 | 175 | ||
165 | static int snmp6_seq_show(struct seq_file *seq, void *v) | 176 | static int snmp6_seq_show(struct seq_file *seq, void *v) |
166 | { | 177 | { |
167 | struct inet6_dev *idev = (struct inet6_dev *)seq->private; | 178 | struct net *net = (struct net *)seq->private; |
168 | 179 | ||
169 | if (idev) { | 180 | snmp6_seq_show_item(seq, (void **)net->mib.ipv6_statistics, |
170 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); | 181 | snmp6_ipstats_list); |
171 | snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); | 182 | snmp6_seq_show_item(seq, (void **)net->mib.icmpv6_statistics, |
172 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); | 183 | snmp6_icmp6_list); |
173 | snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg); | 184 | snmp6_seq_show_icmpv6msg(seq, (void **)net->mib.icmpv6msg_statistics); |
174 | } else { | 185 | snmp6_seq_show_item(seq, (void **)net->mib.udp_stats_in6, |
175 | snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list); | 186 | snmp6_udp6_list); |
176 | snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list); | 187 | snmp6_seq_show_item(seq, (void **)net->mib.udplite_stats_in6, |
177 | snmp6_seq_show_icmpv6msg(seq, (void **)icmpv6msg_statistics); | 188 | snmp6_udplite6_list); |
178 | snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list); | ||
179 | snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list); | ||
180 | } | ||
181 | return 0; | 189 | return 0; |
182 | } | 190 | } |
183 | 191 | ||
184 | static int sockstat6_seq_open(struct inode *inode, struct file *file) | 192 | static int snmp6_seq_open(struct inode *inode, struct file *file) |
185 | { | 193 | { |
186 | return single_open_net(inode, file, sockstat6_seq_show); | 194 | return single_open_net(inode, file, snmp6_seq_show); |
187 | } | 195 | } |
188 | 196 | ||
189 | static const struct file_operations sockstat6_seq_fops = { | 197 | static const struct file_operations snmp6_seq_fops = { |
190 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
191 | .open = sockstat6_seq_open, | 199 | .open = snmp6_seq_open, |
192 | .read = seq_read, | 200 | .read = seq_read, |
193 | .llseek = seq_lseek, | 201 | .llseek = seq_lseek, |
194 | .release = single_release_net, | 202 | .release = single_release_net, |
195 | }; | 203 | }; |
196 | 204 | ||
197 | static int snmp6_seq_open(struct inode *inode, struct file *file) | 205 | static int snmp6_dev_seq_show(struct seq_file *seq, void *v) |
198 | { | 206 | { |
199 | return single_open(file, snmp6_seq_show, PDE(inode)->data); | 207 | struct inet6_dev *idev = (struct inet6_dev *)seq->private; |
208 | |||
209 | seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex); | ||
210 | snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list); | ||
211 | snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list); | ||
212 | snmp6_seq_show_icmpv6msg(seq, (void **)idev->stats.icmpv6msg); | ||
213 | return 0; | ||
200 | } | 214 | } |
201 | 215 | ||
202 | static const struct file_operations snmp6_seq_fops = { | 216 | static int snmp6_dev_seq_open(struct inode *inode, struct file *file) |
217 | { | ||
218 | return single_open(file, snmp6_dev_seq_show, PDE(inode)->data); | ||
219 | } | ||
220 | |||
221 | static const struct file_operations snmp6_dev_seq_fops = { | ||
203 | .owner = THIS_MODULE, | 222 | .owner = THIS_MODULE, |
204 | .open = snmp6_seq_open, | 223 | .open = snmp6_dev_seq_open, |
205 | .read = seq_read, | 224 | .read = seq_read, |
206 | .llseek = seq_lseek, | 225 | .llseek = seq_lseek, |
207 | .release = single_release, | 226 | .release = single_release, |
@@ -210,18 +229,18 @@ static const struct file_operations snmp6_seq_fops = { | |||
210 | int snmp6_register_dev(struct inet6_dev *idev) | 229 | int snmp6_register_dev(struct inet6_dev *idev) |
211 | { | 230 | { |
212 | struct proc_dir_entry *p; | 231 | struct proc_dir_entry *p; |
232 | struct net *net; | ||
213 | 233 | ||
214 | if (!idev || !idev->dev) | 234 | if (!idev || !idev->dev) |
215 | return -EINVAL; | 235 | return -EINVAL; |
216 | 236 | ||
217 | if (!net_eq(dev_net(idev->dev), &init_net)) | 237 | net = dev_net(idev->dev); |
218 | return 0; | 238 | if (!net->mib.proc_net_devsnmp6) |
219 | |||
220 | if (!proc_net_devsnmp6) | ||
221 | return -ENOENT; | 239 | return -ENOENT; |
222 | 240 | ||
223 | p = proc_create_data(idev->dev->name, S_IRUGO, | 241 | p = proc_create_data(idev->dev->name, S_IRUGO, |
224 | proc_net_devsnmp6, &snmp6_seq_fops, idev); | 242 | net->mib.proc_net_devsnmp6, |
243 | &snmp6_dev_seq_fops, idev); | ||
225 | if (!p) | 244 | if (!p) |
226 | return -ENOMEM; | 245 | return -ENOMEM; |
227 | 246 | ||
@@ -231,12 +250,13 @@ int snmp6_register_dev(struct inet6_dev *idev) | |||
231 | 250 | ||
232 | int snmp6_unregister_dev(struct inet6_dev *idev) | 251 | int snmp6_unregister_dev(struct inet6_dev *idev) |
233 | { | 252 | { |
234 | if (!proc_net_devsnmp6) | 253 | struct net *net = dev_net(idev->dev); |
254 | if (!net->mib.proc_net_devsnmp6) | ||
235 | return -ENOENT; | 255 | return -ENOENT; |
236 | if (!idev || !idev->stats.proc_dir_entry) | 256 | if (!idev || !idev->stats.proc_dir_entry) |
237 | return -EINVAL; | 257 | return -EINVAL; |
238 | remove_proc_entry(idev->stats.proc_dir_entry->name, | 258 | remove_proc_entry(idev->stats.proc_dir_entry->name, |
239 | proc_net_devsnmp6); | 259 | net->mib.proc_net_devsnmp6); |
240 | idev->stats.proc_dir_entry = NULL; | 260 | idev->stats.proc_dir_entry = NULL; |
241 | return 0; | 261 | return 0; |
242 | } | 262 | } |
@@ -246,12 +266,27 @@ static int ipv6_proc_init_net(struct net *net) | |||
246 | if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, | 266 | if (!proc_net_fops_create(net, "sockstat6", S_IRUGO, |
247 | &sockstat6_seq_fops)) | 267 | &sockstat6_seq_fops)) |
248 | return -ENOMEM; | 268 | return -ENOMEM; |
269 | |||
270 | if (!proc_net_fops_create(net, "snmp6", S_IRUGO, &snmp6_seq_fops)) | ||
271 | goto proc_snmp6_fail; | ||
272 | |||
273 | net->mib.proc_net_devsnmp6 = proc_mkdir("dev_snmp6", net->proc_net); | ||
274 | if (!net->mib.proc_net_devsnmp6) | ||
275 | goto proc_dev_snmp6_fail; | ||
249 | return 0; | 276 | return 0; |
277 | |||
278 | proc_snmp6_fail: | ||
279 | proc_net_remove(net, "sockstat6"); | ||
280 | proc_dev_snmp6_fail: | ||
281 | proc_net_remove(net, "dev_snmp6"); | ||
282 | return -ENOMEM; | ||
250 | } | 283 | } |
251 | 284 | ||
252 | static void ipv6_proc_exit_net(struct net *net) | 285 | static void ipv6_proc_exit_net(struct net *net) |
253 | { | 286 | { |
254 | proc_net_remove(net, "sockstat6"); | 287 | proc_net_remove(net, "sockstat6"); |
288 | proc_net_remove(net, "dev_snmp6"); | ||
289 | proc_net_remove(net, "snmp6"); | ||
255 | } | 290 | } |
256 | 291 | ||
257 | static struct pernet_operations ipv6_proc_ops = { | 292 | static struct pernet_operations ipv6_proc_ops = { |
@@ -261,33 +296,11 @@ static struct pernet_operations ipv6_proc_ops = { | |||
261 | 296 | ||
262 | int __init ipv6_misc_proc_init(void) | 297 | int __init ipv6_misc_proc_init(void) |
263 | { | 298 | { |
264 | int rc = 0; | 299 | return register_pernet_subsys(&ipv6_proc_ops); |
265 | |||
266 | if (register_pernet_subsys(&ipv6_proc_ops)) | ||
267 | goto proc_net_fail; | ||
268 | |||
269 | if (!proc_net_fops_create(&init_net, "snmp6", S_IRUGO, &snmp6_seq_fops)) | ||
270 | goto proc_snmp6_fail; | ||
271 | |||
272 | proc_net_devsnmp6 = proc_mkdir("dev_snmp6", init_net.proc_net); | ||
273 | if (!proc_net_devsnmp6) | ||
274 | goto proc_dev_snmp6_fail; | ||
275 | out: | ||
276 | return rc; | ||
277 | |||
278 | proc_dev_snmp6_fail: | ||
279 | proc_net_remove(&init_net, "snmp6"); | ||
280 | proc_snmp6_fail: | ||
281 | unregister_pernet_subsys(&ipv6_proc_ops); | ||
282 | proc_net_fail: | ||
283 | rc = -ENOMEM; | ||
284 | goto out; | ||
285 | } | 300 | } |
286 | 301 | ||
287 | void ipv6_misc_proc_exit(void) | 302 | void ipv6_misc_proc_exit(void) |
288 | { | 303 | { |
289 | proc_net_remove(&init_net, "dev_snmp6"); | ||
290 | proc_net_remove(&init_net, "snmp6"); | ||
291 | unregister_pernet_subsys(&ipv6_proc_ops); | 304 | unregister_pernet_subsys(&ipv6_proc_ops); |
292 | } | 305 | } |
293 | 306 | ||