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