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