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