ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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 nr)
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                                          sizeof (unsigned long) * nr));
102                 res +=
103                     *((unsigned long *) (((void *) per_cpu_ptr(mib[1], i)) +
104                                          sizeof (unsigned long) * nr));
105         }
106         return res;
107 }
108
109 /*
110  *      Called from the PROCfs module. This outputs /proc/net/snmp.
111  */
112 static int snmp_seq_show(struct seq_file *seq, void *v)
113 {
114         int i;
115
116         seq_printf(seq, "Ip: Forwarding DefaultTTL InReceives InHdrErrors "
117                         "InAddrErrors ForwDatagrams InUnknownProtos "
118                         "InDiscards InDelivers OutRequests OutDiscards "
119                         "OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs "
120                         "ReasmFails FragOKs FragFails FragCreates\nIp: %d %d",
121                         ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
122
123         for (i = 0;
124              i < offsetof(struct ip_mib, __pad) / sizeof(unsigned long); i++)
125                 seq_printf(seq, " %lu",
126                            fold_field((void **) ip_statistics, i));
127
128         seq_printf(seq, "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds "
129                         "InParmProbs InSrcQuenchs InRedirects InEchos "
130                         "InEchoReps InTimestamps InTimestampReps InAddrMasks "
131                         "InAddrMaskReps OutMsgs OutErrors OutDestUnreachs "
132                         "OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects "
133                         "OutEchos OutEchoReps OutTimestamps OutTimestampReps "
134                         "OutAddrMasks OutAddrMaskReps\nIcmp:");
135
136         for (i = 0;
137              i < offsetof(struct icmp_mib, dummy) / sizeof(unsigned long); i++)
138                 seq_printf(seq, " %lu",
139                            fold_field((void **) icmp_statistics, i)); 
140
141         seq_printf(seq, "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens "
142                         "PassiveOpens AttemptFails EstabResets CurrEstab "
143                         "InSegs OutSegs RetransSegs InErrs OutRsts\nTcp:");
144
145         for (i = 0;
146              i < offsetof(struct tcp_mib, __pad) / sizeof(unsigned long); i++) {
147                 if (i == (offsetof(struct tcp_mib, TcpMaxConn) / sizeof(unsigned long)))
148                         /* MaxConn field is negative, RFC 2012 */
149                         seq_printf(seq, " %ld", 
150                                    fold_field((void **) tcp_statistics, i));
151                 else
152                         seq_printf(seq, " %lu", 
153                                    fold_field((void **) tcp_statistics, i));
154         }
155
156         seq_printf(seq, "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
157                         "Udp:");
158
159         for (i = 0;
160              i < offsetof(struct udp_mib, __pad) / sizeof(unsigned long); i++)
161                 seq_printf(seq, " %lu", 
162                                 fold_field((void **) udp_statistics, i));
163
164         seq_putc(seq, '\n');
165         return 0;
166 }
167
168 static int snmp_seq_open(struct inode *inode, struct file *file)
169 {
170         return single_open(file, snmp_seq_show, NULL);
171 }
172
173 static struct file_operations snmp_seq_fops = {
174         .owner   = THIS_MODULE,
175         .open    = snmp_seq_open,
176         .read    = seq_read,
177         .llseek  = seq_lseek,
178         .release = single_release,
179 };
180
181 /*
182  *      Output /proc/net/netstat
183  */
184 static int netstat_seq_show(struct seq_file *seq, void *v)
185 {
186         int i;
187
188         seq_puts(seq, "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
189                       " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
190                       " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
191                       " TW TWRecycled TWKilled"
192                       " PAWSPassive PAWSActive PAWSEstab"
193                       " DelayedACKs DelayedACKLocked DelayedACKLost"
194                       " ListenOverflows ListenDrops"
195                       " TCPPrequeued TCPDirectCopyFromBacklog"
196                       " TCPDirectCopyFromPrequeue TCPPrequeueDropped"
197                       " TCPHPHits TCPHPHitsToUser"
198                       " TCPPureAcks TCPHPAcks"
199                       " TCPRenoRecovery TCPSackRecovery"
200                       " TCPSACKReneging"
201                       " TCPFACKReorder TCPSACKReorder TCPRenoReorder"
202                       " TCPTSReorder"
203                       " TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo"
204                       " TCPLoss TCPLostRetransmit"
205                       " TCPRenoFailures TCPSackFailures TCPLossFailures"
206                       " TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans"
207                       " TCPTimeouts"
208                       " TCPRenoRecoveryFail TCPSackRecoveryFail"
209                       " TCPSchedulerFailed TCPRcvCollapsed"
210                       " TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv"
211                       " TCPDSACKOfoRecv"
212                       " TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose"
213                       " TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger"
214                       " TCPAbortFailed TCPMemoryPressures\n"
215                       "TcpExt:");
216         for (i = 0;
217              i < offsetof(struct linux_mib, __pad) / sizeof(unsigned long); 
218              i++)
219                 seq_printf(seq, " %lu", 
220                            fold_field((void **) net_statistics, i)); 
221         seq_putc(seq, '\n');
222         return 0;
223 }
224
225 static int netstat_seq_open(struct inode *inode, struct file *file)
226 {
227         return single_open(file, netstat_seq_show, NULL);
228 }
229
230 static struct file_operations netstat_seq_fops = {
231         .owner   = THIS_MODULE,
232         .open    = netstat_seq_open,
233         .read    = seq_read,
234         .llseek  = seq_lseek,
235         .release = single_release,
236 };
237
238 int __init ip_misc_proc_init(void)
239 {
240         int rc = 0;
241
242         if (!proc_net_fops_create("netstat", S_IRUGO, &netstat_seq_fops))
243                 goto out_netstat;
244
245         if (!proc_net_fops_create("snmp", S_IRUGO, &snmp_seq_fops))
246                 goto out_snmp;
247
248         if (!proc_net_fops_create("sockstat", S_IRUGO, &sockstat_seq_fops))
249                 goto out_sockstat;
250 out:
251         return rc;
252 out_sockstat:
253         proc_net_remove("snmp");
254 out_snmp:
255         proc_net_remove("netstat");
256 out_netstat:
257         rc = -ENOMEM;
258         goto out;
259 }
260