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