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