1 /* $NetBSD: inet.c,v 1.87 2008/04/15 16:02:04 thorpej 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.87 2008/04/15 16:02:04 thorpej 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(struct in_addr *); 95 void inetprint(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 const 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(u_long off, 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(u_long off, char *name) 281 { 282 uint64_t tcpstat[TCP_NSTATS]; 283 284 if (use_sysctl) { 285 size_t size = sizeof(tcpstat); 286 287 if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size, 288 NULL, 0) == -1) 289 err(1, "net.inet.tcp.stats"); 290 } else { 291 if (off == 0) 292 return; 293 kread(off, (char *)tcpstat, sizeof (tcpstat)); 294 } 295 296 printf ("%s:\n", name); 297 298 #define ps(f, m) if (tcpstat[f] || sflag <= 1) \ 299 printf(m, (unsigned long long)tcpstat[f]) 300 #define p(f, m) if (tcpstat[f] || sflag <= 1) \ 301 printf(m, (unsigned long long)tcpstat[f], plural(tcpstat[f])) 302 #define p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 303 printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \ 304 (unsigned long long)tcpstat[f2], plural(tcpstat[f2])) 305 #define p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \ 306 printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \ 307 (unsigned long long)tcpstat[f2]) 308 #define p3(f, m) if (tcpstat[f] || sflag <= 1) \ 309 printf(m, (unsigned long long)tcpstat[f], plurales(tcpstat[f])) 310 311 p(TCP_STAT_SNDTOTAL, "\t%llu packet%s sent\n"); 312 p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE, 313 "\t\t%llu data packet%s (%llu byte%s)\n"); 314 p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE, 315 "\t\t%llu data packet%s (%llu byte%s) retransmitted\n"); 316 p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK, 317 "\t\t%llu ack-only packet%s (%llu delayed)\n"); 318 p(TCP_STAT_SNDURG, "\t\t%llu URG only packet%s\n"); 319 p(TCP_STAT_SNDPROBE, "\t\t%llu window probe packet%s\n"); 320 p(TCP_STAT_SNDWINUP, "\t\t%llu window update packet%s\n"); 321 p(TCP_STAT_SNDCTRL, "\t\t%llu control packet%s\n"); 322 p(TCP_STAT_SELFQUENCH, 323 "\t\t%llu send attempt%s resulted in self-quench\n"); 324 p(TCP_STAT_RCVTOTAL, "\t%llu packet%s received\n"); 325 p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE, 326 "\t\t%llu ack%s (for %llu byte%s)\n"); 327 p(TCP_STAT_RCVDUPACK, "\t\t%llu duplicate ack%s\n"); 328 p(TCP_STAT_RCVACKTOOMUCH, "\t\t%llu ack%s for unsent data\n"); 329 p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE, 330 "\t\t%llu packet%s (%llu byte%s) received in-sequence\n"); 331 p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE, 332 "\t\t%llu completely duplicate packet%s (%llu byte%s)\n"); 333 p(TCP_STAT_PAWSDROP, "\t\t%llu old duplicate packet%s\n"); 334 p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE, 335 "\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n"); 336 p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE, 337 "\t\t%llu out-of-order packet%s (%llu byte%s)\n"); 338 p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN, 339 "\t\t%llu packet%s (%llu byte%s) of data after window\n"); 340 p(TCP_STAT_RCVWINPROBE, "\t\t%llu window probe%s\n"); 341 p(TCP_STAT_RCVWINUPD, "\t\t%llu window update packet%s\n"); 342 p(TCP_STAT_RCVAFTERCLOSE, "\t\t%llu packet%s received after close\n"); 343 p(TCP_STAT_RCVBADSUM, "\t\t%llu discarded for bad checksum%s\n"); 344 p(TCP_STAT_RCVBADOFF, "\t\t%llu discarded for bad header offset field%s\n"); 345 ps(TCP_STAT_RCVSHORT, "\t\t%llu discarded because packet too short\n"); 346 p(TCP_STAT_CONNATTEMPT, "\t%llu connection request%s\n"); 347 p(TCP_STAT_ACCEPTS, "\t%llu connection accept%s\n"); 348 p(TCP_STAT_CONNECTS, 349 "\t%llu connection%s established (including accepts)\n"); 350 p2(TCP_STAT_CLOSED, TCP_STAT_DROPS, 351 "\t%llu connection%s closed (including %llu drop%s)\n"); 352 p(TCP_STAT_CONNDROPS, "\t%llu embryonic connection%s dropped\n"); 353 p(TCP_STAT_DELAYED_FREE, "\t%llu delayed free%s of tcpcb\n"); 354 p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED, 355 "\t%llu segment%s updated rtt (of %llu attempt%s)\n"); 356 p(TCP_STAT_REXMTTIMEO, "\t%llu retransmit timeout%s\n"); 357 p(TCP_STAT_TIMEOUTDROP, 358 "\t\t%llu connection%s dropped by rexmit timeout\n"); 359 p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS, 360 "\t%llu persist timeout%s (resulting in %llu dropped " 361 "connection%s)\n"); 362 p(TCP_STAT_KEEPTIMEO, "\t%llu keepalive timeout%s\n"); 363 p(TCP_STAT_KEEPPROBE, "\t\t%llu keepalive probe%s sent\n"); 364 p(TCP_STAT_KEEPDROPS, "\t\t%llu connection%s dropped by keepalive\n"); 365 p(TCP_STAT_PREDACK, "\t%llu correct ACK header prediction%s\n"); 366 p(TCP_STAT_PREDDAT, "\t%llu correct data packet header prediction%s\n"); 367 p3(TCP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n"); 368 ps(TCP_STAT_NOPORT, "\t%llu dropped due to no socket\n"); 369 p(TCP_STAT_CONNSDRAINED, "\t%llu connection%s drained due to memory " 370 "shortage\n"); 371 p(TCP_STAT_PMTUBLACKHOLE, "\t%llu PMTUD blackhole%s detected\n"); 372 373 p(TCP_STAT_BADSYN, "\t%llu bad connection attempt%s\n"); 374 ps(TCP_STAT_SC_ADDED, "\t%llu SYN cache entries added\n"); 375 p(TCP_STAT_SC_COLLISIONS, "\t\t%llu hash collision%s\n"); 376 ps(TCP_STAT_SC_COMPLETED, "\t\t%llu completed\n"); 377 ps(TCP_STAT_SC_ABORTED, "\t\t%llu aborted (no space to build PCB)\n"); 378 ps(TCP_STAT_SC_TIMED_OUT, "\t\t%llu timed out\n"); 379 ps(TCP_STAT_SC_OVERFLOWED, "\t\t%llu dropped due to overflow\n"); 380 ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%llu dropped due to bucket overflow\n"); 381 ps(TCP_STAT_SC_RESET, "\t\t%llu dropped due to RST\n"); 382 ps(TCP_STAT_SC_UNREACH, "\t\t%llu dropped due to ICMP unreachable\n"); 383 ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%llu delayed free of SYN cache " 384 "entries\n"); 385 p(TCP_STAT_SC_RETRANSMITTED, "\t%llu SYN,ACK%s retransmitted\n"); 386 p(TCP_STAT_SC_DUPESYN, "\t%llu duplicate SYN%s received for entries " 387 "already in the cache\n"); 388 p(TCP_STAT_SC_DROPPED, "\t%llu SYN%s dropped (no route or no space)\n"); 389 p(TCP_STAT_BADSIG, "\t%llu packet%s with bad signature\n"); 390 p(TCP_STAT_GOODSIG, "\t%llu packet%s with good signature\n"); 391 392 p(TCP_STAT_ECN_SHS, "\t%llu sucessful ECN handshake%s\n"); 393 p(TCP_STAT_ECN_CE, "\t%llu packet%s with ECN CE bit\n"); 394 p(TCP_STAT_ECN_ECT, "\t%llu packet%s ECN ECT(0) bit\n"); 395 #undef p 396 #undef ps 397 #undef p2 398 #undef p2s 399 #undef p3 400 } 401 402 /* 403 * Dump UDP statistics structure. 404 */ 405 void 406 udp_stats(u_long off, char *name) 407 { 408 uint64_t udpstat[UDP_NSTATS]; 409 u_quad_t delivered; 410 411 if (use_sysctl) { 412 size_t size = sizeof(udpstat); 413 414 if (sysctlbyname("net.inet.udp.stats", udpstat, &size, 415 NULL, 0) == -1) 416 err(1, "net.inet.udp.stats"); 417 } else { 418 if (off == 0) 419 return; 420 kread(off, (char *)udpstat, sizeof (udpstat)); 421 } 422 423 printf ("%s:\n", name); 424 425 #define ps(f, m) if (udpstat[f] || sflag <= 1) \ 426 printf(m, (unsigned long long)udpstat[f]) 427 #define p(f, m) if (udpstat[f] || sflag <= 1) \ 428 printf(m, (unsigned long long)udpstat[f], plural(udpstat[f])) 429 #define p3(f, m) if (udpstat[f] || sflag <= 1) \ 430 printf(m, (unsigned long long)udpstat[f], plurales(udpstat[f])) 431 432 p(UDP_STAT_IPACKETS, "\t%llu datagram%s received\n"); 433 ps(UDP_STAT_HDROPS, "\t%llu with incomplete header\n"); 434 ps(UDP_STAT_BADLEN, "\t%llu with bad data length field\n"); 435 ps(UDP_STAT_BADSUM, "\t%llu with bad checksum\n"); 436 ps(UDP_STAT_NOPORT, "\t%llu dropped due to no socket\n"); 437 p(UDP_STAT_NOPORTBCAST, 438 "\t%llu broadcast/multicast datagram%s dropped due to no socket\n"); 439 ps(UDP_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n"); 440 delivered = udpstat[UDP_STAT_IPACKETS] - 441 udpstat[UDP_STAT_HDROPS] - 442 udpstat[UDP_STAT_BADLEN] - 443 udpstat[UDP_STAT_BADSUM] - 444 udpstat[UDP_STAT_NOPORT] - 445 udpstat[UDP_STAT_NOPORTBCAST] - 446 udpstat[UDP_STAT_FULLSOCK]; 447 if (delivered || sflag <= 1) 448 printf("\t%llu delivered\n", (unsigned long long)delivered); 449 p3(UDP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n"); 450 p(UDP_STAT_OPACKETS, "\t%llu datagram%s output\n"); 451 452 #undef ps 453 #undef p 454 #undef p3 455 } 456 457 /* 458 * Dump IP statistics structure. 459 */ 460 void 461 ip_stats(u_long off, char *name) 462 { 463 uint64_t ipstat[IP_NSTATS]; 464 465 if (use_sysctl) { 466 size_t size = sizeof(ipstat); 467 468 if (sysctlbyname("net.inet.ip.stats", ipstat, &size, 469 NULL, 0) == -1) 470 err(1, "net.inet.ip.stats"); 471 } else { 472 if (off == 0) 473 return; 474 kread(off, (char *)ipstat, sizeof (ipstat)); 475 } 476 477 printf("%s:\n", name); 478 479 #define ps(f, m) if (ipstat[f] || sflag <= 1) \ 480 printf(m, (unsigned long long)ipstat[f]) 481 #define p(f, m) if (ipstat[f] || sflag <= 1) \ 482 printf(m, (unsigned long long)ipstat[f], plural(ipstat[f])) 483 484 p(IP_STAT_TOTAL, "\t%llu total packet%s received\n"); 485 p(IP_STAT_BADSUM, "\t%llu bad header checksum%s\n"); 486 ps(IP_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n"); 487 ps(IP_STAT_TOOSHORT, "\t%llu with data size < data length\n"); 488 ps(IP_STAT_TOOLONG, "\t%llu with length > max ip packet size\n"); 489 ps(IP_STAT_BADHLEN, "\t%llu with header length < data size\n"); 490 ps(IP_STAT_BADLEN, "\t%llu with data length < header length\n"); 491 ps(IP_STAT_BADOPTIONS, "\t%llu with bad options\n"); 492 ps(IP_STAT_BADVERS, "\t%llu with incorrect version number\n"); 493 p(IP_STAT_FRAGMENTS, "\t%llu fragment%s received\n"); 494 p(IP_STAT_FRAGDROPPED, "\t%llu fragment%s dropped (dup or out of space)\n"); 495 p(IP_STAT_RCVMEMDROP, "\t%llu fragment%s dropped (out of ipqent)\n"); 496 p(IP_STAT_BADFRAGS, "\t%llu malformed fragment%s dropped\n"); 497 p(IP_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n"); 498 p(IP_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n"); 499 p(IP_STAT_DELIVERED, "\t%llu packet%s for this host\n"); 500 p(IP_STAT_NOPROTO, "\t%llu packet%s for unknown/unsupported protocol\n"); 501 p(IP_STAT_FORWARD, "\t%llu packet%s forwarded"); 502 p(IP_STAT_FASTFORWARD, " (%llu packet%s fast forwarded)"); 503 if (ipstat[IP_STAT_FORWARD] || sflag <= 1) 504 putchar('\n'); 505 p(IP_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n"); 506 p(IP_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n"); 507 p(IP_STAT_NOGIF, "\t%llu packet%s no matching gif found\n"); 508 p(IP_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n"); 509 p(IP_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n"); 510 p(IP_STAT_ODROPPED, "\t%llu output packet%s dropped due to no bufs, etc.\n"); 511 p(IP_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n"); 512 p(IP_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n"); 513 p(IP_STAT_OFRAGMENTS, "\t%llu fragment%s created\n"); 514 p(IP_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n"); 515 p(IP_STAT_BADADDR, "\t%llu datagram%s with bad address in header\n"); 516 #undef ps 517 #undef p 518 } 519 520 static const char *icmpnames[] = { 521 "echo reply", 522 "#1", 523 "#2", 524 "destination unreachable", 525 "source quench", 526 "routing redirect", 527 "alternate host address", 528 "#7", 529 "echo", 530 "router advertisement", 531 "router solicitation", 532 "time exceeded", 533 "parameter problem", 534 "time stamp", 535 "time stamp reply", 536 "information request", 537 "information request reply", 538 "address mask request", 539 "address mask reply", 540 }; 541 542 /* 543 * Dump ICMP statistics. 544 */ 545 void 546 icmp_stats(u_long off, char *name) 547 { 548 uint64_t icmpstat[ICMP_NSTATS]; 549 int i, first; 550 551 if (use_sysctl) { 552 size_t size = sizeof(icmpstat); 553 554 if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size, 555 NULL, 0) == -1) 556 err(1, "net.inet.icmp.stats"); 557 } else { 558 if (off == 0) 559 return; 560 kread(off, (char *)icmpstat, sizeof (icmpstat)); 561 } 562 563 printf("%s:\n", name); 564 565 #define p(f, m) if (icmpstat[f] || sflag <= 1) \ 566 printf(m, (unsigned long long)icmpstat[f], plural(icmpstat[f])) 567 568 p(ICMP_STAT_ERROR, "\t%llu call%s to icmp_error\n"); 569 p(ICMP_STAT_OLDICMP, 570 "\t%llu error%s not generated because old message was icmp\n"); 571 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 572 if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) { 573 if (first) { 574 printf("\tOutput histogram:\n"); 575 first = 0; 576 } 577 printf("\t\t%s: %llu\n", icmpnames[i], 578 (unsigned long long)icmpstat[ICMP_STAT_OUTHIST + i]); 579 } 580 p(ICMP_STAT_BADCODE, "\t%llu message%s with bad code fields\n"); 581 p(ICMP_STAT_TOOSHORT, "\t%llu message%s < minimum length\n"); 582 p(ICMP_STAT_CHECKSUM, "\t%llu bad checksum%s\n"); 583 p(ICMP_STAT_BADLEN, "\t%llu message%s with bad length\n"); 584 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 585 if (icmpstat[ICMP_STAT_INHIST + i] != 0) { 586 if (first) { 587 printf("\tInput histogram:\n"); 588 first = 0; 589 } 590 printf("\t\t%s: %llu\n", icmpnames[i], 591 (unsigned long long)icmpstat[ICMP_STAT_INHIST + i]); 592 } 593 p(ICMP_STAT_REFLECT, "\t%llu message response%s generated\n"); 594 p(ICMP_STAT_PMTUCHG, "\t%llu path MTU change%s\n"); 595 #undef p 596 } 597 598 /* 599 * Dump IGMP statistics structure. 600 */ 601 void 602 igmp_stats(u_long off, char *name) 603 { 604 uint64_t igmpstat[IGMP_NSTATS]; 605 606 if (use_sysctl) { 607 size_t size = sizeof(igmpstat); 608 609 if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size, 610 NULL, 0) == -1) 611 err(1, "net.inet.igmp.stats"); 612 } else { 613 if (off == 0) 614 return; 615 kread(off, (char *)igmpstat, sizeof (igmpstat)); 616 } 617 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(IGMP_STAT_RCV_TOTAL, "\t%llu message%s received\n"); 625 p(IGMP_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n"); 626 p(IGMP_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n"); 627 py(IGMP_STAT_RCV_QUERIES, "\t%llu membership quer%s received\n"); 628 py(IGMP_STAT_RCV_BADQUERIES, "\t%llu membership quer%s received with invalid field(s)\n"); 629 p(IGMP_STAT_RCV_REPORTS, "\t%llu membership report%s received\n"); 630 p(IGMP_STAT_RCV_BADREPORTS, "\t%llu membership report%s received with invalid field(s)\n"); 631 p(IGMP_STAT_RCV_OURREPORTS, "\t%llu membership report%s received for groups to which we belong\n"); 632 p(IGMP_STAT_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 uint64_t carpstat[CARP_NSTATS]; 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(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n"); 667 p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n"); 668 p(CARP_STAT_BADIF, 669 "\t\t%" PRIu64 " packet%s discarded for bad interface\n"); 670 p(CARP_STAT_BADTTL, 671 "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n"); 672 p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n"); 673 p(CARP_STAT_BADSUM, "\t\t%" PRIu64 674 " packet%s discarded for bad checksum\n"); 675 p(CARP_STAT_BADVER, 676 "\t\t%" PRIu64 " packet%s discarded with a bad version\n"); 677 p2(CARP_STAT_BADLEN, 678 "\t\t%" PRIu64 " discarded because packet was too short\n"); 679 p(CARP_STAT_BADAUTH, 680 "\t\t%" PRIu64 " packet%s discarded for bad authentication\n"); 681 p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n"); 682 p(CARP_STAT_BADADDRS, "\t\t%" PRIu64 683 " packet%s discarded because of a bad address list\n"); 684 p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n"); 685 p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n"); 686 p2(CARP_STAT_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(u_long off, char *name) 697 { 698 struct pimstat pimstat; 699 700 if (off == 0) 701 return; 702 if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) { 703 /* XXX: PIM is probably not enabled in the kernel */ 704 return; 705 } 706 707 printf("%s:\n", name); 708 709 #define p(f, m) if (pimstat.f || sflag <= 1) \ 710 printf(m, (unsigned long long)pimstat.f, plural(pimstat.f)) 711 712 p(pims_rcv_total_msgs, "\t%llu message%s received\n"); 713 p(pims_rcv_total_bytes, "\t%llu byte%s received\n"); 714 p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 715 p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 716 p(pims_rcv_badversion, "\t%llu message%s received with bad version\n"); 717 p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n"); 718 p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n"); 719 p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n"); 720 p(pims_rcv_badregisters, "\t%llu bad register%s received\n"); 721 p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n"); 722 p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n"); 723 #undef p 724 } 725 726 /* 727 * Dump the ARP statistics structure. 728 */ 729 void 730 arp_stats(u_long off, char *name) 731 { 732 uint64_t arpstat[ARP_NSTATS]; 733 734 if (use_sysctl) { 735 size_t size = sizeof(arpstat); 736 737 if (sysctlbyname("net.inet.arp.stats", arpstat, &size, 738 NULL, 0) == -1) { 739 return; 740 } 741 } else { 742 if (off == 0) 743 return; 744 kread(off, (char *)arpstat, sizeof(arpstat)); 745 } 746 747 printf("%s:\n", name); 748 749 #define ps(f, m) if (arpstat[f] || sflag <= 1) \ 750 printf(m, (unsigned long long)arpstat[f]) 751 #define p(f, m) if (arpstat[f] || sflag <= 1) \ 752 printf(m, (unsigned long long)arpstat[f], plural(arpstat[f])) 753 754 p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n"); 755 p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n"); 756 p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n"); 757 758 p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n"); 759 p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n"); 760 p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n"); 761 p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n"); 762 p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n"); 763 p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n"); 764 p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n"); 765 p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n"); 766 ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n"); 767 p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware " 768 "address\n"); 769 p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast " 770 "source hardware address\n"); 771 p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n"); 772 p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n"); 773 p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n"); 774 p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n"); 775 p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n"); 776 777 p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n"); 778 ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n"); 779 ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n"); 780 781 p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n"); 782 783 #undef ps 784 #undef p 785 } 786 787 /* 788 * Pretty print an Internet address (net address + port). 789 * Take numeric_addr and numeric_port into consideration. 790 */ 791 void 792 inetprint(struct in_addr *in, uint16_t port, const char *proto, 793 int numeric_port) 794 { 795 struct servent *sp = 0; 796 char line[80], *cp; 797 size_t space; 798 799 (void)snprintf(line, sizeof line, "%.*s.", 800 (Aflag && !numeric_addr) ? 12 : 16, inetname(in)); 801 cp = strchr(line, '\0'); 802 if (!numeric_port && port) 803 sp = getservbyport((int)port, proto); 804 space = sizeof line - (cp-line); 805 if (sp || port == 0) 806 (void)snprintf(cp, space, "%s", sp ? sp->s_name : "*"); 807 else 808 (void)snprintf(cp, space, "%u", ntohs(port)); 809 (void)printf(" %-*.*s", width, width, line); 810 } 811 812 /* 813 * Construct an Internet address representation. 814 * If numeric_addr has been supplied, give 815 * numeric value, otherwise try for symbolic name. 816 */ 817 char * 818 inetname(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(u_long pcbaddr) 878 { 879 callout_impl_t *ci; 880 struct tcpcb tcpcb; 881 int i, hardticks; 882 883 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb)); 884 hardticks = get_hardticks(); 885 886 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 887 888 printf("Timers:\n"); 889 for (i = 0; i < TCPT_NTIMERS; i++) { 890 ci = (callout_impl_t *)&tcpcb.t_timer[i]; 891 printf("\t%s: %d", tcptimers[i], 892 (ci->c_flags & CALLOUT_PENDING) ? 893 ci->c_time - hardticks : 0); 894 } 895 printf("\n\n"); 896 897 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 898 printf("State: %d", tcpcb.t_state); 899 else 900 printf("State: %s", tcpstates[tcpcb.t_state]); 901 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags, 902 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb); 903 904 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift, 905 tcpcb.t_rxtcur, tcpcb.t_dupacks); 906 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss, 907 tcpcb.t_ourmss, tcpcb.t_segsz); 908 909 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 910 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up); 911 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 912 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd); 913 914 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 915 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs); 916 917 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 918 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh); 919 920 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, " 921 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime, 922 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, 923 tcpcb.max_sndwnd); 924 925 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags, 926 tcpcb.t_iobc, tcpcb.t_softerror); 927 928 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 929 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale, 930 tcpcb.requested_s_scale); 931 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 932 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent); 933 } 934