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