trpt.c revision 73732
1204076Spjd/* 2204076Spjd * Copyright (c) 1983, 1988, 1993 3219351Spjd * The Regents of the University of California. All rights reserved. 4204076Spjd * 5204076Spjd * Redistribution and use in source and binary forms, with or without 6204076Spjd * modification, are permitted provided that the following conditions 7204076Spjd * are met: 8204076Spjd * 1. Redistributions of source code must retain the above copyright 9204076Spjd * notice, this list of conditions and the following disclaimer. 10204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 11204076Spjd * notice, this list of conditions and the following disclaimer in the 12204076Spjd * documentation and/or other materials provided with the distribution. 13204076Spjd * 3. All advertising materials mentioning features or use of this software 14204076Spjd * must display the following acknowledgement: 15204076Spjd * This product includes software developed by the University of 16204076Spjd * California, Berkeley and its contributors. 17204076Spjd * 4. Neither the name of the University nor the names of its contributors 18204076Spjd * may be used to endorse or promote products derived from this software 19204076Spjd * without specific prior written permission. 20204076Spjd * 21204076Spjd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31204076Spjd * SUCH DAMAGE. 32204076Spjd */ 33204076Spjd 34204076Spjd#ifndef lint 35204076Spjdstatic const char copyright[] = 36204076Spjd"@(#) Copyright (c) 1983, 1988, 1993\n\ 37204076Spjd The Regents of the University of California. All rights reserved.\n"; 38204076Spjd#endif /* not lint */ 39204076Spjd 40204076Spjd#ifndef lint 41204076Spjd#if 0 42204076Spjdstatic char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93"; 43204076Spjd#endif 44204076Spjdstatic const char rcsid[] = 45204076Spjd "$FreeBSD: head/usr.sbin/trpt/trpt.c 73732 2001-03-05 12:13:12Z dwmalone $"; 46204076Spjd#endif /* not lint */ 47211982Spjd 48204076Spjd#include <sys/param.h> 49204076Spjd#include <sys/queue.h> 50204076Spjd#include <sys/socket.h> 51204076Spjd#include <sys/socketvar.h> 52204076Spjd#define PRUREQUESTS 53204076Spjd#include <sys/protosw.h> 54204076Spjd#include <sys/file.h> 55204076Spjd#include <sys/time.h> 56204076Spjd 57204076Spjd#include <net/route.h> 58204076Spjd#include <net/if.h> 59212038Spjd 60204076Spjd#include <netinet/in.h> 61204076Spjd#include <netinet/in_systm.h> 62204076Spjd#include <netinet/ip.h> 63211886Spjd#ifdef INET6 64204076Spjd#include <netinet/ip6.h> 65204076Spjd#endif 66204076Spjd#include <netinet/ip_var.h> 67246922Spjd#include <netinet/tcp.h> 68204076Spjd#define TCPSTATES 69204076Spjd#include <netinet/tcp_fsm.h> 70204076Spjd#include <netinet/tcp_seq.h> 71210886Spjd#define TCPTIMERS 72210886Spjd#include <netinet/tcp_timer.h> 73210886Spjd#include <netinet/tcp_var.h> 74204076Spjd#include <netinet/tcpip.h> 75204076Spjd#define TANAMES 76204076Spjd#include <netinet/tcp_debug.h> 77204076Spjd 78204076Spjd#include <arpa/inet.h> 79204076Spjd 80204076Spjd#include <err.h> 81249969Sed#include <nlist.h> 82204076Spjd#include <paths.h> 83204076Spjd#include <stdio.h> 84204076Spjd#include <stdlib.h> 85204076Spjd#include <unistd.h> 86204076Spjd 87204076Spjdstruct nlist nl[] = { 88204076Spjd#define N_TCP_DEBUG 0 89219818Spjd { "_tcp_debug" }, 90204076Spjd#define N_TCP_DEBX 1 91204076Spjd { "_tcp_debx" }, 92226859Spjd { "" }, 93226859Spjd}; 94226859Spjd 95226859Spjdstatic caddr_t tcp_pcbs[TCP_NDEBUG]; 96226859Spjdstatic n_time ntime; 97226859Spjdstatic int aflag, kflag, memf, follow, sflag, tflag; 98226859Spjd 99226859Spjdvoid dotrace __P((caddr_t)); 100226859Spjdvoid klseek __P((int, off_t, int)); 101204076Spjdint numeric __P((const void *, const void *)); 102204076Spjdvoid tcp_trace __P((short, short, struct tcpcb *, struct tcpcb *, 103204076Spjd int, void *, struct tcphdr *, int)); 104204076Spjdstatic void usage __P((void)); 105204076Spjd 106204076Spjdint 107204076Spjdmain(argc, argv) 108204076Spjd int argc; 109204076Spjd char **argv; 110204076Spjd{ 111204076Spjd int ch, i, jflag, npcbs; 112204076Spjd char *system, *core; 113204076Spjd 114204076Spjd jflag = npcbs = 0; 115204076Spjd while ((ch = getopt(argc, argv, "afjp:st")) != -1) 116204076Spjd switch (ch) { 117204076Spjd case 'a': 118204076Spjd ++aflag; 119204076Spjd break; 120204076Spjd case 'f': 121204076Spjd ++follow; 122204076Spjd setlinebuf(stdout); 123204076Spjd break; 124204076Spjd case 'j': 125204076Spjd ++jflag; 126204076Spjd break; 127204076Spjd case 'p': 128204076Spjd if (npcbs >= TCP_NDEBUG) 129204076Spjd errx(1, "too many pcb's specified"); 130204076Spjd (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); 131204076Spjd break; 132204076Spjd case 's': 133204076Spjd ++sflag; 134204076Spjd break; 135204076Spjd case 't': 136204076Spjd ++tflag; 137204076Spjd break; 138204076Spjd case '?': 139204076Spjd default: 140204076Spjd usage(); 141204076Spjd } 142204076Spjd argc -= optind; 143204076Spjd argv += optind; 144204076Spjd 145204076Spjd core = _PATH_KMEM; 146204076Spjd if (argc > 0) { 147204076Spjd system = *argv; 148204076Spjd argc--, argv++; 149204076Spjd if (argc > 0) { 150204076Spjd core = *argv; 151204076Spjd argc--, argv++; 152204076Spjd ++kflag; 153204076Spjd } 154204076Spjd /* 155204076Spjd * Discard setgid privileges if not the running kernel so that 156204076Spjd * bad guys can't print interesting stuff from kernel memory. 157204076Spjd */ 158204076Spjd setgid(getgid()); 159204076Spjd } 160204076Spjd else 161204076Spjd system = (char *)getbootfile(); 162204076Spjd 163204076Spjd if (nlist(system, nl) < 0 || !nl[0].n_value) 164204076Spjd errx(1, "%s: no namelist", system); 165204076Spjd if ((memf = open(core, O_RDONLY)) < 0) 166204076Spjd err(2, "%s", core); 167204076Spjd if (kflag) 168204076Spjd errx(1, "can't do core files yet"); 169204076Spjd (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 170204076Spjd if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 171204076Spjd sizeof(tcp_debx)) 172204076Spjd err(3, "tcp_debx"); 173204076Spjd (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 174204076Spjd if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 175204076Spjd sizeof(tcp_debug)) 176204076Spjd err(3, "tcp_debug"); 177204076Spjd /* 178204076Spjd * If no control blocks have been specified, figure 179204076Spjd * out how many distinct one we have and summarize 180204076Spjd * them in tcp_pcbs for sorting the trace records 181204076Spjd * below. 182204076Spjd */ 183204076Spjd if (!npcbs) { 184204076Spjd for (i = 0; i < TCP_NDEBUG; i++) { 185204076Spjd register struct tcp_debug *td = &tcp_debug[i]; 186204076Spjd register int j; 187214692Spjd 188214692Spjd if (td->td_tcb == 0) 189214692Spjd continue; 190204076Spjd for (j = 0; j < npcbs; j++) 191214692Spjd if (tcp_pcbs[j] == td->td_tcb) 192214692Spjd break; 193214692Spjd if (j >= npcbs) 194214692Spjd tcp_pcbs[npcbs++] = td->td_tcb; 195219864Spjd } 196214692Spjd if (!npcbs) 197204076Spjd exit(0); 198214692Spjd } 199214692Spjd qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 200214692Spjd if (jflag) { 201214692Spjd for (i = 0;;) { 202204076Spjd printf("%x", (int)tcp_pcbs[i]); 203204076Spjd if (++i == npcbs) 204204076Spjd break; 205204076Spjd fputs(", ", stdout); 206204076Spjd } 207204076Spjd putchar('\n'); 208204076Spjd } 209204076Spjd else for (i = 0; i < npcbs; i++) { 210204076Spjd printf("\n%x:\n", (int)tcp_pcbs[i]); 211204076Spjd dotrace(tcp_pcbs[i]); 212204076Spjd } 213204076Spjd exit(0); 214209183Spjd} 215209183Spjd 216209183Spjdstatic void 217209183Spjdusage() 218204076Spjd{ 219204076Spjd (void)fprintf(stderr, 220204076Spjd "usage: trpt [-afjst] [-p hex-address] [system [core]]\n"); 221204076Spjd exit(1); 222204076Spjd} 223204076Spjd 224204076Spjdvoid 225204076Spjddotrace(tcpcb) 226204076Spjd register caddr_t tcpcb; 227204076Spjd{ 228204076Spjd register struct tcp_debug *td; 229204076Spjd register int i; 230204076Spjd int prev_debx = tcp_debx, family; 231220898Spjd 232204076Spjdagain: if (--tcp_debx < 0) 233204076Spjd tcp_debx = TCP_NDEBUG - 1; 234204076Spjd for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 235204076Spjd td = &tcp_debug[i]; 236204076Spjd if (tcpcb && td->td_tcb != tcpcb) 237204076Spjd continue; 238204076Spjd ntime = ntohl(td->td_time); 239204076Spjd#ifdef INET6 240204076Spjd family = td->td_family; 241211982Spjd#else 242204076Spjd family = AF_INET; 243204076Spjd#endif 244204076Spjd switch(family) { 245204076Spjd case AF_INET: 246204076Spjd tcp_trace(td->td_act, td->td_ostate, 247204076Spjd (struct tcpcb *)td->td_tcb, 248204076Spjd &td->td_cb, td->td_family, &td->td_ti.ti_i, 249204076Spjd &td->td_ti.ti_t, td->td_req); 250204076Spjd break; 251204076Spjd#ifdef INET6 252204076Spjd case AF_INET6: 253213533Spjd tcp_trace(td->td_act, td->td_ostate, 254204076Spjd (struct tcpcb *)td->td_tcb, 255204076Spjd &td->td_cb, td->td_family, &td->td_ti6.ip6, 256204076Spjd &td->td_ti6.th, td->td_req); 257229945Spjd break; 258213531Spjd#endif 259213531Spjd } 260204076Spjd if (i == tcp_debx) 261204076Spjd goto done; 262204076Spjd } 263204076Spjd for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 264204076Spjd td = &tcp_debug[i]; 265204076Spjd if (tcpcb && td->td_tcb != tcpcb) 266204076Spjd continue; 267204076Spjd ntime = ntohl(td->td_time); 268204076Spjd#ifdef INET6 269212899Spjd family = td->td_family; 270204076Spjd#else 271204076Spjd family = AF_INET; 272204076Spjd#endif 273204076Spjd switch(family) { 274218138Spjd case AF_INET: 275204076Spjd tcp_trace(td->td_act, td->td_ostate, 276204076Spjd (struct tcpcb *)td->td_tcb, 277204076Spjd &td->td_cb, td->td_family, &td->td_ti.ti_i, 278204076Spjd &td->td_ti.ti_t, td->td_req); 279204076Spjd break; 280204076Spjd#ifdef INET6 281204076Spjd case AF_INET6: 282212899Spjd tcp_trace(td->td_act, td->td_ostate, 283204076Spjd (struct tcpcb *)td->td_tcb, 284204076Spjd &td->td_cb, td->td_family, &td->td_ti6.ip6, 285204076Spjd &td->td_ti6.th, td->td_req); 286204076Spjd break; 287204076Spjd#endif 288204076Spjd } 289204076Spjd } 290204076Spjddone: if (follow) { 291204076Spjd prev_debx = tcp_debx + 1; 292204076Spjd if (prev_debx >= TCP_NDEBUG) 293204076Spjd prev_debx = 0; 294204076Spjd do { 295204076Spjd sleep(1); 296204076Spjd (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); 297204076Spjd if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != 298204076Spjd sizeof(tcp_debx)) 299204076Spjd err(3, "tcp_debx"); 300204076Spjd } while (tcp_debx == prev_debx); 301218138Spjd (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); 302218138Spjd if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != 303204076Spjd sizeof(tcp_debug)) 304204076Spjd err(3, "tcp_debug"); 305225786Spjd goto again; 306247281Strociny } 307204076Spjd} 308204076Spjd 309225830Spjd/* 310225830Spjd * Tcp debug routines 311225830Spjd */ 312225830Spjd/*ARGSUSED*/ 313225830Spjdvoid 314225830Spjdtcp_trace(act, ostate, atp, tp, family, ip, th, req) 315225830Spjd short act, ostate; 316225830Spjd struct tcpcb *atp, *tp; 317247281Strociny int family; 318225830Spjd void *ip; 319225830Spjd struct tcphdr *th; 320225830Spjd int req; 321204076Spjd{ 322204076Spjd tcp_seq seq, ack; 323204076Spjd int flags, len, win, timer; 324210881Spjd struct ip *ip4; 325210881Spjd#ifdef INET6 326210881Spjd int isipv6, nopkt = 1; 327210881Spjd struct ip6_hdr *ip6; 328210881Spjd char ntop_buf[INET6_ADDRSTRLEN]; 329210881Spjd#endif 330210881Spjd 331204076Spjd#ifdef INET6 332204076Spjd switch (family) { 333204076Spjd case AF_INET: 334204076Spjd nopkt = 0; 335204076Spjd isipv6 = 0; 336204076Spjd ip4 = (struct ip *)ip; 337204076Spjd break; 338204076Spjd case AF_INET6: 339204076Spjd nopkt = 0; 340204076Spjd isipv6 = 1; 341204076Spjd ip6 = (struct ip6_hdr *)ip; 342204076Spjd case 0: 343204076Spjd default: 344204076Spjd break; 345204076Spjd } 346204076Spjd#else 347204076Spjd ip4 = (struct ip *)ip; 348204076Spjd#endif 349204076Spjd printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], 350204076Spjd tanames[act]); 351204076Spjd switch (act) { 352204076Spjd case TA_INPUT: 353204076Spjd case TA_OUTPUT: 354204076Spjd case TA_DROP: 355204076Spjd#ifdef INET6 356204076Spjd if (nopkt != 0) 357204076Spjd break; 358204076Spjd#endif 359204076Spjd if (aflag) { 360204076Spjd printf("(src=%s,%u, ", 361204076Spjd 362204076Spjd#ifdef INET6 363204076Spjd isipv6 364204076Spjd ? inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, 365204076Spjd sizeof(ntop_buf)) : 366204076Spjd#endif 367204076Spjd inet_ntoa(ip4->ip_src), 368204076Spjd ntohs(th->th_sport)); 369204076Spjd printf("dst=%s,%u)", 370204076Spjd#ifdef INET6 371204076Spjd isipv6 372204076Spjd ? inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, 373204076Spjd sizeof(ntop_buf)) : 374204076Spjd#endif 375204076Spjd inet_ntoa(ip4->ip_dst), 376204076Spjd ntohs(th->th_dport)); 377204076Spjd } 378204076Spjd seq = th->th_seq; 379204076Spjd ack = th->th_ack; 380204076Spjd 381204076Spjd len = 382204076Spjd#ifdef INET6 383204076Spjd isipv6 ? ip6->ip6_plen : 384204076Spjd#endif 385204076Spjd ip4->ip_len; 386204076Spjd win = th->th_win; 387204076Spjd if (act == TA_OUTPUT) { 388204076Spjd seq = ntohl(seq); 389204076Spjd ack = ntohl(ack); 390204076Spjd len = ntohs(len); 391204076Spjd win = ntohs(win); 392204076Spjd } 393204076Spjd if (act == TA_OUTPUT) 394204076Spjd len -= sizeof(struct tcphdr); 395204076Spjd if (len) 396204076Spjd printf("[%lx..%lx)", seq, seq + len); 397204076Spjd else 398204076Spjd printf("%lx", seq); 399204076Spjd printf("@%lx", ack); 400204076Spjd if (win) 401204076Spjd printf("(win=%x)", win); 402204076Spjd flags = th->th_flags; 403204076Spjd if (flags) { 404204076Spjd register char *cp = "<"; 405204076Spjd#define pf(flag, string) { \ 406204076Spjd if (th->th_flags&flag) { \ 407204076Spjd (void)printf("%s%s", cp, string); \ 408204076Spjd cp = ","; \ 409204076Spjd } \ 410204076Spjd} 411204076Spjd pf(TH_SYN, "SYN"); 412204076Spjd pf(TH_ACK, "ACK"); 413204076Spjd pf(TH_FIN, "FIN"); 414204076Spjd pf(TH_RST, "RST"); 415204076Spjd pf(TH_PUSH, "PUSH"); 416204076Spjd pf(TH_URG, "URG"); 417204076Spjd printf(">"); 418249969Sed } 419204076Spjd break; 420204076Spjd case TA_USER: 421204076Spjd timer = req >> 8; 422204076Spjd req &= 0xff; 423204076Spjd printf("%s", prurequests[req]); 424204076Spjd if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 425204076Spjd printf("<%s>", tcptimers[timer]); 426204076Spjd break; 427204076Spjd } 428204076Spjd printf(" -> %s", tcpstates[tp->t_state]); 429204076Spjd /* print out internal state of tp !?! */ 430204076Spjd printf("\n"); 431204076Spjd if (sflag) { 432204076Spjd printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", 433204076Spjd tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 434204076Spjd tp->snd_max); 435204076Spjd printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, 436204076Spjd tp->snd_wl2, tp->snd_wnd); 437204076Spjd } 438204076Spjd /* print out timers? */ 439204076Spjd#if 0 440204076Spjd /* 441204076Spjd * XXX 442204076Spjd * kernel now uses callouts, not integer time values. 443204076Spjd */ 444214284Spjd if (tflag) { 445214284Spjd register char *cp = "\t"; 446214284Spjd register int i; 447214284Spjd 448214284Spjd for (i = 0; i < TCPT_NTIMERS; i++) { 449214284Spjd if (tp->t_timer[i] == 0) 450214284Spjd continue; 451214284Spjd printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); 452214284Spjd if (i == TCPT_REXMT) 453214284Spjd printf(" (t_rxtshft=%d)", tp->t_rxtshift); 454214284Spjd cp = ", "; 455214284Spjd } 456229945Spjd if (*cp != '\t') 457214284Spjd putchar('\n'); 458214284Spjd } 459214284Spjd#endif 460214284Spjd} 461214284Spjd 462204076Spjdint 463204076Spjdnumeric(v1, v2) 464204076Spjd const void *v1, *v2; 465204076Spjd{ 466204076Spjd const caddr_t *c1 = v1, *c2 = v2; 467204076Spjd return(*c1 - *c2); 468229945Spjd} 469204076Spjd 470204076Spjdvoid 471204076Spjdklseek(fd, base, off) 472229945Spjd int fd, off; 473204076Spjd off_t base; 474204076Spjd{ 475204076Spjd (void)lseek(fd, base, off); 476204076Spjd} 477229945Spjd