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