1 /* $NetBSD: inet.c,v 1.101 2011/12/24 20:18:35 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; 36 #else 37 __RCSID("$NetBSD: inet.c,v 1.101 2011/12/24 20:18:35 christos Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */ 42 43 #include <sys/param.h> 44 #include <sys/queue.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/mbuf.h> 48 #include <sys/protosw.h> 49 #include <sys/sysctl.h> 50 51 #include <net/if_arp.h> 52 #include <net/route.h> 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/ip.h> 56 #include <netinet/in_pcb.h> 57 #define ICMP_STRINGS 58 #include <netinet/ip_icmp.h> 59 60 #ifdef INET6 61 #include <netinet/ip6.h> 62 #endif 63 64 #include <netinet/icmp_var.h> 65 #include <netinet/igmp_var.h> 66 #include <netinet/ip_var.h> 67 #include <netinet/pim_var.h> 68 #include <netinet/tcp.h> 69 #include <netinet/tcpip.h> 70 #include <netinet/tcp_seq.h> 71 #define TCPSTATES 72 #include <netinet/tcp_fsm.h> 73 #define TCPTIMERS 74 #include <netinet/tcp_timer.h> 75 #include <netinet/tcp_var.h> 76 #include <netinet/tcp_debug.h> 77 #include <netinet/udp.h> 78 #include <netinet/ip_carp.h> 79 #include <netinet/udp_var.h> 80 #include <netinet/tcp_vtw.h> 81 82 #include <arpa/inet.h> 83 #include <kvm.h> 84 #include <netdb.h> 85 #include <stdio.h> 86 #include <string.h> 87 #include <unistd.h> 88 #include <stdlib.h> 89 #include <err.h> 90 #include "netstat.h" 91 #include "vtw.h" 92 #include "prog_ops.h" 93 94 char *inetname(struct in_addr *); 95 void inetprint(struct in_addr *, u_int16_t, const char *, int); 96 97 void print_vtw_v4(const vtw_t *); 98 99 /* 100 * Print a summary of connections related to an Internet 101 * protocol. For TCP, also give state of connection. 102 * Listening processes (aflag) are suppressed unless the 103 * -a (all) flag is specified. 104 */ 105 static int width; 106 static int compact; 107 108 /* VTW-related variables. */ 109 static struct timeval now; 110 111 static void 112 protoprhdr(void) 113 { 114 printf("Active Internet connections"); 115 if (aflag) 116 printf(" (including servers)"); 117 putchar('\n'); 118 if (Aflag) 119 printf("%-8.8s ", "PCB"); 120 printf( 121 Vflag ? "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %-13.13s Expires\n" 122 : "%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n", 123 "Proto", "Recv-Q", "Send-Q", compact ? "" : " ", 124 width, width, "Local Address", 125 width, width, "Foreign Address", 126 "State"); 127 } 128 129 static void 130 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc, 131 struct in_addr *laddr, u_int16_t lport, 132 struct in_addr *faddr, u_int16_t fport, 133 short t_state, const char *name, int inp_flags, 134 const struct timeval *expires) 135 { 136 static const char *shorttcpstates[] = { 137 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV", 138 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG", 139 "LASTAK", "FWAIT2", "TMWAIT", 140 }; 141 int istcp; 142 143 istcp = strcmp(name, "tcp") == 0; 144 145 if (Aflag) { 146 printf("%8" PRIxPTR " ", ppcb); 147 } 148 printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc, 149 compact ? "" : " "); 150 if (numeric_port) { 151 inetprint(laddr, lport, name, 1); 152 inetprint(faddr, fport, name, 1); 153 } else if (inp_flags & INP_ANONPORT) { 154 inetprint(laddr, lport, name, 1); 155 inetprint(faddr, fport, name, 0); 156 } else { 157 inetprint(laddr, lport, name, 0); 158 inetprint(faddr, fport, name, 0); 159 } 160 if (istcp) { 161 if (t_state < 0 || t_state >= TCP_NSTATES) 162 printf(" %d", t_state); 163 else 164 printf(" %s", compact ? shorttcpstates[t_state] : 165 tcpstates[t_state]); 166 } 167 if (Vflag && expires != NULL) { 168 if (expires->tv_sec == 0 && expires->tv_usec == -1) 169 printf(" reclaimed"); 170 else { 171 struct timeval delta; 172 173 timersub(expires, &now, &delta); 174 printf(" %.3fms", 175 delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0); 176 } 177 } 178 putchar('\n'); 179 } 180 181 static void 182 dbg_printf(const char *fmt, ...) 183 { 184 return; 185 } 186 187 void 188 print_vtw_v4(const vtw_t *vtw) 189 { 190 const vtw_v4_t *v4 = (const vtw_v4_t *)vtw; 191 struct timeval delta; 192 struct in_addr la, fa; 193 char buf[2][32]; 194 static const struct timeval zero = {.tv_sec = 0, .tv_usec = 0}; 195 196 la.s_addr = v4->laddr; 197 fa.s_addr = v4->faddr; 198 199 snprintf(&buf[0][0], 32, "%s", inet_ntoa(la)); 200 snprintf(&buf[1][0], 32, "%s", inet_ntoa(fa)); 201 202 timersub(&vtw->expire, &now, &delta); 203 204 if (vtw->expire.tv_sec == 0 && vtw->expire.tv_usec == -1) { 205 dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n" 206 ,buf[0], ntohs(v4->lport) 207 ,buf[1], ntohs(v4->fport)); 208 if (!(Vflag && vflag)) 209 return; 210 } else if (vtw->expire.tv_sec == 0) 211 return; 212 else if (timercmp(&delta, &zero, <) && !(Vflag && vflag)) { 213 dbg_printf("%15.15s:%d %15.15s:%d expired\n" 214 ,buf[0], ntohs(v4->lport) 215 ,buf[1], ntohs(v4->fport)); 216 return; 217 } else { 218 dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n" 219 ,buf[0], ntohs(v4->lport) 220 ,buf[1], ntohs(v4->fport) 221 ,delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0); 222 } 223 protopr0(0, 0, 0, 224 &la, v4->lport, 225 &fa, v4->fport, 226 TCPS_TIME_WAIT, "tcp", 0, &vtw->expire); 227 } 228 229 void 230 protopr(u_long off, const char *name) 231 { 232 struct inpcbtable table; 233 struct inpcb *head, *next, *prev; 234 struct inpcb inpcb; 235 struct tcpcb tcpcb; 236 struct socket sockb; 237 int istcp = strcmp(name, "tcp") == 0; 238 static int first = 1; 239 240 compact = 0; 241 if (Aflag) { 242 if (!numeric_addr) 243 width = 18; 244 else { 245 width = 21; 246 compact = 1; 247 } 248 } else 249 width = 22; 250 251 if (use_sysctl) { 252 struct kinfo_pcb *pcblist; 253 int mib[8]; 254 size_t namelen = 0, size = 0, i; 255 char *mibname = NULL; 256 257 memset(mib, 0, sizeof(mib)); 258 259 if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1) 260 err(1, "asprintf"); 261 262 /* get dynamic pcblist node */ 263 if (sysctlnametomib(mibname, mib, &namelen) == -1) 264 err(1, "sysctlnametomib: %s", mibname); 265 266 if (prog_sysctl(mib, __arraycount(mib), 267 NULL, &size, NULL, 0) == -1) 268 err(1, "sysctl (query)"); 269 270 if ((pcblist = malloc(size)) == NULL) 271 err(1, "malloc"); 272 memset(pcblist, 0, size); 273 274 mib[6] = sizeof(*pcblist); 275 mib[7] = size / sizeof(*pcblist); 276 277 if (prog_sysctl(mib, __arraycount(mib), 278 pcblist, &size, NULL, 0) == -1) 279 err(1, "sysctl (copy)"); 280 281 for (i = 0; i < size / sizeof(*pcblist); i++) { 282 struct sockaddr_in src, dst; 283 284 memcpy(&src, &pcblist[i].ki_s, sizeof(src)); 285 memcpy(&dst, &pcblist[i].ki_d, sizeof(dst)); 286 287 if (!aflag && 288 inet_lnaof(dst.sin_addr) == INADDR_ANY) 289 continue; 290 291 if (first) { 292 protoprhdr(); 293 first = 0; 294 } 295 296 protopr0((intptr_t) pcblist[i].ki_ppcbaddr, 297 pcblist[i].ki_rcvq, pcblist[i].ki_sndq, 298 &src.sin_addr, src.sin_port, 299 &dst.sin_addr, dst.sin_port, 300 pcblist[i].ki_tstate, name, 301 pcblist[i].ki_pflags, NULL); 302 } 303 304 free(pcblist); 305 goto end; 306 } 307 308 if (off == 0) 309 return; 310 kread(off, (char *)&table, sizeof table); 311 prev = head = 312 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first; 313 next = (struct inpcb *)table.inpt_queue.cqh_first; 314 315 while (next != head) { 316 kread((u_long)next, (char *)&inpcb, sizeof inpcb); 317 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) { 318 printf("???\n"); 319 break; 320 } 321 prev = next; 322 next = (struct inpcb *)inpcb.inp_queue.cqe_next; 323 324 if (inpcb.inp_af != AF_INET) 325 continue; 326 327 if (!aflag && 328 inet_lnaof(inpcb.inp_faddr) == INADDR_ANY) 329 continue; 330 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb)); 331 if (istcp) { 332 kread((u_long)inpcb.inp_ppcb, 333 (char *)&tcpcb, sizeof (tcpcb)); 334 } 335 336 if (first) { 337 protoprhdr(); 338 first = 0; 339 } 340 341 protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev, 342 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc, 343 &inpcb.inp_laddr, inpcb.inp_lport, 344 &inpcb.inp_faddr, inpcb.inp_fport, 345 tcpcb.t_state, name, inpcb.inp_flags, NULL); 346 } 347 end: 348 if (istcp) { 349 struct timeval t; 350 timebase(&t); 351 gettimeofday(&now, NULL); 352 timersub(&now, &t, &now); 353 show_vtw_v4(print_vtw_v4); 354 } 355 } 356 357 /* 358 * Dump TCP statistics structure. 359 */ 360 void 361 tcp_stats(u_long off, const char *name) 362 { 363 uint64_t tcpstat[TCP_NSTATS]; 364 365 if (use_sysctl) { 366 size_t size = sizeof(tcpstat); 367 368 if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size, 369 NULL, 0) == -1) 370 return; 371 } else { 372 warnx("%s stats not available via KVM.", name); 373 return; 374 } 375 376 printf ("%s:\n", name); 377 378 #define ps(f, m) if (tcpstat[f] || sflag <= 1) \ 379 printf(m, tcpstat[f]) 380 #define p(f, m) if (tcpstat[f] || sflag <= 1) \ 381 printf(m, tcpstat[f], plural(tcpstat[f])) 382 #define p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 383 printf(m, tcpstat[f1], plural(tcpstat[f1]), \ 384 tcpstat[f2], plural(tcpstat[f2])) 385 #define p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 386 printf(m, tcpstat[f1], plural(tcpstat[f1]), \ 387 tcpstat[f2]) 388 #define p3(f, m) if (tcpstat[f] || sflag <= 1) \ 389 printf(m, tcpstat[f], plurales(tcpstat[f])) 390 391 p(TCP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n"); 392 p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE, 393 "\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s)\n"); 394 p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE, 395 "\t\t%" PRIu64 " data packet%s (%" PRIu64 " byte%s) retransmitted\n"); 396 p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK, 397 "\t\t%" PRIu64 " ack-only packet%s (%" PRIu64 " delayed)\n"); 398 p(TCP_STAT_SNDURG, "\t\t%" PRIu64 " URG only packet%s\n"); 399 p(TCP_STAT_SNDPROBE, "\t\t%" PRIu64 " window probe packet%s\n"); 400 p(TCP_STAT_SNDWINUP, "\t\t%" PRIu64 " window update packet%s\n"); 401 p(TCP_STAT_SNDCTRL, "\t\t%" PRIu64 " control packet%s\n"); 402 p(TCP_STAT_SELFQUENCH, 403 "\t\t%" PRIu64 " send attempt%s resulted in self-quench\n"); 404 p(TCP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n"); 405 p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE, 406 "\t\t%" PRIu64 " ack%s (for %" PRIu64 " byte%s)\n"); 407 p(TCP_STAT_RCVDUPACK, "\t\t%" PRIu64 " duplicate ack%s\n"); 408 p(TCP_STAT_RCVACKTOOMUCH, "\t\t%" PRIu64 " ack%s for unsent data\n"); 409 p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE, 410 "\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) received in-sequence\n"); 411 p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE, 412 "\t\t%" PRIu64 " completely duplicate packet%s (%" PRIu64 " byte%s)\n"); 413 p(TCP_STAT_PAWSDROP, "\t\t%" PRIu64 " old duplicate packet%s\n"); 414 p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE, 415 "\t\t%" PRIu64 " packet%s with some dup. data (%" PRIu64 " byte%s duped)\n"); 416 p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE, 417 "\t\t%" PRIu64 " out-of-order packet%s (%" PRIu64 " byte%s)\n"); 418 p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN, 419 "\t\t%" PRIu64 " packet%s (%" PRIu64 " byte%s) of data after window\n"); 420 p(TCP_STAT_RCVWINPROBE, "\t\t%" PRIu64 " window probe%s\n"); 421 p(TCP_STAT_RCVWINUPD, "\t\t%" PRIu64 " window update packet%s\n"); 422 p(TCP_STAT_RCVAFTERCLOSE, "\t\t%" PRIu64 " packet%s received after close\n"); 423 p(TCP_STAT_RCVBADSUM, "\t\t%" PRIu64 " discarded for bad checksum%s\n"); 424 p(TCP_STAT_RCVBADOFF, "\t\t%" PRIu64 " discarded for bad header offset field%s\n"); 425 ps(TCP_STAT_RCVSHORT, "\t\t%" PRIu64 " discarded because packet too short\n"); 426 p(TCP_STAT_CONNATTEMPT, "\t%" PRIu64 " connection request%s\n"); 427 p(TCP_STAT_ACCEPTS, "\t%" PRIu64 " connection accept%s\n"); 428 p(TCP_STAT_CONNECTS, 429 "\t%" PRIu64 " connection%s established (including accepts)\n"); 430 p2(TCP_STAT_CLOSED, TCP_STAT_DROPS, 431 "\t%" PRIu64 " connection%s closed (including %" PRIu64 " drop%s)\n"); 432 p(TCP_STAT_CONNDROPS, "\t%" PRIu64 " embryonic connection%s dropped\n"); 433 p(TCP_STAT_DELAYED_FREE, "\t%" PRIu64 " delayed free%s of tcpcb\n"); 434 p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED, 435 "\t%" PRIu64 " segment%s updated rtt (of %" PRIu64 " attempt%s)\n"); 436 p(TCP_STAT_REXMTTIMEO, "\t%" PRIu64 " retransmit timeout%s\n"); 437 p(TCP_STAT_TIMEOUTDROP, 438 "\t\t%" PRIu64 " connection%s dropped by rexmit timeout\n"); 439 p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS, 440 "\t%" PRIu64 " persist timeout%s (resulting in %" PRIu64 " dropped " 441 "connection%s)\n"); 442 p(TCP_STAT_KEEPTIMEO, "\t%" PRIu64 " keepalive timeout%s\n"); 443 p(TCP_STAT_KEEPPROBE, "\t\t%" PRIu64 " keepalive probe%s sent\n"); 444 p(TCP_STAT_KEEPDROPS, "\t\t%" PRIu64 " connection%s dropped by keepalive\n"); 445 p(TCP_STAT_PREDACK, "\t%" PRIu64 " correct ACK header prediction%s\n"); 446 p(TCP_STAT_PREDDAT, "\t%" PRIu64 " correct data packet header prediction%s\n"); 447 p3(TCP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n"); 448 ps(TCP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n"); 449 p(TCP_STAT_CONNSDRAINED, "\t%" PRIu64 " connection%s drained due to memory " 450 "shortage\n"); 451 p(TCP_STAT_PMTUBLACKHOLE, "\t%" PRIu64 " PMTUD blackhole%s detected\n"); 452 453 p(TCP_STAT_BADSYN, "\t%" PRIu64 " bad connection attempt%s\n"); 454 ps(TCP_STAT_SC_ADDED, "\t%" PRIu64 " SYN cache entries added\n"); 455 p(TCP_STAT_SC_COLLISIONS, "\t\t%" PRIu64 " hash collision%s\n"); 456 ps(TCP_STAT_SC_COMPLETED, "\t\t%" PRIu64 " completed\n"); 457 ps(TCP_STAT_SC_ABORTED, "\t\t%" PRIu64 " aborted (no space to build PCB)\n"); 458 ps(TCP_STAT_SC_TIMED_OUT, "\t\t%" PRIu64 " timed out\n"); 459 ps(TCP_STAT_SC_OVERFLOWED, "\t\t%" PRIu64 " dropped due to overflow\n"); 460 ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%" PRIu64 " dropped due to bucket overflow\n"); 461 ps(TCP_STAT_SC_RESET, "\t\t%" PRIu64 " dropped due to RST\n"); 462 ps(TCP_STAT_SC_UNREACH, "\t\t%" PRIu64 " dropped due to ICMP unreachable\n"); 463 ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%" PRIu64 " delayed free of SYN cache " 464 "entries\n"); 465 p(TCP_STAT_SC_RETRANSMITTED, "\t%" PRIu64 " SYN,ACK%s retransmitted\n"); 466 p(TCP_STAT_SC_DUPESYN, "\t%" PRIu64 " duplicate SYN%s received for entries " 467 "already in the cache\n"); 468 p(TCP_STAT_SC_DROPPED, "\t%" PRIu64 " SYN%s dropped (no route or no space)\n"); 469 p(TCP_STAT_BADSIG, "\t%" PRIu64 " packet%s with bad signature\n"); 470 p(TCP_STAT_GOODSIG, "\t%" PRIu64 " packet%s with good signature\n"); 471 472 p(TCP_STAT_ECN_SHS, "\t%" PRIu64 " successful ECN handshake%s\n"); 473 p(TCP_STAT_ECN_CE, "\t%" PRIu64 " packet%s with ECN CE bit\n"); 474 p(TCP_STAT_ECN_ECT, "\t%" PRIu64 " packet%s ECN ECT(0) bit\n"); 475 #undef p 476 #undef ps 477 #undef p2 478 #undef p2s 479 #undef p3 480 show_vtw_stats(); 481 } 482 483 /* 484 * Dump UDP statistics structure. 485 */ 486 void 487 udp_stats(u_long off, const char *name) 488 { 489 uint64_t udpstat[UDP_NSTATS]; 490 u_quad_t delivered; 491 492 if (use_sysctl) { 493 size_t size = sizeof(udpstat); 494 495 if (sysctlbyname("net.inet.udp.stats", udpstat, &size, 496 NULL, 0) == -1) 497 return; 498 } else { 499 warnx("%s stats not available via KVM.", name); 500 return; 501 } 502 503 printf ("%s:\n", name); 504 505 #define ps(f, m) if (udpstat[f] || sflag <= 1) \ 506 printf(m, udpstat[f]) 507 #define p(f, m) if (udpstat[f] || sflag <= 1) \ 508 printf(m, udpstat[f], plural(udpstat[f])) 509 #define p3(f, m) if (udpstat[f] || sflag <= 1) \ 510 printf(m, udpstat[f], plurales(udpstat[f])) 511 512 p(UDP_STAT_IPACKETS, "\t%" PRIu64 " datagram%s received\n"); 513 ps(UDP_STAT_HDROPS, "\t%" PRIu64 " with incomplete header\n"); 514 ps(UDP_STAT_BADLEN, "\t%" PRIu64 " with bad data length field\n"); 515 ps(UDP_STAT_BADSUM, "\t%" PRIu64 " with bad checksum\n"); 516 ps(UDP_STAT_NOPORT, "\t%" PRIu64 " dropped due to no socket\n"); 517 p(UDP_STAT_NOPORTBCAST, 518 "\t%" PRIu64 " broadcast/multicast datagram%s dropped due to no socket\n"); 519 ps(UDP_STAT_FULLSOCK, "\t%" PRIu64 " dropped due to full socket buffers\n"); 520 delivered = udpstat[UDP_STAT_IPACKETS] - 521 udpstat[UDP_STAT_HDROPS] - 522 udpstat[UDP_STAT_BADLEN] - 523 udpstat[UDP_STAT_BADSUM] - 524 udpstat[UDP_STAT_NOPORT] - 525 udpstat[UDP_STAT_NOPORTBCAST] - 526 udpstat[UDP_STAT_FULLSOCK]; 527 if (delivered || sflag <= 1) 528 printf("\t%" PRIu64 " delivered\n", delivered); 529 p3(UDP_STAT_PCBHASHMISS, "\t%" PRIu64 " PCB hash miss%s\n"); 530 p(UDP_STAT_OPACKETS, "\t%" PRIu64 " datagram%s output\n"); 531 532 #undef ps 533 #undef p 534 #undef p3 535 } 536 537 /* 538 * Dump IP statistics structure. 539 */ 540 void 541 ip_stats(u_long off, const char *name) 542 { 543 uint64_t ipstat[IP_NSTATS]; 544 545 if (use_sysctl) { 546 size_t size = sizeof(ipstat); 547 548 if (sysctlbyname("net.inet.ip.stats", ipstat, &size, 549 NULL, 0) == -1) 550 return; 551 } else { 552 warnx("%s stats not available via KVM.", name); 553 return; 554 } 555 556 printf("%s:\n", name); 557 558 #define ps(f, m) if (ipstat[f] || sflag <= 1) \ 559 printf(m, ipstat[f]) 560 #define p(f, m) if (ipstat[f] || sflag <= 1) \ 561 printf(m, ipstat[f], plural(ipstat[f])) 562 563 p(IP_STAT_TOTAL, "\t%" PRIu64 " total packet%s received\n"); 564 p(IP_STAT_BADSUM, "\t%" PRIu64 " bad header checksum%s\n"); 565 ps(IP_STAT_TOOSMALL, "\t%" PRIu64 " with size smaller than minimum\n"); 566 ps(IP_STAT_TOOSHORT, "\t%" PRIu64 " with data size < data length\n"); 567 ps(IP_STAT_TOOLONG, "\t%" PRIu64 " with length > max ip packet size\n"); 568 ps(IP_STAT_BADHLEN, "\t%" PRIu64 " with header length < data size\n"); 569 ps(IP_STAT_BADLEN, "\t%" PRIu64 " with data length < header length\n"); 570 ps(IP_STAT_BADOPTIONS, "\t%" PRIu64 " with bad options\n"); 571 ps(IP_STAT_BADVERS, "\t%" PRIu64 " with incorrect version number\n"); 572 p(IP_STAT_FRAGMENTS, "\t%" PRIu64 " fragment%s received\n"); 573 p(IP_STAT_FRAGDROPPED, "\t%" PRIu64 " fragment%s dropped (dup or out of space)\n"); 574 p(IP_STAT_RCVMEMDROP, "\t%" PRIu64 " fragment%s dropped (out of ipqent)\n"); 575 p(IP_STAT_BADFRAGS, "\t%" PRIu64 " malformed fragment%s dropped\n"); 576 p(IP_STAT_FRAGTIMEOUT, "\t%" PRIu64 " fragment%s dropped after timeout\n"); 577 p(IP_STAT_REASSEMBLED, "\t%" PRIu64 " packet%s reassembled ok\n"); 578 p(IP_STAT_DELIVERED, "\t%" PRIu64 " packet%s for this host\n"); 579 p(IP_STAT_NOPROTO, "\t%" PRIu64 " packet%s for unknown/unsupported protocol\n"); 580 p(IP_STAT_FORWARD, "\t%" PRIu64 " packet%s forwarded"); 581 p(IP_STAT_FASTFORWARD, " (%" PRIu64 " packet%s fast forwarded)"); 582 if (ipstat[IP_STAT_FORWARD] || sflag <= 1) 583 putchar('\n'); 584 p(IP_STAT_CANTFORWARD, "\t%" PRIu64 " packet%s not forwardable\n"); 585 p(IP_STAT_REDIRECTSENT, "\t%" PRIu64 " redirect%s sent\n"); 586 p(IP_STAT_NOGIF, "\t%" PRIu64 " packet%s no matching gif found\n"); 587 p(IP_STAT_LOCALOUT, "\t%" PRIu64 " packet%s sent from this host\n"); 588 p(IP_STAT_RAWOUT, "\t%" PRIu64 " packet%s sent with fabricated ip header\n"); 589 p(IP_STAT_ODROPPED, "\t%" PRIu64 " output packet%s dropped due to no bufs, etc.\n"); 590 p(IP_STAT_NOROUTE, "\t%" PRIu64 " output packet%s discarded due to no route\n"); 591 p(IP_STAT_FRAGMENTED, "\t%" PRIu64 " output datagram%s fragmented\n"); 592 p(IP_STAT_OFRAGMENTS, "\t%" PRIu64 " fragment%s created\n"); 593 p(IP_STAT_CANTFRAG, "\t%" PRIu64 " datagram%s that can't be fragmented\n"); 594 p(IP_STAT_BADADDR, "\t%" PRIu64 " datagram%s with bad address in header\n"); 595 #undef ps 596 #undef p 597 } 598 599 /* 600 * Dump ICMP statistics. 601 */ 602 void 603 icmp_stats(u_long off, const char *name) 604 { 605 uint64_t icmpstat[ICMP_NSTATS]; 606 int i, first; 607 608 if (use_sysctl) { 609 size_t size = sizeof(icmpstat); 610 611 if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size, 612 NULL, 0) == -1) 613 return; 614 } else { 615 warnx("%s stats not available via KVM.", name); 616 return; 617 } 618 619 printf("%s:\n", name); 620 621 #define p(f, m) if (icmpstat[f] || sflag <= 1) \ 622 printf(m, icmpstat[f], plural(icmpstat[f])) 623 624 p(ICMP_STAT_ERROR, "\t%" PRIu64 " call%s to icmp_error\n"); 625 p(ICMP_STAT_OLDICMP, 626 "\t%" PRIu64 " error%s not generated because old message was icmp\n"); 627 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 628 if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) { 629 if (first) { 630 printf("\tOutput histogram:\n"); 631 first = 0; 632 } 633 printf("\t\t%s: %" PRIu64 "\n", icmp_type[i], 634 icmpstat[ICMP_STAT_OUTHIST + i]); 635 } 636 p(ICMP_STAT_BADCODE, "\t%" PRIu64 " message%s with bad code fields\n"); 637 p(ICMP_STAT_TOOSHORT, "\t%" PRIu64 " message%s < minimum length\n"); 638 p(ICMP_STAT_CHECKSUM, "\t%" PRIu64 " bad checksum%s\n"); 639 p(ICMP_STAT_BADLEN, "\t%" PRIu64 " message%s with bad length\n"); 640 p(ICMP_STAT_BMCASTECHO, "\t%" PRIu64 " multicast echo request%s ignored\n"); 641 p(ICMP_STAT_BMCASTTSTAMP, "\t%" PRIu64 " multicast timestamp request%s ignored\n"); 642 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 643 if (icmpstat[ICMP_STAT_INHIST + i] != 0) { 644 if (first) { 645 printf("\tInput histogram:\n"); 646 first = 0; 647 } 648 printf("\t\t%s: %" PRIu64 "\n", icmp_type[i], 649 icmpstat[ICMP_STAT_INHIST + i]); 650 } 651 p(ICMP_STAT_REFLECT, "\t%" PRIu64 " message response%s generated\n"); 652 p(ICMP_STAT_PMTUCHG, "\t%" PRIu64 " path MTU change%s\n"); 653 #undef p 654 } 655 656 /* 657 * Dump IGMP statistics structure. 658 */ 659 void 660 igmp_stats(u_long off, const char *name) 661 { 662 uint64_t igmpstat[IGMP_NSTATS]; 663 664 if (use_sysctl) { 665 size_t size = sizeof(igmpstat); 666 667 if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size, 668 NULL, 0) == -1) 669 return; 670 } else { 671 warnx("%s stats not available via KVM.", name); 672 return; 673 } 674 675 printf("%s:\n", name); 676 677 #define p(f, m) if (igmpstat[f] || sflag <= 1) \ 678 printf(m, igmpstat[f], plural(igmpstat[f])) 679 #define py(f, m) if (igmpstat[f] || sflag <= 1) \ 680 printf(m, igmpstat[f], igmpstat[f] != 1 ? "ies" : "y") 681 p(IGMP_STAT_RCV_TOTAL, "\t%" PRIu64 " message%s received\n"); 682 p(IGMP_STAT_RCV_TOOSHORT, "\t%" PRIu64 " message%s received with too few bytes\n"); 683 p(IGMP_STAT_RCV_BADSUM, "\t%" PRIu64 " message%s received with bad checksum\n"); 684 py(IGMP_STAT_RCV_QUERIES, "\t%" PRIu64 " membership quer%s received\n"); 685 py(IGMP_STAT_RCV_BADQUERIES, "\t%" PRIu64 " membership quer%s received with invalid field(s)\n"); 686 p(IGMP_STAT_RCV_REPORTS, "\t%" PRIu64 " membership report%s received\n"); 687 p(IGMP_STAT_RCV_BADREPORTS, "\t%" PRIu64 " membership report%s received with invalid field(s)\n"); 688 p(IGMP_STAT_RCV_OURREPORTS, "\t%" PRIu64 " membership report%s received for groups to which we belong\n"); 689 p(IGMP_STAT_SND_REPORTS, "\t%" PRIu64 " membership report%s sent\n"); 690 #undef p 691 #undef py 692 } 693 694 /* 695 * Dump CARP statistics structure. 696 */ 697 void 698 carp_stats(u_long off, const char *name) 699 { 700 uint64_t carpstat[CARP_NSTATS]; 701 702 if (use_sysctl) { 703 size_t size = sizeof(carpstat); 704 705 if (sysctlbyname("net.inet.carp.stats", carpstat, &size, 706 NULL, 0) == -1) 707 return; 708 } else { 709 warnx("%s stats not available via KVM.", name); 710 return; 711 } 712 713 printf("%s:\n", name); 714 715 #define p(f, m) if (carpstat[f] || sflag <= 1) \ 716 printf(m, carpstat[f], plural(carpstat[f])) 717 #define p2(f, m) if (carpstat[f] || sflag <= 1) \ 718 printf(m, carpstat[f]) 719 720 p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n"); 721 p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n"); 722 p(CARP_STAT_BADIF, 723 "\t\t%" PRIu64 " packet%s discarded for bad interface\n"); 724 p(CARP_STAT_BADTTL, 725 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n"); 726 p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n"); 727 p(CARP_STAT_BADSUM, "\t\t%" PRIu64 728 " packet%s discarded for bad checksum\n"); 729 p(CARP_STAT_BADVER, 730 "\t\t%" PRIu64 " packet%s discarded with a bad version\n"); 731 p2(CARP_STAT_BADLEN, 732 "\t\t%" PRIu64 " discarded because packet was too short\n"); 733 p(CARP_STAT_BADAUTH, 734 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n"); 735 p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); 736 p(CARP_STAT_BADADDRS, "\t\t%" PRIu64 737 " packet%s discarded because of a bad address list\n"); 738 p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n"); 739 p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); 740 p2(CARP_STAT_ONOMEM, 741 "\t\t%" PRIu64 " send failed due to mbuf memory error\n"); 742 #undef p 743 #undef p2 744 } 745 746 /* 747 * Dump PIM statistics structure. 748 */ 749 void 750 pim_stats(u_long off, const char *name) 751 { 752 struct pimstat pimstat; 753 754 if (off == 0) 755 return; 756 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) { 757 /* XXX: PIM is probably not enabled in the kernel */ 758 return; 759 } 760 761 printf("%s:\n", name); 762 763 #define p(f, m) if (pimstat.f || sflag <= 1) \ 764 printf(m, pimstat.f, plural(pimstat.f)) 765 766 p(pims_rcv_total_msgs, "\t%" PRIu64 " message%s received\n"); 767 p(pims_rcv_total_bytes, "\t%" PRIu64 " byte%s received\n"); 768 p(pims_rcv_tooshort, "\t%" PRIu64 " message%s received with too few bytes\n"); 769 p(pims_rcv_badsum, "\t%" PRIu64 " message%s received with bad checksum\n"); 770 p(pims_rcv_badversion, "\t%" PRIu64 " message%s received with bad version\n"); 771 p(pims_rcv_registers_msgs, "\t%" PRIu64 " data register message%s received\n"); 772 p(pims_rcv_registers_bytes, "\t%" PRIu64 " data register byte%s received\n"); 773 p(pims_rcv_registers_wrongiif, "\t%" PRIu64 " data register message%s received on wrong iif\n"); 774 p(pims_rcv_badregisters, "\t%" PRIu64 " bad register%s received\n"); 775 p(pims_snd_registers_msgs, "\t%" PRIu64 " data register message%s sent\n"); 776 p(pims_snd_registers_bytes, "\t%" PRIu64 " data register byte%s sent\n"); 777 #undef p 778 } 779 780 /* 781 * Dump the ARP statistics structure. 782 */ 783 void 784 arp_stats(u_long off, const char *name) 785 { 786 uint64_t arpstat[ARP_NSTATS]; 787 788 if (use_sysctl) { 789 size_t size = sizeof(arpstat); 790 791 if (sysctlbyname("net.inet.arp.stats", arpstat, &size, 792 NULL, 0) == -1) 793 return; 794 } else { 795 warnx("%s stats not available via KVM.", name); 796 return; 797 } 798 799 printf("%s:\n", name); 800 801 #define ps(f, m) if (arpstat[f] || sflag <= 1) \ 802 printf(m, arpstat[f]) 803 #define p(f, m) if (arpstat[f] || sflag <= 1) \ 804 printf(m, arpstat[f], plural(arpstat[f])) 805 806 p(ARP_STAT_SNDTOTAL, "\t%" PRIu64 " packet%s sent\n"); 807 p(ARP_STAT_SNDREPLY, "\t\t%" PRIu64 " reply packet%s\n"); 808 p(ARP_STAT_SENDREQUEST, "\t\t%" PRIu64 " request packet%s\n"); 809 810 p(ARP_STAT_RCVTOTAL, "\t%" PRIu64 " packet%s received\n"); 811 p(ARP_STAT_RCVREPLY, "\t\t%" PRIu64 " reply packet%s\n"); 812 p(ARP_STAT_RCVREQUEST, "\t\t%" PRIu64 " valid request packet%s\n"); 813 p(ARP_STAT_RCVMCAST, "\t\t%" PRIu64 " broadcast/multicast packet%s\n"); 814 p(ARP_STAT_RCVBADPROTO, "\t\t%" PRIu64 " packet%s with unknown protocol type\n"); 815 p(ARP_STAT_RCVBADLEN, "\t\t%" PRIu64 " packet%s with bad (short) length\n"); 816 p(ARP_STAT_RCVZEROTPA, "\t\t%" PRIu64 " packet%s with null target IP address\n"); 817 p(ARP_STAT_RCVZEROSPA, "\t\t%" PRIu64 " packet%s with null source IP address\n"); 818 ps(ARP_STAT_RCVNOINT, "\t\t%" PRIu64 " could not be mapped to an interface\n"); 819 p(ARP_STAT_RCVLOCALSHA, "\t\t%" PRIu64 " packet%s sourced from a local hardware " 820 "address\n"); 821 p(ARP_STAT_RCVBCASTSHA, "\t\t%" PRIu64 " packet%s with a broadcast " 822 "source hardware address\n"); 823 p(ARP_STAT_RCVLOCALSPA, "\t\t%" PRIu64 " duplicate%s for a local IP address\n"); 824 p(ARP_STAT_RCVOVERPERM, "\t\t%" PRIu64 " attempt%s to overwrite a static entry\n"); 825 p(ARP_STAT_RCVOVERINT, "\t\t%" PRIu64 " packet%s received on wrong interface\n"); 826 p(ARP_STAT_RCVOVER, "\t\t%" PRIu64 " entry%s overwritten\n"); 827 p(ARP_STAT_RCVLENCHG, "\t\t%" PRIu64 " change%s in hardware address length\n"); 828 829 p(ARP_STAT_DFRTOTAL, "\t%" PRIu64 " packet%s deferred pending ARP resolution\n"); 830 ps(ARP_STAT_DFRSENT, "\t\t%" PRIu64 " sent\n"); 831 ps(ARP_STAT_DFRDROPPED, "\t\t%" PRIu64 " dropped\n"); 832 833 p(ARP_STAT_ALLOCFAIL, "\t%" PRIu64 " failure%s to allocate llinfo\n"); 834 835 #undef ps 836 #undef p 837 } 838 839 /* 840 * Pretty print an Internet address (net address + port). 841 * Take numeric_addr and numeric_port into consideration. 842 */ 843 void 844 inetprint(struct in_addr *in, uint16_t port, const char *proto, 845 int port_numeric) 846 { 847 struct servent *sp = 0; 848 char line[80], *cp; 849 size_t space; 850 851 (void)snprintf(line, sizeof line, "%.*s.", 852 (Aflag && !numeric_addr) ? 12 : 16, inetname(in)); 853 cp = strchr(line, '\0'); 854 if (!port_numeric && port) 855 sp = getservbyport((int)port, proto); 856 space = sizeof line - (cp-line); 857 if (sp || port == 0) 858 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*"); 859 else 860 (void)snprintf(cp, space, "%u", ntohs(port)); 861 (void)printf(" %-*.*s", width, width, line); 862 } 863 864 /* 865 * Construct an Internet address representation. 866 * If numeric_addr has been supplied, give 867 * numeric value, otherwise try for symbolic name. 868 */ 869 char * 870 inetname(struct in_addr *inp) 871 { 872 char *cp; 873 static char line[50]; 874 struct hostent *hp; 875 struct netent *np; 876 static char domain[MAXHOSTNAMELEN + 1]; 877 static int first = 1; 878 879 if (first && !numeric_addr) { 880 first = 0; 881 if (gethostname(domain, sizeof domain) == 0) { 882 domain[sizeof(domain) - 1] = '\0'; 883 if ((cp = strchr(domain, '.'))) 884 (void) strlcpy(domain, cp + 1, sizeof(domain)); 885 else 886 domain[0] = 0; 887 } else 888 domain[0] = 0; 889 } 890 cp = 0; 891 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 892 int net = inet_netof(*inp); 893 int lna = inet_lnaof(*inp); 894 895 if (lna == INADDR_ANY) { 896 np = getnetbyaddr(net, AF_INET); 897 if (np) 898 cp = np->n_name; 899 } 900 if (cp == 0) { 901 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 902 if (hp) { 903 if ((cp = strchr(hp->h_name, '.')) && 904 !strcmp(cp + 1, domain)) 905 *cp = 0; 906 cp = hp->h_name; 907 } 908 } 909 } 910 if (inp->s_addr == INADDR_ANY) 911 strlcpy(line, "*", sizeof line); 912 else if (cp) 913 strlcpy(line, cp, sizeof line); 914 else { 915 inp->s_addr = ntohl(inp->s_addr); 916 #define C(x) ((x) & 0xff) 917 (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 918 C(inp->s_addr >> 24), C(inp->s_addr >> 16), 919 C(inp->s_addr >> 8), C(inp->s_addr)); 920 #undef C 921 } 922 return (line); 923 } 924 925 /* 926 * Dump the contents of a TCP PCB. 927 */ 928 void 929 tcp_dump(u_long pcbaddr) 930 { 931 callout_impl_t *ci; 932 struct tcpcb tcpcb; 933 int i, hardticks; 934 935 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb)); 936 hardticks = get_hardticks(); 937 938 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 939 940 printf("Timers:\n"); 941 for (i = 0; i < TCPT_NTIMERS; i++) { 942 ci = (callout_impl_t *)&tcpcb.t_timer[i]; 943 printf("\t%s: %d", tcptimers[i], 944 (ci->c_flags & CALLOUT_PENDING) ? 945 ci->c_time - hardticks : 0); 946 } 947 printf("\n\n"); 948 949 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 950 printf("State: %d", tcpcb.t_state); 951 else 952 printf("State: %s", tcpstates[tcpcb.t_state]); 953 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags, 954 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb); 955 956 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift, 957 tcpcb.t_rxtcur, tcpcb.t_dupacks); 958 printf("peermss %u, ourmss %u, segsz %u, segqlen %u\n\n", 959 tcpcb.t_peermss, tcpcb.t_ourmss, tcpcb.t_segsz, tcpcb.t_segqlen); 960 961 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 962 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up); 963 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 964 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd); 965 966 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 967 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs); 968 969 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 970 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh); 971 972 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, " 973 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime, 974 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, 975 tcpcb.max_sndwnd); 976 977 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags, 978 tcpcb.t_iobc, tcpcb.t_softerror); 979 980 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 981 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale, 982 tcpcb.requested_s_scale); 983 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 984 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent); 985 } 986