1 /* $NetBSD: inet.c,v 1.89 2009/02/22 07:43:01 dholland 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.89 2009/02/22 07:43:01 dholland 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 (!aflag && 219 inet_lnaof(dst.sin_addr) == INADDR_ANY) 220 continue; 221 222 if (first) { 223 protoprhdr(); 224 first = 0; 225 } 226 227 protopr0((intptr_t) pcblist[i].ki_ppcbaddr, 228 pcblist[i].ki_rcvq, pcblist[i].ki_sndq, 229 &src.sin_addr, src.sin_port, 230 &dst.sin_addr, dst.sin_port, 231 pcblist[i].ki_tstate, name); 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); 277 } 278 } 279 280 /* 281 * Dump TCP statistics structure. 282 */ 283 void 284 tcp_stats(u_long off, 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, (unsigned long long)tcpstat[f]) 303 #define p(f, m) if (tcpstat[f] || sflag <= 1) \ 304 printf(m, (unsigned long long)tcpstat[f], plural(tcpstat[f])) 305 #define p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 306 printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \ 307 (unsigned long long)tcpstat[f2], plural(tcpstat[f2])) 308 #define p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 309 printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \ 310 (unsigned long long)tcpstat[f2]) 311 #define p3(f, m) if (tcpstat[f] || sflag <= 1) \ 312 printf(m, (unsigned long long)tcpstat[f], plurales(tcpstat[f])) 313 314 p(TCP_STAT_SNDTOTAL, "\t%llu packet%s sent\n"); 315 p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE, 316 "\t\t%llu data packet%s (%llu byte%s)\n"); 317 p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE, 318 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n"); 319 p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK, 320 "\t\t%llu ack-only packet%s (%llu delayed)\n"); 321 p(TCP_STAT_SNDURG, "\t\t%llu URG only packet%s\n"); 322 p(TCP_STAT_SNDPROBE, "\t\t%llu window probe packet%s\n"); 323 p(TCP_STAT_SNDWINUP, "\t\t%llu window update packet%s\n"); 324 p(TCP_STAT_SNDCTRL, "\t\t%llu control packet%s\n"); 325 p(TCP_STAT_SELFQUENCH, 326 "\t\t%llu send attempt%s resulted in self-quench\n"); 327 p(TCP_STAT_RCVTOTAL, "\t%llu packet%s received\n"); 328 p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE, 329 "\t\t%llu ack%s (for %llu byte%s)\n"); 330 p(TCP_STAT_RCVDUPACK, "\t\t%llu duplicate ack%s\n"); 331 p(TCP_STAT_RCVACKTOOMUCH, "\t\t%llu ack%s for unsent data\n"); 332 p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE, 333 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n"); 334 p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE, 335 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n"); 336 p(TCP_STAT_PAWSDROP, "\t\t%llu old duplicate packet%s\n"); 337 p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE, 338 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n"); 339 p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE, 340 "\t\t%llu out-of-order packet%s (%llu byte%s)\n"); 341 p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN, 342 "\t\t%llu packet%s (%llu byte%s) of data after window\n"); 343 p(TCP_STAT_RCVWINPROBE, "\t\t%llu window probe%s\n"); 344 p(TCP_STAT_RCVWINUPD, "\t\t%llu window update packet%s\n"); 345 p(TCP_STAT_RCVAFTERCLOSE, "\t\t%llu packet%s received after close\n"); 346 p(TCP_STAT_RCVBADSUM, "\t\t%llu discarded for bad checksum%s\n"); 347 p(TCP_STAT_RCVBADOFF, "\t\t%llu discarded for bad header offset field%s\n"); 348 ps(TCP_STAT_RCVSHORT, "\t\t%llu discarded because packet too short\n"); 349 p(TCP_STAT_CONNATTEMPT, "\t%llu connection request%s\n"); 350 p(TCP_STAT_ACCEPTS, "\t%llu connection accept%s\n"); 351 p(TCP_STAT_CONNECTS, 352 "\t%llu connection%s established (including accepts)\n"); 353 p2(TCP_STAT_CLOSED, TCP_STAT_DROPS, 354 "\t%llu connection%s closed (including %llu drop%s)\n"); 355 p(TCP_STAT_CONNDROPS, "\t%llu embryonic connection%s dropped\n"); 356 p(TCP_STAT_DELAYED_FREE, "\t%llu delayed free%s of tcpcb\n"); 357 p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED, 358 "\t%llu segment%s updated rtt (of %llu attempt%s)\n"); 359 p(TCP_STAT_REXMTTIMEO, "\t%llu retransmit timeout%s\n"); 360 p(TCP_STAT_TIMEOUTDROP, 361 "\t\t%llu connection%s dropped by rexmit timeout\n"); 362 p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS, 363 "\t%llu persist timeout%s (resulting in %llu dropped " 364 "connection%s)\n"); 365 p(TCP_STAT_KEEPTIMEO, "\t%llu keepalive timeout%s\n"); 366 p(TCP_STAT_KEEPPROBE, "\t\t%llu keepalive probe%s sent\n"); 367 p(TCP_STAT_KEEPDROPS, "\t\t%llu connection%s dropped by keepalive\n"); 368 p(TCP_STAT_PREDACK, "\t%llu correct ACK header prediction%s\n"); 369 p(TCP_STAT_PREDDAT, "\t%llu correct data packet header prediction%s\n"); 370 p3(TCP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n"); 371 ps(TCP_STAT_NOPORT, "\t%llu dropped due to no socket\n"); 372 p(TCP_STAT_CONNSDRAINED, "\t%llu connection%s drained due to memory " 373 "shortage\n"); 374 p(TCP_STAT_PMTUBLACKHOLE, "\t%llu PMTUD blackhole%s detected\n"); 375 376 p(TCP_STAT_BADSYN, "\t%llu bad connection attempt%s\n"); 377 ps(TCP_STAT_SC_ADDED, "\t%llu SYN cache entries added\n"); 378 p(TCP_STAT_SC_COLLISIONS, "\t\t%llu hash collision%s\n"); 379 ps(TCP_STAT_SC_COMPLETED, "\t\t%llu completed\n"); 380 ps(TCP_STAT_SC_ABORTED, "\t\t%llu aborted (no space to build PCB)\n"); 381 ps(TCP_STAT_SC_TIMED_OUT, "\t\t%llu timed out\n"); 382 ps(TCP_STAT_SC_OVERFLOWED, "\t\t%llu dropped due to overflow\n"); 383 ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%llu dropped due to bucket overflow\n"); 384 ps(TCP_STAT_SC_RESET, "\t\t%llu dropped due to RST\n"); 385 ps(TCP_STAT_SC_UNREACH, "\t\t%llu dropped due to ICMP unreachable\n"); 386 ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%llu delayed free of SYN cache " 387 "entries\n"); 388 p(TCP_STAT_SC_RETRANSMITTED, "\t%llu SYN,ACK%s retransmitted\n"); 389 p(TCP_STAT_SC_DUPESYN, "\t%llu duplicate SYN%s received for entries " 390 "already in the cache\n"); 391 p(TCP_STAT_SC_DROPPED, "\t%llu SYN%s dropped (no route or no space)\n"); 392 p(TCP_STAT_BADSIG, "\t%llu packet%s with bad signature\n"); 393 p(TCP_STAT_GOODSIG, "\t%llu packet%s with good signature\n"); 394 395 p(TCP_STAT_ECN_SHS, "\t%llu sucessful ECN handshake%s\n"); 396 p(TCP_STAT_ECN_CE, "\t%llu packet%s with ECN CE bit\n"); 397 p(TCP_STAT_ECN_ECT, "\t%llu 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, 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, (unsigned long long)udpstat[f]) 429 #define p(f, m) if (udpstat[f] || sflag <= 1) \ 430 printf(m, (unsigned long long)udpstat[f], plural(udpstat[f])) 431 #define p3(f, m) if (udpstat[f] || sflag <= 1) \ 432 printf(m, (unsigned long long)udpstat[f], plurales(udpstat[f])) 433 434 p(UDP_STAT_IPACKETS, "\t%llu datagram%s received\n"); 435 ps(UDP_STAT_HDROPS, "\t%llu with incomplete header\n"); 436 ps(UDP_STAT_BADLEN, "\t%llu with bad data length field\n"); 437 ps(UDP_STAT_BADSUM, "\t%llu with bad checksum\n"); 438 ps(UDP_STAT_NOPORT, "\t%llu dropped due to no socket\n"); 439 p(UDP_STAT_NOPORTBCAST, 440 "\t%llu broadcast/multicast datagram%s dropped due to no socket\n"); 441 ps(UDP_STAT_FULLSOCK, "\t%llu 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%llu delivered\n", (unsigned long long)delivered); 451 p3(UDP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n"); 452 p(UDP_STAT_OPACKETS, "\t%llu 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, 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, (unsigned long long)ipstat[f]) 482 #define p(f, m) if (ipstat[f] || sflag <= 1) \ 483 printf(m, (unsigned long long)ipstat[f], plural(ipstat[f])) 484 485 p(IP_STAT_TOTAL, "\t%llu total packet%s received\n"); 486 p(IP_STAT_BADSUM, "\t%llu bad header checksum%s\n"); 487 ps(IP_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n"); 488 ps(IP_STAT_TOOSHORT, "\t%llu with data size < data length\n"); 489 ps(IP_STAT_TOOLONG, "\t%llu with length > max ip packet size\n"); 490 ps(IP_STAT_BADHLEN, "\t%llu with header length < data size\n"); 491 ps(IP_STAT_BADLEN, "\t%llu with data length < header length\n"); 492 ps(IP_STAT_BADOPTIONS, "\t%llu with bad options\n"); 493 ps(IP_STAT_BADVERS, "\t%llu with incorrect version number\n"); 494 p(IP_STAT_FRAGMENTS, "\t%llu fragment%s received\n"); 495 p(IP_STAT_FRAGDROPPED, "\t%llu fragment%s dropped (dup or out of space)\n"); 496 p(IP_STAT_RCVMEMDROP, "\t%llu fragment%s dropped (out of ipqent)\n"); 497 p(IP_STAT_BADFRAGS, "\t%llu malformed fragment%s dropped\n"); 498 p(IP_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n"); 499 p(IP_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n"); 500 p(IP_STAT_DELIVERED, "\t%llu packet%s for this host\n"); 501 p(IP_STAT_NOPROTO, "\t%llu packet%s for unknown/unsupported protocol\n"); 502 p(IP_STAT_FORWARD, "\t%llu packet%s forwarded"); 503 p(IP_STAT_FASTFORWARD, " (%llu packet%s fast forwarded)"); 504 if (ipstat[IP_STAT_FORWARD] || sflag <= 1) 505 putchar('\n'); 506 p(IP_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n"); 507 p(IP_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n"); 508 p(IP_STAT_NOGIF, "\t%llu packet%s no matching gif found\n"); 509 p(IP_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n"); 510 p(IP_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n"); 511 p(IP_STAT_ODROPPED, "\t%llu output packet%s dropped due to no bufs, etc.\n"); 512 p(IP_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n"); 513 p(IP_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n"); 514 p(IP_STAT_OFRAGMENTS, "\t%llu fragment%s created\n"); 515 p(IP_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n"); 516 p(IP_STAT_BADADDR, "\t%llu 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, 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, (unsigned long long)icmpstat[f], plural(icmpstat[f])) 567 568 p(ICMP_STAT_ERROR, "\t%llu call%s to icmp_error\n"); 569 p(ICMP_STAT_OLDICMP, 570 "\t%llu 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: %llu\n", icmpnames[i], 578 (unsigned long long)icmpstat[ICMP_STAT_OUTHIST + i]); 579 } 580 p(ICMP_STAT_BADCODE, "\t%llu message%s with bad code fields\n"); 581 p(ICMP_STAT_TOOSHORT, "\t%llu message%s < minimum length\n"); 582 p(ICMP_STAT_CHECKSUM, "\t%llu bad checksum%s\n"); 583 p(ICMP_STAT_BADLEN, "\t%llu message%s with bad length\n"); 584 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 585 if (icmpstat[ICMP_STAT_INHIST + i] != 0) { 586 if (first) { 587 printf("\tInput histogram:\n"); 588 first = 0; 589 } 590 printf("\t\t%s: %llu\n", icmpnames[i], 591 (unsigned long long)icmpstat[ICMP_STAT_INHIST + i]); 592 } 593 p(ICMP_STAT_REFLECT, "\t%llu message response%s generated\n"); 594 p(ICMP_STAT_PMTUCHG, "\t%llu path MTU change%s\n"); 595 #undef p 596 } 597 598 /* 599 * Dump IGMP statistics structure. 600 */ 601 void 602 igmp_stats(u_long off, char *name) 603 { 604 uint64_t igmpstat[IGMP_NSTATS]; 605 606 if (use_sysctl) { 607 size_t size = sizeof(igmpstat); 608 609 if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size, 610 NULL, 0) == -1) 611 return; 612 } else { 613 warnx("%s stats not available via KVM.", name); 614 return; 615 } 616 617 printf("%s:\n", name); 618 619 #define p(f, m) if (igmpstat[f] || sflag <= 1) \ 620 printf(m, (unsigned long long)igmpstat[f], plural(igmpstat[f])) 621 #define py(f, m) if (igmpstat[f] || sflag <= 1) \ 622 printf(m, (unsigned long long)igmpstat[f], igmpstat[f] != 1 ? "ies" : "y") 623 p(IGMP_STAT_RCV_TOTAL, "\t%llu message%s received\n"); 624 p(IGMP_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n"); 625 p(IGMP_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n"); 626 py(IGMP_STAT_RCV_QUERIES, "\t%llu membership quer%s received\n"); 627 py(IGMP_STAT_RCV_BADQUERIES, "\t%llu membership quer%s received with invalid field(s)\n"); 628 p(IGMP_STAT_RCV_REPORTS, "\t%llu membership report%s received\n"); 629 p(IGMP_STAT_RCV_BADREPORTS, "\t%llu membership report%s received with invalid field(s)\n"); 630 p(IGMP_STAT_RCV_OURREPORTS, "\t%llu membership report%s received for groups to which we belong\n"); 631 p(IGMP_STAT_SND_REPORTS, "\t%llu membership report%s sent\n"); 632 #undef p 633 #undef py 634 } 635 636 /* 637 * Dump CARP statistics structure. 638 */ 639 void 640 carp_stats(u_long off, char *name) 641 { 642 uint64_t carpstat[CARP_NSTATS]; 643 644 if (use_sysctl) { 645 size_t size = sizeof(carpstat); 646 647 if (sysctlbyname("net.inet.carp.stats", carpstat, &size, 648 NULL, 0) == -1) 649 return; 650 } else { 651 warnx("%s stats not available via KVM.", name); 652 return; 653 } 654 655 printf("%s:\n", name); 656 657 #define p(f, m) if (carpstat[f] || sflag <= 1) \ 658 printf(m, carpstat[f], plural(carpstat[f])) 659 #define p2(f, m) if (carpstat[f] || sflag <= 1) \ 660 printf(m, carpstat[f]) 661 662 p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n"); 663 p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n"); 664 p(CARP_STAT_BADIF, 665 "\t\t%" PRIu64 " packet%s discarded for bad interface\n"); 666 p(CARP_STAT_BADTTL, 667 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n"); 668 p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n"); 669 p(CARP_STAT_BADSUM, "\t\t%" PRIu64 670 " packet%s discarded for bad checksum\n"); 671 p(CARP_STAT_BADVER, 672 "\t\t%" PRIu64 " packet%s discarded with a bad version\n"); 673 p2(CARP_STAT_BADLEN, 674 "\t\t%" PRIu64 " discarded because packet was too short\n"); 675 p(CARP_STAT_BADAUTH, 676 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n"); 677 p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); 678 p(CARP_STAT_BADADDRS, "\t\t%" PRIu64 679 " packet%s discarded because of a bad address list\n"); 680 p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n"); 681 p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); 682 p2(CARP_STAT_ONOMEM, 683 "\t\t%" PRIu64 " send failed due to mbuf memory error\n"); 684 #undef p 685 #undef p2 686 } 687 688 /* 689 * Dump PIM statistics structure. 690 */ 691 void 692 pim_stats(u_long off, char *name) 693 { 694 struct pimstat pimstat; 695 696 if (off == 0) 697 return; 698 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) { 699 /* XXX: PIM is probably not enabled in the kernel */ 700 return; 701 } 702 703 printf("%s:\n", name); 704 705 #define p(f, m) if (pimstat.f || sflag <= 1) \ 706 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f)) 707 708 p(pims_rcv_total_msgs, "\t%llu message%s received\n"); 709 p(pims_rcv_total_bytes, "\t%llu byte%s received\n"); 710 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 711 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 712 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n"); 713 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n"); 714 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n"); 715 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n"); 716 p(pims_rcv_badregisters, "\t%llu bad register%s received\n"); 717 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n"); 718 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n"); 719 #undef p 720 } 721 722 /* 723 * Dump the ARP statistics structure. 724 */ 725 void 726 arp_stats(u_long off, char *name) 727 { 728 uint64_t arpstat[ARP_NSTATS]; 729 730 if (use_sysctl) { 731 size_t size = sizeof(arpstat); 732 733 if (sysctlbyname("net.inet.arp.stats", arpstat, &size, 734 NULL, 0) == -1) 735 return; 736 } else { 737 warnx("%s stats not available via KVM.", name); 738 return; 739 } 740 741 printf("%s:\n", name); 742 743 #define ps(f, m) if (arpstat[f] || sflag <= 1) \ 744 printf(m, (unsigned long long)arpstat[f]) 745 #define p(f, m) if (arpstat[f] || sflag <= 1) \ 746 printf(m, (unsigned long long)arpstat[f], plural(arpstat[f])) 747 748 p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n"); 749 p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n"); 750 p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n"); 751 752 p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n"); 753 p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n"); 754 p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n"); 755 p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n"); 756 p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n"); 757 p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n"); 758 p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n"); 759 p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n"); 760 ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n"); 761 p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware " 762 "address\n"); 763 p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast " 764 "source hardware address\n"); 765 p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n"); 766 p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n"); 767 p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n"); 768 p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n"); 769 p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n"); 770 771 p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n"); 772 ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n"); 773 ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n"); 774 775 p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n"); 776 777 #undef ps 778 #undef p 779 } 780 781 /* 782 * Pretty print an Internet address (net address + port). 783 * Take numeric_addr and numeric_port into consideration. 784 */ 785 void 786 inetprint(struct in_addr *in, uint16_t port, const char *proto, 787 int numeric_port) 788 { 789 struct servent *sp = 0; 790 char line[80], *cp; 791 size_t space; 792 793 (void)snprintf(line, sizeof line, "%.*s.", 794 (Aflag && !numeric_addr) ? 12 : 16, inetname(in)); 795 cp = strchr(line, '\0'); 796 if (!numeric_port && port) 797 sp = getservbyport((int)port, proto); 798 space = sizeof line - (cp-line); 799 if (sp || port == 0) 800 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*"); 801 else 802 (void)snprintf(cp, space, "%u", ntohs(port)); 803 (void)printf(" %-*.*s", width, width, line); 804 } 805 806 /* 807 * Construct an Internet address representation. 808 * If numeric_addr has been supplied, give 809 * numeric value, otherwise try for symbolic name. 810 */ 811 char * 812 inetname(struct in_addr *inp) 813 { 814 char *cp; 815 static char line[50]; 816 struct hostent *hp; 817 struct netent *np; 818 static char domain[MAXHOSTNAMELEN + 1]; 819 static int first = 1; 820 821 if (first && !numeric_addr) { 822 first = 0; 823 if (gethostname(domain, sizeof domain) == 0) { 824 domain[sizeof(domain) - 1] = '\0'; 825 if ((cp = strchr(domain, '.'))) 826 (void) strlcpy(domain, cp + 1, sizeof(domain)); 827 else 828 domain[0] = 0; 829 } else 830 domain[0] = 0; 831 } 832 cp = 0; 833 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 834 int net = inet_netof(*inp); 835 int lna = inet_lnaof(*inp); 836 837 if (lna == INADDR_ANY) { 838 np = getnetbyaddr(net, AF_INET); 839 if (np) 840 cp = np->n_name; 841 } 842 if (cp == 0) { 843 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 844 if (hp) { 845 if ((cp = strchr(hp->h_name, '.')) && 846 !strcmp(cp + 1, domain)) 847 *cp = 0; 848 cp = hp->h_name; 849 } 850 } 851 } 852 if (inp->s_addr == INADDR_ANY) 853 strlcpy(line, "*", sizeof line); 854 else if (cp) 855 strlcpy(line, cp, sizeof line); 856 else { 857 inp->s_addr = ntohl(inp->s_addr); 858 #define C(x) ((x) & 0xff) 859 (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 860 C(inp->s_addr >> 24), C(inp->s_addr >> 16), 861 C(inp->s_addr >> 8), C(inp->s_addr)); 862 #undef C 863 } 864 return (line); 865 } 866 867 /* 868 * Dump the contents of a TCP PCB. 869 */ 870 void 871 tcp_dump(u_long pcbaddr) 872 { 873 callout_impl_t *ci; 874 struct tcpcb tcpcb; 875 int i, hardticks; 876 877 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb)); 878 hardticks = get_hardticks(); 879 880 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 881 882 printf("Timers:\n"); 883 for (i = 0; i < TCPT_NTIMERS; i++) { 884 ci = (callout_impl_t *)&tcpcb.t_timer[i]; 885 printf("\t%s: %d", tcptimers[i], 886 (ci->c_flags & CALLOUT_PENDING) ? 887 ci->c_time - hardticks : 0); 888 } 889 printf("\n\n"); 890 891 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 892 printf("State: %d", tcpcb.t_state); 893 else 894 printf("State: %s", tcpstates[tcpcb.t_state]); 895 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags, 896 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb); 897 898 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift, 899 tcpcb.t_rxtcur, tcpcb.t_dupacks); 900 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss, 901 tcpcb.t_ourmss, tcpcb.t_segsz); 902 903 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 904 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up); 905 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 906 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd); 907 908 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 909 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs); 910 911 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 912 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh); 913 914 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, " 915 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime, 916 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, 917 tcpcb.max_sndwnd); 918 919 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags, 920 tcpcb.t_iobc, tcpcb.t_softerror); 921 922 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 923 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale, 924 tcpcb.requested_s_scale); 925 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 926 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent); 927 } 928