122014Sdist /* 2*33663Sbostic * Copyright (c) 1983, 1988 Regents of the University of California. 322014Sdist * All rights reserved. The Berkeley software License Agreement 422014Sdist * specifies the terms and conditions for redistribution. 522014Sdist */ 622014Sdist 76463Swnj #ifndef lint 822014Sdist char copyright[] = 9*33663Sbostic "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 1022014Sdist All rights reserved.\n"; 11*33663Sbostic #endif /* not lint */ 126463Swnj 1322014Sdist #ifndef lint 14*33663Sbostic static char sccsid[] = "@(#)trpt.c 5.4 (Berkeley) 03/04/88"; 15*33663Sbostic #endif /* not lint */ 1622014Sdist 17*33663Sbostic #include <machine/pte.h> 18*33663Sbostic 196463Swnj #include <sys/param.h> 20*33663Sbostic #include <sys/vmmac.h> 216463Swnj #include <sys/socket.h> 226463Swnj #include <sys/socketvar.h> 236463Swnj #define PRUREQUESTS 246463Swnj #include <sys/protosw.h> 25*33663Sbostic #include <sys/file.h> 269202Ssam 276463Swnj #include <net/route.h> 286463Swnj #include <net/if.h> 299202Ssam 309202Ssam #include <netinet/in.h> 319202Ssam #include <netinet/in_pcb.h> 329202Ssam #include <netinet/in_systm.h> 339202Ssam #include <netinet/ip.h> 349202Ssam #include <netinet/ip_var.h> 359202Ssam #include <netinet/tcp.h> 366463Swnj #define TCPSTATES 379202Ssam #include <netinet/tcp_fsm.h> 389202Ssam #include <netinet/tcp_seq.h> 396463Swnj #define TCPTIMERS 409202Ssam #include <netinet/tcp_timer.h> 419202Ssam #include <netinet/tcp_var.h> 429202Ssam #include <netinet/tcpip.h> 436463Swnj #define TANAMES 449202Ssam #include <netinet/tcp_debug.h> 459202Ssam 4615252Ssam #include <arpa/inet.h> 4715252Ssam 4810272Ssam #include <stdio.h> 496463Swnj #include <errno.h> 506463Swnj #include <nlist.h> 516463Swnj 52*33663Sbostic struct nlist nl[] = { 53*33663Sbostic #define N_TCP_DEBUG 0 546463Swnj { "_tcp_debug" }, 55*33663Sbostic #define N_TCP_DEBX 1 566463Swnj { "_tcp_debx" }, 57*33663Sbostic #define N_SYSMAP 2 58*33663Sbostic { "_Sysmap" }, 59*33663Sbostic #define N_SYSSIZE 3 60*33663Sbostic { "_Syssize" }, 61*33663Sbostic { "" }, 626463Swnj }; 636463Swnj 64*33663Sbostic static struct pte *Sysmap; 65*33663Sbostic static struct tcp_debug tcp_debug[TCP_NDEBUG]; 66*33663Sbostic static caddr_t tcp_pcbs[TCP_NDEBUG]; 67*33663Sbostic static n_time ntime; 68*33663Sbostic static int aflag, kflag, memf, follow, sflag, tcp_debx, tflag; 69*33663Sbostic 706463Swnj main(argc, argv) 716463Swnj int argc; 726463Swnj char **argv; 736463Swnj { 74*33663Sbostic extern char *optarg; 75*33663Sbostic extern int optind; 76*33663Sbostic int ch, i, jflag, npcbs, numeric(); 77*33663Sbostic char *system, *core, *malloc(); 78*33663Sbostic off_t lseek(); 796463Swnj 80*33663Sbostic jflag = npcbs = 0; 81*33663Sbostic while ((ch = getopt(argc, argv, "afjp:st")) != EOF) 82*33663Sbostic switch((char)ch) { 83*33663Sbostic case 'a': 84*33663Sbostic ++aflag; 85*33663Sbostic break; 86*33663Sbostic case 'f': 87*33663Sbostic ++follow; 88*33663Sbostic setlinebuf(stdout); 89*33663Sbostic break; 90*33663Sbostic case 'j': 91*33663Sbostic ++jflag; 92*33663Sbostic break; 93*33663Sbostic case 'p': 94*33663Sbostic if (npcbs >= TCP_NDEBUG) { 95*33663Sbostic fputs("trpt: too many pcb's specified\n", 96*33663Sbostic stderr); 97*33663Sbostic exit(1); 98*33663Sbostic } 99*33663Sbostic (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); 100*33663Sbostic break; 101*33663Sbostic case 's': 102*33663Sbostic ++sflag; 103*33663Sbostic break; 104*33663Sbostic case 't': 105*33663Sbostic ++tflag; 106*33663Sbostic break; 107*33663Sbostic case '?': 108*33663Sbostic default: 109*33663Sbostic fputs("usage: trpt [-afjst] [-p hex-address] [system [core]]\n", stderr); 11010272Ssam exit(1); 11110272Ssam } 112*33663Sbostic argc -= optind; 113*33663Sbostic argv += optind; 114*33663Sbostic 115*33663Sbostic core = "/dev/kmem"; 11610272Ssam if (argc > 0) { 11710272Ssam system = *argv; 11810272Ssam argc--, argv++; 119*33663Sbostic if (argc > 0) { 120*33663Sbostic core = *argv; 121*33663Sbostic argc--, argv++; 122*33663Sbostic ++kflag; 123*33663Sbostic } 12410272Ssam } 125*33663Sbostic else 126*33663Sbostic system = "/vmunix"; 127*33663Sbostic 128*33663Sbostic if (nlist(system, nl) < 0 || !nl[0].n_value) { 12910272Ssam fprintf(stderr, "trpt: %s: no namelist\n", system); 1306463Swnj exit(1); 1316463Swnj } 132*33663Sbostic if ((memf = open(core, O_RDONLY)) < 0) { 133*33663Sbostic perror(core); 13410272Ssam exit(2); 13510272Ssam } 136*33663Sbostic if (kflag) { 137*33663Sbostic off_t off; 138*33663Sbostic 139*33663Sbostic Sysmap = (struct pte *) 140*33663Sbostic malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 141*33663Sbostic if (!Sysmap) { 142*33663Sbostic fputs("arp: can't get memory for Sysmap.\n", stderr); 143*33663Sbostic exit(1); 144*33663Sbostic } 145*33663Sbostic off = nl[N_SYSMAP].n_value & ~KERNBASE; 146*33663Sbostic (void)lseek(memf, off, L_SET); 147*33663Sbostic (void)read(memf, (char *)Sysmap, 148*33663Sbostic (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 1496463Swnj } 150*33663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 151*33663Sbostic if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 152*33663Sbostic sizeof(tcp_debx)) { 153*33663Sbostic perror("trpt: tcp_debx"); 15410272Ssam exit(3); 15510272Ssam } 156*33663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 157*33663Sbostic if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 158*33663Sbostic sizeof(tcp_debug)) { 159*33663Sbostic perror("trpt: tcp_debug"); 16010272Ssam exit(3); 16110272Ssam } 16210425Ssam /* 16310425Ssam * If no control blocks have been specified, figure 16410425Ssam * out how many distinct one we have and summarize 16510425Ssam * them in tcp_pcbs for sorting the trace records 16610425Ssam * below. 16710425Ssam */ 168*33663Sbostic if (!npcbs) { 16910425Ssam for (i = 0; i < TCP_NDEBUG; i++) { 170*33663Sbostic register struct tcp_debug *td = &tcp_debug[i]; 17110425Ssam register int j; 1728382Ssam 17310425Ssam if (td->td_tcb == 0) 17410425Ssam continue; 17510425Ssam for (j = 0; j < npcbs; j++) 17610425Ssam if (tcp_pcbs[j] == td->td_tcb) 17710425Ssam break; 17810425Ssam if (j >= npcbs) 17910425Ssam tcp_pcbs[npcbs++] = td->td_tcb; 18010425Ssam } 181*33663Sbostic if (!npcbs) 182*33663Sbostic exit(0); 18310425Ssam } 184*33663Sbostic qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 18510425Ssam if (jflag) { 186*33663Sbostic for (i = 0;;) { 187*33663Sbostic printf("%x", (int)tcp_pcbs[i]); 188*33663Sbostic if (++i == npcbs) 189*33663Sbostic break; 190*33663Sbostic fputs(", ", stdout); 19110425Ssam } 192*33663Sbostic putchar('\n'); 19310425Ssam } 194*33663Sbostic else for (i = 0; i < npcbs; i++) { 195*33663Sbostic printf("\n%x:\n", (int)tcp_pcbs[i]); 19610425Ssam dotrace(tcp_pcbs[i]); 19710425Ssam } 19810425Ssam exit(0); 19910425Ssam } 20010425Ssam 20110425Ssam dotrace(tcpcb) 20210425Ssam register caddr_t tcpcb; 20310425Ssam { 204*33663Sbostic register struct tcp_debug *td; 20510425Ssam register int i; 20624910Skarels int prev_debx = tcp_debx; 20710425Ssam 208*33663Sbostic again: if (--tcp_debx < 0) 20924910Skarels tcp_debx = TCP_NDEBUG - 1; 21024910Skarels for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 21110425Ssam td = &tcp_debug[i]; 21210272Ssam if (tcpcb && td->td_tcb != tcpcb) 21310272Ssam continue; 2148382Ssam ntime = ntohl(td->td_time); 2156463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2166463Swnj &td->td_ti, td->td_req); 21724910Skarels if (i == tcp_debx) 21824910Skarels goto done; 2196463Swnj } 22024910Skarels for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 22110425Ssam td = &tcp_debug[i]; 22210272Ssam if (tcpcb && td->td_tcb != tcpcb) 22310272Ssam continue; 2248382Ssam ntime = ntohl(td->td_time); 2256463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2266463Swnj &td->td_ti, td->td_req); 2276463Swnj } 228*33663Sbostic done: if (follow) { 229*33663Sbostic prev_debx = tcp_debx + 1; 230*33663Sbostic if (prev_debx >= TCP_NDEBUG) 231*33663Sbostic prev_debx = 0; 232*33663Sbostic do { 233*33663Sbostic sleep(1); 234*33663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 235*33663Sbostic if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 236*33663Sbostic sizeof(tcp_debx)) { 237*33663Sbostic perror("trpt: tcp_debx"); 238*33663Sbostic exit(3); 239*33663Sbostic } 240*33663Sbostic } while (tcp_debx == prev_debx); 241*33663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 242*33663Sbostic if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 243*33663Sbostic sizeof(tcp_debug)) { 244*33663Sbostic perror("trpt: tcp_debug"); 24524910Skarels exit(3); 24624910Skarels } 247*33663Sbostic goto again; 24824910Skarels } 2496463Swnj } 2506463Swnj 2516463Swnj /* 2526463Swnj * Tcp debug routines 2536463Swnj */ 254*33663Sbostic /*ARGSUSED*/ 2556463Swnj tcp_trace(act, ostate, atp, tp, ti, req) 2566463Swnj short act, ostate; 2576463Swnj struct tcpcb *atp, *tp; 2586463Swnj struct tcpiphdr *ti; 2596463Swnj int req; 2606463Swnj { 2616463Swnj tcp_seq seq, ack; 262*33663Sbostic int flags, len, win, timer; 2636463Swnj 264*33663Sbostic printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], 265*33663Sbostic tanames[act]); 2666463Swnj switch (act) { 2676463Swnj case TA_INPUT: 2686463Swnj case TA_OUTPUT: 26914004Shelge case TA_DROP: 270*33663Sbostic if (aflag) 271*33663Sbostic printf("(src=%s,%u, dst=%s,%u)", inet_ntoa(ti->ti_src), 272*33663Sbostic ntohs(ti->ti_sport), inet_ntoa(ti->ti_dst), 273*33663Sbostic ntohs(ti->ti_dport)); 2746463Swnj seq = ti->ti_seq; 2756463Swnj ack = ti->ti_ack; 2766463Swnj len = ti->ti_len; 2776463Swnj win = ti->ti_win; 2786463Swnj if (act == TA_OUTPUT) { 2796463Swnj seq = ntohl(seq); 2806463Swnj ack = ntohl(ack); 2816463Swnj len = ntohs(len); 2826463Swnj win = ntohs(win); 2836463Swnj } 2846463Swnj if (act == TA_OUTPUT) 285*33663Sbostic len -= sizeof(struct tcphdr); 2866463Swnj if (len) 287*33663Sbostic printf("[%lx..%lx)", seq, seq + len); 2886463Swnj else 289*33663Sbostic printf("%lx", seq); 290*33663Sbostic printf("@%lx", ack); 2916463Swnj if (win) 29214282Shelge printf("(win=%x)", win); 2936463Swnj flags = ti->ti_flags; 2946463Swnj if (flags) { 295*33663Sbostic register char *cp = "<"; 296*33663Sbostic #define pf(flag) { \ 297*33663Sbostic if (ti->ti_flags&flag) \ 298*33663Sbostic printf("%s%s", cp, "f"); \ 299*33663Sbostic cp = ","; \ 300*33663Sbostic } 301*33663Sbostic pf(TH_SYN); 302*33663Sbostic pf(TH_ACK); 303*33663Sbostic pf(TH_FIN); 304*33663Sbostic pf(TH_RST); 305*33663Sbostic pf(TH_PUSH); 306*33663Sbostic pf(TH_URG); 3076463Swnj printf(">"); 3086463Swnj } 3096463Swnj break; 3106463Swnj case TA_USER: 3118382Ssam timer = req >> 8; 3128382Ssam req &= 0xff; 3138382Ssam printf("%s", prurequests[req]); 3148382Ssam if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 3158382Ssam printf("<%s>", tcptimers[timer]); 3166463Swnj break; 3176463Swnj } 3186463Swnj printf(" -> %s", tcpstates[tp->t_state]); 3196463Swnj /* print out internal state of tp !?! */ 3206463Swnj printf("\n"); 3216463Swnj if (sflag) { 322*33663Sbostic printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", 32310272Ssam tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 32410272Ssam tp->snd_max); 325*33663Sbostic printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, 32610272Ssam tp->snd_wl2, tp->snd_wnd); 3276463Swnj } 32810425Ssam /* print out timers? */ 32910425Ssam if (tflag) { 330*33663Sbostic register char *cp = "\t"; 33110425Ssam register int i; 33210425Ssam 33310425Ssam for (i = 0; i < TCPT_NTIMERS; i++) { 33410425Ssam if (tp->t_timer[i] == 0) 33510425Ssam continue; 33610425Ssam printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 33710425Ssam if (i == TCPT_REXMT) 33810425Ssam printf(" (t_rxtshft=%d)", tp->t_rxtshift); 33910425Ssam cp = ", "; 34010425Ssam } 34110425Ssam if (*cp != '\t') 34210425Ssam putchar('\n'); 34310425Ssam } 3446463Swnj } 3456463Swnj 346*33663Sbostic numeric(c1, c2) 347*33663Sbostic caddr_t *c1, *c2; 3486463Swnj { 349*33663Sbostic return(*c1 - *c2); 3506463Swnj } 35110425Ssam 352*33663Sbostic klseek(fd, base, off) 353*33663Sbostic int fd, off; 354*33663Sbostic off_t base; 35510425Ssam { 356*33663Sbostic off_t lseek(); 357*33663Sbostic 358*33663Sbostic if (kflag) { /* get kernel pte */ 359*33663Sbostic base &= ~KERNBASE; 360*33663Sbostic base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 361*33663Sbostic } 362*33663Sbostic (void)lseek(fd, base, off); 36310425Ssam } 364