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