1 /* $NetBSD: inet.c,v 1.52 2002/05/26 16:05:45 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; 40 #else 41 __RCSID("$NetBSD: inet.c,v 1.52 2002/05/26 16:05:45 itojun Exp $"); 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/queue.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/mbuf.h> 50 #include <sys/protosw.h> 51 52 #include <net/if_arp.h> 53 #include <net/route.h> 54 #include <netinet/in.h> 55 #include <netinet/in_systm.h> 56 #include <netinet/ip.h> 57 #include <netinet/in_pcb.h> 58 #include <netinet/ip_icmp.h> 59 60 #ifdef INET6 61 #include <netinet/ip6.h> 62 #endif 63 64 #include <netinet/icmp_var.h> 65 #include <netinet/igmp_var.h> 66 #include <netinet/ip_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/udp_var.h> 78 79 #include <arpa/inet.h> 80 #include <netdb.h> 81 #include <stdio.h> 82 #include <string.h> 83 #include <unistd.h> 84 #include "netstat.h" 85 86 struct inpcb inpcb; 87 struct tcpcb tcpcb; 88 struct socket sockb; 89 90 char *inetname __P((struct in_addr *)); 91 void inetprint __P((struct in_addr *, u_int16_t, const char *, int)); 92 93 /* 94 * Print a summary of connections related to an Internet 95 * protocol. For TCP, also give state of connection. 96 * Listening processes (aflag) are suppressed unless the 97 * -a (all) flag is specified. 98 */ 99 static int width; 100 101 void 102 protopr(off, name) 103 u_long off; 104 char *name; 105 { 106 struct inpcbtable table; 107 struct inpcb *head, *next, *prev; 108 struct inpcb inpcb; 109 int istcp, compact; 110 static int first = 1; 111 static char *shorttcpstates[] = { 112 "CLOSED", "LISTEN", "SYNSEN", "SYSRCV", 113 "ESTABL", "CLWAIT", "FWAIT1", "CLOSNG", 114 "LASTAK", "FWAIT2", "TMWAIT", 115 }; 116 117 if (off == 0) 118 return; 119 istcp = strcmp(name, "tcp") == 0; 120 kread(off, (char *)&table, sizeof table); 121 prev = head = 122 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first; 123 next = table.inpt_queue.cqh_first; 124 125 compact = 0; 126 if (Aflag) { 127 if (!numeric_addr) 128 width = 18; 129 else { 130 width = 21; 131 compact = 1; 132 } 133 } else 134 width = 22; 135 while (next != head) { 136 kread((u_long)next, (char *)&inpcb, sizeof inpcb); 137 if (inpcb.inp_queue.cqe_prev != prev) { 138 printf("???\n"); 139 break; 140 } 141 prev = next; 142 next = inpcb.inp_queue.cqe_next; 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 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 p(tcps_sc_retransmitted, "\t%llu SYN,ACK%s retransmitted\n"); 296 p(tcps_sc_dupesyn, "\t%llu duplicate SYN%s received for entries " 297 "already in the cache\n"); 298 p(tcps_sc_dropped, "\t%llu SYN%s dropped (no route or no space)\n"); 299 300 #undef p 301 #undef ps 302 #undef p2 303 #undef p2s 304 #undef p3 305 } 306 307 /* 308 * Dump UDP statistics structure. 309 */ 310 void 311 udp_stats(off, name) 312 u_long off; 313 char *name; 314 { 315 struct udpstat udpstat; 316 u_quad_t delivered; 317 318 if (off == 0) 319 return; 320 printf("%s:\n", name); 321 kread(off, (char *)&udpstat, sizeof (udpstat)); 322 323 #define ps(f, m) if (udpstat.f || sflag <= 1) \ 324 printf(m, (unsigned long long)udpstat.f) 325 #define p(f, m) if (udpstat.f || sflag <= 1) \ 326 printf(m, (unsigned long long)udpstat.f, plural(udpstat.f)) 327 #define p3(f, m) if (udpstat.f || sflag <= 1) \ 328 printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f)) 329 330 p(udps_ipackets, "\t%llu datagram%s received\n"); 331 ps(udps_hdrops, "\t%llu with incomplete header\n"); 332 ps(udps_badlen, "\t%llu with bad data length field\n"); 333 ps(udps_badsum, "\t%llu with bad checksum\n"); 334 ps(udps_noport, "\t%llu dropped due to no socket\n"); 335 p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n"); 336 ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n"); 337 delivered = udpstat.udps_ipackets - 338 udpstat.udps_hdrops - 339 udpstat.udps_badlen - 340 udpstat.udps_badsum - 341 udpstat.udps_noport - 342 udpstat.udps_noportbcast - 343 udpstat.udps_fullsock; 344 if (delivered || sflag <= 1) 345 printf("\t%llu delivered\n", (unsigned long long)delivered); 346 p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n"); 347 p(udps_opackets, "\t%llu datagram%s output\n"); 348 349 #undef ps 350 #undef p 351 #undef p3 352 } 353 354 /* 355 * Dump IP statistics structure. 356 */ 357 void 358 ip_stats(off, name) 359 u_long off; 360 char *name; 361 { 362 struct ipstat ipstat; 363 364 if (off == 0) 365 return; 366 kread(off, (char *)&ipstat, sizeof (ipstat)); 367 printf("%s:\n", name); 368 369 #define ps(f, m) if (ipstat.f || sflag <= 1) \ 370 printf(m, (unsigned long long)ipstat.f) 371 #define p(f, m) if (ipstat.f || sflag <= 1) \ 372 printf(m, (unsigned long long)ipstat.f, plural(ipstat.f)) 373 374 p(ips_total, "\t%llu total packet%s received\n"); 375 p(ips_badsum, "\t%llu bad header checksum%s\n"); 376 ps(ips_toosmall, "\t%llu with size smaller than minimum\n"); 377 ps(ips_tooshort, "\t%llu with data size < data length\n"); 378 ps(ips_toolong, "\t%llu with length > max ip packet size\n"); 379 ps(ips_badhlen, "\t%llu with header length < data size\n"); 380 ps(ips_badlen, "\t%llu with data length < header length\n"); 381 ps(ips_badoptions, "\t%llu with bad options\n"); 382 ps(ips_badvers, "\t%llu with incorrect version number\n"); 383 p(ips_fragments, "\t%llu fragment%s received\n"); 384 p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n"); 385 p(ips_badfrags, "\t%llu malformed fragment%s dropped\n"); 386 p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n"); 387 p(ips_reassembled, "\t%llu packet%s reassembled ok\n"); 388 p(ips_delivered, "\t%llu packet%s for this host\n"); 389 p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n"); 390 p(ips_forward, "\t%llu packet%s forwarded"); 391 p(ips_fastforward, " (%llu packet%s fast forwarded)"); 392 if (ipstat.ips_forward || sflag <= 1) 393 putchar('\n'); 394 p(ips_cantforward, "\t%llu packet%s not forwardable\n"); 395 p(ips_redirectsent, "\t%llu redirect%s sent\n"); 396 p(ips_localout, "\t%llu packet%s sent from this host\n"); 397 p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n"); 398 p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n"); 399 p(ips_noroute, "\t%llu output packet%s discarded due to no route\n"); 400 p(ips_fragmented, "\t%llu output datagram%s fragmented\n"); 401 p(ips_ofragments, "\t%llu fragment%s created\n"); 402 p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n"); 403 p(ips_badaddr, "\t%llu datagram%s with bad address in header\n"); 404 #undef ps 405 #undef p 406 } 407 408 static char *icmpnames[] = { 409 "echo reply", 410 "#1", 411 "#2", 412 "destination unreachable", 413 "source quench", 414 "routing redirect", 415 "alternate host address", 416 "#7", 417 "echo", 418 "router advertisement", 419 "router solicitation", 420 "time exceeded", 421 "parameter problem", 422 "time stamp", 423 "time stamp reply", 424 "information request", 425 "information request reply", 426 "address mask request", 427 "address mask reply", 428 }; 429 430 /* 431 * Dump ICMP statistics. 432 */ 433 void 434 icmp_stats(off, name) 435 u_long off; 436 char *name; 437 { 438 struct icmpstat icmpstat; 439 int i, first; 440 441 if (off == 0) 442 return; 443 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 444 printf("%s:\n", name); 445 446 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 447 printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f)) 448 449 p(icps_error, "\t%llu call%s to icmp_error\n"); 450 p(icps_oldicmp, 451 "\t%llu error%s not generated because old message was icmp\n"); 452 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 453 if (icmpstat.icps_outhist[i] != 0) { 454 if (first) { 455 printf("\tOutput histogram:\n"); 456 first = 0; 457 } 458 printf("\t\t%s: %llu\n", icmpnames[i], 459 (unsigned long long)icmpstat.icps_outhist[i]); 460 } 461 p(icps_badcode, "\t%llu message%s with bad code fields\n"); 462 p(icps_tooshort, "\t%llu message%s < minimum length\n"); 463 p(icps_checksum, "\t%llu bad checksum%s\n"); 464 p(icps_badlen, "\t%llu message%s with bad length\n"); 465 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 466 if (icmpstat.icps_inhist[i] != 0) { 467 if (first) { 468 printf("\tInput histogram:\n"); 469 first = 0; 470 } 471 printf("\t\t%s: %llu\n", icmpnames[i], 472 (unsigned long long)icmpstat.icps_inhist[i]); 473 } 474 p(icps_reflect, "\t%llu message response%s generated\n"); 475 p(icps_pmtuchg, "\t%llu path MTU change%s\n"); 476 #undef p 477 } 478 479 /* 480 * Dump IGMP statistics structure. 481 */ 482 void 483 igmp_stats(off, name) 484 u_long off; 485 char *name; 486 { 487 struct igmpstat igmpstat; 488 489 if (off == 0) 490 return; 491 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 492 printf("%s:\n", name); 493 494 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 495 printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f)) 496 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 497 printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 498 p(igps_rcv_total, "\t%llu message%s received\n"); 499 p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); 500 p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n"); 501 py(igps_rcv_queries, "\t%llu membership quer%s received\n"); 502 py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n"); 503 p(igps_rcv_reports, "\t%llu membership report%s received\n"); 504 p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n"); 505 p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n"); 506 p(igps_snd_reports, "\t%llu membership report%s sent\n"); 507 #undef p 508 #undef py 509 } 510 511 /* 512 * Dump the ARP statistics structure. 513 */ 514 void 515 arp_stats(off, name) 516 u_long off; 517 char *name; 518 { 519 struct arpstat arpstat; 520 521 if (off == 0) 522 return; 523 kread(off, (char *)&arpstat, sizeof (arpstat)); 524 printf("%s:\n", name); 525 526 #define ps(f, m) if (arpstat.f || sflag <= 1) \ 527 printf(m, (unsigned long long)arpstat.f) 528 #define p(f, m) if (arpstat.f || sflag <= 1) \ 529 printf(m, (unsigned long long)arpstat.f, plural(arpstat.f)) 530 531 p(as_sndtotal, "\t%llu packet%s sent\n"); 532 p(as_sndreply, "\t\t%llu reply packet%s\n"); 533 p(as_sndrequest, "\t\t%llu request packet%s\n"); 534 535 p(as_rcvtotal, "\t%llu packet%s received\n"); 536 p(as_rcvreply, "\t\t%llu reply packet%s\n"); 537 p(as_rcvrequest, "\t\t%llu valid request packet%s\n"); 538 p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n"); 539 p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n"); 540 p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n"); 541 p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n"); 542 p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n"); 543 ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n"); 544 p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware " 545 "address\n"); 546 p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast " 547 "source hardware address\n"); 548 p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n"); 549 p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n"); 550 p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n"); 551 p(as_rcvover, "\t\t%llu entry%s overwritten\n"); 552 p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n"); 553 554 p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n"); 555 ps(as_dfrsent, "\t\t%llu sent\n"); 556 ps(as_dfrdropped, "\t\t%llu dropped\n"); 557 558 p(as_allocfail, "\t%llu failure%s to allocate llinfo\n"); 559 560 #undef ps 561 #undef p 562 } 563 564 /* 565 * Pretty print an Internet address (net address + port). 566 * Take numeric_addr and numeric_port into consideration. 567 */ 568 void 569 inetprint(in, port, proto, numeric_port) 570 struct in_addr *in; 571 u_int16_t port; 572 const char *proto; 573 int numeric_port; 574 { 575 struct servent *sp = 0; 576 char line[80], *cp; 577 size_t space; 578 579 (void)snprintf(line, sizeof line, "%.*s.", 580 (Aflag && !numeric_addr) ? 12 : 16, inetname(in)); 581 cp = strchr(line, '\0'); 582 if (!numeric_port && port) 583 sp = getservbyport((int)port, proto); 584 space = sizeof line - (cp-line); 585 if (sp || port == 0) 586 (void)snprintf(cp, space, "%.8s", sp ? sp->s_name : "*"); 587 else 588 (void)snprintf(cp, space, "%u", ntohs(port)); 589 (void)printf(" %-*.*s", width, width, line); 590 } 591 592 /* 593 * Construct an Internet address representation. 594 * If numeric_addr has been supplied, give 595 * numeric value, otherwise try for symbolic name. 596 */ 597 char * 598 inetname(inp) 599 struct in_addr *inp; 600 { 601 char *cp; 602 static char line[50]; 603 struct hostent *hp; 604 struct netent *np; 605 static char domain[MAXHOSTNAMELEN + 1]; 606 static int first = 1; 607 608 if (first && !numeric_addr) { 609 first = 0; 610 if (gethostname(domain, sizeof domain) == 0) { 611 domain[sizeof(domain) - 1] = '\0'; 612 if ((cp = strchr(domain, '.'))) 613 (void) strlcpy(domain, cp + 1, sizeof(domain)); 614 else 615 domain[0] = 0; 616 } else 617 domain[0] = 0; 618 } 619 cp = 0; 620 if (!numeric_addr && inp->s_addr != INADDR_ANY) { 621 int net = inet_netof(*inp); 622 int lna = inet_lnaof(*inp); 623 624 if (lna == INADDR_ANY) { 625 np = getnetbyaddr(net, AF_INET); 626 if (np) 627 cp = np->n_name; 628 } 629 if (cp == 0) { 630 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 631 if (hp) { 632 if ((cp = strchr(hp->h_name, '.')) && 633 !strcmp(cp + 1, domain)) 634 *cp = 0; 635 cp = hp->h_name; 636 } 637 } 638 } 639 if (inp->s_addr == INADDR_ANY) 640 strncpy(line, "*", sizeof line); 641 else if (cp) 642 strncpy(line, cp, sizeof line); 643 else { 644 inp->s_addr = ntohl(inp->s_addr); 645 #define C(x) ((x) & 0xff) 646 (void)snprintf(line, sizeof line, "%u.%u.%u.%u", 647 C(inp->s_addr >> 24), C(inp->s_addr >> 16), 648 C(inp->s_addr >> 8), C(inp->s_addr)); 649 #undef C 650 } 651 line[sizeof(line) - 1] = '\0'; 652 return (line); 653 } 654 655 /* 656 * Dump the contents of a TCP PCB. 657 */ 658 void 659 tcp_dump(pcbaddr) 660 u_long pcbaddr; 661 { 662 struct tcpcb tcpcb; 663 int i; 664 665 kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb)); 666 667 printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr); 668 669 printf("Timers:\n"); 670 for (i = 0; i < TCPT_NTIMERS; i++) { 671 printf("\t%s: %llu", tcptimers[i], 672 (tcpcb.t_timer[i].c_flags & CALLOUT_ACTIVE) ? 673 (unsigned long long) tcpcb.t_timer[i].c_time : 0); 674 } 675 printf("\n\n"); 676 677 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 678 printf("State: %d", tcpcb.t_state); 679 else 680 printf("State: %s", tcpstates[tcpcb.t_state]); 681 printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags, 682 (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb); 683 684 printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift, 685 tcpcb.t_rxtcur, tcpcb.t_dupacks); 686 printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss, 687 tcpcb.t_ourmss, tcpcb.t_segsz); 688 689 printf("snd_una %u, snd_nxt %u, snd_up %u\n", 690 tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up); 691 printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n", 692 tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd); 693 694 printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n", 695 tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs); 696 697 printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n", 698 tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh); 699 700 printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, " 701 "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime, 702 tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin, 703 tcpcb.max_sndwnd); 704 705 printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags, 706 tcpcb.t_iobc, tcpcb.t_softerror); 707 708 printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n", 709 tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale, 710 tcpcb.requested_s_scale); 711 printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n", 712 tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent); 713 } 714