inet6.c revision 279122
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: head/usr.bin/netstat/inet6.c 279122 2015-02-21 23:47:20Z marcel $");
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>
4778064Sume#include <sys/sysctl.h>
4854263Sshin
4954263Sshin#include <net/route.h>
5054263Sshin#include <net/if.h>
5154263Sshin#include <net/if_var.h>
5254263Sshin#include <netinet/in.h>
5354263Sshin#include <netinet/ip6.h>
5454263Sshin#include <netinet/icmp6.h>
5554263Sshin#include <netinet/in_systm.h>
5654263Sshin#include <netinet6/in6_pcb.h>
5754263Sshin#include <netinet6/in6_var.h>
5854263Sshin#include <netinet6/ip6_var.h>
5954263Sshin#include <netinet6/pim6_var.h>
6078064Sume#include <netinet6/raw_ip6.h>
6154263Sshin
6254263Sshin#include <arpa/inet.h>
6354263Sshin#include <netdb.h>
6454263Sshin
65166952Sbms#include <err.h>
66160787Syar#include <stdint.h>
6754263Sshin#include <stdio.h>
68279122Smarcel#include <stdbool.h>
69160373Sjulian#include <errno.h>
7054263Sshin#include <string.h>
7154263Sshin#include <unistd.h>
72279122Smarcel#include <libxo/xo.h>
7354263Sshin#include "netstat.h"
7454263Sshin
7554263Sshinstruct	socket sockb;
7654263Sshin
77132671Scharnierchar	*inet6name(struct in6_addr *);
7854263Sshin
7954263Sshinstatic char ntop_buf[INET6_ADDRSTRLEN];
8054263Sshin
81102975Sdwmalonestatic	const char *ip6nh[] = {
8254263Sshin	"hop by hop",
8354263Sshin	"ICMP",
8454263Sshin	"IGMP",
8554263Sshin	"#3",
8654263Sshin	"IP",
8754263Sshin	"#5",
8854263Sshin	"TCP",
8954263Sshin	"#7",
9054263Sshin	"#8",
9154263Sshin	"#9",
9254263Sshin	"#10",
9354263Sshin	"#11",
9454263Sshin	"#12",
9554263Sshin	"#13",
9654263Sshin	"#14",
9754263Sshin	"#15",
9854263Sshin	"#16",
9954263Sshin	"UDP",
10054263Sshin	"#18",
101175061Sobrien	"#19",
10254263Sshin	"#20",
10354263Sshin	"#21",
10454263Sshin	"IDP",
10554263Sshin	"#23",
10654263Sshin	"#24",
10754263Sshin	"#25",
10854263Sshin	"#26",
10954263Sshin	"#27",
11054263Sshin	"#28",
111175061Sobrien	"TP",
11254263Sshin	"#30",
11354263Sshin	"#31",
11454263Sshin	"#32",
11554263Sshin	"#33",
11654263Sshin	"#34",
11754263Sshin	"#35",
11854263Sshin	"#36",
11954263Sshin	"#37",
12054263Sshin	"#38",
121175061Sobrien	"#39",
12254263Sshin	"#40",
12354263Sshin	"IP6",
12454263Sshin	"#42",
12554263Sshin	"routing",
12654263Sshin	"fragment",
12754263Sshin	"#45",
12854263Sshin	"#46",
12954263Sshin	"#47",
13054263Sshin	"#48",
131175061Sobrien	"#49",
13254263Sshin	"ESP",
13354263Sshin	"AH",
13454263Sshin	"#52",
13554263Sshin	"#53",
13654263Sshin	"#54",
13754263Sshin	"#55",
13854263Sshin	"#56",
13954263Sshin	"#57",
14054263Sshin	"ICMP6",
141175061Sobrien	"no next header",
14254263Sshin	"destination option",
14354263Sshin	"#61",
144125482Sume	"mobility",
14554263Sshin	"#63",
14654263Sshin	"#64",
14754263Sshin	"#65",
14854263Sshin	"#66",
14954263Sshin	"#67",
15054263Sshin	"#68",
151175061Sobrien	"#69",
15254263Sshin	"#70",
15354263Sshin	"#71",
15454263Sshin	"#72",
15554263Sshin	"#73",
15654263Sshin	"#74",
15754263Sshin	"#75",
15854263Sshin	"#76",
15954263Sshin	"#77",
16054263Sshin	"#78",
161175061Sobrien	"#79",
16254263Sshin	"ISOIP",
16354263Sshin	"#81",
16454263Sshin	"#82",
16554263Sshin	"#83",
16654263Sshin	"#84",
16754263Sshin	"#85",
16854263Sshin	"#86",
16954263Sshin	"#87",
17054263Sshin	"#88",
171175061Sobrien	"OSPF",
17254263Sshin	"#80",
17354263Sshin	"#91",
17454263Sshin	"#92",
17554263Sshin	"#93",
17654263Sshin	"#94",
17754263Sshin	"#95",
17854263Sshin	"#96",
17954263Sshin	"Ethernet",
18054263Sshin	"#98",
181175061Sobrien	"#99",
18254263Sshin	"#100",
18354263Sshin	"#101",
18454263Sshin	"#102",
18554263Sshin	"PIM",
18654263Sshin	"#104",
18754263Sshin	"#105",
18854263Sshin	"#106",
18954263Sshin	"#107",
19054263Sshin	"#108",
191175061Sobrien	"#109",
19254263Sshin	"#110",
19354263Sshin	"#111",
19454263Sshin	"#112",
19554263Sshin	"#113",
19654263Sshin	"#114",
19754263Sshin	"#115",
19854263Sshin	"#116",
19954263Sshin	"#117",
20054263Sshin	"#118",
201175061Sobrien	"#119",
20254263Sshin	"#120",
20354263Sshin	"#121",
20454263Sshin	"#122",
20554263Sshin	"#123",
20654263Sshin	"#124",
20754263Sshin	"#125",
20854263Sshin	"#126",
20954263Sshin	"#127",
21054263Sshin	"#128",
211175061Sobrien	"#129",
21254263Sshin	"#130",
21354263Sshin	"#131",
21454263Sshin	"#132",
21554263Sshin	"#133",
21654263Sshin	"#134",
21754263Sshin	"#135",
21854263Sshin	"#136",
21954263Sshin	"#137",
22054263Sshin	"#138",
221175061Sobrien	"#139",
22254263Sshin	"#140",
22354263Sshin	"#141",
22454263Sshin	"#142",
22554263Sshin	"#143",
22654263Sshin	"#144",
22754263Sshin	"#145",
22854263Sshin	"#146",
22954263Sshin	"#147",
23054263Sshin	"#148",
231175061Sobrien	"#149",
23254263Sshin	"#150",
23354263Sshin	"#151",
23454263Sshin	"#152",
23554263Sshin	"#153",
23654263Sshin	"#154",
23754263Sshin	"#155",
23854263Sshin	"#156",
23954263Sshin	"#157",
24054263Sshin	"#158",
241175061Sobrien	"#159",
24254263Sshin	"#160",
24354263Sshin	"#161",
24454263Sshin	"#162",
24554263Sshin	"#163",
24654263Sshin	"#164",
24754263Sshin	"#165",
24854263Sshin	"#166",
24954263Sshin	"#167",
25054263Sshin	"#168",
251175061Sobrien	"#169",
25254263Sshin	"#170",
25354263Sshin	"#171",
25454263Sshin	"#172",
25554263Sshin	"#173",
25654263Sshin	"#174",
25754263Sshin	"#175",
25854263Sshin	"#176",
25954263Sshin	"#177",
26054263Sshin	"#178",
261175061Sobrien	"#179",
26254263Sshin	"#180",
26354263Sshin	"#181",
26454263Sshin	"#182",
26554263Sshin	"#183",
26654263Sshin	"#184",
26754263Sshin	"#185",
26854263Sshin	"#186",
26954263Sshin	"#187",
27054263Sshin	"#188",
271175061Sobrien	"#189",
27254263Sshin	"#180",
27354263Sshin	"#191",
27454263Sshin	"#192",
27554263Sshin	"#193",
27654263Sshin	"#194",
27754263Sshin	"#195",
27854263Sshin	"#196",
27954263Sshin	"#197",
28054263Sshin	"#198",
281175061Sobrien	"#199",
28254263Sshin	"#200",
28354263Sshin	"#201",
28454263Sshin	"#202",
28554263Sshin	"#203",
28654263Sshin	"#204",
28754263Sshin	"#205",
28854263Sshin	"#206",
28954263Sshin	"#207",
29054263Sshin	"#208",
291175061Sobrien	"#209",
29254263Sshin	"#210",
29354263Sshin	"#211",
29454263Sshin	"#212",
29554263Sshin	"#213",
29654263Sshin	"#214",
29754263Sshin	"#215",
29854263Sshin	"#216",
29954263Sshin	"#217",
30054263Sshin	"#218",
301175061Sobrien	"#219",
30254263Sshin	"#220",
30354263Sshin	"#221",
30454263Sshin	"#222",
30554263Sshin	"#223",
30654263Sshin	"#224",
30754263Sshin	"#225",
30854263Sshin	"#226",
30954263Sshin	"#227",
31054263Sshin	"#228",
311175061Sobrien	"#229",
31254263Sshin	"#230",
31354263Sshin	"#231",
31454263Sshin	"#232",
31554263Sshin	"#233",
31654263Sshin	"#234",
31754263Sshin	"#235",
31854263Sshin	"#236",
31954263Sshin	"#237",
32054263Sshin	"#238",
321175061Sobrien	"#239",
32254263Sshin	"#240",
32354263Sshin	"#241",
32454263Sshin	"#242",
32554263Sshin	"#243",
32654263Sshin	"#244",
32754263Sshin	"#245",
32854263Sshin	"#246",
32954263Sshin	"#247",
33054263Sshin	"#248",
331175061Sobrien	"#249",
33254263Sshin	"#250",
33354263Sshin	"#251",
33454263Sshin	"#252",
33554263Sshin	"#253",
33654263Sshin	"#254",
33754263Sshin	"#255",
33854263Sshin};
33954263Sshin
340246988Scharnierstatic const char *srcrule_str[] = {
341125483Sume	"first candidate",
342125483Sume	"same address",
343125483Sume	"appropriate scope",
344125483Sume	"deprecated address",
345125483Sume	"home address",
346125483Sume	"outgoing interface",
347125483Sume	"matching label",
348125483Sume	"public/temporary address",
349125483Sume	"alive interface",
350270927Sae	"better virtual status",
351271307Sae	"preferred source",
352125483Sume	"rule #11",
353125483Sume	"rule #12",
354125483Sume	"rule #13",
355125483Sume	"longest match",
356125483Sume	"rule #15",
357125483Sume};
358125483Sume
35954263Sshin/*
36054263Sshin * Dump IP6 statistics structure.
36154263Sshin */
36254263Sshinvoid
363171465Sjhbip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
36454263Sshin{
365228700Smaxim	struct ip6stat ip6stat, zerostat;
36654263Sshin	int first, i;
36778931Sume	size_t len;
36854263Sshin
369171465Sjhb	len = sizeof ip6stat;
370171465Sjhb	if (live) {
371171465Sjhb		memset(&ip6stat, 0, len);
372228700Smaxim		if (zflag)
373228700Smaxim			memset(&zerostat, 0, len);
374228700Smaxim		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len,
375228700Smaxim		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
376171465Sjhb			if (errno != ENOENT)
377279122Smarcel				xo_warn("sysctl: net.inet6.ip6.stats");
378171465Sjhb			return;
379171465Sjhb		}
380171465Sjhb	} else
381253085Sae		kread_counters(off, &ip6stat, len);
382279122Smarcel	xo_open_container(name);
383279122Smarcel	xo_emit("{T:/%s}:\n", name);
38454263Sshin
38554263Sshin#define	p(f, m) if (ip6stat.f || sflag <= 1) \
386279122Smarcel	xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
38754263Sshin#define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
388279122Smarcel	xo_emit(m, (uintmax_t)ip6stat.f)
38954263Sshin
390279122Smarcel	p(ip6s_total, "\t{:received-packets/%ju} "
391279122Smarcel	    "{N:/total packet%s received}\n");
392279122Smarcel	p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
393279122Smarcel	    "{N:/with size smaller than minimum}\n");
394279122Smarcel	p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
395279122Smarcel	    "{N:/with data size < data length}\n");
396279122Smarcel	p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
397279122Smarcel	    "{N:/with bad options}\n");
398279122Smarcel	p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
399279122Smarcel	    "{N:/with incorrect version number}\n");
400279122Smarcel	p(ip6s_fragments, "\t{:received-fragments/%ju} "
401279122Smarcel	    "{N:/fragment%s received}\n");
402279122Smarcel	p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
403279122Smarcel	    "{N:/fragment%s dropped (dup or out of space)}\n");
404279122Smarcel	p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
405279122Smarcel	    "{N:/fragment%s dropped after timeout}\n");
406279122Smarcel	p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
407279122Smarcel	    "{N:/fragment%s that exceeded limit}\n");
408279122Smarcel	p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
409279122Smarcel	    "{N:/packet%s reassembled ok}\n");
410279122Smarcel	p(ip6s_delivered, "\t{:received-local-packets/%ju} "
411279122Smarcel	    "{N:/packet%s for this host}\n");
412279122Smarcel	p(ip6s_forward, "\t{:forwarded-packets/%ju} "
413279122Smarcel	    "{N:/packet%s forwarded}\n");
414279122Smarcel	p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
415279122Smarcel	    "{N:/packet%s not forwardable}\n");
416279122Smarcel	p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
417279122Smarcel	    "{N:/redirect%s sent}\n");
418279122Smarcel	p(ip6s_localout, "\t{:sent-packets/%ju} "
419279122Smarcel	    "{N:/packet%s sent from this host}\n");
420279122Smarcel	p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
421279122Smarcel	    "{N:/packet%s sent with fabricated ip header}\n");
422279122Smarcel	p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
423279122Smarcel	    "{N:/output packet%s dropped due to no bufs, etc.}\n");
424279122Smarcel	p(ip6s_noroute, "\t{:discard-no-route/%ju} "
425279122Smarcel	    "{N:/output packet%s discarded due to no route}\n");
426279122Smarcel	p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
427279122Smarcel	    "{N:/output datagram%s fragmented}\n");
428279122Smarcel	p(ip6s_ofragments, "\t{:fragments-created/%ju} "
429279122Smarcel	    "{N:/fragment%s created}\n");
430279122Smarcel	p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
431279122Smarcel	    "{N:/datagram%s that can't be fragmented}\n");
432279122Smarcel	p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
433279122Smarcel	    "{N:/packet%s that violated scope rules}\n");
434279122Smarcel	p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
435279122Smarcel	    "{N:/multicast packet%s which we don't join}\n");
436249545Sae	for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
43754263Sshin		if (ip6stat.ip6s_nxthist[i] != 0) {
43854263Sshin			if (first) {
439279122Smarcel				xo_emit("\t{T:Input histogram}:\n");
440279122Smarcel				xo_open_list("input-histogram");
44154263Sshin				first = 0;
44254263Sshin			}
443279122Smarcel			xo_open_instance("input-histogram");
444279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
445160787Syar			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
446279122Smarcel			xo_close_instance("input-histogram");
44754263Sshin		}
448279122Smarcel	if (!first)
449279122Smarcel		xo_close_list("input-histogram");
450279122Smarcel
451279122Smarcel	xo_open_container("mbuf-statistics");
452279122Smarcel	xo_emit("\t{T:Mbuf statistics}:\n");
453279122Smarcel	xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
454279122Smarcel	    (uintmax_t)ip6stat.ip6s_m1);
455249545Sae	for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
45655163Sshin		char ifbuf[IFNAMSIZ];
457175061Sobrien		if (ip6stat.ip6s_m2m[i] != 0) {
45854263Sshin			if (first) {
459279122Smarcel				xo_emit("\t\t{N:two or more mbuf}:\n");
460279122Smarcel				xo_open_list("mbuf-data");
46154263Sshin				first = 0;
46254263Sshin			}
463279122Smarcel			xo_open_instance("mbuf-data");
464279122Smarcel			xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
46562584Sitojun			    if_indextoname(i, ifbuf),
466160787Syar			    (uintmax_t)ip6stat.ip6s_m2m[i]);
467279122Smarcel			xo_close_instance("mbuf-data");
46854263Sshin		}
46954263Sshin	}
470279122Smarcel	if (!first)
471279122Smarcel		xo_close_list("mbuf-data");
472279122Smarcel	xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
473160787Syar	    (uintmax_t)ip6stat.ip6s_mext1);
474279122Smarcel	xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
475279122Smarcel	    "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
476279122Smarcel	xo_close_container("mbuf-statistics");
47762584Sitojun
478279122Smarcel	p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
479279122Smarcel	    "{N:/packet%s whose headers are not contiguous}\n");
480279122Smarcel	p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
481279122Smarcel	    "{N:/tunneling packet%s that can't find gif}\n");
482279122Smarcel	p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
483279122Smarcel	    "{N:/packet%s discarded because of too many headers}\n");
484279122Smarcel
48562584Sitojun	/* for debugging source address selection */
486175061Sobrien#define	PRINT_SCOPESTAT(s,i) do {\
48762584Sitojun		switch(i) { /* XXX hardcoding in each case */\
48862584Sitojun		case 1:\
489279122Smarcel			p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
490279122Smarcel			  "{N:/interface-local%s}\n");	\
49162584Sitojun			break;\
49262584Sitojun		case 2:\
493279122Smarcel			p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
494279122Smarcel			"{N:/link-local%s}\n"); \
49562584Sitojun			break;\
49662584Sitojun		case 5:\
497279122Smarcel			p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
498279122Smarcel			  "{N:/site-local%s}\n");\
49962584Sitojun			break;\
50062584Sitojun		case 14:\
501279122Smarcel			p(s,"\t\t{ke:name/globals}{:count/%ju} " \
502279122Smarcel			  "{N:/global%s}\n");\
50362584Sitojun			break;\
50462584Sitojun		default:\
505279122Smarcel			xo_emit("\t\t{qke:name/%x}{:count/%ju} " \
506279122Smarcel				"addresses scope=%x\n",\
507279122Smarcel				i, (uintmax_t)ip6stat.s, i);	   \
50862584Sitojun		}\
50962584Sitojun	} while (0);
51062584Sitojun
511279122Smarcel	xo_open_container("source-address-selection");
512279122Smarcel	p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
513279122Smarcel	    "{N:/failure%s of source address selection}\n");
514279122Smarcel
515249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
51662584Sitojun		if (ip6stat.ip6s_sources_sameif[i]) {
51762584Sitojun			if (first) {
518279122Smarcel				xo_open_list("outgoing-interface");
519279122Smarcel				xo_emit("\tsource addresses on an outgoing "
520279122Smarcel				    "I/F\n");
52162584Sitojun				first = 0;
52262584Sitojun			}
523279122Smarcel			xo_open_instance("outgoing-interface");
52462584Sitojun			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
525279122Smarcel			xo_close_instance("outgoing-interface");
52662584Sitojun		}
52762584Sitojun	}
528279122Smarcel	if (!first)
529279122Smarcel		xo_close_list("outgoing-interface");
530279122Smarcel
531249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
53262584Sitojun		if (ip6stat.ip6s_sources_otherif[i]) {
53362584Sitojun			if (first) {
534279122Smarcel				xo_open_list("non-outgoing-interface");
535279122Smarcel				xo_emit("\tsource addresses on a non-outgoing "
536279122Smarcel				    "I/F\n");
53762584Sitojun				first = 0;
53862584Sitojun			}
539279122Smarcel			xo_open_instance("non-outgoing-interface");
54062584Sitojun			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
541279122Smarcel			xo_close_instance("non-outgoing-interface");
54262584Sitojun		}
54362584Sitojun	}
544279122Smarcel	if (!first)
545279122Smarcel		xo_close_list("non-outgoing-interface");
546279122Smarcel
547249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
54862584Sitojun		if (ip6stat.ip6s_sources_samescope[i]) {
54962584Sitojun			if (first) {
550279122Smarcel				xo_open_list("same-source");
551279122Smarcel				xo_emit("\tsource addresses of same scope\n");
55262584Sitojun				first = 0;
55362584Sitojun			}
554279122Smarcel			xo_open_instance("same-source");
55562584Sitojun			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
556279122Smarcel			xo_close_instance("same-source");
55762584Sitojun		}
55862584Sitojun	}
559279122Smarcel	if (!first)
560279122Smarcel		xo_close_list("same-source");
561279122Smarcel
562249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
56362584Sitojun		if (ip6stat.ip6s_sources_otherscope[i]) {
56462584Sitojun			if (first) {
565279122Smarcel				xo_open_list("different-scope");
566279122Smarcel				xo_emit("\tsource addresses of a different "
567279122Smarcel				    "scope\n");
56862584Sitojun				first = 0;
56962584Sitojun			}
570279122Smarcel			xo_open_instance("different-scope");
57162584Sitojun			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
572279122Smarcel			xo_close_instance("different-scope");
57362584Sitojun		}
57462584Sitojun	}
575279122Smarcel	if (!first)
576279122Smarcel		xo_close_list("different-scope");
577279122Smarcel
578249545Sae	for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
57962584Sitojun		if (ip6stat.ip6s_sources_deprecated[i]) {
58062584Sitojun			if (first) {
581279122Smarcel				xo_open_list("deprecated-source");
582279122Smarcel				xo_emit("\tdeprecated source addresses\n");
58362584Sitojun				first = 0;
58462584Sitojun			}
585279122Smarcel			xo_open_instance("deprecated-source");
58662584Sitojun			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
587279122Smarcel			xo_close_instance("deprecated-source");
58862584Sitojun		}
58962584Sitojun	}
590279122Smarcel	if (!first)
591279122Smarcel		xo_close_list("deprecated-source");
59262584Sitojun
593279122Smarcel	for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
594279122Smarcel		if (ip6stat.ip6s_sources_rule[i]) {
595279122Smarcel			if (first) {
596279122Smarcel				xo_open_list("rules-applied");
597279122Smarcel				xo_emit("\t{T:Source addresses selection "
598279122Smarcel				    "rule applied}:\n");
599279122Smarcel				first = 0;
600279122Smarcel			}
601279122Smarcel			xo_open_instance("rules-applied");
602279122Smarcel			xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
603279122Smarcel			    srcrule_str[i],
604279122Smarcel			    (uintmax_t)ip6stat.ip6s_sources_rule[i],
605279122Smarcel			    srcrule_str[i]);
606279122Smarcel			xo_close_instance("rules-applied");
607279122Smarcel		}
608125483Sume	}
609279122Smarcel	if (!first)
610279122Smarcel		xo_close_list("rules-applied");
611279122Smarcel
612279122Smarcel	xo_close_container("source-address-selection");
613279122Smarcel
61454263Sshin#undef p
61562584Sitojun#undef p1a
616279122Smarcel	xo_close_container(name);
61754263Sshin}
61854263Sshin
61954263Sshin/*
62054263Sshin * Dump IPv6 per-interface statistics based on RFC 2465.
62154263Sshin */
62254263Sshinvoid
62378314Sassarip6_ifstats(char *ifname)
62454263Sshin{
62554263Sshin	struct in6_ifreq ifr;
62654263Sshin	int s;
62754263Sshin
628279122Smarcel#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1)	\
629279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f,		\
630279122Smarcel	    plural(ifr.ifr_ifru.ifru_stat.f))
631279122Smarcel
63254263Sshin	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
633279122Smarcel		xo_warn("Warning: socket(AF_INET6)");
63454263Sshin		return;
63554263Sshin	}
63654263Sshin
63754263Sshin	strcpy(ifr.ifr_name, ifname);
63854263Sshin	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
639270349Smarkj		if (errno != EPFNOSUPPORT)
640279122Smarcel			xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
64154263Sshin		goto end;
64254263Sshin	}
64354263Sshin
644279122Smarcel	xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
64554263Sshin
646279122Smarcel	xo_open_instance("ip6-interface-statistics");
647279122Smarcel	xo_emit("{ke:name/%s}", ifr.ifr_name);
64854263Sshin
649279122Smarcel	p(ifs6_in_receive, "\t{:received-packets/%ju} "
650279122Smarcel	    "{N:/total input datagram%s}\n");
651279122Smarcel	p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
652279122Smarcel	    "{N:/datagram%s with invalid header received}\n");
653279122Smarcel	p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
654279122Smarcel	    "{N:/datagram%s exceeded MTU received}\n");
655279122Smarcel	p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
656279122Smarcel	    "{N:/datagram%s with no route received}\n");
657279122Smarcel	p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
658279122Smarcel	    "{N:/datagram%s with invalid dst received}\n");
659279122Smarcel	p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
660279122Smarcel	    "{N:/datagram%s with unknown proto received}\n");
661279122Smarcel	p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
662279122Smarcel	    "{N:/truncated datagram%s received}\n");
663279122Smarcel	p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
664279122Smarcel	    "{N:/input datagram%s discarded}\n");
665279122Smarcel 	p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
666279122Smarcel	    "{N:/datagram%s delivered to an upper layer protocol}\n");
667279122Smarcel	p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
668279122Smarcel	    "{N:/datagram%s forwarded to this interface}\n");
669279122Smarcel 	p(ifs6_out_request, "\t{:sent-packets/%ju} "
670279122Smarcel	    "{N:/datagram%s sent from an upper layer protocol}\n");
671279122Smarcel	p(ifs6_out_discard, "\t{:discard-packets/%ju} "
672279122Smarcel	    "{N:/total discarded output datagram%s}\n");
673279122Smarcel	p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
674279122Smarcel	    "{N:/output datagram%s fragmented}\n");
675279122Smarcel	p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
676279122Smarcel	    "{N:/output datagram%s failed on fragment}\n");
677279122Smarcel	p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
678279122Smarcel	    "{N:/output datagram%s succeeded on fragment}\n");
679279122Smarcel	p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
680279122Smarcel	    "{N:/incoming datagram%s fragmented}\n");
681279122Smarcel	p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
682279122Smarcel	    "{N:/datagram%s reassembled}\n");
683279122Smarcel	p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
684279122Smarcel	    "{N:/datagram%s failed on reassembly}\n");
685279122Smarcel	p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
686279122Smarcel	    "{N:/multicast datagram%s received}\n");
687279122Smarcel	p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
688279122Smarcel	    "{N:/multicast datagram%s sent}\n");
689279122Smarcel
690279122Smarcel end:
691279122Smarcel	xo_close_instance("ip6-interface-statistics");
692279122Smarcel 	close(s);
693279122Smarcel
69454263Sshin#undef p
69554263Sshin}
69654263Sshin
697102975Sdwmalonestatic	const char *icmp6names[] = {
69854263Sshin	"#0",
69954263Sshin	"unreach",
70054263Sshin	"packet too big",
70154263Sshin	"time exceed",
70254263Sshin	"parameter problem",
70354263Sshin	"#5",
70454263Sshin	"#6",
70554263Sshin	"#7",
70654263Sshin	"#8",
70754263Sshin	"#9",
70854263Sshin	"#10",
70954263Sshin	"#11",
71054263Sshin	"#12",
71154263Sshin	"#13",
71254263Sshin	"#14",
71354263Sshin	"#15",
71454263Sshin	"#16",
71554263Sshin	"#17",
71654263Sshin	"#18",
717175061Sobrien	"#19",
71854263Sshin	"#20",
71954263Sshin	"#21",
72054263Sshin	"#22",
72154263Sshin	"#23",
72254263Sshin	"#24",
72354263Sshin	"#25",
72454263Sshin	"#26",
72554263Sshin	"#27",
72654263Sshin	"#28",
727175061Sobrien	"#29",
72854263Sshin	"#30",
72954263Sshin	"#31",
73054263Sshin	"#32",
73154263Sshin	"#33",
73254263Sshin	"#34",
73354263Sshin	"#35",
73454263Sshin	"#36",
73554263Sshin	"#37",
73654263Sshin	"#38",
737175061Sobrien	"#39",
73854263Sshin	"#40",
73954263Sshin	"#41",
74054263Sshin	"#42",
74154263Sshin	"#43",
74254263Sshin	"#44",
74354263Sshin	"#45",
74454263Sshin	"#46",
74554263Sshin	"#47",
74654263Sshin	"#48",
747175061Sobrien	"#49",
74854263Sshin	"#50",
74954263Sshin	"#51",
75054263Sshin	"#52",
75154263Sshin	"#53",
75254263Sshin	"#54",
75354263Sshin	"#55",
75454263Sshin	"#56",
75554263Sshin	"#57",
75654263Sshin	"#58",
757175061Sobrien	"#59",
75854263Sshin	"#60",
75954263Sshin	"#61",
76054263Sshin	"#62",
76154263Sshin	"#63",
76254263Sshin	"#64",
76354263Sshin	"#65",
76454263Sshin	"#66",
76554263Sshin	"#67",
76654263Sshin	"#68",
767175061Sobrien	"#69",
76854263Sshin	"#70",
76954263Sshin	"#71",
77054263Sshin	"#72",
77154263Sshin	"#73",
77254263Sshin	"#74",
77354263Sshin	"#75",
77454263Sshin	"#76",
77554263Sshin	"#77",
77654263Sshin	"#78",
777175061Sobrien	"#79",
77854263Sshin	"#80",
77954263Sshin	"#81",
78054263Sshin	"#82",
78154263Sshin	"#83",
78254263Sshin	"#84",
78354263Sshin	"#85",
78454263Sshin	"#86",
78554263Sshin	"#87",
78654263Sshin	"#88",
787175061Sobrien	"#89",
78854263Sshin	"#80",
78954263Sshin	"#91",
79054263Sshin	"#92",
79154263Sshin	"#93",
79254263Sshin	"#94",
79354263Sshin	"#95",
79454263Sshin	"#96",
79554263Sshin	"#97",
79654263Sshin	"#98",
797175061Sobrien	"#99",
79854263Sshin	"#100",
79954263Sshin	"#101",
80054263Sshin	"#102",
80154263Sshin	"#103",
80254263Sshin	"#104",
80354263Sshin	"#105",
80454263Sshin	"#106",
80554263Sshin	"#107",
80654263Sshin	"#108",
807175061Sobrien	"#109",
80854263Sshin	"#110",
80954263Sshin	"#111",
81054263Sshin	"#112",
81154263Sshin	"#113",
81254263Sshin	"#114",
81354263Sshin	"#115",
81454263Sshin	"#116",
81554263Sshin	"#117",
81654263Sshin	"#118",
817175061Sobrien	"#119",
81854263Sshin	"#120",
81954263Sshin	"#121",
82054263Sshin	"#122",
82154263Sshin	"#123",
82254263Sshin	"#124",
82354263Sshin	"#125",
82454263Sshin	"#126",
82554263Sshin	"#127",
82654263Sshin	"echo",
827175061Sobrien	"echo reply",
82854263Sshin	"multicast listener query",
829191652Sbms	"MLDv1 listener report",
830191652Sbms	"MLDv1 listener done",
83154263Sshin	"router solicitation",
83277565Sdd	"router advertisement",
83354263Sshin	"neighbor solicitation",
83477565Sdd	"neighbor advertisement",
83554263Sshin	"redirect",
83654263Sshin	"router renumbering",
83754263Sshin	"node information request",
83854263Sshin	"node information reply",
83978540Ssumikawa	"inverse neighbor solicitation",
84078540Ssumikawa	"inverse neighbor advertisement",
841191652Sbms	"MLDv2 listener report",
84254263Sshin	"#144",
84354263Sshin	"#145",
84454263Sshin	"#146",
84554263Sshin	"#147",
84654263Sshin	"#148",
847175061Sobrien	"#149",
84854263Sshin	"#150",
84954263Sshin	"#151",
85054263Sshin	"#152",
85154263Sshin	"#153",
85254263Sshin	"#154",
85354263Sshin	"#155",
85454263Sshin	"#156",
85554263Sshin	"#157",
85654263Sshin	"#158",
857175061Sobrien	"#159",
85854263Sshin	"#160",
85954263Sshin	"#161",
86054263Sshin	"#162",
86154263Sshin	"#163",
86254263Sshin	"#164",
86354263Sshin	"#165",
86454263Sshin	"#166",
86554263Sshin	"#167",
86654263Sshin	"#168",
867175061Sobrien	"#169",
86854263Sshin	"#170",
86954263Sshin	"#171",
87054263Sshin	"#172",
87154263Sshin	"#173",
87254263Sshin	"#174",
87354263Sshin	"#175",
87454263Sshin	"#176",
87554263Sshin	"#177",
87654263Sshin	"#178",
877175061Sobrien	"#179",
87854263Sshin	"#180",
87954263Sshin	"#181",
88054263Sshin	"#182",
88154263Sshin	"#183",
88254263Sshin	"#184",
88354263Sshin	"#185",
88454263Sshin	"#186",
88554263Sshin	"#187",
88654263Sshin	"#188",
887175061Sobrien	"#189",
88854263Sshin	"#180",
88954263Sshin	"#191",
89054263Sshin	"#192",
89154263Sshin	"#193",
89254263Sshin	"#194",
89354263Sshin	"#195",
89454263Sshin	"#196",
89554263Sshin	"#197",
89654263Sshin	"#198",
897175061Sobrien	"#199",
89854263Sshin	"#200",
89954263Sshin	"#201",
90054263Sshin	"#202",
90154263Sshin	"#203",
90254263Sshin	"#204",
90354263Sshin	"#205",
90454263Sshin	"#206",
90554263Sshin	"#207",
90654263Sshin	"#208",
907175061Sobrien	"#209",
90854263Sshin	"#210",
90954263Sshin	"#211",
91054263Sshin	"#212",
91154263Sshin	"#213",
91254263Sshin	"#214",
91354263Sshin	"#215",
91454263Sshin	"#216",
91554263Sshin	"#217",
91654263Sshin	"#218",
917175061Sobrien	"#219",
91854263Sshin	"#220",
91954263Sshin	"#221",
92054263Sshin	"#222",
92154263Sshin	"#223",
92254263Sshin	"#224",
92354263Sshin	"#225",
92454263Sshin	"#226",
92554263Sshin	"#227",
92654263Sshin	"#228",
927175061Sobrien	"#229",
92854263Sshin	"#230",
92954263Sshin	"#231",
93054263Sshin	"#232",
93154263Sshin	"#233",
93254263Sshin	"#234",
93354263Sshin	"#235",
93454263Sshin	"#236",
93554263Sshin	"#237",
93654263Sshin	"#238",
937175061Sobrien	"#239",
93854263Sshin	"#240",
93954263Sshin	"#241",
94054263Sshin	"#242",
94154263Sshin	"#243",
94254263Sshin	"#244",
94354263Sshin	"#245",
94454263Sshin	"#246",
94554263Sshin	"#247",
94654263Sshin	"#248",
947175061Sobrien	"#249",
94854263Sshin	"#250",
94954263Sshin	"#251",
95054263Sshin	"#252",
95154263Sshin	"#253",
95254263Sshin	"#254",
95354263Sshin	"#255",
95454263Sshin};
95554263Sshin
95654263Sshin/*
95754263Sshin * Dump ICMP6 statistics.
95854263Sshin */
95954263Sshinvoid
960171465Sjhbicmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
96154263Sshin{
962228700Smaxim	struct icmp6stat icmp6stat, zerostat;
96395637Smarkm	int i, first;
96478931Sume	size_t len;
96554263Sshin
966171465Sjhb	len = sizeof icmp6stat;
967171465Sjhb	if (live) {
968171465Sjhb		memset(&icmp6stat, 0, len);
969228700Smaxim		if (zflag)
970228700Smaxim			memset(&zerostat, 0, len);
971171465Sjhb		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
972228700Smaxim		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
973171465Sjhb			if (errno != ENOENT)
974279122Smarcel				xo_warn("sysctl: net.inet6.icmp6.stats");
975171465Sjhb			return;
976171465Sjhb		}
977171465Sjhb	} else
978253085Sae		kread_counters(off, &icmp6stat, len);
97978931Sume
980279122Smarcel	xo_emit("{T:/%s}:\n", name);
981279122Smarcel	xo_open_container(name);
98254263Sshin
98354263Sshin#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
984279122Smarcel	xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
985187134Smaxim#define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
986279122Smarcel	xo_emit(m, (uintmax_t)icmp6stat.f)
98754263Sshin
988279122Smarcel	p(icp6s_error, "\t{:icmp6-calls/%ju} "
989279122Smarcel	    "{N:/call%s to icmp6_error}\n");
990279122Smarcel	p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
991279122Smarcel	    "{N:/error%s not generated in response to an icmp6 message}\n");
992279122Smarcel	p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
993279122Smarcel	    "{N:/error%s not generated because of rate limitation}\n");
994175061Sobrien#define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
99578540Ssumikawa	for (first = 1, i = 0; i < NELEM; i++)
99654263Sshin		if (icmp6stat.icp6s_outhist[i] != 0) {
99754263Sshin			if (first) {
998279122Smarcel				xo_open_list("output-histogram");
999279122Smarcel				xo_emit("\t{T:Output histogram}:\n");
100054263Sshin				first = 0;
100154263Sshin			}
1002279122Smarcel			xo_open_instance("output-histogram");
1003279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1004279122Smarcel			    icmp6names[i],
1005160787Syar			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
1006279122Smarcel			xo_close_instance("output-histogram");
100754263Sshin		}
1008279122Smarcel	if (!first)
1009279122Smarcel		xo_close_list("output-histogram");
101078540Ssumikawa#undef NELEM
1011279122Smarcel
1012279122Smarcel	p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
1013279122Smarcel	    "{N:/message%s with bad code fields}\n");
1014279122Smarcel	p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
1015279122Smarcel	    "{N:/message%s < minimum length}\n");
1016279122Smarcel	p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
1017279122Smarcel	    "{N:/bad checksum%s}\n");
1018279122Smarcel	p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
1019279122Smarcel	    "{N:/message%s with bad length}\n");
1020175061Sobrien#define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
102178540Ssumikawa	for (first = 1, i = 0; i < NELEM; i++)
102254263Sshin		if (icmp6stat.icp6s_inhist[i] != 0) {
102354263Sshin			if (first) {
1024279122Smarcel				xo_open_list("input-histogram");
1025279122Smarcel				xo_emit("\t{T:Input histogram}:\n");
102654263Sshin				first = 0;
102754263Sshin			}
1028279122Smarcel			xo_open_instance("input-histogram");
1029279122Smarcel			xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1030279122Smarcel			    icmp6names[i],
1031160787Syar			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
1032279122Smarcel			xo_close_instance("input-histogram");
103354263Sshin		}
1034279122Smarcel	if (!first)
1035279122Smarcel		xo_close_list("input-histogram");
103678540Ssumikawa#undef NELEM
1037279122Smarcel	xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1038279122Smarcel	xo_open_container("errors");
1039279122Smarcel	p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1040279122Smarcel	    "{N:/no route}\n");
1041279122Smarcel	p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1042279122Smarcel	    "{N:/administratively prohibited}\n");
1043279122Smarcel	p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1044279122Smarcel	    "{N:/beyond scope}\n");
1045279122Smarcel	p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1046279122Smarcel	    "{N:/address unreachable}\n");
1047279122Smarcel	p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1048279122Smarcel	    "{N:/port unreachable}\n");
1049279122Smarcel	p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1050279122Smarcel	    "{N:/packet too big}\n");
1051279122Smarcel	p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1052279122Smarcel	    "{N:/time exceed transit}\n");
1053279122Smarcel	p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1054279122Smarcel	    "{N:/time exceed reassembly}\n");
1055279122Smarcel	p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1056279122Smarcel	    "{N:/erroneous header field}\n");
1057279122Smarcel	p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1058279122Smarcel	    "{N:/unrecognized next header}\n");
1059279122Smarcel	p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1060279122Smarcel	    "{N:/unrecognized option}\n");
1061279122Smarcel	p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1062279122Smarcel	    "{N:/redirect}\n");
1063279122Smarcel	p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
106462584Sitojun
1065279122Smarcel	p(icp6s_reflect, "\t{:reflect/%ju} "
1066279122Smarcel	    "{N:/message response%s generated}\n");
1067279122Smarcel	p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1068279122Smarcel	    "{N:/message%s with too many ND options}\n");
1069279122Smarcel	p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1070279122Smarcel	    "{N:/message%s with bad ND options}\n");
1071279122Smarcel	p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1072279122Smarcel	    "{N:/bad neighbor solicitation message%s}\n");
1073279122Smarcel	p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1074279122Smarcel	    "{N:/bad neighbor advertisement message%s}\n");
1075279122Smarcel	p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1076279122Smarcel	    "{N:/bad router solicitation message%s}\n");
1077279122Smarcel	p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1078279122Smarcel	    "{N:/bad router advertisement message%s}\n");
1079279122Smarcel	p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1080279122Smarcel	    "{N:/bad redirect message%s}\n");
1081279122Smarcel	xo_close_container("errors");
1082279122Smarcel	p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
108354263Sshin#undef p
108454263Sshin#undef p_5
1085279122Smarcel	xo_close_container(name);
108654263Sshin}
108754263Sshin
108854263Sshin/*
108954263Sshin * Dump ICMPv6 per-interface statistics based on RFC 2466.
109054263Sshin */
109154263Sshinvoid
109278314Sassaricmp6_ifstats(char *ifname)
109354263Sshin{
109454263Sshin	struct in6_ifreq ifr;
109554263Sshin	int s;
109654263Sshin
1097279122Smarcel#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1098279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1099279122Smarcel	    plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1100279122Smarcel#define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1)	\
1101279122Smarcel	xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f,		\
1102279122Smarcel	    pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1103279122Smarcel
110454263Sshin	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1105279122Smarcel		xo_warn("Warning: socket(AF_INET6)");
110654263Sshin		return;
110754263Sshin	}
110854263Sshin
110954263Sshin	strcpy(ifr.ifr_name, ifname);
111054263Sshin	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1111270349Smarkj		if (errno != EPFNOSUPPORT)
1112279122Smarcel			xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
111354263Sshin		goto end;
111454263Sshin	}
111554263Sshin
1116279122Smarcel	xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
111754263Sshin
1118279122Smarcel	xo_open_instance("icmp6-interface-statistics");
1119279122Smarcel	xo_emit("{ke:name/%s}", ifr.ifr_name);
1120279122Smarcel	p(ifs6_in_msg, "\t{:received-packets/%ju} "
1121279122Smarcel	    "{N:/total input message%s}\n");
1122279122Smarcel	p(ifs6_in_error, "\t{:received-errors/%ju} "
1123279122Smarcel	    "{N:/total input error message%s}\n");
1124279122Smarcel	p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1125279122Smarcel	    "{N:/input destination unreachable error%s}\n");
1126279122Smarcel	p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1127279122Smarcel	    "{N:/input administratively prohibited error%s}\n");
1128279122Smarcel	p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1129279122Smarcel	    "{N:/input time exceeded error%s}\n");
1130279122Smarcel	p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1131279122Smarcel	    "{N:/input parameter problem error%s}\n");
1132279122Smarcel	p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1133279122Smarcel	    "{N:/input packet too big error%s}\n");
1134279122Smarcel	p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1135279122Smarcel	    "{N:/input echo request%s}\n");
1136279122Smarcel	p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1137279122Smarcel	    "{N:/input echo repl%s}\n");
1138279122Smarcel	p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1139279122Smarcel	    "{N:/input router solicitation%s}\n");
1140279122Smarcel	p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1141279122Smarcel	    "{N:/input router advertisement%s}\n");
1142279122Smarcel	p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1143279122Smarcel	    "{N:/input neighbor solicitation%s}\n");
1144279122Smarcel	p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1145279122Smarcel	    "{N:/input neighbor advertisement%s}\n");
1146279122Smarcel	p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1147279122Smarcel	    "{N:/input redirect%s}\n");
1148279122Smarcel	p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1149279122Smarcel	    "{N:/input MLD quer%s}\n");
1150279122Smarcel	p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1151279122Smarcel	    "{N:/input MLD report%s}\n");
1152279122Smarcel	p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1153279122Smarcel	    "{N:/input MLD done%s}\n");
115454263Sshin
1155279122Smarcel	p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1156279122Smarcel	    "{N:/total output message%s}\n");
1157279122Smarcel	p(ifs6_out_error, "\t{:sent-errors/%ju} "
1158279122Smarcel	    "{N:/total output error message%s}\n");
1159279122Smarcel	p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1160279122Smarcel	    "{N:/output destination unreachable error%s}\n");
1161279122Smarcel	p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1162279122Smarcel	    "{N:/output administratively prohibited error%s}\n");
1163279122Smarcel	p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1164279122Smarcel	    "{N:/output time exceeded error%s}\n");
1165279122Smarcel	p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1166279122Smarcel	    "{N:/output parameter problem error%s}\n");
1167279122Smarcel	p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1168279122Smarcel	    "{N:/output packet too big error%s}\n");
1169279122Smarcel	p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1170279122Smarcel	    "{N:/output echo request%s}\n");
1171279122Smarcel	p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1172279122Smarcel	    "{N:/output echo repl%s}\n");
1173279122Smarcel	p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1174279122Smarcel	    "{N:/output router solicitation%s}\n");
1175279122Smarcel	p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1176279122Smarcel	    "{N:/output router advertisement%s}\n");
1177279122Smarcel	p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1178279122Smarcel	    "{N:/output neighbor solicitation%s}\n");
1179279122Smarcel	p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1180279122Smarcel	    "{N:/output neighbor advertisement%s}\n");
1181279122Smarcel	p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1182279122Smarcel	    "{N:/output redirect%s}\n");
1183279122Smarcel	p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1184279122Smarcel	    "{N:/output MLD quer%s}\n");
1185279122Smarcel	p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1186279122Smarcel	    "{N:/output MLD report%s}\n");
1187279122Smarcel	p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1188279122Smarcel	    "{N:/output MLD done%s}\n");
1189279122Smarcel
1190279122Smarcelend:
1191279122Smarcel	xo_close_instance("icmp6-interface-statistics");
119254263Sshin	close(s);
119354263Sshin#undef p
119454263Sshin}
119554263Sshin
119654263Sshin/*
119754263Sshin * Dump PIM statistics structure.
119854263Sshin */
119954263Sshinvoid
1200171465Sjhbpim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
120154263Sshin{
1202166952Sbms	struct pim6stat pim6stat, zerostat;
1203166952Sbms	size_t len = sizeof pim6stat;
120454263Sshin
1205171465Sjhb	if (live) {
1206171465Sjhb		if (zflag)
1207171465Sjhb			memset(&zerostat, 0, len);
1208171465Sjhb		if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1209171465Sjhb		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1210171465Sjhb			if (errno != ENOENT)
1211279122Smarcel				xo_warn("sysctl: net.inet6.pim.stats");
1212171465Sjhb			return;
1213171465Sjhb		}
1214171465Sjhb	} else {
1215171465Sjhb		if (off == 0)
1216171465Sjhb			return;
1217171465Sjhb		kread(off, &pim6stat, len);
1218166952Sbms	}
1219171465Sjhb
1220279122Smarcel	xo_emit("{T:/%s}:\n", name);
1221279122Smarcel	xo_open_container(name);
122254263Sshin
122354263Sshin#define	p(f, m) if (pim6stat.f || sflag <= 1) \
1224279122Smarcel	xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1225279122Smarcel
1226279122Smarcel	p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1227279122Smarcel	    "{N:/message%s received}\n");
1228279122Smarcel	p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1229279122Smarcel	    "{N:/message%s received with too few bytes}\n");
1230279122Smarcel	p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1231279122Smarcel	    "{N:/message%s received with bad checksum}\n");
1232279122Smarcel	p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1233279122Smarcel	    "{N:/message%s received with bad version}\n");
1234279122Smarcel	p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1235279122Smarcel	    "{N:/register%s received}\n");
1236279122Smarcel	p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1237279122Smarcel	    "{N:/bad register%s received}\n");
1238279122Smarcel	p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1239279122Smarcel	    "{N:/register%s sent}\n");
124054263Sshin#undef p
1241279122Smarcel	xo_close_container(name);
124254263Sshin}
124354263Sshin
124454263Sshin/*
124578064Sume * Dump raw ip6 statistics structure.
124678064Sume */
124778064Sumevoid
1248171465Sjhbrip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
124978064Sume{
1250228700Smaxim	struct rip6stat rip6stat, zerostat;
125178064Sume	u_quad_t delivered;
1252171465Sjhb	size_t len;
125378064Sume
1254171465Sjhb	len = sizeof(rip6stat);
1255171465Sjhb	if (live) {
1256228700Smaxim		if (zflag)
1257228700Smaxim			memset(&zerostat, 0, len);
1258171465Sjhb		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1259228700Smaxim		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1260171465Sjhb			if (errno != ENOENT)
1261279122Smarcel				xo_warn("sysctl: net.inet6.ip6.rip6stats");
1262171465Sjhb			return;
1263171465Sjhb		}
1264171465Sjhb	} else
1265253085Sae		kread_counters(off, &rip6stat, len);
126678064Sume
1267279122Smarcel	xo_emit("{T:/%s}:\n", name);
1268279122Smarcel	xo_open_container(name);
126978064Sume
127078064Sume#define	p(f, m) if (rip6stat.f || sflag <= 1) \
1271279122Smarcel	xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1272279122Smarcel
1273279122Smarcel	p(rip6s_ipackets, "\t{:received-packets/%ju} "
1274279122Smarcel	    "{N:/message%s received}\n");
1275279122Smarcel	p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1276279122Smarcel	    "{N:/checksum calculation%s on inbound}\n");
1277279122Smarcel	p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1278279122Smarcel	    "{N:/message%s with bad checksum}\n");
1279279122Smarcel	p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1280279122Smarcel	    "{N:/message%s dropped due to no socket}\n");
1281279122Smarcel	p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1282279122Smarcel	    "{N:/multicast message%s dropped due to no socket}\n");
1283279122Smarcel	p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1284279122Smarcel	    "{N:/message%s dropped due to full socket buffers}\n");
128578064Sume	delivered = rip6stat.rip6s_ipackets -
128678064Sume		    rip6stat.rip6s_badsum -
128778064Sume		    rip6stat.rip6s_nosock -
128878064Sume		    rip6stat.rip6s_nosockmcast -
128978064Sume		    rip6stat.rip6s_fullsock;
129078064Sume	if (delivered || sflag <= 1)
1291279122Smarcel		xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1292279122Smarcel		    (uintmax_t)delivered);
1293279122Smarcel	p(rip6s_opackets, "\t{:sent-packets/%ju} "
1294279122Smarcel	    "{N:/datagram%s output}\n");
129578064Sume#undef p
1296279122Smarcel	xo_close_container(name);
129778064Sume}
129878064Sume
129978064Sume/*
130054263Sshin * Pretty print an Internet address (net address + port).
130178238Sassar * Take numeric_addr and numeric_port into consideration.
130254263Sshin */
1303175061Sobrien#define	GETSERVBYPORT6(port, proto, ret)\
130454263Sshin{\
130554263Sshin	if (strcmp((proto), "tcp6") == 0)\
130654263Sshin		(ret) = getservbyport((int)(port), "tcp");\
130754263Sshin	else if (strcmp((proto), "udp6") == 0)\
130854263Sshin		(ret) = getservbyport((int)(port), "udp");\
130954263Sshin	else\
131054263Sshin		(ret) = getservbyport((int)(port), (proto));\
131154263Sshin};
131254263Sshin
131354263Sshinvoid
1314279122Smarcelinet6print(const char *container, struct in6_addr *in6, int port,
1315279122Smarcel    const char *proto, int numeric)
131654263Sshin{
131754263Sshin	struct servent *sp = 0;
131854263Sshin	char line[80], *cp;
131954263Sshin	int width;
132054263Sshin
1321279122Smarcel	if (container)
1322279122Smarcel		xo_open_container(container);
1323279122Smarcel
1324279122Smarcel	sprintf(line, "%.*s.", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1325279122Smarcel	    inet6name(in6));
1326229403Sed	cp = strchr(line, '\0');
132754263Sshin	if (!numeric && port)
132854263Sshin		GETSERVBYPORT6(port, proto, sp);
132954263Sshin	if (sp || port == 0)
1330177352Sume		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
133154263Sshin	else
133254263Sshin		sprintf(cp, "%d", ntohs((u_short)port));
133383200Sru	width = Wflag ? 45 : Aflag ? 18 : 22;
1334279122Smarcel
1335279122Smarcel	xo_emit("{d:target/%-*.*s} ", width, width, line);
1336279122Smarcel
1337279122Smarcel	int alen = cp - line - 1, plen = strlen(cp) - 1;
1338279122Smarcel	xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1339279122Smarcel	    plen, cp);
1340279122Smarcel
1341279122Smarcel	if (container)
1342279122Smarcel		xo_close_container(container);
134354263Sshin}
134454263Sshin
134554263Sshin/*
134654263Sshin * Construct an Internet address representation.
134778238Sassar * If the numeric_addr has been supplied, give
134854263Sshin * numeric value, otherwise try for symbolic name.
134954263Sshin */
135054263Sshin
135154263Sshinchar *
135278314Sassarinet6name(struct in6_addr *in6p)
135354263Sshin{
1354254459Shrs	struct sockaddr_in6 sin6;
1355254459Shrs	char hbuf[NI_MAXHOST], *cp;
135654263Sshin	static char line[50];
135774262Sbrian	static char domain[MAXHOSTNAMELEN];
135854263Sshin	static int first = 1;
1359254459Shrs	int flags, error;
136054263Sshin
1361254459Shrs	if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1362254459Shrs		strcpy(line, "*");
1363254459Shrs		return (line);
1364254459Shrs	}
136578238Sassar	if (first && !numeric_addr) {
136654263Sshin		first = 0;
136754263Sshin		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1368229403Sed		    (cp = strchr(domain, '.')))
136954263Sshin			(void) strcpy(domain, cp + 1);
137054263Sshin		else
137154263Sshin			domain[0] = 0;
137254263Sshin	}
1373254459Shrs	memset(&sin6, 0, sizeof(sin6));
1374254459Shrs	memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1375254459Shrs	sin6.sin6_family = AF_INET6;
1376279122Smarcel	/* XXX: in6p.s6_addr[2] can contain scopeid. */
1377254459Shrs	in6_fillscopeid(&sin6);
1378254459Shrs	flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1379254459Shrs	error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1380254459Shrs	    sizeof(hbuf), NULL, 0, flags);
1381254459Shrs	if (error == 0) {
1382254459Shrs		if ((flags & NI_NUMERICHOST) == 0 &&
1383254459Shrs		    (cp = strchr(hbuf, '.')) &&
1384254459Shrs		    !strcmp(cp + 1, domain))
1385254459Shrs			*cp = 0;
1386254459Shrs		strcpy(line, hbuf);
1387254459Shrs	} else {
1388254459Shrs		/* XXX: this should not happen. */
138954263Sshin		sprintf(line, "%s",
1390254459Shrs			inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,
139154263Sshin				sizeof(ntop_buf)));
1392254459Shrs	}
139354263Sshin	return (line);
139454263Sshin}
139564342Sume#endif /*INET6*/
1396