Home | History | Annotate | Line # | Download | only in netstat
inet.c revision 1.87
      1 /*	$NetBSD: inet.c,v 1.87 2008/04/15 16:02:04 thorpej 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.87 2008/04/15 16:02:04 thorpej Exp $");
     38 #endif
     39 #endif /* not lint */
     40 
     41 #define	_CALLOUT_PRIVATE	/* for defs in sys/callout.h */
     42 
     43 #include <sys/param.h>
     44 #include <sys/queue.h>
     45 #include <sys/socket.h>
     46 #include <sys/socketvar.h>
     47 #include <sys/mbuf.h>
     48 #include <sys/protosw.h>
     49 #include <sys/sysctl.h>
     50 
     51 #include <net/if_arp.h>
     52 #include <net/route.h>
     53 #include <netinet/in.h>
     54 #include <netinet/in_systm.h>
     55 #include <netinet/ip.h>
     56 #include <netinet/in_pcb.h>
     57 #include <netinet/ip_icmp.h>
     58 
     59 #ifdef INET6
     60 #include <netinet/ip6.h>
     61 #endif
     62 
     63 #include <netinet/icmp_var.h>
     64 #include <netinet/igmp_var.h>
     65 #include <netinet/ip_var.h>
     66 #include <netinet/pim_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/ip_carp.h>
     78 #include <netinet/udp_var.h>
     79 
     80 #include <arpa/inet.h>
     81 #include <kvm.h>
     82 #include <netdb.h>
     83 #include <stdio.h>
     84 #include <string.h>
     85 #include <unistd.h>
     86 #include <stdlib.h>
     87 #include <err.h>
     88 #include "netstat.h"
     89 
     90 struct	inpcb inpcb;
     91 struct	tcpcb tcpcb;
     92 struct	socket sockb;
     93 
     94 char	*inetname(struct in_addr *);
     95 void	inetprint(struct in_addr *, u_int16_t, const char *, int);
     96 
     97 /*
     98  * Print a summary of connections related to an Internet
     99  * protocol.  For TCP, also give state of connection.
    100  * Listening processes (aflag) are suppressed unless the
    101  * -a (all) flag is specified.
    102  */
    103 static int width;
    104 static int compact;
    105 
    106 static void
    107 protoprhdr(void)
    108 {
    109 	printf("Active Internet connections");
    110 	if (aflag)
    111 		printf(" (including servers)");
    112 	putchar('\n');
    113 	if (Aflag)
    114 		printf("%-8.8s ", "PCB");
    115 	printf("%-5.5s %-6.6s %-6.6s %s%-*.*s %-*.*s %s\n",
    116 		"Proto", "Recv-Q", "Send-Q", compact ? "" : " ",
    117 		width, width, "Local Address",
    118 		width, width, "Foreign Address",
    119 		"State");
    120 }
    121 
    122 static void
    123 protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
    124 	 struct in_addr *laddr, u_int16_t lport,
    125 	 struct in_addr *faddr, u_int16_t fport,
    126 	 short t_state, char *name)
    127 {
    128 	static const char *shorttcpstates[] = {
    129 		"CLOSED",	"LISTEN",	"SYNSEN",	"SYSRCV",
    130 		"ESTABL",	"CLWAIT",	"FWAIT1",	"CLOSNG",
    131 		"LASTAK",	"FWAIT2",	"TMWAIT",
    132 	};
    133 	int istcp;
    134 
    135 	istcp = strcmp(name, "tcp") == 0;
    136 
    137 	if (Aflag) {
    138 		printf("%8" PRIxPTR " ", ppcb);
    139 	}
    140 	printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
    141 	       compact ? "" : " ");
    142 	if (numeric_port) {
    143 		inetprint(laddr, lport, name, 1);
    144 		inetprint(faddr, fport, name, 1);
    145 	} else if (inpcb.inp_flags & INP_ANONPORT) {
    146 		inetprint(laddr, lport, name, 1);
    147 		inetprint(faddr, fport, name, 0);
    148 	} else {
    149 		inetprint(laddr, lport, name, 0);
    150 		inetprint(faddr, fport, name, 0);
    151 	}
    152 	if (istcp) {
    153 		if (t_state < 0 || t_state >= TCP_NSTATES)
    154 			printf(" %d", t_state);
    155 		else
    156 			printf(" %s", compact ? shorttcpstates[t_state] :
    157 			       tcpstates[t_state]);
    158 	}
    159 	putchar('\n');
    160 }
    161 
    162 void
    163 protopr(u_long off, char *name)
    164 {
    165 	struct inpcbtable table;
    166 	struct inpcb *head, *next, *prev;
    167 	struct inpcb inpcb;
    168 	int istcp;
    169 	static int first = 1;
    170 
    171 	compact = 0;
    172 	if (Aflag) {
    173 		if (!numeric_addr)
    174 			width = 18;
    175 		else {
    176 			width = 21;
    177 			compact = 1;
    178 		}
    179 	} else
    180 		width = 22;
    181 
    182 	if (use_sysctl) {
    183 		struct kinfo_pcb *pcblist;
    184 		int mib[8];
    185 		size_t namelen = 0, size = 0, i;
    186 		char *mibname = NULL;
    187 
    188 		memset(mib, 0, sizeof(mib));
    189 
    190 		if (asprintf(&mibname, "net.inet.%s.pcblist", name) == -1)
    191 			err(1, "asprintf");
    192 
    193 		/* get dynamic pcblist node */
    194 		if (sysctlnametomib(mibname, mib, &namelen) == -1)
    195 			err(1, "sysctlnametomib: %s", mibname);
    196 
    197 		if (sysctl(mib, sizeof(mib) / sizeof(*mib), NULL, &size,
    198 			   NULL, 0) == -1)
    199 			err(1, "sysctl (query)");
    200 
    201 		if ((pcblist = malloc(size)) == NULL)
    202 			err(1, "malloc");
    203 		memset(pcblist, 0, size);
    204 
    205 	        mib[6] = sizeof(*pcblist);
    206         	mib[7] = size / sizeof(*pcblist);
    207 
    208 		if (sysctl(mib, sizeof(mib) / sizeof(*mib), pcblist,
    209 			   &size, NULL, 0) == -1)
    210 			err(1, "sysctl (copy)");
    211 
    212 		for (i = 0; i < size / sizeof(*pcblist); i++) {
    213 			struct sockaddr_in src, dst;
    214 
    215 			memcpy(&src, &pcblist[i].ki_s, sizeof(src));
    216 			memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
    217 
    218 			if (first) {
    219 				protoprhdr();
    220 				first = 0;
    221 			}
    222 
    223 	                protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
    224 				 pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
    225 				 &src.sin_addr, src.sin_port,
    226 				 &dst.sin_addr, dst.sin_port,
    227 				 pcblist[i].ki_tstate, name);
    228 		}
    229 
    230 		free(pcblist);
    231 		return;
    232 	}
    233 
    234 	if (off == 0)
    235 		return;
    236 	istcp = strcmp(name, "tcp") == 0;
    237 	kread(off, (char *)&table, sizeof table);
    238 	prev = head =
    239 	    (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
    240 	next = (struct inpcb *)table.inpt_queue.cqh_first;
    241 
    242 	while (next != head) {
    243 		kread((u_long)next, (char *)&inpcb, sizeof inpcb);
    244 		if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
    245 			printf("???\n");
    246 			break;
    247 		}
    248 		prev = next;
    249 		next = (struct inpcb *)inpcb.inp_queue.cqe_next;
    250 
    251 		if (inpcb.inp_af != AF_INET)
    252 			continue;
    253 
    254 		if (!aflag &&
    255 		    inet_lnaof(inpcb.inp_laddr) == INADDR_ANY)
    256 			continue;
    257 		kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb));
    258 		if (istcp) {
    259 			kread((u_long)inpcb.inp_ppcb,
    260 			    (char *)&tcpcb, sizeof (tcpcb));
    261 		}
    262 
    263 		if (first) {
    264 			protoprhdr();
    265 			first = 0;
    266 		}
    267 
    268 		protopr0(istcp ? (intptr_t) inpcb.inp_ppcb : (intptr_t) prev,
    269 			 sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc,
    270 			 &inpcb.inp_laddr, inpcb.inp_lport,
    271 			 &inpcb.inp_faddr, inpcb.inp_fport,
    272 			 tcpcb.t_state, name);
    273 	}
    274 }
    275 
    276 /*
    277  * Dump TCP statistics structure.
    278  */
    279 void
    280 tcp_stats(u_long off, char *name)
    281 {
    282 	uint64_t tcpstat[TCP_NSTATS];
    283 
    284 	if (use_sysctl) {
    285 		size_t size = sizeof(tcpstat);
    286 
    287 		if (sysctlbyname("net.inet.tcp.stats", tcpstat, &size,
    288 				 NULL, 0) == -1)
    289 			err(1, "net.inet.tcp.stats");
    290 	} else {
    291 		if (off == 0)
    292 			return;
    293 		kread(off, (char *)tcpstat, sizeof (tcpstat));
    294 	}
    295 
    296 	printf ("%s:\n", name);
    297 
    298 #define	ps(f, m) if (tcpstat[f] || sflag <= 1) \
    299     printf(m, (unsigned long long)tcpstat[f])
    300 #define	p(f, m) if (tcpstat[f] || sflag <= 1) \
    301     printf(m, (unsigned long long)tcpstat[f], plural(tcpstat[f]))
    302 #define	p2(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
    303     printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \
    304     (unsigned long long)tcpstat[f2], plural(tcpstat[f2]))
    305 #define	p2s(f1, f2, m) if (tcpstat[f1] || tcpstat[f2] || sflag <= 1) \
    306     printf(m, (unsigned long long)tcpstat[f1], plural(tcpstat[f1]), \
    307     (unsigned long long)tcpstat[f2])
    308 #define	p3(f, m) if (tcpstat[f] || sflag <= 1) \
    309     printf(m, (unsigned long long)tcpstat[f], plurales(tcpstat[f]))
    310 
    311 	p(TCP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
    312 	p2(TCP_STAT_SNDPACK,TCP_STAT_SNDBYTE,
    313 		"\t\t%llu data packet%s (%llu byte%s)\n");
    314 	p2(TCP_STAT_SNDREXMITPACK, TCP_STAT_SNDREXMITBYTE,
    315 		"\t\t%llu data packet%s (%llu byte%s) retransmitted\n");
    316 	p2s(TCP_STAT_SNDACKS, TCP_STAT_DELACK,
    317 		"\t\t%llu ack-only packet%s (%llu delayed)\n");
    318 	p(TCP_STAT_SNDURG, "\t\t%llu URG only packet%s\n");
    319 	p(TCP_STAT_SNDPROBE, "\t\t%llu window probe packet%s\n");
    320 	p(TCP_STAT_SNDWINUP, "\t\t%llu window update packet%s\n");
    321 	p(TCP_STAT_SNDCTRL, "\t\t%llu control packet%s\n");
    322 	p(TCP_STAT_SELFQUENCH,
    323 	    "\t\t%llu send attempt%s resulted in self-quench\n");
    324 	p(TCP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
    325 	p2(TCP_STAT_RCVACKPACK, TCP_STAT_RCVACKBYTE,
    326 		"\t\t%llu ack%s (for %llu byte%s)\n");
    327 	p(TCP_STAT_RCVDUPACK, "\t\t%llu duplicate ack%s\n");
    328 	p(TCP_STAT_RCVACKTOOMUCH, "\t\t%llu ack%s for unsent data\n");
    329 	p2(TCP_STAT_RCVPACK, TCP_STAT_RCVBYTE,
    330 		"\t\t%llu packet%s (%llu byte%s) received in-sequence\n");
    331 	p2(TCP_STAT_RCVDUPPACK, TCP_STAT_RCVDUPBYTE,
    332 		"\t\t%llu completely duplicate packet%s (%llu byte%s)\n");
    333 	p(TCP_STAT_PAWSDROP, "\t\t%llu old duplicate packet%s\n");
    334 	p2(TCP_STAT_RCVPARTDUPPACK, TCP_STAT_RCVPARTDUPBYTE,
    335 		"\t\t%llu packet%s with some dup. data (%llu byte%s duped)\n");
    336 	p2(TCP_STAT_RCVOOPACK, TCP_STAT_RCVOOBYTE,
    337 		"\t\t%llu out-of-order packet%s (%llu byte%s)\n");
    338 	p2(TCP_STAT_RCVPACKAFTERWIN, TCP_STAT_RCVBYTEAFTERWIN,
    339 		"\t\t%llu packet%s (%llu byte%s) of data after window\n");
    340 	p(TCP_STAT_RCVWINPROBE, "\t\t%llu window probe%s\n");
    341 	p(TCP_STAT_RCVWINUPD, "\t\t%llu window update packet%s\n");
    342 	p(TCP_STAT_RCVAFTERCLOSE, "\t\t%llu packet%s received after close\n");
    343 	p(TCP_STAT_RCVBADSUM, "\t\t%llu discarded for bad checksum%s\n");
    344 	p(TCP_STAT_RCVBADOFF, "\t\t%llu discarded for bad header offset field%s\n");
    345 	ps(TCP_STAT_RCVSHORT, "\t\t%llu discarded because packet too short\n");
    346 	p(TCP_STAT_CONNATTEMPT, "\t%llu connection request%s\n");
    347 	p(TCP_STAT_ACCEPTS, "\t%llu connection accept%s\n");
    348 	p(TCP_STAT_CONNECTS,
    349 		"\t%llu connection%s established (including accepts)\n");
    350 	p2(TCP_STAT_CLOSED, TCP_STAT_DROPS,
    351 		"\t%llu connection%s closed (including %llu drop%s)\n");
    352 	p(TCP_STAT_CONNDROPS, "\t%llu embryonic connection%s dropped\n");
    353 	p(TCP_STAT_DELAYED_FREE, "\t%llu delayed free%s of tcpcb\n");
    354 	p2(TCP_STAT_RTTUPDATED, TCP_STAT_SEGSTIMED,
    355 		"\t%llu segment%s updated rtt (of %llu attempt%s)\n");
    356 	p(TCP_STAT_REXMTTIMEO, "\t%llu retransmit timeout%s\n");
    357 	p(TCP_STAT_TIMEOUTDROP,
    358 		"\t\t%llu connection%s dropped by rexmit timeout\n");
    359 	p2(TCP_STAT_PERSISTTIMEO, TCP_STAT_PERSISTDROPS,
    360 	   "\t%llu persist timeout%s (resulting in %llu dropped "
    361 		"connection%s)\n");
    362 	p(TCP_STAT_KEEPTIMEO, "\t%llu keepalive timeout%s\n");
    363 	p(TCP_STAT_KEEPPROBE, "\t\t%llu keepalive probe%s sent\n");
    364 	p(TCP_STAT_KEEPDROPS, "\t\t%llu connection%s dropped by keepalive\n");
    365 	p(TCP_STAT_PREDACK, "\t%llu correct ACK header prediction%s\n");
    366 	p(TCP_STAT_PREDDAT, "\t%llu correct data packet header prediction%s\n");
    367 	p3(TCP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
    368 	ps(TCP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
    369 	p(TCP_STAT_CONNSDRAINED, "\t%llu connection%s drained due to memory "
    370 		"shortage\n");
    371 	p(TCP_STAT_PMTUBLACKHOLE, "\t%llu PMTUD blackhole%s detected\n");
    372 
    373 	p(TCP_STAT_BADSYN, "\t%llu bad connection attempt%s\n");
    374 	ps(TCP_STAT_SC_ADDED, "\t%llu SYN cache entries added\n");
    375 	p(TCP_STAT_SC_COLLISIONS, "\t\t%llu hash collision%s\n");
    376 	ps(TCP_STAT_SC_COMPLETED, "\t\t%llu completed\n");
    377 	ps(TCP_STAT_SC_ABORTED, "\t\t%llu aborted (no space to build PCB)\n");
    378 	ps(TCP_STAT_SC_TIMED_OUT, "\t\t%llu timed out\n");
    379 	ps(TCP_STAT_SC_OVERFLOWED, "\t\t%llu dropped due to overflow\n");
    380 	ps(TCP_STAT_SC_BUCKETOVERFLOW, "\t\t%llu dropped due to bucket overflow\n");
    381 	ps(TCP_STAT_SC_RESET, "\t\t%llu dropped due to RST\n");
    382 	ps(TCP_STAT_SC_UNREACH, "\t\t%llu dropped due to ICMP unreachable\n");
    383 	ps(TCP_STAT_SC_DELAYED_FREE, "\t\t%llu delayed free of SYN cache "
    384 		"entries\n");
    385 	p(TCP_STAT_SC_RETRANSMITTED, "\t%llu SYN,ACK%s retransmitted\n");
    386 	p(TCP_STAT_SC_DUPESYN, "\t%llu duplicate SYN%s received for entries "
    387 		"already in the cache\n");
    388 	p(TCP_STAT_SC_DROPPED, "\t%llu SYN%s dropped (no route or no space)\n");
    389 	p(TCP_STAT_BADSIG, "\t%llu packet%s with bad signature\n");
    390 	p(TCP_STAT_GOODSIG, "\t%llu packet%s with good signature\n");
    391 
    392 	p(TCP_STAT_ECN_SHS, "\t%llu sucessful ECN handshake%s\n");
    393 	p(TCP_STAT_ECN_CE, "\t%llu packet%s with ECN CE bit\n");
    394 	p(TCP_STAT_ECN_ECT, "\t%llu packet%s ECN ECT(0) bit\n");
    395 #undef p
    396 #undef ps
    397 #undef p2
    398 #undef p2s
    399 #undef p3
    400 }
    401 
    402 /*
    403  * Dump UDP statistics structure.
    404  */
    405 void
    406 udp_stats(u_long off, char *name)
    407 {
    408 	uint64_t udpstat[UDP_NSTATS];
    409 	u_quad_t delivered;
    410 
    411 	if (use_sysctl) {
    412 		size_t size = sizeof(udpstat);
    413 
    414 		if (sysctlbyname("net.inet.udp.stats", udpstat, &size,
    415 				 NULL, 0) == -1)
    416 			err(1, "net.inet.udp.stats");
    417 	} else {
    418 		if (off == 0)
    419 			return;
    420 		kread(off, (char *)udpstat, sizeof (udpstat));
    421 	}
    422 
    423 	printf ("%s:\n", name);
    424 
    425 #define	ps(f, m) if (udpstat[f] || sflag <= 1) \
    426     printf(m, (unsigned long long)udpstat[f])
    427 #define	p(f, m) if (udpstat[f] || sflag <= 1) \
    428     printf(m, (unsigned long long)udpstat[f], plural(udpstat[f]))
    429 #define	p3(f, m) if (udpstat[f] || sflag <= 1) \
    430     printf(m, (unsigned long long)udpstat[f], plurales(udpstat[f]))
    431 
    432 	p(UDP_STAT_IPACKETS, "\t%llu datagram%s received\n");
    433 	ps(UDP_STAT_HDROPS, "\t%llu with incomplete header\n");
    434 	ps(UDP_STAT_BADLEN, "\t%llu with bad data length field\n");
    435 	ps(UDP_STAT_BADSUM, "\t%llu with bad checksum\n");
    436 	ps(UDP_STAT_NOPORT, "\t%llu dropped due to no socket\n");
    437 	p(UDP_STAT_NOPORTBCAST,
    438 	  "\t%llu broadcast/multicast datagram%s dropped due to no socket\n");
    439 	ps(UDP_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n");
    440 	delivered = udpstat[UDP_STAT_IPACKETS] -
    441 		    udpstat[UDP_STAT_HDROPS] -
    442 		    udpstat[UDP_STAT_BADLEN] -
    443 		    udpstat[UDP_STAT_BADSUM] -
    444 		    udpstat[UDP_STAT_NOPORT] -
    445 		    udpstat[UDP_STAT_NOPORTBCAST] -
    446 		    udpstat[UDP_STAT_FULLSOCK];
    447 	if (delivered || sflag <= 1)
    448 		printf("\t%llu delivered\n", (unsigned long long)delivered);
    449 	p3(UDP_STAT_PCBHASHMISS, "\t%llu PCB hash miss%s\n");
    450 	p(UDP_STAT_OPACKETS, "\t%llu datagram%s output\n");
    451 
    452 #undef ps
    453 #undef p
    454 #undef p3
    455 }
    456 
    457 /*
    458  * Dump IP statistics structure.
    459  */
    460 void
    461 ip_stats(u_long off, char *name)
    462 {
    463 	uint64_t ipstat[IP_NSTATS];
    464 
    465 	if (use_sysctl) {
    466 		size_t size = sizeof(ipstat);
    467 
    468 		if (sysctlbyname("net.inet.ip.stats", ipstat, &size,
    469 				 NULL, 0) == -1)
    470 			err(1, "net.inet.ip.stats");
    471 	} else {
    472 		if (off == 0)
    473 			return;
    474 		kread(off, (char *)ipstat, sizeof (ipstat));
    475 	}
    476 
    477 	printf("%s:\n", name);
    478 
    479 #define	ps(f, m) if (ipstat[f] || sflag <= 1) \
    480     printf(m, (unsigned long long)ipstat[f])
    481 #define	p(f, m) if (ipstat[f] || sflag <= 1) \
    482     printf(m, (unsigned long long)ipstat[f], plural(ipstat[f]))
    483 
    484 	p(IP_STAT_TOTAL, "\t%llu total packet%s received\n");
    485 	p(IP_STAT_BADSUM, "\t%llu bad header checksum%s\n");
    486 	ps(IP_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
    487 	ps(IP_STAT_TOOSHORT, "\t%llu with data size < data length\n");
    488 	ps(IP_STAT_TOOLONG, "\t%llu with length > max ip packet size\n");
    489 	ps(IP_STAT_BADHLEN, "\t%llu with header length < data size\n");
    490 	ps(IP_STAT_BADLEN, "\t%llu with data length < header length\n");
    491 	ps(IP_STAT_BADOPTIONS, "\t%llu with bad options\n");
    492 	ps(IP_STAT_BADVERS, "\t%llu with incorrect version number\n");
    493 	p(IP_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
    494 	p(IP_STAT_FRAGDROPPED, "\t%llu fragment%s dropped (dup or out of space)\n");
    495 	p(IP_STAT_RCVMEMDROP, "\t%llu fragment%s dropped (out of ipqent)\n");
    496 	p(IP_STAT_BADFRAGS, "\t%llu malformed fragment%s dropped\n");
    497 	p(IP_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
    498 	p(IP_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
    499 	p(IP_STAT_DELIVERED, "\t%llu packet%s for this host\n");
    500 	p(IP_STAT_NOPROTO, "\t%llu packet%s for unknown/unsupported protocol\n");
    501 	p(IP_STAT_FORWARD, "\t%llu packet%s forwarded");
    502 	p(IP_STAT_FASTFORWARD, " (%llu packet%s fast forwarded)");
    503 	if (ipstat[IP_STAT_FORWARD] || sflag <= 1)
    504 		putchar('\n');
    505 	p(IP_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
    506 	p(IP_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
    507 	p(IP_STAT_NOGIF, "\t%llu packet%s no matching gif found\n");
    508 	p(IP_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
    509 	p(IP_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
    510 	p(IP_STAT_ODROPPED, "\t%llu output packet%s dropped due to no bufs, etc.\n");
    511 	p(IP_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n");
    512 	p(IP_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
    513 	p(IP_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
    514 	p(IP_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
    515 	p(IP_STAT_BADADDR, "\t%llu datagram%s with bad address in header\n");
    516 #undef ps
    517 #undef p
    518 }
    519 
    520 static	const char *icmpnames[] = {
    521 	"echo reply",
    522 	"#1",
    523 	"#2",
    524 	"destination unreachable",
    525 	"source quench",
    526 	"routing redirect",
    527 	"alternate host address",
    528 	"#7",
    529 	"echo",
    530 	"router advertisement",
    531 	"router solicitation",
    532 	"time exceeded",
    533 	"parameter problem",
    534 	"time stamp",
    535 	"time stamp reply",
    536 	"information request",
    537 	"information request reply",
    538 	"address mask request",
    539 	"address mask reply",
    540 };
    541 
    542 /*
    543  * Dump ICMP statistics.
    544  */
    545 void
    546 icmp_stats(u_long off, char *name)
    547 {
    548 	uint64_t icmpstat[ICMP_NSTATS];
    549 	int i, first;
    550 
    551 	if (use_sysctl) {
    552 		size_t size = sizeof(icmpstat);
    553 
    554 		if (sysctlbyname("net.inet.icmp.stats", icmpstat, &size,
    555 				 NULL, 0) == -1)
    556 			err(1, "net.inet.icmp.stats");
    557 	} else {
    558 		if (off == 0)
    559 			return;
    560 		kread(off, (char *)icmpstat, sizeof (icmpstat));
    561 	}
    562 
    563 	printf("%s:\n", name);
    564 
    565 #define	p(f, m) if (icmpstat[f] || sflag <= 1) \
    566     printf(m, (unsigned long long)icmpstat[f], plural(icmpstat[f]))
    567 
    568 	p(ICMP_STAT_ERROR, "\t%llu call%s to icmp_error\n");
    569 	p(ICMP_STAT_OLDICMP,
    570 	    "\t%llu error%s not generated because old message was icmp\n");
    571 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    572 		if (icmpstat[ICMP_STAT_OUTHIST + i] != 0) {
    573 			if (first) {
    574 				printf("\tOutput histogram:\n");
    575 				first = 0;
    576 			}
    577 			printf("\t\t%s: %llu\n", icmpnames[i],
    578 			   (unsigned long long)icmpstat[ICMP_STAT_OUTHIST + i]);
    579 		}
    580 	p(ICMP_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
    581 	p(ICMP_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
    582 	p(ICMP_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
    583 	p(ICMP_STAT_BADLEN, "\t%llu message%s with bad length\n");
    584 	for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
    585 		if (icmpstat[ICMP_STAT_INHIST + i] != 0) {
    586 			if (first) {
    587 				printf("\tInput histogram:\n");
    588 				first = 0;
    589 			}
    590 			printf("\t\t%s: %llu\n", icmpnames[i],
    591 			    (unsigned long long)icmpstat[ICMP_STAT_INHIST + i]);
    592 		}
    593 	p(ICMP_STAT_REFLECT, "\t%llu message response%s generated\n");
    594 	p(ICMP_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
    595 #undef p
    596 }
    597 
    598 /*
    599  * Dump IGMP statistics structure.
    600  */
    601 void
    602 igmp_stats(u_long off, char *name)
    603 {
    604 	uint64_t igmpstat[IGMP_NSTATS];
    605 
    606 	if (use_sysctl) {
    607 		size_t size = sizeof(igmpstat);
    608 
    609 		if (sysctlbyname("net.inet.igmp.stats", igmpstat, &size,
    610 				 NULL, 0) == -1)
    611 			err(1, "net.inet.igmp.stats");
    612 	} else {
    613 		if (off == 0)
    614 			return;
    615 		kread(off, (char *)igmpstat, sizeof (igmpstat));
    616 	}
    617 
    618 	printf("%s:\n", name);
    619 
    620 #define	p(f, m) if (igmpstat[f] || sflag <= 1) \
    621     printf(m, (unsigned long long)igmpstat[f], plural(igmpstat[f]))
    622 #define	py(f, m) if (igmpstat[f] || sflag <= 1) \
    623     printf(m, (unsigned long long)igmpstat[f], igmpstat[f] != 1 ? "ies" : "y")
    624 	p(IGMP_STAT_RCV_TOTAL, "\t%llu message%s received\n");
    625         p(IGMP_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n");
    626         p(IGMP_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n");
    627         py(IGMP_STAT_RCV_QUERIES, "\t%llu membership quer%s received\n");
    628         py(IGMP_STAT_RCV_BADQUERIES, "\t%llu membership quer%s received with invalid field(s)\n");
    629         p(IGMP_STAT_RCV_REPORTS, "\t%llu membership report%s received\n");
    630         p(IGMP_STAT_RCV_BADREPORTS, "\t%llu membership report%s received with invalid field(s)\n");
    631         p(IGMP_STAT_RCV_OURREPORTS, "\t%llu membership report%s received for groups to which we belong\n");
    632         p(IGMP_STAT_SND_REPORTS, "\t%llu membership report%s sent\n");
    633 #undef p
    634 #undef py
    635 }
    636 
    637 /*
    638  * Dump CARP statistics structure.
    639  */
    640 void
    641 carp_stats(u_long off, char *name)
    642 {
    643 	uint64_t carpstat[CARP_NSTATS];
    644 
    645 	if (use_sysctl) {
    646 		size_t size = sizeof(carpstat);
    647 
    648 		if (sysctlbyname("net.inet.carp.stats", carpstat, &size,
    649 				 NULL, 0) == -1) {
    650 			/* most likely CARP is not compiled in the kernel */
    651 			return;
    652 		}
    653 	} else {
    654 		if (off == 0)
    655 			return;
    656 		kread(off, (char *)carpstat, sizeof(carpstat));
    657 	}
    658 
    659 	printf("%s:\n", name);
    660 
    661 #define p(f, m) if (carpstat[f] || sflag <= 1) \
    662 	printf(m, carpstat[f], plural(carpstat[f]))
    663 #define p2(f, m) if (carpstat[f] || sflag <= 1) \
    664 	printf(m, carpstat[f])
    665 
    666 	p(CARP_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
    667 	p(CARP_STAT_IPACKETS6, "\t%" PRIu64 " packet%s received (IPv6)\n");
    668 	p(CARP_STAT_BADIF,
    669 	    "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
    670 	p(CARP_STAT_BADTTL,
    671 	    "\t\t%" PRIu64 " packet%s discarded for wrong TTL\n");
    672 	p(CARP_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
    673 	p(CARP_STAT_BADSUM, "\t\t%" PRIu64
    674 		" packet%s discarded for bad checksum\n");
    675 	p(CARP_STAT_BADVER,
    676 	    "\t\t%" PRIu64 " packet%s discarded with a bad version\n");
    677 	p2(CARP_STAT_BADLEN,
    678 	    "\t\t%" PRIu64 " discarded because packet was too short\n");
    679 	p(CARP_STAT_BADAUTH,
    680 	    "\t\t%" PRIu64 " packet%s discarded for bad authentication\n");
    681 	p(CARP_STAT_BADVHID, "\t\t%" PRIu64 " packet%s discarded for bad vhid\n");
    682 	p(CARP_STAT_BADADDRS, "\t\t%" PRIu64
    683 		" packet%s discarded because of a bad address list\n");
    684 	p(CARP_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
    685 	p(CARP_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
    686 	p2(CARP_STAT_ONOMEM,
    687 	    "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
    688 #undef p
    689 #undef p2
    690 }
    691 
    692 /*
    693  * Dump PIM statistics structure.
    694  */
    695 void
    696 pim_stats(u_long off, char *name)
    697 {
    698 	struct pimstat pimstat;
    699 
    700 	if (off == 0)
    701 		return;
    702 	if (kread(off, (char *)&pimstat, sizeof (pimstat)) != 0) {
    703 		/* XXX: PIM is probably not enabled in the kernel */
    704 		return;
    705 	}
    706 
    707 	printf("%s:\n", name);
    708 
    709 #define	p(f, m) if (pimstat.f || sflag <= 1) \
    710 	printf(m, (unsigned long long)pimstat.f, plural(pimstat.f))
    711 
    712 	p(pims_rcv_total_msgs, "\t%llu message%s received\n");
    713 	p(pims_rcv_total_bytes, "\t%llu byte%s received\n");
    714 	p(pims_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
    715         p(pims_rcv_badsum, "\t%llu message%s received with bad checksum\n");
    716 	p(pims_rcv_badversion, "\t%llu message%s received with bad version\n");
    717 	p(pims_rcv_registers_msgs, "\t%llu data register message%s received\n");
    718 	p(pims_rcv_registers_bytes, "\t%llu data register byte%s received\n");
    719 	p(pims_rcv_registers_wrongiif, "\t%llu data register message%s received on wrong iif\n");
    720 	p(pims_rcv_badregisters, "\t%llu bad register%s received\n");
    721 	p(pims_snd_registers_msgs, "\t%llu data register message%s sent\n");
    722 	p(pims_snd_registers_bytes, "\t%llu data register byte%s sent\n");
    723 #undef p
    724 }
    725 
    726 /*
    727  * Dump the ARP statistics structure.
    728  */
    729 void
    730 arp_stats(u_long off, char *name)
    731 {
    732 	uint64_t arpstat[ARP_NSTATS];
    733 
    734 	if (use_sysctl) {
    735 		size_t size = sizeof(arpstat);
    736 
    737 		if (sysctlbyname("net.inet.arp.stats", arpstat, &size,
    738 				 NULL, 0) == -1) {
    739 			return;
    740 		}
    741 	} else {
    742 		if (off == 0)
    743 			return;
    744 		kread(off, (char *)arpstat, sizeof(arpstat));
    745 	}
    746 
    747 	printf("%s:\n", name);
    748 
    749 #define	ps(f, m) if (arpstat[f] || sflag <= 1) \
    750     printf(m, (unsigned long long)arpstat[f])
    751 #define	p(f, m) if (arpstat[f] || sflag <= 1) \
    752     printf(m, (unsigned long long)arpstat[f], plural(arpstat[f]))
    753 
    754 	p(ARP_STAT_SNDTOTAL, "\t%llu packet%s sent\n");
    755 	p(ARP_STAT_SNDREPLY, "\t\t%llu reply packet%s\n");
    756 	p(ARP_STAT_SENDREQUEST, "\t\t%llu request packet%s\n");
    757 
    758 	p(ARP_STAT_RCVTOTAL, "\t%llu packet%s received\n");
    759 	p(ARP_STAT_RCVREPLY, "\t\t%llu reply packet%s\n");
    760 	p(ARP_STAT_RCVREQUEST, "\t\t%llu valid request packet%s\n");
    761 	p(ARP_STAT_RCVMCAST, "\t\t%llu broadcast/multicast packet%s\n");
    762 	p(ARP_STAT_RCVBADPROTO, "\t\t%llu packet%s with unknown protocol type\n");
    763 	p(ARP_STAT_RCVBADLEN, "\t\t%llu packet%s with bad (short) length\n");
    764 	p(ARP_STAT_RCVZEROTPA, "\t\t%llu packet%s with null target IP address\n");
    765 	p(ARP_STAT_RCVZEROSPA, "\t\t%llu packet%s with null source IP address\n");
    766 	ps(ARP_STAT_RCVNOINT, "\t\t%llu could not be mapped to an interface\n");
    767 	p(ARP_STAT_RCVLOCALSHA, "\t\t%llu packet%s sourced from a local hardware "
    768 	    "address\n");
    769 	p(ARP_STAT_RCVBCASTSHA, "\t\t%llu packet%s with a broadcast "
    770 	    "source hardware address\n");
    771 	p(ARP_STAT_RCVLOCALSPA, "\t\t%llu duplicate%s for a local IP address\n");
    772 	p(ARP_STAT_RCVOVERPERM, "\t\t%llu attempt%s to overwrite a static entry\n");
    773 	p(ARP_STAT_RCVOVERINT, "\t\t%llu packet%s received on wrong interface\n");
    774 	p(ARP_STAT_RCVOVER, "\t\t%llu entry%s overwritten\n");
    775 	p(ARP_STAT_RCVLENCHG, "\t\t%llu change%s in hardware address length\n");
    776 
    777 	p(ARP_STAT_DFRTOTAL, "\t%llu packet%s deferred pending ARP resolution\n");
    778 	ps(ARP_STAT_DFRSENT, "\t\t%llu sent\n");
    779 	ps(ARP_STAT_DFRDROPPED, "\t\t%llu dropped\n");
    780 
    781 	p(ARP_STAT_ALLOCFAIL, "\t%llu failure%s to allocate llinfo\n");
    782 
    783 #undef ps
    784 #undef p
    785 }
    786 
    787 /*
    788  * Pretty print an Internet address (net address + port).
    789  * Take numeric_addr and numeric_port into consideration.
    790  */
    791 void
    792 inetprint(struct in_addr *in, uint16_t port, const char *proto,
    793 	  int numeric_port)
    794 {
    795 	struct servent *sp = 0;
    796 	char line[80], *cp;
    797 	size_t space;
    798 
    799 	(void)snprintf(line, sizeof line, "%.*s.",
    800 	    (Aflag && !numeric_addr) ? 12 : 16, inetname(in));
    801 	cp = strchr(line, '\0');
    802 	if (!numeric_port && port)
    803 		sp = getservbyport((int)port, proto);
    804 	space = sizeof line - (cp-line);
    805 	if (sp || port == 0)
    806 		(void)snprintf(cp, space, "%s", sp ? sp->s_name : "*");
    807 	else
    808 		(void)snprintf(cp, space, "%u", ntohs(port));
    809 	(void)printf(" %-*.*s", width, width, line);
    810 }
    811 
    812 /*
    813  * Construct an Internet address representation.
    814  * If numeric_addr has been supplied, give
    815  * numeric value, otherwise try for symbolic name.
    816  */
    817 char *
    818 inetname(struct in_addr *inp)
    819 {
    820 	char *cp;
    821 	static char line[50];
    822 	struct hostent *hp;
    823 	struct netent *np;
    824 	static char domain[MAXHOSTNAMELEN + 1];
    825 	static int first = 1;
    826 
    827 	if (first && !numeric_addr) {
    828 		first = 0;
    829 		if (gethostname(domain, sizeof domain) == 0) {
    830 			domain[sizeof(domain) - 1] = '\0';
    831 			if ((cp = strchr(domain, '.')))
    832 				(void) strlcpy(domain, cp + 1, sizeof(domain));
    833 			else
    834 				domain[0] = 0;
    835 		} else
    836 			domain[0] = 0;
    837 	}
    838 	cp = 0;
    839 	if (!numeric_addr && inp->s_addr != INADDR_ANY) {
    840 		int net = inet_netof(*inp);
    841 		int lna = inet_lnaof(*inp);
    842 
    843 		if (lna == INADDR_ANY) {
    844 			np = getnetbyaddr(net, AF_INET);
    845 			if (np)
    846 				cp = np->n_name;
    847 		}
    848 		if (cp == 0) {
    849 			hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
    850 			if (hp) {
    851 				if ((cp = strchr(hp->h_name, '.')) &&
    852 				    !strcmp(cp + 1, domain))
    853 					*cp = 0;
    854 				cp = hp->h_name;
    855 			}
    856 		}
    857 	}
    858 	if (inp->s_addr == INADDR_ANY)
    859 		strlcpy(line, "*", sizeof line);
    860 	else if (cp)
    861 		strlcpy(line, cp, sizeof line);
    862 	else {
    863 		inp->s_addr = ntohl(inp->s_addr);
    864 #define C(x)	((x) & 0xff)
    865 		(void)snprintf(line, sizeof line, "%u.%u.%u.%u",
    866 		    C(inp->s_addr >> 24), C(inp->s_addr >> 16),
    867 		    C(inp->s_addr >> 8), C(inp->s_addr));
    868 #undef C
    869 	}
    870 	return (line);
    871 }
    872 
    873 /*
    874  * Dump the contents of a TCP PCB.
    875  */
    876 void
    877 tcp_dump(u_long pcbaddr)
    878 {
    879 	callout_impl_t *ci;
    880 	struct tcpcb tcpcb;
    881 	int i, hardticks;
    882 
    883 	kread(pcbaddr, (char *)&tcpcb, sizeof(tcpcb));
    884 	hardticks = get_hardticks();
    885 
    886 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
    887 
    888 	printf("Timers:\n");
    889 	for (i = 0; i < TCPT_NTIMERS; i++) {
    890 		ci = (callout_impl_t *)&tcpcb.t_timer[i];
    891 		printf("\t%s: %d", tcptimers[i],
    892 		    (ci->c_flags & CALLOUT_PENDING) ?
    893 		    ci->c_time - hardticks : 0);
    894 	}
    895 	printf("\n\n");
    896 
    897 	if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES)
    898 		printf("State: %d", tcpcb.t_state);
    899 	else
    900 		printf("State: %s", tcpstates[tcpcb.t_state]);
    901 	printf(", flags 0x%x, inpcb 0x%lx, in6pcb 0x%lx\n\n", tcpcb.t_flags,
    902 	    (u_long)tcpcb.t_inpcb, (u_long)tcpcb.t_in6pcb);
    903 
    904 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcpcb.t_rxtshift,
    905 	    tcpcb.t_rxtcur, tcpcb.t_dupacks);
    906 	printf("peermss %u, ourmss %u, segsz %u\n\n", tcpcb.t_peermss,
    907 	    tcpcb.t_ourmss, tcpcb.t_segsz);
    908 
    909 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
    910 	    tcpcb.snd_una, tcpcb.snd_nxt, tcpcb.snd_up);
    911 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %lu\n\n",
    912 	    tcpcb.snd_wl1, tcpcb.snd_wl2, tcpcb.iss, tcpcb.snd_wnd);
    913 
    914 	printf("rcv_wnd %lu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
    915 	    tcpcb.rcv_wnd, tcpcb.rcv_nxt, tcpcb.rcv_up, tcpcb.irs);
    916 
    917 	printf("rcv_adv %u, snd_max %u, snd_cwnd %lu, snd_ssthresh %lu\n",
    918 	    tcpcb.rcv_adv, tcpcb.snd_max, tcpcb.snd_cwnd, tcpcb.snd_ssthresh);
    919 
    920 	printf("rcvtime %u, rtttime %u, rtseq %u, srtt %d, rttvar %d, "
    921 	    "rttmin %d, max_sndwnd %lu\n\n", tcpcb.t_rcvtime, tcpcb.t_rtttime,
    922 	    tcpcb.t_rtseq, tcpcb.t_srtt, tcpcb.t_rttvar, tcpcb.t_rttmin,
    923 	    tcpcb.max_sndwnd);
    924 
    925 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcpcb.t_oobflags,
    926 	    tcpcb.t_iobc, tcpcb.t_softerror);
    927 
    928 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
    929 	    tcpcb.snd_scale, tcpcb.rcv_scale, tcpcb.request_r_scale,
    930 	    tcpcb.requested_s_scale);
    931 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
    932 	    tcpcb.ts_recent, tcpcb.ts_recent_age, tcpcb.last_ack_sent);
    933 }
    934