1/* 2 * Copyright (c) 2008-2014 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 ** @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 26 */ 27/* 28 * Copyright (c) 1983, 1988, 1993, 1995 29 * The Regents of the University of California. All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions 33 * are met: 34 * 1. Redistributions of source code must retain the above copyright 35 * notice, this list of conditions and the following disclaimer. 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 3. All advertising materials mentioning features or use of this software 40 * must display the following acknowledgement: 41 * This product includes software developed by the University of 42 * California, Berkeley and its contributors. 43 * 4. Neither the name of the University nor the names of its contributors 44 * may be used to endorse or promote products derived from this software 45 * without specific prior written permission. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 57 * SUCH DAMAGE. 58 */ 59 60#include <sys/param.h> 61#include <sys/queue.h> 62#include <sys/socket.h> 63#include <sys/socketvar.h> 64#include <sys/sysctl.h> 65 66#include <net/route.h> 67#include <net/if_arp.h> 68#include <netinet/in.h> 69#include <netinet/in_systm.h> 70#include <netinet/ip.h> 71#ifdef INET6 72#include <netinet/ip6.h> 73#endif /* INET6 */ 74#include <netinet/in_pcb.h> 75#include <netinet/ip_icmp.h> 76#include <netinet/icmp_var.h> 77#include <netinet/igmp_var.h> 78#include <netinet/ip_var.h> 79#include <netinet/tcp.h> 80#include <netinet/tcpip.h> 81#include <netinet/tcp_seq.h> 82#define TCPSTATES 83#include <netinet/tcp_fsm.h> 84#include <netinet/tcp_var.h> 85#include <netinet/udp.h> 86#include <netinet/udp_var.h> 87 88#include <arpa/inet.h> 89#include <err.h> 90#include <errno.h> 91#include <netdb.h> 92#include <stdio.h> 93#include <stdlib.h> 94#include <stdint.h> 95#include <string.h> 96#include <unistd.h> 97#include "netstat.h" 98 99#ifdef __APPLE__ 100#include <TargetConditionals.h> 101#endif 102 103#define ROUNDUP64(a) \ 104 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(uint64_t) - 1))) : sizeof(uint64_t)) 105#define ADVANCE64(x, n) (((char *)x) += ROUNDUP64(n)) 106 107char *inetname (struct in_addr *); 108void inetprint (struct in_addr *, int, char *, int); 109#ifdef INET6 110extern void inet6print (struct in6_addr *, int, char *, int); 111static int udp_done, tcp_done; 112extern int mptcp_done; 113#endif /* INET6 */ 114 115#ifdef SRVCACHE 116typedef struct __table_private table_t; 117 118extern table_t *_nc_table_new(uint32_t n); 119extern void _nc_table_free(table_t *tin); 120 121extern void _nc_table_insert(table_t *t, const char *key, void *datum); 122extern void *_nc_table_find(table_t *t, const char *key); 123extern void _nc_table_delete(table_t *t, const char *key); 124 125static table_t *_serv_cache = NULL; 126 127/* 128 * Read and cache all known services 129 */ 130static void 131_serv_cache_open() 132{ 133 struct servent *s; 134 char *key, *name, *test; 135 136 if (_serv_cache != NULL) return; 137 138 _serv_cache = _nc_table_new(8192); 139 setservent(0); 140 141 while (NULL != (s = getservent())) 142 { 143 if (s->s_name == NULL) continue; 144 key = NULL; 145 asprintf(&key, "%hu/%s", (unsigned short)ntohs(s->s_port), s->s_proto); 146 name = strdup(s->s_name); 147 test = _nc_table_find(_serv_cache, key); 148 if (test == NULL) _nc_table_insert(_serv_cache, key, name); 149 free(key); 150 } 151 152 endservent(); 153} 154 155void 156_serv_cache_close() 157{ 158 _nc_table_free(_serv_cache); 159 _serv_cache = NULL; 160} 161 162struct servent * 163_serv_cache_getservbyport(int port, char *proto) 164{ 165 static struct servent s; 166 char *key; 167 unsigned short p; 168 169 _serv_cache_open(); 170 171 memset(&s, 0, sizeof(struct servent)); 172 asprintf(&key, "%u/%s", port, (proto == NULL) ? "udp" : proto); 173 174 s.s_name = _nc_table_find(_serv_cache, key); 175 free(key); 176 if (s.s_name == NULL) return NULL; 177 178 p = port; 179 s.s_port = htons(p); 180 s.s_proto = proto; 181 return &s; 182} 183 184#endif /* SRVCACHE */ 185 186/* 187 * Print a summary of connections related to an Internet 188 * protocol. For TCP, also give state of connection. 189 * Listening processes (aflag) are suppressed unless the 190 * -a (all) flag is specified. 191 */ 192 193struct xgen_n { 194 u_int32_t xgn_len; /* length of this structure */ 195 u_int32_t xgn_kind; /* number of PCBs at this time */ 196}; 197 198#define ALL_XGN_KIND_INP (XSO_SOCKET | XSO_RCVBUF | XSO_SNDBUF | XSO_STATS | XSO_INPCB) 199#define ALL_XGN_KIND_TCP (ALL_XGN_KIND_INP | XSO_TCPCB) 200 201void 202protopr(uint32_t proto, /* for sysctl version we pass proto # */ 203 char *name, int af) 204{ 205 int istcp; 206 static int first = 1; 207 char *buf, *next; 208 const char *mibvar; 209 struct xinpgen *xig, *oxig; 210 struct xgen_n *xgn; 211 size_t len; 212 struct xtcpcb_n *tp = NULL; 213 struct xinpcb_n *inp = NULL; 214 struct xsocket_n *so = NULL; 215 struct xsockbuf_n *so_rcv = NULL; 216 struct xsockbuf_n *so_snd = NULL; 217 struct xsockstat_n *so_stat = NULL; 218 int which = 0; 219 220 istcp = 0; 221 switch (proto) { 222 case IPPROTO_TCP: 223#ifdef INET6 224 if (tcp_done != 0) 225 return; 226 else 227 tcp_done = 1; 228#endif 229 istcp = 1; 230 mibvar = "net.inet.tcp.pcblist_n"; 231 break; 232 case IPPROTO_UDP: 233#ifdef INET6 234 if (udp_done != 0) 235 return; 236 else 237 udp_done = 1; 238#endif 239 mibvar = "net.inet.udp.pcblist_n"; 240 break; 241 case IPPROTO_DIVERT: 242 mibvar = "net.inet.divert.pcblist_n"; 243 break; 244 default: 245 mibvar = "net.inet.raw.pcblist_n"; 246 break; 247 } 248 len = 0; 249 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { 250 if (errno != ENOENT) 251 warn("sysctl: %s", mibvar); 252 return; 253 } 254 if ((buf = malloc(len)) == 0) { 255 warn("malloc %lu bytes", (u_long)len); 256 return; 257 } 258 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { 259 warn("sysctl: %s", mibvar); 260 free(buf); 261 return; 262 } 263 264 /* 265 * Bail-out to avoid logic error in the loop below when 266 * there is in fact no more control block to process 267 */ 268 if (len <= sizeof(struct xinpgen)) { 269 free(buf); 270 return; 271 } 272 273 oxig = xig = (struct xinpgen *)buf; 274 for (next = buf + ROUNDUP64(xig->xig_len); next < buf + len; next += ROUNDUP64(xgn->xgn_len)) { 275 276 xgn = (struct xgen_n*)next; 277 if (xgn->xgn_len <= sizeof(struct xinpgen)) 278 break; 279 280 if ((which & xgn->xgn_kind) == 0) { 281 which |= xgn->xgn_kind; 282 switch (xgn->xgn_kind) { 283 case XSO_SOCKET: 284 so = (struct xsocket_n *)xgn; 285 break; 286 case XSO_RCVBUF: 287 so_rcv = (struct xsockbuf_n *)xgn; 288 break; 289 case XSO_SNDBUF: 290 so_snd = (struct xsockbuf_n *)xgn; 291 break; 292 case XSO_STATS: 293 so_stat = (struct xsockstat_n *)xgn; 294 break; 295 case XSO_INPCB: 296 inp = (struct xinpcb_n *)xgn; 297 break; 298 case XSO_TCPCB: 299 tp = (struct xtcpcb_n *)xgn; 300 break; 301 default: 302 printf("unexpected kind %d\n", xgn->xgn_kind); 303 break; 304 } 305 } else { 306 if (vflag) 307 printf("got %d twice\n", xgn->xgn_kind); 308 } 309 310 if ((istcp && which != ALL_XGN_KIND_TCP) || (!istcp && which != ALL_XGN_KIND_INP)) 311 continue; 312 which = 0; 313 314 /* Ignore sockets for protocols other than the desired one. */ 315 if (so->xso_protocol != (int)proto) 316 continue; 317 318 /* Ignore PCBs which were freed during copyout. */ 319 if (inp->inp_gencnt > oxig->xig_gen) 320 continue; 321 322 if ((af == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) 323#ifdef INET6 324 || (af == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) 325#endif /* INET6 */ 326 || (af == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 327#ifdef INET6 328 && (inp->inp_vflag & 329 INP_IPV6) == 0 330#endif /* INET6 */ 331 )) 332 ) 333 continue; 334 335 /* 336 * Local address is not an indication of listening socket or 337 * server sockey but just rather the socket has been bound. 338 * That why many UDP sockets were not displayed in the original code. 339 */ 340 if (!aflag && istcp && tp->t_state <= TCPS_LISTEN) 341 continue; 342 343 if (Lflag && !so->so_qlimit) 344 continue; 345 346 if (first) { 347 if (!Lflag) { 348 printf("Active Internet connections"); 349 if (aflag) 350 printf(" (including servers)"); 351 } else 352 printf( 353 "Current listen queue sizes (qlen/incqlen/maxqlen)"); 354 putchar('\n'); 355 if (Aflag) { 356#if !TARGET_OS_EMBEDDED 357 printf("%-16.16s ", "Socket"); 358#else 359 printf("%-8.8s ", "Socket"); 360#endif 361 printf("%-9.9s", "Flowhash"); 362 } 363 if (Lflag) 364 printf("%-14.14s %-22.22s\n", 365 "Listen", "Local Address"); 366 else { 367 printf((Aflag && !Wflag) ? 368 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %-11.11s" : 369 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %-11.11s", 370 "Proto", "Recv-Q", "Send-Q", 371 "Local Address", "Foreign Address", 372 "(state)"); 373 if (bflag > 0) 374 printf(" %10.10s %10.10s", "rxbytes", "txbytes"); 375 if (prioflag >= 0) 376 printf(" %7.7s[%1d] %7.7s[%1d]", "rxbytes", prioflag, "txbytes", prioflag); 377 if (vflag > 0) 378 printf(" %6.6s %6.6s %6.6s %6.6s", 379 "rhiwat", "shiwat", "pid", "epid"); 380 printf("\n"); 381 } 382 first = 0; 383 } 384 if (Aflag) { 385 if (istcp) 386#if !TARGET_OS_EMBEDDED 387 printf("%16lx ", (u_long)inp->inp_ppcb); 388#else 389 printf("%8lx ", (u_long)inp->inp_ppcb); 390 391#endif 392 else 393#if !TARGET_OS_EMBEDDED 394 printf("%16lx ", (u_long)so->so_pcb); 395#else 396 printf("%8lx ", (u_long)so->so_pcb); 397#endif 398 printf("%8x ", inp->inp_flowhash); 399 } 400 if (Lflag) { 401 char buf[15]; 402 403 snprintf(buf, 15, "%d/%d/%d", so->so_qlen, 404 so->so_incqlen, so->so_qlimit); 405 printf("%-14.14s ", buf); 406 } 407 else { 408 const char *vchar; 409 410#ifdef INET6 411 if ((inp->inp_vflag & INP_IPV6) != 0) 412 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 413 ? "46" : "6 "; 414 else 415#endif 416 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 417 ? "4 " : " "; 418 419 printf("%-3.3s%-2.2s %6u %6u ", name, vchar, 420 so_rcv->sb_cc, 421 so_snd->sb_cc); 422 } 423 if (nflag) { 424 if (inp->inp_vflag & INP_IPV4) { 425 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 426 name, 1); 427 if (!Lflag) 428 inetprint(&inp->inp_faddr, 429 (int)inp->inp_fport, name, 1); 430 } 431#ifdef INET6 432 else if (inp->inp_vflag & INP_IPV6) { 433 inet6print(&inp->in6p_laddr, 434 (int)inp->inp_lport, name, 1); 435 if (!Lflag) 436 inet6print(&inp->in6p_faddr, 437 (int)inp->inp_fport, name, 1); 438 } /* else nothing printed now */ 439#endif /* INET6 */ 440 } else if (inp->inp_flags & INP_ANONPORT) { 441 if (inp->inp_vflag & INP_IPV4) { 442 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 443 name, 1); 444 if (!Lflag) 445 inetprint(&inp->inp_faddr, 446 (int)inp->inp_fport, name, 0); 447 } 448#ifdef INET6 449 else if (inp->inp_vflag & INP_IPV6) { 450 inet6print(&inp->in6p_laddr, 451 (int)inp->inp_lport, name, 1); 452 if (!Lflag) 453 inet6print(&inp->in6p_faddr, 454 (int)inp->inp_fport, name, 0); 455 } /* else nothing printed now */ 456#endif /* INET6 */ 457 } else { 458 if (inp->inp_vflag & INP_IPV4) { 459 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 460 name, 0); 461 if (!Lflag) 462 inetprint(&inp->inp_faddr, 463 (int)inp->inp_fport, name, 464 inp->inp_lport != 465 inp->inp_fport); 466 } 467#ifdef INET6 468 else if (inp->inp_vflag & INP_IPV6) { 469 inet6print(&inp->in6p_laddr, 470 (int)inp->inp_lport, name, 0); 471 if (!Lflag) 472 inet6print(&inp->in6p_faddr, 473 (int)inp->inp_fport, name, 474 inp->inp_lport != 475 inp->inp_fport); 476 } /* else nothing printed now */ 477#endif /* INET6 */ 478 } 479 if (istcp && !Lflag) { 480 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) 481 printf("%-11d", tp->t_state); 482 else { 483 printf("%-11s", tcpstates[tp->t_state]); 484#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 485 /* Show T/TCP `hidden state' */ 486 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 487 putchar('*'); 488#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 489 } 490 } 491 if (!istcp) 492 printf("%-11s", " "); 493 if (bflag > 0) { 494 int i; 495 u_int64_t rxbytes = 0; 496 u_int64_t txbytes = 0; 497 498 for (i = 0; i < SO_TC_STATS_MAX; i++) { 499 rxbytes += so_stat->xst_tc_stats[i].rxbytes; 500 txbytes += so_stat->xst_tc_stats[i].txbytes; 501 } 502 503 printf(" %10llu %10llu", rxbytes, txbytes); 504 } 505 if (prioflag >= 0) { 506 printf(" %10llu %10llu", 507 prioflag < SO_TC_STATS_MAX ? so_stat->xst_tc_stats[prioflag].rxbytes : 0, 508 prioflag < SO_TC_STATS_MAX ? so_stat->xst_tc_stats[prioflag].txbytes : 0); 509 } 510 if (vflag > 0) { 511 printf(" %6u %6u %6u %6u", 512 so_rcv->sb_hiwat, 513 so_snd->sb_hiwat, 514 so->so_last_pid, 515 so->so_e_pid); 516 } 517 putchar('\n'); 518 } 519 if (xig != oxig && xig->xig_gen != oxig->xig_gen) { 520 if (oxig->xig_count > xig->xig_count) { 521 printf("Some %s sockets may have been deleted.\n", 522 name); 523 } else if (oxig->xig_count < xig->xig_count) { 524 printf("Some %s sockets may have been created.\n", 525 name); 526 } else { 527 printf("Some %s sockets may have been created or deleted", 528 name); 529 } 530 } 531 free(buf); 532} 533 534/* 535 * Dump TCP statistics structure. 536 */ 537void 538tcp_stats(uint32_t off , char *name, int af) 539{ 540 static struct tcpstat ptcpstat; 541 struct tcpstat tcpstat; 542 size_t len = sizeof tcpstat; 543 static uint32_t r_swcsum, pr_swcsum; 544 static uint32_t t_swcsum, pt_swcsum; 545 546 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { 547 warn("sysctl: net.inet.tcp.stats"); 548 return; 549 } 550 551#ifdef INET6 552 if (tcp_done != 0 && interval == 0) 553 return; 554 else 555 tcp_done = 1; 556#endif 557 558 if (interval && vflag > 0) 559 print_time(); 560 printf ("%s:\n", name); 561 562#define TCPDIFF(f) (tcpstat.f - ptcpstat.f) 563#define p(f, m) if (TCPDIFF(f) || sflag <= 1) \ 564 printf(m, TCPDIFF(f), plural(TCPDIFF(f))) 565#define p1a(f, m) if (TCPDIFF(f) || sflag <= 1) \ 566 printf(m, TCPDIFF(f)) 567#define p2(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \ 568 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2), plural(TCPDIFF(f2))) 569#define p2a(f1, f2, m) if (TCPDIFF(f1) || TCPDIFF(f2) || sflag <= 1) \ 570 printf(m, TCPDIFF(f1), plural(TCPDIFF(f1)), TCPDIFF(f2)) 571#define p3(f, m) if (TCPDIFF(f) || sflag <= 1) \ 572 printf(m, TCPDIFF(f), plurales(TCPDIFF(f))) 573 574 p(tcps_sndtotal, "\t%u packet%s sent\n"); 575 p2(tcps_sndpack,tcps_sndbyte, 576 "\t\t%u data packet%s (%u byte%s)\n"); 577 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 578 "\t\t%u data packet%s (%u byte%s) retransmitted\n"); 579 p(tcps_mturesent, "\t\t%u resend%s initiated by MTU discovery\n"); 580 p2a(tcps_sndacks, tcps_delack, 581 "\t\t%u ack-only packet%s (%u delayed)\n"); 582 p(tcps_sndurg, "\t\t%u URG only packet%s\n"); 583 p(tcps_sndprobe, "\t\t%u window probe packet%s\n"); 584 p(tcps_sndwinup, "\t\t%u window update packet%s\n"); 585 p(tcps_sndctrl, "\t\t%u control packet%s\n"); 586 p(tcps_fcholdpacket, "\t\t%u data packet%s sent after flow control\n"); 587 t_swcsum = tcpstat.tcps_snd_swcsum + tcpstat.tcps_snd6_swcsum; 588 if ((t_swcsum - pt_swcsum) || sflag <= 1) 589 printf("\t\t%u checksummed in software\n", (t_swcsum - pt_swcsum)); 590 p2(tcps_snd_swcsum, tcps_snd_swcsum_bytes, 591 "\t\t\t%u segment%s (%u byte%s) over IPv4\n"); 592#if INET6 593 p2(tcps_snd6_swcsum, tcps_snd6_swcsum_bytes, 594 "\t\t\t%u segment%s (%u byte%s) over IPv6\n"); 595#endif /* INET6 */ 596 p(tcps_rcvtotal, "\t%u packet%s received\n"); 597 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%u ack%s (for %u byte%s)\n"); 598 p(tcps_rcvdupack, "\t\t%u duplicate ack%s\n"); 599 p(tcps_rcvacktoomuch, "\t\t%u ack%s for unsent data\n"); 600 p2(tcps_rcvpack, tcps_rcvbyte, 601 "\t\t%u packet%s (%u byte%s) received in-sequence\n"); 602 p2(tcps_rcvduppack, tcps_rcvdupbyte, 603 "\t\t%u completely duplicate packet%s (%u byte%s)\n"); 604 p(tcps_pawsdrop, "\t\t%u old duplicate packet%s\n"); 605 p(tcps_rcvmemdrop, "\t\t%u received packet%s dropped due to low memory\n"); 606 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 607 "\t\t%u packet%s with some dup. data (%u byte%s duped)\n"); 608 p2(tcps_rcvoopack, tcps_rcvoobyte, 609 "\t\t%u out-of-order packet%s (%u byte%s)\n"); 610 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 611 "\t\t%u packet%s (%u byte%s) of data after window\n"); 612 p(tcps_rcvwinprobe, "\t\t%u window probe%s\n"); 613 p(tcps_rcvwinupd, "\t\t%u window update packet%s\n"); 614 p(tcps_rcvafterclose, "\t\t%u packet%s received after close\n"); 615 p(tcps_badrst, "\t\t%u bad reset%s\n"); 616 p(tcps_rcvbadsum, "\t\t%u discarded for bad checksum%s\n"); 617 r_swcsum = tcpstat.tcps_rcv_swcsum + tcpstat.tcps_rcv6_swcsum; 618 if ((r_swcsum - pr_swcsum) || sflag <= 1) 619 printf("\t\t%u checksummed in software\n", 620 (r_swcsum - pr_swcsum)); 621 p2(tcps_rcv_swcsum, tcps_rcv_swcsum_bytes, 622 "\t\t\t%u segment%s (%u byte%s) over IPv4\n"); 623#if INET6 624 p2(tcps_rcv6_swcsum, tcps_rcv6_swcsum_bytes, 625 "\t\t\t%u segment%s (%u byte%s) over IPv6\n"); 626#endif /* INET6 */ 627 p(tcps_rcvbadoff, "\t\t%u discarded for bad header offset field%s\n"); 628 p1a(tcps_rcvshort, "\t\t%u discarded because packet too short\n"); 629 p(tcps_connattempt, "\t%u connection request%s\n"); 630 p(tcps_accepts, "\t%u connection accept%s\n"); 631 p(tcps_badsyn, "\t%u bad connection attempt%s\n"); 632 p(tcps_listendrop, "\t%u listen queue overflow%s\n"); 633 p(tcps_connects, "\t%u connection%s established (including accepts)\n"); 634 p2(tcps_closed, tcps_drops, 635 "\t%u connection%s closed (including %u drop%s)\n"); 636 p(tcps_cachedrtt, "\t\t%u connection%s updated cached RTT on close\n"); 637 p(tcps_cachedrttvar, 638 "\t\t%u connection%s updated cached RTT variance on close\n"); 639 p(tcps_cachedssthresh, 640 "\t\t%u connection%s updated cached ssthresh on close\n"); 641 p(tcps_conndrops, "\t%u embryonic connection%s dropped\n"); 642 p2(tcps_rttupdated, tcps_segstimed, 643 "\t%u segment%s updated rtt (of %u attempt%s)\n"); 644 p(tcps_rexmttimeo, "\t%u retransmit timeout%s\n"); 645 p(tcps_timeoutdrop, "\t\t%u connection%s dropped by rexmit timeout\n"); 646 p(tcps_rxtfindrop, "\t\t%u connection%s dropped after retransmitting FIN\n"); 647 p(tcps_persisttimeo, "\t%u persist timeout%s\n"); 648 p(tcps_persistdrop, "\t\t%u connection%s dropped by persist timeout\n"); 649 p(tcps_keeptimeo, "\t%u keepalive timeout%s\n"); 650 p(tcps_keepprobe, "\t\t%u keepalive probe%s sent\n"); 651 p(tcps_keepdrops, "\t\t%u connection%s dropped by keepalive\n"); 652 p(tcps_predack, "\t%u correct ACK header prediction%s\n"); 653 p(tcps_preddat, "\t%u correct data packet header prediction%s\n"); 654#ifdef TCP_MAX_SACK 655 /* TCP_MAX_SACK indicates the header has the SACK structures */ 656 p(tcps_sack_recovery_episode, "\t%u SACK recovery episode%s\n"); 657 p(tcps_sack_rexmits, 658 "\t%u segment rexmit%s in SACK recovery episodes\n"); 659 p(tcps_sack_rexmit_bytes, 660 "\t%u byte rexmit%s in SACK recovery episodes\n"); 661 p(tcps_sack_rcv_blocks, 662 "\t%u SACK option%s (SACK blocks) received\n"); 663 p(tcps_sack_send_blocks, "\t%u SACK option%s (SACK blocks) sent\n"); 664 p1a(tcps_sack_sboverflow, "\t%u SACK scoreboard overflow\n"); 665#endif /* TCP_MAX_SACK */ 666 667 p(tcps_coalesced_pack, "\t%u LRO coalesced packet%s\n"); 668 p(tcps_flowtbl_full, "\t\t%u time%s LRO flow table was full\n"); 669 p(tcps_flowtbl_collision, "\t\t%u collision%s in LRO flow table\n"); 670 p(tcps_lro_twopack, "\t\t%u time%s LRO coalesced 2 packets\n"); 671 p(tcps_lro_multpack, "\t\t%u time%s LRO coalesced 3 or 4 packets\n"); 672 p(tcps_lro_largepack, "\t\t%u time%s LRO coalesced 5 or more packets\n"); 673 674 p(tcps_limited_txt, "\t%u limited transmit%s done\n"); 675 p(tcps_early_rexmt, "\t%u early retransmit%s done\n"); 676 p(tcps_sack_ackadv, "\t%u time%s cumulative ack advanced along with SACK\n"); 677 p(tcps_pto, "\t%u probe timeout%s\n"); 678 p(tcps_rto_after_pto, "\t\t%u time%s retransmit timeout triggered after probe\n"); 679 p(tcps_tlp_recovery, "\t\t%u time%s fast recovery after tail loss\n"); 680 p(tcps_tlp_recoverlastpkt, "\t\t%u time%s recovered last packet \n"); 681 p(tcps_ecn_setup, "\t%u connection%s negotiated ECN\n"); 682 p(tcps_sent_ece, "\t\t%u time%s congestion notification was sent using ECE\n"); 683 p(tcps_sent_cwr, "\t\t%u time%s CWR was sent in response to ECE\n"); 684 685 p(tcps_detect_reordering, "\t%u time%s packet reordering was detected on a connection\n"); 686 p(tcps_reordered_pkts, "\t\t%u time%s transmitted packets were reordered\n"); 687 p(tcps_delay_recovery, "\t\t%u time%s fast recovery was delayed to handle reordering\n"); 688 p(tcps_avoid_rxmt, "\t\t%u time%s retransmission was avoided by delaying recovery\n"); 689 p(tcps_unnecessary_rxmt, "\t\t%u retransmission%s not needed \n"); 690 691 if (interval > 0) { 692 bcopy(&tcpstat, &ptcpstat, len); 693 pr_swcsum = r_swcsum; 694 pt_swcsum = t_swcsum; 695 } 696 697#undef TCPDIFF 698#undef p 699#undef p1a 700#undef p2 701#undef p2a 702#undef p3 703} 704 705/* 706 * Dump MPTCP statistics 707 */ 708void 709mptcp_stats(uint32_t off , char *name, int af) 710{ 711 static struct tcpstat ptcpstat; 712 struct tcpstat tcpstat; 713 size_t len = sizeof tcpstat; 714 715 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { 716 warn("sysctl: net.inet.tcp.stats"); 717 return; 718 } 719 720#ifdef INET6 721 if (mptcp_done != 0 && interval == 0) 722 return; 723 else 724 mptcp_done = 1; 725#endif 726 727 if (interval && vflag > 0) 728 print_time(); 729 printf ("%s:\n", name); 730 731#define MPTCPDIFF(f) (tcpstat.f - ptcpstat.f) 732#define p(f, m) if (MPTCPDIFF(f) || sflag <= 1) \ 733 printf(m, MPTCPDIFF(f), plural(MPTCPDIFF(f))) 734#define p1a(f, m) if (MPTCPDIFF(f) || sflag <= 1) \ 735 printf(m, MPTCPDIFF(f)) 736#define p2(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \ 737 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), \ 738 MPTCPDIFF(f2), plural(MPTCPDIFF(f2))) 739#define p2a(f1, f2, m) if (MPTCPDIFF(f1) || MPTCPDIFF(f2) || sflag <= 1) \ 740 printf(m, MPTCPDIFF(f1), plural(MPTCPDIFF(f1)), MPTCPDIFF(f2)) 741#define p3(f, m) if (MPTCPDIFF(f) || sflag <= 1) \ 742 printf(m, MPTCPDIFF(f), plurales(MPTCPDIFF(f))) 743 744 p(tcps_mp_sndpacks, "\t%u data packet%s sent\n"); 745 p(tcps_mp_sndbytes, "\t%u data byte%s sent\n"); 746 p(tcps_mp_rcvtotal, "\t%u data packet%s received\n"); 747 p(tcps_mp_rcvbytes, "\t%u data byte%s received\n"); 748 p(tcps_invalid_mpcap, "\t%u packet%s with an invalid MPCAP option\n"); 749 p(tcps_invalid_joins, "\t%u packet%s with an invalid MPJOIN option\n"); 750 p(tcps_mpcap_fallback, "\t%u time%s primary subflow fell back to " 751 "TCP\n"); 752 p(tcps_join_fallback, "\t%u time%s secondary subflow fell back to " 753 "TCP\n"); 754 p(tcps_estab_fallback, "\t%u DSS option drop%s\n"); 755 p(tcps_invalid_opt, "\t%u other invalid MPTCP option%s\n"); 756 p(tcps_mp_reducedwin, "\t%u time%s the MPTCP subflow window was reduced\n"); 757 p(tcps_mp_badcsum, "\t%u bad DSS checksum%s\n"); 758 p(tcps_mp_oodata, "\t%u time%s received out of order data \n"); 759 p3(tcps_mp_switches, "\t%u subflow switch%s\n"); 760 761 if (interval > 0) { 762 bcopy(&tcpstat, &ptcpstat, len); 763 } 764 765#undef MPTCPDIFF 766#undef p 767#undef p1a 768#undef p2 769#undef p2a 770#undef p3 771} 772 773/* 774 * Dump UDP statistics structure. 775 */ 776void 777udp_stats(uint32_t off , char *name, int af ) 778{ 779 static struct udpstat pudpstat; 780 struct udpstat udpstat; 781 size_t len = sizeof udpstat; 782 uint32_t delivered; 783 static uint32_t r_swcsum, pr_swcsum; 784 static uint32_t t_swcsum, pt_swcsum; 785 786 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) { 787 warn("sysctl: net.inet.udp.stats"); 788 return; 789 } 790 791#ifdef INET6 792 if (udp_done != 0 && interval == 0) 793 return; 794 else 795 udp_done = 1; 796#endif 797 798 if (interval && vflag > 0) 799 print_time(); 800 printf("%s:\n", name); 801 802#define UDPDIFF(f) (udpstat.f - pudpstat.f) 803#define p(f, m) if (UDPDIFF(f) || sflag <= 1) \ 804 printf(m, UDPDIFF(f), plural(UDPDIFF(f))) 805#define p1a(f, m) if (UDPDIFF(f) || sflag <= 1) \ 806 printf(m, UDPDIFF(f)) 807#define p2(f1, f2, m) if (UDPDIFF(f1) || UDPDIFF(f2) || sflag <= 1) \ 808 printf(m, UDPDIFF(f1), plural(UDPDIFF(f1)), UDPDIFF(f2), plural(UDPDIFF(f2))) 809 p(udps_ipackets, "\t%u datagram%s received\n"); 810 p1a(udps_hdrops, "\t\t%u with incomplete header\n"); 811 p1a(udps_badlen, "\t\t%u with bad data length field\n"); 812 p1a(udps_badsum, "\t\t%u with bad checksum\n"); 813 p1a(udps_nosum, "\t\t%u with no checksum\n"); 814 r_swcsum = udpstat.udps_rcv_swcsum + udpstat.udps_rcv6_swcsum; 815 if ((r_swcsum - pr_swcsum) || sflag <= 1) 816 printf("\t\t%u checksummed in software\n", (r_swcsum - pr_swcsum)); 817 p2(udps_rcv_swcsum, udps_rcv_swcsum_bytes, 818 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n"); 819#if INET6 820 p2(udps_rcv6_swcsum, udps_rcv6_swcsum_bytes, 821 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n"); 822#endif /* INET6 */ 823 p1a(udps_noport, "\t\t%u dropped due to no socket\n"); 824 p(udps_noportbcast, 825 "\t\t%u broadcast/multicast datagram%s undelivered\n"); 826 /* the next statistic is cumulative in udps_noportbcast */ 827 p(udps_filtermcast, 828 "\t\t%u time%s multicast source filter matched\n"); 829 p1a(udps_fullsock, "\t\t%u dropped due to full socket buffers\n"); 830 p1a(udpps_pcbhashmiss, "\t\t%u not for hashed pcb\n"); 831 delivered = UDPDIFF(udps_ipackets) - 832 UDPDIFF(udps_hdrops) - 833 UDPDIFF(udps_badlen) - 834 UDPDIFF(udps_badsum) - 835 UDPDIFF(udps_noport) - 836 UDPDIFF(udps_noportbcast) - 837 UDPDIFF(udps_fullsock); 838 if (delivered || sflag <= 1) 839 printf("\t\t%u delivered\n", delivered); 840 p(udps_opackets, "\t%u datagram%s output\n"); 841 t_swcsum = udpstat.udps_snd_swcsum + udpstat.udps_snd6_swcsum; 842 if ((t_swcsum - pt_swcsum) || sflag <= 1) 843 printf("\t\t%u checksummed in software\n", (t_swcsum - pt_swcsum)); 844 p2(udps_snd_swcsum, udps_snd_swcsum_bytes, 845 "\t\t\t%u datagram%s (%u byte%s) over IPv4\n"); 846#if INET6 847 p2(udps_snd6_swcsum, udps_snd6_swcsum_bytes, 848 "\t\t\t%u datagram%s (%u byte%s) over IPv6\n"); 849#endif /* INET6 */ 850 851 if (interval > 0) { 852 bcopy(&udpstat, &pudpstat, len); 853 pr_swcsum = r_swcsum; 854 pt_swcsum = t_swcsum; 855 } 856 857#undef UDPDIFF 858#undef p 859#undef p1a 860#undef p2 861} 862 863/* 864 * Dump IP statistics structure. 865 */ 866void 867ip_stats(uint32_t off , char *name, int af ) 868{ 869 static struct ipstat pipstat; 870 struct ipstat ipstat; 871 size_t len = sizeof ipstat; 872 873 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) { 874 warn("sysctl: net.inet.ip.stats"); 875 return; 876 } 877 878 if (interval && vflag > 0) 879 print_time(); 880 printf("%s:\n", name); 881 882#define IPDIFF(f) (ipstat.f - pipstat.f) 883#define p(f, m) if (IPDIFF(f) || sflag <= 1) \ 884 printf(m, IPDIFF(f), plural(IPDIFF(f))) 885#define p1a(f, m) if (IPDIFF(f) || sflag <= 1) \ 886 printf(m, IPDIFF(f)) 887#define p2(f1, f2, m) if (IPDIFF(f1) || IPDIFF(f2) || sflag <= 1) \ 888 printf(m, IPDIFF(f1), plural(IPDIFF(f1)), IPDIFF(f2), plural(IPDIFF(f2))) 889 890 p(ips_total, "\t%u total packet%s received\n"); 891 p(ips_badsum, "\t\t%u bad header checksum%s\n"); 892 p2(ips_rcv_swcsum, ips_rcv_swcsum_bytes, 893 "\t\t%u header%s (%u byte%s) checksummed in software\n"); 894 p1a(ips_toosmall, "\t\t%u with size smaller than minimum\n"); 895 p1a(ips_tooshort, "\t\t%u with data size < data length\n"); 896 p1a(ips_adj, "\t\t%u with data size > data length\n"); 897 p(ips_adj_hwcsum_clr, 898 "\t\t\t%u packet%s forced to software checksum\n"); 899 p1a(ips_toolong, "\t\t%u with ip length > max ip packet size\n"); 900 p1a(ips_badhlen, "\t\t%u with header length < data size\n"); 901 p1a(ips_badlen, "\t\t%u with data length < header length\n"); 902 p1a(ips_badoptions, "\t\t%u with bad options\n"); 903 p1a(ips_badvers, "\t\t%u with incorrect version number\n"); 904 p(ips_fragments, "\t\t%u fragment%s received\n"); 905 p1a(ips_fragdropped, "\t\t\t%u dropped (dup or out of space)\n"); 906 p1a(ips_fragtimeout, "\t\t\t%u dropped after timeout\n"); 907 p1a(ips_reassembled, "\t\t\t%u reassembled ok\n"); 908 p(ips_delivered, "\t\t%u packet%s for this host\n"); 909 p(ips_noproto, "\t\t%u packet%s for unknown/unsupported protocol\n"); 910 p(ips_forward, "\t\t%u packet%s forwarded"); 911 p(ips_fastforward, " (%u packet%s fast forwarded)"); 912 if (IPDIFF(ips_forward) || sflag <= 1) 913 putchar('\n'); 914 p(ips_cantforward, "\t\t%u packet%s not forwardable\n"); 915 p(ips_notmember, 916 "\t\t%u packet%s received for unknown multicast group\n"); 917 p(ips_redirectsent, "\t\t%u redirect%s sent\n"); 918 p(ips_localout, "\t%u packet%s sent from this host\n"); 919 p(ips_rawout, "\t\t%u packet%s sent with fabricated ip header\n"); 920 p(ips_odropped, 921 "\t\t%u output packet%s dropped due to no bufs, etc.\n"); 922 p(ips_noroute, "\t\t%u output packet%s discarded due to no route\n"); 923 p(ips_fragmented, "\t\t%u output datagram%s fragmented\n"); 924 p(ips_ofragments, "\t\t%u fragment%s created\n"); 925 p(ips_cantfrag, "\t\t%u datagram%s that can't be fragmented\n"); 926 p(ips_nogif, "\t\t%u tunneling packet%s that can't find gif\n"); 927 p(ips_badaddr, "\t\t%u datagram%s with bad address in header\n"); 928 p(ips_pktdropcntrl, 929 "\t\t%u packet%s dropped due to no bufs for control data\n"); 930 p2(ips_snd_swcsum, ips_snd_swcsum_bytes, 931 "\t\t%u header%s (%u byte%s) checksummed in software\n"); 932 933 if (interval > 0) 934 bcopy(&ipstat, &pipstat, len); 935 936#undef IPDIFF 937#undef p 938#undef p1a 939#undef p2 940} 941 942/* 943 * Dump ARP statistics structure. 944 */ 945void 946arp_stats(uint32_t off, char *name, int af) 947{ 948 static struct arpstat parpstat; 949 struct arpstat arpstat; 950 size_t len = sizeof (arpstat); 951 952 if (sysctlbyname("net.link.ether.inet.stats", &arpstat, 953 &len, 0, 0) < 0) { 954 warn("sysctl: net.link.ether.inet.stats"); 955 return; 956 } 957 958 if (interval && vflag > 0) 959 print_time(); 960 printf("%s:\n", name); 961 962#define ARPDIFF(f) (arpstat.f - parpstat.f) 963#define p(f, m) if (ARPDIFF(f) || sflag <= 1) \ 964 printf(m, ARPDIFF(f), plural(ARPDIFF(f))) 965#define p2(f, m) if (ARPDIFF(f) || sflag <= 1) \ 966 printf(m, ARPDIFF(f), pluralies(ARPDIFF(f))) 967 968 p(txrequests, "\t%u ARP request%s sent\n"); 969 p2(txreplies, "\t%u ARP repl%s sent\n"); 970 p(txannounces, "\t%u ARP announcement%s sent\n"); 971 p(rxrequests, "\t%u ARP request%s received\n"); 972 p2(rxreplies, "\t%u ARP repl%s received\n"); 973 p(received, "\t%u total ARP packet%s received\n"); 974 p(txconflicts, "\t%u ARP conflict probe%s sent\n"); 975 p(invalidreqs, "\t%u invalid ARP resolve request%s\n"); 976 p(reqnobufs, "\t%u total packet%s dropped due to lack of memory\n"); 977 p(dropped, "\t%u total packet%s dropped due to no ARP entry\n"); 978 p(purged, "\t%u total packet%s dropped during ARP entry removal\n"); 979 p2(timeouts, "\t%u ARP entr%s timed out\n"); 980 p(dupips, "\t%u Duplicate IP%s seen\n"); 981 982 if (interval > 0) 983 bcopy(&arpstat, &parpstat, len); 984 985#undef ARPDIFF 986#undef p 987#undef p2 988} 989 990static char *icmpnames[] = { 991 "echo reply", 992 "#1", 993 "#2", 994 "destination unreachable", 995 "source quench", 996 "routing redirect", 997 "#6", 998 "#7", 999 "echo", 1000 "router advertisement", 1001 "router solicitation", 1002 "time exceeded", 1003 "parameter problem", 1004 "time stamp", 1005 "time stamp reply", 1006 "information request", 1007 "information request reply", 1008 "address mask request", 1009 "address mask reply", 1010}; 1011 1012/* 1013 * Dump ICMP statistics. 1014 */ 1015void 1016icmp_stats(uint32_t off , char *name, int af ) 1017{ 1018 static struct icmpstat picmpstat; 1019 struct icmpstat icmpstat; 1020 int i, first; 1021 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ 1022 size_t len; 1023 1024 mib[0] = CTL_NET; 1025 mib[1] = PF_INET; 1026 mib[2] = IPPROTO_ICMP; 1027 mib[3] = ICMPCTL_STATS; 1028 1029 len = sizeof icmpstat; 1030 memset(&icmpstat, 0, len); 1031 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0) 1032 return; /* XXX should complain, but not traditional */ 1033 1034 if (interval && vflag > 0) 1035 print_time(); 1036 printf("%s:\n", name); 1037 1038#define ICMPDIFF(f) (icmpstat.f - picmpstat.f) 1039#define p(f, m) if (ICMPDIFF(f) || sflag <= 1) \ 1040 printf(m, ICMPDIFF(f), plural(ICMPDIFF(f))) 1041#define p1a(f, m) if (ICMPDIFF(f) || sflag <= 1) \ 1042 printf(m, ICMPDIFF(f)) 1043 1044 p(icps_error, "\t%u call%s to icmp_error\n"); 1045 p(icps_oldicmp, 1046 "\t%u error%s not generated 'cuz old message was icmp\n"); 1047 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 1048 if (ICMPDIFF(icps_outhist[i]) != 0) { 1049 if (first) { 1050 printf("\tOutput histogram:\n"); 1051 first = 0; 1052 } 1053 printf("\t\t%s: %u\n", icmpnames[i], 1054 ICMPDIFF(icps_outhist[i])); 1055 } 1056 p(icps_badcode, "\t%u message%s with bad code fields\n"); 1057 p(icps_tooshort, "\t%u message%s < minimum length\n"); 1058 p(icps_checksum, "\t%u bad checksum%s\n"); 1059 p(icps_badlen, "\t%u message%s with bad length\n"); 1060 p1a(icps_bmcastecho, "\t%u multicast echo requests ignored\n"); 1061 p1a(icps_bmcasttstamp, "\t%u multicast timestamp requests ignored\n"); 1062 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 1063 if (ICMPDIFF(icps_inhist[i]) != 0) { 1064 if (first) { 1065 printf("\tInput histogram:\n"); 1066 first = 0; 1067 } 1068 printf("\t\t%s: %u\n", icmpnames[i], 1069 ICMPDIFF(icps_inhist[i])); 1070 } 1071 p(icps_reflect, "\t%u message response%s generated\n"); 1072 1073#undef ICMPDIFF 1074#undef p 1075#undef p1a 1076 mib[3] = ICMPCTL_MASKREPL; 1077 len = sizeof i; 1078 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0) 1079 return; 1080 printf("\tICMP address mask responses are %sabled\n", 1081 i ? "en" : "dis"); 1082 1083 if (interval > 0) 1084 bcopy(&icmpstat, &picmpstat, sizeof (icmpstat)); 1085} 1086 1087/* 1088 * Dump IGMP statistics structure. 1089 */ 1090void 1091igmp_stats(uint32_t off , char *name, int af ) 1092{ 1093 static struct igmpstat_v3 pigmpstat; 1094 struct igmpstat_v3 igmpstat; 1095 size_t len = sizeof igmpstat; 1096 1097 if (sysctlbyname("net.inet.igmp.v3stats", &igmpstat, &len, 0, 0) < 0) { 1098 warn("sysctl: net.inet.igmp.v3stats"); 1099 return; 1100 } 1101 1102 if (igmpstat.igps_version != IGPS_VERSION_3) { 1103 warnx("%s: version mismatch (%d != %d)", __func__, 1104 igmpstat.igps_version, IGPS_VERSION_3); 1105 } 1106 if (igmpstat.igps_len != IGPS_VERSION3_LEN) { 1107 warnx("%s: size mismatch (%d != %d)", __func__, 1108 igmpstat.igps_len, IGPS_VERSION3_LEN); 1109 } 1110 1111 if (interval && vflag > 0) 1112 print_time(); 1113 printf("%s:\n", name); 1114 1115#define IGMPDIFF(f) ((uintmax_t)(igmpstat.f - pigmpstat.f)) 1116#define p64(f, m) if (IGMPDIFF(f) || sflag <= 1) \ 1117 printf(m, IGMPDIFF(f), plural(IGMPDIFF(f))) 1118#define py64(f, m) if (IGMPDIFF(f) || sflag <= 1) \ 1119 printf(m, IGMPDIFF(f), IGMPDIFF(f) != 1 ? "ies" : "y") 1120 1121 p64(igps_rcv_total, "\t%ju message%s received\n"); 1122 p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n"); 1123 p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n"); 1124 p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n"); 1125 py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n"); 1126 py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n"); 1127 py64(igps_rcv_badqueries, 1128 "\t%ju membership quer%s received with invalid field(s)\n"); 1129 py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n"); 1130 py64(igps_rcv_group_queries, "\t%ju group quer%s received\n"); 1131 py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n"); 1132 py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n"); 1133 p64(igps_rcv_reports, "\t%ju membership report%s received\n"); 1134 p64(igps_rcv_badreports, 1135 "\t%ju membership report%s received with invalid field(s)\n"); 1136 p64(igps_rcv_ourreports, 1137"\t%ju membership report%s received for groups to which we belong\n"); 1138 p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n"); 1139 p64(igps_snd_reports, "\t%ju membership report%s sent\n"); 1140 1141 if (interval > 0) 1142 bcopy(&igmpstat, &pigmpstat, len); 1143 1144#undef IGMPDIFF 1145#undef p64 1146#undef py64 1147} 1148 1149/* 1150 * Pretty print an Internet address (net address + port). 1151 */ 1152void 1153inetprint(struct in_addr *in, int port, char *proto, int numeric_port) 1154{ 1155 struct servent *sp = 0; 1156 char line[80], *cp; 1157 int width; 1158 1159 if (Wflag) 1160 snprintf(line, sizeof(line), "%s.", inetname(in)); 1161 else 1162 snprintf(line, sizeof(line), "%.*s.", (Aflag && !numeric_port) ? 12 : 16, inetname(in)); 1163 cp = index(line, '\0'); 1164 if (!numeric_port && port) 1165#ifdef _SERVICE_CACHE_ 1166 sp = _serv_cache_getservbyport(port, proto); 1167#else 1168 sp = getservbyport((int)port, proto); 1169#endif 1170 if (sp || port == 0) 1171 snprintf(cp, sizeof(line) - (cp - line), "%.15s ", sp ? sp->s_name : "*"); 1172 else 1173 snprintf(cp, sizeof(line) - (cp - line), "%d ", ntohs((u_short)port)); 1174 width = (Aflag && !Wflag) ? 18 : 22; 1175 if (Wflag) 1176 printf("%-*s ", width, line); 1177 else 1178 printf("%-*.*s ", width, width, line); 1179} 1180 1181/* 1182 * Construct an Internet address representation. 1183 * If the nflag has been supplied, give 1184 * numeric value, otherwise try for symbolic name. 1185 */ 1186char * 1187inetname(struct in_addr *inp) 1188{ 1189 register char *cp; 1190 static char line[MAXHOSTNAMELEN]; 1191 struct hostent *hp; 1192 struct netent *np; 1193 1194 cp = 0; 1195 if (!nflag && inp->s_addr != INADDR_ANY) { 1196 int net = inet_netof(*inp); 1197 int lna = inet_lnaof(*inp); 1198 1199 if (lna == INADDR_ANY) { 1200 np = getnetbyaddr(net, AF_INET); 1201 if (np) 1202 cp = np->n_name; 1203 } 1204 if (cp == 0) { 1205 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 1206 if (hp) { 1207 cp = hp->h_name; 1208 //### trimdomain(cp, strlen(cp)); 1209 } 1210 } 1211 } 1212 if (inp->s_addr == INADDR_ANY) 1213 strlcpy(line, "*", sizeof(line)); 1214 else if (cp) { 1215 strncpy(line, cp, sizeof(line) - 1); 1216 line[sizeof(line) - 1] = '\0'; 1217 } else { 1218 inp->s_addr = ntohl(inp->s_addr); 1219#define C(x) ((u_int)((x) & 0xff)) 1220 snprintf(line, sizeof(line), "%u.%u.%u.%u", C(inp->s_addr >> 24), 1221 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 1222 } 1223 return (line); 1224} 1225