154263Sshin/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
2175061Sobrien/*-
354263Sshin * Copyright (c) 1983, 1988, 1993
454263Sshin *	The Regents of the University of California.  All rights reserved.
554263Sshin *
654263Sshin * Redistribution and use in source and binary forms, with or without
754263Sshin * modification, are permitted provided that the following conditions
854263Sshin * are met:
954263Sshin * 1. Redistributions of source code must retain the above copyright
1054263Sshin *    notice, this list of conditions and the following disclaimer.
1154263Sshin * 2. Redistributions in binary form must reproduce the above copyright
1254263Sshin *    notice, this list of conditions and the following disclaimer in the
1354263Sshin *    documentation and/or other materials provided with the distribution.
1454263Sshin * 4. Neither the name of the University nor the names of its contributors
1554263Sshin *    may be used to endorse or promote products derived from this software
1654263Sshin *    without specific prior written permission.
1754263Sshin *
1854263Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1954263Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2054263Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2154263Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2254263Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2354263Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2454263Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2554263Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2654263Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2754263Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2854263Sshin * SUCH DAMAGE.
2954263Sshin */
3054263Sshin
31132671Scharnier#if 0
3254263Sshin#ifndef lint
3354263Sshinstatic char sccsid[] = "@(#)inet6.c	8.4 (Berkeley) 4/20/94";
3454263Sshin#endif /* not lint */
35132671Scharnier#endif
3654263Sshin
37132671Scharnier#include <sys/cdefs.h>
38132671Scharnier__FBSDID("$FreeBSD: stable/11/usr.bin/netstat/inet6.c 355869 2019-12-17 23:45:50Z bz $");
39132671Scharnier
4064342Sume#ifdef INET6
4154263Sshin#include <sys/param.h>
4254263Sshin#include <sys/socket.h>
4354263Sshin#include <sys/socketvar.h>
4454263Sshin#include <sys/ioctl.h>
4554263Sshin#include <sys/mbuf.h>
4654263Sshin#include <sys/protosw.h>
4754263Sshin
4854263Sshin#include <net/route.h>
4954263Sshin#include <net/if.h>
5054263Sshin#include <netinet/in.h>
5154263Sshin#include <netinet/ip6.h>
5254263Sshin#include <netinet/icmp6.h>
5354263Sshin#include <netinet/in_systm.h>
5454263Sshin#include <netinet6/in6_pcb.h>
5554263Sshin#include <netinet6/in6_var.h>
5654263Sshin#include <netinet6/ip6_var.h>
5754263Sshin#include <netinet6/pim6_var.h>
5878064Sume#include <netinet6/raw_ip6.h>
5954263Sshin
6054263Sshin#include <arpa/inet.h>
6154263Sshin#include <netdb.h>
6254263Sshin
63166952Sbms#include <err.h>
64160787Syar#include <stdint.h>
6554263Sshin#include <stdio.h>
66279122Smarcel#include <stdbool.h>
67160373Sjulian#include <errno.h>
6854263Sshin#include <string.h>
6954263Sshin#include <unistd.h>
70279122Smarcel#include <libxo/xo.h>
7154263Sshin#include "netstat.h"
7254263Sshin
7354263Sshinstatic char ntop_buf[INET6_ADDRSTRLEN];
7454263Sshin
75102975Sdwmalonestatic	const char *ip6nh[] = {
7654263Sshin	"hop by hop",
7754263Sshin	"ICMP",
7854263Sshin	"IGMP",
7954263Sshin	"#3",
8054263Sshin	"IP",
8154263Sshin	"#5",
8254263Sshin	"TCP",
8354263Sshin	"#7",
8454263Sshin	"#8",
8554263Sshin	"#9",
8654263Sshin	"#10",
8754263Sshin	"#11",
8854263Sshin	"#12",
8954263Sshin	"#13",
9054263Sshin	"#14",
9154263Sshin	"#15",
9254263Sshin	"#16",
9354263Sshin	"UDP",
9454263Sshin	"#18",
95175061Sobrien	"#19",
9654263Sshin	"#20",
9754263Sshin	"#21",
9854263Sshin	"IDP",
9954263Sshin	"#23",
10054263Sshin	"#24",
10154263Sshin	"#25",
10254263Sshin	"#26",
10354263Sshin	"#27",
10454263Sshin	"#28",
105175061Sobrien	"TP",
10654263Sshin	"#30",
10754263Sshin	"#31",
10854263Sshin	"#32",
10954263Sshin	"#33",
11054263Sshin	"#34",
11154263Sshin	"#35",
11254263Sshin	"#36",
11354263Sshin	"#37",
11454263Sshin	"#38",
115175061Sobrien	"#39",
11654263Sshin	"#40",
11754263Sshin	"IP6",
11854263Sshin	"#42",
11954263Sshin	"routing",
12054263Sshin	"fragment",
12154263Sshin	"#45",
12254263Sshin	"#46",
12354263Sshin	"#47",
12454263Sshin	"#48",
125175061Sobrien	"#49",
12654263Sshin	"ESP",
12754263Sshin	"AH",
12854263Sshin	"#52",
12954263Sshin	"#53",
13054263Sshin	"#54",
13154263Sshin	"#55",
13254263Sshin	"#56",
13354263Sshin	"#57",
13454263Sshin	"ICMP6",
135175061Sobrien	"no next header",
13654263Sshin	"destination option",
13754263Sshin	"#61",
138125482Sume	"mobility",
13954263Sshin	"#63",
14054263Sshin	"#64",
14154263Sshin	"#65",
14254263Sshin	"#66",
14354263Sshin	"#67",
14454263Sshin	"#68",
145175061Sobrien	"#69",
14654263Sshin	"#70",
14754263Sshin	"#71",
14854263Sshin	"#72",
14954263Sshin	"#73",
15054263Sshin	"#74",
15154263Sshin	"#75",
15254263Sshin	"#76",
15354263Sshin	"#77",
15454263Sshin	"#78",
155175061Sobrien	"#79",
15654263Sshin	"ISOIP",
15754263Sshin	"#81",
15854263Sshin	"#82",
15954263Sshin	"#83",
16054263Sshin	"#84",
16154263Sshin	"#85",
16254263Sshin	"#86",
16354263Sshin	"#87",
16454263Sshin	"#88",
165175061Sobrien	"OSPF",
16654263Sshin	"#80",
16754263Sshin	"#91",
16854263Sshin	"#92",
16954263Sshin	"#93",
17054263Sshin	"#94",
17154263Sshin	"#95",
17254263Sshin	"#96",
17354263Sshin	"Ethernet",
17454263Sshin	"#98",
175175061Sobrien	"#99",
17654263Sshin	"#100",
17754263Sshin	"#101",
17854263Sshin	"#102",
17954263Sshin	"PIM",
18054263Sshin	"#104",
18154263Sshin	"#105",
18254263Sshin	"#106",
18354263Sshin	"#107",
18454263Sshin	"#108",
185175061Sobrien	"#109",
18654263Sshin	"#110",
18754263Sshin	"#111",
18854263Sshin	"#112",
18954263Sshin	"#113",
19054263Sshin	"#114",
19154263Sshin	"#115",
19254263Sshin	"#116",
19354263Sshin	"#117",
19454263Sshin	"#118",
195175061Sobrien	"#119",
19654263Sshin	"#120",
19754263Sshin	"#121",
19854263Sshin	"#122",
19954263Sshin	"#123",
20054263Sshin	"#124",
20154263Sshin	"#125",
20254263Sshin	"#126",
20354263Sshin	"#127",
20454263Sshin	"#128",
205175061Sobrien	"#129",
20654263Sshin	"#130",
20754263Sshin	"#131",
208304519Stuexen	"SCTP",
20954263Sshin	"#133",
21054263Sshin	"#134",
21154263Sshin	"#135",
212304519Stuexen	"UDPLite",
21354263Sshin	"#137",
21454263Sshin	"#138",
215175061Sobrien	"#139",
21654263Sshin	"#140",
21754263Sshin	"#141",
21854263Sshin	"#142",
21954263Sshin	"#143",
22054263Sshin	"#144",
22154263Sshin	"#145",
22254263Sshin	"#146",
22354263Sshin	"#147",
22454263Sshin	"#148",
225175061Sobrien	"#149",
22654263Sshin	"#150",
22754263Sshin	"#151",
22854263Sshin	"#152",
22954263Sshin	"#153",
23054263Sshin	"#154",
23154263Sshin	"#155",
23254263Sshin	"#156",
23354263Sshin	"#157",
23454263Sshin	"#158",
235175061Sobrien	"#159",
23654263Sshin	"#160",
23754263Sshin	"#161",
23854263Sshin	"#162",
23954263Sshin	"#163",
24054263Sshin	"#164",
24154263Sshin	"#165",
24254263Sshin	"#166",
24354263Sshin	"#167",
24454263Sshin	"#168",
245175061Sobrien	"#169",
24654263Sshin	"#170",
24754263Sshin	"#171",
24854263Sshin	"#172",
24954263Sshin	"#173",
25054263Sshin	"#174",
25154263Sshin	"#175",
25254263Sshin	"#176",
25354263Sshin	"#177",
25454263Sshin	"#178",
255175061Sobrien	"#179",
25654263Sshin	"#180",
25754263Sshin	"#181",
25854263Sshin	"#182",
25954263Sshin	"#183",
26054263Sshin	"#184",
26154263Sshin	"#185",
26254263Sshin	"#186",
26354263Sshin	"#187",
26454263Sshin	"#188",
265175061Sobrien	"#189",
26654263Sshin	"#180",
26754263Sshin	"#191",
26854263Sshin	"#192",
26954263Sshin	"#193",
27054263Sshin	"#194",
27154263Sshin	"#195",
27254263Sshin	"#196",
27354263Sshin	"#197",
27454263Sshin	"#198",
275175061Sobrien	"#199",
27654263Sshin	"#200",
27754263Sshin	"#201",
27854263Sshin	"#202",
27954263Sshin	"#203",
28054263Sshin	"#204",
28154263Sshin	"#205",
28254263Sshin	"#206",
28354263Sshin	"#207",
28454263Sshin	"#208",
285175061Sobrien	"#209",
28654263Sshin	"#210",
28754263Sshin	"#211",
28854263Sshin	"#212",
28954263Sshin	"#213",
29054263Sshin	"#214",
29154263Sshin	"#215",
29254263Sshin	"#216",
29354263Sshin	"#217",
29454263Sshin	"#218",
295175061Sobrien	"#219",
29654263Sshin	"#220",
29754263Sshin	"#221",
29854263Sshin	"#222",
29954263Sshin	"#223",
30054263Sshin	"#224",
30154263Sshin	"#225",
30254263Sshin	"#226",
30354263Sshin	"#227",
30454263Sshin	"#228",
305175061Sobrien	"#229",
30654263Sshin	"#230",
30754263Sshin	"#231",
30854263Sshin	"#232",
30954263Sshin	"#233",
31054263Sshin	"#234",
31154263Sshin	"#235",
31254263Sshin	"#236",
31354263Sshin	"#237",
31454263Sshin	"#238",
315175061Sobrien	"#239",
31654263Sshin	"#240",
31754263Sshin	"#241",
31854263Sshin	"#242",
31954263Sshin	"#243",
32054263Sshin	"#244",
32154263Sshin	"#245",
32254263Sshin	"#246",
32354263Sshin	"#247",
32454263Sshin	"#248",
325175061Sobrien	"#249",
32654263Sshin	"#250",
32754263Sshin	"#251",
32854263Sshin	"#252",
32954263Sshin	"#253",
33054263Sshin	"#254",
33154263Sshin	"#255",
33254263Sshin};
33354263Sshin
334246988Scharnierstatic const char *srcrule_str[] = {
335125483Sume	"first candidate",
336125483Sume	"same address",
337125483Sume	"appropriate scope",
338125483Sume	"deprecated address",
339125483Sume	"home address",
340125483Sume	"outgoing interface",
341125483Sume	"matching label",
342125483Sume	"public/temporary address",
343125483Sume	"alive interface",
344270927Sae	"better virtual status",
345271307Sae	"preferred source",
346125483Sume	"rule #11",
347125483Sume	"rule #12",
348125483Sume	"rule #13",
349125483Sume	"longest match",
350125483Sume	"rule #15",
351125483Sume};
352125483Sume
35354263Sshin/*
35454263Sshin * Dump IP6 statistics structure.
35554263Sshin */
35654263Sshinvoid
357171465Sjhbip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
35854263Sshin{
359287649Smarkj	struct ip6stat ip6stat;
36054263Sshin	int first, i;
36154263Sshin
362287649Smarkj	if (fetch_stats("net.inet6.ip6.stats", off, &ip6stat,
363287649Smarkj	    sizeof(ip6stat), kread_counters) != 0)
364287649Smarkj		return;
365287649Smarkj
366279122Smarcel	xo_open_container(name);
367279122Smarcel	xo_emit("{T:/%s}:\n", name);
36854263Sshin
36954263Sshin#define	p(f, m) if (ip6stat.f || sflag <= 1) \
370279122Smarcel	xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
37154263Sshin#define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
372279122Smarcel	xo_emit(m, (uintmax_t)ip6stat.f)
37354263Sshin
374279122Smarcel	p(ip6s_total, "\t{:received-packets/%ju} "
375279122Smarcel	    "{N:/total packet%s received}\n");
376279122Smarcel	p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
377279122Smarcel	    "{N:/with size smaller than minimum}\n");
378279122Smarcel	p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
379279122Smarcel	    "{N:/with data size < data length}\n");
380279122Smarcel	p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
381279122Smarcel	    "{N:/with bad options}\n");
382279122Smarcel	p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
383279122Smarcel	    "{N:/with incorrect version number}\n");
384279122Smarcel	p(ip6s_fragments, "\t{:received-fragments/%ju} "
385279122Smarcel	    "{N:/fragment%s received}\n");
386279122Smarcel	p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
387279122Smarcel	    "{N:/fragment%s dropped (dup or out of space)}\n");
388279122Smarcel	p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
389279122Smarcel	    "{N:/fragment%s dropped after timeout}\n");
390279122Smarcel	p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
391279122Smarcel	    "{N:/fragment%s that exceeded limit}\n");
392279122Smarcel	p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
393279122Smarcel	    "{N:/packet%s reassembled ok}\n");
394279122Smarcel	p(ip6s_delivered, "\t{:received-local-packets/%ju} "
395279122Smarcel	    "{N:/packet%s for this host}\n");
396279122Smarcel	p(ip6s_forward, "\t{:forwarded-packets/%ju} "
397279122Smarcel	    "{N:/packet%s forwarded}\n");
398279122Smarcel	p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
399279122Smarcel	    "{N:/packet%s not forwardable}\n");
400279122Smarcel	p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
401279122Smarcel	    "{N:/redirect%s sent}\n");
402279122Smarcel	p(ip6s_localout, "\t{:sent-packets/%ju} "
403279122Smarcel	    "{N:/packet%s sent from this host}\n");
404279122Smarcel	p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
405279122Smarcel	    "{N:/packet%s sent with fabricated ip header}\n");
406279122Smarcel	p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
407279122Smarcel	    "{N:/output packet%s dropped due to no bufs, etc.}\n");
408279122Smarcel	p(ip6s_noroute, "\t{:discard-no-route/%ju} "
409279122Smarcel	    "{N:/output packet%s discarded due to no route}\n");
410279122Smarcel	p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
411279122Smarcel	    "{N:/output datagram%s fragmented}\n");
412279122Smarcel	p(ip6s_ofragments, "\t{:fragments-created/%ju} "
413279122Smarcel	    "{N:/fragment%s created}\n");
414279122Smarcel	p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
415279122Smarcel	    "{N:/datagram%s that can't be fragmented}\n");
416279122Smarcel	p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
417279122Smarcel	    "{N:/packet%s that violated scope rules}\n");
418279122Smarcel	p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
419279122Smarcel	    "{N:/multicast packet%s which we don't join}\n");
420249545Sae	for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
42154263Sshin		if (ip6stat.ip6s_nxthist[i] != 0) {
42254263Sshin			if (first) {
423279122Smarcel				xo_emit("\t{T:Input histogram}:\n");
424279122Smarcel				xo_open_list("input-histogram");
42554263Sshin				first = 0;
42654263Sshin			}
427279122Smarcel			xo_open_instance("input-histogram");
428279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
429160787Syar			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
430279122Smarcel			xo_close_instance("input-histogram");
43154263Sshin		}
432279122Smarcel	if (!first)
433279122Smarcel		xo_close_list("input-histogram");
434279122Smarcel
435279122Smarcel	xo_open_container("mbuf-statistics");
436279122Smarcel	xo_emit("\t{T:Mbuf statistics}:\n");
437279122Smarcel	xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
438279122Smarcel	    (uintmax_t)ip6stat.ip6s_m1);
439249545Sae	for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
44055163Sshin		char ifbuf[IFNAMSIZ];
441175061Sobrien		if (ip6stat.ip6s_m2m[i] != 0) {
44254263Sshin			if (first) {
443279122Smarcel				xo_emit("\t\t{N:two or more mbuf}:\n");
444279122Smarcel				xo_open_list("mbuf-data");
44554263Sshin				first = 0;
44654263Sshin			}
447279122Smarcel			xo_open_instance("mbuf-data");
448279122Smarcel			xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
44962584Sitojun			    if_indextoname(i, ifbuf),
450160787Syar			    (uintmax_t)ip6stat.ip6s_m2m[i]);
451279122Smarcel			xo_close_instance("mbuf-data");
45254263Sshin		}
45354263Sshin	}
454279122Smarcel	if (!first)
455279122Smarcel		xo_close_list("mbuf-data");
456279122Smarcel	xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
457160787Syar	    (uintmax_t)ip6stat.ip6s_mext1);
458279122Smarcel	xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
459279122Smarcel	    "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
460279122Smarcel	xo_close_container("mbuf-statistics");
46162584Sitojun
462279122Smarcel	p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
463279122Smarcel	    "{N:/packet%s whose headers are not contiguous}\n");
464279122Smarcel	p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
465279122Smarcel	    "{N:/tunneling packet%s that can't find gif}\n");
466279122Smarcel	p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
467279122Smarcel	    "{N:/packet%s discarded because of too many headers}\n");
468279122Smarcel
46962584Sitojun	/* for debugging source address selection */
470175061Sobrien#define	PRINT_SCOPESTAT(s,i) do {\
47162584Sitojun		switch(i) { /* XXX hardcoding in each case */\
47262584Sitojun		case 1:\
473279122Smarcel			p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
474279122Smarcel			  "{N:/interface-local%s}\n");	\
47562584Sitojun			break;\
47662584Sitojun		case 2:\
477279122Smarcel			p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
478279122Smarcel			"{N:/link-local%s}\n"); \
47962584Sitojun			break;\
48062584Sitojun		case 5:\
481279122Smarcel			p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
482279122Smarcel			  "{N:/site-local%s}\n");\
48362584Sitojun			break;\
48462584Sitojun		case 14:\
485279122Smarcel			p(s,"\t\t{ke:name/globals}{:count/%ju} " \
486279122Smarcel			  "{N:/global%s}\n");\
48762584Sitojun			break;\
48862584Sitojun		default:\
489304519Stuexen			xo_emit("\t\t{qke:name/%#x}{:count/%ju} " \
490304519Stuexen				"{N:/addresses scope=%#x}\n",\
491279122Smarcel				i, (uintmax_t)ip6stat.s, i);	   \
49262584Sitojun		}\
49362584Sitojun	} while (0);
49462584Sitojun
495279122Smarcel	xo_open_container("source-address-selection");
496279122Smarcel	p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
497279122Smarcel	    "{N:/failure%s of source address selection}\n");
498279122Smarcel
499249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
50062584Sitojun		if (ip6stat.ip6s_sources_sameif[i]) {
50162584Sitojun			if (first) {
502279122Smarcel				xo_open_list("outgoing-interface");
503279122Smarcel				xo_emit("\tsource addresses on an outgoing "
504279122Smarcel				    "I/F\n");
50562584Sitojun				first = 0;
50662584Sitojun			}
507279122Smarcel			xo_open_instance("outgoing-interface");
50862584Sitojun			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
509279122Smarcel			xo_close_instance("outgoing-interface");
51062584Sitojun		}
51162584Sitojun	}
512279122Smarcel	if (!first)
513279122Smarcel		xo_close_list("outgoing-interface");
514279122Smarcel
515249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
51662584Sitojun		if (ip6stat.ip6s_sources_otherif[i]) {
51762584Sitojun			if (first) {
518279122Smarcel				xo_open_list("non-outgoing-interface");
519279122Smarcel				xo_emit("\tsource addresses on a non-outgoing "
520279122Smarcel				    "I/F\n");
52162584Sitojun				first = 0;
52262584Sitojun			}
523279122Smarcel			xo_open_instance("non-outgoing-interface");
52462584Sitojun			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
525279122Smarcel			xo_close_instance("non-outgoing-interface");
52662584Sitojun		}
52762584Sitojun	}
528279122Smarcel	if (!first)
529279122Smarcel		xo_close_list("non-outgoing-interface");
530279122Smarcel
531249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
53262584Sitojun		if (ip6stat.ip6s_sources_samescope[i]) {
53362584Sitojun			if (first) {
534279122Smarcel				xo_open_list("same-source");
535279122Smarcel				xo_emit("\tsource addresses of same scope\n");
53662584Sitojun				first = 0;
53762584Sitojun			}
538279122Smarcel			xo_open_instance("same-source");
53962584Sitojun			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
540279122Smarcel			xo_close_instance("same-source");
54162584Sitojun		}
54262584Sitojun	}
543279122Smarcel	if (!first)
544279122Smarcel		xo_close_list("same-source");
545279122Smarcel
546249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
54762584Sitojun		if (ip6stat.ip6s_sources_otherscope[i]) {
54862584Sitojun			if (first) {
549279122Smarcel				xo_open_list("different-scope");
550279122Smarcel				xo_emit("\tsource addresses of a different "
551279122Smarcel				    "scope\n");
55262584Sitojun				first = 0;
55362584Sitojun			}
554279122Smarcel			xo_open_instance("different-scope");
55562584Sitojun			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
556279122Smarcel			xo_close_instance("different-scope");
55762584Sitojun		}
55862584Sitojun	}
559279122Smarcel	if (!first)
560279122Smarcel		xo_close_list("different-scope");
561279122Smarcel
562249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
56362584Sitojun		if (ip6stat.ip6s_sources_deprecated[i]) {
56462584Sitojun			if (first) {
565279122Smarcel				xo_open_list("deprecated-source");
566279122Smarcel				xo_emit("\tdeprecated source addresses\n");
56762584Sitojun				first = 0;
56862584Sitojun			}
569279122Smarcel			xo_open_instance("deprecated-source");
57062584Sitojun			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
571279122Smarcel			xo_close_instance("deprecated-source");
57262584Sitojun		}
57362584Sitojun	}
574279122Smarcel	if (!first)
575279122Smarcel		xo_close_list("deprecated-source");
57662584Sitojun
577279122Smarcel	for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
578279122Smarcel		if (ip6stat.ip6s_sources_rule[i]) {
579279122Smarcel			if (first) {
580279122Smarcel				xo_open_list("rules-applied");
581279122Smarcel				xo_emit("\t{T:Source addresses selection "
582279122Smarcel				    "rule applied}:\n");
583279122Smarcel				first = 0;
584279122Smarcel			}
585279122Smarcel			xo_open_instance("rules-applied");
586279122Smarcel			xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
587279122Smarcel			    srcrule_str[i],
588279122Smarcel			    (uintmax_t)ip6stat.ip6s_sources_rule[i],
589279122Smarcel			    srcrule_str[i]);
590279122Smarcel			xo_close_instance("rules-applied");
591279122Smarcel		}
592125483Sume	}
593279122Smarcel	if (!first)
594279122Smarcel		xo_close_list("rules-applied");
595279122Smarcel
596279122Smarcel	xo_close_container("source-address-selection");
597279122Smarcel
59854263Sshin#undef p
59962584Sitojun#undef p1a
600279122Smarcel	xo_close_container(name);
60154263Sshin}
60254263Sshin
60354263Sshin/*
60454263Sshin * Dump IPv6 per-interface statistics based on RFC 2465.
60554263Sshin */
60654263Sshinvoid
60778314Sassarip6_ifstats(char *ifname)
60854263Sshin{
60954263Sshin	struct in6_ifreq ifr;
61054263Sshin	int s;
61154263Sshin
612279122Smarcel#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1)	\
613279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f,		\
614279122Smarcel	    plural(ifr.ifr_ifru.ifru_stat.f))
615279122Smarcel
61654263Sshin	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
617279122Smarcel		xo_warn("Warning: socket(AF_INET6)");
61854263Sshin		return;
61954263Sshin	}
62054263Sshin
621317555Sasomers	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
62254263Sshin	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
623270349Smarkj		if (errno != EPFNOSUPPORT)
624279122Smarcel			xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
62554263Sshin		goto end;
62654263Sshin	}
62754263Sshin
628279122Smarcel	xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
62954263Sshin
630279122Smarcel	xo_open_instance("ip6-interface-statistics");
631279122Smarcel	xo_emit("{ke:name/%s}", ifr.ifr_name);
63254263Sshin
633279122Smarcel	p(ifs6_in_receive, "\t{:received-packets/%ju} "
634279122Smarcel	    "{N:/total input datagram%s}\n");
635279122Smarcel	p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
636279122Smarcel	    "{N:/datagram%s with invalid header received}\n");
637279122Smarcel	p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
638279122Smarcel	    "{N:/datagram%s exceeded MTU received}\n");
639279122Smarcel	p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
640279122Smarcel	    "{N:/datagram%s with no route received}\n");
641279122Smarcel	p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
642279122Smarcel	    "{N:/datagram%s with invalid dst received}\n");
643279122Smarcel	p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
644279122Smarcel	    "{N:/datagram%s with unknown proto received}\n");
645279122Smarcel	p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
646279122Smarcel	    "{N:/truncated datagram%s received}\n");
647279122Smarcel	p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
648279122Smarcel	    "{N:/input datagram%s discarded}\n");
649279122Smarcel 	p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
650279122Smarcel	    "{N:/datagram%s delivered to an upper layer protocol}\n");
651279122Smarcel	p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
652279122Smarcel	    "{N:/datagram%s forwarded to this interface}\n");
653279122Smarcel 	p(ifs6_out_request, "\t{:sent-packets/%ju} "
654279122Smarcel	    "{N:/datagram%s sent from an upper layer protocol}\n");
655279122Smarcel	p(ifs6_out_discard, "\t{:discard-packets/%ju} "
656279122Smarcel	    "{N:/total discarded output datagram%s}\n");
657279122Smarcel	p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
658279122Smarcel	    "{N:/output datagram%s fragmented}\n");
659279122Smarcel	p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
660279122Smarcel	    "{N:/output datagram%s failed on fragment}\n");
661279122Smarcel	p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
662279122Smarcel	    "{N:/output datagram%s succeeded on fragment}\n");
663279122Smarcel	p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
664279122Smarcel	    "{N:/incoming datagram%s fragmented}\n");
665279122Smarcel	p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
666279122Smarcel	    "{N:/datagram%s reassembled}\n");
667279122Smarcel	p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
668279122Smarcel	    "{N:/datagram%s failed on reassembly}\n");
669279122Smarcel	p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
670279122Smarcel	    "{N:/multicast datagram%s received}\n");
671279122Smarcel	p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
672279122Smarcel	    "{N:/multicast datagram%s sent}\n");
673279122Smarcel
674279122Smarcel end:
675279122Smarcel	xo_close_instance("ip6-interface-statistics");
676279122Smarcel 	close(s);
677279122Smarcel
67854263Sshin#undef p
67954263Sshin}
68054263Sshin
681102975Sdwmalonestatic	const char *icmp6names[] = {
68254263Sshin	"#0",
68354263Sshin	"unreach",
68454263Sshin	"packet too big",
68554263Sshin	"time exceed",
68654263Sshin	"parameter problem",
68754263Sshin	"#5",
68854263Sshin	"#6",
68954263Sshin	"#7",
69054263Sshin	"#8",
69154263Sshin	"#9",
69254263Sshin	"#10",
69354263Sshin	"#11",
69454263Sshin	"#12",
69554263Sshin	"#13",
69654263Sshin	"#14",
69754263Sshin	"#15",
69854263Sshin	"#16",
69954263Sshin	"#17",
70054263Sshin	"#18",
701175061Sobrien	"#19",
70254263Sshin	"#20",
70354263Sshin	"#21",
70454263Sshin	"#22",
70554263Sshin	"#23",
70654263Sshin	"#24",
70754263Sshin	"#25",
70854263Sshin	"#26",
70954263Sshin	"#27",
71054263Sshin	"#28",
711175061Sobrien	"#29",
71254263Sshin	"#30",
71354263Sshin	"#31",
71454263Sshin	"#32",
71554263Sshin	"#33",
71654263Sshin	"#34",
71754263Sshin	"#35",
71854263Sshin	"#36",
71954263Sshin	"#37",
72054263Sshin	"#38",
721175061Sobrien	"#39",
72254263Sshin	"#40",
72354263Sshin	"#41",
72454263Sshin	"#42",
72554263Sshin	"#43",
72654263Sshin	"#44",
72754263Sshin	"#45",
72854263Sshin	"#46",
72954263Sshin	"#47",
73054263Sshin	"#48",
731175061Sobrien	"#49",
73254263Sshin	"#50",
73354263Sshin	"#51",
73454263Sshin	"#52",
73554263Sshin	"#53",
73654263Sshin	"#54",
73754263Sshin	"#55",
73854263Sshin	"#56",
73954263Sshin	"#57",
74054263Sshin	"#58",
741175061Sobrien	"#59",
74254263Sshin	"#60",
74354263Sshin	"#61",
74454263Sshin	"#62",
74554263Sshin	"#63",
74654263Sshin	"#64",
74754263Sshin	"#65",
74854263Sshin	"#66",
74954263Sshin	"#67",
75054263Sshin	"#68",
751175061Sobrien	"#69",
75254263Sshin	"#70",
75354263Sshin	"#71",
75454263Sshin	"#72",
75554263Sshin	"#73",
75654263Sshin	"#74",
75754263Sshin	"#75",
75854263Sshin	"#76",
75954263Sshin	"#77",
76054263Sshin	"#78",
761175061Sobrien	"#79",
76254263Sshin	"#80",
76354263Sshin	"#81",
76454263Sshin	"#82",
76554263Sshin	"#83",
76654263Sshin	"#84",
76754263Sshin	"#85",
76854263Sshin	"#86",
76954263Sshin	"#87",
77054263Sshin	"#88",
771175061Sobrien	"#89",
77254263Sshin	"#80",
77354263Sshin	"#91",
77454263Sshin	"#92",
77554263Sshin	"#93",
77654263Sshin	"#94",
77754263Sshin	"#95",
77854263Sshin	"#96",
77954263Sshin	"#97",
78054263Sshin	"#98",
781175061Sobrien	"#99",
78254263Sshin	"#100",
78354263Sshin	"#101",
78454263Sshin	"#102",
78554263Sshin	"#103",
78654263Sshin	"#104",
78754263Sshin	"#105",
78854263Sshin	"#106",
78954263Sshin	"#107",
79054263Sshin	"#108",
791175061Sobrien	"#109",
79254263Sshin	"#110",
79354263Sshin	"#111",
79454263Sshin	"#112",
79554263Sshin	"#113",
79654263Sshin	"#114",
79754263Sshin	"#115",
79854263Sshin	"#116",
79954263Sshin	"#117",
80054263Sshin	"#118",
801175061Sobrien	"#119",
80254263Sshin	"#120",
80354263Sshin	"#121",
80454263Sshin	"#122",
80554263Sshin	"#123",
80654263Sshin	"#124",
80754263Sshin	"#125",
80854263Sshin	"#126",
80954263Sshin	"#127",
81054263Sshin	"echo",
811175061Sobrien	"echo reply",
81254263Sshin	"multicast listener query",
813191652Sbms	"MLDv1 listener report",
814191652Sbms	"MLDv1 listener done",
81554263Sshin	"router solicitation",
81677565Sdd	"router advertisement",
81754263Sshin	"neighbor solicitation",
81877565Sdd	"neighbor advertisement",
81954263Sshin	"redirect",
82054263Sshin	"router renumbering",
82154263Sshin	"node information request",
82254263Sshin	"node information reply",
82378540Ssumikawa	"inverse neighbor solicitation",
82478540Ssumikawa	"inverse neighbor advertisement",
825191652Sbms	"MLDv2 listener report",
82654263Sshin	"#144",
82754263Sshin	"#145",
82854263Sshin	"#146",
82954263Sshin	"#147",
83054263Sshin	"#148",
831175061Sobrien	"#149",
83254263Sshin	"#150",
83354263Sshin	"#151",
83454263Sshin	"#152",
83554263Sshin	"#153",
83654263Sshin	"#154",
83754263Sshin	"#155",
83854263Sshin	"#156",
83954263Sshin	"#157",
84054263Sshin	"#158",
841175061Sobrien	"#159",
84254263Sshin	"#160",
84354263Sshin	"#161",
84454263Sshin	"#162",
84554263Sshin	"#163",
84654263Sshin	"#164",
84754263Sshin	"#165",
84854263Sshin	"#166",
84954263Sshin	"#167",
85054263Sshin	"#168",
851175061Sobrien	"#169",
85254263Sshin	"#170",
85354263Sshin	"#171",
85454263Sshin	"#172",
85554263Sshin	"#173",
85654263Sshin	"#174",
85754263Sshin	"#175",
85854263Sshin	"#176",
85954263Sshin	"#177",
86054263Sshin	"#178",
861175061Sobrien	"#179",
86254263Sshin	"#180",
86354263Sshin	"#181",
86454263Sshin	"#182",
86554263Sshin	"#183",
86654263Sshin	"#184",
86754263Sshin	"#185",
86854263Sshin	"#186",
86954263Sshin	"#187",
87054263Sshin	"#188",
871175061Sobrien	"#189",
87254263Sshin	"#180",
87354263Sshin	"#191",
87454263Sshin	"#192",
87554263Sshin	"#193",
87654263Sshin	"#194",
87754263Sshin	"#195",
87854263Sshin	"#196",
87954263Sshin	"#197",
88054263Sshin	"#198",
881175061Sobrien	"#199",
88254263Sshin	"#200",
88354263Sshin	"#201",
88454263Sshin	"#202",
88554263Sshin	"#203",
88654263Sshin	"#204",
88754263Sshin	"#205",
88854263Sshin	"#206",
88954263Sshin	"#207",
89054263Sshin	"#208",
891175061Sobrien	"#209",
89254263Sshin	"#210",
89354263Sshin	"#211",
89454263Sshin	"#212",
89554263Sshin	"#213",
89654263Sshin	"#214",
89754263Sshin	"#215",
89854263Sshin	"#216",
89954263Sshin	"#217",
90054263Sshin	"#218",
901175061Sobrien	"#219",
90254263Sshin	"#220",
90354263Sshin	"#221",
90454263Sshin	"#222",
90554263Sshin	"#223",
90654263Sshin	"#224",
90754263Sshin	"#225",
90854263Sshin	"#226",
90954263Sshin	"#227",
91054263Sshin	"#228",
911175061Sobrien	"#229",
91254263Sshin	"#230",
91354263Sshin	"#231",
91454263Sshin	"#232",
91554263Sshin	"#233",
91654263Sshin	"#234",
91754263Sshin	"#235",
91854263Sshin	"#236",
91954263Sshin	"#237",
92054263Sshin	"#238",
921175061Sobrien	"#239",
92254263Sshin	"#240",
92354263Sshin	"#241",
92454263Sshin	"#242",
92554263Sshin	"#243",
92654263Sshin	"#244",
92754263Sshin	"#245",
92854263Sshin	"#246",
92954263Sshin	"#247",
93054263Sshin	"#248",
931175061Sobrien	"#249",
93254263Sshin	"#250",
93354263Sshin	"#251",
93454263Sshin	"#252",
93554263Sshin	"#253",
93654263Sshin	"#254",
93754263Sshin	"#255",
93854263Sshin};
93954263Sshin
94054263Sshin/*
94154263Sshin * Dump ICMP6 statistics.
94254263Sshin */
94354263Sshinvoid
944171465Sjhbicmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
94554263Sshin{
946287649Smarkj	struct icmp6stat icmp6stat;
94795637Smarkm	int i, first;
94854263Sshin
949287649Smarkj	if (fetch_stats("net.inet6.icmp6.stats", off, &icmp6stat,
950287649Smarkj	    sizeof(icmp6stat), kread_counters) != 0)
951287649Smarkj		return;
95278931Sume
953279122Smarcel	xo_emit("{T:/%s}:\n", name);
954279122Smarcel	xo_open_container(name);
95554263Sshin
95654263Sshin#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
957279122Smarcel	xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
958187134Smaxim#define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
959279122Smarcel	xo_emit(m, (uintmax_t)icmp6stat.f)
96054263Sshin
961279122Smarcel	p(icp6s_error, "\t{:icmp6-calls/%ju} "
962279122Smarcel	    "{N:/call%s to icmp6_error}\n");
963279122Smarcel	p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
964279122Smarcel	    "{N:/error%s not generated in response to an icmp6 message}\n");
965279122Smarcel	p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
966279122Smarcel	    "{N:/error%s not generated because of rate limitation}\n");
967175061Sobrien#define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
96878540Ssumikawa	for (first = 1, i = 0; i < NELEM; i++)
96954263Sshin		if (icmp6stat.icp6s_outhist[i] != 0) {
97054263Sshin			if (first) {
971279122Smarcel				xo_open_list("output-histogram");
972279122Smarcel				xo_emit("\t{T:Output histogram}:\n");
97354263Sshin				first = 0;
97454263Sshin			}
975279122Smarcel			xo_open_instance("output-histogram");
976279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
977279122Smarcel			    icmp6names[i],
978160787Syar			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
979279122Smarcel			xo_close_instance("output-histogram");
98054263Sshin		}
981279122Smarcel	if (!first)
982279122Smarcel		xo_close_list("output-histogram");
98378540Ssumikawa#undef NELEM
984279122Smarcel
985279122Smarcel	p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
986279122Smarcel	    "{N:/message%s with bad code fields}\n");
987279122Smarcel	p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
988279122Smarcel	    "{N:/message%s < minimum length}\n");
989279122Smarcel	p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
990279122Smarcel	    "{N:/bad checksum%s}\n");
991279122Smarcel	p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
992279122Smarcel	    "{N:/message%s with bad length}\n");
993175061Sobrien#define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
99478540Ssumikawa	for (first = 1, i = 0; i < NELEM; i++)
99554263Sshin		if (icmp6stat.icp6s_inhist[i] != 0) {
99654263Sshin			if (first) {
997279122Smarcel				xo_open_list("input-histogram");
998279122Smarcel				xo_emit("\t{T:Input histogram}:\n");
99954263Sshin				first = 0;
100054263Sshin			}
1001279122Smarcel			xo_open_instance("input-histogram");
1002279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1003279122Smarcel			    icmp6names[i],
1004160787Syar			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
1005279122Smarcel			xo_close_instance("input-histogram");
100654263Sshin		}
1007279122Smarcel	if (!first)
1008279122Smarcel		xo_close_list("input-histogram");
100978540Ssumikawa#undef NELEM
1010279122Smarcel	xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1011279122Smarcel	xo_open_container("errors");
1012279122Smarcel	p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1013279122Smarcel	    "{N:/no route}\n");
1014279122Smarcel	p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1015279122Smarcel	    "{N:/administratively prohibited}\n");
1016279122Smarcel	p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1017279122Smarcel	    "{N:/beyond scope}\n");
1018279122Smarcel	p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1019279122Smarcel	    "{N:/address unreachable}\n");
1020279122Smarcel	p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1021279122Smarcel	    "{N:/port unreachable}\n");
1022279122Smarcel	p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1023279122Smarcel	    "{N:/packet too big}\n");
1024279122Smarcel	p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1025279122Smarcel	    "{N:/time exceed transit}\n");
1026279122Smarcel	p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1027279122Smarcel	    "{N:/time exceed reassembly}\n");
1028279122Smarcel	p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1029279122Smarcel	    "{N:/erroneous header field}\n");
1030279122Smarcel	p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1031279122Smarcel	    "{N:/unrecognized next header}\n");
1032279122Smarcel	p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1033279122Smarcel	    "{N:/unrecognized option}\n");
1034279122Smarcel	p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1035279122Smarcel	    "{N:/redirect}\n");
1036279122Smarcel	p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
103762584Sitojun
1038279122Smarcel	p(icp6s_reflect, "\t{:reflect/%ju} "
1039279122Smarcel	    "{N:/message response%s generated}\n");
1040279122Smarcel	p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1041279122Smarcel	    "{N:/message%s with too many ND options}\n");
1042279122Smarcel	p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1043279122Smarcel	    "{N:/message%s with bad ND options}\n");
1044279122Smarcel	p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1045279122Smarcel	    "{N:/bad neighbor solicitation message%s}\n");
1046279122Smarcel	p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1047279122Smarcel	    "{N:/bad neighbor advertisement message%s}\n");
1048279122Smarcel	p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1049279122Smarcel	    "{N:/bad router solicitation message%s}\n");
1050279122Smarcel	p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1051279122Smarcel	    "{N:/bad router advertisement message%s}\n");
1052279122Smarcel	p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1053279122Smarcel	    "{N:/bad redirect message%s}\n");
1054279122Smarcel	xo_close_container("errors");
1055279122Smarcel	p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
105654263Sshin#undef p
105754263Sshin#undef p_5
1058279122Smarcel	xo_close_container(name);
105954263Sshin}
106054263Sshin
106154263Sshin/*
106254263Sshin * Dump ICMPv6 per-interface statistics based on RFC 2466.
106354263Sshin */
106454263Sshinvoid
106578314Sassaricmp6_ifstats(char *ifname)
106654263Sshin{
106754263Sshin	struct in6_ifreq ifr;
106854263Sshin	int s;
106954263Sshin
1070279122Smarcel#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1071279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1072279122Smarcel	    plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1073279122Smarcel#define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1074279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1075279122Smarcel	    pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1076279122Smarcel
107754263Sshin	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1078279122Smarcel		xo_warn("Warning: socket(AF_INET6)");
107954263Sshin		return;
108054263Sshin	}
108154263Sshin
1082317555Sasomers	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
108354263Sshin	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1084270349Smarkj		if (errno != EPFNOSUPPORT)
1085279122Smarcel			xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
108654263Sshin		goto end;
108754263Sshin	}
108854263Sshin
1089279122Smarcel	xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
109054263Sshin
1091279122Smarcel	xo_open_instance("icmp6-interface-statistics");
1092279122Smarcel	xo_emit("{ke:name/%s}", ifr.ifr_name);
1093279122Smarcel	p(ifs6_in_msg, "\t{:received-packets/%ju} "
1094279122Smarcel	    "{N:/total input message%s}\n");
1095279122Smarcel	p(ifs6_in_error, "\t{:received-errors/%ju} "
1096279122Smarcel	    "{N:/total input error message%s}\n");
1097279122Smarcel	p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1098279122Smarcel	    "{N:/input destination unreachable error%s}\n");
1099279122Smarcel	p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1100279122Smarcel	    "{N:/input administratively prohibited error%s}\n");
1101279122Smarcel	p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1102279122Smarcel	    "{N:/input time exceeded error%s}\n");
1103279122Smarcel	p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1104279122Smarcel	    "{N:/input parameter problem error%s}\n");
1105279122Smarcel	p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1106279122Smarcel	    "{N:/input packet too big error%s}\n");
1107279122Smarcel	p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1108279122Smarcel	    "{N:/input echo request%s}\n");
1109279122Smarcel	p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1110279122Smarcel	    "{N:/input echo repl%s}\n");
1111279122Smarcel	p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1112279122Smarcel	    "{N:/input router solicitation%s}\n");
1113279122Smarcel	p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1114279122Smarcel	    "{N:/input router advertisement%s}\n");
1115279122Smarcel	p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1116279122Smarcel	    "{N:/input neighbor solicitation%s}\n");
1117279122Smarcel	p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1118279122Smarcel	    "{N:/input neighbor advertisement%s}\n");
1119279122Smarcel	p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1120279122Smarcel	    "{N:/input redirect%s}\n");
1121279122Smarcel	p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1122279122Smarcel	    "{N:/input MLD quer%s}\n");
1123279122Smarcel	p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1124279122Smarcel	    "{N:/input MLD report%s}\n");
1125279122Smarcel	p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1126279122Smarcel	    "{N:/input MLD done%s}\n");
112754263Sshin
1128279122Smarcel	p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1129279122Smarcel	    "{N:/total output message%s}\n");
1130279122Smarcel	p(ifs6_out_error, "\t{:sent-errors/%ju} "
1131279122Smarcel	    "{N:/total output error message%s}\n");
1132279122Smarcel	p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1133279122Smarcel	    "{N:/output destination unreachable error%s}\n");
1134279122Smarcel	p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1135279122Smarcel	    "{N:/output administratively prohibited error%s}\n");
1136279122Smarcel	p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1137279122Smarcel	    "{N:/output time exceeded error%s}\n");
1138279122Smarcel	p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1139279122Smarcel	    "{N:/output parameter problem error%s}\n");
1140279122Smarcel	p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1141279122Smarcel	    "{N:/output packet too big error%s}\n");
1142279122Smarcel	p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1143279122Smarcel	    "{N:/output echo request%s}\n");
1144279122Smarcel	p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1145279122Smarcel	    "{N:/output echo repl%s}\n");
1146279122Smarcel	p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1147279122Smarcel	    "{N:/output router solicitation%s}\n");
1148279122Smarcel	p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1149279122Smarcel	    "{N:/output router advertisement%s}\n");
1150279122Smarcel	p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1151279122Smarcel	    "{N:/output neighbor solicitation%s}\n");
1152279122Smarcel	p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1153279122Smarcel	    "{N:/output neighbor advertisement%s}\n");
1154279122Smarcel	p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1155279122Smarcel	    "{N:/output redirect%s}\n");
1156279122Smarcel	p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1157279122Smarcel	    "{N:/output MLD quer%s}\n");
1158279122Smarcel	p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1159279122Smarcel	    "{N:/output MLD report%s}\n");
1160279122Smarcel	p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1161279122Smarcel	    "{N:/output MLD done%s}\n");
1162279122Smarcel
1163279122Smarcelend:
1164279122Smarcel	xo_close_instance("icmp6-interface-statistics");
116554263Sshin	close(s);
116654263Sshin#undef p
116754263Sshin}
116854263Sshin
116954263Sshin/*
117054263Sshin * Dump PIM statistics structure.
117154263Sshin */
117254263Sshinvoid
1173171465Sjhbpim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
117454263Sshin{
1175287649Smarkj	struct pim6stat pim6stat;
117654263Sshin
1177287649Smarkj	if (fetch_stats("net.inet6.pim.stats", off, &pim6stat,
1178287649Smarkj	    sizeof(pim6stat), kread) != 0)
1179287649Smarkj		return;
1180171465Sjhb
1181279122Smarcel	xo_emit("{T:/%s}:\n", name);
1182279122Smarcel	xo_open_container(name);
118354263Sshin
118454263Sshin#define	p(f, m) if (pim6stat.f || sflag <= 1) \
1185279122Smarcel	xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1186279122Smarcel
1187279122Smarcel	p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1188279122Smarcel	    "{N:/message%s received}\n");
1189279122Smarcel	p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1190279122Smarcel	    "{N:/message%s received with too few bytes}\n");
1191279122Smarcel	p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1192279122Smarcel	    "{N:/message%s received with bad checksum}\n");
1193279122Smarcel	p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1194279122Smarcel	    "{N:/message%s received with bad version}\n");
1195279122Smarcel	p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1196279122Smarcel	    "{N:/register%s received}\n");
1197279122Smarcel	p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1198279122Smarcel	    "{N:/bad register%s received}\n");
1199279122Smarcel	p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1200279122Smarcel	    "{N:/register%s sent}\n");
120154263Sshin#undef p
1202279122Smarcel	xo_close_container(name);
120354263Sshin}
120454263Sshin
120554263Sshin/*
120678064Sume * Dump raw ip6 statistics structure.
120778064Sume */
120878064Sumevoid
1209171465Sjhbrip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
121078064Sume{
1211287649Smarkj	struct rip6stat rip6stat;
121278064Sume	u_quad_t delivered;
121378064Sume
1214287649Smarkj	if (fetch_stats("net.inet6.ip6.rip6stats", off, &rip6stat,
1215287649Smarkj	    sizeof(rip6stat), kread_counters) != 0)
1216287649Smarkj		return;
121778064Sume
1218279122Smarcel	xo_emit("{T:/%s}:\n", name);
1219279122Smarcel	xo_open_container(name);
122078064Sume
122178064Sume#define	p(f, m) if (rip6stat.f || sflag <= 1) \
1222279122Smarcel	xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1223279122Smarcel
1224279122Smarcel	p(rip6s_ipackets, "\t{:received-packets/%ju} "
1225279122Smarcel	    "{N:/message%s received}\n");
1226279122Smarcel	p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1227279122Smarcel	    "{N:/checksum calculation%s on inbound}\n");
1228279122Smarcel	p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1229279122Smarcel	    "{N:/message%s with bad checksum}\n");
1230279122Smarcel	p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1231279122Smarcel	    "{N:/message%s dropped due to no socket}\n");
1232279122Smarcel	p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1233279122Smarcel	    "{N:/multicast message%s dropped due to no socket}\n");
1234279122Smarcel	p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1235279122Smarcel	    "{N:/message%s dropped due to full socket buffers}\n");
123678064Sume	delivered = rip6stat.rip6s_ipackets -
123778064Sume		    rip6stat.rip6s_badsum -
123878064Sume		    rip6stat.rip6s_nosock -
123978064Sume		    rip6stat.rip6s_nosockmcast -
124078064Sume		    rip6stat.rip6s_fullsock;
124178064Sume	if (delivered || sflag <= 1)
1242279122Smarcel		xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1243279122Smarcel		    (uintmax_t)delivered);
1244279122Smarcel	p(rip6s_opackets, "\t{:sent-packets/%ju} "
1245279122Smarcel	    "{N:/datagram%s output}\n");
124678064Sume#undef p
1247279122Smarcel	xo_close_container(name);
124878064Sume}
124978064Sume
125078064Sume/*
125154263Sshin * Pretty print an Internet address (net address + port).
125278238Sassar * Take numeric_addr and numeric_port into consideration.
125354263Sshin */
1254175061Sobrien#define	GETSERVBYPORT6(port, proto, ret)\
125554263Sshin{\
125654263Sshin	if (strcmp((proto), "tcp6") == 0)\
125754263Sshin		(ret) = getservbyport((int)(port), "tcp");\
125854263Sshin	else if (strcmp((proto), "udp6") == 0)\
125954263Sshin		(ret) = getservbyport((int)(port), "udp");\
126054263Sshin	else\
126154263Sshin		(ret) = getservbyport((int)(port), (proto));\
126254263Sshin};
126354263Sshin
126454263Sshinvoid
1265279122Smarcelinet6print(const char *container, struct in6_addr *in6, int port,
1266279122Smarcel    const char *proto, int numeric)
126754263Sshin{
126854263Sshin	struct servent *sp = 0;
126954263Sshin	char line[80], *cp;
127054263Sshin	int width;
1271311670Sdelphij	size_t alen, plen;
127254263Sshin
1273279122Smarcel	if (container)
1274279122Smarcel		xo_open_container(container);
1275279122Smarcel
1276311670Sdelphij	snprintf(line, sizeof(line), "%.*s.",
1277311670Sdelphij	    Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1278279122Smarcel	    inet6name(in6));
1279311670Sdelphij	alen = strlen(line);
1280311670Sdelphij	cp = line + alen;
128154263Sshin	if (!numeric && port)
128254263Sshin		GETSERVBYPORT6(port, proto, sp);
128354263Sshin	if (sp || port == 0)
1284311670Sdelphij		snprintf(cp, sizeof(line) - alen,
1285311670Sdelphij		    "%.15s", sp ? sp->s_name : "*");
128654263Sshin	else
1287311670Sdelphij		snprintf(cp, sizeof(line) - alen,
1288311670Sdelphij		    "%d", ntohs((u_short)port));
128983200Sru	width = Wflag ? 45 : Aflag ? 18 : 22;
1290279122Smarcel
1291279122Smarcel	xo_emit("{d:target/%-*.*s} ", width, width, line);
1292279122Smarcel
1293311674Sume	plen = strlen(cp);
1294311670Sdelphij	alen--;
1295279122Smarcel	xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1296279122Smarcel	    plen, cp);
1297279122Smarcel
1298279122Smarcel	if (container)
1299279122Smarcel		xo_close_container(container);
130054263Sshin}
130154263Sshin
130254263Sshin/*
130354263Sshin * Construct an Internet address representation.
130478238Sassar * If the numeric_addr has been supplied, give
130554263Sshin * numeric value, otherwise try for symbolic name.
130654263Sshin */
130754263Sshin
130854263Sshinchar *
1309355869Sbzinet6name(struct in6_addr *ia6)
131054263Sshin{
1311254459Shrs	struct sockaddr_in6 sin6;
1312254459Shrs	char hbuf[NI_MAXHOST], *cp;
1313311670Sdelphij	static char line[NI_MAXHOST];
131474262Sbrian	static char domain[MAXHOSTNAMELEN];
131554263Sshin	static int first = 1;
1316254459Shrs	int flags, error;
131754263Sshin
1318355869Sbz	if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
1319254459Shrs		strcpy(line, "*");
1320254459Shrs		return (line);
1321254459Shrs	}
132278238Sassar	if (first && !numeric_addr) {
132354263Sshin		first = 0;
1324311670Sdelphij		if (gethostname(domain, sizeof(domain)) == 0 &&
1325229403Sed		    (cp = strchr(domain, '.')))
1326311670Sdelphij			strlcpy(domain, cp + 1, sizeof(domain));
132754263Sshin		else
132854263Sshin			domain[0] = 0;
132954263Sshin	}
1330254459Shrs	memset(&sin6, 0, sizeof(sin6));
1331355869Sbz	memcpy(&sin6.sin6_addr, ia6, sizeof(*ia6));
1332254459Shrs	sin6.sin6_family = AF_INET6;
1333355869Sbz	/* XXX: ia6.s6_addr[2] can contain scopeid. */
1334254459Shrs	in6_fillscopeid(&sin6);
1335254459Shrs	flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1336254459Shrs	error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1337254459Shrs	    sizeof(hbuf), NULL, 0, flags);
1338254459Shrs	if (error == 0) {
1339254459Shrs		if ((flags & NI_NUMERICHOST) == 0 &&
1340254459Shrs		    (cp = strchr(hbuf, '.')) &&
1341254459Shrs		    !strcmp(cp + 1, domain))
1342254459Shrs			*cp = 0;
1343311670Sdelphij		strlcpy(line, hbuf, sizeof(line));
1344254459Shrs	} else {
1345254459Shrs		/* XXX: this should not happen. */
1346311670Sdelphij		snprintf(line, sizeof(line), "%s",
1347254459Shrs			inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
134854263Sshin				sizeof(ntop_buf)));
1349254459Shrs	}
135054263Sshin	return (line);
135154263Sshin}
135264342Sume#endif /*INET6*/
1353