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