xref: /csrg-svn/usr.sbin/trpt/trpt.c (revision 15252)
16463Swnj #ifndef lint
2*15252Ssam static char sccsid[] = "@(#)trpt.c	4.11 10/16/83";
36463Swnj #endif
46463Swnj 
56463Swnj #include <sys/param.h>
66463Swnj #include <sys/socket.h>
76463Swnj #include <sys/socketvar.h>
86463Swnj #define PRUREQUESTS
96463Swnj #include <sys/protosw.h>
109202Ssam 
116463Swnj #include <net/route.h>
126463Swnj #include <net/if.h>
139202Ssam 
149202Ssam #include <netinet/in.h>
159202Ssam #include <netinet/in_pcb.h>
169202Ssam #include <netinet/in_systm.h>
179202Ssam #include <netinet/ip.h>
189202Ssam #include <netinet/ip_var.h>
199202Ssam #include <netinet/tcp.h>
206463Swnj #define TCPSTATES
219202Ssam #include <netinet/tcp_fsm.h>
229202Ssam #include <netinet/tcp_seq.h>
236463Swnj #define	TCPTIMERS
249202Ssam #include <netinet/tcp_timer.h>
259202Ssam #include <netinet/tcp_var.h>
269202Ssam #include <netinet/tcpip.h>
276463Swnj #define	TANAMES
289202Ssam #include <netinet/tcp_debug.h>
299202Ssam 
30*15252Ssam #include <arpa/inet.h>
31*15252Ssam 
3210272Ssam #include <stdio.h>
336463Swnj #include <errno.h>
346463Swnj #include <nlist.h>
356463Swnj 
366463Swnj n_time	ntime;
376463Swnj int	sflag;
3810425Ssam int	tflag;
3910425Ssam int	jflag;
4010593Ssam int	aflag;
4110425Ssam int	numeric();
426463Swnj struct	nlist nl[] = {
436463Swnj 	{ "_tcp_debug" },
446463Swnj 	{ "_tcp_debx" },
456463Swnj 	0
466463Swnj };
476463Swnj struct	tcp_debug tcp_debug[TCP_NDEBUG];
4810425Ssam caddr_t	tcp_pcbs[TCP_NDEBUG];
496463Swnj int	tcp_debx;
506463Swnj 
516463Swnj main(argc, argv)
526463Swnj 	int argc;
536463Swnj 	char **argv;
546463Swnj {
5510425Ssam 	int i, mask = 0, npcbs = 0;
5610272Ssam 	char *system = "/vmunix", *core = "/dev/kmem";
576463Swnj 
586463Swnj 	argc--, argv++;
596463Swnj again:
6010593Ssam 	if (argc > 0 && !strcmp(*argv, "-a")) {
6110593Ssam 		aflag++, argc--, argv++;
6210593Ssam 		goto again;
6310593Ssam 	}
646463Swnj 	if (argc > 0 && !strcmp(*argv, "-s")) {
656463Swnj 		sflag++, argc--, argv++;
666463Swnj 		goto again;
676463Swnj 	}
6810425Ssam 	if (argc > 0 && !strcmp(*argv, "-t")) {
6910425Ssam 		tflag++, argc--, argv++;
7010425Ssam 		goto again;
7110425Ssam 	}
7210425Ssam 	if (argc > 0 && !strcmp(*argv, "-j")) {
7310425Ssam 		jflag++, argc--, argv++;
7410425Ssam 		goto again;
7510425Ssam 	}
7610272Ssam 	if (argc > 0 && !strcmp(*argv, "-p")) {
7710425Ssam 		argc--, argv++;
7810272Ssam 		if (argc < 1) {
7910272Ssam 			fprintf(stderr, "-p: missing tcpcb address\n");
8010272Ssam 			exit(1);
8110272Ssam 		}
8210425Ssam 		if (npcbs >= TCP_NDEBUG) {
8310425Ssam 			fprintf(stderr, "-p: too many pcb's specified\n");
8410425Ssam 			exit(1);
8510425Ssam 		}
8610425Ssam 		sscanf(*argv, "%x", &tcp_pcbs[npcbs++]);
8710272Ssam 		argc--, argv++;
8810272Ssam 		goto again;
8910272Ssam 	}
9010272Ssam 	if (argc > 0) {
9110272Ssam 		system = *argv;
9210272Ssam 		argc--, argv++;
9310272Ssam 		mask++;
9410272Ssam 	}
9510272Ssam 	if (argc > 0) {
9610272Ssam 		core = *argv;
9710272Ssam 		argc--, argv++;
9810272Ssam 		mask++;
9910272Ssam 	}
10010272Ssam 	(void) nlist(system, nl);
1016463Swnj 	if (nl[0].n_value == 0) {
10210272Ssam 		fprintf(stderr, "trpt: %s: no namelist\n", system);
1036463Swnj 		exit(1);
1046463Swnj 	}
10510272Ssam 	(void) close(0);
10610272Ssam 	if (open(core, 0) < 0) {
10710272Ssam 		fprintf(stderr, "trpt: "); perror(core);
10810272Ssam 		exit(2);
10910272Ssam 	}
11010272Ssam 	if (mask) {
1116463Swnj 		nl[0].n_value &= 0x7fffffff;
1126463Swnj 		nl[1].n_value &= 0x7fffffff;
1136463Swnj 	}
11410272Ssam 	(void) lseek(0, nl[1].n_value, 0);
11510272Ssam 	if (read(0, &tcp_debx, sizeof (tcp_debx)) != sizeof (tcp_debx)) {
11610272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debx");
11710272Ssam 		exit(3);
11810272Ssam 	}
1196463Swnj 	printf("tcp_debx=%d\n", tcp_debx);
12010272Ssam 	(void) lseek(0, nl[0].n_value, 0);
12110272Ssam 	if (read(0, tcp_debug, sizeof (tcp_debug)) != sizeof (tcp_debug)) {
12210272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debug");
12310272Ssam 		exit(3);
12410272Ssam 	}
12510425Ssam 	/*
12610425Ssam 	 * If no control blocks have been specified, figure
12710425Ssam 	 * out how many distinct one we have and summarize
12810425Ssam 	 * them in tcp_pcbs for sorting the trace records
12910425Ssam 	 * below.
13010425Ssam 	 */
13110425Ssam 	if (npcbs == 0) {
13210425Ssam 		for (i = 0; i < TCP_NDEBUG; i++) {
13310425Ssam 			register int j;
13410425Ssam 			register struct tcp_debug *td = &tcp_debug[i];
1358382Ssam 
13610425Ssam 			if (td->td_tcb == 0)
13710425Ssam 				continue;
13810425Ssam 			for (j = 0; j < npcbs; j++)
13910425Ssam 				if (tcp_pcbs[j] == td->td_tcb)
14010425Ssam 					break;
14110425Ssam 			if (j >= npcbs)
14210425Ssam 				tcp_pcbs[npcbs++] = td->td_tcb;
14310425Ssam 		}
14410425Ssam 	}
14510425Ssam 	qsort(tcp_pcbs, npcbs, sizeof (caddr_t), numeric);
14610425Ssam 	if (jflag) {
14710425Ssam 		char *cp = "";
14810425Ssam 
14910425Ssam 		for (i = 0; i < npcbs; i++) {
15010425Ssam 			printf("%s%x", cp, tcp_pcbs[i]);
15110425Ssam 			cp = ", ";
15210425Ssam 		}
15310425Ssam 		if (*cp)
15410425Ssam 			putchar('\n');
15510425Ssam 		exit(0);
15610425Ssam 	}
15710425Ssam 	for (i = 0; i < npcbs; i++) {
15810425Ssam 		printf("\n%x:\n", tcp_pcbs[i]);
15910425Ssam 		dotrace(tcp_pcbs[i]);
16010425Ssam 	}
16110425Ssam 	exit(0);
16210425Ssam }
16310425Ssam 
16410425Ssam dotrace(tcpcb)
16510425Ssam 	register caddr_t tcpcb;
16610425Ssam {
16710425Ssam 	register int i;
16810425Ssam 	register struct tcp_debug *td;
16910425Ssam 
17010425Ssam 	for (i = 0; i < tcp_debx % TCP_NDEBUG; i++) {
17110425Ssam 		td = &tcp_debug[i];
17210272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
17310272Ssam 			continue;
1748382Ssam 		ntime = ntohl(td->td_time);
1756463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1766463Swnj 		    &td->td_ti, td->td_req);
1776463Swnj 	}
17810425Ssam 	for (i = tcp_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
17910425Ssam 		td = &tcp_debug[i];
18010272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
18110272Ssam 			continue;
1828382Ssam 		ntime = ntohl(td->td_time);
1836463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1846463Swnj 		    &td->td_ti, td->td_req);
1856463Swnj 	}
1866463Swnj }
1876463Swnj 
1886463Swnj /*
1896463Swnj  * Tcp debug routines
1906463Swnj  */
1916463Swnj tcp_trace(act, ostate, atp, tp, ti, req)
1926463Swnj 	short act, ostate;
1936463Swnj 	struct tcpcb *atp, *tp;
1946463Swnj 	struct tcpiphdr *ti;
1956463Swnj 	int req;
1966463Swnj {
1976463Swnj 	tcp_seq seq, ack;
1988382Ssam 	int len, flags, win, timer;
1996463Swnj 	char *cp;
2006463Swnj 
2016463Swnj 	ptime(ntime);
20210425Ssam 	printf("%s:%s ", tcpstates[ostate], tanames[act]);
2036463Swnj 	switch (act) {
2046463Swnj 
2056463Swnj 	case TA_INPUT:
2066463Swnj 	case TA_OUTPUT:
20714004Shelge 	case TA_DROP:
20810593Ssam 		if (aflag) {
209*15252Ssam 			printf("(src=%s,%d, ", inet_ntoa(ti->ti_src),
21010593Ssam 				ntohs(ti->ti_sport));
211*15252Ssam 			printf("dst=%s,%d)", inet_ntoa(ti->ti_dst),
21210593Ssam 				ntohs(ti->ti_dport));
21310593Ssam 		}
2146463Swnj 		seq = ti->ti_seq;
2156463Swnj 		ack = ti->ti_ack;
2166463Swnj 		len = ti->ti_len;
2176463Swnj 		win = ti->ti_win;
2186463Swnj 		if (act == TA_OUTPUT) {
2196463Swnj 			seq = ntohl(seq);
2206463Swnj 			ack = ntohl(ack);
2216463Swnj 			len = ntohs(len);
2226463Swnj 			win = ntohs(win);
2236463Swnj 		}
2246463Swnj 		if (act == TA_OUTPUT)
2256463Swnj 			len -= sizeof (struct tcphdr);
2266463Swnj 		if (len)
2276463Swnj 			printf("[%x..%x)", seq, seq+len);
2286463Swnj 		else
2296463Swnj 			printf("%x", seq);
2306463Swnj 		printf("@%x", ack);
2316463Swnj 		if (win)
23214282Shelge 			printf("(win=%x)", win);
2336463Swnj 		flags = ti->ti_flags;
2346463Swnj 		if (flags) {
2356463Swnj 			char *cp = "<";
2366463Swnj #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } }
23710411Ssam 			pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
2386463Swnj 			printf(">");
2396463Swnj 		}
2406463Swnj 		break;
2416463Swnj 
2426463Swnj 	case TA_USER:
2438382Ssam 		timer = req >> 8;
2448382Ssam 		req &= 0xff;
2458382Ssam 		printf("%s", prurequests[req]);
2468382Ssam 		if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
2478382Ssam 			printf("<%s>", tcptimers[timer]);
2486463Swnj 		break;
2496463Swnj 	}
2506463Swnj 	printf(" -> %s", tcpstates[tp->t_state]);
2516463Swnj 	/* print out internal state of tp !?! */
2526463Swnj 	printf("\n");
2536463Swnj 	if (sflag) {
25414000Shelge 		printf("\trcv_nxt %x rcv_wnd %x snd_una %x snd_nxt %x snd_max %x\n",
25510272Ssam 		    tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
25610272Ssam 		    tp->snd_max);
25710272Ssam 		printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %x\n", tp->snd_wl1,
25810272Ssam 		    tp->snd_wl2, tp->snd_wnd);
2596463Swnj 	}
26010425Ssam 	/* print out timers? */
26110425Ssam 	if (tflag) {
26210425Ssam 		char *cp = "\t";
26310425Ssam 		register int i;
26410425Ssam 
26510425Ssam 		for (i = 0; i < TCPT_NTIMERS; i++) {
26610425Ssam 			if (tp->t_timer[i] == 0)
26710425Ssam 				continue;
26810425Ssam 			printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
26910425Ssam 			if (i == TCPT_REXMT)
27010425Ssam 				printf(" (t_rxtshft=%d)", tp->t_rxtshift);
27110425Ssam 			cp = ", ";
27210425Ssam 		}
27310425Ssam 		if (*cp != '\t')
27410425Ssam 			putchar('\n');
27510425Ssam 	}
2766463Swnj }
2776463Swnj 
2786463Swnj ptime(ms)
2796463Swnj 	int ms;
2806463Swnj {
2816463Swnj 
2826463Swnj 	printf("%03d ", (ms/10) % 1000);
2836463Swnj }
28410425Ssam 
28510425Ssam numeric(c1, c2)
28610425Ssam 	caddr_t *c1, *c2;
28710425Ssam {
28810425Ssam 
28910425Ssam 	return (*c1 - *c2);
29010425Ssam }
291