xref: /csrg-svn/usr.sbin/trpt/trpt.c (revision 22014)
1*22014Sdist /*
2*22014Sdist  * Copyright (c) 1983 Regents of the University of California.
3*22014Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22014Sdist  * specifies the terms and conditions for redistribution.
5*22014Sdist  */
6*22014Sdist 
76463Swnj #ifndef lint
8*22014Sdist char copyright[] =
9*22014Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10*22014Sdist  All rights reserved.\n";
11*22014Sdist #endif not lint
126463Swnj 
13*22014Sdist #ifndef lint
14*22014Sdist static char sccsid[] = "@(#)trpt.c	5.1 (Berkeley) 06/04/85";
15*22014Sdist #endif not lint
16*22014Sdist 
176463Swnj #include <sys/param.h>
186463Swnj #include <sys/socket.h>
196463Swnj #include <sys/socketvar.h>
206463Swnj #define PRUREQUESTS
216463Swnj #include <sys/protosw.h>
229202Ssam 
236463Swnj #include <net/route.h>
246463Swnj #include <net/if.h>
259202Ssam 
269202Ssam #include <netinet/in.h>
279202Ssam #include <netinet/in_pcb.h>
289202Ssam #include <netinet/in_systm.h>
299202Ssam #include <netinet/ip.h>
309202Ssam #include <netinet/ip_var.h>
319202Ssam #include <netinet/tcp.h>
326463Swnj #define TCPSTATES
339202Ssam #include <netinet/tcp_fsm.h>
349202Ssam #include <netinet/tcp_seq.h>
356463Swnj #define	TCPTIMERS
369202Ssam #include <netinet/tcp_timer.h>
379202Ssam #include <netinet/tcp_var.h>
389202Ssam #include <netinet/tcpip.h>
396463Swnj #define	TANAMES
409202Ssam #include <netinet/tcp_debug.h>
419202Ssam 
4215252Ssam #include <arpa/inet.h>
4315252Ssam 
4410272Ssam #include <stdio.h>
456463Swnj #include <errno.h>
466463Swnj #include <nlist.h>
476463Swnj 
486463Swnj n_time	ntime;
496463Swnj int	sflag;
5010425Ssam int	tflag;
5110425Ssam int	jflag;
5210593Ssam int	aflag;
5310425Ssam int	numeric();
546463Swnj struct	nlist nl[] = {
556463Swnj 	{ "_tcp_debug" },
566463Swnj 	{ "_tcp_debx" },
576463Swnj 	0
586463Swnj };
596463Swnj struct	tcp_debug tcp_debug[TCP_NDEBUG];
6010425Ssam caddr_t	tcp_pcbs[TCP_NDEBUG];
616463Swnj int	tcp_debx;
626463Swnj 
636463Swnj main(argc, argv)
646463Swnj 	int argc;
656463Swnj 	char **argv;
666463Swnj {
6710425Ssam 	int i, mask = 0, npcbs = 0;
6810272Ssam 	char *system = "/vmunix", *core = "/dev/kmem";
696463Swnj 
706463Swnj 	argc--, argv++;
716463Swnj again:
7210593Ssam 	if (argc > 0 && !strcmp(*argv, "-a")) {
7310593Ssam 		aflag++, argc--, argv++;
7410593Ssam 		goto again;
7510593Ssam 	}
766463Swnj 	if (argc > 0 && !strcmp(*argv, "-s")) {
776463Swnj 		sflag++, argc--, argv++;
786463Swnj 		goto again;
796463Swnj 	}
8010425Ssam 	if (argc > 0 && !strcmp(*argv, "-t")) {
8110425Ssam 		tflag++, argc--, argv++;
8210425Ssam 		goto again;
8310425Ssam 	}
8410425Ssam 	if (argc > 0 && !strcmp(*argv, "-j")) {
8510425Ssam 		jflag++, argc--, argv++;
8610425Ssam 		goto again;
8710425Ssam 	}
8810272Ssam 	if (argc > 0 && !strcmp(*argv, "-p")) {
8910425Ssam 		argc--, argv++;
9010272Ssam 		if (argc < 1) {
9110272Ssam 			fprintf(stderr, "-p: missing tcpcb address\n");
9210272Ssam 			exit(1);
9310272Ssam 		}
9410425Ssam 		if (npcbs >= TCP_NDEBUG) {
9510425Ssam 			fprintf(stderr, "-p: too many pcb's specified\n");
9610425Ssam 			exit(1);
9710425Ssam 		}
9810425Ssam 		sscanf(*argv, "%x", &tcp_pcbs[npcbs++]);
9910272Ssam 		argc--, argv++;
10010272Ssam 		goto again;
10110272Ssam 	}
10210272Ssam 	if (argc > 0) {
10310272Ssam 		system = *argv;
10410272Ssam 		argc--, argv++;
10510272Ssam 		mask++;
10610272Ssam 	}
10710272Ssam 	if (argc > 0) {
10810272Ssam 		core = *argv;
10910272Ssam 		argc--, argv++;
11010272Ssam 		mask++;
11110272Ssam 	}
11210272Ssam 	(void) nlist(system, nl);
1136463Swnj 	if (nl[0].n_value == 0) {
11410272Ssam 		fprintf(stderr, "trpt: %s: no namelist\n", system);
1156463Swnj 		exit(1);
1166463Swnj 	}
11710272Ssam 	(void) close(0);
11810272Ssam 	if (open(core, 0) < 0) {
11910272Ssam 		fprintf(stderr, "trpt: "); perror(core);
12010272Ssam 		exit(2);
12110272Ssam 	}
12210272Ssam 	if (mask) {
1236463Swnj 		nl[0].n_value &= 0x7fffffff;
1246463Swnj 		nl[1].n_value &= 0x7fffffff;
1256463Swnj 	}
12610272Ssam 	(void) lseek(0, nl[1].n_value, 0);
12710272Ssam 	if (read(0, &tcp_debx, sizeof (tcp_debx)) != sizeof (tcp_debx)) {
12810272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debx");
12910272Ssam 		exit(3);
13010272Ssam 	}
13110272Ssam 	(void) lseek(0, nl[0].n_value, 0);
13210272Ssam 	if (read(0, tcp_debug, sizeof (tcp_debug)) != sizeof (tcp_debug)) {
13310272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debug");
13410272Ssam 		exit(3);
13510272Ssam 	}
13610425Ssam 	/*
13710425Ssam 	 * If no control blocks have been specified, figure
13810425Ssam 	 * out how many distinct one we have and summarize
13910425Ssam 	 * them in tcp_pcbs for sorting the trace records
14010425Ssam 	 * below.
14110425Ssam 	 */
14210425Ssam 	if (npcbs == 0) {
14310425Ssam 		for (i = 0; i < TCP_NDEBUG; i++) {
14410425Ssam 			register int j;
14510425Ssam 			register struct tcp_debug *td = &tcp_debug[i];
1468382Ssam 
14710425Ssam 			if (td->td_tcb == 0)
14810425Ssam 				continue;
14910425Ssam 			for (j = 0; j < npcbs; j++)
15010425Ssam 				if (tcp_pcbs[j] == td->td_tcb)
15110425Ssam 					break;
15210425Ssam 			if (j >= npcbs)
15310425Ssam 				tcp_pcbs[npcbs++] = td->td_tcb;
15410425Ssam 		}
15510425Ssam 	}
15610425Ssam 	qsort(tcp_pcbs, npcbs, sizeof (caddr_t), numeric);
15710425Ssam 	if (jflag) {
15810425Ssam 		char *cp = "";
15910425Ssam 
16010425Ssam 		for (i = 0; i < npcbs; i++) {
16110425Ssam 			printf("%s%x", cp, tcp_pcbs[i]);
16210425Ssam 			cp = ", ";
16310425Ssam 		}
16410425Ssam 		if (*cp)
16510425Ssam 			putchar('\n');
16610425Ssam 		exit(0);
16710425Ssam 	}
16810425Ssam 	for (i = 0; i < npcbs; i++) {
16910425Ssam 		printf("\n%x:\n", tcp_pcbs[i]);
17010425Ssam 		dotrace(tcp_pcbs[i]);
17110425Ssam 	}
17210425Ssam 	exit(0);
17310425Ssam }
17410425Ssam 
17510425Ssam dotrace(tcpcb)
17610425Ssam 	register caddr_t tcpcb;
17710425Ssam {
17810425Ssam 	register int i;
17910425Ssam 	register struct tcp_debug *td;
18010425Ssam 
18121814Skarels 	for (i = tcp_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
18210425Ssam 		td = &tcp_debug[i];
18310272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
18410272Ssam 			continue;
1858382Ssam 		ntime = ntohl(td->td_time);
1866463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1876463Swnj 		    &td->td_ti, td->td_req);
1886463Swnj 	}
18921814Skarels 	for (i = 0; i < tcp_debx % TCP_NDEBUG; i++) {
19010425Ssam 		td = &tcp_debug[i];
19110272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
19210272Ssam 			continue;
1938382Ssam 		ntime = ntohl(td->td_time);
1946463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1956463Swnj 		    &td->td_ti, td->td_req);
1966463Swnj 	}
1976463Swnj }
1986463Swnj 
1996463Swnj /*
2006463Swnj  * Tcp debug routines
2016463Swnj  */
2026463Swnj tcp_trace(act, ostate, atp, tp, ti, req)
2036463Swnj 	short act, ostate;
2046463Swnj 	struct tcpcb *atp, *tp;
2056463Swnj 	struct tcpiphdr *ti;
2066463Swnj 	int req;
2076463Swnj {
2086463Swnj 	tcp_seq seq, ack;
2098382Ssam 	int len, flags, win, timer;
2106463Swnj 	char *cp;
2116463Swnj 
2126463Swnj 	ptime(ntime);
21310425Ssam 	printf("%s:%s ", tcpstates[ostate], tanames[act]);
2146463Swnj 	switch (act) {
2156463Swnj 
2166463Swnj 	case TA_INPUT:
2176463Swnj 	case TA_OUTPUT:
21814004Shelge 	case TA_DROP:
21910593Ssam 		if (aflag) {
22015252Ssam 			printf("(src=%s,%d, ", inet_ntoa(ti->ti_src),
22110593Ssam 				ntohs(ti->ti_sport));
22215252Ssam 			printf("dst=%s,%d)", inet_ntoa(ti->ti_dst),
22310593Ssam 				ntohs(ti->ti_dport));
22410593Ssam 		}
2256463Swnj 		seq = ti->ti_seq;
2266463Swnj 		ack = ti->ti_ack;
2276463Swnj 		len = ti->ti_len;
2286463Swnj 		win = ti->ti_win;
2296463Swnj 		if (act == TA_OUTPUT) {
2306463Swnj 			seq = ntohl(seq);
2316463Swnj 			ack = ntohl(ack);
2326463Swnj 			len = ntohs(len);
2336463Swnj 			win = ntohs(win);
2346463Swnj 		}
2356463Swnj 		if (act == TA_OUTPUT)
2366463Swnj 			len -= sizeof (struct tcphdr);
2376463Swnj 		if (len)
2386463Swnj 			printf("[%x..%x)", seq, seq+len);
2396463Swnj 		else
2406463Swnj 			printf("%x", seq);
2416463Swnj 		printf("@%x", ack);
2426463Swnj 		if (win)
24314282Shelge 			printf("(win=%x)", win);
2446463Swnj 		flags = ti->ti_flags;
2456463Swnj 		if (flags) {
2466463Swnj 			char *cp = "<";
2476463Swnj #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } }
24810411Ssam 			pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
2496463Swnj 			printf(">");
2506463Swnj 		}
2516463Swnj 		break;
2526463Swnj 
2536463Swnj 	case TA_USER:
2548382Ssam 		timer = req >> 8;
2558382Ssam 		req &= 0xff;
2568382Ssam 		printf("%s", prurequests[req]);
2578382Ssam 		if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
2588382Ssam 			printf("<%s>", tcptimers[timer]);
2596463Swnj 		break;
2606463Swnj 	}
2616463Swnj 	printf(" -> %s", tcpstates[tp->t_state]);
2626463Swnj 	/* print out internal state of tp !?! */
2636463Swnj 	printf("\n");
2646463Swnj 	if (sflag) {
26514000Shelge 		printf("\trcv_nxt %x rcv_wnd %x snd_una %x snd_nxt %x snd_max %x\n",
26610272Ssam 		    tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
26710272Ssam 		    tp->snd_max);
26810272Ssam 		printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %x\n", tp->snd_wl1,
26910272Ssam 		    tp->snd_wl2, tp->snd_wnd);
2706463Swnj 	}
27110425Ssam 	/* print out timers? */
27210425Ssam 	if (tflag) {
27310425Ssam 		char *cp = "\t";
27410425Ssam 		register int i;
27510425Ssam 
27610425Ssam 		for (i = 0; i < TCPT_NTIMERS; i++) {
27710425Ssam 			if (tp->t_timer[i] == 0)
27810425Ssam 				continue;
27910425Ssam 			printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
28010425Ssam 			if (i == TCPT_REXMT)
28110425Ssam 				printf(" (t_rxtshft=%d)", tp->t_rxtshift);
28210425Ssam 			cp = ", ";
28310425Ssam 		}
28410425Ssam 		if (*cp != '\t')
28510425Ssam 			putchar('\n');
28610425Ssam 	}
2876463Swnj }
2886463Swnj 
2896463Swnj ptime(ms)
2906463Swnj 	int ms;
2916463Swnj {
2926463Swnj 
2936463Swnj 	printf("%03d ", (ms/10) % 1000);
2946463Swnj }
29510425Ssam 
29610425Ssam numeric(c1, c2)
29710425Ssam 	caddr_t *c1, *c2;
29810425Ssam {
29910425Ssam 
30010425Ssam 	return (*c1 - *c2);
30110425Ssam }
302