inet6.c revision 160373
1185380Ssam/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
2185380Ssam/*
3185380Ssam * Copyright (c) 1983, 1988, 1993
4185380Ssam *	The Regents of the University of California.  All rights reserved.
5185380Ssam *
6185380Ssam * Redistribution and use in source and binary forms, with or without
7185380Ssam * modification, are permitted provided that the following conditions
8185380Ssam * are met:
9185380Ssam * 1. Redistributions of source code must retain the above copyright
10185380Ssam *    notice, this list of conditions and the following disclaimer.
11185380Ssam * 2. Redistributions in binary form must reproduce the above copyright
12185380Ssam *    notice, this list of conditions and the following disclaimer in the
13185380Ssam *    documentation and/or other materials provided with the distribution.
14185380Ssam * 3. All advertising materials mentioning features or use of this software
15185380Ssam *    must display the following acknowledgement:
16185380Ssam *	This product includes software developed by the University of
17204644Srpaulo *	California, Berkeley and its contributors.
18185380Ssam * 4. Neither the name of the University nor the names of its contributors
19185380Ssam *    may be used to endorse or promote products derived from this software
20185380Ssam *    without specific prior written permission.
21185380Ssam *
22185380Ssam * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23185380Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24185380Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25185380Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26185380Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27185380Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28185380Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29185380Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30185380Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31185380Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32185380Ssam * SUCH DAMAGE.
33185380Ssam */
34185380Ssam
35185380Ssam#if 0
36185380Ssam#ifndef lint
37185380Ssamstatic char sccsid[] = "@(#)inet6.c	8.4 (Berkeley) 4/20/94";
38185380Ssam#endif /* not lint */
39185380Ssam#endif
40185380Ssam
41185380Ssam#include <sys/cdefs.h>
42185380Ssam__FBSDID("$FreeBSD: head/usr.bin/netstat/inet6.c 160373 2006-07-14 23:32:43Z julian $");
43185380Ssam
44185380Ssam#ifdef INET6
45185380Ssam#include <sys/param.h>
46185380Ssam#include <sys/socket.h>
47185380Ssam#include <sys/socketvar.h>
48185380Ssam#include <sys/ioctl.h>
49185380Ssam#include <sys/mbuf.h>
50185380Ssam#include <sys/protosw.h>
51185380Ssam#include <sys/sysctl.h>
52185380Ssam
53185380Ssam#include <net/route.h>
54185380Ssam#include <net/if.h>
55185380Ssam#include <net/if_var.h>
56185380Ssam#include <netinet/in.h>
57185380Ssam#include <netinet/ip6.h>
58185380Ssam#include <netinet/icmp6.h>
59185380Ssam#include <netinet/in_systm.h>
60185380Ssam#include <netinet6/in6_pcb.h>
61185380Ssam#include <netinet6/in6_var.h>
62185380Ssam#include <netinet6/ip6_var.h>
63185380Ssam#include <netinet6/pim6_var.h>
64185380Ssam#include <netinet6/raw_ip6.h>
65185380Ssam
66185380Ssam#include <arpa/inet.h>
67185380Ssam#include <netdb.h>
68185380Ssam
69185380Ssam#include <stdio.h>
70185380Ssam#include <errno.h>
71185380Ssam#include <string.h>
72185380Ssam#include <unistd.h>
73185380Ssam#include "netstat.h"
74185380Ssam
75185380Ssamstruct	socket sockb;
76185380Ssam
77185380Ssamchar	*inet6name(struct in6_addr *);
78185380Ssamconst char *pluralies(int);
79185380Ssam
80185380Ssamstatic char ntop_buf[INET6_ADDRSTRLEN];
81185380Ssam
82185380Ssamstatic	const char *ip6nh[] = {
83185380Ssam	"hop by hop",
84185380Ssam	"ICMP",
85185380Ssam	"IGMP",
86185380Ssam	"#3",
87185380Ssam	"IP",
88185380Ssam	"#5",
89185380Ssam	"TCP",
90185380Ssam	"#7",
91185380Ssam	"#8",
92185380Ssam	"#9",
93185380Ssam	"#10",
94185380Ssam	"#11",
95185380Ssam	"#12",
96185380Ssam	"#13",
97185380Ssam	"#14",
98185380Ssam	"#15",
99185380Ssam	"#16",
100185380Ssam	"UDP",
101185380Ssam	"#18",
102185380Ssam	"#19",
103185380Ssam	"#20",
104185380Ssam	"#21",
105185380Ssam	"IDP",
106185380Ssam	"#23",
107185380Ssam	"#24",
108185380Ssam	"#25",
109185380Ssam	"#26",
110185380Ssam	"#27",
111185380Ssam	"#28",
112185380Ssam	"TP",
113185380Ssam	"#30",
114185380Ssam	"#31",
115185380Ssam	"#32",
116185380Ssam	"#33",
117185380Ssam	"#34",
118185380Ssam	"#35",
119185380Ssam	"#36",
120185380Ssam	"#37",
121185380Ssam	"#38",
122185380Ssam	"#39",
123185380Ssam	"#40",
124185380Ssam	"IP6",
125185380Ssam	"#42",
126185380Ssam	"routing",
127185380Ssam	"fragment",
128185380Ssam	"#45",
129185380Ssam	"#46",
130185380Ssam	"#47",
131185380Ssam	"#48",
132185380Ssam	"#49",
133185380Ssam	"ESP",
134185380Ssam	"AH",
135185380Ssam	"#52",
136185380Ssam	"#53",
137185380Ssam	"#54",
138185380Ssam	"#55",
139185380Ssam	"#56",
140185380Ssam	"#57",
141185380Ssam	"ICMP6",
142185380Ssam	"no next header",
143185380Ssam	"destination option",
144185380Ssam	"#61",
145185380Ssam	"mobility",
146185380Ssam	"#63",
147185380Ssam	"#64",
148185380Ssam	"#65",
149185380Ssam	"#66",
150185380Ssam	"#67",
151185380Ssam	"#68",
152185380Ssam	"#69",
153185380Ssam	"#70",
154185380Ssam	"#71",
155185380Ssam	"#72",
156185380Ssam	"#73",
157185380Ssam	"#74",
158185380Ssam	"#75",
159185380Ssam	"#76",
160185380Ssam	"#77",
161185380Ssam	"#78",
162185380Ssam	"#79",
163185380Ssam	"ISOIP",
164185380Ssam	"#81",
165185380Ssam	"#82",
166185380Ssam	"#83",
167185380Ssam	"#84",
168185380Ssam	"#85",
169185380Ssam	"#86",
170185380Ssam	"#87",
171185380Ssam	"#88",
172185380Ssam	"OSPF",
173185380Ssam	"#80",
174185380Ssam	"#91",
175185380Ssam	"#92",
176185380Ssam	"#93",
177185380Ssam	"#94",
178185380Ssam	"#95",
179185380Ssam	"#96",
180185380Ssam	"Ethernet",
181185380Ssam	"#98",
182185380Ssam	"#99",
183185380Ssam	"#100",
184185380Ssam	"#101",
185185380Ssam	"#102",
186185380Ssam	"PIM",
187185380Ssam	"#104",
188185380Ssam	"#105",
189185380Ssam	"#106",
190185380Ssam	"#107",
191185380Ssam	"#108",
192185380Ssam	"#109",
193185380Ssam	"#110",
194185380Ssam	"#111",
195185380Ssam	"#112",
196185380Ssam	"#113",
197185380Ssam	"#114",
198185380Ssam	"#115",
199185380Ssam	"#116",
200185380Ssam	"#117",
201185380Ssam	"#118",
202185380Ssam	"#119",
203185380Ssam	"#120",
204185380Ssam	"#121",
205185380Ssam	"#122",
206185380Ssam	"#123",
207185380Ssam	"#124",
208185380Ssam	"#125",
209185380Ssam	"#126",
210185380Ssam	"#127",
211185380Ssam	"#128",
212185380Ssam	"#129",
213185380Ssam	"#130",
214185380Ssam	"#131",
215185380Ssam	"#132",
216185380Ssam	"#133",
217185380Ssam	"#134",
218185380Ssam	"#135",
219185380Ssam	"#136",
220185380Ssam	"#137",
221185380Ssam	"#138",
222185380Ssam	"#139",
223185380Ssam	"#140",
224185380Ssam	"#141",
225185380Ssam	"#142",
226185380Ssam	"#143",
227185380Ssam	"#144",
228185380Ssam	"#145",
229185380Ssam	"#146",
230185380Ssam	"#147",
231185380Ssam	"#148",
232185380Ssam	"#149",
233185380Ssam	"#150",
234185380Ssam	"#151",
235185380Ssam	"#152",
236185380Ssam	"#153",
237185380Ssam	"#154",
238185380Ssam	"#155",
239185380Ssam	"#156",
240185380Ssam	"#157",
241185380Ssam	"#158",
242185380Ssam	"#159",
243185380Ssam	"#160",
244185380Ssam	"#161",
245185380Ssam	"#162",
246185380Ssam	"#163",
247185380Ssam	"#164",
248185380Ssam	"#165",
249185380Ssam	"#166",
250185380Ssam	"#167",
251185380Ssam	"#168",
252185380Ssam	"#169",
253185380Ssam	"#170",
254	"#171",
255	"#172",
256	"#173",
257	"#174",
258	"#175",
259	"#176",
260	"#177",
261	"#178",
262	"#179",
263	"#180",
264	"#181",
265	"#182",
266	"#183",
267	"#184",
268	"#185",
269	"#186",
270	"#187",
271	"#188",
272	"#189",
273	"#180",
274	"#191",
275	"#192",
276	"#193",
277	"#194",
278	"#195",
279	"#196",
280	"#197",
281	"#198",
282	"#199",
283	"#200",
284	"#201",
285	"#202",
286	"#203",
287	"#204",
288	"#205",
289	"#206",
290	"#207",
291	"#208",
292	"#209",
293	"#210",
294	"#211",
295	"#212",
296	"#213",
297	"#214",
298	"#215",
299	"#216",
300	"#217",
301	"#218",
302	"#219",
303	"#220",
304	"#221",
305	"#222",
306	"#223",
307	"#224",
308	"#225",
309	"#226",
310	"#227",
311	"#228",
312	"#229",
313	"#230",
314	"#231",
315	"#232",
316	"#233",
317	"#234",
318	"#235",
319	"#236",
320	"#237",
321	"#238",
322	"#239",
323	"#240",
324	"#241",
325	"#242",
326	"#243",
327	"#244",
328	"#245",
329	"#246",
330	"#247",
331	"#248",
332	"#249",
333	"#250",
334	"#251",
335	"#252",
336	"#253",
337	"#254",
338	"#255",
339};
340
341static char *srcrule_str[] = {
342	"first candidate",
343	"same address",
344	"appropriate scope",
345	"deprecated address",
346	"home address",
347	"outgoing interface",
348	"matching label",
349	"public/temporary address",
350	"alive interface",
351	"preferred interface",
352	"rule #10",
353	"rule #11",
354	"rule #12",
355	"rule #13",
356	"longest match",
357	"rule #15",
358};
359
360/*
361 * Dump IP6 statistics structure.
362 */
363void
364ip6_stats(u_long off __unused, const char *name, int af1 __unused)
365{
366	struct ip6stat ip6stat;
367	int first, i;
368	int mib[4];
369	size_t len;
370
371	mib[0] = CTL_NET;
372	mib[1] = PF_INET6;
373	mib[2] = IPPROTO_IPV6;
374	mib[3] = IPV6CTL_STATS;
375
376	len = sizeof ip6stat;
377	memset(&ip6stat, 0, len);
378	if (sysctl(mib, 4, &ip6stat, &len, (void *)0, 0) < 0)
379		return;
380	printf("%s:\n", name);
381
382#define	p(f, m) if (ip6stat.f || sflag <= 1) \
383    printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f))
384#define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
385    printf(m, (unsigned long long)ip6stat.f)
386
387	p(ip6s_total, "\t%llu total packet%s received\n");
388	p1a(ip6s_toosmall, "\t%llu with size smaller than minimum\n");
389	p1a(ip6s_tooshort, "\t%llu with data size < data length\n");
390	p1a(ip6s_badoptions, "\t%llu with bad options\n");
391	p1a(ip6s_badvers, "\t%llu with incorrect version number\n");
392	p(ip6s_fragments, "\t%llu fragment%s received\n");
393	p(ip6s_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n");
394	p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
395	p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n");
396	p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n");
397	p(ip6s_delivered, "\t%llu packet%s for this host\n");
398	p(ip6s_forward, "\t%llu packet%s forwarded\n");
399	p(ip6s_cantforward, "\t%llu packet%s not forwardable\n");
400	p(ip6s_redirectsent, "\t%llu redirect%s sent\n");
401	p(ip6s_localout, "\t%llu packet%s sent from this host\n");
402	p(ip6s_rawout, "\t%llu packet%s sent with fabricated ip header\n");
403	p(ip6s_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n");
404	p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n");
405	p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n");
406	p(ip6s_ofragments, "\t%llu fragment%s created\n");
407	p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
408	p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n");
409	p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\n");
410	for (first = 1, i = 0; i < 256; i++)
411		if (ip6stat.ip6s_nxthist[i] != 0) {
412			if (first) {
413				printf("\tInput histogram:\n");
414				first = 0;
415			}
416			printf("\t\t%s: %llu\n", ip6nh[i],
417			    (unsigned long long)ip6stat.ip6s_nxthist[i]);
418		}
419	printf("\tMbuf statistics:\n");
420	printf("\t\t%llu one mbuf\n", (unsigned long long)ip6stat.ip6s_m1);
421	for (first = 1, i = 0; i < 32; i++) {
422		char ifbuf[IFNAMSIZ];
423		if (ip6stat.ip6s_m2m[i] != 0) {
424			if (first) {
425				printf("\t\ttwo or more mbuf:\n");
426				first = 0;
427			}
428			printf("\t\t\t%s= %llu\n",
429			    if_indextoname(i, ifbuf),
430			    (unsigned long long)ip6stat.ip6s_m2m[i]);
431		}
432	}
433	printf("\t\t%llu one ext mbuf\n",
434	    (unsigned long long)ip6stat.ip6s_mext1);
435	printf("\t\t%llu two or more ext mbuf\n",
436	    (unsigned long long)ip6stat.ip6s_mext2m);
437	p(ip6s_exthdrtoolong,
438	    "\t%llu packet%s whose headers are not continuous\n");
439	p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n");
440	p(ip6s_toomanyhdr,
441	    "\t%llu packet%s discarded because of too many headers\n");
442
443	/* for debugging source address selection */
444#define PRINT_SCOPESTAT(s,i) do {\
445		switch(i) { /* XXX hardcoding in each case */\
446		case 1:\
447			p(s, "\t\t%llu node-local%s\n");\
448			break;\
449		case 2:\
450			p(s,"\t\t%llu link-local%s\n");\
451			break;\
452		case 5:\
453			p(s,"\t\t%llu site-local%s\n");\
454			break;\
455		case 14:\
456			p(s,"\t\t%llu global%s\n");\
457			break;\
458		default:\
459			printf("\t\t%llu addresses scope=%x\n",\
460			    (unsigned long long)ip6stat.s, i);\
461		}\
462	} while (0);
463
464	p(ip6s_sources_none,
465	  "\t%llu failure%s of source address selection\n");
466	for (first = 1, i = 0; i < 16; i++) {
467		if (ip6stat.ip6s_sources_sameif[i]) {
468			if (first) {
469				printf("\tsource addresses on an outgoing I/F\n");
470				first = 0;
471			}
472			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
473		}
474	}
475	for (first = 1, i = 0; i < 16; i++) {
476		if (ip6stat.ip6s_sources_otherif[i]) {
477			if (first) {
478				printf("\tsource addresses on a non-outgoing I/F\n");
479				first = 0;
480			}
481			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
482		}
483	}
484	for (first = 1, i = 0; i < 16; i++) {
485		if (ip6stat.ip6s_sources_samescope[i]) {
486			if (first) {
487				printf("\tsource addresses of same scope\n");
488				first = 0;
489			}
490			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
491		}
492	}
493	for (first = 1, i = 0; i < 16; i++) {
494		if (ip6stat.ip6s_sources_otherscope[i]) {
495			if (first) {
496				printf("\tsource addresses of a different scope\n");
497				first = 0;
498			}
499			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
500		}
501	}
502	for (first = 1, i = 0; i < 16; i++) {
503		if (ip6stat.ip6s_sources_deprecated[i]) {
504			if (first) {
505				printf("\tdeprecated source addresses\n");
506				first = 0;
507			}
508			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
509		}
510	}
511
512	p1a(ip6s_forward_cachehit, "\t%llu forward cache hit\n");
513	p1a(ip6s_forward_cachemiss, "\t%llu forward cache miss\n");
514	printf("\tSource addresses selection rule applied:\n");
515	for (i = 0; i < 16; i++) {
516		if (ip6stat.ip6s_sources_rule[i])
517			printf("\t\t%llu %s\n", ip6stat.ip6s_sources_rule[i],
518			       srcrule_str[i]);
519	}
520#undef p
521#undef p1a
522}
523
524/*
525 * Dump IPv6 per-interface statistics based on RFC 2465.
526 */
527void
528ip6_ifstats(char *ifname)
529{
530	struct in6_ifreq ifr;
531	int s;
532#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
533    printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
534#define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
535    printf(m, (unsigned long long)ip6stat.f)
536
537	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
538		perror("Warning: socket(AF_INET6)");
539		return;
540	}
541
542	strcpy(ifr.ifr_name, ifname);
543	printf("ip6 on %s:\n", ifr.ifr_name);
544
545	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
546		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
547		goto end;
548	}
549
550	p(ifs6_in_receive, "\t%llu total input datagram%s\n");
551	p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
552	p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
553	p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
554	p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
555	p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
556	p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
557	p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
558	p(ifs6_in_deliver,
559	  "\t%llu datagram%s delivered to an upper layer protocol\n");
560	p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
561	p(ifs6_out_request,
562	  "\t%llu datagram%s sent from an upper layer protocol\n");
563	p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
564	p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
565	p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
566	p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
567	p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
568	p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
569	p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembly\n");
570	p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
571	p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
572
573  end:
574	close(s);
575
576#undef p
577#undef p_5
578}
579
580static	const char *icmp6names[] = {
581	"#0",
582	"unreach",
583	"packet too big",
584	"time exceed",
585	"parameter problem",
586	"#5",
587	"#6",
588	"#7",
589	"#8",
590	"#9",
591	"#10",
592	"#11",
593	"#12",
594	"#13",
595	"#14",
596	"#15",
597	"#16",
598	"#17",
599	"#18",
600	"#19",
601	"#20",
602	"#21",
603	"#22",
604	"#23",
605	"#24",
606	"#25",
607	"#26",
608	"#27",
609	"#28",
610	"#29",
611	"#30",
612	"#31",
613	"#32",
614	"#33",
615	"#34",
616	"#35",
617	"#36",
618	"#37",
619	"#38",
620	"#39",
621	"#40",
622	"#41",
623	"#42",
624	"#43",
625	"#44",
626	"#45",
627	"#46",
628	"#47",
629	"#48",
630	"#49",
631	"#50",
632	"#51",
633	"#52",
634	"#53",
635	"#54",
636	"#55",
637	"#56",
638	"#57",
639	"#58",
640	"#59",
641	"#60",
642	"#61",
643	"#62",
644	"#63",
645	"#64",
646	"#65",
647	"#66",
648	"#67",
649	"#68",
650	"#69",
651	"#70",
652	"#71",
653	"#72",
654	"#73",
655	"#74",
656	"#75",
657	"#76",
658	"#77",
659	"#78",
660	"#79",
661	"#80",
662	"#81",
663	"#82",
664	"#83",
665	"#84",
666	"#85",
667	"#86",
668	"#87",
669	"#88",
670	"#89",
671	"#80",
672	"#91",
673	"#92",
674	"#93",
675	"#94",
676	"#95",
677	"#96",
678	"#97",
679	"#98",
680	"#99",
681	"#100",
682	"#101",
683	"#102",
684	"#103",
685	"#104",
686	"#105",
687	"#106",
688	"#107",
689	"#108",
690	"#109",
691	"#110",
692	"#111",
693	"#112",
694	"#113",
695	"#114",
696	"#115",
697	"#116",
698	"#117",
699	"#118",
700	"#119",
701	"#120",
702	"#121",
703	"#122",
704	"#123",
705	"#124",
706	"#125",
707	"#126",
708	"#127",
709	"echo",
710	"echo reply",
711	"multicast listener query",
712	"multicast listener report",
713	"multicast listener done",
714	"router solicitation",
715	"router advertisement",
716	"neighbor solicitation",
717	"neighbor advertisement",
718	"redirect",
719	"router renumbering",
720	"node information request",
721	"node information reply",
722	"inverse neighbor solicitation",
723	"inverse neighbor advertisement",
724	"#143",
725	"#144",
726	"#145",
727	"#146",
728	"#147",
729	"#148",
730	"#149",
731	"#150",
732	"#151",
733	"#152",
734	"#153",
735	"#154",
736	"#155",
737	"#156",
738	"#157",
739	"#158",
740	"#159",
741	"#160",
742	"#161",
743	"#162",
744	"#163",
745	"#164",
746	"#165",
747	"#166",
748	"#167",
749	"#168",
750	"#169",
751	"#170",
752	"#171",
753	"#172",
754	"#173",
755	"#174",
756	"#175",
757	"#176",
758	"#177",
759	"#178",
760	"#179",
761	"#180",
762	"#181",
763	"#182",
764	"#183",
765	"#184",
766	"#185",
767	"#186",
768	"#187",
769	"#188",
770	"#189",
771	"#180",
772	"#191",
773	"#192",
774	"#193",
775	"#194",
776	"#195",
777	"#196",
778	"#197",
779	"#198",
780	"#199",
781	"#200",
782	"#201",
783	"#202",
784	"#203",
785	"#204",
786	"#205",
787	"#206",
788	"#207",
789	"#208",
790	"#209",
791	"#210",
792	"#211",
793	"#212",
794	"#213",
795	"#214",
796	"#215",
797	"#216",
798	"#217",
799	"#218",
800	"#219",
801	"#220",
802	"#221",
803	"#222",
804	"#223",
805	"#224",
806	"#225",
807	"#226",
808	"#227",
809	"#228",
810	"#229",
811	"#230",
812	"#231",
813	"#232",
814	"#233",
815	"#234",
816	"#235",
817	"#236",
818	"#237",
819	"#238",
820	"#239",
821	"#240",
822	"#241",
823	"#242",
824	"#243",
825	"#244",
826	"#245",
827	"#246",
828	"#247",
829	"#248",
830	"#249",
831	"#250",
832	"#251",
833	"#252",
834	"#253",
835	"#254",
836	"#255",
837};
838
839/*
840 * Dump ICMP6 statistics.
841 */
842void
843icmp6_stats(u_long off __unused, const char *name, int af1 __unused)
844{
845	struct icmp6stat icmp6stat;
846	int i, first;
847	int mib[4];
848	size_t len;
849
850	mib[0] = CTL_NET;
851	mib[1] = PF_INET6;
852	mib[2] = IPPROTO_ICMPV6;
853	mib[3] = ICMPV6CTL_STATS;
854
855	len = sizeof icmp6stat;
856	memset(&icmp6stat, 0, len);
857	if (sysctl(mib, 4, &icmp6stat, &len, (void *)0, 0) < 0)
858		return;
859	printf("%s:\n", name);
860
861#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
862    printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f))
863#define p_5(f, m) printf(m, (unsigned long long)icmp6stat.f)
864
865	p(icp6s_error, "\t%llu call%s to icmp6_error\n");
866	p(icp6s_canterror,
867	    "\t%llu error%s not generated in response to an icmp6 message\n");
868	p(icp6s_toofreq,
869	  "\t%llu error%s not generated because of rate limitation\n");
870#define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
871	for (first = 1, i = 0; i < NELEM; i++)
872		if (icmp6stat.icp6s_outhist[i] != 0) {
873			if (first) {
874				printf("\tOutput histogram:\n");
875				first = 0;
876			}
877			printf("\t\t%s: %llu\n", icmp6names[i],
878			    (unsigned long long)icmp6stat.icp6s_outhist[i]);
879		}
880#undef NELEM
881	p(icp6s_badcode, "\t%llu message%s with bad code fields\n");
882	p(icp6s_tooshort, "\t%llu message%s < minimum length\n");
883	p(icp6s_checksum, "\t%llu bad checksum%s\n");
884	p(icp6s_badlen, "\t%llu message%s with bad length\n");
885#define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
886	for (first = 1, i = 0; i < NELEM; i++)
887		if (icmp6stat.icp6s_inhist[i] != 0) {
888			if (first) {
889				printf("\tInput histogram:\n");
890				first = 0;
891			}
892			printf("\t\t%s: %llu\n", icmp6names[i],
893			    (unsigned long long)icmp6stat.icp6s_inhist[i]);
894		}
895#undef NELEM
896	printf("\tHistogram of error messages to be generated:\n");
897	p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n");
898	p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n");
899	p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n");
900	p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n");
901	p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n");
902	p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n");
903	p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n");
904	p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n");
905	p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n");
906	p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n");
907	p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n");
908	p_5(icp6s_oredirect, "\t\t%llu redirect\n");
909	p_5(icp6s_ounknown, "\t\t%llu unknown\n");
910
911	p(icp6s_reflect, "\t%llu message response%s generated\n");
912	p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n");
913	p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n");
914	p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n");
915	p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n");
916	p(icp6s_badrs, "\t%llu bad router solicitation message%s\n");
917	p(icp6s_badra, "\t%llu bad router advertisement message%s\n");
918	p(icp6s_badredirect, "\t%llu bad redirect message%s\n");
919	p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
920#undef p
921#undef p_5
922}
923
924/*
925 * Dump ICMPv6 per-interface statistics based on RFC 2466.
926 */
927void
928icmp6_ifstats(char *ifname)
929{
930	struct in6_ifreq ifr;
931	int s;
932#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
933    printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
934#define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
935    printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
936
937	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
938		perror("Warning: socket(AF_INET6)");
939		return;
940	}
941
942	strcpy(ifr.ifr_name, ifname);
943	printf("icmp6 on %s:\n", ifr.ifr_name);
944
945	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
946		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
947		goto end;
948	}
949
950	p(ifs6_in_msg, "\t%llu total input message%s\n");
951	p(ifs6_in_error, "\t%llu total input error message%s\n");
952	p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
953	p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
954	p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
955	p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
956	p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
957	p(ifs6_in_echo, "\t%llu input echo request%s\n");
958	p2(ifs6_in_echoreply, "\t%llu input echo repl%s\n");
959	p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
960	p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
961	p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
962	p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
963	p(ifs6_in_redirect, "\t%llu input redirect%s\n");
964	p2(ifs6_in_mldquery, "\t%llu input MLD quer%s\n");
965	p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
966	p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
967
968	p(ifs6_out_msg, "\t%llu total output message%s\n");
969	p(ifs6_out_error, "\t%llu total output error message%s\n");
970	p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
971	p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
972	p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
973	p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
974	p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
975	p(ifs6_out_echo, "\t%llu output echo request%s\n");
976	p2(ifs6_out_echoreply, "\t%llu output echo repl%s\n");
977	p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
978	p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
979	p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
980	p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
981	p(ifs6_out_redirect, "\t%llu output redirect%s\n");
982	p2(ifs6_out_mldquery, "\t%llu output MLD quer%s\n");
983	p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
984	p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
985
986  end:
987	close(s);
988#undef p
989}
990
991/*
992 * Dump PIM statistics structure.
993 */
994void
995pim6_stats(u_long off __unused, const char *name, int af1 __unused)
996{
997	struct pim6stat pim6stat;
998
999	if (off == 0)
1000		return;
1001	if (kread(off, (char *)&pim6stat, sizeof(pim6stat)))
1002		return;
1003	printf("%s:\n", name);
1004
1005#define	p(f, m) if (pim6stat.f || sflag <= 1) \
1006    printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f))
1007	p(pim6s_rcv_total, "\t%llu message%s received\n");
1008	p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
1009	p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n");
1010	p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n");
1011	p(pim6s_rcv_registers, "\t%llu register%s received\n");
1012	p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n");
1013	p(pim6s_snd_registers, "\t%llu register%s sent\n");
1014#undef p
1015}
1016
1017/*
1018 * Dump raw ip6 statistics structure.
1019 */
1020void
1021rip6_stats(u_long off __unused, const char *name, int af1 __unused)
1022{
1023	struct rip6stat rip6stat;
1024	u_quad_t delivered;
1025	int mib[4];
1026	size_t l;
1027
1028	mib[0] = CTL_NET;
1029	mib[1] = PF_INET6;
1030	mib[2] = IPPROTO_IPV6;
1031	mib[3] = IPV6CTL_RIP6STATS;
1032	l = sizeof(rip6stat);
1033	if (sysctl(mib, 4, &rip6stat, &l, NULL, 0) < 0) {
1034		/* Just shut up if the kernel doesn't have ipv6. */
1035		if (errno != ENOENT)
1036			perror("Warning: sysctl(net.inet6.ip6.rip6stats)");
1037		return;
1038	}
1039
1040	printf("%s:\n", name);
1041
1042#define	p(f, m) if (rip6stat.f || sflag <= 1) \
1043    printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f))
1044	p(rip6s_ipackets, "\t%llu message%s received\n");
1045	p(rip6s_isum, "\t%llu checksum calcuration%s on inbound\n");
1046	p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
1047	p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
1048	p(rip6s_nosockmcast,
1049	    "\t%llu multicast message%s dropped due to no socket\n");
1050	p(rip6s_fullsock,
1051	    "\t%llu message%s dropped due to full socket buffers\n");
1052	delivered = rip6stat.rip6s_ipackets -
1053		    rip6stat.rip6s_badsum -
1054		    rip6stat.rip6s_nosock -
1055		    rip6stat.rip6s_nosockmcast -
1056		    rip6stat.rip6s_fullsock;
1057	if (delivered || sflag <= 1)
1058		printf("\t%llu delivered\n", (unsigned long long)delivered);
1059	p(rip6s_opackets, "\t%llu datagram%s output\n");
1060#undef p
1061}
1062
1063/*
1064 * Pretty print an Internet address (net address + port).
1065 * Take numeric_addr and numeric_port into consideration.
1066 */
1067#define GETSERVBYPORT6(port, proto, ret)\
1068{\
1069	if (strcmp((proto), "tcp6") == 0)\
1070		(ret) = getservbyport((int)(port), "tcp");\
1071	else if (strcmp((proto), "udp6") == 0)\
1072		(ret) = getservbyport((int)(port), "udp");\
1073	else\
1074		(ret) = getservbyport((int)(port), (proto));\
1075};
1076
1077void
1078inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
1079{
1080	struct servent *sp = 0;
1081	char line[80], *cp;
1082	int width;
1083
1084	sprintf(line, "%.*s.", Wflag ? 39 :
1085		(Aflag && !numeric) ? 12 : 16, inet6name(in6));
1086	cp = index(line, '\0');
1087	if (!numeric && port)
1088		GETSERVBYPORT6(port, proto, sp);
1089	if (sp || port == 0)
1090		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
1091	else
1092		sprintf(cp, "%d", ntohs((u_short)port));
1093	width = Wflag ? 45 : Aflag ? 18 : 22;
1094	printf("%-*.*s ", width, width, line);
1095}
1096
1097/*
1098 * Construct an Internet address representation.
1099 * If the numeric_addr has been supplied, give
1100 * numeric value, otherwise try for symbolic name.
1101 */
1102
1103char *
1104inet6name(struct in6_addr *in6p)
1105{
1106	char *cp;
1107	static char line[50];
1108	struct hostent *hp;
1109	static char domain[MAXHOSTNAMELEN];
1110	static int first = 1;
1111
1112	if (first && !numeric_addr) {
1113		first = 0;
1114		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1115		    (cp = index(domain, '.')))
1116			(void) strcpy(domain, cp + 1);
1117		else
1118			domain[0] = 0;
1119	}
1120	cp = 0;
1121	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1122		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1123		if (hp) {
1124			if ((cp = index(hp->h_name, '.')) &&
1125			    !strcmp(cp + 1, domain))
1126				*cp = 0;
1127			cp = hp->h_name;
1128		}
1129	}
1130	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1131		strcpy(line, "*");
1132	else if (cp)
1133		strcpy(line, cp);
1134	else
1135		sprintf(line, "%s",
1136			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
1137				sizeof(ntop_buf)));
1138	return (line);
1139}
1140#endif /*INET6*/
1141