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