import of upstream 2.4.34.4 from kernel.org
[linux-2.4.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  *
30  *              This program is free software; you can redistribute it and/or
31  *              modify it under the terms of the GNU General Public License
32  *              as published by the Free Software Foundation; either version
33  *              2 of the License, or (at your option) any later version.
34  */
35 #include <asm/system.h>
36 #include <linux/sched.h>
37 #include <linux/socket.h>
38 #include <linux/net.h>
39 #include <linux/un.h>
40 #include <linux/in.h>
41 #include <linux/param.h>
42 #include <linux/inet.h>
43 #include <linux/netdevice.h>
44 #include <net/ip.h>
45 #include <net/icmp.h>
46 #include <net/protocol.h>
47 #include <net/tcp.h>
48 #include <net/udp.h>
49 #include <linux/skbuff.h>
50 #include <net/sock.h>
51 #include <net/raw.h>
52
53 static int fold_prot_inuse(struct proto *proto)
54 {
55         int res = 0;
56         int cpu;
57
58         for (cpu=0; cpu<smp_num_cpus; cpu++)
59                 res += proto->stats[cpu_logical_map(cpu)].inuse;
60
61         return res;
62 }
63
64 /*
65  *      Report socket allocation statistics [mea@utu.fi]
66  */
67 int afinet_get_info(char *buffer, char **start, off_t offset, int length)
68 {
69         /* From  net/socket.c  */
70         extern int socket_get_info(char *, char **, off_t, int);
71
72         int len  = socket_get_info(buffer,start,offset,length);
73
74         len += sprintf(buffer+len,"TCP: inuse %d orphan %d tw %d alloc %d mem %d\n",
75                        fold_prot_inuse(&tcp_prot),
76                        atomic_read(&tcp_orphan_count), tcp_tw_count,
77                        atomic_read(&tcp_sockets_allocated),
78                        atomic_read(&tcp_memory_allocated));
79         len += sprintf(buffer+len,"UDP: inuse %d\n",
80                        fold_prot_inuse(&udp_prot));
81         len += sprintf(buffer+len,"RAW: inuse %d\n",
82                        fold_prot_inuse(&raw_prot));
83         len += sprintf(buffer+len, "FRAG: inuse %d memory %d\n",
84                        ip_frag_nqueues, atomic_read(&ip_frag_mem));
85         if (offset >= len)
86         {
87                 *start = buffer;
88                 return 0;
89         }
90         *start = buffer + offset;
91         len -= offset;
92         if (len > length)
93                 len = length;
94         if (len < 0)
95                 len = 0;
96         return len;
97 }
98
99 static unsigned long fold_field(unsigned long *begin, int sz, int nr)
100 {
101         unsigned long res = 0;
102         int i;
103
104         sz /= sizeof(unsigned long);
105
106         for (i=0; i<smp_num_cpus; i++) {
107                 res += begin[2*cpu_logical_map(i)*sz + nr];
108                 res += begin[(2*cpu_logical_map(i)+1)*sz + nr];
109         }
110         return res;
111 }
112
113 /* 
114  *      Called from the PROCfs module. This outputs /proc/net/snmp.
115  */
116  
117 int snmp_get_info(char *buffer, char **start, off_t offset, int length)
118 {
119         extern int sysctl_ip_default_ttl;
120         int len, i;
121
122         len = sprintf (buffer,
123                 "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
124                 "Ip: %d %d", ipv4_devconf.forwarding ? 1 : 2, sysctl_ip_default_ttl);
125         for (i=0; i<offsetof(struct ip_mib, __pad)/sizeof(unsigned long); i++)
126                 len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)ip_statistics, sizeof(struct ip_mib), i));
127
128         len += sprintf (buffer + len,
129                 "\nIcmp: InMsgs InErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps\n"
130                   "Icmp:");
131         for (i=0; i<offsetof(struct icmp_mib, dummy)/sizeof(unsigned long); i++)
132                 len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)icmp_statistics, sizeof(struct icmp_mib), i));
133
134         len += sprintf (buffer + len,
135                 "\nTcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts\n"
136                   "Tcp:");
137         for (i=0; i<offsetof(struct tcp_mib, __pad)/sizeof(unsigned long); i++) {
138                 if (i == (offsetof(struct tcp_mib, TcpMaxConn) / sizeof(unsigned long)))
139                         /* MaxConn field is negative, RFC 2012 */
140                         len += sprintf(buffer+len, " %ld",
141                                        fold_field((unsigned long*)tcp_statistics,
142                                                   sizeof(struct tcp_mib), i));
143                 else
144                         len += sprintf(buffer+len, " %lu",
145                                        fold_field((unsigned long*)tcp_statistics,
146                                                   sizeof(struct tcp_mib), i));
147         }
148         len += sprintf (buffer + len,
149                 "\nUdp: InDatagrams NoPorts InErrors OutDatagrams\n"
150                   "Udp:");
151         for (i=0; i<offsetof(struct udp_mib, __pad)/sizeof(unsigned long); i++)
152                 len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)udp_statistics, sizeof(struct udp_mib), i));
153
154         len += sprintf (buffer + len, "\n");
155
156         if (offset >= len)
157         {
158                 *start = buffer;
159                 return 0;
160         }
161         *start = buffer + offset;
162         len -= offset;
163         if (len > length)
164                 len = length;
165         if (len < 0)
166                 len = 0; 
167         return len;
168 }
169
170 /* 
171  *      Output /proc/net/netstat
172  */
173  
174 int netstat_get_info(char *buffer, char **start, off_t offset, int length)
175 {
176         int len, i;
177
178         len = sprintf(buffer,
179                       "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
180                       " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
181                       " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
182                       " TW TWRecycled TWKilled"
183                       " PAWSPassive PAWSActive PAWSEstab"
184                       " DelayedACKs DelayedACKLocked DelayedACKLost"
185                       " ListenOverflows ListenDrops"
186                       " TCPPrequeued TCPDirectCopyFromBacklog"
187                       " TCPDirectCopyFromPrequeue TCPPrequeueDropped"
188                       " TCPHPHits TCPHPHitsToUser"
189                       " TCPPureAcks TCPHPAcks"
190                       " TCPRenoRecovery TCPSackRecovery"
191                       " TCPSACKReneging"
192                       " TCPFACKReorder TCPSACKReorder TCPRenoReorder TCPTSReorder"
193                       " TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo"
194                       " TCPLoss TCPLostRetransmit"
195                       " TCPRenoFailures TCPSackFailures TCPLossFailures"
196                       " TCPFastRetrans TCPForwardRetrans TCPSlowStartRetrans"
197                       " TCPTimeouts"
198                       " TCPRenoRecoveryFail TCPSackRecoveryFail"
199                       " TCPSchedulerFailed TCPRcvCollapsed"
200                       " TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv"
201                       " TCPAbortOnSyn TCPAbortOnData TCPAbortOnClose"
202                       " TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger"
203                       " TCPAbortFailed TCPMemoryPressures\n"
204                       "TcpExt:");
205         for (i=0; i<offsetof(struct linux_mib, __pad)/sizeof(unsigned long); i++)
206                 len += sprintf(buffer+len, " %lu", fold_field((unsigned long*)net_statistics, sizeof(struct linux_mib), i));
207
208         len += sprintf (buffer + len, "\n");
209
210         if (offset >= len)
211         {
212                 *start = buffer;
213                 return 0;
214         }
215         *start = buffer + offset;
216         len -= offset;
217         if (len > length)
218                 len = length;
219         if (len < 0)
220                 len = 0; 
221         return len;
222 }