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