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