xref: /csrg-svn/usr.sbin/trpt/trpt.c (revision 10593)
16463Swnj #ifndef lint
2*10593Ssam static char sccsid[] = "@(#)trpt.c	4.7 01/22/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 
3010272Ssam #include <stdio.h>
316463Swnj #include <errno.h>
326463Swnj #include <nlist.h>
336463Swnj 
346463Swnj n_time	ntime;
356463Swnj int	sflag;
3610425Ssam int	tflag;
3710425Ssam int	jflag;
38*10593Ssam int	aflag;
3910425Ssam int	numeric();
406463Swnj struct	nlist nl[] = {
416463Swnj 	{ "_tcp_debug" },
426463Swnj 	{ "_tcp_debx" },
436463Swnj 	0
446463Swnj };
456463Swnj struct	tcp_debug tcp_debug[TCP_NDEBUG];
4610425Ssam caddr_t	tcp_pcbs[TCP_NDEBUG];
476463Swnj int	tcp_debx;
48*10593Ssam char	*ntoa();
496463Swnj 
506463Swnj main(argc, argv)
516463Swnj 	int argc;
526463Swnj 	char **argv;
536463Swnj {
5410425Ssam 	int i, mask = 0, npcbs = 0;
5510272Ssam 	char *system = "/vmunix", *core = "/dev/kmem";
566463Swnj 
576463Swnj 	argc--, argv++;
586463Swnj again:
59*10593Ssam 	if (argc > 0 && !strcmp(*argv, "-a")) {
60*10593Ssam 		aflag++, argc--, argv++;
61*10593Ssam 		goto again;
62*10593Ssam 	}
636463Swnj 	if (argc > 0 && !strcmp(*argv, "-s")) {
646463Swnj 		sflag++, argc--, argv++;
656463Swnj 		goto again;
666463Swnj 	}
6710425Ssam 	if (argc > 0 && !strcmp(*argv, "-t")) {
6810425Ssam 		tflag++, argc--, argv++;
6910425Ssam 		goto again;
7010425Ssam 	}
7110425Ssam 	if (argc > 0 && !strcmp(*argv, "-j")) {
7210425Ssam 		jflag++, argc--, argv++;
7310425Ssam 		goto again;
7410425Ssam 	}
7510272Ssam 	if (argc > 0 && !strcmp(*argv, "-p")) {
7610425Ssam 		argc--, argv++;
7710272Ssam 		if (argc < 1) {
7810272Ssam 			fprintf(stderr, "-p: missing tcpcb address\n");
7910272Ssam 			exit(1);
8010272Ssam 		}
8110425Ssam 		if (npcbs >= TCP_NDEBUG) {
8210425Ssam 			fprintf(stderr, "-p: too many pcb's specified\n");
8310425Ssam 			exit(1);
8410425Ssam 		}
8510425Ssam 		sscanf(*argv, "%x", &tcp_pcbs[npcbs++]);
8610272Ssam 		argc--, argv++;
8710272Ssam 		goto again;
8810272Ssam 	}
8910272Ssam 	if (argc > 0) {
9010272Ssam 		system = *argv;
9110272Ssam 		argc--, argv++;
9210272Ssam 		mask++;
9310272Ssam 	}
9410272Ssam 	if (argc > 0) {
9510272Ssam 		core = *argv;
9610272Ssam 		argc--, argv++;
9710272Ssam 		mask++;
9810272Ssam 	}
9910272Ssam 	(void) nlist(system, nl);
1006463Swnj 	if (nl[0].n_value == 0) {
10110272Ssam 		fprintf(stderr, "trpt: %s: no namelist\n", system);
1026463Swnj 		exit(1);
1036463Swnj 	}
10410272Ssam 	(void) close(0);
10510272Ssam 	if (open(core, 0) < 0) {
10610272Ssam 		fprintf(stderr, "trpt: "); perror(core);
10710272Ssam 		exit(2);
10810272Ssam 	}
10910272Ssam 	if (mask) {
1106463Swnj 		nl[0].n_value &= 0x7fffffff;
1116463Swnj 		nl[1].n_value &= 0x7fffffff;
1126463Swnj 	}
11310272Ssam 	(void) lseek(0, nl[1].n_value, 0);
11410272Ssam 	if (read(0, &tcp_debx, sizeof (tcp_debx)) != sizeof (tcp_debx)) {
11510272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debx");
11610272Ssam 		exit(3);
11710272Ssam 	}
1186463Swnj 	printf("tcp_debx=%d\n", tcp_debx);
11910272Ssam 	(void) lseek(0, nl[0].n_value, 0);
12010272Ssam 	if (read(0, tcp_debug, sizeof (tcp_debug)) != sizeof (tcp_debug)) {
12110272Ssam 		fprintf(stderr, "trpt: "); perror("tcp_debug");
12210272Ssam 		exit(3);
12310272Ssam 	}
12410425Ssam 	/*
12510425Ssam 	 * If no control blocks have been specified, figure
12610425Ssam 	 * out how many distinct one we have and summarize
12710425Ssam 	 * them in tcp_pcbs for sorting the trace records
12810425Ssam 	 * below.
12910425Ssam 	 */
13010425Ssam 	if (npcbs == 0) {
13110425Ssam 		for (i = 0; i < TCP_NDEBUG; i++) {
13210425Ssam 			register int j;
13310425Ssam 			register struct tcp_debug *td = &tcp_debug[i];
1348382Ssam 
13510425Ssam 			if (td->td_tcb == 0)
13610425Ssam 				continue;
13710425Ssam 			for (j = 0; j < npcbs; j++)
13810425Ssam 				if (tcp_pcbs[j] == td->td_tcb)
13910425Ssam 					break;
14010425Ssam 			if (j >= npcbs)
14110425Ssam 				tcp_pcbs[npcbs++] = td->td_tcb;
14210425Ssam 		}
14310425Ssam 	}
14410425Ssam 	qsort(tcp_pcbs, npcbs, sizeof (caddr_t), numeric);
14510425Ssam 	if (jflag) {
14610425Ssam 		char *cp = "";
14710425Ssam 
14810425Ssam 		for (i = 0; i < npcbs; i++) {
14910425Ssam 			printf("%s%x", cp, tcp_pcbs[i]);
15010425Ssam 			cp = ", ";
15110425Ssam 		}
15210425Ssam 		if (*cp)
15310425Ssam 			putchar('\n');
15410425Ssam 		exit(0);
15510425Ssam 	}
15610425Ssam 	for (i = 0; i < npcbs; i++) {
15710425Ssam 		printf("\n%x:\n", tcp_pcbs[i]);
15810425Ssam 		dotrace(tcp_pcbs[i]);
15910425Ssam 	}
16010425Ssam 	exit(0);
16110425Ssam }
16210425Ssam 
16310425Ssam dotrace(tcpcb)
16410425Ssam 	register caddr_t tcpcb;
16510425Ssam {
16610425Ssam 	register int i;
16710425Ssam 	register struct tcp_debug *td;
16810425Ssam 
16910425Ssam 	for (i = 0; i < tcp_debx % TCP_NDEBUG; i++) {
17010425Ssam 		td = &tcp_debug[i];
17110272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
17210272Ssam 			continue;
1738382Ssam 		ntime = ntohl(td->td_time);
1746463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1756463Swnj 		    &td->td_ti, td->td_req);
1766463Swnj 	}
17710425Ssam 	for (i = tcp_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
17810425Ssam 		td = &tcp_debug[i];
17910272Ssam 		if (tcpcb && td->td_tcb != tcpcb)
18010272Ssam 			continue;
1818382Ssam 		ntime = ntohl(td->td_time);
1826463Swnj 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
1836463Swnj 		    &td->td_ti, td->td_req);
1846463Swnj 	}
1856463Swnj }
1866463Swnj 
1876463Swnj /*
1886463Swnj  * Tcp debug routines
1896463Swnj  */
1906463Swnj tcp_trace(act, ostate, atp, tp, ti, req)
1916463Swnj 	short act, ostate;
1926463Swnj 	struct tcpcb *atp, *tp;
1936463Swnj 	struct tcpiphdr *ti;
1946463Swnj 	int req;
1956463Swnj {
1966463Swnj 	tcp_seq seq, ack;
1978382Ssam 	int len, flags, win, timer;
1986463Swnj 	char *cp;
1996463Swnj 
2006463Swnj 	ptime(ntime);
20110425Ssam 	printf("%s:%s ", tcpstates[ostate], tanames[act]);
2026463Swnj 	switch (act) {
2036463Swnj 
2046463Swnj 	case TA_INPUT:
2056463Swnj 	case TA_OUTPUT:
206*10593Ssam 		if (aflag) {
207*10593Ssam 			printf("(src=%s,%d, ", ntoa(ti->ti_src),
208*10593Ssam 				ntohs(ti->ti_sport));
209*10593Ssam 			printf("dst=%s,%d)", ntoa(ti->ti_dst),
210*10593Ssam 				ntohs(ti->ti_dport));
211*10593Ssam 		}
2126463Swnj 		seq = ti->ti_seq;
2136463Swnj 		ack = ti->ti_ack;
2146463Swnj 		len = ti->ti_len;
2156463Swnj 		win = ti->ti_win;
2166463Swnj 		if (act == TA_OUTPUT) {
2176463Swnj 			seq = ntohl(seq);
2186463Swnj 			ack = ntohl(ack);
2196463Swnj 			len = ntohs(len);
2206463Swnj 			win = ntohs(win);
2216463Swnj 		}
2226463Swnj 		if (act == TA_OUTPUT)
2236463Swnj 			len -= sizeof (struct tcphdr);
2246463Swnj 		if (len)
2256463Swnj 			printf("[%x..%x)", seq, seq+len);
2266463Swnj 		else
2276463Swnj 			printf("%x", seq);
2286463Swnj 		printf("@%x", ack);
2296463Swnj 		if (win)
2306463Swnj 			printf("(win=%d)", win);
2316463Swnj 		flags = ti->ti_flags;
2326463Swnj 		if (flags) {
2336463Swnj 			char *cp = "<";
2346463Swnj #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } }
23510411Ssam 			pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
2366463Swnj 			printf(">");
2376463Swnj 		}
2386463Swnj 		break;
2396463Swnj 
2406463Swnj 	case TA_USER:
2418382Ssam 		timer = req >> 8;
2428382Ssam 		req &= 0xff;
2438382Ssam 		printf("%s", prurequests[req]);
2448382Ssam 		if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
2458382Ssam 			printf("<%s>", tcptimers[timer]);
2466463Swnj 		break;
2476463Swnj 	}
2486463Swnj 	printf(" -> %s", tcpstates[tp->t_state]);
2496463Swnj 	/* print out internal state of tp !?! */
2506463Swnj 	printf("\n");
2516463Swnj 	if (sflag) {
2526463Swnj 		printf("\trcv_nxt %x rcv_wnd %d snd_una %x snd_nxt %x snd_max %x\n",
25310272Ssam 		    tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
25410272Ssam 		    tp->snd_max);
25510272Ssam 		printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %x\n", tp->snd_wl1,
25610272Ssam 		    tp->snd_wl2, tp->snd_wnd);
2576463Swnj 	}
25810425Ssam 	/* print out timers? */
25910425Ssam 	if (tflag) {
26010425Ssam 		char *cp = "\t";
26110425Ssam 		register int i;
26210425Ssam 
26310425Ssam 		for (i = 0; i < TCPT_NTIMERS; i++) {
26410425Ssam 			if (tp->t_timer[i] == 0)
26510425Ssam 				continue;
26610425Ssam 			printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
26710425Ssam 			if (i == TCPT_REXMT)
26810425Ssam 				printf(" (t_rxtshft=%d)", tp->t_rxtshift);
26910425Ssam 			cp = ", ";
27010425Ssam 		}
27110425Ssam 		if (*cp != '\t')
27210425Ssam 			putchar('\n');
27310425Ssam 	}
2746463Swnj }
2756463Swnj 
2766463Swnj ptime(ms)
2776463Swnj 	int ms;
2786463Swnj {
2796463Swnj 
2806463Swnj 	printf("%03d ", (ms/10) % 1000);
2816463Swnj }
28210425Ssam 
28310425Ssam numeric(c1, c2)
28410425Ssam 	caddr_t *c1, *c2;
28510425Ssam {
28610425Ssam 
28710425Ssam 	return (*c1 - *c2);
28810425Ssam }
289*10593Ssam 
290*10593Ssam /*
291*10593Ssam  * Convert network-format internet address
292*10593Ssam  * to base 256 d.d.d.d representation.
293*10593Ssam  */
294*10593Ssam char *
295*10593Ssam ntoa(in)
296*10593Ssam 	struct in_addr in;
297*10593Ssam {
298*10593Ssam 	static char b[18];
299*10593Ssam 	register char *p;
300*10593Ssam 
301*10593Ssam 	in.s_addr = ntohl(in.s_addr);
302*10593Ssam 	p = (char *)&in;
303*10593Ssam #define	UC(b)	(((int)b)&0xff)
304*10593Ssam 	sprintf(b, "%d.%d.%d.%d", UC(p[0]), UC(p[1]), UC(p[2]), UC(p[3]));
305*10593Ssam 	return (b);
306*10593Ssam }
307