Home | History | Annotate | Line # | Download | only in netstat
inet.c revision 1.59
      1 /*	$NetBSD: inet.c,v 1.59 2003/09/04 09:23:38 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.59 2003/09/04 09:23:38 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 
    302 #undef p
    303 #undef ps
    304 #undef p2
    305 #undef p2s
    306 #undef p3
    307 }
    308 
    309 /*
    310  * Dump UDP statistics structure.
    311  */
    312 void
    313 udp_stats(off, name)
    314 	u_long off;
    315 	char *name;
    316 {
    317 	struct udpstat udpstat;
    318 	u_quad_t delivered;
    319 
    320 	if (off == 0)
    321 		return;
    322 	printf("%s:\n", name);
    323 	kread(off, (char *)&udpstat, sizeof (udpstat));
    324 
    325 #define	ps(f, m) if (udpstat.f || sflag <= 1) \
    326     printf(m, (unsigned long long)udpstat.f)
    327 #define	p(f, m) if (udpstat.f || sflag <= 1) \
    328     printf(m, (unsigned long long)udpstat.f, plural(udpstat.f))
    329 #define	p3(f, m) if (udpstat.f || sflag <= 1) \
    330     printf(m, (unsigned long long)udpstat.f, plurales(udpstat.f))
    331 
    332 	p(udps_ipackets, "\t%llu datagram%s received\n");
    333 	ps(udps_hdrops, "\t%llu with incomplete header\n");
    334 	ps(udps_badlen, "\t%llu with bad data length field\n");
    335 	ps(udps_badsum, "\t%llu with bad checksum\n");
    336 	ps(udps_noport, "\t%llu dropped due to no socket\n");
    337 	p(udps_noportbcast, "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
    338 	ps(udps_fullsock, "\t%llu dropped due to full socket buffers\n");
    339 	delivered = udpstat.udps_ipackets -
    340 		    udpstat.udps_hdrops -
    341 		    udpstat.udps_badlen -
    342 		    udpstat.udps_badsum -
    343 		    udpstat.udps_noport -
    344 		    udpstat.udps_noportbcast -
    345 		    udpstat.udps_fullsock;
    346 	if (delivered || sflag <= 1)
    347 		printf("\t%llu delivered\n", (unsigned long long)delivered);
    348 	p3(udps_pcbhashmiss, "\t%llu PCB hash miss%s\n");
    349 	p(udps_opackets, "\t%llu datagram%s output\n");
    350 
    351 #undef ps
    352 #undef p
    353 #undef p3
    354 }
    355 
    356 /*
    357  * Dump IP statistics structure.
    358  */
    359 void
    360 ip_stats(off, name)
    361 	u_long off;
    362 	char *name;
    363 {
    364 	struct ipstat ipstat;
    365 
    366 	if (off == 0)
    367 		return;
    368 	kread(off, (char *)&ipstat, sizeof (ipstat));
    369 	printf("%s:\n", name);
    370 
    371 #define	ps(f, m) if (ipstat.f || sflag <= 1) \
    372     printf(m, (unsigned long long)ipstat.f)
    373 #define	p(f, m) if (ipstat.f || sflag <= 1) \
    374     printf(m, (unsigned long long)ipstat.f, plural(ipstat.f))
    375 
    376 	p(ips_total, "\t%llu total packet%s received\n");
    377 	p(ips_badsum, "\t%llu bad header checksum%s\n");
    378 	ps(ips_toosmall, "\t%llu with size smaller than minimum\n");
    379 	ps(ips_tooshort, "\t%llu with data size < data length\n");
    380 	ps(ips_toolong, "\t%llu with length > max ip packet size\n");
    381 	ps(ips_badhlen, "\t%llu with header length < data size\n");
    382 	ps(ips_badlen, "\t%llu with data length < header length\n");
    383 	ps(ips_badoptions, "\t%llu with bad options\n");
    384 	ps(ips_badvers, "\t%llu with incorrect version number\n");
    385 	p(ips_fragments, "\t%llu fragment%s received\n");
    386 	p(ips_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
    387 	p(ips_badfrags, "\t%llu malformed fragment%s dropped\n");
    388 	p(ips_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
    389 	p(ips_reassembled, "\t%llu packet%s reassembled ok\n");
    390 	p(ips_delivered, "\t%llu packet%s for this host\n");
    391 	p(ips_noproto, "\t%llu packet%s for unknown/unsupported protocol\n");
    392 	p(ips_forward, "\t%llu packet%s forwarded");
    393 	p(ips_fastforward, " (%llu packet%s fast forwarded)");
    394 	if (ipstat.ips_forward || sflag <= 1)
    395 		putchar('\n');
    396 	p(ips_cantforward, "\t%llu packet%s not forwardable\n");
    397 	p(ips_redirectsent, "\t%llu redirect%s sent\n");
    398 	p(ips_localout, "\t%llu packet%s sent from this host\n");
    399 	p(ips_rawout, "\t%llu packet%s sent with fabricated ip header\n");
    400 	p(ips_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
    401 	p(ips_noroute, "\t%llu output packet%s discarded due to no route\n");
    402 	p(ips_fragmented, "\t%llu output datagram%s fragmented\n");
    403 	p(ips_ofragments, "\t%llu fragment%s created\n");
    404 	p(ips_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
    405 	p(ips_badaddr, "\t%llu datagram%s with bad address in header\n");
    406 #undef ps
    407 #undef p
    408 }
    409 
    410 static	char *icmpnames[] = {
    411 	"echo reply",
    412 	"#1",
    413 	"#2",
    414 	"destination unreachable",
    415 	"source quench",
    416 	"routing redirect",
    417 	"alternate host address",
    418 	"#7",
    419 	"echo",
    420 	"router advertisement",
    421 	"router solicitation",
    422 	"time exceeded",
    423 	"parameter problem",
    424 	"time stamp",
    425 	"time stamp reply",
    426 	"information request",
    427 	"information request reply",
    428 	"address mask request",
    429 	"address mask reply",
    430 };
    431 
    432 /*
    433  * Dump ICMP statistics.
    434  */
    435 void
    436 icmp_stats(off, name)
    437 	u_long off;
    438 	char *name;
    439 {
    440 	struct icmpstat icmpstat;
    441 	int i, first;
    442 
    443 	if (off == 0)
    444 		return;
    445 	kread(off, (char *)&icmpstat, sizeof (icmpstat));
    446 	printf("%s:\n", name);
    447 
    448 #define	p(f, m) if (icmpstat.f || sflag <= 1) \
    449     printf(m, (unsigned long long)icmpstat.f, plural(icmpstat.f))
    450 
    451 	p(icps_error, "\t%llu call%s to icmp_error\n");
    452 	p(icps_oldicmp,
    453 	    "\t%llu error%s not generated because old message was icmp\n");
    454 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    455 		if (icmpstat.icps_outhist[i] != 0) {
    456 			if (first) {
    457 				printf("\tOutput histogram:\n");
    458 				first = 0;
    459 			}
    460 			printf("\t\t%s: %llu\n", icmpnames[i],
    461 				(unsigned long long)icmpstat.icps_outhist[i]);
    462 		}
    463 	p(icps_badcode, "\t%llu message%s with bad code fields\n");
    464 	p(icps_tooshort, "\t%llu message%s < minimum length\n");
    465 	p(icps_checksum, "\t%llu bad checksum%s\n");
    466 	p(icps_badlen, "\t%llu message%s with bad length\n");
    467 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    468 		if (icmpstat.icps_inhist[i] != 0) {
    469 			if (first) {
    470 				printf("\tInput histogram:\n");
    471 				first = 0;
    472 			}
    473 			printf("\t\t%s: %llu\n", icmpnames[i],
    474 				(unsigned long long)icmpstat.icps_inhist[i]);
    475 		}
    476 	p(icps_reflect, "\t%llu message response%s generated\n");
    477 	p(icps_pmtuchg, "\t%llu path MTU change%s\n");
    478 #undef p
    479 }
    480 
    481 /*
    482  * Dump IGMP statistics structure.
    483  */
    484 void
    485 igmp_stats(off, name)
    486 	u_long off;
    487 	char *name;
    488 {
    489 	struct igmpstat igmpstat;
    490 
    491 	if (off == 0)
    492 		return;
    493 	kread(off, (char *)&igmpstat, sizeof (igmpstat));
    494 	printf("%s:\n", name);
    495 
    496 #define	p(f, m) if (igmpstat.f || sflag <= 1) \
    497     printf(m, (unsigned long long)igmpstat.f, plural(igmpstat.f))
    498 #define	py(f, m) if (igmpstat.f || sflag <= 1) \
    499     printf(m, (unsigned long long)igmpstat.f, igmpstat.f != 1 ? "ies" : "y")
    500 	p(igps_rcv_total, "\t%llu message%s received\n");
    501         p(igps_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
    502         p(igps_rcv_badsum, "\t%llu message%s received with bad checksum\n");
    503         py(igps_rcv_queries, "\t%llu membership quer%s received\n");
    504         py(igps_rcv_badqueries, "\t%llu membership quer%s received with invalid field(s)\n");
    505         p(igps_rcv_reports, "\t%llu membership report%s received\n");
    506         p(igps_rcv_badreports, "\t%llu membership report%s received with invalid field(s)\n");
    507         p(igps_rcv_ourreports, "\t%llu membership report%s received for groups to which we belong\n");
    508         p(igps_snd_reports, "\t%llu membership report%s sent\n");
    509 #undef p
    510 #undef py
    511 }
    512 
    513 /*
    514  * Dump the ARP statistics structure.
    515  */
    516 void
    517 arp_stats(off, name)
    518 	u_long off;
    519 	char *name;
    520 {
    521 	struct arpstat arpstat;
    522 
    523 	if (off == 0)
    524 		return;
    525 	kread(off, (char *)&arpstat, sizeof (arpstat));
    526 	printf("%s:\n", name);
    527 
    528 #define	ps(f, m) if (arpstat.f || sflag <= 1) \
    529     printf(m, (unsigned long long)arpstat.f)
    530 #define	p(f, m) if (arpstat.f || sflag <= 1) \
    531     printf(m, (unsigned long long)arpstat.f, plural(arpstat.f))
    532 
    533 	p(as_sndtotal, "\t%llu packet%s sent\n");
    534 	p(as_sndreply, "\t\t%llu reply packet%s\n");
    535 	p(as_sndrequest, "\t\t%llu request packet%s\n");
    536 
    537 	p(as_rcvtotal, "\t%llu packet%s received\n");
    538 	p(as_rcvreply, "\t\t%llu reply packet%s\n");
    539 	p(as_rcvrequest, "\t\t%llu valid request packet%s\n");
    540 	p(as_rcvmcast, "\t\t%llu broadcast/multicast packet%s\n");
    541 	p(as_rcvbadproto, "\t\t%llu packet%s with unknown protocol type\n");
    542 	p(as_rcvbadlen, "\t\t%llu packet%s with bad (short) length\n");
    543 	p(as_rcvzerotpa, "\t\t%llu packet%s with null target IP address\n");
    544 	p(as_rcvzerospa, "\t\t%llu packet%s with null source IP address\n");
    545 	ps(as_rcvnoint, "\t\t%llu could not be mapped to an interface\n");
    546 	p(as_rcvlocalsha, "\t\t%llu packet%s sourced from a local hardware "
    547 	    "address\n");
    548 	p(as_rcvbcastsha, "\t\t%llu packet%s with a broadcast "
    549 	    "source hardware address\n");
    550 	p(as_rcvlocalspa, "\t\t%llu duplicate%s for a local IP address\n");
    551 	p(as_rcvoverperm, "\t\t%llu attempt%s to overwrite a static entry\n");
    552 	p(as_rcvoverint, "\t\t%llu packet%s received on wrong interface\n");
    553 	p(as_rcvover, "\t\t%llu entry%s overwritten\n");
    554 	p(as_rcvlenchg, "\t\t%llu change%s in hardware address length\n");
    555 
    556 	p(as_dfrtotal, "\t%llu packet%s deferred pending ARP resolution\n");
    557 	ps(as_dfrsent, "\t\t%llu sent\n");
    558 	ps(as_dfrdropped, "\t\t%llu dropped\n");
    559 
    560 	p(as_allocfail, "\t%llu failure%s to allocate llinfo\n");
    561 
    562 #undef ps
    563 #undef p
    564 }
    565 
    566 /*
    567  * Pretty print an Internet address (net address + port).
    568  * Take numeric_addr and numeric_port into consideration.
    569  */
    570 void
    571 inetprint(in, port, proto, numeric_port)
    572 	struct in_addr *in;
    573 	u_int16_t port;
    574 	const char *proto;
    575 	int numeric_port;
    576 {
    577 	struct servent *sp = 0;
    578 	char line[80], *cp;
    579 	size_t space;
    580 
    581 	(void)snprintf(line, sizeof line, "%.*s.",
    582 	    (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
    583 	cp = strchr(line, '\0');
    584 	if (!numeric_port && port)
    585 		sp = getservbyport((int)port, proto);
    586 	space = sizeof line - (cp-line);
    587 	if (sp || port == 0)
    588 		(void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
    589 	else
    590 		(void)snprintf(cp, space, "%u", ntohs(port));
    591 	(void)printf(" %-*.*s", width, width, line);
    592 }
    593 
    594 /*
    595  * Construct an Internet address representation.
    596  * If numeric_addr has been supplied, give
    597  * numeric value, otherwise try for symbolic name.
    598  */
    599 char *
    600 inetname(inp)
    601 	struct in_addr *inp;
    602 {
    603 	char *cp;
    604 	static char line[50];
    605 	struct hostent *hp;
    606 	struct netent *np;
    607 	static char domain[MAXHOSTNAMELEN + 1];
    608 	static int first = 1;
    609 
    610 	if (first && !numeric_addr) {
    611 		first = 0;
    612 		if (gethostname(domain, sizeof domain) == 0) {
    613 			domain[sizeof(domain) - 1] = '\0';
    614 			if ((cp = strchr(domain, '.')))
    615 				(void) strlcpy(domain, cp + 1, sizeof(domain));
    616 			else
    617 				domain[0] = 0;
    618 		} else
    619 			domain[0] = 0;
    620 	}
    621 	cp = 0;
    622 	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
    623 		int net = inet_netof(*inp);
    624 		int lna = inet_lnaof(*inp);
    625 
    626 		if (lna == INADDR_ANY) {
    627 			np = getnetbyaddr(net, AF_INET);
    628 			if (np)
    629 				cp = np->n_name;
    630 		}
    631 		if (cp == 0) {
    632 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
    633 			if (hp) {
    634 				if ((cp = strchr(hp->h_name, '.')) &&
    635 				    !strcmp(cp + 1, domain))
    636 					*cp = 0;
    637 				cp = hp->h_name;
    638 			}
    639 		}
    640 	}
    641 	if (inp->s_addr == INADDR_ANY)
    642 		strlcpy(line, "*", sizeof line);
    643 	else if (cp)
    644 		strlcpy(line, cp, sizeof line);
    645 	else {
    646 		inp->s_addr = ntohl(inp->s_addr);
    647 #define C(x)	((x) & 0xff)
    648 		(void)snprintf(line, sizeof line, "%u.%u.%u.%u",
    649 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
    650 		    C(inp->s_addr >> 8), C(inp->s_addr));
    651 #undef C
    652 	}
    653 	return (line);
    654 }
    655 
    656 /*
    657  * Dump the contents of a TCP PCB.
    658  */
    659 void
    660 tcp_dump(pcbaddr)
    661 	u_long pcbaddr;
    662 {
    663 	struct tcpcb tcpcb;
    664 	int i, hardticks;
    665 
    666 	kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
    667 	hardticks = get_hardticks();
    668 
    669 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
    670 
    671 	printf("Timers:\n");
    672 	for (i = 0; i < TCPT_NTIMERS; i++) {
    673 		printf("\t%s: %d", tcptimers[i],
    674 		    (tcpcb.t_timer[i].c_flags & CALLOUT_PENDING) ?
    675 		    tcpcb.t_timer[i].c_time - hardticks : 0);
    676 	}
    677 	printf("\n\n");
    678 
    679 	if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
    680 		printf("State: %d", tcpcb.t_state);
    681 	else
    682 		printf("State: %s", tcpstates[tcpcb.t_state]);
    683 	printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
    684 	    (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
    685 
    686 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
    687 	    tcpcb.t_rxtcur, tcpcb.t_dupacks);
    688 	printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
    689 	    tcpcb.t_ourmss, tcpcb.t_segsz);
    690 
    691 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
    692 	    tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
    693 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
    694 	    tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
    695 
    696 	printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
    697 	    tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
    698 
    699 	printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
    700 	    tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
    701 
    702 	printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
    703 	    "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
    704 	    tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
    705 	    tcpcb.max_sndwnd);
    706 
    707 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
    708 	    tcpcb.t_iobc, tcpcb.t_softerror);
    709 
    710 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
    711 	    tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
    712 	    tcpcb.requested_s_scale);
    713 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
    714 	    tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
    715 }
    716