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