122014Sdist /* 233663Sbostic * Copyright (c) 1983, 1988 Regents of the University of California. 334939Sbostic * All rights reserved. 434939Sbostic * 542829Sbostic * %sccs.include.redist.c% 622014Sdist */ 722014Sdist 86463Swnj #ifndef lint 922014Sdist char copyright[] = 1033663Sbostic "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ 1122014Sdist All rights reserved.\n"; 1233663Sbostic #endif /* not lint */ 136463Swnj 1422014Sdist #ifndef lint 15*52255Sbostic static char sccsid[] = "@(#)trpt.c 5.15 (Berkeley) 01/28/92"; 1633663Sbostic #endif /* not lint */ 1722014Sdist 1850356Skarels #include <sys/param.h> 1950356Skarels #if BSD >= 199103 2050356Skarels #define NEWVM 2150356Skarels #endif 2250356Skarels #ifndef NEWVM 2333663Sbostic #include <machine/pte.h> 2433663Sbostic #include <sys/vmmac.h> 2550356Skarels #endif 266463Swnj #include <sys/socket.h> 276463Swnj #include <sys/socketvar.h> 286463Swnj #define PRUREQUESTS 296463Swnj #include <sys/protosw.h> 3033663Sbostic #include <sys/file.h> 319202Ssam 326463Swnj #include <net/route.h> 336463Swnj #include <net/if.h> 349202Ssam 359202Ssam #include <netinet/in.h> 369202Ssam #include <netinet/in_systm.h> 379202Ssam #include <netinet/ip.h> 3840893Ssklower #include <netinet/in_pcb.h> 399202Ssam #include <netinet/ip_var.h> 409202Ssam #include <netinet/tcp.h> 416463Swnj #define TCPSTATES 429202Ssam #include <netinet/tcp_fsm.h> 439202Ssam #include <netinet/tcp_seq.h> 446463Swnj #define TCPTIMERS 459202Ssam #include <netinet/tcp_timer.h> 469202Ssam #include <netinet/tcp_var.h> 479202Ssam #include <netinet/tcpip.h> 486463Swnj #define TANAMES 499202Ssam #include <netinet/tcp_debug.h> 509202Ssam 5115252Ssam #include <arpa/inet.h> 5215252Ssam 5310272Ssam #include <stdio.h> 546463Swnj #include <errno.h> 556463Swnj #include <nlist.h> 5637984Sbostic #include <paths.h> 576463Swnj 5833663Sbostic struct nlist nl[] = { 5933663Sbostic #define N_TCP_DEBUG 0 606463Swnj { "_tcp_debug" }, 6133663Sbostic #define N_TCP_DEBX 1 626463Swnj { "_tcp_debx" }, 6350356Skarels #ifndef NEWVM 6433663Sbostic #define N_SYSMAP 2 6533663Sbostic { "_Sysmap" }, 6633663Sbostic #define N_SYSSIZE 3 6733663Sbostic { "_Syssize" }, 6850356Skarels #endif 6933663Sbostic { "" }, 706463Swnj }; 716463Swnj 7250356Skarels #ifndef NEWVM 7335690Sbostic static struct pte *Sysmap; 7450356Skarels #endif 7535690Sbostic static caddr_t tcp_pcbs[TCP_NDEBUG]; 7635690Sbostic static n_time ntime; 7735690Sbostic static int aflag, kflag, memf, follow, sflag, tflag; 7833663Sbostic 796463Swnj main(argc, argv) 806463Swnj int argc; 816463Swnj char **argv; 826463Swnj { 8333663Sbostic extern char *optarg; 8433663Sbostic extern int optind; 8533663Sbostic int ch, i, jflag, npcbs, numeric(); 8633663Sbostic char *system, *core, *malloc(); 8733663Sbostic off_t lseek(); 886463Swnj 8933663Sbostic jflag = npcbs = 0; 9033663Sbostic while ((ch = getopt(argc, argv, "afjp:st")) != EOF) 9150356Skarels switch (ch) { 9233663Sbostic case 'a': 9333663Sbostic ++aflag; 9433663Sbostic break; 9533663Sbostic case 'f': 9633663Sbostic ++follow; 9733663Sbostic setlinebuf(stdout); 9833663Sbostic break; 9933663Sbostic case 'j': 10033663Sbostic ++jflag; 10133663Sbostic break; 10233663Sbostic case 'p': 10333663Sbostic if (npcbs >= TCP_NDEBUG) { 10433663Sbostic fputs("trpt: too many pcb's specified\n", 10533663Sbostic stderr); 10633663Sbostic exit(1); 10733663Sbostic } 10833663Sbostic (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); 10933663Sbostic break; 11033663Sbostic case 's': 11133663Sbostic ++sflag; 11233663Sbostic break; 11333663Sbostic case 't': 11433663Sbostic ++tflag; 11533663Sbostic break; 11633663Sbostic case '?': 11733663Sbostic default: 11837308Sbostic (void)fprintf(stderr, 11937308Sbostic "usage: trpt [-afjst] [-p hex-address] [system [core]]\n"); 12010272Ssam exit(1); 12110272Ssam } 12233663Sbostic argc -= optind; 12333663Sbostic argv += optind; 12433663Sbostic 12537308Sbostic core = _PATH_KMEM; 12610272Ssam if (argc > 0) { 12710272Ssam system = *argv; 12810272Ssam argc--, argv++; 12933663Sbostic if (argc > 0) { 13033663Sbostic core = *argv; 13133663Sbostic argc--, argv++; 13233663Sbostic ++kflag; 13333663Sbostic } 134*52255Sbostic /* 135*52255Sbostic * Discard setgid privileges if not the running kernel so that 136*52255Sbostic * bad guys can't print interesting stuff from kernel memory. 137*52255Sbostic */ 138*52255Sbostic setgid(getgid()); 13910272Ssam } 14033663Sbostic else 14137308Sbostic system = _PATH_UNIX; 14233663Sbostic 14333663Sbostic if (nlist(system, nl) < 0 || !nl[0].n_value) { 14410272Ssam fprintf(stderr, "trpt: %s: no namelist\n", system); 1456463Swnj exit(1); 1466463Swnj } 14733663Sbostic if ((memf = open(core, O_RDONLY)) < 0) { 14833663Sbostic perror(core); 14910272Ssam exit(2); 15010272Ssam } 15133663Sbostic if (kflag) { 15250356Skarels #ifdef NEWVM 15350356Skarels fputs("trpt: can't do core files yet\n", stderr); 15450356Skarels exit(1); 15550356Skarels #else 15633663Sbostic off_t off; 15733663Sbostic 15833663Sbostic Sysmap = (struct pte *) 15933663Sbostic malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 16033663Sbostic if (!Sysmap) { 16150356Skarels fputs("trpt: can't get memory for Sysmap.\n", stderr); 16233663Sbostic exit(1); 16333663Sbostic } 16433663Sbostic off = nl[N_SYSMAP].n_value & ~KERNBASE; 16533663Sbostic (void)lseek(memf, off, L_SET); 16633663Sbostic (void)read(memf, (char *)Sysmap, 16733663Sbostic (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 16850356Skarels #endif 1696463Swnj } 17033663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 17133663Sbostic if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 17233663Sbostic sizeof(tcp_debx)) { 17333663Sbostic perror("trpt: tcp_debx"); 17410272Ssam exit(3); 17510272Ssam } 17633663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 17733663Sbostic if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 17833663Sbostic sizeof(tcp_debug)) { 17933663Sbostic perror("trpt: tcp_debug"); 18010272Ssam exit(3); 18110272Ssam } 18210425Ssam /* 18310425Ssam * If no control blocks have been specified, figure 18410425Ssam * out how many distinct one we have and summarize 18510425Ssam * them in tcp_pcbs for sorting the trace records 18610425Ssam * below. 18710425Ssam */ 18833663Sbostic if (!npcbs) { 18910425Ssam for (i = 0; i < TCP_NDEBUG; i++) { 19033663Sbostic register struct tcp_debug *td = &tcp_debug[i]; 19110425Ssam register int j; 1928382Ssam 19310425Ssam if (td->td_tcb == 0) 19410425Ssam continue; 19510425Ssam for (j = 0; j < npcbs; j++) 19610425Ssam if (tcp_pcbs[j] == td->td_tcb) 19710425Ssam break; 19810425Ssam if (j >= npcbs) 19910425Ssam tcp_pcbs[npcbs++] = td->td_tcb; 20010425Ssam } 20133663Sbostic if (!npcbs) 20233663Sbostic exit(0); 20310425Ssam } 20433663Sbostic qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 20510425Ssam if (jflag) { 20633663Sbostic for (i = 0;;) { 20733663Sbostic printf("%x", (int)tcp_pcbs[i]); 20833663Sbostic if (++i == npcbs) 20933663Sbostic break; 21033663Sbostic fputs(", ", stdout); 21110425Ssam } 21233663Sbostic putchar('\n'); 21310425Ssam } 21433663Sbostic else for (i = 0; i < npcbs; i++) { 21533663Sbostic printf("\n%x:\n", (int)tcp_pcbs[i]); 21610425Ssam dotrace(tcp_pcbs[i]); 21710425Ssam } 21810425Ssam exit(0); 21910425Ssam } 22010425Ssam 22110425Ssam dotrace(tcpcb) 22210425Ssam register caddr_t tcpcb; 22310425Ssam { 22433663Sbostic register struct tcp_debug *td; 22510425Ssam register int i; 22624910Skarels int prev_debx = tcp_debx; 22710425Ssam 22833663Sbostic again: if (--tcp_debx < 0) 22924910Skarels tcp_debx = TCP_NDEBUG - 1; 23024910Skarels for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 23110425Ssam td = &tcp_debug[i]; 23210272Ssam if (tcpcb && td->td_tcb != tcpcb) 23310272Ssam continue; 2348382Ssam ntime = ntohl(td->td_time); 2356463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2366463Swnj &td->td_ti, td->td_req); 23724910Skarels if (i == tcp_debx) 23824910Skarels goto done; 2396463Swnj } 24024910Skarels for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 24110425Ssam td = &tcp_debug[i]; 24210272Ssam if (tcpcb && td->td_tcb != tcpcb) 24310272Ssam continue; 2448382Ssam ntime = ntohl(td->td_time); 2456463Swnj tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2466463Swnj &td->td_ti, td->td_req); 2476463Swnj } 24833663Sbostic done: if (follow) { 24933663Sbostic prev_debx = tcp_debx + 1; 25033663Sbostic if (prev_debx >= TCP_NDEBUG) 25133663Sbostic prev_debx = 0; 25233663Sbostic do { 25333663Sbostic sleep(1); 25433663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 25533663Sbostic if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 25633663Sbostic sizeof(tcp_debx)) { 25733663Sbostic perror("trpt: tcp_debx"); 25833663Sbostic exit(3); 25933663Sbostic } 26033663Sbostic } while (tcp_debx == prev_debx); 26133663Sbostic (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 26233663Sbostic if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 26333663Sbostic sizeof(tcp_debug)) { 26433663Sbostic perror("trpt: tcp_debug"); 26524910Skarels exit(3); 26624910Skarels } 26733663Sbostic goto again; 26824910Skarels } 2696463Swnj } 2706463Swnj 2716463Swnj /* 2726463Swnj * Tcp debug routines 2736463Swnj */ 27433663Sbostic /*ARGSUSED*/ 2756463Swnj tcp_trace(act, ostate, atp, tp, ti, req) 2766463Swnj short act, ostate; 2776463Swnj struct tcpcb *atp, *tp; 2786463Swnj struct tcpiphdr *ti; 2796463Swnj int req; 2806463Swnj { 2816463Swnj tcp_seq seq, ack; 28233663Sbostic int flags, len, win, timer; 2836463Swnj 28433663Sbostic printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], 28533663Sbostic tanames[act]); 2866463Swnj switch (act) { 2876463Swnj case TA_INPUT: 2886463Swnj case TA_OUTPUT: 28914004Shelge case TA_DROP: 29038432Ssam if (aflag) { 29138432Ssam printf("(src=%s,%u, ", 29238432Ssam inet_ntoa(ti->ti_src), ntohs(ti->ti_sport)); 29338432Ssam printf("dst=%s,%u)", 29438432Ssam inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport)); 29538432Ssam } 2966463Swnj seq = ti->ti_seq; 2976463Swnj ack = ti->ti_ack; 2986463Swnj len = ti->ti_len; 2996463Swnj win = ti->ti_win; 3006463Swnj if (act == TA_OUTPUT) { 3016463Swnj seq = ntohl(seq); 3026463Swnj ack = ntohl(ack); 3036463Swnj len = ntohs(len); 3046463Swnj win = ntohs(win); 3056463Swnj } 3066463Swnj if (act == TA_OUTPUT) 30733663Sbostic len -= sizeof(struct tcphdr); 3086463Swnj if (len) 30933663Sbostic printf("[%lx..%lx)", seq, seq + len); 3106463Swnj else 31133663Sbostic printf("%lx", seq); 31233663Sbostic printf("@%lx", ack); 3136463Swnj if (win) 31414282Shelge printf("(win=%x)", win); 3156463Swnj flags = ti->ti_flags; 31638433Ssam if (flags) { 31738433Ssam register char *cp = "<"; 31838464Sbostic #define pf(flag, string) { \ 31938464Sbostic if (ti->ti_flags&flag) { \ 32038464Sbostic (void)printf("%s%s", cp, string); \ 32138464Sbostic cp = ","; \ 32238464Sbostic } \ 32338464Sbostic } 32438464Sbostic pf(TH_SYN, "SYN"); 32538464Sbostic pf(TH_ACK, "ACK"); 32638464Sbostic pf(TH_FIN, "FIN"); 32738464Sbostic pf(TH_RST, "RST"); 32838464Sbostic pf(TH_PUSH, "PUSH"); 32938464Sbostic pf(TH_URG, "URG"); 3306463Swnj printf(">"); 3316463Swnj } 3326463Swnj break; 3336463Swnj case TA_USER: 3348382Ssam timer = req >> 8; 3358382Ssam req &= 0xff; 3368382Ssam printf("%s", prurequests[req]); 3378382Ssam if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 3388382Ssam printf("<%s>", tcptimers[timer]); 3396463Swnj break; 3406463Swnj } 3416463Swnj printf(" -> %s", tcpstates[tp->t_state]); 3426463Swnj /* print out internal state of tp !?! */ 3436463Swnj printf("\n"); 3446463Swnj if (sflag) { 34533663Sbostic printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", 34610272Ssam tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 34710272Ssam tp->snd_max); 34833663Sbostic printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, 34910272Ssam tp->snd_wl2, tp->snd_wnd); 3506463Swnj } 35110425Ssam /* print out timers? */ 35210425Ssam if (tflag) { 35333663Sbostic register char *cp = "\t"; 35410425Ssam register int i; 35510425Ssam 35610425Ssam for (i = 0; i < TCPT_NTIMERS; i++) { 35710425Ssam if (tp->t_timer[i] == 0) 35810425Ssam continue; 35910425Ssam printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 36010425Ssam if (i == TCPT_REXMT) 36110425Ssam printf(" (t_rxtshft=%d)", tp->t_rxtshift); 36210425Ssam cp = ", "; 36310425Ssam } 36410425Ssam if (*cp != '\t') 36510425Ssam putchar('\n'); 36610425Ssam } 3676463Swnj } 3686463Swnj 36933663Sbostic numeric(c1, c2) 37033663Sbostic caddr_t *c1, *c2; 3716463Swnj { 37233663Sbostic return(*c1 - *c2); 3736463Swnj } 37410425Ssam 37533663Sbostic klseek(fd, base, off) 37633663Sbostic int fd, off; 37733663Sbostic off_t base; 37810425Ssam { 37933663Sbostic off_t lseek(); 38033663Sbostic 38150356Skarels #ifndef NEWVM 38233663Sbostic if (kflag) { /* get kernel pte */ 38333663Sbostic base &= ~KERNBASE; 38433663Sbostic base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 38533663Sbostic } 38650356Skarels #endif 38733663Sbostic (void)lseek(fd, base, off); 38810425Ssam } 389