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