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 "inet.h"
40 #include "dev.h"
41 #include "ip.h"
42 #include "protocol.h"
43 #include "tcp.h"
44 #include "udp.h"
45 #include "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 static int
57 get__netinfo(struct proto *pro, char *buffer, int format)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
58 {
59 struct sock **s_array;
60 struct sock *sp;
61 char *pos=buffer;
62 int i;
63 int timer_active;
64 unsigned long dest, src;
65 unsigned short destp, srcp;
66
67 s_array = pro->sock_array;
68 pos+=sprintf(pos, "sl local_address rem_address st tx_queue rx_queue tr tm->when uid\n");
69 /*
70 * This was very pretty but didn't work when a socket is destroyed at the wrong moment
71 * (eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
72 * with timers we just concede defeat and cli().
73 */
74 for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
75 cli();
76 sp = s_array[i];
77 while(sp != NULL) {
78 dest = sp->daddr;
79 src = sp->saddr;
80 destp = sp->dummy_th.dest;
81 srcp = sp->dummy_th.source;
82
83 /* Since we are Little Endian we need to swap the bytes :-( */
84 destp = ntohs(destp);
85 srcp = ntohs(srcp);
86 timer_active = del_timer(&sp->timer);
87 if (!timer_active)
88 sp->timer.expires = 0;
89 pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
90 i, src, srcp, dest, destp, sp->state,
91 format==0?sp->send_seq-sp->rcv_ack_seq:sp->rmem_alloc,
92 format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
93 timer_active, sp->timer.expires, (unsigned) sp->retransmits,
94 SOCK_INODE(sp->socket)->i_uid);
95 if (timer_active)
96 add_timer(&sp->timer);
97 /* Is place in buffer too rare? then abort. */
98 if (pos > buffer+PAGE_SIZE-80) {
99 printk("oops, too many %s sockets for netinfo.\n",
100 pro->name);
101 return(strlen(buffer));
102 }
103
104 /*
105 * All sockets with (port mod SOCK_ARRAY_SIZE) = i
106 * are kept in sock_array[i], so we must follow the
107 * 'next' link to get them all.
108 */
109 sp = sp->next;
110 }
111 sti(); /* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
112 before this will clear before we jump back and cli, so its not as bad as it looks */
113 }
114 return(strlen(buffer));
115 }
116
117
118 int tcp_get_info(char *buffer)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
119 {
120 return get__netinfo(&tcp_prot, buffer,0);
121 }
122
123
124 int udp_get_info(char *buffer)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
125 {
126 return get__netinfo(&udp_prot, buffer,1);
127 }
128
129
130 int raw_get_info(char *buffer)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
131 {
132 return get__netinfo(&raw_prot, buffer,1);
133 }