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