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