1 1.28 maxv /* $NetBSD: trpt.c,v 1.28 2018/05/03 07:13:49 maxv Exp $ */ 2 1.5 thorpej 3 1.5 thorpej /*- 4 1.22 rpaulo * Copyright (c) 1997, 2005, 2006 The NetBSD Foundation, Inc. 5 1.5 thorpej * All rights reserved. 6 1.5 thorpej * 7 1.5 thorpej * This code is derived from software contributed to The NetBSD Foundation 8 1.5 thorpej * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 1.5 thorpej * NASA Ames Research Center. 10 1.5 thorpej * 11 1.5 thorpej * Redistribution and use in source and binary forms, with or without 12 1.5 thorpej * modification, are permitted provided that the following conditions 13 1.5 thorpej * are met: 14 1.5 thorpej * 1. Redistributions of source code must retain the above copyright 15 1.5 thorpej * notice, this list of conditions and the following disclaimer. 16 1.5 thorpej * 2. Redistributions in binary form must reproduce the above copyright 17 1.5 thorpej * notice, this list of conditions and the following disclaimer in the 18 1.5 thorpej * documentation and/or other materials provided with the distribution. 19 1.5 thorpej * 20 1.5 thorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.5 thorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.5 thorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.5 thorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.5 thorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.5 thorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.5 thorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.5 thorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.5 thorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.5 thorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.5 thorpej * POSSIBILITY OF SUCH DAMAGE. 31 1.5 thorpej */ 32 1.4 mikel 33 1.1 cgd /* 34 1.4 mikel * Copyright (c) 1983, 1988, 1993 35 1.4 mikel * The Regents of the University of California. All rights reserved. 36 1.1 cgd * 37 1.1 cgd * Redistribution and use in source and binary forms, with or without 38 1.1 cgd * modification, are permitted provided that the following conditions 39 1.1 cgd * are met: 40 1.1 cgd * 1. Redistributions of source code must retain the above copyright 41 1.1 cgd * notice, this list of conditions and the following disclaimer. 42 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 43 1.1 cgd * notice, this list of conditions and the following disclaimer in the 44 1.1 cgd * documentation and/or other materials provided with the distribution. 45 1.17 agc * 3. Neither the name of the University nor the names of its contributors 46 1.1 cgd * may be used to endorse or promote products derived from this software 47 1.1 cgd * without specific prior written permission. 48 1.1 cgd * 49 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 1.1 cgd * SUCH DAMAGE. 60 1.1 cgd */ 61 1.1 cgd 62 1.5 thorpej #include <sys/cdefs.h> 63 1.1 cgd #ifndef lint 64 1.25 lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\ 65 1.25 lukem The Regents of the University of California. All rights reserved."); 66 1.1 cgd #endif /* not lint */ 67 1.1 cgd 68 1.1 cgd #ifndef lint 69 1.4 mikel #if 0 70 1.4 mikel static char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93"; 71 1.4 mikel #else 72 1.28 maxv __RCSID("$NetBSD: trpt.c,v 1.28 2018/05/03 07:13:49 maxv Exp $"); 73 1.4 mikel #endif 74 1.1 cgd #endif /* not lint */ 75 1.1 cgd 76 1.23 jmcneill #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */ 77 1.23 jmcneill 78 1.1 cgd #include <sys/param.h> 79 1.3 cgd #include <sys/queue.h> 80 1.1 cgd #include <sys/socket.h> 81 1.1 cgd #include <sys/socketvar.h> 82 1.21 rpaulo #include <sys/sysctl.h> 83 1.1 cgd #define PRUREQUESTS 84 1.1 cgd #include <sys/protosw.h> 85 1.1 cgd #include <sys/file.h> 86 1.1 cgd 87 1.1 cgd #include <net/route.h> 88 1.1 cgd #include <net/if.h> 89 1.1 cgd 90 1.1 cgd #include <netinet/in.h> 91 1.1 cgd #include <netinet/in_systm.h> 92 1.1 cgd #include <netinet/ip.h> 93 1.1 cgd #include <netinet/in_pcb.h> 94 1.1 cgd #include <netinet/ip_var.h> 95 1.9 itojun 96 1.9 itojun #ifdef INET6 97 1.9 itojun #ifndef INET 98 1.9 itojun #include <netinet/in.h> 99 1.9 itojun #endif 100 1.9 itojun #include <netinet/ip6.h> 101 1.9 itojun #endif 102 1.9 itojun 103 1.1 cgd #include <netinet/tcp.h> 104 1.1 cgd #define TCPSTATES 105 1.1 cgd #include <netinet/tcp_fsm.h> 106 1.1 cgd #include <netinet/tcp_seq.h> 107 1.1 cgd #define TCPTIMERS 108 1.1 cgd #include <netinet/tcp_timer.h> 109 1.1 cgd #include <netinet/tcp_var.h> 110 1.1 cgd #define TANAMES 111 1.1 cgd #include <netinet/tcp_debug.h> 112 1.1 cgd 113 1.1 cgd #include <arpa/inet.h> 114 1.1 cgd 115 1.5 thorpej #include <err.h> 116 1.1 cgd #include <stdio.h> 117 1.1 cgd #include <errno.h> 118 1.5 thorpej #include <kvm.h> 119 1.1 cgd #include <nlist.h> 120 1.1 cgd #include <paths.h> 121 1.5 thorpej #include <limits.h> 122 1.5 thorpej #include <stdlib.h> 123 1.5 thorpej #include <unistd.h> 124 1.1 cgd 125 1.27 joerg static struct nlist nl[] = { 126 1.16 thorpej #define N_HARDCLOCK_TICKS 0 127 1.26 lukem { "_hardclock_ticks", 0, 0, 0, 0 }, 128 1.16 thorpej #define N_TCP_DEBUG 1 129 1.26 lukem { "_tcp_debug", 0, 0, 0, 0 }, 130 1.16 thorpej #define N_TCP_DEBX 2 131 1.26 lukem { "_tcp_debx", 0, 0, 0, 0 }, 132 1.26 lukem { NULL, 0, 0, 0, 0 }, 133 1.1 cgd }; 134 1.1 cgd 135 1.1 cgd static caddr_t tcp_pcbs[TCP_NDEBUG]; 136 1.1 cgd static n_time ntime; 137 1.5 thorpej static int aflag, follow, sflag, tflag; 138 1.11 itojun 139 1.11 itojun /* see sys/netinet/tcp_debug.c */ 140 1.27 joerg static struct tcp_debug tcp_debug[TCP_NDEBUG]; 141 1.27 joerg static int tcp_debx; 142 1.5 thorpej 143 1.27 joerg static void dotrace(caddr_t); 144 1.27 joerg static void tcp_trace(short, short, struct tcpcb *, struct tcpcb *, 145 1.19 perry int, void *, int); 146 1.27 joerg static int numeric(const void *, const void *); 147 1.27 joerg __dead static void usage(void); 148 1.1 cgd 149 1.27 joerg static kvm_t *kd; 150 1.27 joerg static int use_sysctl; 151 1.5 thorpej 152 1.5 thorpej int 153 1.19 perry main(int argc, char *argv[]) 154 1.1 cgd { 155 1.5 thorpej int ch, i, jflag, npcbs; 156 1.26 lukem char *kernel, *core, *cp, errbuf[_POSIX2_LINE_MAX]; 157 1.14 itojun unsigned long l; 158 1.5 thorpej 159 1.21 rpaulo jflag = npcbs = 0; 160 1.26 lukem kernel = core = NULL; 161 1.1 cgd 162 1.13 soda while ((ch = getopt(argc, argv, "afjp:stN:M:")) != -1) { 163 1.1 cgd switch (ch) { 164 1.1 cgd case 'a': 165 1.1 cgd ++aflag; 166 1.1 cgd break; 167 1.1 cgd case 'f': 168 1.1 cgd ++follow; 169 1.1 cgd setlinebuf(stdout); 170 1.1 cgd break; 171 1.1 cgd case 'j': 172 1.1 cgd ++jflag; 173 1.1 cgd break; 174 1.1 cgd case 'p': 175 1.5 thorpej if (npcbs >= TCP_NDEBUG) 176 1.5 thorpej errx(1, "too many pcbs specified"); 177 1.5 thorpej errno = 0; 178 1.14 itojun cp = NULL; 179 1.14 itojun l = strtoul(optarg, &cp, 16); 180 1.14 itojun tcp_pcbs[npcbs] = (caddr_t)l; 181 1.14 itojun if (*optarg == '\0' || *cp != '\0' || errno || 182 1.14 itojun (unsigned long)tcp_pcbs[npcbs] != l) 183 1.5 thorpej errx(1, "invalid address: %s", optarg); 184 1.14 itojun npcbs++; 185 1.1 cgd break; 186 1.1 cgd case 's': 187 1.1 cgd ++sflag; 188 1.1 cgd break; 189 1.1 cgd case 't': 190 1.1 cgd ++tflag; 191 1.1 cgd break; 192 1.5 thorpej case 'N': 193 1.26 lukem kernel = optarg; 194 1.5 thorpej break; 195 1.5 thorpej case 'M': 196 1.5 thorpej core = optarg; 197 1.5 thorpej break; 198 1.1 cgd default: 199 1.5 thorpej usage(); 200 1.5 thorpej /* NOTREACHED */ 201 1.1 cgd } 202 1.5 thorpej } 203 1.1 cgd argc -= optind; 204 1.1 cgd argv += optind; 205 1.1 cgd 206 1.5 thorpej if (argc) 207 1.5 thorpej usage(); 208 1.5 thorpej 209 1.26 lukem use_sysctl = (kernel == NULL && core == NULL); 210 1.1 cgd 211 1.21 rpaulo if (use_sysctl) { 212 1.21 rpaulo size_t lenx = sizeof(tcp_debx); 213 1.21 rpaulo size_t lend = sizeof(tcp_debug); 214 1.21 rpaulo 215 1.21 rpaulo if (sysctlbyname("net.inet.tcp.debx", &tcp_debx, &lenx, 216 1.21 rpaulo NULL, 0) == -1) 217 1.21 rpaulo err(1, "net.inet.tcp.debx"); 218 1.21 rpaulo if (sysctlbyname("net.inet.tcp.debug", &tcp_debug, &lend, 219 1.21 rpaulo NULL, 0) == -1) 220 1.21 rpaulo err(1, "net.inet.tcp.debug"); 221 1.21 rpaulo } else { 222 1.26 lukem kd = kvm_openfiles(kernel, core, NULL, O_RDONLY, errbuf); 223 1.21 rpaulo if (kd == NULL) 224 1.21 rpaulo errx(1, "can't open kmem: %s", errbuf); 225 1.21 rpaulo 226 1.21 rpaulo if (kvm_nlist(kd, nl)) 227 1.26 lukem errx(2, "%s: no namelist", kernel); 228 1.21 rpaulo 229 1.21 rpaulo if (kvm_read(kd, nl[N_TCP_DEBX].n_value, (char *)&tcp_debx, 230 1.21 rpaulo sizeof(tcp_debx)) != sizeof(tcp_debx)) 231 1.21 rpaulo errx(3, "tcp_debx: %s", kvm_geterr(kd)); 232 1.21 rpaulo 233 1.21 rpaulo if (kvm_read(kd, nl[N_TCP_DEBUG].n_value, (char *)tcp_debug, 234 1.21 rpaulo sizeof(tcp_debug)) != sizeof(tcp_debug)) 235 1.21 rpaulo errx(3, "tcp_debug: %s", kvm_geterr(kd)); 236 1.21 rpaulo } 237 1.1 cgd 238 1.1 cgd /* 239 1.1 cgd * If no control blocks have been specified, figure 240 1.1 cgd * out how many distinct one we have and summarize 241 1.1 cgd * them in tcp_pcbs for sorting the trace records 242 1.1 cgd * below. 243 1.1 cgd */ 244 1.5 thorpej if (npcbs == 0) { 245 1.1 cgd for (i = 0; i < TCP_NDEBUG; i++) { 246 1.5 thorpej struct tcp_debug *td = &tcp_debug[i]; 247 1.5 thorpej int j; 248 1.1 cgd 249 1.1 cgd if (td->td_tcb == 0) 250 1.1 cgd continue; 251 1.1 cgd for (j = 0; j < npcbs; j++) 252 1.1 cgd if (tcp_pcbs[j] == td->td_tcb) 253 1.1 cgd break; 254 1.1 cgd if (j >= npcbs) 255 1.1 cgd tcp_pcbs[npcbs++] = td->td_tcb; 256 1.1 cgd } 257 1.5 thorpej if (npcbs == 0) 258 1.1 cgd exit(0); 259 1.1 cgd } 260 1.1 cgd qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); 261 1.1 cgd if (jflag) { 262 1.1 cgd for (i = 0;;) { 263 1.3 cgd printf("%lx", (long)tcp_pcbs[i]); 264 1.1 cgd if (++i == npcbs) 265 1.1 cgd break; 266 1.1 cgd fputs(", ", stdout); 267 1.1 cgd } 268 1.1 cgd putchar('\n'); 269 1.5 thorpej } else { 270 1.5 thorpej for (i = 0; i < npcbs; i++) { 271 1.5 thorpej printf("\n%lx:\n", (long)tcp_pcbs[i]); 272 1.5 thorpej dotrace(tcp_pcbs[i]); 273 1.5 thorpej } 274 1.1 cgd } 275 1.1 cgd exit(0); 276 1.1 cgd } 277 1.1 cgd 278 1.27 joerg static void 279 1.19 perry dotrace(caddr_t tcpcb) 280 1.1 cgd { 281 1.5 thorpej struct tcp_debug *td; 282 1.1 cgd int prev_debx = tcp_debx; 283 1.5 thorpej int i; 284 1.1 cgd 285 1.5 thorpej again: 286 1.5 thorpej if (--tcp_debx < 0) 287 1.1 cgd tcp_debx = TCP_NDEBUG - 1; 288 1.1 cgd for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { 289 1.1 cgd td = &tcp_debug[i]; 290 1.1 cgd if (tcpcb && td->td_tcb != tcpcb) 291 1.1 cgd continue; 292 1.1 cgd ntime = ntohl(td->td_time); 293 1.9 itojun switch (td->td_family) { 294 1.9 itojun case AF_INET: 295 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 296 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 297 1.9 itojun td->td_family, &td->td_ti, td->td_req); 298 1.9 itojun break; 299 1.9 itojun #ifdef INET6 300 1.9 itojun case AF_INET6: 301 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 302 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 303 1.9 itojun td->td_family, &td->td_ti6, td->td_req); 304 1.9 itojun break; 305 1.9 itojun #endif 306 1.9 itojun default: 307 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 308 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 309 1.9 itojun td->td_family, NULL, td->td_req); 310 1.9 itojun break; 311 1.9 itojun } 312 1.1 cgd if (i == tcp_debx) 313 1.1 cgd goto done; 314 1.1 cgd } 315 1.1 cgd for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { 316 1.1 cgd td = &tcp_debug[i]; 317 1.1 cgd if (tcpcb && td->td_tcb != tcpcb) 318 1.1 cgd continue; 319 1.1 cgd ntime = ntohl(td->td_time); 320 1.9 itojun switch (td->td_family) { 321 1.9 itojun case AF_INET: 322 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 323 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 324 1.9 itojun td->td_family, &td->td_ti, td->td_req); 325 1.9 itojun break; 326 1.9 itojun #ifdef INET6 327 1.9 itojun case AF_INET6: 328 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 329 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 330 1.9 itojun td->td_family, &td->td_ti6, td->td_req); 331 1.9 itojun break; 332 1.9 itojun #endif 333 1.9 itojun default: 334 1.9 itojun tcp_trace(td->td_act, td->td_ostate, 335 1.9 itojun (struct tcpcb *)td->td_tcb, &td->td_cb, 336 1.9 itojun td->td_family, NULL, td->td_req); 337 1.9 itojun break; 338 1.9 itojun } 339 1.1 cgd } 340 1.5 thorpej done: 341 1.5 thorpej if (follow) { 342 1.1 cgd prev_debx = tcp_debx + 1; 343 1.1 cgd if (prev_debx >= TCP_NDEBUG) 344 1.1 cgd prev_debx = 0; 345 1.1 cgd do { 346 1.1 cgd sleep(1); 347 1.21 rpaulo if (use_sysctl) { 348 1.21 rpaulo size_t len = sizeof(tcp_debx); 349 1.21 rpaulo 350 1.21 rpaulo if (sysctlbyname("net.inet.tcp.debx", 351 1.21 rpaulo &tcp_debx, &len, NULL, 0) == -1) 352 1.21 rpaulo err(1, "net.inet.tcp.debx"); 353 1.21 rpaulo } else 354 1.21 rpaulo if (kvm_read(kd, nl[N_TCP_DEBX].n_value, 355 1.21 rpaulo (char *)&tcp_debx, sizeof(tcp_debx)) != 356 1.21 rpaulo sizeof(tcp_debx)) 357 1.21 rpaulo errx(3, "tcp_debx: %s", 358 1.21 rpaulo kvm_geterr(kd)); 359 1.1 cgd } while (tcp_debx == prev_debx); 360 1.5 thorpej 361 1.21 rpaulo if (use_sysctl) { 362 1.21 rpaulo size_t len = sizeof(tcp_debug); 363 1.21 rpaulo 364 1.21 rpaulo if (sysctlbyname("net.inet.tcp.debug", &tcp_debug, 365 1.21 rpaulo &len, NULL, 0) == -1) 366 1.21 rpaulo err(1, "net.inet.tcp.debug"); 367 1.21 rpaulo } else 368 1.21 rpaulo if (kvm_read(kd, nl[N_TCP_DEBUG].n_value, 369 1.21 rpaulo (char *)tcp_debug, 370 1.21 rpaulo sizeof(tcp_debug)) != sizeof(tcp_debug)) 371 1.21 rpaulo errx(3, "tcp_debug: %s", kvm_geterr(kd)); 372 1.5 thorpej 373 1.1 cgd goto again; 374 1.1 cgd } 375 1.1 cgd } 376 1.1 cgd 377 1.1 cgd /* 378 1.1 cgd * Tcp debug routines 379 1.1 cgd */ 380 1.1 cgd /*ARGSUSED*/ 381 1.27 joerg static void 382 1.19 perry tcp_trace(short act, short ostate, struct tcpcb *atp, struct tcpcb *tp, 383 1.19 perry int family, void *packet, int req) 384 1.1 cgd { 385 1.1 cgd tcp_seq seq, ack; 386 1.1 cgd int flags, len, win, timer; 387 1.9 itojun struct tcphdr *th = NULL; 388 1.9 itojun struct ip *ip = NULL; 389 1.9 itojun #ifdef INET6 390 1.9 itojun struct ip6_hdr *ip6 = NULL; 391 1.9 itojun #endif 392 1.23 jmcneill callout_impl_t *ci; 393 1.9 itojun char hbuf[MAXHOSTNAMELEN]; 394 1.9 itojun 395 1.20 lukem len = 0; /* XXXGCC -Wuninitialized */ 396 1.20 lukem 397 1.9 itojun switch (family) { 398 1.9 itojun case AF_INET: 399 1.9 itojun if (packet) { 400 1.9 itojun ip = (struct ip *)packet; 401 1.9 itojun th = (struct tcphdr *)(ip + 1); 402 1.9 itojun } 403 1.9 itojun break; 404 1.9 itojun #ifdef INET6 405 1.9 itojun case AF_INET6: 406 1.9 itojun if (packet) { 407 1.9 itojun ip6 = (struct ip6_hdr *)packet; 408 1.9 itojun th = (struct tcphdr *)(ip6 + 1); 409 1.9 itojun } 410 1.9 itojun break; 411 1.9 itojun #endif 412 1.9 itojun default: 413 1.9 itojun return; 414 1.9 itojun } 415 1.1 cgd 416 1.5 thorpej printf("%03d %s:%s ", (ntime/10) % 1000, tcpstates[ostate], 417 1.1 cgd tanames[act]); 418 1.9 itojun 419 1.9 itojun #ifndef INET6 420 1.9 itojun if (!ip) 421 1.9 itojun #else 422 1.9 itojun if (!(ip || ip6)) 423 1.9 itojun #endif 424 1.9 itojun goto skipact; 425 1.9 itojun 426 1.1 cgd switch (act) { 427 1.1 cgd case TA_INPUT: 428 1.1 cgd case TA_OUTPUT: 429 1.1 cgd case TA_DROP: 430 1.1 cgd if (aflag) { 431 1.9 itojun inet_ntop(family, 432 1.9 itojun #ifndef INET6 433 1.9 itojun (void *)&ip->ip_src, 434 1.9 itojun #else 435 1.9 itojun family == AF_INET ? (void *)&ip->ip_src 436 1.9 itojun : (void *)&ip6->ip6_src, 437 1.9 itojun #endif 438 1.9 itojun hbuf, sizeof(hbuf)); 439 1.1 cgd printf("(src=%s,%u, ", 440 1.9 itojun hbuf, ntohs(th->th_sport)); 441 1.9 itojun inet_ntop(family, 442 1.9 itojun #ifndef INET6 443 1.9 itojun (void *)&ip->ip_dst, 444 1.9 itojun #else 445 1.9 itojun family == AF_INET ? (void *)&ip->ip_dst 446 1.9 itojun : (void *)&ip6->ip6_dst, 447 1.9 itojun #endif 448 1.9 itojun hbuf, sizeof(hbuf)); 449 1.1 cgd printf("dst=%s,%u)", 450 1.9 itojun hbuf, ntohs(th->th_dport)); 451 1.1 cgd } 452 1.9 itojun seq = th->th_seq; 453 1.9 itojun ack = th->th_ack; 454 1.9 itojun if (ip) 455 1.9 itojun len = ip->ip_len; 456 1.9 itojun #ifdef INET6 457 1.9 itojun else if (ip6) 458 1.9 itojun len = ip6->ip6_plen; 459 1.9 itojun #endif 460 1.9 itojun win = th->th_win; 461 1.1 cgd if (act == TA_OUTPUT) { 462 1.5 thorpej NTOHL(seq); 463 1.5 thorpej NTOHL(ack); 464 1.5 thorpej NTOHS(len); 465 1.5 thorpej NTOHS(win); 466 1.1 cgd } 467 1.1 cgd if (act == TA_OUTPUT) 468 1.1 cgd len -= sizeof(struct tcphdr); 469 1.1 cgd if (len) 470 1.5 thorpej printf("[%x..%x)", seq, seq + len); 471 1.1 cgd else 472 1.5 thorpej printf("%x", seq); 473 1.5 thorpej printf("@%x", ack); 474 1.1 cgd if (win) 475 1.1 cgd printf("(win=%x)", win); 476 1.9 itojun flags = th->th_flags; 477 1.1 cgd if (flags) { 478 1.26 lukem const char *cp = "<"; 479 1.1 cgd #define pf(flag, string) { \ 480 1.9 itojun if (th->th_flags&flag) { \ 481 1.1 cgd (void)printf("%s%s", cp, string); \ 482 1.1 cgd cp = ","; \ 483 1.1 cgd } \ 484 1.1 cgd } 485 1.1 cgd pf(TH_SYN, "SYN"); 486 1.1 cgd pf(TH_ACK, "ACK"); 487 1.1 cgd pf(TH_FIN, "FIN"); 488 1.1 cgd pf(TH_RST, "RST"); 489 1.1 cgd pf(TH_PUSH, "PUSH"); 490 1.1 cgd pf(TH_URG, "URG"); 491 1.22 rpaulo pf(TH_CWR, "CWR"); 492 1.22 rpaulo pf(TH_ECE, "ECE"); 493 1.1 cgd printf(">"); 494 1.1 cgd } 495 1.1 cgd break; 496 1.1 cgd case TA_USER: 497 1.1 cgd timer = req >> 8; 498 1.1 cgd req &= 0xff; 499 1.1 cgd printf("%s", prurequests[req]); 500 1.1 cgd if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) 501 1.1 cgd printf("<%s>", tcptimers[timer]); 502 1.1 cgd break; 503 1.1 cgd } 504 1.9 itojun 505 1.9 itojun skipact: 506 1.1 cgd printf(" -> %s", tcpstates[tp->t_state]); 507 1.1 cgd /* print out internal state of tp !?! */ 508 1.1 cgd printf("\n"); 509 1.1 cgd if (sflag) { 510 1.5 thorpej printf("\trcv_nxt %x rcv_wnd %lx snd_una %x snd_nxt %x snd_max %x\n", 511 1.1 cgd tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, 512 1.1 cgd tp->snd_max); 513 1.5 thorpej printf("\tsnd_wl1 %x snd_wl2 %x snd_wnd %lx\n", tp->snd_wl1, 514 1.1 cgd tp->snd_wl2, tp->snd_wnd); 515 1.1 cgd } 516 1.1 cgd /* print out timers? */ 517 1.1 cgd if (tflag) { 518 1.26 lukem const char *cp = "\t"; 519 1.19 perry int i; 520 1.16 thorpej int hardticks; 521 1.16 thorpej 522 1.21 rpaulo if (use_sysctl) { 523 1.26 lukem size_t hlen = sizeof(hardticks); 524 1.1 cgd 525 1.21 rpaulo if (sysctlbyname("kern.hardclock_ticks", &hardticks, 526 1.26 lukem &hlen, NULL, 0) == -1) 527 1.21 rpaulo err(1, "kern.hardclock_ticks"); 528 1.21 rpaulo } else { 529 1.21 rpaulo if (kvm_read(kd, nl[N_HARDCLOCK_TICKS].n_value, 530 1.21 rpaulo (char *)&hardticks, 531 1.21 rpaulo sizeof(hardticks)) != sizeof(hardticks)) 532 1.21 rpaulo errx(3, "hardclock_ticks: %s", kvm_geterr(kd)); 533 1.21 rpaulo 534 1.21 rpaulo for (i = 0; i < TCPT_NTIMERS; i++) { 535 1.23 jmcneill ci = (callout_impl_t *)&tp->t_timer[i]; 536 1.23 jmcneill if ((ci->c_flags & CALLOUT_PENDING) == 0) 537 1.21 rpaulo continue; 538 1.21 rpaulo printf("%s%s=%d", cp, tcptimers[i], 539 1.23 jmcneill ci->c_time - hardticks); 540 1.21 rpaulo if (i == TCPT_REXMT) 541 1.21 rpaulo printf(" (t_rxtshft=%d)", 542 1.21 rpaulo tp->t_rxtshift); 543 1.21 rpaulo cp = ", "; 544 1.21 rpaulo } 545 1.21 rpaulo if (*cp != '\t') 546 1.21 rpaulo putchar('\n'); 547 1.1 cgd } 548 1.1 cgd } 549 1.1 cgd } 550 1.1 cgd 551 1.27 joerg static int 552 1.19 perry numeric(const void *v1, const void *v2) 553 1.1 cgd { 554 1.6 thorpej const caddr_t *c1 = v1; 555 1.6 thorpej const caddr_t *c2 = v2; 556 1.7 thorpej int rv; 557 1.5 thorpej 558 1.7 thorpej if (*c1 < *c2) 559 1.7 thorpej rv = -1; 560 1.7 thorpej else if (*c1 > *c2) 561 1.7 thorpej rv = 1; 562 1.7 thorpej else 563 1.7 thorpej rv = 0; 564 1.7 thorpej 565 1.7 thorpej return (rv); 566 1.1 cgd } 567 1.1 cgd 568 1.27 joerg static void 569 1.19 perry usage(void) 570 1.1 cgd { 571 1.1 cgd 572 1.5 thorpej (void) fprintf(stderr, "usage: %s [-afjst] [-p hex-address]" 573 1.10 cgd " [-N system] [-M core]\n", getprogname()); 574 1.5 thorpej exit(1); 575 1.1 cgd } 576