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