1 /* $NetBSD: inet.c,v 1.78 2007/07/10 21:12:33 ad Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 #if 0 35 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; 36 #else 37 __RCSID("$NetBSD: inet.c,v 1.78 2007/07/10 21:12:33 ad Exp $"); 38 #endif 39 #endif /* not lint */ 40 41 #define _CALLOUT_PRIVATE /* for defs in sys/callout.h */ 42 43 #include <sys/param.h> 44 #include <sys/queue.h> 45 #include <sys/socket.h> 46 #include <sys/socketvar.h> 47 #include <sys/mbuf.h> 48 #include <sys/protosw.h> 49 #include <sys/sysctl.h> 50 51 #include <net/if_arp.h> 52 #include <net/route.h> 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/ip.h> 56 #include <netinet/in_pcb.h> 57 #include <netinet/ip_icmp.h> 58 59 #ifdef INET6 60 #include <netinet/ip6.h> 61 #endif 62 63 #include <netinet/icmp_var.h> 64 #include <netinet/igmp_var.h> 65 #include <netinet/ip_var.h> 66 #include <netinet/pim_var.h> 67 #include <netinet/tcp.h> 68 #include <netinet/tcpip.h> 69 #include <netinet/tcp_seq.h> 70 #define TCPSTATES 71 #include <netinet/tcp_fsm.h> 72 #define TCPTIMERS 73 #include <netinet/tcp_timer.h> 74 #include <netinet/tcp_var.h> 75 #include <netinet/tcp_debug.h> 76 #include <netinet/udp.h> 77 #include <netinet/ip_carp.h> 78 #include <netinet/udp_var.h> 79 80 #include <arpa/inet.h> 81 #include <kvm.h> 82 #include <netdb.h> 83 #include <stdio.h> 84 #include <string.h> 85 #include <unistd.h> 86 #include <stdlib.h> 87 #include <err.h> 88 #include "netstat.h" 89 90 struct inpcb inpcb; 91 struct tcpcb tcpcb; 92 struct socket sockb; 93 94 char *inetname __P((struct in_addr *)); 95 void inetprint __P((struct in_addr *, u_int16_t, const char *, int)); 96 97 /* 98 * Print a summary of connections related to an Internet 99 * protocol. For TCP, also give state of connection. 100 * Listening processes (aflag) are suppressed unless the 101 * -a (all) flag is specified. 102 */ 103 static int width; 104 static int compact; 105 106 static void 107 protoprhdr(void) 108 { 109 printf("Active Internet connections"); 110 if (aflag) 111 printf(" (including servers)"); 112 putchar('\n'); 113 if (Aflag) 114 printf("%-8.8s ", "PCB"); 115 printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n", 116 "Proto", "Recv-Q", "Send-Q", compact ? "" : " ", 117 width, width, "Local Address", 118 width, width, "Foreign Address", 119 "State"); 120 } 121 122 static void 123 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc, 124 struct in_addr *laddr, u_int16_t lport, 125 struct in_addr *faddr, u_int16_t fport, 126 short t_state, char *name) 127 { 128 static char *shorttcpstates[] = { 129 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV", 130 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG", 131 "LASTAK", "FWAIT2", "TMWAIT", 132 }; 133 int istcp; 134 135 istcp = strcmp(name, "tcp") == 0; 136 137 if (Aflag) { 138 printf("%8" PRIxPTR " ", ppcb); 139 } 140 printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc, 141 compact ? "" : " "); 142 if (numeric_port) { 143 inetprint(laddr, lport, name, 1); 144 inetprint(faddr, fport, name, 1); 145 } else if (inpcb.inp_flags & INP_ANONPORT) { 146 inetprint(laddr, lport, name, 1); 147 inetprint(faddr, fport, name, 0); 148 } else { 149 inetprint(laddr, lport, name, 0); 150 inetprint(faddr, fport, name, 0); 151 } 152 if (istcp) { 153 if (t_state < 0 || t_state >= TCP_NSTATES) 154 printf(" %d", t_state); 155 else 156 printf(" %s", compact ? shorttcpstates[t_state] : 157 tcpstates[t_state]); 158 } 159 putchar('\n'); 160 } 161 162 void 163 protopr(off, name) 164 u_long off; 165 char *name; 166 { 167 struct inpcbtable table; 168 struct inpcb *head, *next, *prev; 169 struct inpcb inpcb; 170 int istcp; 171 static int first = 1; 172 173 compact = 0; 174 if (Aflag) { 175 if (!numeric_addr) 176 width = 18; 177 else { 178 width = 21; 179 compact = 1; 180 } 181 } else 182 width = 22; 183 184 if (use_sysctl) { 185 struct kinfo_pcb *pcblist; 186 int mib[8]; 187 size_t namelen = 0, size = 0, i; 188 char *mibname = NULL; 189 190 memset(mib, 0, sizeof(mib)); 191 192 if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1) 193 err(1, "asprintf"); 194 195 /* get dynamic pcblist node */ 196 if (sysctlnametomib(mibname, mib, &namelen) == -1) 197 err(1, "sysctlnametomib: %s", mibname); 198 199 if (sysctl(mib, sizeof(mib) / sizeof(*mib), NULL, &size, 200 NULL, 0) == -1) 201 err(1, "sysctl (query)"); 202 203 if ((pcblist = malloc(size)) == NULL) 204 err(1, "malloc"); 205 memset(pcblist, 0, size); 206 207 mib[6] = sizeof(*pcblist); 208 mib[7] = size / sizeof(*pcblist); 209 210 if (sysctl(mib, sizeof(mib) / sizeof(*mib), pcblist, 211 &size, NULL, 0) == -1) 212 err(1, "sysctl (copy)"); 213 214 for (i = 0; i < size / sizeof(*pcblist); i++) { 215 struct sockaddr_in src, dst; 216 217 memcpy(&src, &pcblist[i].ki_s, sizeof(src)); 218 memcpy(&dst, &pcblist[i].ki_d, sizeof(dst)); 219 220 if (first) { 221 protoprhdr(); 222 first = 0; 223 } 224 225 protopr0((intptr_t) pcblist[i].ki_ppcbaddr, 226 pcblist[i].ki_rcvq, pcblist[i].ki_sndq, 227 &src.sin_addr, src.sin_port, 228 &dst.sin_addr, dst.sin_port, 229 pcblist[i].ki_tstate, name); 230 } 231 232 free(pcblist); 233 return; 234 } 235 236 if (off == 0) 237 return; 238 istcp = strcmp(name, "tcp") == 0; 239 kread(off, (char *)&table, sizeof table); 240 prev = head = 241 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first; 242 next = (struct inpcb *)table.inpt_queue.cqh_first; 243 244 while (next != head) { 245 kread((u_long)next, (char *)&inpcb, sizeof inpcb); 246 if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) { 247 printf("???\n"); 248 break; 249 } 250 prev = next; 251 next = (struct inpcb *)inpcb.inp_queue.cqe_next; 252 253 if (inpcb.inp_af != AF_INET) 254 continue; 255 256 if (!aflag && 257 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) 258 continue; 259 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb)); 260 if (istcp) { 261 kread((u_long)inpcb.inp_ppcb, 262 (char *)&tcpcb, sizeof (tcpcb)); 263 } 264 265 if (first) { 266 protoprhdr(); 267 first = 0; 268 } 269 270 protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev, 271 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc, 272 &inpcb.inp_laddr, inpcb.inp_lport, 273 &inpcb.inp_faddr, inpcb.inp_fport, 274 tcpcb.t_state, name); 275 } 276 } 277 278 /* 279 * Dump TCP statistics structure. 280 */ 281 void 282 tcp_stats(off, name) 283 u_long off; 284 char *name; 285 { 286 struct tcpstat tcpstat; 287 288 if (use_sysctl) { 289 size_t size = sizeof(tcpstat); 290 291 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &size, 292 NULL, 0) == -1) 293 err(1, "net.inet.tcp.stats"); 294 } else { 295 if (off == 0) 296 return; 297 kread(off, (char *)&tcpstat, sizeof (tcpstat)); 298 } 299 300 printf ("%s:\n", name); 301 302 #define ps(f, m) if (tcpstat.f || sflag <= 1) \ 303 printf(m, (unsigned long long)tcpstat.f) 304 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 305 printf(m, (unsigned long long)tcpstat.f, plural(tcpstat.f)) 306 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 307 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \ 308 (unsigned long long)tcpstat.f2, plural(tcpstat.f2)) 309 #define p2s(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 310 printf(m, (unsigned long long)tcpstat.f1, plural(tcpstat.f1), \ 311 (unsigned long long)tcpstat.f2) 312 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 313 printf(m, (unsigned long long)tcpstat.f, plurales(tcpstat.f)) 314 315 p(tcps_sndtotal, "\t%llu packet%s sent\n"); 316 p2(tcps_sndpack,tcps_sndbyte, 317 "\t\t%llu data packet%s (%llu byte%s)\n"); 318 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 319 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n"); 320 p2s(tcps_sndacks, tcps_delack, 321 "\t\t%llu ack-only packet%s (%llu delayed)\n"); 322 p(tcps_sndurg, "\t\t%llu URG only packet%s\n"); 323 p(tcps_sndprobe, "\t\t%llu window probe packet%s\n"); 324 p(tcps_sndwinup, "\t\t%llu window update packet%s\n"); 325 p(tcps_sndctrl, "\t\t%llu control packet%s\n"); 326 p(tcps_selfquench, 327 "\t\t%llu send attempt%s resulted in self-quench\n"); 328 p(tcps_rcvtotal, "\t%llu packet%s received\n"); 329 p2(tcps_rcvackpack, tcps_rcvackbyte, 330 "\t\t%llu ack%s (for %llu byte%s)\n"); 331 p(tcps_rcvdupack, "\t\t%llu duplicate ack%s\n"); 332 p(tcps_rcvacktoomuch, "\t\t%llu ack%s for unsent data\n"); 333 p2(tcps_rcvpack, tcps_rcvbyte, 334 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n"); 335 p2(tcps_rcvduppack, tcps_rcvdupbyte, 336 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n"); 337 p(tcps_pawsdrop, "\t\t%llu old duplicate packet%s\n"); 338 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 339 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n"); 340 p2(tcps_rcvoopack, tcps_rcvoobyte, 341 "\t\t%llu out-of-order packet%s (%llu byte%s)\n"); 342 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 343 "\t\t%llu packet%s (%llu byte%s) of data after window\n"); 344 p(tcps_rcvwinprobe, "\t\t%llu window probe%s\n"); 345 p(tcps_rcvwinupd, "\t\t%llu window update packet%s\n"); 346 p(tcps_rcvafterclose, "\t\t%llu packet%s received after close\n"); 347 p(tcps_rcvbadsum, "\t\t%llu discarded for bad checksum%s\n"); 348 p(tcps_rcvbadoff, "\t\t%llu discarded for bad header offset field%s\n"); 349 ps(tcps_rcvshort, "\t\t%llu discarded because packet too short\n"); 350 p(tcps_connattempt, "\t%llu connection request%s\n"); 351 p(tcps_accepts, "\t%llu connection accept%s\n"); 352 p(tcps_connects, 353 "\t%llu connection%s established (including accepts)\n"); 354 p2(tcps_closed, tcps_drops, 355 "\t%llu connection%s closed (including %llu drop%s)\n"); 356 p(tcps_conndrops, "\t%llu embryonic connection%s dropped\n"); 357 p(tcps_delayed_free, "\t%llu delayed free%s of tcpcb\n"); 358 p2(tcps_rttupdated, tcps_segstimed, 359 "\t%llu segment%s updated rtt (of %llu attempt%s)\n"); 360 p(tcps_rexmttimeo, "\t%llu retransmit timeout%s\n"); 361 p(tcps_timeoutdrop, 362 "\t\t%llu connection%s dropped by rexmit timeout\n"); 363 p2(tcps_persisttimeo, tcps_persistdrops, 364 "\t%llu persist timeout%s (resulting in %llu dropped " 365 "connection%s)\n"); 366 p(tcps_keeptimeo, "\t%llu keepalive timeout%s\n"); 367 p(tcps_keepprobe, "\t\t%llu keepalive probe%s sent\n"); 368 p(tcps_keepdrops, "\t\t%llu connection%s dropped by keepalive\n"); 369 p(tcps_predack, "\t%llu correct ACK header prediction%s\n"); 370 p(tcps_preddat, "\t%llu correct data packet header prediction%s\n"); 371 p3(tcps_pcbhashmiss, "\t%llu PCB hash miss%s\n"); 372 ps(tcps_noport, "\t%llu dropped due to no socket\n"); 373 p(tcps_connsdrained, "\t%llu connection%s drained due to memory " 374 "shortage\n"); 375 p(tcps_pmtublackhole, "\t%llu PMTUD blackhole%s detected\n"); 376 377 p(tcps_badsyn, "\t%llu bad connection attempt%s\n"); 378 ps(tcps_sc_added, "\t%llu SYN cache entries added\n"); 379 p(tcps_sc_collisions, "\t\t%llu hash collision%s\n"); 380 ps(tcps_sc_completed, "\t\t%llu completed\n"); 381 ps(tcps_sc_aborted, "\t\t%llu aborted (no space to build PCB)\n"); 382 ps(tcps_sc_timed_out, "\t\t%llu timed out\n"); 383 ps(tcps_sc_overflowed, "\t\t%llu dropped due to overflow\n"); 384 ps(tcps_sc_bucketoverflow, "\t\t%llu dropped due to bucket overflow\n"); 385 ps(tcps_sc_reset, "\t\t%llu dropped due to RST\n"); 386 ps(tcps_sc_unreach, "\t\t%llu dropped due to ICMP unreachable\n"); 387 ps(tcps_sc_delayed_free, "\t\t%llu delayed free of SYN cache " 388 "entries\n"); 389 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n"); 390 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries " 391 "already in the cache\n"); 392 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n"); 393 p(tcps_badsig, "\t%llu packet%s with bad signature\n"); 394 p(tcps_goodsig, "\t%llu packet%s with good signature\n"); 395 396 p(tcps_ecn_shs, "\t%llu sucessful ECN handshake%s\n"); 397 p(tcps_ecn_ce, "\t%llu packet%s with ECN CE bit\n"); 398 p(tcps_ecn_ect, "\t%llu packet%s ECN ECT(0) bit\n"); 399 #undef p 400 #undef ps 401 #undef p2 402 #undef p2s 403 #undef p3 404 } 405 406 /* 407 * Dump UDP statistics structure. 408 */ 409 void 410 udp_stats(off, name) 411 u_long off; 412 char *name; 413 { 414 struct udpstat udpstat; 415 u_quad_t delivered; 416 417 if (use_sysctl) { 418 size_t size = sizeof(udpstat); 419 420 if (sysctlbyname("net.inet.udp.stats", &udpstat, &size, 421 NULL, 0) == -1) 422 err(1, "net.inet.udp.stats"); 423 } else { 424 if (off == 0) 425 return; 426 kread(off, (char *)&udpstat, sizeof (udpstat)); 427 } 428 429 printf ("%s:\n", name); 430 431 #define ps(f, m) if (udpstat.f || sflag <= 1) \ 432 printf(m, (unsigned long long)udpstat.f) 433 #define p(f, m) if (udpstat.f || sflag <= 1) \ 434 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f)) 435 #define p3(f, m) if (udpstat.f || sflag <= 1) \ 436 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f)) 437 438 p(udps_ipackets, "\t%llu datagram%s received\n"); 439 ps(udps_hdrops, "\t%llu with incomplete header\n"); 440 ps(udps_badlen, "\t%llu with bad data length field\n"); 441 ps(udps_badsum, "\t%llu with bad checksum\n"); 442 ps(udps_noport, "\t%llu dropped due to no socket\n"); 443 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n"); 444 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n"); 445 delivered = udpstat.udps_ipackets - 446 udpstat.udps_hdrops - 447 udpstat.udps_badlen - 448 udpstat.udps_badsum - 449 udpstat.udps_noport - 450 udpstat.udps_noportbcast - 451 udpstat.udps_fullsock; 452 if (delivered || sflag <= 1) 453 printf("\t%llu delivered\n", (unsigned long long)delivered); 454 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n"); 455 p(udps_opackets, "\t%llu datagram%s output\n"); 456 457 #undef ps 458 #undef p 459 #undef p3 460 } 461 462 /* 463 * Dump IP statistics structure. 464 */ 465 void 466 ip_stats(off, name) 467 u_long off; 468 char *name; 469 { 470 struct ipstat ipstat; 471 472 if (use_sysctl) { 473 size_t size = sizeof(ipstat); 474 475 if (sysctlbyname("net.inet.ip.stats", &ipstat, &size, 476 NULL, 0) == -1) 477 err(1, "net.inet.ip.stats"); 478 } else { 479 if (off == 0) 480 return; 481 kread(off, (char *)&ipstat, sizeof (ipstat)); 482 } 483 484 printf("%s:\n", name); 485 486 #define ps(f, m) if (ipstat.f || sflag <= 1) \ 487 printf(m, (unsigned long long)ipstat.f) 488 #define p(f, m) if (ipstat.f || sflag <= 1) \ 489 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f)) 490 491 p(ips_total, "\t%llu total packet%s received\n"); 492 p(ips_badsum, "\t%llu bad header checksum%s\n"); 493 ps(ips_toosmall, "\t%llu with size smaller than minimum\n"); 494 ps(ips_tooshort, "\t%llu with data size < data length\n"); 495 ps(ips_toolong, "\t%llu with length > max ip packet size\n"); 496 ps(ips_badhlen, "\t%llu with header length < data size\n"); 497 ps(ips_badlen, "\t%llu with data length < header length\n"); 498 ps(ips_badoptions, "\t%llu with bad options\n"); 499 ps(ips_badvers, "\t%llu with incorrect version number\n"); 500 p(ips_fragments, "\t%llu fragment%s received\n"); 501 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n"); 502 p(ips_rcvmemdrop, "\t%llu fragment%s dropped (out of ipqent)\n"); 503 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n"); 504 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n"); 505 p(ips_reassembled, "\t%llu packet%s reassembled ok\n"); 506 p(ips_delivered, "\t%llu packet%s for this host\n"); 507 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n"); 508 p(ips_forward, "\t%llu packet%s forwarded"); 509 p(ips_fastforward, " (%llu packet%s fast forwarded)"); 510 if (ipstat.ips_forward || sflag <= 1) 511 putchar('\n'); 512 p(ips_cantforward, "\t%llu packet%s not forwardable\n"); 513 p(ips_redirectsent, "\t%llu redirect%s sent\n"); 514 p(ips_nogif, "\t%llu packet%s no matching gif found\n"); 515 p(ips_localout, "\t%llu packet%s sent from this host\n"); 516 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n"); 517 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n"); 518 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n"); 519 p(ips_fragmented, "\t%llu output datagram%s fragmented\n"); 520 p(ips_ofragments, "\t%llu fragment%s created\n"); 521 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n"); 522 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n"); 523 #undef ps 524 #undef p 525 } 526 527 static char *icmpnames[] = { 528 "echo reply", 529 "#1", 530 "#2", 531 "destination unreachable", 532 "source quench", 533 "routing redirect", 534 "alternate host address", 535 "#7", 536 "echo", 537 "router advertisement", 538 "router solicitation", 539 "time exceeded", 540 "parameter problem", 541 "time stamp", 542 "time stamp reply", 543 "information request", 544 "information request reply", 545 "address mask request", 546 "address mask reply", 547 }; 548 549 /* 550 * Dump ICMP statistics. 551 */ 552 void 553 icmp_stats(off, name) 554 u_long off; 555 char *name; 556 { 557 struct icmpstat icmpstat; 558 int i, first; 559 560 if (use_sysctl) { 561 size_t size = sizeof(icmpstat); 562 563 if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &size, 564 NULL, 0) == -1) 565 err(1, "net.inet.icmp.stats"); 566 } else { 567 if (off == 0) 568 return; 569 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 570 } 571 572 printf("%s:\n", name); 573 574 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 575 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f)) 576 577 p(icps_error, "\t%llu call%s to icmp_error\n"); 578 p(icps_oldicmp, 579 "\t%llu error%s not generated because old message was icmp\n"); 580 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 581 if (icmpstat.icps_outhist[i] != 0) { 582 if (first) { 583 printf("\tOutput histogram:\n"); 584 first = 0; 585 } 586 printf("\t\t%s: %llu\n", icmpnames[i], 587 (unsigned long long)icmpstat.icps_outhist[i]); 588 } 589 p(icps_badcode, "\t%llu message%s with bad code fields\n"); 590 p(icps_tooshort, "\t%llu message%s < minimum length\n"); 591 p(icps_checksum, "\t%llu bad checksum%s\n"); 592 p(icps_badlen, "\t%llu message%s with bad length\n"); 593 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 594 if (icmpstat.icps_inhist[i] != 0) { 595 if (first) { 596 printf("\tInput histogram:\n"); 597 first = 0; 598 } 599 printf("\t\t%s: %llu\n", icmpnames[i], 600 (unsigned long long)icmpstat.icps_inhist[i]); 601 } 602 p(icps_reflect, "\t%llu message response%s generated\n"); 603 p(icps_pmtuchg, "\t%llu path MTU change%s\n"); 604 #undef p 605 } 606 607 /* 608 * Dump IGMP statistics structure. 609 */ 610 void 611 igmp_stats(off, name) 612 u_long off; 613 char *name; 614 { 615 struct igmpstat igmpstat; 616 617 if (off == 0) 618 return; 619 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 620 printf("%s:\n", name); 621 622 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 623 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f)) 624 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 625 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 626 p(igps_rcv_total, "\t%llu message%s received\n"); 627 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 628 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 629 py(igps_rcv_queries, "\t%llu membership quer%s received\n"); 630 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n"); 631 p(igps_rcv_reports, "\t%llu membership report%s received\n"); 632 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n"); 633 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n"); 634 p(igps_snd_reports, "\t%llu membership report%s sent\n"); 635 #undef p 636 #undef py 637 } 638 639 /* 640 * Dump CARP statistics structure. 641 */ 642 void 643 carp_stats(u_long off, char *name) 644 { 645 struct carpstats carpstat; 646 647 if (use_sysctl) { 648 size_t size = sizeof(carpstat); 649 650 if (sysctlbyname("net.inet.carp.stats", &carpstat, &size, 651 NULL, 0) == -1) { 652 /* most likely CARP is not compiled in the kernel */ 653 return; 654 } 655 } else { 656 if (off == 0) 657 return; 658 kread(off, (char *)&carpstat, sizeof(carpstat)); 659 } 660 661 printf("%s:\n", name); 662 663 #define p(f, m) if (carpstat.f || sflag <= 1) \ 664 printf(m, carpstat.f, plural(carpstat.f)) 665 #define p2(f, m) if (carpstat.f || sflag <= 1) \ 666 printf(m, carpstat.f) 667 668 p(carps_ipackets, "\t%" PRIu64 " packet%s received (IPv4)\n"); 669 p(carps_ipackets6, "\t%" PRIu64 " packet%s received (IPv6)\n"); 670 p(carps_badif, 671 "\t\t%" PRIu64 " packet%s discarded for bad interface\n"); 672 p(carps_badttl, 673 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n"); 674 p(carps_hdrops, "\t\t%" PRIu64 " packet%s shorter than header\n"); 675 p(carps_badsum, "\t\t%" PRIu64 676 " packet%s discarded for bad checksum\n"); 677 p(carps_badver, 678 "\t\t%" PRIu64 " packet%s discarded with a bad version\n"); 679 p2(carps_badlen, 680 "\t\t%" PRIu64 " discarded because packet was too short\n"); 681 p(carps_badauth, 682 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n"); 683 p(carps_badvhid, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); 684 p(carps_badaddrs, "\t\t%" PRIu64 685 " packet%s discarded because of a bad address list\n"); 686 p(carps_opackets, "\t%" PRIu64 " packet%s sent (IPv4)\n"); 687 p(carps_opackets6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); 688 p2(carps_onomem, 689 "\t\t%" PRIu64 " send failed due to mbuf memory error\n"); 690 #undef p 691 #undef p2 692 } 693 694 /* 695 * Dump PIM statistics structure. 696 */ 697 void 698 pim_stats(off, name) 699 u_long off; 700 char *name; 701 { 702 struct pimstat pimstat; 703 704 if (off == 0) 705 return; 706 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) { 707 /* XXX: PIM is probably not enabled in the kernel */ 708 return; 709 } 710 711 printf("%s:\n", name); 712 713 #define p(f, m) if (pimstat.f || sflag <= 1) \ 714 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f)) 715 716 p(pims_rcv_total_msgs, "\t%llu message%s received\n"); 717 p(pims_rcv_total_bytes, "\t%llu byte%s received\n"); 718 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 719 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 720 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n"); 721 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n"); 722 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n"); 723 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n"); 724 p(pims_rcv_badregisters, "\t%llu bad register%s received\n"); 725 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n"); 726 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n"); 727 #undef p 728 } 729 730 /* 731 * Dump the ARP statistics structure. 732 */ 733 void 734 arp_stats(off, name) 735 u_long off; 736 char *name; 737 { 738 struct arpstat arpstat; 739 740 if (off == 0) 741 return; 742 kread(off, (char *)&arpstat, sizeof (arpstat)); 743 printf("%s:\n", name); 744 745 #define ps(f, m) if (arpstat.f || sflag <= 1) \ 746 printf(m, (unsigned long long)arpstat.f) 747 #define p(f, m) if (arpstat.f || sflag <= 1) \ 748 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f)) 749 750 p(as_sndtotal, "\t%llu packet%s sent\n"); 751 p(as_sndreply, "\t\t%llu reply packet%s\n"); 752 p(as_sndrequest, "\t\t%llu request packet%s\n"); 753 754 p(as_rcvtotal, "\t%llu packet%s received\n"); 755 p(as_rcvreply, "\t\t%llu reply packet%s\n"); 756 p(as_rcvrequest, "\t\t%llu valid request packet%s\n"); 757 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n"); 758 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n"); 759 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n"); 760 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n"); 761 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n"); 762 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n"); 763 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware " 764 "address\n"); 765 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast " 766 "source hardware address\n"); 767 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n"); 768 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n"); 769 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n"); 770 p(as_rcvover, "\t\t%llu entry%s overwritten\n"); 771 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n"); 772 773 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n"); 774 ps(as_dfrsent, "\t\t%llu sent\n"); 775 ps(as_dfrdropped, "\t\t%llu dropped\n"); 776 777 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n"); 778 779 #undef ps 780 #undef p 781 } 782 783 /* 784 * Pretty print an Internet address (net address + port). 785 * Take numeric_addr and numeric_port into consideration. 786 */ 787 void 788 inetprint(in, port, proto, numeric_port) 789 struct in_addr *in; 790 u_int16_t port; 791 const char *proto; 792 int numeric_port; 793 { 794 struct servent *sp = 0; 795 char line[80], *cp; 796 size_t space; 797 798 (void)snprintf(line, sizeof line, "%.*s.", 799 (Aflag && !numeric_addr) ? 12 : 16, inetname(in)); 800 cp = strchr(line, '\0'); 801 if (!numeric_port && port) 802 sp = getservbyport((int)port, proto); 803 space = sizeof line - (cp-line); 804 if (sp || port == 0) 805 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*"); 806 else 807 (void)snprintf(cp, space, "%u", ntohs(port)); 808 (void)printf(" %-*.*s", width, width, line); 809 } 810 811 /* 812 * Construct an Internet address representation. 813 * If numeric_addr has been supplied, give 814 * numeric value, otherwise try for symbolic name. 815 */ 816 char * 817 inetname(inp) 818 struct in_addr *inp; 819 { 820 char *cp; 821 static char line[50]; 822 struct hostent *hp; 823 struct netent *np; 824 static char domain[MAXHOSTNAMELEN + 1]; 825 static int first = 1; 826 827 if (first && !numeric_addr) { 828 first = 0; 829 if (gethostname(domain, sizeof domain) == 0) { 830 domain[sizeof(domain) - 1] = '\0'; 831 if ((cp = strchr(domain, '.'))) 832 (void) strlcpy(domain, cp + 1, sizeof(domain)); 833 else 834 domain[0] = 0; 835 } else 836 domain[0] = 0; 837 } 838 cp = 0; 839 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 840 int net = inet_netof(*inp); 841 int lna = inet_lnaof(*inp); 842 843 if (lna == INADDR_ANY) { 844 np = getnetbyaddr(net, AF_INET); 845 if (np) 846 cp = np->n_name; 847 } 848 if (cp == 0) { 849 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 850 if (hp) { 851 if ((cp = strchr(hp->h_name, '.')) && 852 !strcmp(cp + 1, domain)) 853 *cp = 0; 854 cp = hp->h_name; 855 } 856 } 857 } 858 if (inp->s_addr == INADDR_ANY) 859 strlcpy(line, "*", sizeof line); 860 else if (cp) 861 strlcpy(line, cp, sizeof line); 862 else { 863 inp->s_addr = ntohl(inp->s_addr); 864 #define C(x) ((x) & 0xff) 865 (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 866 C(inp->s_addr >> 24), C(inp->s_addr >> 16), 867 C(inp->s_addr >> 8), C(inp->s_addr)); 868 #undef C 869 } 870 return (line); 871 } 872 873 /* 874 * Dump the contents of a TCP PCB. 875 */ 876 void 877 tcp_dump(pcbaddr) 878 u_long pcbaddr; 879 { 880 callout_impl_t *ci; 881 struct tcpcb tcpcb; 882 int i, hardticks; 883 884 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb)); 885 hardticks = get_hardticks(); 886 887 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 888 889 printf("Timers:\n"); 890 for (i = 0; i < TCPT_NTIMERS; i++) { 891 ci = (callout_impl_t *)&tcpcb.t_timer[i]; 892 printf("\t%s: %d", tcptimers[i], 893 (ci->c_flags & CALLOUT_PENDING) ? 894 ci->c_time - hardticks : 0); 895 } 896 printf("\n\n"); 897 898 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 899 printf("State: %d", tcpcb.t_state); 900 else 901 printf("State: %s", tcpstates[tcpcb.t_state]); 902 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags, 903 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb); 904 905 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift, 906 tcpcb.t_rxtcur, tcpcb.t_dupacks); 907 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss, 908 tcpcb.t_ourmss, tcpcb.t_segsz); 909 910 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 911 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up); 912 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 913 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd); 914 915 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 916 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs); 917 918 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 919 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh); 920 921 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, " 922 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime, 923 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, 924 tcpcb.max_sndwnd); 925 926 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags, 927 tcpcb.t_iobc, tcpcb.t_softerror); 928 929 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 930 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale, 931 tcpcb.requested_s_scale); 932 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 933 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent); 934 } 935