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