add Berkeley specific header
[unix-history] / usr / src / usr.sbin / trpt / trpt.c
CommitLineData
5ff67f98 1/*
7c5704a5 2 * Copyright (c) 1983, 1988 Regents of the University of California.
5ff67f98
DF
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
7c5704a5 9"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
5ff67f98 10 All rights reserved.\n";
7c5704a5 11#endif /* not lint */
5ff67f98 12
9a3a7863 13#ifndef lint
7c5704a5
KB
14static char sccsid[] = "@(#)trpt.c 5.4 (Berkeley) %G%";
15#endif /* not lint */
16
17#include <machine/pte.h>
9a3a7863
BJ
18
19#include <sys/param.h>
7c5704a5 20#include <sys/vmmac.h>
9a3a7863
BJ
21#include <sys/socket.h>
22#include <sys/socketvar.h>
23#define PRUREQUESTS
24#include <sys/protosw.h>
7c5704a5 25#include <sys/file.h>
94a2d2a7 26
9a3a7863 27#include <net/route.h>
9a3a7863 28#include <net/if.h>
94a2d2a7
SL
29
30#include <netinet/in.h>
31#include <netinet/in_pcb.h>
32#include <netinet/in_systm.h>
33#include <netinet/ip.h>
34#include <netinet/ip_var.h>
35#include <netinet/tcp.h>
9a3a7863 36#define TCPSTATES
94a2d2a7
SL
37#include <netinet/tcp_fsm.h>
38#include <netinet/tcp_seq.h>
9a3a7863 39#define TCPTIMERS
94a2d2a7
SL
40#include <netinet/tcp_timer.h>
41#include <netinet/tcp_var.h>
42#include <netinet/tcpip.h>
9a3a7863 43#define TANAMES
94a2d2a7 44#include <netinet/tcp_debug.h>
9a3a7863 45
7d3cb675
SL
46#include <arpa/inet.h>
47
eb0fbeab 48#include <stdio.h>
94a2d2a7 49#include <errno.h>
9a3a7863
BJ
50#include <nlist.h>
51
7c5704a5
KB
52struct nlist nl[] = {
53#define N_TCP_DEBUG 0
9a3a7863 54 { "_tcp_debug" },
7c5704a5 55#define N_TCP_DEBX 1
9a3a7863 56 { "_tcp_debx" },
7c5704a5
KB
57#define N_SYSMAP 2
58 { "_Sysmap" },
59#define N_SYSSIZE 3
60 { "_Syssize" },
61 { "" },
9a3a7863 62};
7c5704a5
KB
63
64static struct pte *Sysmap;
65static struct tcp_debug tcp_debug[TCP_NDEBUG];
66static caddr_t tcp_pcbs[TCP_NDEBUG];
67static n_time ntime;
68static int aflag, kflag, memf, follow, sflag, tcp_debx, tflag;
9a3a7863
BJ
69
70main(argc, argv)
71 int argc;
72 char **argv;
73{
7c5704a5
KB
74 extern char *optarg;
75 extern int optind;
76 int ch, i, jflag, npcbs, numeric();
77 char *system, *core, *malloc();
78 off_t lseek();
9a3a7863 79
7c5704a5
KB
80 jflag = npcbs = 0;
81 while ((ch = getopt(argc, argv, "afjp:st")) != EOF)
82 switch((char)ch) {
83 case 'a':
84 ++aflag;
85 break;
86 case 'f':
87 ++follow;
88 setlinebuf(stdout);
89 break;
90 case 'j':
91 ++jflag;
92 break;
93 case 'p':
94 if (npcbs >= TCP_NDEBUG) {
95 fputs("trpt: too many pcb's specified\n",
96 stderr);
97 exit(1);
98 }
99 (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]);
100 break;
101 case 's':
102 ++sflag;
103 break;
104 case 't':
105 ++tflag;
106 break;
107 case '?':
108 default:
109 fputs("usage: trpt [-afjst] [-p hex-address] [system [core]]\n", stderr);
175d35a6
SL
110 exit(1);
111 }
7c5704a5
KB
112 argc -= optind;
113 argv += optind;
114
115 core = "/dev/kmem";
eb0fbeab
SL
116 if (argc > 0) {
117 system = *argv;
118 argc--, argv++;
7c5704a5
KB
119 if (argc > 0) {
120 core = *argv;
121 argc--, argv++;
122 ++kflag;
123 }
eb0fbeab 124 }
7c5704a5
KB
125 else
126 system = "/vmunix";
127
128 if (nlist(system, nl) < 0 || !nl[0].n_value) {
eb0fbeab 129 fprintf(stderr, "trpt: %s: no namelist\n", system);
9a3a7863
BJ
130 exit(1);
131 }
7c5704a5
KB
132 if ((memf = open(core, O_RDONLY)) < 0) {
133 perror(core);
eb0fbeab
SL
134 exit(2);
135 }
7c5704a5
KB
136 if (kflag) {
137 off_t off;
138
139 Sysmap = (struct pte *)
140 malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
141 if (!Sysmap) {
142 fputs("arp: can't get memory for Sysmap.\n", stderr);
143 exit(1);
144 }
145 off = nl[N_SYSMAP].n_value & ~KERNBASE;
146 (void)lseek(memf, off, L_SET);
147 (void)read(memf, (char *)Sysmap,
148 (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte)));
9a3a7863 149 }
7c5704a5
KB
150 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
151 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
152 sizeof(tcp_debx)) {
153 perror("trpt: tcp_debx");
eb0fbeab
SL
154 exit(3);
155 }
7c5704a5
KB
156 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
157 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
158 sizeof(tcp_debug)) {
159 perror("trpt: tcp_debug");
eb0fbeab
SL
160 exit(3);
161 }
175d35a6
SL
162 /*
163 * If no control blocks have been specified, figure
164 * out how many distinct one we have and summarize
165 * them in tcp_pcbs for sorting the trace records
166 * below.
167 */
7c5704a5 168 if (!npcbs) {
175d35a6 169 for (i = 0; i < TCP_NDEBUG; i++) {
175d35a6 170 register struct tcp_debug *td = &tcp_debug[i];
7c5704a5 171 register int j;
175d35a6
SL
172
173 if (td->td_tcb == 0)
174 continue;
175 for (j = 0; j < npcbs; j++)
176 if (tcp_pcbs[j] == td->td_tcb)
177 break;
178 if (j >= npcbs)
179 tcp_pcbs[npcbs++] = td->td_tcb;
180 }
7c5704a5
KB
181 if (!npcbs)
182 exit(0);
175d35a6 183 }
7c5704a5 184 qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric);
175d35a6 185 if (jflag) {
7c5704a5
KB
186 for (i = 0;;) {
187 printf("%x", (int)tcp_pcbs[i]);
188 if (++i == npcbs)
189 break;
190 fputs(", ", stdout);
175d35a6 191 }
7c5704a5 192 putchar('\n');
175d35a6 193 }
7c5704a5
KB
194 else for (i = 0; i < npcbs; i++) {
195 printf("\n%x:\n", (int)tcp_pcbs[i]);
175d35a6
SL
196 dotrace(tcp_pcbs[i]);
197 }
198 exit(0);
199}
200
201dotrace(tcpcb)
202 register caddr_t tcpcb;
203{
175d35a6 204 register struct tcp_debug *td;
7c5704a5 205 register int i;
89586647 206 int prev_debx = tcp_debx;
175d35a6 207
7c5704a5 208again: if (--tcp_debx < 0)
89586647
MK
209 tcp_debx = TCP_NDEBUG - 1;
210 for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) {
175d35a6 211 td = &tcp_debug[i];
eb0fbeab
SL
212 if (tcpcb && td->td_tcb != tcpcb)
213 continue;
10ce0f6a 214 ntime = ntohl(td->td_time);
9a3a7863
BJ
215 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
216 &td->td_ti, td->td_req);
89586647
MK
217 if (i == tcp_debx)
218 goto done;
9a3a7863 219 }
89586647 220 for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) {
175d35a6 221 td = &tcp_debug[i];
eb0fbeab
SL
222 if (tcpcb && td->td_tcb != tcpcb)
223 continue;
10ce0f6a 224 ntime = ntohl(td->td_time);
9a3a7863
BJ
225 tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb,
226 &td->td_ti, td->td_req);
227 }
7c5704a5
KB
228done: if (follow) {
229 prev_debx = tcp_debx + 1;
230 if (prev_debx >= TCP_NDEBUG)
231 prev_debx = 0;
232 do {
233 sleep(1);
234 (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET);
235 if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) !=
236 sizeof(tcp_debx)) {
237 perror("trpt: tcp_debx");
238 exit(3);
239 }
240 } while (tcp_debx == prev_debx);
241 (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET);
242 if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) !=
243 sizeof(tcp_debug)) {
244 perror("trpt: tcp_debug");
89586647
MK
245 exit(3);
246 }
7c5704a5 247 goto again;
89586647 248 }
9a3a7863
BJ
249}
250
251/*
252 * Tcp debug routines
253 */
7c5704a5 254/*ARGSUSED*/
9a3a7863
BJ
255tcp_trace(act, ostate, atp, tp, ti, req)
256 short act, ostate;
257 struct tcpcb *atp, *tp;
258 struct tcpiphdr *ti;
259 int req;
260{
261 tcp_seq seq, ack;
7c5704a5 262 int flags, len, win, timer;
9a3a7863 263
7c5704a5
KB
264 printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate],
265 tanames[act]);
9a3a7863 266 switch (act) {
9a3a7863
BJ
267 case TA_INPUT:
268 case TA_OUTPUT:
3cd6f35b 269 case TA_DROP:
7c5704a5
KB
270 if (aflag)
271 printf("(src=%s,%u, dst=%s,%u)", inet_ntoa(ti->ti_src),
272 ntohs(ti->ti_sport), inet_ntoa(ti->ti_dst),
273 ntohs(ti->ti_dport));
9a3a7863
BJ
274 seq = ti->ti_seq;
275 ack = ti->ti_ack;
276 len = ti->ti_len;
277 win = ti->ti_win;
9a3a7863
BJ
278 if (act == TA_OUTPUT) {
279 seq = ntohl(seq);
280 ack = ntohl(ack);
281 len = ntohs(len);
282 win = ntohs(win);
283 }
9a3a7863 284 if (act == TA_OUTPUT)
7c5704a5 285 len -= sizeof(struct tcphdr);
9a3a7863 286 if (len)
7c5704a5 287 printf("[%lx..%lx)", seq, seq + len);
9a3a7863 288 else
7c5704a5
KB
289 printf("%lx", seq);
290 printf("@%lx", ack);
9a3a7863 291 if (win)
23c416d7 292 printf("(win=%x)", win);
9a3a7863
BJ
293 flags = ti->ti_flags;
294 if (flags) {
7c5704a5
KB
295 register char *cp = "<";
296#define pf(flag) { \
297 if (ti->ti_flags&flag) \
298 printf("%s%s", cp, "f"); \
299 cp = ","; \
300 }
301 pf(TH_SYN);
302 pf(TH_ACK);
303 pf(TH_FIN);
304 pf(TH_RST);
305 pf(TH_PUSH);
306 pf(TH_URG);
9a3a7863
BJ
307 printf(">");
308 }
309 break;
9a3a7863 310 case TA_USER:
10ce0f6a
SL
311 timer = req >> 8;
312 req &= 0xff;
313 printf("%s", prurequests[req]);
314 if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO)
315 printf("<%s>", tcptimers[timer]);
9a3a7863
BJ
316 break;
317 }
318 printf(" -> %s", tcpstates[tp->t_state]);
319 /* print out internal state of tp !?! */
320 printf("\n");
321 if (sflag) {
7c5704a5 322 printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n",
eb0fbeab
SL
323 tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt,
324 tp->snd_max);
7c5704a5 325 printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1,
eb0fbeab 326 tp->snd_wl2, tp->snd_wnd);
9a3a7863 327 }
175d35a6
SL
328 /* print out timers? */
329 if (tflag) {
7c5704a5 330 register char *cp = "\t";
175d35a6
SL
331 register int i;
332
333 for (i = 0; i < TCPT_NTIMERS; i++) {
334 if (tp->t_timer[i] == 0)
335 continue;
336 printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]);
337 if (i == TCPT_REXMT)
338 printf(" (t_rxtshft=%d)", tp->t_rxtshift);
339 cp = ", ";
340 }
341 if (*cp != '\t')
342 putchar('\n');
343 }
9a3a7863
BJ
344}
345
7c5704a5
KB
346numeric(c1, c2)
347 caddr_t *c1, *c2;
9a3a7863 348{
7c5704a5 349 return(*c1 - *c2);
9a3a7863 350}
175d35a6 351
7c5704a5
KB
352klseek(fd, base, off)
353 int fd, off;
354 off_t base;
175d35a6 355{
7c5704a5
KB
356 off_t lseek();
357
358 if (kflag) { /* get kernel pte */
359 base &= ~KERNBASE;
360 base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET);
361 }
362 (void)lseek(fd, base, off);
175d35a6 363}