Import 2.1.15
[davej-history.git] / net / ipv4 / proc.c
blobc5721e5655b18d5d08f50799ee19eb45d79cbfba
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.
6 * This file implements the various access functions for the
7 * PROC file system. It is mainly used for debugging and
8 * statistics.
10 * Version: @(#)proc.c 1.0.5 05/27/93
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>
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)
27 * This program is free software; you can redistribute it and/or
28 * modify it under the terms of the GNU General Public License
29 * as published by the Free Software Foundation; either version
30 * 2 of the License, or (at your option) any later version.
32 #include <asm/system.h>
33 #include <linux/sched.h>
34 #include <linux/socket.h>
35 #include <linux/net.h>
36 #include <linux/un.h>
37 #include <linux/in.h>
38 #include <linux/param.h>
39 #include <linux/inet.h>
40 #include <linux/netdevice.h>
41 #include <net/ip.h>
42 #include <net/icmp.h>
43 #include <net/protocol.h>
44 #include <net/tcp.h>
45 #include <net/udp.h>
46 #include <linux/skbuff.h>
47 #include <net/sock.h>
48 #include <net/raw.h>
51 * Get__netinfo returns the length of that string.
53 * KNOWN BUGS
54 * As in get_unix_netinfo, the buffer might be too small. If this
55 * happens, get__netinfo returns only part of the available infos.
57 static int
58 get__netinfo(struct proto *pro,char*buffer,int format,char**start, off_t offset,int length)
60 struct sock **s_array;
61 struct sock *sp;
62 struct tcp_opt *tp;
63 int i;
64 int timer_active;
65 int timer_active1;
66 int timer_active2;
67 unsigned long timer_expires;
68 unsigned long dest, src;
69 unsigned short destp, srcp;
70 int len=0;
71 off_t pos=0;
72 off_t begin;
73 char tmpbuf[129];
75 s_array = pro->sock_array;
76 if(offset <128)
77 len +=sprintf(buffer,"%-127s\n",
78 " sl local_address rem_address st tx_queue "
79 "rx_queue tr tm->when retrnsmt uid timeout inode");
80 pos =128;
82 * This was very pretty but didn't work when a socket is destroyed
83 * at the wrong moment (eg a syn recv socket getting a reset), or
84 * a memory timer destroy. Instead of playing with timers we just
85 * concede defeat and cli().
87 start_bh_atomic();
89 for(i =0; i < SOCK_ARRAY_SIZE; i++)
91 sp = s_array[i];
93 while(sp != NULL)
95 pos +=128;
96 if(pos < offset)
98 sp = sp->next;
99 continue;
102 tp = &(sp->tp_pinfo.af_tcp);
104 dest = sp->daddr;
105 src = sp->saddr;
106 destp = sp->dummy_th.dest;
107 srcp = sp->dummy_th.source;
109 /* Since we are Little Endian we need to swap the bytes :-( */
110 destp =ntohs(destp);
111 srcp =ntohs(srcp);
112 timer_active1 =del_timer(&sp->retransmit_timer);
113 timer_active2 =del_timer(&sp->timer);
114 if(!timer_active1) sp->retransmit_timer.expires=0;
115 if(!timer_active2) sp->timer.expires=0;
116 timer_active=0;
117 timer_expires=(unsigned)-1;
118 if(timer_active1 &&
119 sp->retransmit_timer.expires < timer_expires) {
120 timer_active=timer_active1;
121 timer_expires=sp->retransmit_timer.expires;
123 if(timer_active2 &&
124 sp->timer.expires < timer_expires) {
125 timer_active=timer_active2;
126 timer_expires=sp->timer.expires;
128 sprintf(tmpbuf,"%4d: %08lX:%04X %08lX:%04X"
129 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
130 i, src, srcp, dest, destp, sp->state,
131 format==0?sp->write_seq-tp->snd_una:sp->wmem_alloc,
132 format==0?tp->rcv_nxt-sp->copied_seq:sp->rmem_alloc,
133 timer_active, timer_expires-jiffies, (unsigned) sp->retransmits,
134 sp->socket ? sp->socket->inode->i_uid:0,
135 timer_active?sp->timeout:0,
136 sp->socket ? sp->socket->inode->i_ino:0);
138 if(timer_active1)add_timer(&sp->retransmit_timer);
139 if(timer_active2)add_timer(&sp->timer);
140 len +=sprintf(buffer+len,"%-127s\n", tmpbuf);
142 * All sockets with (port mod SOCK_ARRAY_SIZE) = i
143 * are kept in sock_array[i], so we must follow the
144 * 'next' link to get them all.
146 if(len >= length)
147 break;
148 sp = sp->next;
150 if(len>= length)
151 break;
153 end_bh_atomic();
154 begin = len - (pos - offset);
155 *start = buffer + begin;
156 len -= begin;
157 if(len>length)
158 len = length;
159 return len;
163 inttcp_get_info(char*buffer,char**start, off_t offset,int length,int dummy)
165 returnget__netinfo(&tcp_prot, buffer,0, start, offset, length);
169 intudp_get_info(char*buffer,char**start, off_t offset,int length,int dummy)
171 returnget__netinfo(&udp_prot, buffer,1, start, offset, length);
175 intraw_get_info(char*buffer,char**start, off_t offset,int length,int dummy)
177 returnget__netinfo(&raw_prot, buffer,1, start, offset, length);
182 * Report socket allocation statistics [mea@utu.fi]
184 intafinet_get_info(char*buffer,char**start, off_t offset,int length,int dummy)
186 /* From net/socket.c */
187 externintsocket_get_info(char*,char**, off_t,int);
188 externstruct proto packet_prot;
190 int len =socket_get_info(buffer,start,offset,length);
192 len +=sprintf(buffer+len,"SOCK_ARRAY_SIZE=%d\n",SOCK_ARRAY_SIZE);
193 len +=sprintf(buffer+len,"TCP: inuse %d highest %d\n",
194 tcp_prot.inuse, tcp_prot.highestinuse);
195 len +=sprintf(buffer+len,"UDP: inuse %d highest %d\n",
196 udp_prot.inuse, udp_prot.highestinuse);
197 len +=sprintf(buffer+len,"RAW: inuse %d highest %d\n",
198 raw_prot.inuse, raw_prot.highestinuse);
199 len +=sprintf(buffer+len,"PAC: inuse %d highest %d\n",
200 packet_prot.inuse, packet_prot.highestinuse);
201 *start = buffer + offset;
202 len -= offset;
203 if(len > length)
204 len = length;
205 return len;
210 * Called from the PROCfs module. This outputs /proc/net/snmp.
213 intsnmp_get_info(char*buffer,char**start, off_t offset,int length,int dummy)
215 externstruct tcp_mib tcp_statistics;
216 externstruct udp_mib udp_statistics;
217 int len;
219 extern unsigned long tcp_rx_miss, tcp_rx_hit1,tcp_rx_hit2;
222 len =sprintf(buffer,
223 "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
224 "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
225 ip_statistics.IpForwarding, ip_statistics.IpDefaultTTL,
226 ip_statistics.IpInReceives, ip_statistics.IpInHdrErrors,
227 ip_statistics.IpInAddrErrors, ip_statistics.IpForwDatagrams,
228 ip_statistics.IpInUnknownProtos, ip_statistics.IpInDiscards,
229 ip_statistics.IpInDelivers, ip_statistics.IpOutRequests,
230 ip_statistics.IpOutDiscards, ip_statistics.IpOutNoRoutes,
231 ip_statistics.IpReasmTimeout, ip_statistics.IpReasmReqds,
232 ip_statistics.IpReasmOKs, ip_statistics.IpReasmFails,
233 ip_statistics.IpFragOKs, ip_statistics.IpFragFails,
234 ip_statistics.IpFragCreates);
236 len +=sprintf(buffer + len,
237 "Icmp: 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"
238 "Icmp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
239 icmp_statistics.IcmpInMsgs, icmp_statistics.IcmpInErrors,
240 icmp_statistics.IcmpInDestUnreachs, icmp_statistics.IcmpInTimeExcds,
241 icmp_statistics.IcmpInParmProbs, icmp_statistics.IcmpInSrcQuenchs,
242 icmp_statistics.IcmpInRedirects, icmp_statistics.IcmpInEchos,
243 icmp_statistics.IcmpInEchoReps, icmp_statistics.IcmpInTimestamps,
244 icmp_statistics.IcmpInTimestampReps, icmp_statistics.IcmpInAddrMasks,
245 icmp_statistics.IcmpInAddrMaskReps, icmp_statistics.IcmpOutMsgs,
246 icmp_statistics.IcmpOutErrors, icmp_statistics.IcmpOutDestUnreachs,
247 icmp_statistics.IcmpOutTimeExcds, icmp_statistics.IcmpOutParmProbs,
248 icmp_statistics.IcmpOutSrcQuenchs, icmp_statistics.IcmpOutRedirects,
249 icmp_statistics.IcmpOutEchos, icmp_statistics.IcmpOutEchoReps,
250 icmp_statistics.IcmpOutTimestamps, icmp_statistics.IcmpOutTimestampReps,
251 icmp_statistics.IcmpOutAddrMasks, icmp_statistics.IcmpOutAddrMaskReps);
253 len +=sprintf(buffer + len,
254 "Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs\n"
255 "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
256 tcp_statistics.TcpRtoAlgorithm, tcp_statistics.TcpRtoMin,
257 tcp_statistics.TcpRtoMax, tcp_statistics.TcpMaxConn,
258 tcp_statistics.TcpActiveOpens, tcp_statistics.TcpPassiveOpens,
259 tcp_statistics.TcpAttemptFails, tcp_statistics.TcpEstabResets,
260 tcp_statistics.TcpCurrEstab, tcp_statistics.TcpInSegs,
261 tcp_statistics.TcpOutSegs, tcp_statistics.TcpRetransSegs);
263 len +=sprintf(buffer + len,
264 "Udp: InDatagrams NoPorts InErrors OutDatagrams\nUdp: %lu %lu %lu %lu\n",
265 udp_statistics.UdpInDatagrams, udp_statistics.UdpNoPorts,
266 udp_statistics.UdpInErrors, udp_statistics.UdpOutDatagrams);
268 len += sprintf( buffer + len,
269 "TCP fast path RX: H2: %ul H1: %ul L: %ul\n",
270 tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
273 if(offset >= len)
275 *start = buffer;
276 return0;
278 *start = buffer + offset;
279 len -= offset;
280 if(len > length)
281 len = length;
282 return len;
close