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