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