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.28 20/12/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 * Alan Cox : Final clean up. 22 * 23 * This program is free software; you can redistribute it and/or 24 * modify it under the terms of the GNU General Public License 25 * as published by the Free Software Foundation; either version 26 * 2 of the License, or (at your option) any later version. 27 */ 28 #include <asm/system.h>
29 #include <linux/autoconf.h>
30 #include <linux/sched.h>
31 #include <linux/socket.h>
32 #include <linux/net.h>
33 #include <linux/un.h>
34 #include <linux/in.h>
35 #include <linux/param.h>
36 #include "inet.h"
37 #include "devinet.h"
38 #include "ip.h"
39 #include "protocol.h"
40 #include "tcp.h"
41 #include "udp.h"
42 #include "socket/skbuff.h"
43 #include "sockinet.h"
44 #include "raw.h"
45
46 /* 47 * Get__netinfo returns the length of that string. 48 * 49 * KNOWN BUGS 50 * As in get_unix_netinfo, the buffer might be too small. If this 51 * happens, get__netinfo returns only part of the available infos. 52 */ 53 staticintget__netinfo(structproto *pro, char *buffer, intformat)
/* */ 54 { 55 structsock **s_array;
56 structsock *sp;
57 char *pos=buffer;
58 inti;
59 inttimer_active;
60 unsignedlongdest, src;
61 unsignedshortdestp, srcp;
62
63 s_array = pro->sock_array;
64 pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
65 /* 66 * This was very pretty but didn't work when a socket is destroyed at the wrong moment 67 * (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing 68 * with timers we just concede defeat and cli(). 69 */ 70 for(i = 0; i < SOCK_ARRAY_SIZE; i++)
71 { 72 cli();
73 sp = s_array[i];
74 while(sp != NULL)
75 { 76 dest = sp->daddr;
77 src = sp->saddr;
78 destp = sp->dummy_th.dest;
79 srcp = sp->dummy_th.source;
80
81 /* Since we are Little Endian we need to swap the bytes :-( */ 82 destp = ntohs(destp);
83 srcp = ntohs(srcp);
84 timer_active = del_timer(&sp->timer);
85 if (!timer_active)
86 sp->timer.expires = 0;
87 pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
88 i, src, srcp, dest, destp, sp->state,
89 format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
90 format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
91 timer_active, sp->timer.expires, (unsigned) sp->retransmits,
92 SOCK_INODE(sp->socket)->i_uid);
93 if (timer_active)
94 add_timer(&sp->timer);
95 /* Is place in buffer too rare? then abort. */ 96 if (pos > buffer+PAGE_SIZE-80)
97 { 98 printk("oops, too many %s sockets for netinfo.\n",
99 pro->name);
100 return(strlen(buffer));
101 } 102
103 /* 104 * All sockets with (port mod SOCK_ARRAY_SIZE) = i 105 * are kept in sock_array[i], so we must follow the 106 * 'next' link to get them all. 107 */ 108 sp = sp->next;
109 } 110 sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up 111 before this will clear before we jump back and cli, so its not as bad as it looks */ 112 } 113 return(strlen(buffer));
114 } 115
116
117 inttcp_get_info(char *buffer)
/* */ 118 { 119 returnget__netinfo(&tcp_prot, buffer,0);
120 } 121
122
123 intudp_get_info(char *buffer)
/* */ 124 { 125 returnget__netinfo(&udp_prot, buffer,1);
126 } 127
128
129 intraw_get_info(char *buffer)
/* */ 130 { 131 returnget__netinfo(&raw_prot, buffer,1);
132 }