1*22014Sdist /* 2*22014Sdist * Copyright (c) 1983 Regents of the University of California. 3*22014Sdist * All rights reserved. The Berkeley software License Agreement 4*22014Sdist * specifies the terms and conditions for redistribution. 5*22014Sdist */ 6*22014Sdist 76463Swnj #ifndef lint 8*22014Sdist char copyright[] = 9*22014Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 10*22014Sdist All rights reserved.\n"; 11*22014Sdist #endif not lint 126463Swnj 13*22014Sdist #ifndef lint 14*22014Sdist static char sccsid[] = "@(#)trpt.c 5.1 (Berkeley) 06/04/85"; 15*22014Sdist #endif not lint 16*22014Sdist 176463Swnj #include <sys/param.h> 186463Swnj #include <sys/socket.h> 196463Swnj #include <sys/socketvar.h> 206463Swnj #define PRUREQUESTS 216463Swnj #include <sys/protosw.h> 229202Ssam 236463Swnj #include <net/route.h> 246463Swnj #include <net/if.h> 259202Ssam 269202Ssam #include <netinet/in.h> 279202Ssam #include <netinet/in_pcb.h> 289202Ssam #include <netinet/in_systm.h> 299202Ssam #include <netinet/ip.h> 309202Ssam #include <netinet/ip_var.h> 319202Ssam #include <netinet/tcp.h> 326463Swnj #define TCPSTATES 339202Ssam #include <netinet/tcp_fsm.h> 349202Ssam #include <netinet/tcp_seq.h> 356463Swnj #define TCPTIMERS 369202Ssam #include <netinet/tcp_timer.h> 379202Ssam #include <netinet/tcp_var.h> 389202Ssam #include <netinet/tcpip.h> 396463Swnj #define TANAMES 409202Ssam #include <netinet/tcp_debug.h> 419202Ssam 4215252Ssam #include <arpa/inet.h> 4315252Ssam 4410272Ssam #include <stdio.h> 456463Swnj #include <errno.h> 466463Swnj #include <nlist.h> 476463Swnj 486463Swnj n_time ntime; 496463Swnj int sflag; 5010425Ssam int tflag; 5110425Ssam int jflag; 5210593Ssam int aflag; 5310425Ssam int numeric(); 546463Swnj struct nlist nl[] = { 556463Swnj { "_tcp_debug" }, 566463Swnj { "_tcp_debx" }, 576463Swnj 0 586463Swnj }; 596463Swnj struct tcp_debug tcp_debug[TCP_NDEBUG]; 6010425Ssam caddr_t tcp_pcbs[TCP_NDEBUG]; 616463Swnj int tcp_debx; 626463Swnj 636463Swnj main(argc, argv) 646463Swnj int argc; 656463Swnj char **argv; 666463Swnj { 6710425Ssam int i, mask = 0, npcbs = 0; 6810272Ssam char *system = "/vmunix", *core = "/dev/kmem"; 696463Swnj 706463Swnj argc--, argv++; 716463Swnj again: 7210593Ssam if (argc > 0 && !strcmp(*argv, "-a")) { 7310593Ssam aflag++, argc--, argv++; 7410593Ssam goto again; 7510593Ssam } 766463Swnj if (argc > 0 && !strcmp(*argv, "-s")) { 776463Swnj sflag++, argc--, argv++; 786463Swnj goto again; 796463Swnj } 8010425Ssam if (argc > 0 && !strcmp(*argv, "-t")) { 8110425Ssam tflag++, argc--, argv++; 8210425Ssam goto again; 8310425Ssam } 8410425Ssam if (argc > 0 && !strcmp(*argv, "-j")) { 8510425Ssam jflag++, argc--, argv++; 8610425Ssam goto again; 8710425Ssam } 8810272Ssam if (argc > 0 && !strcmp(*argv, "-p")) { 8910425Ssam argc--, argv++; 9010272Ssam if (argc < 1) { 9110272Ssam fprintf(stderr, "-p: missing tcpcb address\n"); 9210272Ssam exit(1); 9310272Ssam } 9410425Ssam if (npcbs >= TCP_NDEBUG) { 9510425Ssam fprintf(stderr, "-p: too many pcb's specified\n"); 9610425Ssam exit(1); 9710425Ssam } 9810425Ssam sscanf(*argv, "%x", &tcp_pcbs[npcbs++]); 9910272Ssam argc--, argv++; 10010272Ssam goto again; 10110272Ssam } 10210272Ssam if (argc > 0) { 10310272Ssam system = *argv; 10410272Ssam argc--, argv++; 10510272Ssam mask++; 10610272Ssam } 10710272Ssam if (argc > 0) { 10810272Ssam core = *argv; 10910272Ssam argc--, argv++; 11010272Ssam mask++; 11110272Ssam } 11210272Ssam (void) nlist(system, nl); 1136463Swnj if (nl[0].n_value == 0) { 11410272Ssam fprintf(stderr, "trpt: %s: no namelist\n", system); 1156463Swnj exit(1); 1166463Swnj } 11710272Ssam (void) close(0); 11810272Ssam if (open(core, 0) < 0) { 11910272Ssam fprintf(stderr, "trpt: "); perror(core); 12010272Ssam exit(2); 12110272Ssam } 12210272Ssam if (mask) { 1236463Swnj nl[0].n_value &= 0x7fffffff; 1246463Swnj nl[1].n_value &= 0x7fffffff; 1256463Swnj } 12610272Ssam (void) lseek(0, nl[1].n_value, 0); 12710272Ssam if (read(0, &tcp_debx, sizeof (tcp_debx)) != sizeof (tcp_debx)) { 12810272Ssam fprintf(stderr, "trpt: "); perror("tcp_debx"); 12910272Ssam exit(3); 13010272Ssam } 13110272Ssam (void) lseek(0, nl[0].n_value, 0); 13210272Ssam if (read(0, tcp_debug, sizeof (tcp_debug)) != sizeof (tcp_debug)) { 13310272Ssam fprintf(stderr, "trpt: "); perror("tcp_debug"); 13410272Ssam exit(3); 13510272Ssam } 13610425Ssam /* 13710425Ssam * If no control blocks have been specified, figure 13810425Ssam * out how many distinct one we have and summarize 13910425Ssam * them in tcp_pcbs for sorting the trace records 14010425Ssam * below. 14110425Ssam */ 14210425Ssam if (npcbs == 0) { 14310425Ssam for (i = 0; i < TCP_NDEBUG; i++) { 14410425Ssam register int j; 14510425Ssam register struct tcp_debug *td = &tcp_debug[i]; 1468382Ssam 14710425Ssam if (td->td_tcb == 0) 14810425Ssam continue; 14910425Ssam for (j = 0; j < npcbs; j++) 15010425Ssam if (tcp_pcbs[j] == td->td_tcb) 15110425Ssam break; 15210425Ssam if (j >= npcbs) 15310425Ssam tcp_pcbs[npcbs++] = td->td_tcb; 15410425Ssam } 15510425Ssam } 15610425Ssam qsort(tcp_pcbs, npcbs, sizeof (caddr_t), numeric); 15710425Ssam if (jflag) { 15810425Ssam char *cp = ""; 15910425Ssam 16010425Ssam for (i = 0; i < npcbs; i++) { 16110425Ssam printf("%s%x", cp, tcp_pcbs[i]); 16210425Ssam cp = ", "; 16310425Ssam } 16410425Ssam if (*cp) 16510425Ssam putchar('\n'); 16610425Ssam exit(0); 16710425Ssam } 16810425Ssam for (i = 0; i < npcbs; i++) { 16910425Ssam printf("\n%x:\n", tcp_pcbs[i]); 17010425Ssam dotrace(tcp_pcbs[i]); 17110425Ssam } 17210425Ssam exit(0); 17310425Ssam } 17410425Ssam 17510425Ssam dotrace(tcpcb) 17610425Ssam register caddr_t tcpcb; 17710425Ssam { 17810425Ssam register int i; 17910425Ssam register struct tcp_debug *td; 18010425Ssam 18121814Skarels for (i = tcp_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 18210425Ssam td = &tcp_debug[i]; 18310272Ssam if (tcpcb && td->td_tcb != tcpcb) 18410272Ssam continue; 1858382Ssam ntime = ntohl(td->td_time); 1866463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 1876463Swnj &td->td_ti, td->td_req); 1886463Swnj } 18921814Skarels for (i = 0; i < tcp_debx % TCP_NDEBUG; i++) { 19010425Ssam td = &tcp_debug[i]; 19110272Ssam if (tcpcb && td->td_tcb != tcpcb) 19210272Ssam continue; 1938382Ssam ntime = ntohl(td->td_time); 1946463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 1956463Swnj &td->td_ti, td->td_req); 1966463Swnj } 1976463Swnj } 1986463Swnj 1996463Swnj /* 2006463Swnj * Tcp debug routines 2016463Swnj */ 2026463Swnj tcp_trace(act, ostate, atp, tp, ti, req) 2036463Swnj short act, ostate; 2046463Swnj struct tcpcb *atp, *tp; 2056463Swnj struct tcpiphdr *ti; 2066463Swnj int req; 2076463Swnj { 2086463Swnj tcp_seq seq, ack; 2098382Ssam int len, flags, win, timer; 2106463Swnj char *cp; 2116463Swnj 2126463Swnj ptime(ntime); 21310425Ssam printf("%s:%s ", tcpstates[ostate], tanames[act]); 2146463Swnj switch (act) { 2156463Swnj 2166463Swnj case TA_INPUT: 2176463Swnj case TA_OUTPUT: 21814004Shelge case TA_DROP: 21910593Ssam if (aflag) { 22015252Ssam printf("(src=%s,%d, ", inet_ntoa(ti->ti_src), 22110593Ssam ntohs(ti->ti_sport)); 22215252Ssam printf("dst=%s,%d)", inet_ntoa(ti->ti_dst), 22310593Ssam ntohs(ti->ti_dport)); 22410593Ssam } 2256463Swnj seq = ti->ti_seq; 2266463Swnj ack = ti->ti_ack; 2276463Swnj len = ti->ti_len; 2286463Swnj win = ti->ti_win; 2296463Swnj if (act == TA_OUTPUT) { 2306463Swnj seq = ntohl(seq); 2316463Swnj ack = ntohl(ack); 2326463Swnj len = ntohs(len); 2336463Swnj win = ntohs(win); 2346463Swnj } 2356463Swnj if (act == TA_OUTPUT) 2366463Swnj len -= sizeof (struct tcphdr); 2376463Swnj if (len) 2386463Swnj printf("[%x..%x)", seq, seq+len); 2396463Swnj else 2406463Swnj printf("%x", seq); 2416463Swnj printf("@%x", ack); 2426463Swnj if (win) 24314282Shelge printf("(win=%x)", win); 2446463Swnj flags = ti->ti_flags; 2456463Swnj if (flags) { 2466463Swnj char *cp = "<"; 2476463Swnj #define pf(f) { if (ti->ti_flags&TH_/**/f) { printf("%s%s", cp, "f"); cp = ","; } } 24810411Ssam pf(SYN); pf(ACK); pf(FIN); pf(RST); pf(PUSH); pf(URG); 2496463Swnj printf(">"); 2506463Swnj } 2516463Swnj break; 2526463Swnj 2536463Swnj case TA_USER: 2548382Ssam timer = req >> 8; 2558382Ssam req &= 0xff; 2568382Ssam printf("%s", prurequests[req]); 2578382Ssam if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 2588382Ssam printf("<%s>", tcptimers[timer]); 2596463Swnj break; 2606463Swnj } 2616463Swnj printf(" -> %s", tcpstates[tp->t_state]); 2626463Swnj /* print out internal state of tp !?! */ 2636463Swnj printf("\n"); 2646463Swnj if (sflag) { 26514000Shelge printf("\trcv_nxt %x rcv_wnd %x snd_una %x snd_nxt %x snd_max %x\n", 26610272Ssam tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 26710272Ssam tp->snd_max); 26810272Ssam printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %x\n", tp->snd_wl1, 26910272Ssam tp->snd_wl2, tp->snd_wnd); 2706463Swnj } 27110425Ssam /* print out timers? */ 27210425Ssam if (tflag) { 27310425Ssam char *cp = "\t"; 27410425Ssam register int i; 27510425Ssam 27610425Ssam for (i = 0; i < TCPT_NTIMERS; i++) { 27710425Ssam if (tp->t_timer[i] == 0) 27810425Ssam continue; 27910425Ssam printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 28010425Ssam if (i == TCPT_REXMT) 28110425Ssam printf(" (t_rxtshft=%d)", tp->t_rxtshift); 28210425Ssam cp = ", "; 28310425Ssam } 28410425Ssam if (*cp != '\t') 28510425Ssam putchar('\n'); 28610425Ssam } 2876463Swnj } 2886463Swnj 2896463Swnj ptime(ms) 2906463Swnj int ms; 2916463Swnj { 2926463Swnj 2936463Swnj printf("%03d ", (ms/10) % 1000); 2946463Swnj } 29510425Ssam 29610425Ssam numeric(c1, c2) 29710425Ssam caddr_t *c1, *c2; 29810425Ssam { 29910425Ssam 30010425Ssam return (*c1 - *c2); 30110425Ssam } 302