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