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