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