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