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