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