1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * INET		An implementation of the TCP/IP protocol suite for the LINUX
 *		operating system.  INET is implemented using the  BSD Socket
 *		interface as the means of communication with the user level.
 *
 *		This file implements the various access functions for the
 *		PROC file system.  It is mainly used for debugging and
 *		statistics.
 *
 * Version:	@(#)proc.c	1.0.5	05/27/93
 *
 * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
 *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
 *		Fred Baumgarten, <dc6iq@insu1.etec.uni-karlsruhe.de>
 *
 * Fixes:
 *		Alan Cox	:	UDP sockets show the rxqueue/txqueue
 *					using hint flag for the netinfo.
 *	Pauline Middelink	:	Pidentd support
 *		Alan Cox	:	Make /proc safer.
 *
 * To Do:
 *		Put the creating userid in the proc/net/... files. This will
 *		allow us to write an RFC931 daemon for Linux
 *
 *		This program is free software; you can redistribute it and/or
 *		modify it under the terms of the GNU General Public License
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 */
#include <asm/system.h>
#include <linux/autoconf.h>
#include <linux/sched.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/un.h>
#include <linux/in.h>
#include <linux/param.h>
#include "inet.h"
#include "dev.h"
#include "ip.h"
#include "protocol.h"
#include "tcp.h"
#include "udp.h"
#include "skbuff.h"
#include "sock.h"
#include "raw.h"

/*
 * Get__netinfo returns the length of that string.
 *
 * KNOWN BUGS
 *  As in get_unix_netinfo, the buffer might be too small. If this
 *  happens, get__netinfo returns only part of the available infos.
 */
static int
get__netinfo(struct proto *pro, char *buffer, int format)
{
  struct sock **s_array;
  struct sock *sp;
  char *pos=buffer;
  int i;
  int timer_active;
  unsigned long  dest, src;
  unsigned short destp, srcp;

  s_array = pro->sock_array;
  pos+=sprintf(pos, "sl  local_address rem_address   st tx_queue rx_queue tr tm->when uid\n");
/*
 *	This was very pretty but didn't work when a socket is destroyed at the wrong moment
 *	(eg a syn recv socket getting a reset), or a memory timer destroy. Instead of playing
 *	with timers we just concede defeat and cli().
 */
  for(i = 0; i < SOCK_ARRAY_SIZE; i++) {
  	cli();
	sp = s_array[i];
	while(sp != NULL) {
		dest  = sp->daddr;
		src   = sp->saddr;
		destp = sp->dummy_th.dest;
		srcp  = sp->dummy_th.source;

		/* Since we are Little Endian we need to swap the bytes :-( */
		destp = ntohs(destp);
		srcp  = ntohs(srcp);
		timer_active = del_timer(&sp->timer);
		if (!timer_active)
			sp->timer.expires = 0;
		pos+=sprintf(pos, "%2d: %08lX:%04X %08lX:%04X %02X %08lX:%08lX %02X:%08lX %08X %d\n",
			i, src, srcp, dest, destp, sp->state, 
			format==0?sp->write_seq-sp->rcv_ack_seq:sp->rmem_alloc, 
			format==0?sp->acked_seq-sp->copied_seq:sp->wmem_alloc,
			timer_active, sp->timer.expires, (unsigned) sp->retransmits,
			SOCK_INODE(sp->socket)->i_uid);
		if (timer_active)
			add_timer(&sp->timer);
		/* Is place in buffer too rare? then abort. */
		if (pos > buffer+PAGE_SIZE-80) {
			printk("oops, too many %s sockets for netinfo.\n",
					pro->name);
			return(strlen(buffer));
		}

		/*
		 * All sockets with (port mod SOCK_ARRAY_SIZE) = i
		 * are kept in sock_array[i], so we must follow the
		 * 'next' link to get them all.
		 */
		sp = sp->next;
	}
	sti();	/* We only turn interrupts back on for a moment, but because the interrupt queues anything built up
		   before this will clear before we jump back and cli, so its not as bad as it looks */
  }
  return(strlen(buffer));
} 


int tcp_get_info(char *buffer)
{
  return get__netinfo(&tcp_prot, buffer,0);
}


int udp_get_info(char *buffer)
{
  return get__netinfo(&udp_prot, buffer,1);
}


int raw_get_info(char *buffer)
{
  return get__netinfo(&raw_prot, buffer,1);
}
鱼站在海里脚会痛吗