]> bbs.cooldavid.org Git - net-next-2.6.git/blame - net/ipv6/proc.c
[PATCH] mark struct file_operations const 7
[net-next-2.6.git] / net / ipv6 / proc.c
CommitLineData
1da177e4
LT
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * This file implements the various access functions for the
7 * PROC file system. This is very similar to the IPv4 version,
8 * except it reports the sockets in the INET6 address family.
9 *
10 * Version: $Id: proc.c,v 1.17 2002/02/01 22:01:04 davem Exp $
11 *
12 * Authors: David S. Miller (davem@caip.rutgers.edu)
13 * YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version
18 * 2 of the License, or (at your option) any later version.
19 */
1da177e4
LT
20#include <linux/sched.h>
21#include <linux/socket.h>
22#include <linux/net.h>
23#include <linux/ipv6.h>
24#include <linux/proc_fs.h>
25#include <linux/seq_file.h>
26#include <linux/stddef.h>
27#include <net/sock.h>
28#include <net/tcp.h>
29#include <net/transp_v6.h>
30#include <net/ipv6.h>
31
32#ifdef CONFIG_PROC_FS
33static struct proc_dir_entry *proc_net_devsnmp6;
34
35static int fold_prot_inuse(struct proto *proto)
36{
37 int res = 0;
38 int cpu;
39
6f912042 40 for_each_possible_cpu(cpu)
1da177e4
LT
41 res += proto->stats[cpu].inuse;
42
43 return res;
44}
45
46static int sockstat6_seq_show(struct seq_file *seq, void *v)
47{
48 seq_printf(seq, "TCP6: inuse %d\n",
49 fold_prot_inuse(&tcpv6_prot));
50 seq_printf(seq, "UDP6: inuse %d\n",
51 fold_prot_inuse(&udpv6_prot));
ba4e58ec 52 seq_printf(seq, "UDPLITE6: inuse %d\n",
1ab1457c 53 fold_prot_inuse(&udplitev6_prot));
1da177e4
LT
54 seq_printf(seq, "RAW6: inuse %d\n",
55 fold_prot_inuse(&rawv6_prot));
56 seq_printf(seq, "FRAG6: inuse %d memory %d\n",
57 ip6_frag_nqueues, atomic_read(&ip6_frag_mem));
58 return 0;
59}
60
61static struct snmp_mib snmp6_ipstats_list[] = {
62/* ipv6 mib according to RFC 2465 */
63 SNMP_MIB_ITEM("Ip6InReceives", IPSTATS_MIB_INRECEIVES),
64 SNMP_MIB_ITEM("Ip6InHdrErrors", IPSTATS_MIB_INHDRERRORS),
65 SNMP_MIB_ITEM("Ip6InTooBigErrors", IPSTATS_MIB_INTOOBIGERRORS),
66 SNMP_MIB_ITEM("Ip6InNoRoutes", IPSTATS_MIB_INNOROUTES),
67 SNMP_MIB_ITEM("Ip6InAddrErrors", IPSTATS_MIB_INADDRERRORS),
68 SNMP_MIB_ITEM("Ip6InUnknownProtos", IPSTATS_MIB_INUNKNOWNPROTOS),
69 SNMP_MIB_ITEM("Ip6InTruncatedPkts", IPSTATS_MIB_INTRUNCATEDPKTS),
70 SNMP_MIB_ITEM("Ip6InDiscards", IPSTATS_MIB_INDISCARDS),
71 SNMP_MIB_ITEM("Ip6InDelivers", IPSTATS_MIB_INDELIVERS),
72 SNMP_MIB_ITEM("Ip6OutForwDatagrams", IPSTATS_MIB_OUTFORWDATAGRAMS),
73 SNMP_MIB_ITEM("Ip6OutRequests", IPSTATS_MIB_OUTREQUESTS),
74 SNMP_MIB_ITEM("Ip6OutDiscards", IPSTATS_MIB_OUTDISCARDS),
75 SNMP_MIB_ITEM("Ip6OutNoRoutes", IPSTATS_MIB_OUTNOROUTES),
76 SNMP_MIB_ITEM("Ip6ReasmTimeout", IPSTATS_MIB_REASMTIMEOUT),
77 SNMP_MIB_ITEM("Ip6ReasmReqds", IPSTATS_MIB_REASMREQDS),
78 SNMP_MIB_ITEM("Ip6ReasmOKs", IPSTATS_MIB_REASMOKS),
79 SNMP_MIB_ITEM("Ip6ReasmFails", IPSTATS_MIB_REASMFAILS),
80 SNMP_MIB_ITEM("Ip6FragOKs", IPSTATS_MIB_FRAGOKS),
81 SNMP_MIB_ITEM("Ip6FragFails", IPSTATS_MIB_FRAGFAILS),
82 SNMP_MIB_ITEM("Ip6FragCreates", IPSTATS_MIB_FRAGCREATES),
83 SNMP_MIB_ITEM("Ip6InMcastPkts", IPSTATS_MIB_INMCASTPKTS),
84 SNMP_MIB_ITEM("Ip6OutMcastPkts", IPSTATS_MIB_OUTMCASTPKTS),
85 SNMP_MIB_SENTINEL
86};
87
88static struct snmp_mib snmp6_icmp6_list[] = {
89/* icmpv6 mib according to RFC 2466
90
91 Exceptions: {In|Out}AdminProhibs are removed, because I see
1ab1457c 92 no good reasons to account them separately
1da177e4
LT
93 of another dest.unreachs.
94 OutErrs is zero identically.
95 OutEchos too.
96 OutRouterAdvertisements too.
97 OutGroupMembQueries too.
98 */
99 SNMP_MIB_ITEM("Icmp6InMsgs", ICMP6_MIB_INMSGS),
100 SNMP_MIB_ITEM("Icmp6InErrors", ICMP6_MIB_INERRORS),
101 SNMP_MIB_ITEM("Icmp6InDestUnreachs", ICMP6_MIB_INDESTUNREACHS),
102 SNMP_MIB_ITEM("Icmp6InPktTooBigs", ICMP6_MIB_INPKTTOOBIGS),
103 SNMP_MIB_ITEM("Icmp6InTimeExcds", ICMP6_MIB_INTIMEEXCDS),
104 SNMP_MIB_ITEM("Icmp6InParmProblems", ICMP6_MIB_INPARMPROBLEMS),
105 SNMP_MIB_ITEM("Icmp6InEchos", ICMP6_MIB_INECHOS),
106 SNMP_MIB_ITEM("Icmp6InEchoReplies", ICMP6_MIB_INECHOREPLIES),
107 SNMP_MIB_ITEM("Icmp6InGroupMembQueries", ICMP6_MIB_INGROUPMEMBQUERIES),
108 SNMP_MIB_ITEM("Icmp6InGroupMembResponses", ICMP6_MIB_INGROUPMEMBRESPONSES),
109 SNMP_MIB_ITEM("Icmp6InGroupMembReductions", ICMP6_MIB_INGROUPMEMBREDUCTIONS),
110 SNMP_MIB_ITEM("Icmp6InRouterSolicits", ICMP6_MIB_INROUTERSOLICITS),
111 SNMP_MIB_ITEM("Icmp6InRouterAdvertisements", ICMP6_MIB_INROUTERADVERTISEMENTS),
112 SNMP_MIB_ITEM("Icmp6InNeighborSolicits", ICMP6_MIB_INNEIGHBORSOLICITS),
113 SNMP_MIB_ITEM("Icmp6InNeighborAdvertisements", ICMP6_MIB_INNEIGHBORADVERTISEMENTS),
114 SNMP_MIB_ITEM("Icmp6InRedirects", ICMP6_MIB_INREDIRECTS),
115 SNMP_MIB_ITEM("Icmp6OutMsgs", ICMP6_MIB_OUTMSGS),
116 SNMP_MIB_ITEM("Icmp6OutDestUnreachs", ICMP6_MIB_OUTDESTUNREACHS),
117 SNMP_MIB_ITEM("Icmp6OutPktTooBigs", ICMP6_MIB_OUTPKTTOOBIGS),
118 SNMP_MIB_ITEM("Icmp6OutTimeExcds", ICMP6_MIB_OUTTIMEEXCDS),
119 SNMP_MIB_ITEM("Icmp6OutParmProblems", ICMP6_MIB_OUTPARMPROBLEMS),
120 SNMP_MIB_ITEM("Icmp6OutEchoReplies", ICMP6_MIB_OUTECHOREPLIES),
121 SNMP_MIB_ITEM("Icmp6OutRouterSolicits", ICMP6_MIB_OUTROUTERSOLICITS),
122 SNMP_MIB_ITEM("Icmp6OutNeighborSolicits", ICMP6_MIB_OUTNEIGHBORSOLICITS),
123 SNMP_MIB_ITEM("Icmp6OutNeighborAdvertisements", ICMP6_MIB_OUTNEIGHBORADVERTISEMENTS),
124 SNMP_MIB_ITEM("Icmp6OutRedirects", ICMP6_MIB_OUTREDIRECTS),
125 SNMP_MIB_ITEM("Icmp6OutGroupMembResponses", ICMP6_MIB_OUTGROUPMEMBRESPONSES),
126 SNMP_MIB_ITEM("Icmp6OutGroupMembReductions", ICMP6_MIB_OUTGROUPMEMBREDUCTIONS),
127 SNMP_MIB_SENTINEL
128};
129
130static struct snmp_mib snmp6_udp6_list[] = {
131 SNMP_MIB_ITEM("Udp6InDatagrams", UDP_MIB_INDATAGRAMS),
132 SNMP_MIB_ITEM("Udp6NoPorts", UDP_MIB_NOPORTS),
133 SNMP_MIB_ITEM("Udp6InErrors", UDP_MIB_INERRORS),
134 SNMP_MIB_ITEM("Udp6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
135 SNMP_MIB_SENTINEL
136};
137
ba4e58ec
GR
138static struct snmp_mib snmp6_udplite6_list[] = {
139 SNMP_MIB_ITEM("UdpLite6InDatagrams", UDP_MIB_INDATAGRAMS),
140 SNMP_MIB_ITEM("UdpLite6NoPorts", UDP_MIB_NOPORTS),
141 SNMP_MIB_ITEM("UdpLite6InErrors", UDP_MIB_INERRORS),
142 SNMP_MIB_ITEM("UdpLite6OutDatagrams", UDP_MIB_OUTDATAGRAMS),
143 SNMP_MIB_SENTINEL
144};
145
1da177e4
LT
146static unsigned long
147fold_field(void *mib[], int offt)
148{
1ab1457c
YH
149 unsigned long res = 0;
150 int i;
151
152 for_each_possible_cpu(i) {
153 res += *(((unsigned long *)per_cpu_ptr(mib[0], i)) + offt);
154 res += *(((unsigned long *)per_cpu_ptr(mib[1], i)) + offt);
155 }
156 return res;
1da177e4
LT
157}
158
159static inline void
160snmp6_seq_show_item(struct seq_file *seq, void **mib, struct snmp_mib *itemlist)
161{
162 int i;
163 for (i=0; itemlist[i].name; i++)
1ab1457c 164 seq_printf(seq, "%-32s\t%lu\n", itemlist[i].name,
1da177e4
LT
165 fold_field(mib, itemlist[i].entry));
166}
167
168static int snmp6_seq_show(struct seq_file *seq, void *v)
169{
170 struct inet6_dev *idev = (struct inet6_dev *)seq->private;
171
172 if (idev) {
173 seq_printf(seq, "%-32s\t%u\n", "ifIndex", idev->dev->ifindex);
a11d206d 174 snmp6_seq_show_item(seq, (void **)idev->stats.ipv6, snmp6_ipstats_list);
1da177e4
LT
175 snmp6_seq_show_item(seq, (void **)idev->stats.icmpv6, snmp6_icmp6_list);
176 } else {
177 snmp6_seq_show_item(seq, (void **)ipv6_statistics, snmp6_ipstats_list);
178 snmp6_seq_show_item(seq, (void **)icmpv6_statistics, snmp6_icmp6_list);
179 snmp6_seq_show_item(seq, (void **)udp_stats_in6, snmp6_udp6_list);
ba4e58ec 180 snmp6_seq_show_item(seq, (void **)udplite_stats_in6, snmp6_udplite6_list);
1da177e4
LT
181 }
182 return 0;
183}
184
185static int sockstat6_seq_open(struct inode *inode, struct file *file)
186{
187 return single_open(file, sockstat6_seq_show, NULL);
188}
189
9a32144e 190static const struct file_operations sockstat6_seq_fops = {
1da177e4
LT
191 .owner = THIS_MODULE,
192 .open = sockstat6_seq_open,
193 .read = seq_read,
194 .llseek = seq_lseek,
195 .release = single_release,
196};
197
198static int snmp6_seq_open(struct inode *inode, struct file *file)
199{
200 return single_open(file, snmp6_seq_show, PDE(inode)->data);
201}
202
9a32144e 203static const struct file_operations snmp6_seq_fops = {
1da177e4
LT
204 .owner = THIS_MODULE,
205 .open = snmp6_seq_open,
206 .read = seq_read,
207 .llseek = seq_lseek,
208 .release = single_release,
209};
210
211int snmp6_register_dev(struct inet6_dev *idev)
212{
213 struct proc_dir_entry *p;
214
215 if (!idev || !idev->dev)
216 return -EINVAL;
217
218 if (!proc_net_devsnmp6)
219 return -ENOENT;
220
221 p = create_proc_entry(idev->dev->name, S_IRUGO, proc_net_devsnmp6);
222 if (!p)
223 return -ENOMEM;
224
225 p->data = idev;
226 p->proc_fops = &snmp6_seq_fops;
227
228 idev->stats.proc_dir_entry = p;
229 return 0;
230}
231
232int snmp6_unregister_dev(struct inet6_dev *idev)
233{
234 if (!proc_net_devsnmp6)
235 return -ENOENT;
236 if (!idev || !idev->stats.proc_dir_entry)
237 return -EINVAL;
238 remove_proc_entry(idev->stats.proc_dir_entry->name,
239 proc_net_devsnmp6);
240 return 0;
241}
242
243int __init ipv6_misc_proc_init(void)
244{
245 int rc = 0;
246
247 if (!proc_net_fops_create("snmp6", S_IRUGO, &snmp6_seq_fops))
248 goto proc_snmp6_fail;
249
250 proc_net_devsnmp6 = proc_mkdir("dev_snmp6", proc_net);
251 if (!proc_net_devsnmp6)
252 goto proc_dev_snmp6_fail;
253
254 if (!proc_net_fops_create("sockstat6", S_IRUGO, &sockstat6_seq_fops))
255 goto proc_sockstat6_fail;
256out:
257 return rc;
258
259proc_sockstat6_fail:
260 proc_net_remove("dev_snmp6");
261proc_dev_snmp6_fail:
262 proc_net_remove("snmp6");
263proc_snmp6_fail:
264 rc = -ENOMEM;
265 goto out;
266}
267
268void ipv6_misc_proc_exit(void)
269{
270 proc_net_remove("sockstat6");
271 proc_net_remove("dev_snmp6");
272 proc_net_remove("snmp6");
273}
274
275#else /* CONFIG_PROC_FS */
276
277
278int snmp6_register_dev(struct inet6_dev *idev)
279{
280 return 0;
281}
282
283int snmp6_unregister_dev(struct inet6_dev *idev)
284{
285 return 0;
286}
287#endif /* CONFIG_PROC_FS */
288
289int snmp6_alloc_dev(struct inet6_dev *idev)
290{
291 int err = -ENOMEM;
292
293 if (!idev || !idev->dev)
294 return -EINVAL;
295
a11d206d
YH
296 if (snmp6_mib_init((void **)idev->stats.ipv6, sizeof(struct ipstats_mib),
297 __alignof__(struct ipstats_mib)) < 0)
298 goto err_ip;
1da177e4
LT
299 if (snmp6_mib_init((void **)idev->stats.icmpv6, sizeof(struct icmpv6_mib),
300 __alignof__(struct icmpv6_mib)) < 0)
301 goto err_icmp;
302
303 return 0;
304
305err_icmp:
a11d206d
YH
306 snmp6_mib_free((void **)idev->stats.ipv6);
307err_ip:
1da177e4
LT
308 return err;
309}
310
311int snmp6_free_dev(struct inet6_dev *idev)
312{
313 snmp6_mib_free((void **)idev->stats.icmpv6);
a11d206d 314 snmp6_mib_free((void **)idev->stats.ipv6);
1da177e4
LT
315 return 0;
316}
317
318