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 * 16 * Fixes: 17 * Alan Cox : UDP sockets show the rxqueue/txqueue 18 * using hint flag for the netinfo. 19 * Pauline Middelink : Pidentd support 20 * Alan Cox : Make /proc safer. 21 * 22 * To Do: 23 * Put the creating userid in the proc/net/... files. This will 24 * allow us to write an RFC931 daemon for Linux 25 * 26 * This program is free software; you can redistribute it and/or 27 * modify it under the terms of the GNU General Public License 28 * as published by the Free Software Foundation; either version 29 * 2 of the License, or (at your option) any later version. 30 */ 31 #include <asm/system.h>
32 #include <linux/autoconf.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 "ip.h"
42 #include "protocol.h"
43 #include "tcp.h"
44 #include "udp.h"
45 #include <linux/skbuff.h>
46 #include "sock.h"
47 #include "raw.h"
48
49 /* 50 * Get__netinfo returns the length of that string. 51 * 52 * KNOWN BUGS 53 * As in get_unix_netinfo, the buffer might be too small. If this 54 * happens, get__netinfo returns only part of the available infos. 55 */ 56 staticint 57 get__netinfo(structproto *pro, char *buffer, intformat, char **start, off_toffset, intlength)
/* */ 58 { 59 structsock **s_array;
60 structsock *sp;
61 inti;
62 inttimer_active;
63 unsignedlongdest, src;
64 unsignedshortdestp, srcp;
65 intlen=0;
66 off_tpos=0;
67 off_tbegin=0;
68
69
70 s_array = pro->sock_array;
71 len+=sprintf(buffer, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
72 /* 73 * This was very pretty but didn't work when a socket is destroyed at the wrong moment 74 * (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing 75 * with timers we just concede defeat and cli(). 76 */ 77 for(i = 0; i < SOCK_ARRAY_SIZE; i++) { 78 cli();
79 sp = s_array[i];
80 while(sp != NULL) { 81 dest = sp->daddr;
82 src = sp->saddr;
83 destp = sp->dummy_th.dest;
84 srcp = sp->dummy_th.source;
85
86 /* Since we are Little Endian we need to swap the bytes :-( */ 87 destp = ntohs(destp);
88 srcp = ntohs(srcp);
89 timer_active = del_timer(&sp->timer);
90 if (!timer_active)
91 sp->timer.expires = 0;
92 len+=sprintf(buffer+len, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
93 i, src, srcp, dest, destp, sp->state,
94 format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc,
95 format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
96 timer_active, sp->timer.expires, (unsigned) sp->retransmits,
97 SOCK_INODE(sp->socket)->i_uid);
98 if (timer_active)
99 add_timer(&sp->timer);
100 /* 101 * All sockets with (port mod SOCK_ARRAY_SIZE) = i 102 * are kept in sock_array[i], so we must follow the 103 * 'next' link to get them all. 104 */ 105 sp = sp->next;
106 pos=begin+len;
107 if(pos<offset)
108 { 109 len=0;
110 begin=pos;
111 } 112 if(pos>offset+length)
113 break;
114 } 115 sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up 116 before this will clear before we jump back and cli, so its not as bad as it looks */ 117 if(pos>offset+length)
118 break;
119 } 120 *start=buffer+(offset-begin);
121 len-=(offset-begin);
122 if(len>length)
123 len=length;
124 returnlen;
125 } 126
127
128 inttcp_get_info(char *buffer, char **start, off_toffset, intlength)
/* */ 129 { 130 returnget__netinfo(&tcp_prot, buffer,0, start, offset, length);
131 } 132
133
134 intudp_get_info(char *buffer, char **start, off_toffset, intlength)
/* */ 135 { 136 returnget__netinfo(&udp_prot, buffer,1, start, offset, length);
137 } 138
139
140 intraw_get_info(char *buffer, char **start, off_toffset, intlength)
/* */ 141 { 142 returnget__netinfo(&raw_prot, buffer,1, start, offset, length);
143 }