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