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