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