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/tcp.h> 62 #include <netinet/tcpip.h> 63 #include <netinet/tcp_seq.h> 64 #define TCPSTATES 65 #include <netinet/tcp_fsm.h> 66 #include <netinet/tcp_timer.h> 67 #include <netinet/tcp_var.h> 68 #include <netinet/tcp_debug.h> 69 #include <netinet/udp.h> 70 #include <netinet/udp_var.h> 71 72 #include <arpa/inet.h> 73 #include <err.h> 74 #include <errno.h> 75 #include <libutil.h> 76 #include <netdb.h> 77 #include <stdio.h> 78 #include <stdlib.h> 79 #include <string.h> 80 #include <unistd.h> 81 #include "netstat.h" 82 83 char *inetname (struct in_addr *); 84 void inetprint (struct in_addr *, int, const char *, int); 85 #ifdef INET6 86 static int udp_done, tcp_done; 87 #endif /* INET6 */ 88 89 /* 90 * Print a summary of connections related to an Internet 91 * protocol. For TCP, also give state of connection. 92 * Listening processes (aflag) are suppressed unless the 93 * -a (all) flag is specified. 94 */ 95 void 96 protopr(u_long proto, /* for sysctl version we pass proto # */ 97 const char *name, int af1) 98 { 99 int istcp; 100 static int first = 1; 101 char *buf; 102 const char *mibvar, *vchar; 103 struct tcpcb *tp = NULL; 104 struct inpcb *inp; 105 struct xinpgen *xig, *oxig; 106 struct xsocket *so; 107 size_t len; 108 109 istcp = 0; 110 switch (proto) { 111 case IPPROTO_TCP: 112 #ifdef INET6 113 if (tcp_done != 0) 114 return; 115 else 116 tcp_done = 1; 117 #endif 118 istcp = 1; 119 mibvar = "net.inet.tcp.pcblist"; 120 break; 121 case IPPROTO_UDP: 122 #ifdef INET6 123 if (udp_done != 0) 124 return; 125 else 126 udp_done = 1; 127 #endif 128 mibvar = "net.inet.udp.pcblist"; 129 break; 130 case IPPROTO_DIVERT: 131 mibvar = "net.inet.divert.pcblist"; 132 break; 133 default: 134 mibvar = "net.inet.raw.pcblist"; 135 break; 136 } 137 len = 0; 138 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { 139 if (errno != ENOENT) 140 warn("sysctl: %s", mibvar); 141 return; 142 } 143 if ((buf = malloc(len)) == 0) { 144 warn("malloc %lu bytes", (u_long)len); 145 return; 146 } 147 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { 148 warn("sysctl: %s", mibvar); 149 free(buf); 150 return; 151 } 152 153 oxig = xig = (struct xinpgen *)buf; 154 for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); 155 xig->xig_len > sizeof(struct xinpgen); 156 xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { 157 if (istcp) { 158 tp = &((struct xtcpcb *)xig)->xt_tp; 159 inp = &((struct xtcpcb *)xig)->xt_inp; 160 so = &((struct xtcpcb *)xig)->xt_socket; 161 } else { 162 inp = &((struct xinpcb *)xig)->xi_inp; 163 so = &((struct xinpcb *)xig)->xi_socket; 164 } 165 166 /* Ignore sockets for protocols other than the desired one. */ 167 if (so->xso_protocol != (int)proto) 168 continue; 169 170 /* Ignore PCBs which were freed during copyout. */ 171 if (inp->inp_gencnt > oxig->xig_gen) 172 continue; 173 174 if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0) 175 #ifdef INET6 176 || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0) 177 #endif /* INET6 */ 178 || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0 179 #ifdef INET6 180 && (inp->inp_vflag & 181 INP_IPV6) == 0 182 #endif /* INET6 */ 183 )) 184 ) 185 continue; 186 if (!aflag && 187 ( 188 (af1 == AF_INET && 189 inet_lnaof(inp->inp_laddr) == INADDR_ANY) 190 #ifdef INET6 191 || (af1 == AF_INET6 && 192 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 193 #endif /* INET6 */ 194 || (af1 == AF_UNSPEC && 195 (((inp->inp_vflag & INP_IPV4) != 0 && 196 inet_lnaof(inp->inp_laddr) == INADDR_ANY) 197 #ifdef INET6 198 || ((inp->inp_vflag & INP_IPV6) != 0 && 199 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 200 #endif 201 )) 202 )) 203 continue; 204 205 if (first) { 206 if (!Lflag) { 207 printf("Active Internet connections"); 208 if (aflag) 209 printf(" (including servers)"); 210 } else 211 printf( 212 "Current listen queue sizes (qlen/incqlen/maxqlen)"); 213 putchar('\n'); 214 if (Aflag) 215 printf("%-8.8s ", "Socket"); 216 if (Lflag) 217 printf("%-5.5s %-14.14s %-22.22s\n", 218 "Proto", "Listen", "Local Address"); 219 else 220 printf((Aflag && !Wflag) ? 221 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 222 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 223 "Proto", "Recv-Q", "Send-Q", 224 "Local Address", "Foreign Address", 225 "(state)"); 226 first = 0; 227 } 228 if (Lflag && so->so_qlimit == 0) 229 continue; 230 if (Aflag) { 231 if (istcp) 232 printf("%8lx ", (u_long)inp->inp_ppcb); 233 else 234 printf("%8lx ", (u_long)so->so_pcb); 235 } 236 #ifdef INET6 237 if ((inp->inp_vflag & INP_IPV6) != 0) 238 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 239 ? "46" : "6 "; 240 else 241 #endif 242 vchar = ((inp->inp_vflag & INP_IPV4) != 0) 243 ? "4 " : " "; 244 printf("%-3.3s%-2.2s ", name, vchar); 245 if (Lflag) { 246 char buf1[15]; 247 248 snprintf(buf1, 15, "%d/%d/%d", so->so_qlen, 249 so->so_incqlen, so->so_qlimit); 250 printf("%-14.14s ", buf1); 251 } else { 252 printf("%6u %6u ", 253 so->so_rcv.sb_cc, 254 so->so_snd.sb_cc); 255 } 256 if (numeric_port) { 257 if (inp->inp_vflag & INP_IPV4) { 258 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 259 name, 1); 260 if (!Lflag) 261 inetprint(&inp->inp_faddr, 262 (int)inp->inp_fport, name, 1); 263 } 264 #ifdef INET6 265 else if (inp->inp_vflag & INP_IPV6) { 266 inet6print(&inp->in6p_laddr, 267 (int)inp->inp_lport, name, 1); 268 if (!Lflag) 269 inet6print(&inp->in6p_faddr, 270 (int)inp->inp_fport, name, 1); 271 } /* else nothing printed now */ 272 #endif /* INET6 */ 273 } else if (inp->inp_flags & INP_ANONPORT) { 274 if (inp->inp_vflag & INP_IPV4) { 275 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 276 name, 1); 277 if (!Lflag) 278 inetprint(&inp->inp_faddr, 279 (int)inp->inp_fport, name, 0); 280 } 281 #ifdef INET6 282 else if (inp->inp_vflag & INP_IPV6) { 283 inet6print(&inp->in6p_laddr, 284 (int)inp->inp_lport, name, 1); 285 if (!Lflag) 286 inet6print(&inp->in6p_faddr, 287 (int)inp->inp_fport, name, 0); 288 } /* else nothing printed now */ 289 #endif /* INET6 */ 290 } else { 291 if (inp->inp_vflag & INP_IPV4) { 292 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 293 name, 0); 294 if (!Lflag) 295 inetprint(&inp->inp_faddr, 296 (int)inp->inp_fport, name, 297 inp->inp_lport != 298 inp->inp_fport); 299 } 300 #ifdef INET6 301 else if (inp->inp_vflag & INP_IPV6) { 302 inet6print(&inp->in6p_laddr, 303 (int)inp->inp_lport, name, 0); 304 if (!Lflag) 305 inet6print(&inp->in6p_faddr, 306 (int)inp->inp_fport, name, 307 inp->inp_lport != 308 inp->inp_fport); 309 } /* else nothing printed now */ 310 #endif /* INET6 */ 311 } 312 if (istcp && !Lflag) { 313 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) 314 printf("%d", tp->t_state); 315 else { 316 printf("%s", tcpstates[tp->t_state]); 317 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 318 /* Show T/TCP `hidden state' */ 319 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 320 putchar('*'); 321 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 322 } 323 } 324 putchar('\n'); 325 } 326 if (xig != oxig && xig->xig_gen != oxig->xig_gen) { 327 if (oxig->xig_count > xig->xig_count) { 328 printf("Some %s sockets may have been deleted.\n", 329 name); 330 } else if (oxig->xig_count < xig->xig_count) { 331 printf("Some %s sockets may have been created.\n", 332 name); 333 } else { 334 printf("Some %s sockets may have been created or deleted", 335 name); 336 } 337 } 338 free(buf); 339 } 340 341 /* 342 * Dump TCP statistics structure. 343 */ 344 void 345 tcp_stats(u_long off __unused, const char *name, int af1 __unused) 346 { 347 struct tcpstat tcpstat, zerostat; 348 size_t len = sizeof tcpstat; 349 350 if (zflag) 351 memset(&zerostat, 0, len); 352 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 353 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) { 354 warn("sysctl: net.inet.tcp.stats"); 355 return; 356 } 357 358 #ifdef INET6 359 if (tcp_done != 0) 360 return; 361 else 362 tcp_done = 1; 363 #endif 364 365 printf ("%s:\n", name); 366 367 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 368 printf(m, tcpstat.f, plural(tcpstat.f)) 369 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ 370 printf(m, tcpstat.f) 371 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 372 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 373 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 374 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) 375 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 376 printf(m, tcpstat.f, plurales(tcpstat.f)) 377 378 p(tcps_sndtotal, "\t%lu packet%s sent\n"); 379 p2(tcps_sndpack,tcps_sndbyte, 380 "\t\t%lu data packet%s (%lu byte%s)\n"); 381 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 382 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); 383 p(tcps_sndrexmitbad, 384 "\t\t%lu data packet%s unnecessarily retransmitted\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 entrie%s added\n"); 439 p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n"); 440 p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n"); 441 p1a(tcps_sc_dropped, "\t\t%lu dropped\n"); 442 p1a(tcps_sc_completed, "\t\t%lu completed\n"); 443 p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n"); 444 p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n"); 445 p1a(tcps_sc_reset, "\t\t%lu reset\n"); 446 p1a(tcps_sc_stale, "\t\t%lu stale\n"); 447 p1a(tcps_sc_aborted, "\t\t%lu aborted\n"); 448 p1a(tcps_sc_badack, "\t\t%lu badack\n"); 449 p1a(tcps_sc_unreach, "\t\t%lu unreach\n"); 450 p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n"); 451 p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n"); 452 p(tcps_sc_recvcookie, "\t%lu cookie%s 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, const char *name, int af1 __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, const char *name, int af1 __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 const 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, const char *name, int af1 __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 in response to an icmp message\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, const char *name, int af1 __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 * Pretty print an Internet address (net address + port). 710 */ 711 void 712 inetprint(struct in_addr *in, int port, const char *proto, int num_port) 713 { 714 struct servent *sp = 0; 715 char line[80], *cp; 716 int width; 717 718 if (Wflag) 719 sprintf(line, "%s.", inetname(in)); 720 else 721 sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in)); 722 cp = index(line, '\0'); 723 if (!num_port && port) 724 sp = getservbyport((int)port, proto); 725 if (sp || port == 0) 726 sprintf(cp, "%.15s ", sp ? sp->s_name : "*"); 727 else 728 sprintf(cp, "%d ", ntohs((u_short)port)); 729 width = (Aflag && !Wflag) ? 18 : 22; 730 if (Wflag) 731 printf("%-*s ", width, line); 732 else 733 printf("%-*.*s ", width, width, line); 734 } 735 736 /* 737 * Construct an Internet address representation. 738 * If numeric_addr has been supplied, give 739 * numeric value, otherwise try for symbolic name. 740 */ 741 char * 742 inetname(struct in_addr *inp) 743 { 744 char *cp; 745 static char line[MAXHOSTNAMELEN]; 746 struct hostent *hp; 747 struct netent *np; 748 749 cp = 0; 750 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 751 int net = inet_netof(*inp); 752 int lna = inet_lnaof(*inp); 753 754 if (lna == INADDR_ANY) { 755 np = getnetbyaddr(net, AF_INET); 756 if (np) 757 cp = np->n_name; 758 } 759 if (cp == 0) { 760 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 761 if (hp) { 762 cp = hp->h_name; 763 trimdomain(cp, strlen(cp)); 764 } 765 } 766 } 767 if (inp->s_addr == INADDR_ANY) 768 strcpy(line, "*"); 769 else if (cp) { 770 strncpy(line, cp, sizeof(line) - 1); 771 line[sizeof(line) - 1] = '\0'; 772 } else { 773 inp->s_addr = ntohl(inp->s_addr); 774 #define C(x) ((u_int)((x) & 0xff)) 775 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), 776 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 777 } 778 return (line); 779 } 780