patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / net / ipv4 / proc.c
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.  It is mainly used for debugging and
8  *              statistics.
9  *
10  * Version:     $Id: proc.c,v 1.45 2001/05/16 16:45:35 davem Exp $
11  *
12  * Authors:     Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
13  *              Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
14  *              Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
15  *              Erik Schoenfelder, <schoenfr@ibr.cs.tu-bs.de>
16  *
17  * Fixes:
18  *              Alan Cox        :       UDP sockets show the rxqueue/txqueue
19  *                                      using hint flag for the netinfo.
20  *      Pauline Middelink       :       identd support
21  *              Alan Cox        :       Make /proc safer.
22  *      Erik Schoenfelder       :       /proc/net/snmp
23  *              Alan Cox        :       Handle dead sockets properly.
24  *      Gerhard Koerting        :       Show both timers
25  *              Alan Cox        :       Allow inode to be NULL (kernel socket)
26  *      Andi Kleen              :       Add support for open_requests and
27  *                                      split functions for more readibility.
28  *      Andi Kleen              :       Add support for /proc/net/netstat
29  *      Arnaldo C. Melo         :       Convert to seq_file
30  *
31  *              This program is free software; you can redistribute it and/or
32  *              modify it under the terms of the GNU General Public License
33  *              as published by the Free Software Foundation; either version
34  *              2 of the License, or (at your option) any later version.
35  */
36 #include <linux/types.h>
37 #include <net/icmp.h>
38 #include <net/protocol.h>
39 #include <net/tcp.h>
40 #include <net/udp.h>
41 #include <linux/proc_fs.h>
42 #include <linux/seq_file.h>
43 #include <net/sock.h>
44 #include <net/raw.h>
45
46 static int fold_prot_inuse(struct proto *proto)
47 {
48         int res = 0;
49         int cpu;
50
51         for (cpu = 0; cpu < NR_CPUS; cpu++)
52                 res += proto->stats[cpu].inuse;
53
54         return res;
55 }
56
57 /*
58  *      Report socket allocation statistics [mea@utu.fi]
59  */
60 static int sockstat_seq_show(struct seq_file *seq, void *v)
61 {
62         /* From net/socket.c */
63         extern void socket_seq_show(struct seq_file *seq);
64
65         socket_seq_show(seq);
66         seq_printf(seq, "TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
67                    fold_prot_inuse(&tcp_prot), atomic_read(&tcp_orphan_count),
68                    tcp_tw_count, atomic_read(&tcp_sockets_allocated),
69                    atomic_read(&tcp_memory_allocated));
70         seq_printf(seq, "UDP: inuse %d\n", fold_prot_inuse(&udp_prot));
71         seq_printf(seq, "RAW: inuse %d\n", fold_prot_inuse(&raw_prot));
72         seq_printf(seq,  "FRAG: inuse %d memory %d\n", ip_frag_nqueues,
73                    atomic_read(&ip_frag_mem));
74         return 0;
75 }
76
77 static int sockstat_seq_open(struct inode *inode, struct file *file)
78 {
79         return single_open(file, sockstat_seq_show, NULL);
80 }
81
82 static struct file_operations sockstat_seq_fops = {
83         .owner   = THIS_MODULE,
84         .open    = sockstat_seq_open,
85         .read    = seq_read,
86         .llseek  = seq_lseek,
87         .release = single_release,
88 };
89
90 static unsigned long
91 __fold_field(void *mib[], int offt)
92 {
93         unsigned long res = 0;
94         int i;
95
96         for (i = 0; i < NR_CPUS; i++) {
97                 if (!cpu_possible(i))
98                         continue;
99                 res +=
100                     *((unsigned long *) (((void *) per_cpu_ptr(mib[0], i)) +
101                                          offt));
102                 res +=
103                     *((unsigned long *) (((void *) per_cpu_ptr(mib[1], i)) +
104                                          offt));
105         }
106         return res;
107 }
108
109 #define fold_field(_mib, _nr)   __fold_field(_mib, (sizeof(unsigned long) * (_nr)))
110
111 /* snmp items */
112 static struct snmp_item snmp4_ipstats_list[] = {
113 #define __SNMP_GEN(x,y) SNMP_ITEM(struct ipstats_mib, x, y)
114 #define SNMP_GEN(x)     __SNMP_GEN(x, #x)
115         SNMP_GEN(InReceives),
116         SNMP_GEN(InHdrErrors),
117         SNMP_GEN(InAddrErrors),
118         __SNMP_GEN(OutForwDatagrams,"ForwDatagrams"),   /* for backward compatibility */
119         SNMP_GEN(InUnknownProtos),
120         SNMP_GEN(InDiscards),
121         SNMP_GEN(InDelivers),
122         SNMP_GEN(OutRequests),
123         SNMP_GEN(OutDiscards),
124         SNMP_GEN(OutNoRoutes),
125         SNMP_GEN(ReasmTimeout),
126         SNMP_GEN(ReasmReqds),
127         SNMP_GEN(ReasmOKs),
128         SNMP_GEN(ReasmFails),
129         SNMP_GEN(FragOKs),
130         SNMP_GEN(FragFails),
131         SNMP_GEN(FragCreates),
132         SNMP_ITEM_SENTINEL
133 #undef SNMP_GEN
134 };
135
136 /*
137  *      Called from the PROCfs module. This outputs /proc/net/snmp.
138  */
139 static int snmp_seq_show(struct seq_file *seq, void *v)
140 {
141         int i;
142
143         seq_printf(seq, "Ip: Forwarding DefaultTTL");
144
145         for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
146                 seq_printf(seq, " %s", snmp4_ipstats_list[i].name);
147
148         seq_printf(seq, "\nIp: %d %d",
149                         ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
150
151         for (i = 0; snmp4_ipstats_list[i].name != NULL; i++)
152                 seq_printf(seq, " %lu",
153                            __fold_field((void **) ip_statistics, 
154                                         snmp4_ipstats_list[i].offset));
155
156         seq_printf(seq, "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds "
157                         "InParmProbs InSrcQuenchs InRedirects InEchos "
158                         "InEchoReps InTimestamps InTimestampReps InAddrMasks "
159                         "InAddrMaskReps OutMsgs OutErrors OutDestUnreachs "
160                         "OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects "
161                         "OutEchos OutEchoReps OutTimestamps OutTimestampReps "
162                         "OutAddrMasks OutAddrMaskReps\nIcmp:");
163
164         for (i = 0;
165              i < offsetof(struct icmp_mib, dummy) / sizeof(unsigned long); i++)
166                 seq_printf(seq, " %lu",
167                            fold_field((void **) icmp_statistics, i)); 
168
169         seq_printf(seq, "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens "
170                         "PassiveOpens AttemptFails EstabResets CurrEstab "
171                         "InSegs OutSegs RetransSegs InErrs OutRsts\nTcp:");
172
173         for (i = 0;
174              i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++) {
175                 if (i == (offsetof(struct tcp_mib, TcpMaxConn) / sizeof(unsigned long)))
176                         /* MaxConn field is negative, RFC 2012 */
177                         seq_printf(seq, " %ld", 
178                                    fold_field((void **) tcp_statistics, i));
179                 else
180                         seq_printf(seq, " %lu", 
181                                    fold_field((void **) tcp_statistics, i));
182         }
183
184         seq_printf(seq, "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
185                         "Udp:");
186
187         for (i = 0;
188              i < offsetof(struct udp_mib, __pad) / sizeof(unsigned long); i++)
189                 seq_printf(seq, " %lu", 
190                                 fold_field((void **) udp_statistics, i));
191
192         seq_putc(seq, '\n');
193         return 0;
194 }
195
196 static int snmp_seq_open(struct inode *inode, struct file *file)
197 {
198         return single_open(file, snmp_seq_show, NULL);
199 }
200
201 static struct file_operations snmp_seq_fops = {
202         .owner   = THIS_MODULE,
203         .open    = snmp_seq_open,
204         .read    = seq_read,
205         .llseek  = seq_lseek,
206         .release = single_release,
207 };
208
209 /*
210  *      Output /proc/net/netstat
211  */
212 static int netstat_seq_show(struct seq_file *seq, void *v)
213 {
214         int i;
215
216         seq_puts(seq, "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
217                       " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
218                       " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
219                       " TW TWRecycled TWKilled"
220                       " PAWSPassive PAWSActive PAWSEstab"
221                       " DelayedACKs DelayedACKLocked DelayedACKLost"
222                       " ListenOverflows ListenDrops"
223                       " TCPPrequeued TCPDirectCopyFromBacklog"
224                       " TCPDirectCopyFromPrequeue TCPPrequeueDropped"
225                       " TCPHPHits TCPHPHitsToUser"
226                       " TCPPureAcks TCPHPAcks"
227                       " TCPRenoRecovery TCPSackRecovery"
228                       " TCPSACKReneging"
229                       " TCPFACKReorder TCPSACKReorder TCPRenoReorder"
230                       " TCPTSReorder"
231                       " TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo"
232                       " TCPLoss TCPLostRetransmit"
233                       " TCPRenoFailures TCPSackFailures TCPLossFailures"
234                       " TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans"
235                       " TCPTimeouts"
236                       " TCPRenoRecoveryFail TCPSackRecoveryFail"
237                       " TCPSchedulerFailed TCPRcvCollapsed"
238                       " TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv"
239                       " TCPDSACKOfoRecv"
240                       " TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose"
241                       " TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger"
242                       " TCPAbortFailed TCPMemoryPressures\n"
243                       "TcpExt:");
244         for (i = 0;
245              i < offsetof(struct linux_mib, __pad) / sizeof(unsigned long); 
246              i++)
247                 seq_printf(seq, " %lu", 
248                            fold_field((void **) net_statistics, i)); 
249         seq_putc(seq, '\n');
250         return 0;
251 }
252
253 static int netstat_seq_open(struct inode *inode, struct file *file)
254 {
255         return single_open(file, netstat_seq_show, NULL);
256 }
257
258 static struct file_operations netstat_seq_fops = {
259         .owner   = THIS_MODULE,
260         .open    = netstat_seq_open,
261         .read    = seq_read,
262         .llseek  = seq_lseek,
263         .release = single_release,
264 };
265
266 int __init ip_misc_proc_init(void)
267 {
268         int rc = 0;
269
270         if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
271                 goto out_netstat;
272
273         if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
274                 goto out_snmp;
275
276         if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
277                 goto out_sockstat;
278 out:
279         return rc;
280 out_sockstat:
281         proc_net_remove("snmp");
282 out_snmp:
283         proc_net_remove("netstat");
284 out_netstat:
285         rc = -ENOMEM;
286         goto out;
287 }
288