trpt.c revision 14544
11553Srgrimes/* 21553Srgrimes * Copyright (c) 1983, 1988, 1993 31553Srgrimes * The Regents of the University of California. All rights reserved. 41553Srgrimes * 51553Srgrimes * Redistribution and use in source and binary forms, with or without 61553Srgrimes * modification, are permitted provided that the following conditions 71553Srgrimes * are met: 81553Srgrimes * 1. Redistributions of source code must retain the above copyright 91553Srgrimes * notice, this list of conditions and the following disclaimer. 101553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111553Srgrimes * notice, this list of conditions and the following disclaimer in the 121553Srgrimes * documentation and/or other materials provided with the distribution. 131553Srgrimes * 3. All advertising materials mentioning features or use of this software 141553Srgrimes * must display the following acknowledgement: 151553Srgrimes * This product includes software developed by the University of 161553Srgrimes * California, Berkeley and its contributors. 171553Srgrimes * 4. Neither the name of the University nor the names of its contributors 181553Srgrimes * may be used to endorse or promote products derived from this software 191553Srgrimes * without specific prior written permission. 201553Srgrimes * 211553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221553Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231553Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241553Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251553Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261553Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271553Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281553Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291553Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301553Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311553Srgrimes * SUCH DAMAGE. 321553Srgrimes */ 331553Srgrimes 341553Srgrimes#ifndef lint 351553Srgrimesstatic char copyright[] = 361553Srgrimes"@(#) Copyright (c) 1983, 1988, 1993\n\ 371553Srgrimes The Regents of the University of California. All rights reserved.\n"; 381553Srgrimes#endif /* not lint */ 391553Srgrimes 401553Srgrimes#ifndef lint 411553Srgrimesstatic char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93"; 421553Srgrimes#endif /* not lint */ 431553Srgrimes 441553Srgrimes#include <sys/param.h> 4514544Sdg#include <sys/queue.h> 461553Srgrimes#if BSD >= 199103 471553Srgrimes#define NEWVM 481553Srgrimes#endif 491553Srgrimes#ifndef NEWVM 501553Srgrimes#include <machine/pte.h> 511553Srgrimes#include <sys/vmmac.h> 521553Srgrimes#endif 531553Srgrimes#include <sys/socket.h> 541553Srgrimes#include <sys/socketvar.h> 551553Srgrimes#define PRUREQUESTS 561553Srgrimes#include <sys/protosw.h> 571553Srgrimes#include <sys/file.h> 581553Srgrimes 591553Srgrimes#include <net/route.h> 601553Srgrimes#include <net/if.h> 611553Srgrimes 621553Srgrimes#include <netinet/in.h> 631553Srgrimes#include <netinet/in_systm.h> 641553Srgrimes#include <netinet/ip.h> 651553Srgrimes#include <netinet/ip_var.h> 661553Srgrimes#include <netinet/tcp.h> 671553Srgrimes#define TCPSTATES 681553Srgrimes#include <netinet/tcp_fsm.h> 691553Srgrimes#include <netinet/tcp_seq.h> 701553Srgrimes#define TCPTIMERS 711553Srgrimes#include <netinet/tcp_timer.h> 721553Srgrimes#include <netinet/tcp_var.h> 731553Srgrimes#include <netinet/tcpip.h> 741553Srgrimes#define TANAMES 751553Srgrimes#include <netinet/tcp_debug.h> 761553Srgrimes 771553Srgrimes#include <arpa/inet.h> 781553Srgrimes 791553Srgrimes#include <stdio.h> 801553Srgrimes#include <errno.h> 811553Srgrimes#include <nlist.h> 821553Srgrimes#include <paths.h> 831553Srgrimes 841553Srgrimesstruct nlist nl[] = { 851553Srgrimes#define N_TCP_DEBUG 0 861553Srgrimes { "_tcp_debug" }, 871553Srgrimes#define N_TCP_DEBX 1 881553Srgrimes { "_tcp_debx" }, 891553Srgrimes#ifndef NEWVM 901553Srgrimes#define N_SYSMAP 2 911553Srgrimes { "_Sysmap" }, 921553Srgrimes#define N_SYSSIZE 3 931553Srgrimes { "_Syssize" }, 941553Srgrimes#endif 951553Srgrimes { "" }, 961553Srgrimes}; 971553Srgrimes 981553Srgrimes#ifndef NEWVM 991553Srgrimesstatic struct pte *Sysmap; 1001553Srgrimes#endif 1011553Srgrimesstatic caddr_t tcp_pcbs[TCP_NDEBUG]; 1021553Srgrimesstatic n_time ntime; 1031553Srgrimesstatic int aflag, kflag, memf, follow, sflag, tflag; 1041553Srgrimes 1051553Srgrimesmain(argc, argv) 1061553Srgrimes int argc; 1071553Srgrimes char **argv; 1081553Srgrimes{ 1091553Srgrimes extern char *optarg; 1101553Srgrimes extern int optind; 1111553Srgrimes int ch, i, jflag, npcbs, numeric(); 1121553Srgrimes char *system, *core, *malloc(); 1131553Srgrimes off_t lseek(); 1141553Srgrimes 1151553Srgrimes jflag = npcbs = 0; 1161553Srgrimes while ((ch = getopt(argc, argv, "afjp:st")) != EOF) 1171553Srgrimes switch (ch) { 1181553Srgrimes case 'a': 1191553Srgrimes ++aflag; 1201553Srgrimes break; 1211553Srgrimes case 'f': 1221553Srgrimes ++follow; 1231553Srgrimes setlinebuf(stdout); 1241553Srgrimes break; 1251553Srgrimes case 'j': 1261553Srgrimes ++jflag; 1271553Srgrimes break; 1281553Srgrimes case 'p': 1291553Srgrimes if (npcbs >= TCP_NDEBUG) { 1301553Srgrimes fputs("trpt: too many pcb's specified\n", 1311553Srgrimes stderr); 1321553Srgrimes exit(1); 1331553Srgrimes } 1341553Srgrimes (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); 1351553Srgrimes break; 1361553Srgrimes case 's': 1371553Srgrimes ++sflag; 1381553Srgrimes break; 1391553Srgrimes case 't': 1401553Srgrimes ++tflag; 1411553Srgrimes break; 1421553Srgrimes case '?': 1431553Srgrimes default: 1441553Srgrimes (void)fprintf(stderr, 1451553Srgrimes"usage: trpt [-afjst] [-p hex-address] [system [core]]\n"); 1461553Srgrimes exit(1); 1471553Srgrimes } 1481553Srgrimes argc -= optind; 1491553Srgrimes argv += optind; 1501553Srgrimes 1511553Srgrimes core = _PATH_KMEM; 1521553Srgrimes if (argc > 0) { 1531553Srgrimes system = *argv; 1541553Srgrimes argc--, argv++; 1551553Srgrimes if (argc > 0) { 1561553Srgrimes core = *argv; 1571553Srgrimes argc--, argv++; 1581553Srgrimes ++kflag; 1591553Srgrimes } 1601553Srgrimes /* 1611553Srgrimes * Discard setgid privileges if not the running kernel so that 1621553Srgrimes * bad guys can't print interesting stuff from kernel memory. 1631553Srgrimes */ 1641553Srgrimes setgid(getgid()); 1651553Srgrimes } 1661553Srgrimes else 1673041Swollman system = (char *)getbootfile(); 1681553Srgrimes 1691553Srgrimes if (nlist(system, nl) < 0 || !nl[0].n_value) { 1701553Srgrimes fprintf(stderr, "trpt: %s: no namelist\n", system); 1711553Srgrimes exit(1); 1721553Srgrimes } 1731553Srgrimes if ((memf = open(core, O_RDONLY)) < 0) { 1741553Srgrimes perror(core); 1751553Srgrimes exit(2); 1761553Srgrimes } 1771553Srgrimes if (kflag) { 1781553Srgrimes#ifdef NEWVM 1791553Srgrimes fputs("trpt: can't do core files yet\n", stderr); 1801553Srgrimes exit(1); 1811553Srgrimes#else 1821553Srgrimes off_t off; 1831553Srgrimes 1841553Srgrimes Sysmap = (struct pte *) 1851553Srgrimes malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 1861553Srgrimes if (!Sysmap) { 1871553Srgrimes fputs("trpt: can't get memory for Sysmap.\n", stderr); 1881553Srgrimes exit(1); 1891553Srgrimes } 1901553Srgrimes off = nl[N_SYSMAP].n_value & ~KERNBASE; 1911553Srgrimes (void)lseek(memf, off, L_SET); 1921553Srgrimes (void)read(memf, (char *)Sysmap, 1931553Srgrimes (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); 1941553Srgrimes#endif 1951553Srgrimes } 1961553Srgrimes (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 1971553Srgrimes if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 1981553Srgrimes sizeof(tcp_debx)) { 1991553Srgrimes perror("trpt: tcp_debx"); 2001553Srgrimes exit(3); 2011553Srgrimes } 2021553Srgrimes (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 2031553Srgrimes if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 2041553Srgrimes sizeof(tcp_debug)) { 2051553Srgrimes perror("trpt: tcp_debug"); 2061553Srgrimes exit(3); 2071553Srgrimes } 2081553Srgrimes /* 2091553Srgrimes * If no control blocks have been specified, figure 2101553Srgrimes * out how many distinct one we have and summarize 2111553Srgrimes * them in tcp_pcbs for sorting the trace records 2121553Srgrimes * below. 2131553Srgrimes */ 2141553Srgrimes if (!npcbs) { 2151553Srgrimes for (i = 0; i < TCP_NDEBUG; i++) { 2161553Srgrimes register struct tcp_debug *td = &tcp_debug[i]; 2171553Srgrimes register int j; 2181553Srgrimes 2191553Srgrimes if (td->td_tcb == 0) 2201553Srgrimes continue; 2211553Srgrimes for (j = 0; j < npcbs; j++) 2221553Srgrimes if (tcp_pcbs[j] == td->td_tcb) 2231553Srgrimes break; 2241553Srgrimes if (j >= npcbs) 2251553Srgrimes tcp_pcbs[npcbs++] = td->td_tcb; 2261553Srgrimes } 2271553Srgrimes if (!npcbs) 2281553Srgrimes exit(0); 2291553Srgrimes } 2301553Srgrimes qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 2311553Srgrimes if (jflag) { 2321553Srgrimes for (i = 0;;) { 2331553Srgrimes printf("%x", (int)tcp_pcbs[i]); 2341553Srgrimes if (++i == npcbs) 2351553Srgrimes break; 2361553Srgrimes fputs(", ", stdout); 2371553Srgrimes } 2381553Srgrimes putchar('\n'); 2391553Srgrimes } 2401553Srgrimes else for (i = 0; i < npcbs; i++) { 2411553Srgrimes printf("\n%x:\n", (int)tcp_pcbs[i]); 2421553Srgrimes dotrace(tcp_pcbs[i]); 2431553Srgrimes } 2441553Srgrimes exit(0); 2451553Srgrimes} 2461553Srgrimes 2471553Srgrimesdotrace(tcpcb) 2481553Srgrimes register caddr_t tcpcb; 2491553Srgrimes{ 2501553Srgrimes register struct tcp_debug *td; 2511553Srgrimes register int i; 2521553Srgrimes int prev_debx = tcp_debx; 2531553Srgrimes 2541553Srgrimesagain: if (--tcp_debx < 0) 2551553Srgrimes tcp_debx = TCP_NDEBUG - 1; 2561553Srgrimes for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 2571553Srgrimes td = &tcp_debug[i]; 2581553Srgrimes if (tcpcb && td->td_tcb != tcpcb) 2591553Srgrimes continue; 2601553Srgrimes ntime = ntohl(td->td_time); 2611553Srgrimes tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2621553Srgrimes &td->td_ti, td->td_req); 2631553Srgrimes if (i == tcp_debx) 2641553Srgrimes goto done; 2651553Srgrimes } 2661553Srgrimes for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 2671553Srgrimes td = &tcp_debug[i]; 2681553Srgrimes if (tcpcb && td->td_tcb != tcpcb) 2691553Srgrimes continue; 2701553Srgrimes ntime = ntohl(td->td_time); 2711553Srgrimes tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, 2721553Srgrimes &td->td_ti, td->td_req); 2731553Srgrimes } 2741553Srgrimesdone: if (follow) { 2751553Srgrimes prev_debx = tcp_debx + 1; 2761553Srgrimes if (prev_debx >= TCP_NDEBUG) 2771553Srgrimes prev_debx = 0; 2781553Srgrimes do { 2791553Srgrimes sleep(1); 2801553Srgrimes (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 2811553Srgrimes if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 2821553Srgrimes sizeof(tcp_debx)) { 2831553Srgrimes perror("trpt: tcp_debx"); 2841553Srgrimes exit(3); 2851553Srgrimes } 2861553Srgrimes } while (tcp_debx == prev_debx); 2871553Srgrimes (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 2881553Srgrimes if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 2891553Srgrimes sizeof(tcp_debug)) { 2901553Srgrimes perror("trpt: tcp_debug"); 2911553Srgrimes exit(3); 2921553Srgrimes } 2931553Srgrimes goto again; 2941553Srgrimes } 2951553Srgrimes} 2961553Srgrimes 2971553Srgrimes/* 2981553Srgrimes * Tcp debug routines 2991553Srgrimes */ 3001553Srgrimes/*ARGSUSED*/ 3011553Srgrimestcp_trace(act, ostate, atp, tp, ti, req) 3021553Srgrimes short act, ostate; 3031553Srgrimes struct tcpcb *atp, *tp; 3041553Srgrimes struct tcpiphdr *ti; 3051553Srgrimes int req; 3061553Srgrimes{ 3071553Srgrimes tcp_seq seq, ack; 3081553Srgrimes int flags, len, win, timer; 3091553Srgrimes 3101553Srgrimes printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], 3111553Srgrimes tanames[act]); 3121553Srgrimes switch (act) { 3131553Srgrimes case TA_INPUT: 3141553Srgrimes case TA_OUTPUT: 3151553Srgrimes case TA_DROP: 3161553Srgrimes if (aflag) { 3171553Srgrimes printf("(src=%s,%u, ", 3181553Srgrimes inet_ntoa(ti->ti_src), ntohs(ti->ti_sport)); 3191553Srgrimes printf("dst=%s,%u)", 3201553Srgrimes inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport)); 3211553Srgrimes } 3221553Srgrimes seq = ti->ti_seq; 3231553Srgrimes ack = ti->ti_ack; 3241553Srgrimes len = ti->ti_len; 3251553Srgrimes win = ti->ti_win; 3261553Srgrimes if (act == TA_OUTPUT) { 3271553Srgrimes seq = ntohl(seq); 3281553Srgrimes ack = ntohl(ack); 3291553Srgrimes len = ntohs(len); 3301553Srgrimes win = ntohs(win); 3311553Srgrimes } 3321553Srgrimes if (act == TA_OUTPUT) 3331553Srgrimes len -= sizeof(struct tcphdr); 3341553Srgrimes if (len) 3351553Srgrimes printf("[%lx..%lx)", seq, seq + len); 3361553Srgrimes else 3371553Srgrimes printf("%lx", seq); 3381553Srgrimes printf("@%lx", ack); 3391553Srgrimes if (win) 3401553Srgrimes printf("(win=%x)", win); 3411553Srgrimes flags = ti->ti_flags; 3421553Srgrimes if (flags) { 3431553Srgrimes register char *cp = "<"; 3441553Srgrimes#define pf(flag, string) { \ 3451553Srgrimes if (ti->ti_flags&flag) { \ 3461553Srgrimes (void)printf("%s%s", cp, string); \ 3471553Srgrimes cp = ","; \ 3481553Srgrimes } \ 3491553Srgrimes} 3501553Srgrimes pf(TH_SYN, "SYN"); 3511553Srgrimes pf(TH_ACK, "ACK"); 3521553Srgrimes pf(TH_FIN, "FIN"); 3531553Srgrimes pf(TH_RST, "RST"); 3541553Srgrimes pf(TH_PUSH, "PUSH"); 3551553Srgrimes pf(TH_URG, "URG"); 3561553Srgrimes printf(">"); 3571553Srgrimes } 3581553Srgrimes break; 3591553Srgrimes case TA_USER: 3601553Srgrimes timer = req >> 8; 3611553Srgrimes req &= 0xff; 3621553Srgrimes printf("%s", prurequests[req]); 3631553Srgrimes if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 3641553Srgrimes printf("<%s>", tcptimers[timer]); 3651553Srgrimes break; 3661553Srgrimes } 3671553Srgrimes printf(" -> %s", tcpstates[tp->t_state]); 3681553Srgrimes /* print out internal state of tp !?! */ 3691553Srgrimes printf("\n"); 3701553Srgrimes if (sflag) { 3711553Srgrimes printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", 3721553Srgrimes tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 3731553Srgrimes tp->snd_max); 3741553Srgrimes printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, 3751553Srgrimes tp->snd_wl2, tp->snd_wnd); 3761553Srgrimes } 3771553Srgrimes /* print out timers? */ 3781553Srgrimes if (tflag) { 3791553Srgrimes register char *cp = "\t"; 3801553Srgrimes register int i; 3811553Srgrimes 3821553Srgrimes for (i = 0; i < TCPT_NTIMERS; i++) { 3831553Srgrimes if (tp->t_timer[i] == 0) 3841553Srgrimes continue; 3851553Srgrimes printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 3861553Srgrimes if (i == TCPT_REXMT) 3871553Srgrimes printf(" (t_rxtshft=%d)", tp->t_rxtshift); 3881553Srgrimes cp = ", "; 3891553Srgrimes } 3901553Srgrimes if (*cp != '\t') 3911553Srgrimes putchar('\n'); 3921553Srgrimes } 3931553Srgrimes} 3941553Srgrimes 3951553Srgrimesnumeric(c1, c2) 3961553Srgrimes caddr_t *c1, *c2; 3971553Srgrimes{ 3981553Srgrimes return(*c1 - *c2); 3991553Srgrimes} 4001553Srgrimes 4011553Srgrimesklseek(fd, base, off) 4021553Srgrimes int fd, off; 4031553Srgrimes off_t base; 4041553Srgrimes{ 4051553Srgrimes off_t lseek(); 4061553Srgrimes 4071553Srgrimes#ifndef NEWVM 4081553Srgrimes if (kflag) { /* get kernel pte */ 4091553Srgrimes base &= ~KERNBASE; 4101553Srgrimes base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); 4111553Srgrimes } 4121553Srgrimes#endif 4131553Srgrimes (void)lseek(fd, base, off); 4141553Srgrimes} 415