xref: /freebsd/usr.bin/netstat/inet6.c (revision 9fc5c47fa5c7fa58d61245f0408611943e613164)
1 /*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
2 /*-
3  * Copyright (c) 1983, 1988, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 4. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 #if 0
32 #ifndef lint
33 static char sccsid[] = "@(#)inet6.c	8.4 (Berkeley) 4/20/94";
34 #endif /* not lint */
35 #endif
36 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39 
40 #ifdef INET6
41 #include <sys/param.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/ioctl.h>
45 #include <sys/mbuf.h>
46 #include <sys/protosw.h>
47 #include <sys/sysctl.h>
48 
49 #include <net/route.h>
50 #include <net/if.h>
51 #include <netinet/in.h>
52 #include <netinet/ip6.h>
53 #include <netinet/icmp6.h>
54 #include <netinet/in_systm.h>
55 #include <netinet6/in6_pcb.h>
56 #include <netinet6/in6_var.h>
57 #include <netinet6/ip6_var.h>
58 #include <netinet6/pim6_var.h>
59 #include <netinet6/raw_ip6.h>
60 
61 #include <arpa/inet.h>
62 #include <netdb.h>
63 
64 #include <err.h>
65 #include <stdint.h>
66 #include <stdio.h>
67 #include <stdbool.h>
68 #include <errno.h>
69 #include <string.h>
70 #include <unistd.h>
71 #include <libxo/xo.h>
72 #include "netstat.h"
73 
74 char	*inet6name(struct in6_addr *);
75 
76 static char ntop_buf[INET6_ADDRSTRLEN];
77 
78 static	const char *ip6nh[] = {
79 	"hop by hop",
80 	"ICMP",
81 	"IGMP",
82 	"#3",
83 	"IP",
84 	"#5",
85 	"TCP",
86 	"#7",
87 	"#8",
88 	"#9",
89 	"#10",
90 	"#11",
91 	"#12",
92 	"#13",
93 	"#14",
94 	"#15",
95 	"#16",
96 	"UDP",
97 	"#18",
98 	"#19",
99 	"#20",
100 	"#21",
101 	"IDP",
102 	"#23",
103 	"#24",
104 	"#25",
105 	"#26",
106 	"#27",
107 	"#28",
108 	"TP",
109 	"#30",
110 	"#31",
111 	"#32",
112 	"#33",
113 	"#34",
114 	"#35",
115 	"#36",
116 	"#37",
117 	"#38",
118 	"#39",
119 	"#40",
120 	"IP6",
121 	"#42",
122 	"routing",
123 	"fragment",
124 	"#45",
125 	"#46",
126 	"#47",
127 	"#48",
128 	"#49",
129 	"ESP",
130 	"AH",
131 	"#52",
132 	"#53",
133 	"#54",
134 	"#55",
135 	"#56",
136 	"#57",
137 	"ICMP6",
138 	"no next header",
139 	"destination option",
140 	"#61",
141 	"mobility",
142 	"#63",
143 	"#64",
144 	"#65",
145 	"#66",
146 	"#67",
147 	"#68",
148 	"#69",
149 	"#70",
150 	"#71",
151 	"#72",
152 	"#73",
153 	"#74",
154 	"#75",
155 	"#76",
156 	"#77",
157 	"#78",
158 	"#79",
159 	"ISOIP",
160 	"#81",
161 	"#82",
162 	"#83",
163 	"#84",
164 	"#85",
165 	"#86",
166 	"#87",
167 	"#88",
168 	"OSPF",
169 	"#80",
170 	"#91",
171 	"#92",
172 	"#93",
173 	"#94",
174 	"#95",
175 	"#96",
176 	"Ethernet",
177 	"#98",
178 	"#99",
179 	"#100",
180 	"#101",
181 	"#102",
182 	"PIM",
183 	"#104",
184 	"#105",
185 	"#106",
186 	"#107",
187 	"#108",
188 	"#109",
189 	"#110",
190 	"#111",
191 	"#112",
192 	"#113",
193 	"#114",
194 	"#115",
195 	"#116",
196 	"#117",
197 	"#118",
198 	"#119",
199 	"#120",
200 	"#121",
201 	"#122",
202 	"#123",
203 	"#124",
204 	"#125",
205 	"#126",
206 	"#127",
207 	"#128",
208 	"#129",
209 	"#130",
210 	"#131",
211 	"#132",
212 	"#133",
213 	"#134",
214 	"#135",
215 	"#136",
216 	"#137",
217 	"#138",
218 	"#139",
219 	"#140",
220 	"#141",
221 	"#142",
222 	"#143",
223 	"#144",
224 	"#145",
225 	"#146",
226 	"#147",
227 	"#148",
228 	"#149",
229 	"#150",
230 	"#151",
231 	"#152",
232 	"#153",
233 	"#154",
234 	"#155",
235 	"#156",
236 	"#157",
237 	"#158",
238 	"#159",
239 	"#160",
240 	"#161",
241 	"#162",
242 	"#163",
243 	"#164",
244 	"#165",
245 	"#166",
246 	"#167",
247 	"#168",
248 	"#169",
249 	"#170",
250 	"#171",
251 	"#172",
252 	"#173",
253 	"#174",
254 	"#175",
255 	"#176",
256 	"#177",
257 	"#178",
258 	"#179",
259 	"#180",
260 	"#181",
261 	"#182",
262 	"#183",
263 	"#184",
264 	"#185",
265 	"#186",
266 	"#187",
267 	"#188",
268 	"#189",
269 	"#180",
270 	"#191",
271 	"#192",
272 	"#193",
273 	"#194",
274 	"#195",
275 	"#196",
276 	"#197",
277 	"#198",
278 	"#199",
279 	"#200",
280 	"#201",
281 	"#202",
282 	"#203",
283 	"#204",
284 	"#205",
285 	"#206",
286 	"#207",
287 	"#208",
288 	"#209",
289 	"#210",
290 	"#211",
291 	"#212",
292 	"#213",
293 	"#214",
294 	"#215",
295 	"#216",
296 	"#217",
297 	"#218",
298 	"#219",
299 	"#220",
300 	"#221",
301 	"#222",
302 	"#223",
303 	"#224",
304 	"#225",
305 	"#226",
306 	"#227",
307 	"#228",
308 	"#229",
309 	"#230",
310 	"#231",
311 	"#232",
312 	"#233",
313 	"#234",
314 	"#235",
315 	"#236",
316 	"#237",
317 	"#238",
318 	"#239",
319 	"#240",
320 	"#241",
321 	"#242",
322 	"#243",
323 	"#244",
324 	"#245",
325 	"#246",
326 	"#247",
327 	"#248",
328 	"#249",
329 	"#250",
330 	"#251",
331 	"#252",
332 	"#253",
333 	"#254",
334 	"#255",
335 };
336 
337 static const char *srcrule_str[] = {
338 	"first candidate",
339 	"same address",
340 	"appropriate scope",
341 	"deprecated address",
342 	"home address",
343 	"outgoing interface",
344 	"matching label",
345 	"public/temporary address",
346 	"alive interface",
347 	"better virtual status",
348 	"preferred source",
349 	"rule #11",
350 	"rule #12",
351 	"rule #13",
352 	"longest match",
353 	"rule #15",
354 };
355 
356 /*
357  * Dump IP6 statistics structure.
358  */
359 void
360 ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
361 {
362 	struct ip6stat ip6stat, zerostat;
363 	int first, i;
364 	size_t len;
365 
366 	len = sizeof ip6stat;
367 	if (live) {
368 		memset(&ip6stat, 0, len);
369 		if (zflag)
370 			memset(&zerostat, 0, len);
371 		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len,
372 		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
373 			if (errno != ENOENT)
374 				xo_warn("sysctl: net.inet6.ip6.stats");
375 			return;
376 		}
377 	} else
378 		kread_counters(off, &ip6stat, len);
379 	xo_open_container(name);
380 	xo_emit("{T:/%s}:\n", name);
381 
382 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
383 	xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
384 #define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
385 	xo_emit(m, (uintmax_t)ip6stat.f)
386 
387 	p(ip6s_total, "\t{:received-packets/%ju} "
388 	    "{N:/total packet%s received}\n");
389 	p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
390 	    "{N:/with size smaller than minimum}\n");
391 	p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
392 	    "{N:/with data size < data length}\n");
393 	p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
394 	    "{N:/with bad options}\n");
395 	p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
396 	    "{N:/with incorrect version number}\n");
397 	p(ip6s_fragments, "\t{:received-fragments/%ju} "
398 	    "{N:/fragment%s received}\n");
399 	p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
400 	    "{N:/fragment%s dropped (dup or out of space)}\n");
401 	p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
402 	    "{N:/fragment%s dropped after timeout}\n");
403 	p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
404 	    "{N:/fragment%s that exceeded limit}\n");
405 	p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
406 	    "{N:/packet%s reassembled ok}\n");
407 	p(ip6s_delivered, "\t{:received-local-packets/%ju} "
408 	    "{N:/packet%s for this host}\n");
409 	p(ip6s_forward, "\t{:forwarded-packets/%ju} "
410 	    "{N:/packet%s forwarded}\n");
411 	p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
412 	    "{N:/packet%s not forwardable}\n");
413 	p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
414 	    "{N:/redirect%s sent}\n");
415 	p(ip6s_localout, "\t{:sent-packets/%ju} "
416 	    "{N:/packet%s sent from this host}\n");
417 	p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
418 	    "{N:/packet%s sent with fabricated ip header}\n");
419 	p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
420 	    "{N:/output packet%s dropped due to no bufs, etc.}\n");
421 	p(ip6s_noroute, "\t{:discard-no-route/%ju} "
422 	    "{N:/output packet%s discarded due to no route}\n");
423 	p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
424 	    "{N:/output datagram%s fragmented}\n");
425 	p(ip6s_ofragments, "\t{:fragments-created/%ju} "
426 	    "{N:/fragment%s created}\n");
427 	p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
428 	    "{N:/datagram%s that can't be fragmented}\n");
429 	p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
430 	    "{N:/packet%s that violated scope rules}\n");
431 	p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
432 	    "{N:/multicast packet%s which we don't join}\n");
433 	for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
434 		if (ip6stat.ip6s_nxthist[i] != 0) {
435 			if (first) {
436 				xo_emit("\t{T:Input histogram}:\n");
437 				xo_open_list("input-histogram");
438 				first = 0;
439 			}
440 			xo_open_instance("input-histogram");
441 			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
442 			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
443 			xo_close_instance("input-histogram");
444 		}
445 	if (!first)
446 		xo_close_list("input-histogram");
447 
448 	xo_open_container("mbuf-statistics");
449 	xo_emit("\t{T:Mbuf statistics}:\n");
450 	xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
451 	    (uintmax_t)ip6stat.ip6s_m1);
452 	for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
453 		char ifbuf[IFNAMSIZ];
454 		if (ip6stat.ip6s_m2m[i] != 0) {
455 			if (first) {
456 				xo_emit("\t\t{N:two or more mbuf}:\n");
457 				xo_open_list("mbuf-data");
458 				first = 0;
459 			}
460 			xo_open_instance("mbuf-data");
461 			xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
462 			    if_indextoname(i, ifbuf),
463 			    (uintmax_t)ip6stat.ip6s_m2m[i]);
464 			xo_close_instance("mbuf-data");
465 		}
466 	}
467 	if (!first)
468 		xo_close_list("mbuf-data");
469 	xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
470 	    (uintmax_t)ip6stat.ip6s_mext1);
471 	xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
472 	    "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
473 	xo_close_container("mbuf-statistics");
474 
475 	p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
476 	    "{N:/packet%s whose headers are not contiguous}\n");
477 	p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
478 	    "{N:/tunneling packet%s that can't find gif}\n");
479 	p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
480 	    "{N:/packet%s discarded because of too many headers}\n");
481 
482 	/* for debugging source address selection */
483 #define	PRINT_SCOPESTAT(s,i) do {\
484 		switch(i) { /* XXX hardcoding in each case */\
485 		case 1:\
486 			p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
487 			  "{N:/interface-local%s}\n");	\
488 			break;\
489 		case 2:\
490 			p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
491 			"{N:/link-local%s}\n"); \
492 			break;\
493 		case 5:\
494 			p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
495 			  "{N:/site-local%s}\n");\
496 			break;\
497 		case 14:\
498 			p(s,"\t\t{ke:name/globals}{:count/%ju} " \
499 			  "{N:/global%s}\n");\
500 			break;\
501 		default:\
502 			xo_emit("\t\t{qke:name/%x}{:count/%ju} " \
503 				"addresses scope=%x\n",\
504 				i, (uintmax_t)ip6stat.s, i);	   \
505 		}\
506 	} while (0);
507 
508 	xo_open_container("source-address-selection");
509 	p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
510 	    "{N:/failure%s of source address selection}\n");
511 
512 	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
513 		if (ip6stat.ip6s_sources_sameif[i]) {
514 			if (first) {
515 				xo_open_list("outgoing-interface");
516 				xo_emit("\tsource addresses on an outgoing "
517 				    "I/F\n");
518 				first = 0;
519 			}
520 			xo_open_instance("outgoing-interface");
521 			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
522 			xo_close_instance("outgoing-interface");
523 		}
524 	}
525 	if (!first)
526 		xo_close_list("outgoing-interface");
527 
528 	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
529 		if (ip6stat.ip6s_sources_otherif[i]) {
530 			if (first) {
531 				xo_open_list("non-outgoing-interface");
532 				xo_emit("\tsource addresses on a non-outgoing "
533 				    "I/F\n");
534 				first = 0;
535 			}
536 			xo_open_instance("non-outgoing-interface");
537 			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
538 			xo_close_instance("non-outgoing-interface");
539 		}
540 	}
541 	if (!first)
542 		xo_close_list("non-outgoing-interface");
543 
544 	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
545 		if (ip6stat.ip6s_sources_samescope[i]) {
546 			if (first) {
547 				xo_open_list("same-source");
548 				xo_emit("\tsource addresses of same scope\n");
549 				first = 0;
550 			}
551 			xo_open_instance("same-source");
552 			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
553 			xo_close_instance("same-source");
554 		}
555 	}
556 	if (!first)
557 		xo_close_list("same-source");
558 
559 	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
560 		if (ip6stat.ip6s_sources_otherscope[i]) {
561 			if (first) {
562 				xo_open_list("different-scope");
563 				xo_emit("\tsource addresses of a different "
564 				    "scope\n");
565 				first = 0;
566 			}
567 			xo_open_instance("different-scope");
568 			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
569 			xo_close_instance("different-scope");
570 		}
571 	}
572 	if (!first)
573 		xo_close_list("different-scope");
574 
575 	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
576 		if (ip6stat.ip6s_sources_deprecated[i]) {
577 			if (first) {
578 				xo_open_list("deprecated-source");
579 				xo_emit("\tdeprecated source addresses\n");
580 				first = 0;
581 			}
582 			xo_open_instance("deprecated-source");
583 			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
584 			xo_close_instance("deprecated-source");
585 		}
586 	}
587 	if (!first)
588 		xo_close_list("deprecated-source");
589 
590 	for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
591 		if (ip6stat.ip6s_sources_rule[i]) {
592 			if (first) {
593 				xo_open_list("rules-applied");
594 				xo_emit("\t{T:Source addresses selection "
595 				    "rule applied}:\n");
596 				first = 0;
597 			}
598 			xo_open_instance("rules-applied");
599 			xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
600 			    srcrule_str[i],
601 			    (uintmax_t)ip6stat.ip6s_sources_rule[i],
602 			    srcrule_str[i]);
603 			xo_close_instance("rules-applied");
604 		}
605 	}
606 	if (!first)
607 		xo_close_list("rules-applied");
608 
609 	xo_close_container("source-address-selection");
610 
611 #undef p
612 #undef p1a
613 	xo_close_container(name);
614 }
615 
616 /*
617  * Dump IPv6 per-interface statistics based on RFC 2465.
618  */
619 void
620 ip6_ifstats(char *ifname)
621 {
622 	struct in6_ifreq ifr;
623 	int s;
624 
625 #define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1)	\
626 	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f,		\
627 	    plural(ifr.ifr_ifru.ifru_stat.f))
628 
629 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
630 		xo_warn("Warning: socket(AF_INET6)");
631 		return;
632 	}
633 
634 	strcpy(ifr.ifr_name, ifname);
635 	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
636 		if (errno != EPFNOSUPPORT)
637 			xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
638 		goto end;
639 	}
640 
641 	xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
642 
643 	xo_open_instance("ip6-interface-statistics");
644 	xo_emit("{ke:name/%s}", ifr.ifr_name);
645 
646 	p(ifs6_in_receive, "\t{:received-packets/%ju} "
647 	    "{N:/total input datagram%s}\n");
648 	p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
649 	    "{N:/datagram%s with invalid header received}\n");
650 	p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
651 	    "{N:/datagram%s exceeded MTU received}\n");
652 	p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
653 	    "{N:/datagram%s with no route received}\n");
654 	p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
655 	    "{N:/datagram%s with invalid dst received}\n");
656 	p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
657 	    "{N:/datagram%s with unknown proto received}\n");
658 	p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
659 	    "{N:/truncated datagram%s received}\n");
660 	p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
661 	    "{N:/input datagram%s discarded}\n");
662  	p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
663 	    "{N:/datagram%s delivered to an upper layer protocol}\n");
664 	p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
665 	    "{N:/datagram%s forwarded to this interface}\n");
666  	p(ifs6_out_request, "\t{:sent-packets/%ju} "
667 	    "{N:/datagram%s sent from an upper layer protocol}\n");
668 	p(ifs6_out_discard, "\t{:discard-packets/%ju} "
669 	    "{N:/total discarded output datagram%s}\n");
670 	p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
671 	    "{N:/output datagram%s fragmented}\n");
672 	p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
673 	    "{N:/output datagram%s failed on fragment}\n");
674 	p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
675 	    "{N:/output datagram%s succeeded on fragment}\n");
676 	p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
677 	    "{N:/incoming datagram%s fragmented}\n");
678 	p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
679 	    "{N:/datagram%s reassembled}\n");
680 	p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
681 	    "{N:/datagram%s failed on reassembly}\n");
682 	p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
683 	    "{N:/multicast datagram%s received}\n");
684 	p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
685 	    "{N:/multicast datagram%s sent}\n");
686 
687  end:
688 	xo_close_instance("ip6-interface-statistics");
689  	close(s);
690 
691 #undef p
692 }
693 
694 static	const char *icmp6names[] = {
695 	"#0",
696 	"unreach",
697 	"packet too big",
698 	"time exceed",
699 	"parameter problem",
700 	"#5",
701 	"#6",
702 	"#7",
703 	"#8",
704 	"#9",
705 	"#10",
706 	"#11",
707 	"#12",
708 	"#13",
709 	"#14",
710 	"#15",
711 	"#16",
712 	"#17",
713 	"#18",
714 	"#19",
715 	"#20",
716 	"#21",
717 	"#22",
718 	"#23",
719 	"#24",
720 	"#25",
721 	"#26",
722 	"#27",
723 	"#28",
724 	"#29",
725 	"#30",
726 	"#31",
727 	"#32",
728 	"#33",
729 	"#34",
730 	"#35",
731 	"#36",
732 	"#37",
733 	"#38",
734 	"#39",
735 	"#40",
736 	"#41",
737 	"#42",
738 	"#43",
739 	"#44",
740 	"#45",
741 	"#46",
742 	"#47",
743 	"#48",
744 	"#49",
745 	"#50",
746 	"#51",
747 	"#52",
748 	"#53",
749 	"#54",
750 	"#55",
751 	"#56",
752 	"#57",
753 	"#58",
754 	"#59",
755 	"#60",
756 	"#61",
757 	"#62",
758 	"#63",
759 	"#64",
760 	"#65",
761 	"#66",
762 	"#67",
763 	"#68",
764 	"#69",
765 	"#70",
766 	"#71",
767 	"#72",
768 	"#73",
769 	"#74",
770 	"#75",
771 	"#76",
772 	"#77",
773 	"#78",
774 	"#79",
775 	"#80",
776 	"#81",
777 	"#82",
778 	"#83",
779 	"#84",
780 	"#85",
781 	"#86",
782 	"#87",
783 	"#88",
784 	"#89",
785 	"#80",
786 	"#91",
787 	"#92",
788 	"#93",
789 	"#94",
790 	"#95",
791 	"#96",
792 	"#97",
793 	"#98",
794 	"#99",
795 	"#100",
796 	"#101",
797 	"#102",
798 	"#103",
799 	"#104",
800 	"#105",
801 	"#106",
802 	"#107",
803 	"#108",
804 	"#109",
805 	"#110",
806 	"#111",
807 	"#112",
808 	"#113",
809 	"#114",
810 	"#115",
811 	"#116",
812 	"#117",
813 	"#118",
814 	"#119",
815 	"#120",
816 	"#121",
817 	"#122",
818 	"#123",
819 	"#124",
820 	"#125",
821 	"#126",
822 	"#127",
823 	"echo",
824 	"echo reply",
825 	"multicast listener query",
826 	"MLDv1 listener report",
827 	"MLDv1 listener done",
828 	"router solicitation",
829 	"router advertisement",
830 	"neighbor solicitation",
831 	"neighbor advertisement",
832 	"redirect",
833 	"router renumbering",
834 	"node information request",
835 	"node information reply",
836 	"inverse neighbor solicitation",
837 	"inverse neighbor advertisement",
838 	"MLDv2 listener report",
839 	"#144",
840 	"#145",
841 	"#146",
842 	"#147",
843 	"#148",
844 	"#149",
845 	"#150",
846 	"#151",
847 	"#152",
848 	"#153",
849 	"#154",
850 	"#155",
851 	"#156",
852 	"#157",
853 	"#158",
854 	"#159",
855 	"#160",
856 	"#161",
857 	"#162",
858 	"#163",
859 	"#164",
860 	"#165",
861 	"#166",
862 	"#167",
863 	"#168",
864 	"#169",
865 	"#170",
866 	"#171",
867 	"#172",
868 	"#173",
869 	"#174",
870 	"#175",
871 	"#176",
872 	"#177",
873 	"#178",
874 	"#179",
875 	"#180",
876 	"#181",
877 	"#182",
878 	"#183",
879 	"#184",
880 	"#185",
881 	"#186",
882 	"#187",
883 	"#188",
884 	"#189",
885 	"#180",
886 	"#191",
887 	"#192",
888 	"#193",
889 	"#194",
890 	"#195",
891 	"#196",
892 	"#197",
893 	"#198",
894 	"#199",
895 	"#200",
896 	"#201",
897 	"#202",
898 	"#203",
899 	"#204",
900 	"#205",
901 	"#206",
902 	"#207",
903 	"#208",
904 	"#209",
905 	"#210",
906 	"#211",
907 	"#212",
908 	"#213",
909 	"#214",
910 	"#215",
911 	"#216",
912 	"#217",
913 	"#218",
914 	"#219",
915 	"#220",
916 	"#221",
917 	"#222",
918 	"#223",
919 	"#224",
920 	"#225",
921 	"#226",
922 	"#227",
923 	"#228",
924 	"#229",
925 	"#230",
926 	"#231",
927 	"#232",
928 	"#233",
929 	"#234",
930 	"#235",
931 	"#236",
932 	"#237",
933 	"#238",
934 	"#239",
935 	"#240",
936 	"#241",
937 	"#242",
938 	"#243",
939 	"#244",
940 	"#245",
941 	"#246",
942 	"#247",
943 	"#248",
944 	"#249",
945 	"#250",
946 	"#251",
947 	"#252",
948 	"#253",
949 	"#254",
950 	"#255",
951 };
952 
953 /*
954  * Dump ICMP6 statistics.
955  */
956 void
957 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
958 {
959 	struct icmp6stat icmp6stat, zerostat;
960 	int i, first;
961 	size_t len;
962 
963 	len = sizeof icmp6stat;
964 	if (live) {
965 		memset(&icmp6stat, 0, len);
966 		if (zflag)
967 			memset(&zerostat, 0, len);
968 		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
969 		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
970 			if (errno != ENOENT)
971 				xo_warn("sysctl: net.inet6.icmp6.stats");
972 			return;
973 		}
974 	} else
975 		kread_counters(off, &icmp6stat, len);
976 
977 	xo_emit("{T:/%s}:\n", name);
978 	xo_open_container(name);
979 
980 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
981 	xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
982 #define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
983 	xo_emit(m, (uintmax_t)icmp6stat.f)
984 
985 	p(icp6s_error, "\t{:icmp6-calls/%ju} "
986 	    "{N:/call%s to icmp6_error}\n");
987 	p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
988 	    "{N:/error%s not generated in response to an icmp6 message}\n");
989 	p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
990 	    "{N:/error%s not generated because of rate limitation}\n");
991 #define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
992 	for (first = 1, i = 0; i < NELEM; i++)
993 		if (icmp6stat.icp6s_outhist[i] != 0) {
994 			if (first) {
995 				xo_open_list("output-histogram");
996 				xo_emit("\t{T:Output histogram}:\n");
997 				first = 0;
998 			}
999 			xo_open_instance("output-histogram");
1000 			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1001 			    icmp6names[i],
1002 			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
1003 			xo_close_instance("output-histogram");
1004 		}
1005 	if (!first)
1006 		xo_close_list("output-histogram");
1007 #undef NELEM
1008 
1009 	p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
1010 	    "{N:/message%s with bad code fields}\n");
1011 	p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
1012 	    "{N:/message%s < minimum length}\n");
1013 	p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
1014 	    "{N:/bad checksum%s}\n");
1015 	p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
1016 	    "{N:/message%s with bad length}\n");
1017 #define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
1018 	for (first = 1, i = 0; i < NELEM; i++)
1019 		if (icmp6stat.icp6s_inhist[i] != 0) {
1020 			if (first) {
1021 				xo_open_list("input-histogram");
1022 				xo_emit("\t{T:Input histogram}:\n");
1023 				first = 0;
1024 			}
1025 			xo_open_instance("input-histogram");
1026 			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1027 			    icmp6names[i],
1028 			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
1029 			xo_close_instance("input-histogram");
1030 		}
1031 	if (!first)
1032 		xo_close_list("input-histogram");
1033 #undef NELEM
1034 	xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1035 	xo_open_container("errors");
1036 	p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1037 	    "{N:/no route}\n");
1038 	p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1039 	    "{N:/administratively prohibited}\n");
1040 	p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1041 	    "{N:/beyond scope}\n");
1042 	p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1043 	    "{N:/address unreachable}\n");
1044 	p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1045 	    "{N:/port unreachable}\n");
1046 	p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1047 	    "{N:/packet too big}\n");
1048 	p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1049 	    "{N:/time exceed transit}\n");
1050 	p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1051 	    "{N:/time exceed reassembly}\n");
1052 	p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1053 	    "{N:/erroneous header field}\n");
1054 	p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1055 	    "{N:/unrecognized next header}\n");
1056 	p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1057 	    "{N:/unrecognized option}\n");
1058 	p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1059 	    "{N:/redirect}\n");
1060 	p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1061 
1062 	p(icp6s_reflect, "\t{:reflect/%ju} "
1063 	    "{N:/message response%s generated}\n");
1064 	p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1065 	    "{N:/message%s with too many ND options}\n");
1066 	p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1067 	    "{N:/message%s with bad ND options}\n");
1068 	p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1069 	    "{N:/bad neighbor solicitation message%s}\n");
1070 	p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1071 	    "{N:/bad neighbor advertisement message%s}\n");
1072 	p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1073 	    "{N:/bad router solicitation message%s}\n");
1074 	p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1075 	    "{N:/bad router advertisement message%s}\n");
1076 	p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1077 	    "{N:/bad redirect message%s}\n");
1078 	xo_close_container("errors");
1079 	p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1080 #undef p
1081 #undef p_5
1082 	xo_close_container(name);
1083 }
1084 
1085 /*
1086  * Dump ICMPv6 per-interface statistics based on RFC 2466.
1087  */
1088 void
1089 icmp6_ifstats(char *ifname)
1090 {
1091 	struct in6_ifreq ifr;
1092 	int s;
1093 
1094 #define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1095 	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1096 	    plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1097 #define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1098 	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1099 	    pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1100 
1101 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1102 		xo_warn("Warning: socket(AF_INET6)");
1103 		return;
1104 	}
1105 
1106 	strcpy(ifr.ifr_name, ifname);
1107 	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1108 		if (errno != EPFNOSUPPORT)
1109 			xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1110 		goto end;
1111 	}
1112 
1113 	xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1114 
1115 	xo_open_instance("icmp6-interface-statistics");
1116 	xo_emit("{ke:name/%s}", ifr.ifr_name);
1117 	p(ifs6_in_msg, "\t{:received-packets/%ju} "
1118 	    "{N:/total input message%s}\n");
1119 	p(ifs6_in_error, "\t{:received-errors/%ju} "
1120 	    "{N:/total input error message%s}\n");
1121 	p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1122 	    "{N:/input destination unreachable error%s}\n");
1123 	p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1124 	    "{N:/input administratively prohibited error%s}\n");
1125 	p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1126 	    "{N:/input time exceeded error%s}\n");
1127 	p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1128 	    "{N:/input parameter problem error%s}\n");
1129 	p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1130 	    "{N:/input packet too big error%s}\n");
1131 	p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1132 	    "{N:/input echo request%s}\n");
1133 	p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1134 	    "{N:/input echo repl%s}\n");
1135 	p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1136 	    "{N:/input router solicitation%s}\n");
1137 	p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1138 	    "{N:/input router advertisement%s}\n");
1139 	p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1140 	    "{N:/input neighbor solicitation%s}\n");
1141 	p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1142 	    "{N:/input neighbor advertisement%s}\n");
1143 	p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1144 	    "{N:/input redirect%s}\n");
1145 	p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1146 	    "{N:/input MLD quer%s}\n");
1147 	p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1148 	    "{N:/input MLD report%s}\n");
1149 	p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1150 	    "{N:/input MLD done%s}\n");
1151 
1152 	p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1153 	    "{N:/total output message%s}\n");
1154 	p(ifs6_out_error, "\t{:sent-errors/%ju} "
1155 	    "{N:/total output error message%s}\n");
1156 	p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1157 	    "{N:/output destination unreachable error%s}\n");
1158 	p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1159 	    "{N:/output administratively prohibited error%s}\n");
1160 	p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1161 	    "{N:/output time exceeded error%s}\n");
1162 	p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1163 	    "{N:/output parameter problem error%s}\n");
1164 	p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1165 	    "{N:/output packet too big error%s}\n");
1166 	p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1167 	    "{N:/output echo request%s}\n");
1168 	p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1169 	    "{N:/output echo repl%s}\n");
1170 	p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1171 	    "{N:/output router solicitation%s}\n");
1172 	p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1173 	    "{N:/output router advertisement%s}\n");
1174 	p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1175 	    "{N:/output neighbor solicitation%s}\n");
1176 	p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1177 	    "{N:/output neighbor advertisement%s}\n");
1178 	p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1179 	    "{N:/output redirect%s}\n");
1180 	p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1181 	    "{N:/output MLD quer%s}\n");
1182 	p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1183 	    "{N:/output MLD report%s}\n");
1184 	p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1185 	    "{N:/output MLD done%s}\n");
1186 
1187 end:
1188 	xo_close_instance("icmp6-interface-statistics");
1189 	close(s);
1190 #undef p
1191 }
1192 
1193 /*
1194  * Dump PIM statistics structure.
1195  */
1196 void
1197 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1198 {
1199 	struct pim6stat pim6stat, zerostat;
1200 	size_t len = sizeof pim6stat;
1201 
1202 	if (live) {
1203 		if (zflag)
1204 			memset(&zerostat, 0, len);
1205 		if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1206 		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1207 			if (errno != ENOENT)
1208 				xo_warn("sysctl: net.inet6.pim.stats");
1209 			return;
1210 		}
1211 	} else {
1212 		if (off == 0)
1213 			return;
1214 		kread(off, &pim6stat, len);
1215 	}
1216 
1217 	xo_emit("{T:/%s}:\n", name);
1218 	xo_open_container(name);
1219 
1220 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
1221 	xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1222 
1223 	p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1224 	    "{N:/message%s received}\n");
1225 	p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1226 	    "{N:/message%s received with too few bytes}\n");
1227 	p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1228 	    "{N:/message%s received with bad checksum}\n");
1229 	p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1230 	    "{N:/message%s received with bad version}\n");
1231 	p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1232 	    "{N:/register%s received}\n");
1233 	p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1234 	    "{N:/bad register%s received}\n");
1235 	p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1236 	    "{N:/register%s sent}\n");
1237 #undef p
1238 	xo_close_container(name);
1239 }
1240 
1241 /*
1242  * Dump raw ip6 statistics structure.
1243  */
1244 void
1245 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1246 {
1247 	struct rip6stat rip6stat, zerostat;
1248 	u_quad_t delivered;
1249 	size_t len;
1250 
1251 	len = sizeof(rip6stat);
1252 	if (live) {
1253 		if (zflag)
1254 			memset(&zerostat, 0, len);
1255 		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1256 		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1257 			if (errno != ENOENT)
1258 				xo_warn("sysctl: net.inet6.ip6.rip6stats");
1259 			return;
1260 		}
1261 	} else
1262 		kread_counters(off, &rip6stat, len);
1263 
1264 	xo_emit("{T:/%s}:\n", name);
1265 	xo_open_container(name);
1266 
1267 #define	p(f, m) if (rip6stat.f || sflag <= 1) \
1268 	xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1269 
1270 	p(rip6s_ipackets, "\t{:received-packets/%ju} "
1271 	    "{N:/message%s received}\n");
1272 	p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1273 	    "{N:/checksum calculation%s on inbound}\n");
1274 	p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1275 	    "{N:/message%s with bad checksum}\n");
1276 	p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1277 	    "{N:/message%s dropped due to no socket}\n");
1278 	p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1279 	    "{N:/multicast message%s dropped due to no socket}\n");
1280 	p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1281 	    "{N:/message%s dropped due to full socket buffers}\n");
1282 	delivered = rip6stat.rip6s_ipackets -
1283 		    rip6stat.rip6s_badsum -
1284 		    rip6stat.rip6s_nosock -
1285 		    rip6stat.rip6s_nosockmcast -
1286 		    rip6stat.rip6s_fullsock;
1287 	if (delivered || sflag <= 1)
1288 		xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1289 		    (uintmax_t)delivered);
1290 	p(rip6s_opackets, "\t{:sent-packets/%ju} "
1291 	    "{N:/datagram%s output}\n");
1292 #undef p
1293 	xo_close_container(name);
1294 }
1295 
1296 /*
1297  * Pretty print an Internet address (net address + port).
1298  * Take numeric_addr and numeric_port into consideration.
1299  */
1300 #define	GETSERVBYPORT6(port, proto, ret)\
1301 {\
1302 	if (strcmp((proto), "tcp6") == 0)\
1303 		(ret) = getservbyport((int)(port), "tcp");\
1304 	else if (strcmp((proto), "udp6") == 0)\
1305 		(ret) = getservbyport((int)(port), "udp");\
1306 	else\
1307 		(ret) = getservbyport((int)(port), (proto));\
1308 };
1309 
1310 void
1311 inet6print(const char *container, struct in6_addr *in6, int port,
1312     const char *proto, int numeric)
1313 {
1314 	struct servent *sp = 0;
1315 	char line[80], *cp;
1316 	int width;
1317 
1318 	if (container)
1319 		xo_open_container(container);
1320 
1321 	sprintf(line, "%.*s.", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1322 	    inet6name(in6));
1323 	cp = strchr(line, '\0');
1324 	if (!numeric && port)
1325 		GETSERVBYPORT6(port, proto, sp);
1326 	if (sp || port == 0)
1327 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1328 	else
1329 		sprintf(cp, "%d", ntohs((u_short)port));
1330 	width = Wflag ? 45 : Aflag ? 18 : 22;
1331 
1332 	xo_emit("{d:target/%-*.*s} ", width, width, line);
1333 
1334 	int alen = cp - line - 1, plen = strlen(cp) - 1;
1335 	xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1336 	    plen, cp);
1337 
1338 	if (container)
1339 		xo_close_container(container);
1340 }
1341 
1342 /*
1343  * Construct an Internet address representation.
1344  * If the numeric_addr has been supplied, give
1345  * numeric value, otherwise try for symbolic name.
1346  */
1347 
1348 char *
1349 inet6name(struct in6_addr *in6p)
1350 {
1351 	struct sockaddr_in6 sin6;
1352 	char hbuf[NI_MAXHOST], *cp;
1353 	static char line[50];
1354 	static char domain[MAXHOSTNAMELEN];
1355 	static int first = 1;
1356 	int flags, error;
1357 
1358 	if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1359 		strcpy(line, "*");
1360 		return (line);
1361 	}
1362 	if (first && !numeric_addr) {
1363 		first = 0;
1364 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1365 		    (cp = strchr(domain, '.')))
1366 			(void) strcpy(domain, cp + 1);
1367 		else
1368 			domain[0] = 0;
1369 	}
1370 	memset(&sin6, 0, sizeof(sin6));
1371 	memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1372 	sin6.sin6_family = AF_INET6;
1373 	/* XXX: in6p.s6_addr[2] can contain scopeid. */
1374 	in6_fillscopeid(&sin6);
1375 	flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1376 	error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1377 	    sizeof(hbuf), NULL, 0, flags);
1378 	if (error == 0) {
1379 		if ((flags & NI_NUMERICHOST) == 0 &&
1380 		    (cp = strchr(hbuf, '.')) &&
1381 		    !strcmp(cp + 1, domain))
1382 			*cp = 0;
1383 		strcpy(line, hbuf);
1384 	} else {
1385 		/* XXX: this should not happen. */
1386 		sprintf(line, "%s",
1387 			inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
1388 				sizeof(ntop_buf)));
1389 	}
1390 	return (line);
1391 }
1392 #endif /*INET6*/
1393