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