root/net/ipv4/proc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. get__netinfo
  2. tcp_get_info
  3. udp_get_info
  4. raw_get_info
  5. afinet_get_info
  6. snmp_get_info

   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:     @(#)proc.c      1.0.5   05/27/93
  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  *
  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.
  31  */
  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>
  49 
  50 /*
  51  * Get__netinfo returns the length of that string.
  52  *
  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.
  56  */
  57 static int
  58 get__netinfo(struct proto *pro, char *buffer, int format, char **start, off_t offset, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
  59 {
  60         struct sock **s_array;
  61         struct sock *sp;
  62         int i;
  63         int timer_active;
  64         int timer_active1;
  65         int timer_active2;
  66         unsigned long timer_expires;
  67         unsigned long  dest, src;
  68         unsigned short destp, srcp;
  69         int len=0;
  70         off_t pos=0;
  71         off_t begin;
  72         char tmpbuf[129];
  73   
  74         s_array = pro->sock_array;
  75         if (offset < 128) 
  76                 len += sprintf(buffer, "%-127s\n",
  77                                "  sl  local_address rem_address   st tx_queue "
  78                                "rx_queue tr tm->when retrnsmt   uid  timeout inode");
  79         pos = 128;
  80 /*
  81  *      This was very pretty but didn't work when a socket is destroyed
  82  *      at the wrong moment (eg a syn recv socket getting a reset), or
  83  *      a memory timer destroy. Instead of playing with timers we just
  84  *      concede defeat and cli().
  85  */
  86         for(i = 0; i < SOCK_ARRAY_SIZE; i++) 
  87         {
  88                 cli();
  89                 sp = s_array[i];
  90                 while(sp != NULL) 
  91                 {
  92                         pos += 128;
  93                         if (pos < offset)
  94                         {
  95                                 sp = sp->next;
  96                                 continue;
  97                         }
  98                         dest  = sp->daddr;
  99                         src   = sp->saddr;
 100                         destp = sp->dummy_th.dest;
 101                         srcp  = sp->dummy_th.source;
 102 
 103                         /* Since we are Little Endian we need to swap the bytes :-( */
 104                         destp = ntohs(destp);
 105                         srcp  = ntohs(srcp);
 106                         timer_active1 = del_timer(&sp->retransmit_timer);
 107                         timer_active2 = del_timer(&sp->timer);
 108                         if (!timer_active1) sp->retransmit_timer.expires=0;
 109                         if (!timer_active2) sp->timer.expires=0;
 110                         timer_active=0;
 111                         timer_expires=(unsigned)-1;
 112                         if (timer_active1 &&
 113                           sp->retransmit_timer.expires < timer_expires) {
 114                             timer_active=timer_active1;
 115                             timer_expires=sp->retransmit_timer.expires;
 116                         }
 117                         if (timer_active2 &&
 118                           sp->timer.expires < timer_expires) {
 119                             timer_active=timer_active2;
 120                             timer_expires=sp->timer.expires;
 121                         }
 122                         sprintf(tmpbuf, "%4d: %08lX:%04X %08lX:%04X"
 123                                 " %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld",
 124                                 i, src, srcp, dest, destp, sp->state, 
 125                                 format==0?sp->write_seq-sp->rcv_ack_seq:sp->wmem_alloc, 
 126                                 format==0?sp->acked_seq-sp->copied_seq:sp->rmem_alloc,
 127                                 timer_active, timer_expires-jiffies, (unsigned) sp->retransmits,
 128                                 (sp->socket&&SOCK_INODE(sp->socket))?SOCK_INODE(sp->socket)->i_uid:0,
 129                                 timer_active?sp->timeout:0,
 130                                 sp->socket && SOCK_INODE(sp->socket) ?
 131                                 SOCK_INODE(sp->socket)->i_ino : 0);
 132                         if (timer_active1) add_timer(&sp->retransmit_timer);
 133                         if (timer_active2) add_timer(&sp->timer);
 134                         len += sprintf(buffer+len, "%-127s\n", tmpbuf);
 135                         /*
 136                          * All sockets with (port mod SOCK_ARRAY_SIZE) = i
 137                          * are kept in sock_array[i], so we must follow the
 138                          * 'next' link to get them all.
 139                          */
 140                         if(len >= length)
 141                                 break;
 142                         sp = sp->next;
 143                 }
 144                 sti();  /* We only turn interrupts back on for a moment,
 145                            but because the interrupt queues anything built
 146                            up before this will clear before we jump back
 147                            and cli(), so it's not as bad as it looks */
 148                 if(len>= length)
 149                         break;
 150         }
 151         begin = len - (pos - offset);
 152         *start = buffer + begin;
 153         len -= begin;
 154         if(len>length)
 155                 len = length;
 156         return len;
 157 } 
 158 
 159 
 160 int tcp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 161 {
 162         return get__netinfo(&tcp_prot, buffer,0, start, offset, length);
 163 }
 164 
 165 
 166 int udp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 167 {
 168         return get__netinfo(&udp_prot, buffer,1, start, offset, length);
 169 }
 170 
 171 
 172 int raw_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 173 {
 174         return get__netinfo(&raw_prot, buffer,1, start, offset, length);
 175 }
 176 
 177 
 178 /*
 179  *      Report socket allocation statistics [mea@utu.fi]
 180  */
 181 int afinet_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         /* From  net/socket.c  */
 184         extern int socket_get_info(char *, char **, off_t, int);
 185         extern struct proto packet_prot;
 186 
 187         int len  = socket_get_info(buffer,start,offset,length);
 188 
 189         len += sprintf(buffer+len,"SOCK_ARRAY_SIZE=%d\n",SOCK_ARRAY_SIZE);
 190         len += sprintf(buffer+len,"TCP: inuse %d highest %d\n",
 191                        tcp_prot.inuse, tcp_prot.highestinuse);
 192         len += sprintf(buffer+len,"UDP: inuse %d highest %d\n",
 193                        udp_prot.inuse, udp_prot.highestinuse);
 194         len += sprintf(buffer+len,"RAW: inuse %d highest %d\n",
 195                        raw_prot.inuse, raw_prot.highestinuse);
 196         len += sprintf(buffer+len,"PAC: inuse %d highest %d\n",
 197                        packet_prot.inuse, packet_prot.highestinuse);
 198         *start = buffer + offset;
 199         len -= offset;
 200         if (len > length)
 201                 len = length;
 202         return len;
 203 }
 204 
 205 
 206 /* 
 207  *      Called from the PROCfs module. This outputs /proc/net/snmp.
 208  */
 209  
 210 int snmp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212         extern struct tcp_mib tcp_statistics;
 213         extern struct udp_mib udp_statistics;
 214         int len;
 215 /*
 216   extern unsigned long tcp_rx_miss, tcp_rx_hit1,tcp_rx_hit2;
 217 */
 218 
 219         len = sprintf (buffer,
 220                 "Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates\n"
 221                 "Ip: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
 222                     ip_statistics.IpForwarding, ip_statistics.IpDefaultTTL, 
 223                     ip_statistics.IpInReceives, ip_statistics.IpInHdrErrors, 
 224                     ip_statistics.IpInAddrErrors, ip_statistics.IpForwDatagrams, 
 225                     ip_statistics.IpInUnknownProtos, ip_statistics.IpInDiscards, 
 226                     ip_statistics.IpInDelivers, ip_statistics.IpOutRequests, 
 227                     ip_statistics.IpOutDiscards, ip_statistics.IpOutNoRoutes, 
 228                     ip_statistics.IpReasmTimeout, ip_statistics.IpReasmReqds, 
 229                     ip_statistics.IpReasmOKs, ip_statistics.IpReasmFails, 
 230                     ip_statistics.IpFragOKs, ip_statistics.IpFragFails, 
 231                     ip_statistics.IpFragCreates);
 232                                 
 233         len += sprintf (buffer + len,
 234                 "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"
 235                 "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",
 236                     icmp_statistics.IcmpInMsgs, icmp_statistics.IcmpInErrors,
 237                     icmp_statistics.IcmpInDestUnreachs, icmp_statistics.IcmpInTimeExcds,
 238                     icmp_statistics.IcmpInParmProbs, icmp_statistics.IcmpInSrcQuenchs,
 239                     icmp_statistics.IcmpInRedirects, icmp_statistics.IcmpInEchos,
 240                     icmp_statistics.IcmpInEchoReps, icmp_statistics.IcmpInTimestamps,
 241                     icmp_statistics.IcmpInTimestampReps, icmp_statistics.IcmpInAddrMasks,
 242                     icmp_statistics.IcmpInAddrMaskReps, icmp_statistics.IcmpOutMsgs,
 243                     icmp_statistics.IcmpOutErrors, icmp_statistics.IcmpOutDestUnreachs,
 244                     icmp_statistics.IcmpOutTimeExcds, icmp_statistics.IcmpOutParmProbs,
 245                     icmp_statistics.IcmpOutSrcQuenchs, icmp_statistics.IcmpOutRedirects,
 246                     icmp_statistics.IcmpOutEchos, icmp_statistics.IcmpOutEchoReps,
 247                     icmp_statistics.IcmpOutTimestamps, icmp_statistics.IcmpOutTimestampReps,
 248                     icmp_statistics.IcmpOutAddrMasks, icmp_statistics.IcmpOutAddrMaskReps);
 249         
 250         len += sprintf (buffer + len,
 251                 "Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs\n"
 252                 "Tcp: %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu\n",
 253                     tcp_statistics.TcpRtoAlgorithm, tcp_statistics.TcpRtoMin,
 254                     tcp_statistics.TcpRtoMax, tcp_statistics.TcpMaxConn,
 255                     tcp_statistics.TcpActiveOpens, tcp_statistics.TcpPassiveOpens,
 256                     tcp_statistics.TcpAttemptFails, tcp_statistics.TcpEstabResets,
 257                     tcp_statistics.TcpCurrEstab, tcp_statistics.TcpInSegs,
 258                     tcp_statistics.TcpOutSegs, tcp_statistics.TcpRetransSegs);
 259                 
 260         len += sprintf (buffer + len,
 261                 "Udp: InDatagrams NoPorts InErrors OutDatagrams\nUdp: %lu %lu %lu %lu\n",
 262                     udp_statistics.UdpInDatagrams, udp_statistics.UdpNoPorts,
 263                     udp_statistics.UdpInErrors, udp_statistics.UdpOutDatagrams);            
 264 /*      
 265           len += sprintf( buffer + len,
 266                 "TCP fast path RX:  H2: %ul H1: %ul L: %ul\n",
 267                         tcp_rx_hit2,tcp_rx_hit1,tcp_rx_miss);
 268 */
 269         
 270         if (offset >= len)
 271         {
 272                 *start = buffer;
 273                 return 0;
 274         }
 275         *start = buffer + offset;
 276         len -= offset;
 277         if (len > length)
 278                 len = length;
 279         return len;
 280 }

/* [previous][next][first][last][top][bottom][index][help] */