340 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			340 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
tcpstat.c
 | 
						|
 | 
						|
Created:	June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
 | 
						|
*/
 | 
						|
 | 
						|
#define _MINIX_SOURCE
 | 
						|
#define _POSIX_C_SOURCE 2
 | 
						|
 | 
						|
#include <inet/inet.h>
 | 
						|
#undef printf
 | 
						|
 | 
						|
#include <fcntl.h>
 | 
						|
#include <stdio.h>
 | 
						|
#include <time.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <sys/svrctl.h>
 | 
						|
#ifndef __minix_vmd
 | 
						|
#include <sys/times.h>
 | 
						|
#endif
 | 
						|
#include <net/netlib.h>
 | 
						|
#include <net/gen/inet.h>
 | 
						|
#include <net/gen/netdb.h>
 | 
						|
#include <net/gen/socket.h>
 | 
						|
#include <minix/queryparam.h>
 | 
						|
#include <minix/com.h>
 | 
						|
#include <minix/sysinfo.h>
 | 
						|
 | 
						|
#include <inet/generic/buf.h>
 | 
						|
#include <inet/generic/clock.h>
 | 
						|
#include <inet/generic/event.h>
 | 
						|
#include <inet/generic/type.h>
 | 
						|
#include <inet/generic/tcp.h>
 | 
						|
#include <inet/generic/tcp_int.h>
 | 
						|
 | 
						|
u32_t system_hz;
 | 
						|
char *prog_name;
 | 
						|
tcp_conn_t tcp_conn_table[TCP_CONN_NR];
 | 
						|
char values[2 * sizeof(tcp_conn_table) + 1];
 | 
						|
int inclListen, numerical, verbose;
 | 
						|
 | 
						|
void print_conn(int i, clock_t now);
 | 
						|
void usage(void);
 | 
						|
 | 
						|
int main(int argc, char*argv[])
 | 
						|
{
 | 
						|
	char *ipstat_device;
 | 
						|
	int fd, i, r;
 | 
						|
	char *query, *pval;
 | 
						|
	size_t len;
 | 
						|
	struct timeval uptime;
 | 
						|
	clock_t now;
 | 
						|
	int fl;
 | 
						|
	int a_flag, n_flag, v_flag;
 | 
						|
 | 
						|
	getsysinfo_up(PM_PROC_NR, SIU_SYSTEMHZ, sizeof(system_hz), &system_hz);
 | 
						|
 | 
						|
	(prog_name=strrchr(argv[0], '/')) ? prog_name++ : (prog_name=argv[0]);
 | 
						|
 | 
						|
	a_flag= 0;
 | 
						|
	n_flag= 0;
 | 
						|
	v_flag= 0;
 | 
						|
	while ((fl= getopt(argc, argv, "?anv")) != -1)
 | 
						|
	{
 | 
						|
		switch(fl)
 | 
						|
		{
 | 
						|
		case '?':
 | 
						|
			usage();
 | 
						|
		case 'a':
 | 
						|
			a_flag= 1;
 | 
						|
			break;
 | 
						|
		case 'n':
 | 
						|
			n_flag= 1;
 | 
						|
			break;
 | 
						|
		case 'v':
 | 
						|
			v_flag= 1;
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			fprintf(stderr, "%s: getopt failed: '%c'\n", 
 | 
						|
				prog_name, fl);
 | 
						|
			exit(1);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	inclListen= !!a_flag;
 | 
						|
	numerical= !!n_flag;
 | 
						|
	verbose= !!v_flag;
 | 
						|
 | 
						|
	ipstat_device= IPSTAT_DEVICE;
 | 
						|
	if ((fd= open(ipstat_device, O_RDWR)) == -1)
 | 
						|
	{
 | 
						|
		fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
 | 
						|
			ipstat_device, strerror(errno));
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
 | 
						|
	query= "tcp_conn_table";
 | 
						|
	len= strlen(query);
 | 
						|
	r= write(fd, query, len);
 | 
						|
	if (r != len)
 | 
						|
	{
 | 
						|
		fprintf(stderr, "%s: write to %s failed: %s\n",
 | 
						|
			prog_name, ipstat_device, r < 0 ? strerror(errno) :
 | 
						|
			"short write");
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	r= read(fd, values, sizeof(values));
 | 
						|
	if (r == -1)
 | 
						|
	{
 | 
						|
		fprintf(stderr, "%s: read from %s failed: %s\n", prog_name,
 | 
						|
			ipstat_device, strerror(errno));
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	pval= values;
 | 
						|
	if (paramvalue(&pval, tcp_conn_table, sizeof(tcp_conn_table)) !=
 | 
						|
		sizeof(tcp_conn_table))
 | 
						|
	{
 | 
						|
		fprintf(stderr,
 | 
						|
			"%s: unable to decode the results from queryparam\n",
 | 
						|
			prog_name);
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef __minix_vmd
 | 
						|
	/* Get the uptime in clock ticks. */
 | 
						|
	if (sysutime(UTIME_UPTIME, &uptime) == -1)
 | 
						|
	{
 | 
						|
		fprintf(stderr, "%s: sysutime failed: %s\n", prog_name,
 | 
						|
			strerror(errno));
 | 
						|
		exit(1);
 | 
						|
	}
 | 
						|
	now= uptime.tv_sec * HZ + (uptime.tv_usec*HZ/1000000);
 | 
						|
#else	/* Minix 3 */
 | 
						|
	now= times(NULL);
 | 
						|
#endif
 | 
						|
 | 
						|
	for (i= 0; i<TCP_CONN_NR; i++)
 | 
						|
		print_conn(i, now);
 | 
						|
	exit(0);
 | 
						|
}
 | 
						|
 | 
						|
void print_conn(int i, clock_t now)
 | 
						|
{
 | 
						|
	tcp_conn_t *tcp_conn;
 | 
						|
	char *addr_str;
 | 
						|
	struct hostent *hostent;
 | 
						|
	struct servent *servent;
 | 
						|
	ipaddr_t a1, a2;
 | 
						|
	tcpport_t p1, p2;
 | 
						|
	unsigned flags;
 | 
						|
	int no_verbose;
 | 
						|
	clock_t rtt, artt, drtt;
 | 
						|
 | 
						|
	tcp_conn= &tcp_conn_table[i];
 | 
						|
	if (!(tcp_conn->tc_flags & TCF_INUSE))
 | 
						|
		return;
 | 
						|
	if (tcp_conn->tc_state == TCS_LISTEN && !inclListen)
 | 
						|
		return;
 | 
						|
	if (tcp_conn->tc_state == TCS_CLOSED && tcp_conn->tc_fd == NULL &&
 | 
						|
		tcp_conn->tc_senddis < now)
 | 
						|
	{
 | 
						|
		return;
 | 
						|
	}
 | 
						|
	
 | 
						|
	printf("%3d", i);
 | 
						|
 | 
						|
	a1= tcp_conn->tc_locaddr;
 | 
						|
	p1= tcp_conn->tc_locport;
 | 
						|
	a2= tcp_conn->tc_remaddr;
 | 
						|
	p2= tcp_conn->tc_remport;
 | 
						|
 | 
						|
	if (a1 == 0)
 | 
						|
		addr_str= "*";
 | 
						|
	else if (!numerical &&
 | 
						|
		(hostent= gethostbyaddr((char *)&a1,
 | 
						|
		sizeof(a1), AF_INET)) != NULL)
 | 
						|
	{
 | 
						|
		addr_str= hostent->h_name;
 | 
						|
	}
 | 
						|
	else
 | 
						|
		addr_str= inet_ntoa(a1);
 | 
						|
	printf(" %s:", addr_str);
 | 
						|
 | 
						|
	if (p1 == 0)
 | 
						|
		printf("*");
 | 
						|
	else if ((servent= getservbyport(p1, "tcp")) != NULL)
 | 
						|
	{
 | 
						|
		printf("%s", servent->s_name);
 | 
						|
	}
 | 
						|
	else
 | 
						|
		printf("%u", ntohs(p1));
 | 
						|
 | 
						|
	if (tcp_conn->tc_orglisten)
 | 
						|
		printf(" <- ");
 | 
						|
	else
 | 
						|
		printf(" -> ");
 | 
						|
 | 
						|
	if (a2 == 0)
 | 
						|
		addr_str= "*";
 | 
						|
	else if (!numerical &&
 | 
						|
		(hostent= gethostbyaddr((char *)&a2,
 | 
						|
		sizeof(a2), AF_INET)) != NULL)
 | 
						|
	{
 | 
						|
		addr_str= hostent->h_name;
 | 
						|
	}
 | 
						|
	else
 | 
						|
		addr_str= inet_ntoa(a2);
 | 
						|
	printf("%s:", addr_str);
 | 
						|
 | 
						|
	if (p2 == 0)
 | 
						|
		printf("*");
 | 
						|
	else if ((servent= getservbyport(p2, "tcp")) !=
 | 
						|
		NULL)
 | 
						|
	{
 | 
						|
		printf("%s", servent->s_name);
 | 
						|
	}
 | 
						|
	else
 | 
						|
		printf("%u", ntohs(p2));
 | 
						|
 | 
						|
	printf(" ");
 | 
						|
	no_verbose= 0;
 | 
						|
	switch(tcp_conn->tc_state)
 | 
						|
	{
 | 
						|
	case TCS_CLOSED:	printf("CLOSED");
 | 
						|
				if (tcp_conn->tc_senddis >= now)
 | 
						|
				{
 | 
						|
					printf("(time wait %ld s)",
 | 
						|
					(tcp_conn->tc_senddis-now)/system_hz);
 | 
						|
				}
 | 
						|
				no_verbose= 1;
 | 
						|
				break;
 | 
						|
	case TCS_LISTEN:	printf("LISTEN"); no_verbose= 1; break;
 | 
						|
	case TCS_SYN_RECEIVED:	printf("SYN_RECEIVED"); break;
 | 
						|
	case TCS_SYN_SENT:	printf("SYN_SENT"); break;
 | 
						|
	case TCS_ESTABLISHED:	printf("ESTABLISHED"); break;
 | 
						|
	case TCS_CLOSING:	printf("CLOSING"); break;
 | 
						|
	default:		printf("state(%d)", tcp_conn->tc_state);
 | 
						|
				break;
 | 
						|
	}
 | 
						|
 | 
						|
	if (tcp_conn->tc_flags & TCF_FIN_RECV)
 | 
						|
		printf(" F<");
 | 
						|
	if (tcp_conn->tc_flags & TCF_FIN_SENT)
 | 
						|
	{
 | 
						|
		printf(" F>");
 | 
						|
		if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
 | 
						|
			printf("+");
 | 
						|
	}
 | 
						|
	if (tcp_conn->tc_state != TCS_CLOSED &&
 | 
						|
		tcp_conn->tc_state != TCS_LISTEN)
 | 
						|
	{
 | 
						|
		printf("\n\t");
 | 
						|
		printf("RQ: %lu, SQ: %lu, RWnd: %u, SWnd: %lu, SWThresh: %lu",
 | 
						|
			tcp_conn->tc_RCV_NXT - tcp_conn->tc_RCV_LO,
 | 
						|
			tcp_conn->tc_SND_NXT - tcp_conn->tc_SND_UNA,
 | 
						|
			tcp_conn->tc_rcv_wnd,
 | 
						|
			tcp_conn->tc_snd_cwnd - tcp_conn->tc_SND_UNA,
 | 
						|
			tcp_conn->tc_snd_cthresh);
 | 
						|
	}
 | 
						|
 | 
						|
	printf("\n");
 | 
						|
 | 
						|
	if (!verbose || no_verbose)
 | 
						|
		return;
 | 
						|
	rtt= tcp_conn->tc_rtt;
 | 
						|
	artt= tcp_conn->tc_artt;
 | 
						|
	drtt= tcp_conn->tc_drtt;
 | 
						|
	printf("\tmss %u, mtu %u%s, rtt %.3f (%.3f+%d*%.3f) s\n",
 | 
						|
		tcp_conn->tc_max_mtu-IP_TCP_MIN_HDR_SIZE,
 | 
						|
		tcp_conn->tc_mtu,
 | 
						|
		(tcp_conn->tc_flags & TCF_PMTU) ? "" : " (no PMTU)",
 | 
						|
		rtt/(system_hz+0.0),
 | 
						|
		artt/(system_hz+0.0)/TCP_RTT_SCALE, TCP_DRTT_MULT,
 | 
						|
		drtt/(system_hz+0.0)/TCP_RTT_SCALE);
 | 
						|
	flags= tcp_conn->tc_flags;
 | 
						|
	printf("\tflags:");
 | 
						|
	if (!flags)
 | 
						|
		printf(" TCF_EMPTY");
 | 
						|
	if (flags & TCF_INUSE)
 | 
						|
		flags &= ~TCF_INUSE;
 | 
						|
	if (flags & TCF_FIN_RECV)
 | 
						|
	{
 | 
						|
		printf(" TCF_FIN_RECV");
 | 
						|
		flags &= ~TCF_FIN_RECV;
 | 
						|
	}
 | 
						|
	if (flags & TCF_RCV_PUSH)
 | 
						|
	{
 | 
						|
		printf(" TCF_RCV_PUSH");
 | 
						|
		flags &= ~TCF_RCV_PUSH;
 | 
						|
	}
 | 
						|
	if (flags & TCF_MORE2WRITE)
 | 
						|
	{
 | 
						|
		printf(" TCF_MORE2WRITE");
 | 
						|
		flags &= ~TCF_MORE2WRITE;
 | 
						|
	}
 | 
						|
	if (flags & TCF_SEND_ACK)
 | 
						|
	{
 | 
						|
		printf(" TCF_SEND_ACK");
 | 
						|
		flags &= ~TCF_SEND_ACK;
 | 
						|
	}
 | 
						|
	if (flags & TCF_FIN_SENT)
 | 
						|
	{
 | 
						|
		printf(" TCF_FIN_SENT");
 | 
						|
		flags &= ~TCF_FIN_SENT;
 | 
						|
	}
 | 
						|
	if (flags & TCF_BSD_URG)
 | 
						|
	{
 | 
						|
		printf(" TCF_BSD_URG");
 | 
						|
		flags &= ~TCF_BSD_URG;
 | 
						|
	}
 | 
						|
	if (flags & TCF_NO_PUSH)
 | 
						|
	{
 | 
						|
		printf(" TCF_NO_PUSH");
 | 
						|
		flags &= ~TCF_NO_PUSH;
 | 
						|
	}
 | 
						|
	if (flags & TCF_PUSH_NOW)
 | 
						|
	{
 | 
						|
		printf(" TCF_PUSH_NOW");
 | 
						|
		flags &= ~TCF_PUSH_NOW;
 | 
						|
	}
 | 
						|
	if (flags & TCF_PMTU)
 | 
						|
		flags &= ~TCF_PMTU;
 | 
						|
	if (flags)
 | 
						|
		printf(" 0x%x", flags);
 | 
						|
	printf("\n");
 | 
						|
	printf("\ttimer: ref %d, time %f, active %d\n",
 | 
						|
		tcp_conn->tc_transmit_timer.tim_ref,
 | 
						|
		(0.0+tcp_conn->tc_transmit_timer.tim_time-now)/system_hz,
 | 
						|
		tcp_conn->tc_transmit_timer.tim_active);
 | 
						|
}
 | 
						|
 | 
						|
void usage(void)
 | 
						|
{
 | 
						|
	fprintf(stderr, "Usage: %s [-anv]\n", prog_name);
 | 
						|
	exit(1);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * $PchId: tcpstat.c,v 1.8 2005/01/30 01:04:38 philip Exp $
 | 
						|
 */
 |