1 /* 2 * Copyright (c) 1983, 1988, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #if 0 35 #ifndef lint 36 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 37 #endif /* not lint */ 38 #endif 39 40 #include <sys/cdefs.h> 41 __FBSDID("$FreeBSD$"); 42 43 #include <sys/param.h> 44 #include <sys/queue.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/sysctl.h> 48 #include <sys/protosw.h> 49 50 #include <net/route.h> 51 #include <netinet/in.h> 52 #include <netinet/in_systm.h> 53 #include <netinet/ip.h> 54 #include <netinet/ip_carp.h> 55 #ifdef INET6 56 #include <netinet/ip6.h> 57 #endif /* INET6 */ 58 #include <netinet/in_pcb.h> 59 #include <netinet/ip_icmp.h> 60 #include <netinet/icmp_var.h> 61 #include <netinet/igmp_var.h> 62 #include <netinet/ip_var.h> 63 #include <netinet/pim_var.h> 64 #include <netinet/tcp.h> 65 #include <netinet/tcpip.h> 66 #include <netinet/tcp_seq.h> 67 #define TCPSTATES 68 #include <netinet/tcp_fsm.h> 69 #include <netinet/tcp_timer.h> 70 #include <netinet/tcp_var.h> 71 #include <netinet/tcp_debug.h> 72 #include <netinet/udp.h> 73 #include <netinet/udp_var.h> 74 75 #include <arpa/inet.h> 76 #include <err.h> 77 #include <errno.h> 78 #include <libutil.h> 79 #include <netdb.h> 80 #include <stdint.h> 81 #include <stdio.h> 82 #include <stdlib.h> 83 #include <string.h> 84 #include <unistd.h> 85 #include "netstat.h" 86 87 char *inetname (struct in_addr *); 88 void inetprint (struct in_addr *, int, const char *, int); 89 #ifdef INET6 90 static int udp_done, tcp_done; 91 #endif /* INET6 */ 92 93 /* 94 * Print a summary of connections related to an Internet 95 * protocol. For TCP, also give state of connection. 96 * Listening processes (aflag) are suppressed unless the 97 * -a (all) flag is specified. 98 */ 99 void 100 protopr(u_long proto, /* for sysctl version we pass proto # */ 101 const char *name, int af1) 102 { 103 int istcp; 104 static int first = 1; 105 char *buf; 106 const char *mibvar, *vchar; 107 struct tcpcb *tp = NULL; 108 struct inpcb *inp; 109 struct xinpgen *xig, *oxig; 110 struct xsocket *so; 111 size_t len; 112 113 istcp = 0; 114 switch (proto) { 115 case IPPROTO_TCP: 116 #ifdef INET6 117 if (tcp_done != 0) 118 return; 119 else 120 tcp_done = 1; 121 #endif 122 istcp = 1; 123 mibvar = "net.inet.tcp.pcblist"; 124 break; 125 case IPPROTO_UDP: 126 #ifdef INET6 127 if (udp_done != 0) 128 return; 129 else 130 udp_done = 1; 131 #endif 132 mibvar = "net.inet.udp.pcblist"; 133 break; 134 case IPPROTO_DIVERT: 135 mibvar = "net.inet.divert.pcblist"; 136 break; 137 default: 138 mibvar = "net.inet.raw.pcblist"; 139 break; 140 } 141 len = 0; 142 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { 143 if (errno != ENOENT) 144 warn("sysctl: %s", mibvar); 145 return; 146 } 147 if ((buf = malloc(len)) == 0) { 148 warnx("malloc %lu bytes", (u_long)len); 149 return; 150 } 151 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { 152 warn("sysctl: %s", mibvar); 153 free(buf); 154 return; 155 } 156 157 oxig = xig = (struct xinpgen *)buf; 158 for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); 159 xig->xig_len > sizeof(struct xinpgen); 160 xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { 161 if (istcp) { 162 tp = &((struct xtcpcb *)xig)->xt_tp; 163 inp = &((struct xtcpcb *)xig)->xt_inp; 164 so = &((struct xtcpcb *)xig)->xt_socket; 165 } else { 166 inp = &((struct xinpcb *)xig)->xi_inp; 167 so = &((struct xinpcb *)xig)->xi_socket; 168 } 169 170 /* Ignore sockets for protocols other than the desired one. */ 171 if (so->xso_protocol != (int)proto) 172 continue; 173 174 /* Ignore PCBs which were freed during copyout. */ 175 if (inp->inp_gencnt > oxig->xig_gen) 176 continue; 177 178 if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) 179 #ifdef INET6 180 || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) 181 #endif /* INET6 */ 182 || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 183 #ifdef INET6 184 && (inp->inp_vflag & 185 INP_IPV6) == 0 186 #endif /* INET6 */ 187 )) 188 ) 189 continue; 190 if (!aflag && 191 ( 192 (istcp && tp->t_state == TCPS_LISTEN) 193 || (af1 == AF_INET && 194 inet_lnaof(inp->inp_laddr) == INADDR_ANY) 195 #ifdef INET6 196 || (af1 == AF_INET6 && 197 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 198 #endif /* INET6 */ 199 || (af1 == AF_UNSPEC && 200 (((inp->inp_vflag & INP_IPV4) != 0 && 201 inet_lnaof(inp->inp_laddr) == INADDR_ANY) 202 #ifdef INET6 203 || ((inp->inp_vflag & INP_IPV6) != 0 && 204 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 205 #endif 206 )) 207 )) 208 continue; 209 210 if (first) { 211 if (!Lflag) { 212 printf("Active Internet connections"); 213 if (aflag) 214 printf(" (including servers)"); 215 } else 216 printf( 217 "Current listen queue sizes (qlen/incqlen/maxqlen)"); 218 putchar('\n'); 219 if (Aflag) 220 printf("%-8.8s ", "Socket"); 221 if (Lflag) 222 printf("%-5.5s %-14.14s %-22.22s\n", 223 "Proto", "Listen", "Local Address"); 224 else 225 printf((Aflag && !Wflag) ? 226 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 227 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 228 "Proto", "Recv-Q", "Send-Q", 229 "Local Address", "Foreign Address", 230 "(state)"); 231 first = 0; 232 } 233 if (Lflag && so->so_qlimit == 0) 234 continue; 235 if (Aflag) { 236 if (istcp) 237 printf("%8lx ", (u_long)inp->inp_ppcb); 238 else 239 printf("%8lx ", (u_long)so->so_pcb); 240 } 241 #ifdef INET6 242 if ((inp->inp_vflag & INP_IPV6) != 0) 243 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 244 ? "46" : "6 "; 245 else 246 #endif 247 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 248 ? "4 " : " "; 249 printf("%-3.3s%-2.2s ", name, vchar); 250 if (Lflag) { 251 char buf1[15]; 252 253 snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, 254 so->so_incqlen, so->so_qlimit); 255 printf("%-14.14s ", buf1); 256 } else { 257 printf("%6u %6u ", 258 so->so_rcv.sb_cc, 259 so->so_snd.sb_cc); 260 } 261 if (numeric_port) { 262 if (inp->inp_vflag & INP_IPV4) { 263 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 264 name, 1); 265 if (!Lflag) 266 inetprint(&inp->inp_faddr, 267 (int)inp->inp_fport, name, 1); 268 } 269 #ifdef INET6 270 else if (inp->inp_vflag & INP_IPV6) { 271 inet6print(&inp->in6p_laddr, 272 (int)inp->inp_lport, name, 1); 273 if (!Lflag) 274 inet6print(&inp->in6p_faddr, 275 (int)inp->inp_fport, name, 1); 276 } /* else nothing printed now */ 277 #endif /* INET6 */ 278 } else if (inp->inp_flags & INP_ANONPORT) { 279 if (inp->inp_vflag & INP_IPV4) { 280 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 281 name, 1); 282 if (!Lflag) 283 inetprint(&inp->inp_faddr, 284 (int)inp->inp_fport, name, 0); 285 } 286 #ifdef INET6 287 else if (inp->inp_vflag & INP_IPV6) { 288 inet6print(&inp->in6p_laddr, 289 (int)inp->inp_lport, name, 1); 290 if (!Lflag) 291 inet6print(&inp->in6p_faddr, 292 (int)inp->inp_fport, name, 0); 293 } /* else nothing printed now */ 294 #endif /* INET6 */ 295 } else { 296 if (inp->inp_vflag & INP_IPV4) { 297 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 298 name, 0); 299 if (!Lflag) 300 inetprint(&inp->inp_faddr, 301 (int)inp->inp_fport, name, 302 inp->inp_lport != 303 inp->inp_fport); 304 } 305 #ifdef INET6 306 else if (inp->inp_vflag & INP_IPV6) { 307 inet6print(&inp->in6p_laddr, 308 (int)inp->inp_lport, name, 0); 309 if (!Lflag) 310 inet6print(&inp->in6p_faddr, 311 (int)inp->inp_fport, name, 312 inp->inp_lport != 313 inp->inp_fport); 314 } /* else nothing printed now */ 315 #endif /* INET6 */ 316 } 317 if (istcp && !Lflag) { 318 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) 319 printf("%d", tp->t_state); 320 else { 321 printf("%s", tcpstates[tp->t_state]); 322 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 323 /* Show T/TCP `hidden state' */ 324 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 325 putchar('*'); 326 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 327 } 328 } 329 putchar('\n'); 330 } 331 if (xig != oxig && xig->xig_gen != oxig->xig_gen) { 332 if (oxig->xig_count > xig->xig_count) { 333 printf("Some %s sockets may have been deleted.\n", 334 name); 335 } else if (oxig->xig_count < xig->xig_count) { 336 printf("Some %s sockets may have been created.\n", 337 name); 338 } else { 339 printf("Some %s sockets may have been created or deleted.\n", 340 name); 341 } 342 } 343 free(buf); 344 } 345 346 /* 347 * Dump TCP statistics structure. 348 */ 349 void 350 tcp_stats(u_long off __unused, const char *name, int af1 __unused) 351 { 352 struct tcpstat tcpstat, zerostat; 353 size_t len = sizeof tcpstat; 354 355 if (zflag) 356 memset(&zerostat, 0, len); 357 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 358 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 359 warn("sysctl: net.inet.tcp.stats"); 360 return; 361 } 362 363 #ifdef INET6 364 if (tcp_done != 0) 365 return; 366 else 367 tcp_done = 1; 368 #endif 369 370 printf ("%s:\n", name); 371 372 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 373 printf(m, tcpstat.f, plural(tcpstat.f)) 374 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ 375 printf(m, tcpstat.f) 376 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 377 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 378 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 379 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) 380 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 381 printf(m, tcpstat.f, plurales(tcpstat.f)) 382 383 p(tcps_sndtotal, "\t%lu packet%s sent\n"); 384 p2(tcps_sndpack,tcps_sndbyte, 385 "\t\t%lu data packet%s (%lu byte%s)\n"); 386 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 387 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); 388 p(tcps_sndrexmitbad, 389 "\t\t%lu data packet%s unnecessarily retransmitted\n"); 390 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); 391 p2a(tcps_sndacks, tcps_delack, 392 "\t\t%lu ack-only packet%s (%lu delayed)\n"); 393 p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); 394 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); 395 p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); 396 p(tcps_sndctrl, "\t\t%lu control packet%s\n"); 397 p(tcps_rcvtotal, "\t%lu packet%s received\n"); 398 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); 399 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); 400 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); 401 p2(tcps_rcvpack, tcps_rcvbyte, 402 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); 403 p2(tcps_rcvduppack, tcps_rcvdupbyte, 404 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); 405 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); 406 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 407 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); 408 p2(tcps_rcvoopack, tcps_rcvoobyte, 409 "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); 410 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 411 "\t\t%lu packet%s (%lu byte%s) of data after window\n"); 412 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); 413 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); 414 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); 415 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); 416 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); 417 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); 418 p(tcps_connattempt, "\t%lu connection request%s\n"); 419 p(tcps_accepts, "\t%lu connection accept%s\n"); 420 p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); 421 p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); 422 p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n"); 423 p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); 424 p2(tcps_closed, tcps_drops, 425 "\t%lu connection%s closed (including %lu drop%s)\n"); 426 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); 427 p(tcps_cachedrttvar, 428 "\t\t%lu connection%s updated cached RTT variance on close\n"); 429 p(tcps_cachedssthresh, 430 "\t\t%lu connection%s updated cached ssthresh on close\n"); 431 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); 432 p2(tcps_rttupdated, tcps_segstimed, 433 "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); 434 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); 435 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); 436 p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); 437 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); 438 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); 439 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); 440 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); 441 p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); 442 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); 443 444 p(tcps_sc_added, "\t%lu syncache entrie%s added\n"); 445 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); 446 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); 447 p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); 448 p1a(tcps_sc_completed, "\t\t%lu completed\n"); 449 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); 450 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); 451 p1a(tcps_sc_reset, "\t\t%lu reset\n"); 452 p1a(tcps_sc_stale, "\t\t%lu stale\n"); 453 p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); 454 p1a(tcps_sc_badack, "\t\t%lu badack\n"); 455 p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); 456 p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n"); 457 p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n"); 458 p(tcps_sc_recvcookie, "\t%lu cookie%s received\n"); 459 460 p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n"); 461 p(tcps_sack_rexmits, 462 "\t%lu segment rexmit%s in SACK recovery episodes\n"); 463 p(tcps_sack_rexmit_bytes, 464 "\t%lu byte rexmit%s in SACK recovery episodes\n"); 465 p(tcps_sack_rcv_blocks, 466 "\t%lu SACK option%s (SACK blocks) received\n"); 467 p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n"); 468 p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n"); 469 470 #undef p 471 #undef p1a 472 #undef p2 473 #undef p2a 474 #undef p3 475 } 476 477 /* 478 * Dump UDP statistics structure. 479 */ 480 void 481 udp_stats(u_long off __unused, const char *name, int af1 __unused) 482 { 483 struct udpstat udpstat, zerostat; 484 size_t len = sizeof udpstat; 485 u_long delivered; 486 487 if (zflag) 488 memset(&zerostat, 0, len); 489 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 490 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 491 warn("sysctl: net.inet.udp.stats"); 492 return; 493 } 494 495 #ifdef INET6 496 if (udp_done != 0) 497 return; 498 else 499 udp_done = 1; 500 #endif 501 502 printf("%s:\n", name); 503 #define p(f, m) if (udpstat.f || sflag <= 1) \ 504 printf(m, udpstat.f, plural(udpstat.f)) 505 #define p1a(f, m) if (udpstat.f || sflag <= 1) \ 506 printf(m, udpstat.f) 507 p(udps_ipackets, "\t%lu datagram%s received\n"); 508 p1a(udps_hdrops, "\t%lu with incomplete header\n"); 509 p1a(udps_badlen, "\t%lu with bad data length field\n"); 510 p1a(udps_badsum, "\t%lu with bad checksum\n"); 511 p1a(udps_nosum, "\t%lu with no checksum\n"); 512 p1a(udps_noport, "\t%lu dropped due to no socket\n"); 513 p(udps_noportbcast, 514 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); 515 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); 516 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); 517 delivered = udpstat.udps_ipackets - 518 udpstat.udps_hdrops - 519 udpstat.udps_badlen - 520 udpstat.udps_badsum - 521 udpstat.udps_noport - 522 udpstat.udps_noportbcast - 523 udpstat.udps_fullsock; 524 if (delivered || sflag <= 1) 525 printf("\t%lu delivered\n", delivered); 526 p(udps_opackets, "\t%lu datagram%s output\n"); 527 #undef p 528 #undef p1a 529 } 530 531 /* 532 * Dump CARP statistics structure. 533 */ 534 void 535 carp_stats(u_long off __unused, const char *name, int af1 __unused) 536 { 537 struct carpstats carpstat, zerostat; 538 size_t len = sizeof(struct carpstats); 539 540 if (zflag) 541 memset(&zerostat, 0, len); 542 if (sysctlbyname("net.inet.carp.stats", &carpstat, &len, 543 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 544 if (errno != ENOENT) 545 warn("sysctl: net.inet.carp.stats"); 546 return; 547 } 548 549 printf("%s:\n", name); 550 551 #define p(f, m) if (carpstat.f || sflag <= 1) \ 552 printf(m, (uintmax_t)carpstat.f, plural(carpstat.f)) 553 #define p2(f, m) if (carpstat.f || sflag <= 1) \ 554 printf(m, (uintmax_t)carpstat.f) 555 556 p(carps_ipackets, "\t%ju packet%s received (IPv4)\n"); 557 p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n"); 558 p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n"); 559 p(carps_hdrops, "\t\t%ju packet%s shorter than header\n"); 560 p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n"); 561 p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n"); 562 p2(carps_badlen, "\t\t%ju discarded because packet too short\n"); 563 p2(carps_badauth, "\t\t%ju discarded for bad authentication\n"); 564 p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n"); 565 p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n"); 566 p(carps_opackets, "\t%ju packet%s sent (IPv4)\n"); 567 p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n"); 568 p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n"); 569 #if notyet 570 p(carps_ostates, "\t\t%s state update%s sent\n"); 571 #endif 572 #undef p 573 #undef p2 574 } 575 576 /* 577 * Dump IP statistics structure. 578 */ 579 void 580 ip_stats(u_long off __unused, const char *name, int af1 __unused) 581 { 582 struct ipstat ipstat, zerostat; 583 size_t len = sizeof ipstat; 584 585 if (zflag) 586 memset(&zerostat, 0, len); 587 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 588 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 589 warn("sysctl: net.inet.ip.stats"); 590 return; 591 } 592 593 printf("%s:\n", name); 594 595 #define p(f, m) if (ipstat.f || sflag <= 1) \ 596 printf(m, ipstat.f, plural(ipstat.f)) 597 #define p1a(f, m) if (ipstat.f || sflag <= 1) \ 598 printf(m, ipstat.f) 599 600 p(ips_total, "\t%lu total packet%s received\n"); 601 p(ips_badsum, "\t%lu bad header checksum%s\n"); 602 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); 603 p1a(ips_tooshort, "\t%lu with data size < data length\n"); 604 p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n"); 605 p1a(ips_badhlen, "\t%lu with header length < data size\n"); 606 p1a(ips_badlen, "\t%lu with data length < header length\n"); 607 p1a(ips_badoptions, "\t%lu with bad options\n"); 608 p1a(ips_badvers, "\t%lu with incorrect version number\n"); 609 p(ips_fragments, "\t%lu fragment%s received\n"); 610 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); 611 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); 612 p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); 613 p(ips_delivered, "\t%lu packet%s for this host\n"); 614 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); 615 p(ips_forward, "\t%lu packet%s forwarded"); 616 p(ips_fastforward, " (%lu packet%s fast forwarded)"); 617 if (ipstat.ips_forward || sflag <= 1) 618 putchar('\n'); 619 p(ips_cantforward, "\t%lu packet%s not forwardable\n"); 620 p(ips_notmember, 621 "\t%lu packet%s received for unknown multicast group\n"); 622 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 623 p(ips_localout, "\t%lu packet%s sent from this host\n"); 624 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 625 p(ips_odropped, 626 "\t%lu output packet%s dropped due to no bufs, etc.\n"); 627 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 628 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 629 p(ips_ofragments, "\t%lu fragment%s created\n"); 630 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 631 p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n"); 632 p(ips_badaddr, "\t%lu datagram%s with bad address in header\n"); 633 #undef p 634 #undef p1a 635 } 636 637 static const char *icmpnames[] = { 638 "echo reply", 639 "#1", 640 "#2", 641 "destination unreachable", 642 "source quench", 643 "routing redirect", 644 "#6", 645 "#7", 646 "echo", 647 "router advertisement", 648 "router solicitation", 649 "time exceeded", 650 "parameter problem", 651 "time stamp", 652 "time stamp reply", 653 "information request", 654 "information request reply", 655 "address mask request", 656 "address mask reply", 657 }; 658 659 /* 660 * Dump ICMP statistics. 661 */ 662 void 663 icmp_stats(u_long off __unused, const char *name, int af1 __unused) 664 { 665 struct icmpstat icmpstat, zerostat; 666 int i, first; 667 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ 668 size_t len; 669 670 mib[0] = CTL_NET; 671 mib[1] = PF_INET; 672 mib[2] = IPPROTO_ICMP; 673 mib[3] = ICMPCTL_STATS; 674 675 len = sizeof icmpstat; 676 if (zflag) 677 memset(&zerostat, 0, len); 678 if (sysctl(mib, 4, &icmpstat, &len, 679 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 680 warn("sysctl: net.inet.icmp.stats"); 681 return; 682 } 683 684 printf("%s:\n", name); 685 686 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 687 printf(m, icmpstat.f, plural(icmpstat.f)) 688 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \ 689 printf(m, icmpstat.f) 690 #define p2(f, m) if (icmpstat.f || sflag <= 1) \ 691 printf(m, icmpstat.f, plurales(icmpstat.f)) 692 693 p(icps_error, "\t%lu call%s to icmp_error\n"); 694 p(icps_oldicmp, 695 "\t%lu error%s not generated in response to an icmp message\n"); 696 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 697 if (icmpstat.icps_outhist[i] != 0) { 698 if (first) { 699 printf("\tOutput histogram:\n"); 700 first = 0; 701 } 702 printf("\t\t%s: %lu\n", icmpnames[i], 703 icmpstat.icps_outhist[i]); 704 } 705 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 706 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 707 p(icps_checksum, "\t%lu bad checksum%s\n"); 708 p(icps_badlen, "\t%lu message%s with bad length\n"); 709 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); 710 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); 711 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 712 if (icmpstat.icps_inhist[i] != 0) { 713 if (first) { 714 printf("\tInput histogram:\n"); 715 first = 0; 716 } 717 printf("\t\t%s: %lu\n", icmpnames[i], 718 icmpstat.icps_inhist[i]); 719 } 720 p(icps_reflect, "\t%lu message response%s generated\n"); 721 p2(icps_badaddr, "\t%lu invalid return address%s\n"); 722 p(icps_noroute, "\t%lu no return route%s\n"); 723 #undef p 724 #undef p1a 725 #undef p2 726 mib[3] = ICMPCTL_MASKREPL; 727 len = sizeof i; 728 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0) 729 return; 730 printf("\tICMP address mask responses are %sabled\n", 731 i ? "en" : "dis"); 732 } 733 734 /* 735 * Dump IGMP statistics structure. 736 */ 737 void 738 igmp_stats(u_long off __unused, const char *name, int af1 __unused) 739 { 740 struct igmpstat igmpstat, zerostat; 741 size_t len = sizeof igmpstat; 742 743 if (zflag) 744 memset(&zerostat, 0, len); 745 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 746 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 747 warn("sysctl: net.inet.igmp.stats"); 748 return; 749 } 750 751 printf("%s:\n", name); 752 753 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 754 printf(m, igmpstat.f, plural(igmpstat.f)) 755 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 756 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 757 p(igps_rcv_total, "\t%u message%s received\n"); 758 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 759 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 760 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 761 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 762 p(igps_rcv_reports, "\t%u membership report%s received\n"); 763 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 764 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 765 p(igps_snd_reports, "\t%u membership report%s sent\n"); 766 #undef p 767 #undef py 768 } 769 770 /* 771 * Dump PIM statistics structure. 772 */ 773 void 774 pim_stats(u_long off __unused, const char *name, int af1 __unused) 775 { 776 struct pimstat pimstat, zerostat; 777 size_t len = sizeof pimstat; 778 779 if (zflag) 780 memset(&zerostat, 0, len); 781 if (sysctlbyname("net.inet.pim.stats", &pimstat, &len, 782 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 783 if (errno != ENOENT) 784 warn("sysctl: net.inet.pim.stats"); 785 return; 786 } 787 788 printf("%s:\n", name); 789 790 #define p(f, m) if (pimstat.f || sflag <= 1) \ 791 printf(m, (uintmax_t)pimstat.f, plural(pimstat.f)) 792 #define py(f, m) if (pimstat.f || sflag <= 1) \ 793 printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y") 794 p(pims_rcv_total_msgs, "\t%ju message%s received\n"); 795 p(pims_rcv_total_bytes, "\t%ju byte%s received\n"); 796 p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); 797 p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n"); 798 p(pims_rcv_badversion, "\t%ju message%s received with bad version\n"); 799 p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n"); 800 p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n"); 801 p(pims_rcv_registers_wrongiif, "\t%ju data register message%s received on wrong iif\n"); 802 p(pims_rcv_badregisters, "\t%ju bad register%s received\n"); 803 p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n"); 804 p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n"); 805 #undef p 806 #undef py 807 } 808 809 /* 810 * Pretty print an Internet address (net address + port). 811 */ 812 void 813 inetprint(struct in_addr *in, int port, const char *proto, int num_port) 814 { 815 struct servent *sp = 0; 816 char line[80], *cp; 817 int width; 818 819 if (Wflag) 820 sprintf(line, "%s.", inetname(in)); 821 else 822 sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in)); 823 cp = index(line, '\0'); 824 if (!num_port && port) 825 sp = getservbyport((int)port, proto); 826 if (sp || port == 0) 827 sprintf(cp, "%.15s ", sp ? sp->s_name : "*"); 828 else 829 sprintf(cp, "%d ", ntohs((u_short)port)); 830 width = (Aflag && !Wflag) ? 18 : 22; 831 if (Wflag) 832 printf("%-*s ", width, line); 833 else 834 printf("%-*.*s ", width, width, line); 835 } 836 837 /* 838 * Construct an Internet address representation. 839 * If numeric_addr has been supplied, give 840 * numeric value, otherwise try for symbolic name. 841 */ 842 char * 843 inetname(struct in_addr *inp) 844 { 845 char *cp; 846 static char line[MAXHOSTNAMELEN]; 847 struct hostent *hp; 848 struct netent *np; 849 850 cp = 0; 851 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 852 int net = inet_netof(*inp); 853 int lna = inet_lnaof(*inp); 854 855 if (lna == INADDR_ANY) { 856 np = getnetbyaddr(net, AF_INET); 857 if (np) 858 cp = np->n_name; 859 } 860 if (cp == 0) { 861 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 862 if (hp) { 863 cp = hp->h_name; 864 trimdomain(cp, strlen(cp)); 865 } 866 } 867 } 868 if (inp->s_addr == INADDR_ANY) 869 strcpy(line, "*"); 870 else if (cp) { 871 strncpy(line, cp, sizeof(line) - 1); 872 line[sizeof(line) - 1] = '\0'; 873 } else { 874 inp->s_addr = ntohl(inp->s_addr); 875 #define C(x) ((u_int)((x) & 0xff)) 876 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), 877 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 878 } 879 return (line); 880 } 881