xref: /netbsd-src/usr.bin/netstat/inet6.c (revision 4391d5e9d4f291db41e3b3ba26a01b5e51364aae)
1 /*	$NetBSD: inet6.c,v 1.65 2013/10/19 15:56:06 christos Exp $	*/
2 /*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 /*
34  * Copyright (c) 1983, 1988, 1993
35  *	The Regents of the University of California.  All rights reserved.
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. Neither the name of the University nor the names of its contributors
46  *    may be used to endorse or promote products derived from this software
47  *    without specific prior written permission.
48  *
49  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59  * SUCH DAMAGE.
60  */
61 
62 #include <sys/cdefs.h>
63 #ifndef lint
64 #if 0
65 static char sccsid[] = "@(#)inet.c	8.4 (Berkeley) 4/20/94";
66 #else
67 __RCSID("$NetBSD: inet6.c,v 1.65 2013/10/19 15:56:06 christos Exp $");
68 #endif
69 #endif /* not lint */
70 
71 #include <sys/param.h>
72 #include <sys/socket.h>
73 #include <sys/socketvar.h>
74 #include <sys/ioctl.h>
75 #include <sys/mbuf.h>
76 #include <sys/protosw.h>
77 #include <sys/sysctl.h>
78 
79 #include <net/route.h>
80 #include <net/if.h>
81 #include <netinet/in.h>
82 #include <netinet/ip6.h>
83 #include <netinet/icmp6.h>
84 #include <netinet/in_systm.h>
85 #ifndef TCP6
86 #include <netinet/ip.h>
87 #include <netinet/ip_var.h>
88 #endif
89 #include <netinet6/ip6_var.h>
90 #include <netinet6/in6_pcb.h>
91 #include <netinet6/in6_var.h>
92 #ifdef TCP6
93 #include <netinet6/tcp6.h>
94 #include <netinet6/tcp6_seq.h>
95 #define TCP6STATES
96 #include <netinet6/tcp6_fsm.h>
97 #define TCP6TIMERS
98 #include <netinet6/tcp6_timer.h>
99 #include <netinet6/tcp6_var.h>
100 #include <netinet6/tcp6_debug.h>
101 #else
102 #include <netinet/tcp.h>
103 #include <netinet/tcpip.h>
104 #include <netinet/tcp_seq.h>
105 /*#define TCPSTATES*/
106 #include <netinet/tcp_fsm.h>
107 extern const char * const tcpstates[];
108 /*#define	TCPTIMERS*/
109 #include <netinet/tcp_timer.h>
110 #include <netinet/tcp_var.h>
111 #include <netinet/tcp_debug.h>
112 #endif /*TCP6*/
113 #include <netinet6/udp6.h>
114 #include <netinet6/udp6_var.h>
115 #include <netinet6/pim6_var.h>
116 #include <netinet6/raw_ip6.h>
117 #include <netinet/tcp_vtw.h>
118 
119 #include <arpa/inet.h>
120 #if 0
121 #include "gethostbyname2.h"
122 #endif
123 #include <netdb.h>
124 
125 #include <err.h>
126 #include <errno.h>
127 #include <kvm.h>
128 #include <stdio.h>
129 #include <stdlib.h>
130 #include <string.h>
131 #include <unistd.h>
132 #include "netstat.h"
133 #include "vtw.h"
134 #include "prog_ops.h"
135 
136 #ifdef INET6
137 
138 struct	in6pcb in6pcb;
139 #ifdef TCP6
140 struct	tcp6cb tcp6cb;
141 #else
142 struct	tcpcb tcpcb;
143 #endif
144 struct	socket sockb;
145 
146 char	*inet6name(const struct in6_addr *);
147 void	inet6print(const struct in6_addr *, int, const char *);
148 void	print_vtw_v6(const vtw_t *);
149 
150 /*
151  * Print a summary of connections related to an Internet
152  * protocol.  For TCP, also give state of connection.
153  * Listening processes (aflag) are suppressed unless the
154  * -a (all) flag is specified.
155  */
156 static int width;
157 static int compact;
158 
159 /* VTW-related variables. */
160 static struct timeval now;
161 
162 static void
163 ip6protoprhdr(void)
164 {
165 
166 	printf("Active Internet6 connections");
167 
168 	if (aflag)
169 		printf(" (including servers)");
170 	putchar('\n');
171 
172 	if (Aflag) {
173 		printf("%-8.8s ", "PCB");
174 		width = 18;
175 	}
176 	printf(
177 	    Vflag ? "%-5.5s %-6.6s %-6.6s  %*.*s %*.*s %-13.13s Expires\n"
178 	          : "%-5.5s %-6.6s %-6.6s  %*.*s %*.*s %s\n",
179 	    "Proto", "Recv-Q", "Send-Q",
180 	    -width, width, "Local Address",
181 	    -width, width, "Foreign Address", "(state)");
182 }
183 
184 static void
185 ip6protopr0(intptr_t ppcb, u_long rcv_sb_cc, u_long snd_sb_cc,
186 	const struct in6_addr *laddr, u_int16_t lport,
187 	const struct in6_addr *faddr, u_int16_t fport,
188 	short t_state, const char *name, const struct timeval *expires)
189 {
190 	static const char *shorttcpstates[] = {
191 		"CLOSED",       "LISTEN",       "SYNSEN",       "SYSRCV",
192 		"ESTABL",       "CLWAIT",       "FWAIT1",       "CLOSNG",
193 		"LASTAK",       "FWAIT2",       "TMWAIT",
194 	};
195 	int istcp;
196 
197 	istcp = strcmp(name, "tcp6") == 0;
198 	if (Aflag)
199 		printf("%8" PRIxPTR " ", ppcb);
200 
201 	printf("%-5.5s %6ld %6ld%s", name, rcv_sb_cc, snd_sb_cc,
202 	    compact ? "" : " ");
203 
204 	inet6print(laddr, (int)lport, name);
205 	inet6print(faddr, (int)fport, name);
206 	if (istcp) {
207 #ifdef TCP6
208 		if (t_state < 0 || t_state >= TCP6_NSTATES)
209 			printf(" %d", t_state);
210 		else
211 			printf(" %s", tcp6states[t_state]);
212 #else
213 		if (t_state < 0 || t_state >= TCP_NSTATES)
214 			printf(" %d", t_state);
215 		else
216 			printf(" %s", compact ? shorttcpstates[t_state] :
217 			    tcpstates[t_state]);
218 #endif
219 	}
220 	if (Vflag && expires != NULL) {
221 		if (expires->tv_sec == 0 && expires->tv_usec == -1)
222 			printf(" reclaimed");
223 		else {
224 			struct timeval delta;
225 
226 			timersub(expires, &now, &delta);
227 			printf(" %.3fms",
228 			    delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
229 		}
230 	}
231 	putchar('\n');
232 }
233 
234 static void
235 dbg_printf(const char *fmt, ...)
236 {
237 	return;
238 }
239 
240 void
241 print_vtw_v6(const vtw_t *vtw)
242 {
243 	const vtw_v6_t *v6 = (const vtw_v6_t *)vtw;
244 	struct timeval delta;
245 	char buf[2][128];
246 	static const struct timeval zero = {.tv_sec = 0, .tv_usec = 0};
247 
248 	inet_ntop(AF_INET6, &v6->laddr, buf[0], sizeof(buf[0]));
249 	inet_ntop(AF_INET6, &v6->faddr, buf[1], sizeof(buf[1]));
250 
251 	timersub(&vtw->expire, &now, &delta);
252 
253 	if (vtw->expire.tv_sec == 0 && vtw->expire.tv_usec == -1) {
254 		dbg_printf("%15.15s:%d %15.15s:%d reclaimed\n"
255 		    ,buf[0], ntohs(v6->lport)
256 		    ,buf[1], ntohs(v6->fport));
257 		if (!(Vflag && vflag))
258 			return;
259 	} else if (vtw->expire.tv_sec == 0)
260 		return;
261 	else if (timercmp(&delta, &zero, <) && !(Vflag && vflag)) {
262 		dbg_printf("%15.15s:%d %15.15s:%d expired\n"
263 		    ,buf[0], ntohs(v6->lport)
264 		    ,buf[1], ntohs(v6->fport));
265 		return;
266 	} else {
267 		dbg_printf("%15.15s:%d %15.15s:%d expires in %.3fms\n"
268 		    ,buf[0], ntohs(v6->lport)
269 		    ,buf[1], ntohs(v6->fport)
270 		    ,delta.tv_sec * 1000.0 + delta.tv_usec / 1000.0);
271 	}
272 	ip6protopr0(0, 0, 0,
273 		 &v6->laddr, v6->lport,
274 		 &v6->faddr, v6->fport,
275 		 TCPS_TIME_WAIT, "tcp6", &vtw->expire);
276 }
277 
278 
279 static struct kinfo_pcb *
280 getpcblist_kmem(u_long off, const char *name, size_t *len) {
281 
282 	struct inpcbtable table;
283 	struct in6pcb *head, *prev, *next;
284 	int istcp = strcmp(name, "tcp6") == 0;
285 	struct kinfo_pcb *pcblist;
286 	size_t size = 100, i;
287 	struct sockaddr_in6 sin6;
288 
289 	if (off == 0) {
290 		*len = 0;
291 		return NULL;
292 	}
293 	kread(off, (char *)&table, sizeof (table));
294 	head = prev =
295 	    (struct in6pcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
296 	next = (struct in6pcb *)table.inpt_queue.cqh_first;
297 
298 	if ((pcblist = malloc(size)) == NULL)
299 		err(1, "malloc");
300 
301 	i = 0;
302 	while (next != head) {
303 		kread((u_long)next, (char *)&in6pcb, sizeof in6pcb);
304 		if ((struct in6pcb *)in6pcb.in6p_queue.cqe_prev != prev) {
305 			warnx("bad pcb");
306 			break;
307 		}
308 		prev = next;
309 		next = (struct in6pcb *)in6pcb.in6p_queue.cqe_next;
310 
311 		if (in6pcb.in6p_af != AF_INET6)
312 			continue;
313 
314 		kread((u_long)in6pcb.in6p_socket, (char *)&sockb,
315 		    sizeof (sockb));
316 		if (istcp) {
317 #ifdef TCP6
318 			kread((u_long)in6pcb.in6p_ppcb,
319 			    (char *)&tcp6cb, sizeof (tcp6cb));
320 #else
321 			kread((u_long)in6pcb.in6p_ppcb,
322 			    (char *)&tcpcb, sizeof (tcpcb));
323 #endif
324 		}
325 		pcblist[i].ki_ppcbaddr =
326 		    istcp ? (uintptr_t) in6pcb.in6p_ppcb : (uintptr_t) prev;
327 		pcblist[i].ki_rcvq = (uint64_t)sockb.so_rcv.sb_cc;
328 		pcblist[i].ki_sndq = (uint64_t)sockb.so_snd.sb_cc;
329 		sin6.sin6_addr = in6pcb.in6p_laddr;
330 		sin6.sin6_port = in6pcb.in6p_lport;
331 		memcpy(&pcblist[i].ki_s, &sin6, sizeof(sin6));
332 		sin6.sin6_addr = in6pcb.in6p_faddr;
333 		sin6.sin6_port = in6pcb.in6p_fport;
334 		memcpy(&pcblist[i].ki_d, &sin6, sizeof(sin6));
335 		pcblist[i].ki_tstate = tcpcb.t_state;
336 		if (i++ == size) {
337 			struct kinfo_pcb *n = realloc(pcblist, size += 100);
338 			if (n == NULL)
339 				err(1, "realloc");
340 			pcblist = n;
341 		}
342 	}
343 	*len = i;
344 	return pcblist;
345 }
346 
347 void
348 ip6protopr(u_long off, const char *name)
349 {
350 	struct kinfo_pcb *pcblist;
351 	size_t i, len;
352 	static int first = 1;
353 
354 	compact = 0;
355 	if (Aflag) {
356 		if (!numeric_addr)
357 			width = 18;
358 		else {
359 			width = 21;
360 			compact = 1;
361 		}
362 	} else
363 		width = 22;
364 
365 	if (use_sysctl)
366 		pcblist = getpcblist_sysctl(name, &len);
367 	else
368 		pcblist = getpcblist_kmem(off, name, &len);
369 
370 	for (i = 0; i < len; i++) {
371 		struct sockaddr_in6 src, dst;
372 
373 		memcpy(&src, &pcblist[i].ki_s, sizeof(src));
374 		memcpy(&dst, &pcblist[i].ki_d, sizeof(dst));
375 
376 		if (!aflag && IN6_IS_ADDR_UNSPECIFIED(&dst.sin6_addr))
377 			continue;
378 
379 		if (first) {
380 			ip6protoprhdr();
381 			first = 0;
382 		}
383 
384 		ip6protopr0((intptr_t) pcblist[i].ki_ppcbaddr,
385 		    pcblist[i].ki_rcvq, pcblist[i].ki_sndq,
386 		    &src.sin6_addr, src.sin6_port,
387 		    &dst.sin6_addr, dst.sin6_port,
388 		    pcblist[i].ki_tstate, name, NULL);
389 	}
390 
391 	free(pcblist);
392 
393 	if (strcmp(name, "tcp6") == 0) {
394 		struct timeval t;
395 		timebase(&t);
396 		gettimeofday(&now, NULL);
397 		timersub(&now, &t, &now);
398 		show_vtw_v6(print_vtw_v6);
399 	}
400 }
401 
402 #ifdef TCP6
403 /*
404  * Dump TCP6 statistics structure.
405  */
406 void
407 tcp6_stats(u_long off, const char *name)
408 {
409 	struct tcp6stat tcp6stat;
410 
411 	if (use_sysctl) {
412 		size_t size = sizeof(tcp6stat);
413 
414 		if (sysctlbyname("net.inet6.tcp6.stats", &tcp6stat, &size,
415 		    NULL, 0) == -1)
416 			return;
417 	} else {
418 		warnx("%s stats not available via KVM.", name);
419 		return;
420 	}
421 
422 	printf ("%s:\n", name);
423 
424 #define	p(f, m) if (tcp6stat.f || sflag <= 1) \
425     printf(m, tcp6stat.f, plural(tcp6stat.f))
426 #define	p2(f1, f2, m) if (tcp6stat.f1 || tcp6stat.f2 || sflag <= 1) \
427     printf(m, tcp6stat.f1, plural(tcp6stat.f1), tcp6stat.f2, plural(tcp6stat.f2))
428 #define	p3(f, m) if (tcp6stat.f || sflag <= 1) \
429     printf(m, tcp6stat.f, plurales(tcp6stat.f))
430 
431 	p(tcp6s_sndtotal, "\t%ld packet%s sent\n");
432 	p2(tcp6s_sndpack,tcp6s_sndbyte,
433 		"\t\t%ld data packet%s (%ld byte%s)\n");
434 	p2(tcp6s_sndrexmitpack, tcp6s_sndrexmitbyte,
435 		"\t\t%ld data packet%s (%ld byte%s) retransmitted\n");
436 	p2(tcp6s_sndacks, tcp6s_delack,
437 		"\t\t%ld ack-only packet%s (%ld packet%s delayed)\n");
438 	p(tcp6s_sndurg, "\t\t%ld URG only packet%s\n");
439 	p(tcp6s_sndprobe, "\t\t%ld window probe packet%s\n");
440 	p(tcp6s_sndwinup, "\t\t%ld window update packet%s\n");
441 	p(tcp6s_sndctrl, "\t\t%ld control packet%s\n");
442 	p(tcp6s_rcvtotal, "\t%ld packet%s received\n");
443 	p2(tcp6s_rcvackpack, tcp6s_rcvackbyte, "\t\t%ld ack%s (for %ld byte%s)\n");
444 	p(tcp6s_rcvdupack, "\t\t%ld duplicate ack%s\n");
445 	p(tcp6s_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n");
446 	p2(tcp6s_rcvpack, tcp6s_rcvbyte,
447 		"\t\t%ld packet%s (%ld byte%s) received in-sequence\n");
448 	p2(tcp6s_rcvduppack, tcp6s_rcvdupbyte,
449 		"\t\t%ld completely duplicate packet%s (%ld byte%s)\n");
450 	p(tcp6s_pawsdrop, "\t\t%ld old duplicate packet%s\n");
451 	p2(tcp6s_rcvpartduppack, tcp6s_rcvpartdupbyte,
452 		"\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n");
453 	p2(tcp6s_rcvoopack, tcp6s_rcvoobyte,
454 		"\t\t%ld out-of-order packet%s (%ld byte%s)\n");
455 	p2(tcp6s_rcvpackafterwin, tcp6s_rcvbyteafterwin,
456 		"\t\t%ld packet%s (%ld byte%s) of data after window\n");
457 	p(tcp6s_rcvwinprobe, "\t\t%ld window probe%s\n");
458 	p(tcp6s_rcvwinupd, "\t\t%ld window update packet%s\n");
459 	p(tcp6s_rcvafterclose, "\t\t%ld packet%s received after close\n");
460 	p(tcp6s_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n");
461 	p(tcp6s_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n");
462 	p(tcp6s_rcvshort, "\t\t%ld discarded because packet%s too short\n");
463 	p(tcp6s_connattempt, "\t%ld connection request%s\n");
464 	p(tcp6s_accepts, "\t%ld connection accept%s\n");
465 	p(tcp6s_badsyn, "\t%ld bad connection attempt%s\n");
466 	p(tcp6s_connects, "\t%ld connection%s established (including accepts)\n");
467 	p2(tcp6s_closed, tcp6s_drops,
468 		"\t%ld connection%s closed (including %ld drop%s)\n");
469 	p(tcp6s_conndrops, "\t%ld embryonic connection%s dropped\n");
470 	p2(tcp6s_rttupdated, tcp6s_segstimed,
471 		"\t%ld segment%s updated rtt (of %ld attempt%s)\n");
472 	p(tcp6s_rexmttimeo, "\t%ld retransmit timeout%s\n");
473 	p(tcp6s_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n");
474 	p(tcp6s_persisttimeo, "\t%ld persist timeout%s\n");
475 	p(tcp6s_persistdrop, "\t%ld connection%s timed out in persist\n");
476 	p(tcp6s_keeptimeo, "\t%ld keepalive timeout%s\n");
477 	p(tcp6s_keepprobe, "\t\t%ld keepalive probe%s sent\n");
478 	p(tcp6s_keepdrops, "\t\t%ld connection%s dropped by keepalive\n");
479 	p(tcp6s_predack, "\t%ld correct ACK header prediction%s\n");
480 	p(tcp6s_preddat, "\t%ld correct data packet header prediction%s\n");
481 	p3(tcp6s_pcbcachemiss, "\t%ld PCB cache miss%s\n");
482 #undef p
483 #undef p2
484 #undef p3
485 }
486 #endif
487 
488 /*
489  * Dump UDP6 statistics structure.
490  */
491 void
492 udp6_stats(u_long off, const char *name)
493 {
494 	uint64_t udp6stat[UDP6_NSTATS];
495 	u_quad_t delivered;
496 
497 	if (use_sysctl) {
498 		size_t size = sizeof(udp6stat);
499 
500 		if (sysctlbyname("net.inet6.udp6.stats", udp6stat, &size,
501 		    NULL, 0) == -1)
502 			return;
503 	} else {
504 		warnx("%s stats not available via KVM.", name);
505 		return;
506 	}
507 	printf("%s:\n", name);
508 #define	p(f, m) if (udp6stat[f] || sflag <= 1) \
509     printf(m, (unsigned long long)udp6stat[f], plural(udp6stat[f]))
510 #define	p1(f, m) if (udp6stat[f] || sflag <= 1) \
511     printf(m, (unsigned long long)udp6stat[f])
512 	p(UDP6_STAT_IPACKETS, "\t%llu datagram%s received\n");
513 	p1(UDP6_STAT_HDROPS, "\t%llu with incomplete header\n");
514 	p1(UDP6_STAT_BADLEN, "\t%llu with bad data length field\n");
515 	p1(UDP6_STAT_BADSUM, "\t%llu with bad checksum\n");
516 	p1(UDP6_STAT_NOSUM, "\t%llu with no checksum\n");
517 	p1(UDP6_STAT_NOPORT, "\t%llu dropped due to no socket\n");
518 	p(UDP6_STAT_NOPORTMCAST,
519 	    "\t%llu multicast datagram%s dropped due to no socket\n");
520 	p1(UDP6_STAT_FULLSOCK, "\t%llu dropped due to full socket buffers\n");
521 	delivered = udp6stat[UDP6_STAT_IPACKETS] -
522 		    udp6stat[UDP6_STAT_HDROPS] -
523 		    udp6stat[UDP6_STAT_BADLEN] -
524 		    udp6stat[UDP6_STAT_BADSUM] -
525 		    udp6stat[UDP6_STAT_NOPORT] -
526 		    udp6stat[UDP6_STAT_NOPORTMCAST] -
527 		    udp6stat[UDP6_STAT_FULLSOCK];
528 	if (delivered || sflag <= 1)
529 		printf("\t%llu delivered\n", (unsigned long long)delivered);
530 	p(UDP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
531 #undef p
532 #undef p1
533 }
534 
535 static	const char *ip6nh[] = {
536 /*0*/	"hop by hop",
537 	"ICMP",
538 	"IGMP",
539 	NULL,
540 	"IP",
541 /*5*/	NULL,
542 	"TCP",
543 	NULL,
544 	NULL,
545 	NULL,
546 /*10*/	NULL, NULL, NULL, NULL, NULL,
547 /*15*/	NULL,
548 	NULL,
549 	"UDP",
550 	NULL,
551 	NULL,
552 /*20*/	NULL,
553 	NULL,
554 	"IDP",
555 	NULL,
556 	NULL,
557 /*25*/	NULL,
558 	NULL,
559 	NULL,
560 	NULL,
561 	NULL,
562 /*30*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
563 /*40*/	NULL,
564 	"IP6",
565 	NULL,
566 	"routing",
567 	"fragment",
568 /*45*/	NULL, NULL, NULL, NULL, NULL,
569 /*50*/	"ESP",
570 	"AH",
571 	NULL,
572 	NULL,
573 	NULL,
574 /*55*/	NULL,
575 	NULL,
576 	NULL,
577 	"ICMP6",
578 	"no next header",
579 /*60*/	"destination option",
580 	NULL,
581 	NULL,
582 	NULL,
583 	NULL,
584 /*65*/	NULL, NULL, NULL, NULL, NULL,
585 /*70*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
586 /*80*/	NULL,
587 	NULL,
588 	NULL,
589 	NULL,
590 	NULL,
591 	NULL,
592 	NULL,
593 	NULL,
594 	NULL,
595 	"OSPF",
596 /*90*/	NULL, NULL, NULL, NULL, NULL,
597 /*95*/	NULL,
598 	NULL,
599 	"Ethernet",
600 	NULL,
601 	NULL,
602 /*100*/	NULL,
603 	NULL,
604 	NULL,
605 	"PIM",
606 	NULL,
607 /*105*/	NULL, NULL, NULL, NULL, NULL,
608 /*110*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
609 /*120*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
610 /*130*/	NULL,
611 	NULL,
612 	"SCTP",
613 	NULL,
614 	NULL,
615 /*135*/	NULL, NULL, NULL, NULL, NULL,
616 /*140*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
617 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
618 /*160*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
619 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
620 /*180*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
621 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
622 /*200*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
623 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
624 /*220*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
625 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
626 /*240*/	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
627 	NULL, NULL, NULL, NULL, NULL, NULL,
628 };
629 
630 /*
631  * Dump IP6 statistics structure.
632  */
633 void
634 ip6_stats(u_long off, const char *name)
635 {
636 	uint64_t ip6stat[IP6_NSTATS];
637 	int first, i;
638 	struct protoent *ep;
639 	const char *n;
640 
641 	if (use_sysctl) {
642 		size_t size = sizeof(ip6stat);
643 
644 		if (sysctlbyname("net.inet6.ip6.stats", ip6stat, &size,
645 		    NULL, 0) == -1)
646 			return;
647 	} else {
648 		warnx("%s stats not available via KVM.", name);
649 		return;
650 	}
651 	printf("%s:\n", name);
652 
653 #define	p(f, m) if (ip6stat[f] || sflag <= 1) \
654     printf(m, (unsigned long long)ip6stat[f], plural(ip6stat[f]))
655 #define	p1(f, m) if (ip6stat[f] || sflag <= 1) \
656     printf(m, (unsigned long long)ip6stat[f])
657 
658 	p(IP6_STAT_TOTAL, "\t%llu total packet%s received\n");
659 	p1(IP6_STAT_TOOSMALL, "\t%llu with size smaller than minimum\n");
660 	p1(IP6_STAT_TOOSHORT, "\t%llu with data size < data length\n");
661 	p1(IP6_STAT_BADOPTIONS, "\t%llu with bad options\n");
662 	p1(IP6_STAT_BADVERS, "\t%llu with incorrect version number\n");
663 	p(IP6_STAT_FRAGMENTS, "\t%llu fragment%s received\n");
664 	p(IP6_STAT_FRAGDROPPED,
665 	    "\t%llu fragment%s dropped (dup or out of space)\n");
666 	p(IP6_STAT_FRAGTIMEOUT, "\t%llu fragment%s dropped after timeout\n");
667 	p(IP6_STAT_FRAGOVERFLOW, "\t%llu fragment%s that exceeded limit\n");
668 	p(IP6_STAT_REASSEMBLED, "\t%llu packet%s reassembled ok\n");
669 	p(IP6_STAT_DELIVERED, "\t%llu packet%s for this host\n");
670 	p(IP6_STAT_FORWARD, "\t%llu packet%s forwarded\n");
671 	p(IP6_STAT_FASTFORWARD, "\t%llu packet%s fast forwarded\n");
672 	p1(IP6_STAT_FASTFORWARDFLOWS, "\t%llu fast forward flows\n");
673 	p(IP6_STAT_CANTFORWARD, "\t%llu packet%s not forwardable\n");
674 	p(IP6_STAT_REDIRECTSENT, "\t%llu redirect%s sent\n");
675 	p(IP6_STAT_LOCALOUT, "\t%llu packet%s sent from this host\n");
676 	p(IP6_STAT_RAWOUT, "\t%llu packet%s sent with fabricated ip header\n");
677 	p(IP6_STAT_ODROPPED,
678 	    "\t%llu output packet%s dropped due to no bufs, etc.\n");
679 	p(IP6_STAT_NOROUTE, "\t%llu output packet%s discarded due to no route\n");
680 	p(IP6_STAT_FRAGMENTED, "\t%llu output datagram%s fragmented\n");
681 	p(IP6_STAT_OFRAGMENTS, "\t%llu fragment%s created\n");
682 	p(IP6_STAT_CANTFRAG, "\t%llu datagram%s that can't be fragmented\n");
683 	p(IP6_STAT_BADSCOPE, "\t%llu packet%s that violated scope rules\n");
684 	p(IP6_STAT_NOTMEMBER, "\t%llu multicast packet%s which we don't join\n");
685 	for (first = 1, i = 0; i < 256; i++)
686 		if (ip6stat[IP6_STAT_NXTHIST + i] != 0) {
687 			if (first) {
688 				printf("\tInput packet histogram:\n");
689 				first = 0;
690 			}
691 			n = NULL;
692 			if (ip6nh[i])
693 				n = ip6nh[i];
694 			else if ((ep = getprotobynumber(i)) != NULL)
695 				n = ep->p_name;
696 			if (n)
697 				printf("\t\t%s: %llu\n", n,
698 				    (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
699 			else
700 				printf("\t\t#%d: %llu\n", i,
701 				    (unsigned long long)ip6stat[IP6_STAT_NXTHIST + i]);
702 		}
703 	printf("\tMbuf statistics:\n");
704 	p(IP6_STAT_M1, "\t\t%llu one mbuf%s\n");
705 	for (first = 1, i = 0; i < 32; i++) {
706 		char ifbuf[IFNAMSIZ];
707 		if (ip6stat[IP6_STAT_M2M + i] != 0) {
708 			if (first) {
709 				printf("\t\ttwo or more mbuf:\n");
710 				first = 0;
711 			}
712 			printf("\t\t\t%s = %llu\n",
713 			       if_indextoname(i, ifbuf),
714 			       (unsigned long long)ip6stat[IP6_STAT_M2M + i]);
715 		}
716 	}
717 	p(IP6_STAT_MEXT1, "\t\t%llu one ext mbuf%s\n");
718 	p(IP6_STAT_MEXT2M, "\t\t%llu two or more ext mbuf%s\n");
719 	p(IP6_STAT_EXTHDRTOOLONG,
720 	    "\t%llu packet%s whose headers are not continuous\n");
721 	p(IP6_STAT_NOGIF, "\t%llu tunneling packet%s that can't find gif\n");
722 	p(IP6_STAT_TOOMANYHDR,
723 	    "\t%llu packet%s discarded due to too many headers\n");
724 
725 	/* for debugging source address selection */
726 #define PRINT_SCOPESTAT(s,i) do {\
727 		switch(i) { /* XXX hardcoding in each case */\
728 		case 1:\
729 			p(s, "\t\t%llu node-local%s\n");\
730 			break;\
731 		case 2:\
732 			p(s, "\t\t%llu link-local%s\n");\
733 			break;\
734 		case 5:\
735 			p(s, "\t\t%llu site-local%s\n");\
736 			break;\
737 		case 14:\
738 			p(s, "\t\t%llu global%s\n");\
739 			break;\
740 		default:\
741 			printf("\t\t%llu addresses scope=%x\n",\
742 			       (unsigned long long)ip6stat[s], i);\
743 		}\
744 	} while(/*CONSTCOND*/0);
745 
746 	p(IP6_STAT_SOURCES_NONE,
747 	  "\t%llu failure%s of source address selection\n");
748 	for (first = 1, i = 0; i < 16; i++) {
749 		if (ip6stat[IP6_STAT_SOURCES_SAMEIF + i]) {
750 			if (first) {
751 				printf("\tsource addresses on an outgoing I/F\n");
752 				first = 0;
753 			}
754 			PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMEIF + i, i);
755 		}
756 	}
757 	for (first = 1, i = 0; i < 16; i++) {
758 		if (ip6stat[IP6_STAT_SOURCES_OTHERIF + i]) {
759 			if (first) {
760 				printf("\tsource addresses on a non-outgoing I/F\n");
761 				first = 0;
762 			}
763 			PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERIF + i, i);
764 		}
765 	}
766 	for (first = 1, i = 0; i < 16; i++) {
767 		if (ip6stat[IP6_STAT_SOURCES_SAMESCOPE + i]) {
768 			if (first) {
769 				printf("\tsource addresses of same scope\n");
770 				first = 0;
771 			}
772 			PRINT_SCOPESTAT(IP6_STAT_SOURCES_SAMESCOPE + i, i);
773 		}
774 	}
775 	for (first = 1, i = 0; i < 16; i++) {
776 		if (ip6stat[IP6_STAT_SOURCES_OTHERSCOPE + i]) {
777 			if (first) {
778 				printf("\tsource addresses of a different scope\n");
779 				first = 0;
780 			}
781 			PRINT_SCOPESTAT(IP6_STAT_SOURCES_OTHERSCOPE + i, i);
782 		}
783 	}
784 	for (first = 1, i = 0; i < 16; i++) {
785 		if (ip6stat[IP6_STAT_SOURCES_DEPRECATED + i]) {
786 			if (first) {
787 				printf("\tdeprecated source addresses\n");
788 				first = 0;
789 			}
790 			PRINT_SCOPESTAT(IP6_STAT_SOURCES_DEPRECATED + i, i);
791 		}
792 	}
793 
794 	p1(IP6_STAT_FORWARD_CACHEHIT, "\t%llu forward cache hit\n");
795 	p1(IP6_STAT_FORWARD_CACHEMISS, "\t%llu forward cache miss\n");
796 #undef p
797 #undef p1
798 }
799 
800 /*
801  * Dump IPv6 per-interface statistics based on RFC 2465.
802  */
803 void
804 ip6_ifstats(const char *ifname)
805 {
806 	struct in6_ifreq ifr;
807 	int s;
808 #define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
809     printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \
810 	plural(ifr.ifr_ifru.ifru_stat.f))
811 #define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
812     printf(m, (unsigned long long)ip6stat.f)
813 
814 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
815 		perror("Warning: socket(AF_INET6)");
816 		return;
817 	}
818 
819 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
820 	printf("ip6 on %s:\n", ifname);
821 
822 	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
823 		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
824 		goto end;
825 	}
826 
827 	p(ifs6_in_receive, "\t%llu total input datagram%s\n");
828 	p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
829 	p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
830 	p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
831 	p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
832 	p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
833 	p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
834 	p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
835 	p(ifs6_in_deliver,
836 	  "\t%llu datagram%s delivered to an upper layer protocol\n");
837 	p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
838 	p(ifs6_out_request,
839 	  "\t%llu datagram%s sent from an upper layer protocol\n");
840 	p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
841 	p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
842 	p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
843 	p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
844 	p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
845 	p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
846 	p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
847 	p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
848 	p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
849 
850   end:
851 	close(s);
852 
853 #undef p
854 #undef p_5
855 }
856 
857 static	const char *icmp6names[] = {
858 	"#0",
859 	"unreach",
860 	"packet too big",
861 	"time exceed",
862 	"parameter problem",
863 	"#5",
864 	"#6",
865 	"#7",
866 	"#8",
867 	"#9",
868 	"#10",
869 	"#11",
870 	"#12",
871 	"#13",
872 	"#14",
873 	"#15",
874 	"#16",
875 	"#17",
876 	"#18",
877 	"#19",
878 	"#20",
879 	"#21",
880 	"#22",
881 	"#23",
882 	"#24",
883 	"#25",
884 	"#26",
885 	"#27",
886 	"#28",
887 	"#29",
888 	"#30",
889 	"#31",
890 	"#32",
891 	"#33",
892 	"#34",
893 	"#35",
894 	"#36",
895 	"#37",
896 	"#38",
897 	"#39",
898 	"#40",
899 	"#41",
900 	"#42",
901 	"#43",
902 	"#44",
903 	"#45",
904 	"#46",
905 	"#47",
906 	"#48",
907 	"#49",
908 	"#50",
909 	"#51",
910 	"#52",
911 	"#53",
912 	"#54",
913 	"#55",
914 	"#56",
915 	"#57",
916 	"#58",
917 	"#59",
918 	"#60",
919 	"#61",
920 	"#62",
921 	"#63",
922 	"#64",
923 	"#65",
924 	"#66",
925 	"#67",
926 	"#68",
927 	"#69",
928 	"#70",
929 	"#71",
930 	"#72",
931 	"#73",
932 	"#74",
933 	"#75",
934 	"#76",
935 	"#77",
936 	"#78",
937 	"#79",
938 	"#80",
939 	"#81",
940 	"#82",
941 	"#83",
942 	"#84",
943 	"#85",
944 	"#86",
945 	"#87",
946 	"#88",
947 	"#89",
948 	"#80",
949 	"#91",
950 	"#92",
951 	"#93",
952 	"#94",
953 	"#95",
954 	"#96",
955 	"#97",
956 	"#98",
957 	"#99",
958 	"#100",
959 	"#101",
960 	"#102",
961 	"#103",
962 	"#104",
963 	"#105",
964 	"#106",
965 	"#107",
966 	"#108",
967 	"#109",
968 	"#110",
969 	"#111",
970 	"#112",
971 	"#113",
972 	"#114",
973 	"#115",
974 	"#116",
975 	"#117",
976 	"#118",
977 	"#119",
978 	"#120",
979 	"#121",
980 	"#122",
981 	"#123",
982 	"#124",
983 	"#125",
984 	"#126",
985 	"#127",
986 	"echo",
987 	"echo reply",
988 	"multicast listener query",
989 	"multicast listener report",
990 	"multicast listener done",
991 	"router solicitation",
992 	"router advertisement",
993 	"neighbor solicitation",
994 	"neighbor advertisement",
995 	"redirect",
996 	"router renumbering",
997 	"node information request",
998 	"node information reply",
999 	"#141",
1000 	"#142",
1001 	"#143",
1002 	"#144",
1003 	"#145",
1004 	"#146",
1005 	"#147",
1006 	"#148",
1007 	"#149",
1008 	"#150",
1009 	"#151",
1010 	"#152",
1011 	"#153",
1012 	"#154",
1013 	"#155",
1014 	"#156",
1015 	"#157",
1016 	"#158",
1017 	"#159",
1018 	"#160",
1019 	"#161",
1020 	"#162",
1021 	"#163",
1022 	"#164",
1023 	"#165",
1024 	"#166",
1025 	"#167",
1026 	"#168",
1027 	"#169",
1028 	"#170",
1029 	"#171",
1030 	"#172",
1031 	"#173",
1032 	"#174",
1033 	"#175",
1034 	"#176",
1035 	"#177",
1036 	"#178",
1037 	"#179",
1038 	"#180",
1039 	"#181",
1040 	"#182",
1041 	"#183",
1042 	"#184",
1043 	"#185",
1044 	"#186",
1045 	"#187",
1046 	"#188",
1047 	"#189",
1048 	"#180",
1049 	"#191",
1050 	"#192",
1051 	"#193",
1052 	"#194",
1053 	"#195",
1054 	"#196",
1055 	"#197",
1056 	"#198",
1057 	"#199",
1058 	"#200",
1059 	"#201",
1060 	"#202",
1061 	"#203",
1062 	"#204",
1063 	"#205",
1064 	"#206",
1065 	"#207",
1066 	"#208",
1067 	"#209",
1068 	"#210",
1069 	"#211",
1070 	"#212",
1071 	"#213",
1072 	"#214",
1073 	"#215",
1074 	"#216",
1075 	"#217",
1076 	"#218",
1077 	"#219",
1078 	"#220",
1079 	"#221",
1080 	"#222",
1081 	"#223",
1082 	"#224",
1083 	"#225",
1084 	"#226",
1085 	"#227",
1086 	"#228",
1087 	"#229",
1088 	"#230",
1089 	"#231",
1090 	"#232",
1091 	"#233",
1092 	"#234",
1093 	"#235",
1094 	"#236",
1095 	"#237",
1096 	"#238",
1097 	"#239",
1098 	"#240",
1099 	"#241",
1100 	"#242",
1101 	"#243",
1102 	"#244",
1103 	"#245",
1104 	"#246",
1105 	"#247",
1106 	"#248",
1107 	"#249",
1108 	"#250",
1109 	"#251",
1110 	"#252",
1111 	"#253",
1112 	"#254",
1113 	"#255",
1114 };
1115 
1116 /*
1117  * Dump ICMPv6 statistics.
1118  */
1119 void
1120 icmp6_stats(u_long off, const char *name)
1121 {
1122 	uint64_t icmp6stat[ICMP6_NSTATS];
1123 	int i, first;
1124 
1125 	if (use_sysctl) {
1126 		size_t size = sizeof(icmp6stat);
1127 
1128 		if (sysctlbyname("net.inet6.icmp6.stats", icmp6stat, &size,
1129 		    NULL, 0) == -1)
1130 			return;
1131 	} else {
1132 		warnx("%s stats not available via KVM.", name);
1133 		return;
1134 	}
1135 
1136 	printf("%s:\n", name);
1137 
1138 #define	p(f, m) if (icmp6stat[f] || sflag <= 1) \
1139     printf(m, (unsigned long long)icmp6stat[f], plural(icmp6stat[f]))
1140 #define p_oerr(f, m) if (icmp6stat[ICMP6_STAT_OUTERRHIST + f] || sflag <= 1) \
1141     printf(m, (unsigned long long)icmp6stat[ICMP6_STAT_OUTERRHIST + f])
1142 
1143 	p(ICMP6_STAT_ERROR, "\t%llu call%s to icmp6_error\n");
1144 	p(ICMP6_STAT_CANTERROR,
1145 	    "\t%llu error%s not generated because old message was icmp6 or so\n");
1146 	p(ICMP6_STAT_TOOFREQ,
1147 	    "\t%llu error%s not generated because of rate limitation\n");
1148 	for (first = 1, i = 0; i < 256; i++)
1149 		if (icmp6stat[ICMP6_STAT_OUTHIST + i] != 0) {
1150 			if (first) {
1151 				printf("\tOutput packet histogram:\n");
1152 				first = 0;
1153 			}
1154 			printf("\t\t%s: %llu\n", icmp6names[i],
1155 			 (unsigned long long)icmp6stat[ICMP6_STAT_OUTHIST + i]);
1156 		}
1157 	p(ICMP6_STAT_BADCODE, "\t%llu message%s with bad code fields\n");
1158 	p(ICMP6_STAT_TOOSHORT, "\t%llu message%s < minimum length\n");
1159 	p(ICMP6_STAT_CHECKSUM, "\t%llu bad checksum%s\n");
1160 	p(ICMP6_STAT_BADLEN, "\t%llu message%s with bad length\n");
1161 	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
1162 		if (icmp6stat[ICMP6_STAT_INHIST + i] != 0) {
1163 			if (first) {
1164 				printf("\tInput packet histogram:\n");
1165 				first = 0;
1166 			}
1167 			printf("\t\t%s: %llu\n", icmp6names[i],
1168 			  (unsigned long long)icmp6stat[ICMP6_STAT_INHIST + i]);
1169 		}
1170 	printf("\tHistogram of error messages to be generated:\n");
1171 	p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOROUTE, "\t\t%llu no route\n");
1172 	p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADMIN, "\t\t%llu administratively prohibited\n");
1173 	p_oerr(ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE, "\t\t%llu beyond scope\n");
1174 	p_oerr(ICMP6_ERRSTAT_DST_UNREACH_ADDR, "\t\t%llu address unreachable\n");
1175 	p_oerr(ICMP6_ERRSTAT_DST_UNREACH_NOPORT, "\t\t%llu port unreachable\n");
1176 	p_oerr(ICMP6_ERRSTAT_PACKET_TOO_BIG, "\t\t%llu packet too big\n");
1177 	p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT, "\t\t%llu time exceed transit\n");
1178 	p_oerr(ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY, "\t\t%llu time exceed reassembly\n");
1179 	p_oerr(ICMP6_ERRSTAT_PARAMPROB_HEADER, "\t\t%llu erroneous header field\n");
1180 	p_oerr(ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER, "\t\t%llu unrecognized next header\n");
1181 	p_oerr(ICMP6_ERRSTAT_PARAMPROB_OPTION, "\t\t%llu unrecognized option\n");
1182 	p_oerr(ICMP6_ERRSTAT_REDIRECT, "\t\t%llu redirect\n");
1183 	p_oerr(ICMP6_ERRSTAT_UNKNOWN, "\t\t%llu unknown\n");
1184 
1185 	p(ICMP6_STAT_REFLECT, "\t%llu message response%s generated\n");
1186 	p(ICMP6_STAT_ND_TOOMANYOPT, "\t%llu message%s with too many ND options\n");
1187 	p(ICMP6_STAT_ND_BADOPT, "\t%llu message%s with bad ND options\n");
1188 	p(ICMP6_STAT_BADNS, "\t%llu bad neighbor solicitation message%s\n");
1189 	p(ICMP6_STAT_BADNA, "\t%llu bad neighbor advertisement message%s\n");
1190 	p(ICMP6_STAT_BADRS, "\t%llu bad router solicitation message%s\n");
1191 	p(ICMP6_STAT_BADRA, "\t%llu bad router advertisement message%s\n");
1192 	p(ICMP6_STAT_DROPPED_RAROUTE, "\t%llu router advertisement route%s dropped\n");
1193 	p(ICMP6_STAT_BADREDIRECT, "\t%llu bad redirect message%s\n");
1194 	p(ICMP6_STAT_PMTUCHG, "\t%llu path MTU change%s\n");
1195 #undef p
1196 #undef p_oerr
1197 }
1198 
1199 /*
1200  * Dump ICMPv6 per-interface statistics based on RFC 2466.
1201  */
1202 void
1203 icmp6_ifstats(const char *ifname)
1204 {
1205 	struct in6_ifreq ifr;
1206 	int s;
1207 #define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1208     printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \
1209 	plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1210 
1211 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1212 		perror("Warning: socket(AF_INET6)");
1213 		return;
1214 	}
1215 
1216 	strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1217 	printf("icmp6 on %s:\n", ifname);
1218 
1219 	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1220 		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1221 		goto end;
1222 	}
1223 
1224 	p(ifs6_in_msg, "\t%llu total input message%s\n");
1225 	p(ifs6_in_error, "\t%llu total input error message%s\n");
1226 	p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
1227 	p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
1228 	p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
1229 	p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
1230 	p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
1231 	p(ifs6_in_echo, "\t%llu input echo request%s\n");
1232 	p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
1233 	p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
1234 	p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
1235 	p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
1236 	p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
1237 	p(ifs6_in_redirect, "\t%llu input redirect%s\n");
1238 	p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
1239 	p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
1240 	p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
1241 
1242 	p(ifs6_out_msg, "\t%llu total output message%s\n");
1243 	p(ifs6_out_error, "\t%llu total output error message%s\n");
1244 	p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
1245 	p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
1246 	p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
1247 	p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
1248 	p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
1249 	p(ifs6_out_echo, "\t%llu output echo request%s\n");
1250 	p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
1251 	p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
1252 	p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
1253 	p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
1254 	p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
1255 	p(ifs6_out_redirect, "\t%llu output redirect%s\n");
1256 	p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
1257 	p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
1258 	p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
1259 
1260   end:
1261 	close(s);
1262 #undef p
1263 }
1264 
1265 /*
1266  * Dump PIM statistics structure.
1267  */
1268 void
1269 pim6_stats(u_long off, const char *name)
1270 {
1271 	uint64_t pim6stat[PIM6_NSTATS];
1272 
1273 	if (use_sysctl) {
1274 		size_t size = sizeof(pim6stat);
1275 
1276 		if (sysctlbyname("net.inet6.pim6.stats", pim6stat, &size,
1277 		    NULL, 0) == -1)
1278 			return;
1279         } else {
1280 		warnx("%s stats not available via KVM.", name);
1281 		return;
1282 	}
1283 	printf("%s:\n", name);
1284 
1285 #define	p(f, m) if (pim6stat[f] || sflag <= 1) \
1286     printf(m, (unsigned long long)pim6stat[f], plural(pim6stat[f]))
1287 	p(PIM6_STAT_RCV_TOTAL, "\t%llu message%s received\n");
1288 	p(PIM6_STAT_RCV_TOOSHORT, "\t%llu message%s received with too few bytes\n");
1289 	p(PIM6_STAT_RCV_BADSUM, "\t%llu message%s received with bad checksum\n");
1290 	p(PIM6_STAT_RCV_BADVERSION, "\t%llu message%s received with bad version\n");
1291 	p(PIM6_STAT_RCV_REGISTERS, "\t%llu register%s received\n");
1292 	p(PIM6_STAT_RCV_BADREGISTERS, "\t%llu bad register%s received\n");
1293 	p(PIM6_STAT_SND_REGISTERS, "\t%llu register%s sent\n");
1294 #undef p
1295 }
1296 
1297 /*
1298  * Dump raw ip6 statistics structure.
1299  */
1300 void
1301 rip6_stats(u_long off, const char *name)
1302 {
1303 	uint64_t rip6stat[RIP6_NSTATS];
1304 	u_quad_t delivered;
1305 
1306 	if (use_sysctl) {
1307 		size_t size = sizeof(rip6stat);
1308 
1309 		if (sysctlbyname("net.inet6.raw6.stats", rip6stat, &size,
1310 		    NULL, 0) == -1)
1311 			return;
1312 	} else {
1313 		warnx("%s stats not available via KVM.", name);
1314 		return;
1315 	}
1316 	printf("%s:\n", name);
1317 
1318 #define	p(f, m) if (rip6stat[f] || sflag <= 1) \
1319     printf(m, (unsigned long long)rip6stat[f], plural(rip6stat[f]))
1320 	p(RIP6_STAT_IPACKETS, "\t%llu message%s received\n");
1321 	p(RIP6_STAT_ISUM, "\t%llu checksum calculation%s on inbound\n");
1322 	p(RIP6_STAT_BADSUM, "\t%llu message%s with bad checksum\n");
1323 	p(RIP6_STAT_NOSOCK, "\t%llu message%s dropped due to no socket\n");
1324 	p(RIP6_STAT_NOSOCKMCAST,
1325 	    "\t%llu multicast message%s dropped due to no socket\n");
1326 	p(RIP6_STAT_FULLSOCK,
1327 	    "\t%llu message%s dropped due to full socket buffers\n");
1328 	delivered = rip6stat[RIP6_STAT_IPACKETS] -
1329 		    rip6stat[RIP6_STAT_BADSUM] -
1330 		    rip6stat[RIP6_STAT_NOSOCK] -
1331 		    rip6stat[RIP6_STAT_NOSOCKMCAST] -
1332 		    rip6stat[RIP6_STAT_FULLSOCK];
1333 	if (delivered || sflag <= 1)
1334 		printf("\t%llu delivered\n", (unsigned long long)delivered);
1335 	p(RIP6_STAT_OPACKETS, "\t%llu datagram%s output\n");
1336 #undef p
1337 }
1338 
1339 /*
1340  * Pretty print an Internet address (net address + port).
1341  * Take numeric_addr and numeric_port into consideration.
1342  */
1343 void
1344 inet6print(const struct in6_addr *in6, int port, const char *proto)
1345 {
1346 #define GETSERVBYPORT6(port, proto, ret)\
1347 do {\
1348 	if (strcmp((proto), "tcp6") == 0)\
1349 		(ret) = getservbyport((int)(port), "tcp");\
1350 	else if (strcmp((proto), "udp6") == 0)\
1351 		(ret) = getservbyport((int)(port), "udp");\
1352 	else\
1353 		(ret) = getservbyport((int)(port), (proto));\
1354 } while (0)
1355 	struct servent *sp = 0;
1356 	char line[80], *cp;
1357 	int lwidth;
1358 
1359 	lwidth = Aflag ? 12 : 16;
1360 	if (vflag && lwidth < (int)strlen(inet6name(in6)))
1361 		lwidth = strlen(inet6name(in6));
1362 	snprintf(line, sizeof(line), "%.*s.", lwidth, inet6name(in6));
1363 	cp = strchr(line, '\0');
1364 	if (!numeric_port && port)
1365 		GETSERVBYPORT6(port, proto, sp);
1366 	if (sp || port == 0)
1367 		snprintf(cp, sizeof(line) - (cp - line),
1368 		    "%s", sp ? sp->s_name : "*");
1369 	else
1370 		snprintf(cp, sizeof(line) - (cp - line),
1371 		    "%d", ntohs((u_short)port));
1372 	lwidth = Aflag ? 18 : 22;
1373 	if (vflag && lwidth < (int)strlen(line))
1374 		lwidth = strlen(line);
1375 	printf(" %-*.*s", lwidth, lwidth, line);
1376 }
1377 
1378 /*
1379  * Construct an Internet address representation.
1380  * If the numeric_addr has been supplied, give
1381  * numeric value, otherwise try for symbolic name.
1382  */
1383 
1384 char *
1385 inet6name(const struct in6_addr *in6p)
1386 {
1387 	char *cp;
1388 	static char line[NI_MAXHOST];
1389 	struct hostent *hp;
1390 	static char domain[MAXHOSTNAMELEN + 1];
1391 	static int first = 1;
1392 	char hbuf[NI_MAXHOST];
1393 	struct sockaddr_in6 sin6;
1394 	const int niflag = NI_NUMERICHOST;
1395 
1396 	if (first && !numeric_addr) {
1397 		first = 0;
1398 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1399 		    (cp = strchr(domain, '.')))
1400 			(void) strlcpy(domain, cp + 1, sizeof(domain));
1401 		else
1402 			domain[0] = 0;
1403 	}
1404 	cp = 0;
1405 	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1406 		hp = gethostbyaddr((const char *)in6p, sizeof(*in6p), AF_INET6);
1407 		if (hp) {
1408 			if ((cp = strchr(hp->h_name, '.')) &&
1409 			    !strcmp(cp + 1, domain))
1410 				*cp = 0;
1411 			cp = hp->h_name;
1412 		}
1413 	}
1414 	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1415 		strlcpy(line, "*", sizeof(line));
1416 	else if (cp)
1417 		strlcpy(line, cp, sizeof(line));
1418 	else {
1419 		memset(&sin6, 0, sizeof(sin6));
1420 		sin6.sin6_len = sizeof(sin6);
1421 		sin6.sin6_family = AF_INET6;
1422 		sin6.sin6_addr = *in6p;
1423 		inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL|
1424 		    INET6_IS_ADDR_MC_LINKLOCAL);
1425 		if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1426 				hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
1427 			strlcpy(hbuf, "?", sizeof(hbuf));
1428 		strlcpy(line, hbuf, sizeof(line));
1429 	}
1430 	return (line);
1431 }
1432 
1433 #ifdef TCP6
1434 /*
1435  * Dump the contents of a TCP6 PCB.
1436  */
1437 void
1438 tcp6_dump(u_long pcbaddr)
1439 	u_long pcbaddr;
1440 {
1441 	struct tcp6cb tcp6cb;
1442 	int i;
1443 	struct kinfo_pcb *pcblist;
1444 	size_t j, len;
1445 
1446 	if (use_sysctl)
1447 		pcblist = getpcblist_sysctl(name, &len);
1448 	else
1449 		pcblist = getpcblist_kmem(off, name, &len);
1450 
1451 	for (j = 0; j < len; j++)
1452 		if (pcblist[j].ki_ppcbaddr == pcbaddr)
1453 			break;
1454 	free(pcblist);
1455 
1456 	if (j == len)
1457 		errx(1, "0x%lx is not a valid pcb address", pcbaddr);
1458 
1459 	kread(pcbaddr, (char *)&tcp6cb, sizeof(tcp6cb));
1460 
1461 	printf("TCP Protocol Control Block at 0x%08lx:\n\n", pcbaddr);
1462 
1463 	printf("Timers:\n");
1464 	for (i = 0; i < TCP6T_NTIMERS; i++)
1465 		printf("\t%s: %u", tcp6timers[i], tcp6cb.t_timer[i]);
1466 	printf("\n\n");
1467 
1468 	if (tcp6cb.t_state < 0 || tcp6cb.t_state >= TCP6_NSTATES)
1469 		printf("State: %d", tcp6cb.t_state);
1470 	else
1471 		printf("State: %s", tcp6states[tcp6cb.t_state]);
1472 	printf(", flags 0x%x, in6pcb 0x%lx\n\n", tcp6cb.t_flags,
1473 	    (u_long)tcp6cb.t_in6pcb);
1474 
1475 	printf("rxtshift %d, rxtcur %d, dupacks %d\n", tcp6cb.t_rxtshift,
1476 	    tcp6cb.t_rxtcur, tcp6cb.t_dupacks);
1477 	printf("peermaxseg %u, maxseg %u, force %d\n\n", tcp6cb.t_peermaxseg,
1478 	    tcp6cb.t_maxseg, tcp6cb.t_force);
1479 
1480 	printf("snd_una %u, snd_nxt %u, snd_up %u\n",
1481 	    tcp6cb.snd_una, tcp6cb.snd_nxt, tcp6cb.snd_up);
1482 	printf("snd_wl1 %u, snd_wl2 %u, iss %u, snd_wnd %llu\n\n",
1483 	    tcp6cb.snd_wl1, tcp6cb.snd_wl2, tcp6cb.iss,
1484 	    (unsigned long long)tcp6cb.snd_wnd);
1485 
1486 	printf("rcv_wnd %llu, rcv_nxt %u, rcv_up %u, irs %u\n\n",
1487 	    (unsigned long long)cp6cb.rcv_wnd, tcp6cb.rcv_nxt,
1488 	    tcp6cb.rcv_up, tcp6cb.irs);
1489 
1490 	printf("rcv_adv %u, snd_max %u, snd_cwnd %llu, snd_ssthresh %llu\n",
1491 	    tcp6cb.rcv_adv, tcp6cb.snd_max, (unsigned long long)tcp6cb.snd_cwnd,
1492 	    (unsigned long long)tcp6cb.snd_ssthresh);
1493 
1494 	printf("idle %d, rtt %d, rtseq %u, srtt %d, rttvar %d, rttmin %d, "
1495 	    "max_sndwnd %llu\n\n", tcp6cb.t_idle, tcp6cb.t_rtt, tcp6cb.t_rtseq,
1496 	    tcp6cb.t_srtt, tcp6cb.t_rttvar, tcp6cb.t_rttmin,
1497 	    (unsigned long long)tcp6cb.max_sndwnd);
1498 
1499 	printf("oobflags %d, iobc %d, softerror %d\n\n", tcp6cb.t_oobflags,
1500 	    tcp6cb.t_iobc, tcp6cb.t_softerror);
1501 
1502 	printf("snd_scale %d, rcv_scale %d, req_r_scale %d, req_s_scale %d\n",
1503 	    tcp6cb.snd_scale, tcp6cb.rcv_scale, tcp6cb.request_r_scale,
1504 	    tcp6cb.requested_s_scale);
1505 	printf("ts_recent %u, ts_regent_age %d, last_ack_sent %u\n",
1506 	    tcp6cb.ts_recent, tcp6cb.ts_recent_age, tcp6cb.last_ack_sent);
1507 }
1508 #endif
1509 
1510 #endif /*INET6*/
1511