xref: /original-bsd/usr.sbin/trpt/trpt.c (revision 90dba07b)
1 #ifndef lint
2 static char sccsid[] = "@(#)trpt.c	4.12 06/03/85";
3 #endif
4 
5 #include <sys/param.h>
6 #include <sys/socket.h>
7 #include <sys/socketvar.h>
8 #define PRUREQUESTS
9 #include <sys/protosw.h>
10 
11 #include <net/route.h>
12 #include <net/if.h>
13 
14 #include <netinet/in.h>
15 #include <netinet/in_pcb.h>
16 #include <netinet/in_systm.h>
17 #include <netinet/ip.h>
18 #include <netinet/ip_var.h>
19 #include <netinet/tcp.h>
20 #define TCPSTATES
21 #include <netinet/tcp_fsm.h>
22 #include <netinet/tcp_seq.h>
23 #define	TCPTIMERS
24 #include <netinet/tcp_timer.h>
25 #include <netinet/tcp_var.h>
26 #include <netinet/tcpip.h>
27 #define	TANAMES
28 #include <netinet/tcp_debug.h>
29 
30 #include <arpa/inet.h>
31 
32 #include <stdio.h>
33 #include <errno.h>
34 #include <nlist.h>
35 
36 n_time	ntime;
37 int	sflag;
38 int	tflag;
39 int	jflag;
40 int	aflag;
41 int	numeric();
42 struct	nlist nl[] = {
43 	{ "_tcp_debug" },
44 	{ "_tcp_debx" },
45 	0
46 };
47 struct	tcp_debug tcp_debug[TCP_NDEBUG];
48 caddr_t	tcp_pcbs[TCP_NDEBUG];
49 int	tcp_debx;
50 
51 main(argc, argv)
52 	int argc;
53 	char **argv;
54 {
55 	int i, mask = 0, npcbs = 0;
56 	char *system = "/vmunix", *core = "/dev/kmem";
57 
58 	argc--, argv++;
59 again:
60 	if (argc > 0 && !strcmp(*argv, "-a")) {
61 		aflag++, argc--, argv++;
62 		goto again;
63 	}
64 	if (argc > 0 && !strcmp(*argv, "-s")) {
65 		sflag++, argc--, argv++;
66 		goto again;
67 	}
68 	if (argc > 0 && !strcmp(*argv, "-t")) {
69 		tflag++, argc--, argv++;
70 		goto again;
71 	}
72 	if (argc > 0 && !strcmp(*argv, "-j")) {
73 		jflag++, argc--, argv++;
74 		goto again;
75 	}
76 	if (argc > 0 && !strcmp(*argv, "-p")) {
77 		argc--, argv++;
78 		if (argc < 1) {
79 			fprintf(stderr, "-p: missing tcpcb address\n");
80 			exit(1);
81 		}
82 		if (npcbs >= TCP_NDEBUG) {
83 			fprintf(stderr, "-p: too many pcb's specified\n");
84 			exit(1);
85 		}
86 		sscanf(*argv, "%x", &tcp_pcbs[npcbs++]);
87 		argc--, argv++;
88 		goto again;
89 	}
90 	if (argc > 0) {
91 		system = *argv;
92 		argc--, argv++;
93 		mask++;
94 	}
95 	if (argc > 0) {
96 		core = *argv;
97 		argc--, argv++;
98 		mask++;
99 	}
100 	(void) nlist(system, nl);
101 	if (nl[0].n_value == 0) {
102 		fprintf(stderr, "trpt: %s: no namelist\n", system);
103 		exit(1);
104 	}
105 	(void) close(0);
106 	if (open(core, 0) < 0) {
107 		fprintf(stderr, "trpt: "); perror(core);
108 		exit(2);
109 	}
110 	if (mask) {
111 		nl[0].n_value &= 0x7fffffff;
112 		nl[1].n_value &= 0x7fffffff;
113 	}
114 	(void) lseek(0, nl[1].n_value, 0);
115 	if (read(0, &tcp_debx, sizeof (tcp_debx)) != sizeof (tcp_debx)) {
116 		fprintf(stderr, "trpt: "); perror("tcp_debx");
117 		exit(3);
118 	}
119 	(void) lseek(0, nl[0].n_value, 0);
120 	if (read(0, tcp_debug, sizeof (tcp_debug)) != sizeof (tcp_debug)) {
121 		fprintf(stderr, "trpt: "); perror("tcp_debug");
122 		exit(3);
123 	}
124 	/*
125 	 * If no control blocks have been specified, figure
126 	 * out how many distinct one we have and summarize
127 	 * them in tcp_pcbs for sorting the trace records
128 	 * below.
129 	 */
130 	if (npcbs == 0) {
131 		for (i = 0; i < TCP_NDEBUG; i++) {
132 			register int j;
133 			register struct tcp_debug *td = &tcp_debug[i];
134 
135 			if (td->td_tcb == 0)
136 				continue;
137 			for (j = 0; j < npcbs; j++)
138 				if (tcp_pcbs[j] == td->td_tcb)
139 					break;
140 			if (j >= npcbs)
141 				tcp_pcbs[npcbs++] = td->td_tcb;
142 		}
143 	}
144 	qsort(tcp_pcbs, npcbs, sizeof (caddr_t), numeric);
145 	if (jflag) {
146 		char *cp = "";
147 
148 		for (i = 0; i < npcbs; i++) {
149 			printf("%s%x", cp, tcp_pcbs[i]);
150 			cp = ", ";
151 		}
152 		if (*cp)
153 			putchar('\n');
154 		exit(0);
155 	}
156 	for (i = 0; i < npcbs; i++) {
157 		printf("\n%x:\n", tcp_pcbs[i]);
158 		dotrace(tcp_pcbs[i]);
159 	}
160 	exit(0);
161 }
162 
163 dotrace(tcpcb)
164 	register caddr_t tcpcb;
165 {
166 	register int i;
167 	register struct tcp_debug *td;
168 
169 	for (i = tcp_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
170 		td = &tcp_debug[i];
171 		if (tcpcb && td->td_tcb != tcpcb)
172 			continue;
173 		ntime = ntohl(td->td_time);
174 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
175 		    &td->td_ti, td->td_req);
176 	}
177 	for (i = 0; i < tcp_debx % TCP_NDEBUG; i++) {
178 		td = &tcp_debug[i];
179 		if (tcpcb && td->td_tcb != tcpcb)
180 			continue;
181 		ntime = ntohl(td->td_time);
182 		tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
183 		    &td->td_ti, td->td_req);
184 	}
185 }
186 
187 /*
188  * Tcp debug routines
189  */
190 tcp_trace(act, ostate, atp, tp, ti, req)
191 	short act, ostate;
192 	struct tcpcb *atp, *tp;
193 	struct tcpiphdr *ti;
194 	int req;
195 {
196 	tcp_seq seq, ack;
197 	int len, flags, win, timer;
198 	char *cp;
199 
200 	ptime(ntime);
201 	printf("%s:%s ", tcpstates[ostate], tanames[act]);
202 	switch (act) {
203 
204 	case TA_INPUT:
205 	case TA_OUTPUT:
206 	case TA_DROP:
207 		if (aflag) {
208 			printf("(src=%s,%d, ", inet_ntoa(ti->ti_src),
209 				ntohs(ti->ti_sport));
210 			printf("dst=%s,%d)", inet_ntoa(ti->ti_dst),
211 				ntohs(ti->ti_dport));
212 		}
213 		seq = ti->ti_seq;
214 		ack = ti->ti_ack;
215 		len = ti->ti_len;
216 		win = ti->ti_win;
217 		if (act == TA_OUTPUT) {
218 			seq = ntohl(seq);
219 			ack = ntohl(ack);
220 			len = ntohs(len);
221 			win = ntohs(win);
222 		}
223 		if (act == TA_OUTPUT)
224 			len -= sizeof (struct tcphdr);
225 		if (len)
226 			printf("[%x..%x)", seq, seq+len);
227 		else
228 			printf("%x", seq);
229 		printf("@%x", ack);
230 		if (win)
231 			printf("(win=%x)", win);
232 		flags = ti->ti_flags;
233 		if (flags) {
234 			char *cp = "<";
235 #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } }
236 			pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG);
237 			printf(">");
238 		}
239 		break;
240 
241 	case TA_USER:
242 		timer = req >> 8;
243 		req &= 0xff;
244 		printf("%s", prurequests[req]);
245 		if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
246 			printf("<%s>", tcptimers[timer]);
247 		break;
248 	}
249 	printf(" -> %s", tcpstates[tp->t_state]);
250 	/* print out internal state of tp !?! */
251 	printf("\n");
252 	if (sflag) {
253 		printf("\trcv_nxt %x rcv_wnd %x snd_una %x snd_nxt %x snd_max %x\n",
254 		    tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
255 		    tp->snd_max);
256 		printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %x\n", tp->snd_wl1,
257 		    tp->snd_wl2, tp->snd_wnd);
258 	}
259 	/* print out timers? */
260 	if (tflag) {
261 		char *cp = "\t";
262 		register int i;
263 
264 		for (i = 0; i < TCPT_NTIMERS; i++) {
265 			if (tp->t_timer[i] == 0)
266 				continue;
267 			printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
268 			if (i == TCPT_REXMT)
269 				printf(" (t_rxtshft=%d)", tp->t_rxtshift);
270 			cp = ", ";
271 		}
272 		if (*cp != '\t')
273 			putchar('\n');
274 	}
275 }
276 
277 ptime(ms)
278 	int ms;
279 {
280 
281 	printf("%03d ", (ms/10) % 1000);
282 }
283 
284 numeric(c1, c2)
285 	caddr_t *c1, *c2;
286 {
287 
288 	return (*c1 - *c2);
289 }
290