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