inet6.c revision 1.46
1/*	$OpenBSD: inet6.c,v 1.46 2014/08/14 12:55:50 mpi Exp $	*/
2/*	BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp	*/
3/*
4 * Copyright (c) 1983, 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/param.h>
33#include <sys/socket.h>
34#include <sys/socketvar.h>
35#include <sys/ioctl.h>
36#include <sys/protosw.h>
37#include <sys/sysctl.h>
38
39#include <net/route.h>
40#include <net/if.h>
41#include <netinet/in.h>
42#include <netinet/ip6.h>
43#include <netinet/icmp6.h>
44#include <netinet/ip.h>
45#include <netinet/ip_var.h>
46#include <netinet6/ip6_var.h>
47#include <netinet6/in6_var.h>
48#include <netinet6/pim6_var.h>
49#include <netinet6/raw_ip6.h>
50#include <netinet6/ip6_divert.h>
51
52#include <arpa/inet.h>
53#if 0
54#include "gethostbyname2.h"
55#endif
56#include <netdb.h>
57
58#include <err.h>
59#include <errno.h>
60#include <stdio.h>
61#include <string.h>
62#include <unistd.h>
63#include "netstat.h"
64
65struct	socket sockb;
66
67char	*inet6name(struct in6_addr *);
68void	inet6print(struct in6_addr *, int, char *);
69
70static	char *ip6nh[] = {
71	"hop by hop",
72	"ICMP",
73	"IGMP",
74	"#3",
75	"IP",
76	"#5",
77	"TCP",
78	"#7",
79	"#8",
80	"#9",
81	"#10",
82	"#11",
83	"#12",
84	"#13",
85	"#14",
86	"#15",
87	"#16",
88	"UDP",
89	"#18",
90	"#19",
91	"#20",
92	"#21",
93	"IDP",
94	"#23",
95	"#24",
96	"#25",
97	"#26",
98	"#27",
99	"#28",
100	"TP",
101	"#30",
102	"#31",
103	"#32",
104	"#33",
105	"#34",
106	"#35",
107	"#36",
108	"#37",
109	"#38",
110	"#39",
111	"#40",
112	"IP6",
113	"#42",
114	"routing",
115	"fragment",
116	"#45",
117	"#46",
118	"#47",
119	"#48",
120	"#49",
121	"ESP",
122	"AH",
123	"#52",
124	"#53",
125	"#54",
126	"#55",
127	"#56",
128	"#57",
129	"ICMP6",
130	"no next header",
131	"destination option",
132	"#61",
133	"#62",
134	"#63",
135	"#64",
136	"#65",
137	"#66",
138	"#67",
139	"#68",
140	"#69",
141	"#70",
142	"#71",
143	"#72",
144	"#73",
145	"#74",
146	"#75",
147	"#76",
148	"#77",
149	"#78",
150	"#79",
151	"ISOIP",
152	"#81",
153	"#82",
154	"#83",
155	"#84",
156	"#85",
157	"#86",
158	"#87",
159	"#88",
160	"OSPF",
161	"#80",
162	"#91",
163	"#92",
164	"#93",
165	"#94",
166	"#95",
167	"#96",
168	"Ethernet",
169	"#98",
170	"#99",
171	"#100",
172	"#101",
173	"#102",
174	"PIM",
175	"#104",
176	"#105",
177	"#106",
178	"#107",
179	"#108",
180	"#109",
181	"#110",
182	"#111",
183	"#112",
184	"#113",
185	"#114",
186	"#115",
187	"#116",
188	"#117",
189	"#118",
190	"#119",
191	"#120",
192	"#121",
193	"#122",
194	"#123",
195	"#124",
196	"#125",
197	"#126",
198	"#127",
199	"#128",
200	"#129",
201	"#130",
202	"#131",
203	"#132",
204	"#133",
205	"#134",
206	"#135",
207	"#136",
208	"#137",
209	"#138",
210	"#139",
211	"#140",
212	"#141",
213	"#142",
214	"#143",
215	"#144",
216	"#145",
217	"#146",
218	"#147",
219	"#148",
220	"#149",
221	"#150",
222	"#151",
223	"#152",
224	"#153",
225	"#154",
226	"#155",
227	"#156",
228	"#157",
229	"#158",
230	"#159",
231	"#160",
232	"#161",
233	"#162",
234	"#163",
235	"#164",
236	"#165",
237	"#166",
238	"#167",
239	"#168",
240	"#169",
241	"#170",
242	"#171",
243	"#172",
244	"#173",
245	"#174",
246	"#175",
247	"#176",
248	"#177",
249	"#178",
250	"#179",
251	"#180",
252	"#181",
253	"#182",
254	"#183",
255	"#184",
256	"#185",
257	"#186",
258	"#187",
259	"#188",
260	"#189",
261	"#180",
262	"#191",
263	"#192",
264	"#193",
265	"#194",
266	"#195",
267	"#196",
268	"#197",
269	"#198",
270	"#199",
271	"#200",
272	"#201",
273	"#202",
274	"#203",
275	"#204",
276	"#205",
277	"#206",
278	"#207",
279	"#208",
280	"#209",
281	"#210",
282	"#211",
283	"#212",
284	"#213",
285	"#214",
286	"#215",
287	"#216",
288	"#217",
289	"#218",
290	"#219",
291	"#220",
292	"#221",
293	"#222",
294	"#223",
295	"#224",
296	"#225",
297	"#226",
298	"#227",
299	"#228",
300	"#229",
301	"#230",
302	"#231",
303	"#232",
304	"#233",
305	"#234",
306	"#235",
307	"#236",
308	"#237",
309	"#238",
310	"#239",
311	"#240",
312	"#241",
313	"#242",
314	"#243",
315	"#244",
316	"#245",
317	"#246",
318	"#247",
319	"#248",
320	"#249",
321	"#250",
322	"#251",
323	"#252",
324	"#253",
325	"#254",
326	"#255",
327};
328
329/*
330 * Dump IP6 statistics structure.
331 */
332void
333ip6_stats(char *name)
334{
335	struct ip6stat ip6stat;
336	int first, i;
337	struct protoent *ep;
338	const char *n;
339	int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_STATS };
340	size_t len = sizeof(ip6stat);
341
342	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
343	    &ip6stat, &len, NULL, 0) == -1) {
344		if (errno != ENOPROTOOPT)
345			warn("%s", name);
346		return;
347	}
348
349	printf("%s:\n", name);
350#define	p(f, m) if (ip6stat.f || sflag <= 1) \
351	printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f))
352#define	p1(f, m) if (ip6stat.f || sflag <= 1) \
353	printf(m, (unsigned long long)ip6stat.f)
354
355	p(ip6s_total, "\t%llu total packet%s received\n");
356	p1(ip6s_toosmall, "\t%llu with size smaller than minimum\n");
357	p1(ip6s_tooshort, "\t%llu with data size < data length\n");
358	p1(ip6s_badoptions, "\t%llu with bad options\n");
359	p1(ip6s_badvers, "\t%llu with incorrect version number\n");
360	p(ip6s_fragments, "\t%llu fragment%s received\n");
361	p(ip6s_fragdropped,
362	    "\t%llu fragment%s dropped (duplicates or out of space)\n");
363	p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n");
364	p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n");
365	p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n");
366	p(ip6s_delivered, "\t%llu packet%s for this host\n");
367	p(ip6s_forward, "\t%llu packet%s forwarded\n");
368	p(ip6s_cantforward, "\t%llu packet%s not forwardable\n");
369	p(ip6s_redirectsent, "\t%llu redirect%s sent\n");
370	p(ip6s_localout, "\t%llu packet%s sent from this host\n");
371	p(ip6s_rawout, "\t%llu packet%s sent with fabricated ip header\n");
372	p(ip6s_odropped,
373	    "\t%llu output packet%s dropped due to no bufs, etc.\n");
374	p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n");
375	p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n");
376	p(ip6s_ofragments, "\t%llu fragment%s created\n");
377	p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n");
378	p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n");
379	p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\n");
380	for (first = 1, i = 0; i < 256; i++)
381		if (ip6stat.ip6s_nxthist[i] != 0) {
382			if (first) {
383				printf("\tInput packet histogram:\n");
384				first = 0;
385			}
386			n = NULL;
387			if (ip6nh[i])
388				n = ip6nh[i];
389			else if ((ep = getprotobynumber(i)) != NULL)
390				n = ep->p_name;
391			if (n)
392				printf("\t\t%s: %llu\n", n,
393				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
394			else
395				printf("\t\t#%d: %llu\n", i,
396				    (unsigned long long)ip6stat.ip6s_nxthist[i]);
397		}
398	printf("\tMbuf statistics:\n");
399	p(ip6s_m1, "\t\t%llu one mbuf%s\n");
400	for (first = 1, i = 0; i < 32; i++) {
401		char ifbuf[IFNAMSIZ];
402		if (ip6stat.ip6s_m2m[i] != 0) {
403			if (first) {
404				printf("\t\ttwo or more mbuf:\n");
405				first = 0;
406			}
407			printf("\t\t\t%s = %llu\n",
408			    if_indextoname(i, ifbuf),
409			    (unsigned long long)ip6stat.ip6s_m2m[i]);
410		}
411	}
412	p(ip6s_mext1, "\t\t%llu one ext mbuf%s\n");
413	p(ip6s_mext2m, "\t\t%llu two or more ext mbuf%s\n");
414	p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n");
415	p(ip6s_toomanyhdr,
416	    "\t%llu packet%s discarded due to too many headers\n");
417
418	/* for debugging source address selection */
419#define PRINT_SCOPESTAT(s,i) do {\
420		switch(i) { /* XXX hardcoding in each case */\
421		case 1:\
422			p(s, "\t\t%llu node-local%s\n");\
423			break;\
424		case 2:\
425			p(s, "\t\t%llu link-local%s\n");\
426			break;\
427		case 5:\
428			p(s, "\t\t%llu site-local%s\n");\
429			break;\
430		case 14:\
431			p(s, "\t\t%llu global%s\n");\
432			break;\
433		default:\
434			printf("\t\t%llu addresses scope=%x\n",\
435			    (unsigned long long)ip6stat.s, i);\
436		}\
437	} while(0);
438
439	p(ip6s_sources_none,
440	    "\t%llu failure%s of source address selection\n");
441	for (first = 1, i = 0; i < 16; i++) {
442		if (ip6stat.ip6s_sources_sameif[i]) {
443			if (first) {
444				printf("\tsource addresses on an outgoing I/F\n");
445				first = 0;
446			}
447			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
448		}
449	}
450	for (first = 1, i = 0; i < 16; i++) {
451		if (ip6stat.ip6s_sources_otherif[i]) {
452			if (first) {
453				printf("\tsource addresses on a non-outgoing I/F\n");
454				first = 0;
455			}
456			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
457		}
458	}
459	for (first = 1, i = 0; i < 16; i++) {
460		if (ip6stat.ip6s_sources_samescope[i]) {
461			if (first) {
462				printf("\tsource addresses of same scope\n");
463				first = 0;
464			}
465			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
466		}
467	}
468	for (first = 1, i = 0; i < 16; i++) {
469		if (ip6stat.ip6s_sources_otherscope[i]) {
470			if (first) {
471				printf("\tsource addresses of a different scope\n");
472				first = 0;
473			}
474			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
475		}
476	}
477	for (first = 1, i = 0; i < 16; i++) {
478		if (ip6stat.ip6s_sources_deprecated[i]) {
479			if (first) {
480				printf("\tdeprecated source addresses\n");
481				first = 0;
482			}
483			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
484		}
485	}
486
487	p1(ip6s_forward_cachehit, "\t%llu forward cache hit\n");
488	p1(ip6s_forward_cachemiss, "\t%llu forward cache miss\n");
489#undef p
490#undef p1
491}
492
493/*
494 * Dump IPv6 per-interface statistics based on RFC 2465.
495 */
496void
497ip6_ifstats(char *ifname)
498{
499	struct in6_ifreq ifr;
500	int s;
501
502#define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
503	printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, \
504	    plural(ifr.ifr_ifru.ifru_stat.f))
505#define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
506	printf(m, (unsigned long long)ip6stat.f)
507
508	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
509		perror("Warning: socket(AF_INET6)");
510		return;
511	}
512
513	strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
514	printf("ip6 on %s:\n", ifr.ifr_name);
515
516	if (ioctl(s, SIOCGIFSTAT_IN6, &ifr) < 0) {
517		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
518		goto end;
519	}
520
521	p(ifs6_in_receive, "\t%llu total input datagram%s\n");
522	p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
523	p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
524	p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
525	p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
526	p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
527	p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
528	p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
529	p(ifs6_in_deliver,
530	    "\t%llu datagram%s delivered to an upper layer protocol\n");
531	p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
532	p(ifs6_out_request,
533	    "\t%llu datagram%s sent from an upper layer protocol\n");
534	p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
535	p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
536	p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
537	p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
538	p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
539	p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
540	p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
541	p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
542	p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
543
544  end:
545	close(s);
546
547#undef p
548#undef p_5
549}
550
551static	char *icmp6names[] = {
552	"#0",
553	"unreach",
554	"packet too big",
555	"time exceed",
556	"parameter problem",
557	"#5",
558	"#6",
559	"#7",
560	"#8",
561	"#9",
562	"#10",
563	"#11",
564	"#12",
565	"#13",
566	"#14",
567	"#15",
568	"#16",
569	"#17",
570	"#18",
571	"#19",
572	"#20",
573	"#21",
574	"#22",
575	"#23",
576	"#24",
577	"#25",
578	"#26",
579	"#27",
580	"#28",
581	"#29",
582	"#30",
583	"#31",
584	"#32",
585	"#33",
586	"#34",
587	"#35",
588	"#36",
589	"#37",
590	"#38",
591	"#39",
592	"#40",
593	"#41",
594	"#42",
595	"#43",
596	"#44",
597	"#45",
598	"#46",
599	"#47",
600	"#48",
601	"#49",
602	"#50",
603	"#51",
604	"#52",
605	"#53",
606	"#54",
607	"#55",
608	"#56",
609	"#57",
610	"#58",
611	"#59",
612	"#60",
613	"#61",
614	"#62",
615	"#63",
616	"#64",
617	"#65",
618	"#66",
619	"#67",
620	"#68",
621	"#69",
622	"#70",
623	"#71",
624	"#72",
625	"#73",
626	"#74",
627	"#75",
628	"#76",
629	"#77",
630	"#78",
631	"#79",
632	"#80",
633	"#81",
634	"#82",
635	"#83",
636	"#84",
637	"#85",
638	"#86",
639	"#87",
640	"#88",
641	"#89",
642	"#80",
643	"#91",
644	"#92",
645	"#93",
646	"#94",
647	"#95",
648	"#96",
649	"#97",
650	"#98",
651	"#99",
652	"#100",
653	"#101",
654	"#102",
655	"#103",
656	"#104",
657	"#105",
658	"#106",
659	"#107",
660	"#108",
661	"#109",
662	"#110",
663	"#111",
664	"#112",
665	"#113",
666	"#114",
667	"#115",
668	"#116",
669	"#117",
670	"#118",
671	"#119",
672	"#120",
673	"#121",
674	"#122",
675	"#123",
676	"#124",
677	"#125",
678	"#126",
679	"#127",
680	"echo",
681	"echo reply",
682	"multicast listener query",
683	"multicast listener report",
684	"multicast listener done",
685	"router solicitation",
686	"router advertisement",
687	"neighbor solicitation",
688	"neighbor advertisement",
689	"redirect",
690	"router renumbering",
691	"node information request",
692	"node information reply",
693	"#141",
694	"#142",
695	"#143",
696	"#144",
697	"#145",
698	"#146",
699	"#147",
700	"#148",
701	"#149",
702	"#150",
703	"#151",
704	"#152",
705	"#153",
706	"#154",
707	"#155",
708	"#156",
709	"#157",
710	"#158",
711	"#159",
712	"#160",
713	"#161",
714	"#162",
715	"#163",
716	"#164",
717	"#165",
718	"#166",
719	"#167",
720	"#168",
721	"#169",
722	"#170",
723	"#171",
724	"#172",
725	"#173",
726	"#174",
727	"#175",
728	"#176",
729	"#177",
730	"#178",
731	"#179",
732	"#180",
733	"#181",
734	"#182",
735	"#183",
736	"#184",
737	"#185",
738	"#186",
739	"#187",
740	"#188",
741	"#189",
742	"#180",
743	"#191",
744	"#192",
745	"#193",
746	"#194",
747	"#195",
748	"#196",
749	"#197",
750	"#198",
751	"#199",
752	"#200",
753	"#201",
754	"#202",
755	"#203",
756	"#204",
757	"#205",
758	"#206",
759	"#207",
760	"#208",
761	"#209",
762	"#210",
763	"#211",
764	"#212",
765	"#213",
766	"#214",
767	"#215",
768	"#216",
769	"#217",
770	"#218",
771	"#219",
772	"#220",
773	"#221",
774	"#222",
775	"#223",
776	"#224",
777	"#225",
778	"#226",
779	"#227",
780	"#228",
781	"#229",
782	"#230",
783	"#231",
784	"#232",
785	"#233",
786	"#234",
787	"#235",
788	"#236",
789	"#237",
790	"#238",
791	"#239",
792	"#240",
793	"#241",
794	"#242",
795	"#243",
796	"#244",
797	"#245",
798	"#246",
799	"#247",
800	"#248",
801	"#249",
802	"#250",
803	"#251",
804	"#252",
805	"#253",
806	"#254",
807	"#255",
808};
809
810/*
811 * Dump ICMPv6 statistics.
812 */
813void
814icmp6_stats(char *name)
815{
816	struct icmp6stat icmp6stat;
817	int i, first;
818	int mib[] = { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_STATS };
819	size_t len = sizeof(icmp6stat);
820
821	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
822	    &icmp6stat, &len, NULL, 0) == -1) {
823		if (errno != ENOPROTOOPT)
824			warn("%s", name);
825		return;
826	}
827
828	printf("%s:\n", name);
829#define	p(f, m) if (icmp6stat.f || sflag <= 1) \
830	printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f))
831#define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
832	printf(m, (unsigned long long)icmp6stat.f)
833
834	p(icp6s_error, "\t%llu call%s to icmp6_error\n");
835	p(icp6s_canterror,
836	    "\t%llu error%s not generated because old message was icmp6 or so\n");
837	p(icp6s_toofreq,
838	    "\t%llu error%s not generated because of rate limitation\n");
839	for (first = 1, i = 0; i < 256; i++)
840		if (icmp6stat.icp6s_outhist[i] != 0) {
841			if (first) {
842				printf("\tOutput packet histogram:\n");
843				first = 0;
844			}
845			printf("\t\t%s: %llu\n", icmp6names[i],
846			    (unsigned long long)icmp6stat.icp6s_outhist[i]);
847		}
848	p(icp6s_badcode, "\t%llu message%s with bad code fields\n");
849	p(icp6s_tooshort, "\t%llu message%s < minimum length\n");
850	p(icp6s_checksum, "\t%llu bad checksum%s\n");
851	p(icp6s_badlen, "\t%llu message%s with bad length\n");
852	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
853		if (icmp6stat.icp6s_inhist[i] != 0) {
854			if (first) {
855				printf("\tInput packet histogram:\n");
856				first = 0;
857			}
858			printf("\t\t%s: %llu\n", icmp6names[i],
859			    (unsigned long long)icmp6stat.icp6s_inhist[i]);
860		}
861	printf("\tHistogram of error messages to be generated:\n");
862	p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n");
863	p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n");
864	p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n");
865	p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n");
866	p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n");
867	p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n");
868	p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n");
869	p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n");
870	p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n");
871	p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n");
872	p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n");
873	p_5(icp6s_oredirect, "\t\t%llu redirect\n");
874	p_5(icp6s_ounknown, "\t\t%llu unknown\n");
875
876	p(icp6s_reflect, "\t%llu message response%s generated\n");
877	p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n");
878	p(icp6s_nd_badopt, "\t%llu message%s with bad ND options\n");
879	p(icp6s_badns, "\t%llu bad neighbor solicitation message%s\n");
880	p(icp6s_badna, "\t%llu bad neighbor advertisement message%s\n");
881	p(icp6s_badrs, "\t%llu bad router solicitation message%s\n");
882	p(icp6s_badra, "\t%llu bad router advertisement message%s\n");
883	p(icp6s_badredirect, "\t%llu bad redirect message%s\n");
884	p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
885#undef p
886#undef p_5
887}
888
889/*
890 * Dump ICMPv6 per-interface statistics based on RFC 2466.
891 */
892void
893icmp6_ifstats(char *ifname)
894{
895	struct in6_ifreq ifr;
896	int s;
897
898#define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
899	printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, \
900	    plural(ifr.ifr_ifru.ifru_icmp6stat.f))
901
902	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
903		perror("Warning: socket(AF_INET6)");
904		return;
905	}
906
907	strlcpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
908	printf("icmp6 on %s:\n", ifr.ifr_name);
909
910	if (ioctl(s, SIOCGIFSTAT_ICMP6, &ifr) < 0) {
911		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
912		goto end;
913	}
914
915	p(ifs6_in_msg, "\t%llu total input message%s\n");
916	p(ifs6_in_error, "\t%llu total input error message%s\n");
917	p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
918	p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
919	p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
920	p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
921	p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
922	p(ifs6_in_echo, "\t%llu input echo request%s\n");
923	p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
924	p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
925	p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
926	p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
927	p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
928	p(ifs6_in_redirect, "\t%llu input redirect%s\n");
929	p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
930	p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
931	p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
932
933	p(ifs6_out_msg, "\t%llu total output message%s\n");
934	p(ifs6_out_error, "\t%llu total output error message%s\n");
935	p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
936	p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
937	p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
938	p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
939	p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
940	p(ifs6_out_echo, "\t%llu output echo request%s\n");
941	p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
942	p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
943	p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
944	p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
945	p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
946	p(ifs6_out_redirect, "\t%llu output redirect%s\n");
947	p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
948	p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
949	p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
950
951  end:
952	close(s);
953#undef p
954}
955
956/*
957 * Dump PIM statistics structure.
958 */
959void
960pim6_stats(char *name)
961{
962	struct pim6stat pim6stat;
963	int mib[] = { CTL_NET, PF_INET6, IPPROTO_PIM, PIM6CTL_STATS };
964	size_t len = sizeof(pim6stat);
965
966	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
967	    &pim6stat, &len, NULL, 0) == -1) {
968		if (errno != ENOPROTOOPT)
969			warn("%s", name);
970		return;
971	}
972
973	printf("%s:\n", name);
974#define	p(f, m) if (pim6stat.f || sflag <= 1) \
975	printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f))
976
977	p(pim6s_rcv_total, "\t%llu message%s received\n");
978	p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n");
979	p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n");
980	p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n");
981	p(pim6s_rcv_registers, "\t%llu register%s received\n");
982	p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n");
983	p(pim6s_snd_registers, "\t%llu register%s sent\n");
984#undef p
985}
986
987/*
988 * Dump raw ip6 statistics structure.
989 */
990void
991rip6_stats(char *name)
992{
993	struct rip6stat rip6stat;
994	u_int64_t delivered;
995	int mib[] = { CTL_NET, PF_INET6, IPPROTO_RAW, RIPV6CTL_STATS };
996	size_t len = sizeof(rip6stat);
997
998	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
999	    &rip6stat, &len, NULL, 0) == -1) {
1000		if (errno != ENOPROTOOPT)
1001			warn("%s", name);
1002		return;
1003	}
1004
1005	printf("%s:\n", name);
1006
1007#define	p(f, m) if (rip6stat.f || sflag <= 1) \
1008    printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f))
1009	p(rip6s_ipackets, "\t%llu message%s received\n");
1010	p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n");
1011	p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
1012	p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
1013	p(rip6s_nosockmcast,
1014	    "\t%llu multicast message%s dropped due to no socket\n");
1015	p(rip6s_fullsock,
1016	    "\t%llu message%s dropped due to full socket buffers\n");
1017	delivered = rip6stat.rip6s_ipackets -
1018		    rip6stat.rip6s_badsum -
1019		    rip6stat.rip6s_nosock -
1020		    rip6stat.rip6s_nosockmcast -
1021		    rip6stat.rip6s_fullsock;
1022	if (delivered || sflag <= 1)
1023		printf("\t%llu delivered\n", (unsigned long long)delivered);
1024	p(rip6s_opackets, "\t%llu datagram%s output\n");
1025#undef p
1026}
1027
1028/*
1029 * Dump divert6 statistics structure.
1030 */
1031void
1032div6_stats(char *name)
1033{
1034	struct div6stat div6stat;
1035	int mib[] = { CTL_NET, PF_INET6, IPPROTO_DIVERT, DIVERT6CTL_STATS };
1036	size_t len = sizeof(div6stat);
1037
1038	if (sysctl(mib, sizeof(mib) / sizeof(mib[0]),
1039	    &div6stat, &len, NULL, 0) == -1) {
1040		if (errno != ENOPROTOOPT)
1041			warn("%s", name);
1042		return;
1043	}
1044
1045	printf("%s:\n", name);
1046#define p(f, m) if (div6stat.f || sflag <= 1) \
1047    printf(m, div6stat.f, plural(div6stat.f))
1048#define p1(f, m) if (div6stat.f || sflag <= 1) \
1049    printf(m, div6stat.f)
1050	p(divs_ipackets, "\t%lu total packet%s received\n");
1051	p1(divs_noport, "\t%lu dropped due to no socket\n");
1052	p1(divs_fullsock, "\t%lu dropped due to full socket buffers\n");
1053	p(divs_opackets, "\t%lu packet%s output\n");
1054	p1(divs_errors, "\t%lu errors\n");
1055#undef p
1056#undef p1
1057}
1058
1059/*
1060 * Pretty print an Internet address (net address + port).
1061 * If the nflag was specified, use numbers instead of names.
1062 */
1063
1064void
1065inet6print(struct in6_addr *in6, int port, char *proto)
1066{
1067
1068#define GETSERVBYPORT6(port, proto, ret) do { \
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	} while (0)
1076
1077	struct servent *sp = 0;
1078	char line[80], *cp;
1079	int width;
1080	int len = sizeof line;
1081
1082	width = Aflag ? 12 : 16;
1083	if (vflag && width < strlen(inet6name(in6)))
1084		width = strlen(inet6name(in6));
1085	snprintf(line, len, "%.*s.", width, inet6name(in6));
1086	len -= strlen(line);
1087	if (len <= 0)
1088		goto bail;
1089
1090	cp = strchr(line, '\0');
1091	if (!nflag && port)
1092		GETSERVBYPORT6(port, proto, sp);
1093	if (sp || port == 0)
1094		snprintf(cp, len, "%.8s", sp ? sp->s_name : "*");
1095	else
1096		snprintf(cp, len, "%d", ntohs((u_short)port));
1097	width = Aflag ? 18 : 22;
1098	if (vflag && width < strlen(line))
1099		width = strlen(line);
1100bail:
1101	printf(" %-*.*s", width, width, line);
1102}
1103
1104/*
1105 * Construct an Internet address representation.
1106 * If the nflag has been supplied, give
1107 * numeric value, otherwise try for symbolic name.
1108 */
1109
1110char *
1111inet6name(struct in6_addr *in6p)
1112{
1113	char *cp;
1114	static char line[NI_MAXHOST];
1115	struct hostent *hp;
1116	static char domain[MAXHOSTNAMELEN];
1117	static int first = 1;
1118	char hbuf[NI_MAXHOST];
1119	struct sockaddr_in6 sin6;
1120	const int niflag = NI_NUMERICHOST;
1121
1122	if (first && !nflag) {
1123		first = 0;
1124		if (gethostname(domain, sizeof(domain)) == 0 &&
1125		    (cp = strchr(domain, '.')))
1126			(void) strlcpy(domain, cp + 1, sizeof domain);
1127		else
1128			domain[0] = '\0';
1129	}
1130	cp = 0;
1131	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1132		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1133		if (hp) {
1134			if ((cp = strchr(hp->h_name, '.')) &&
1135			    !strcmp(cp + 1, domain))
1136				*cp = 0;
1137			cp = hp->h_name;
1138		}
1139	}
1140	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1141		strlcpy(line, "*", sizeof(line));
1142	else if (cp)
1143		strlcpy(line, cp, sizeof(line));
1144	else {
1145		memset(&sin6, 0, sizeof(sin6));
1146		sin6.sin6_len = sizeof(sin6);
1147		sin6.sin6_family = AF_INET6;
1148		sin6.sin6_addr = *in6p;
1149#ifdef __KAME__
1150		if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
1151		    IN6_IS_ADDR_MC_LINKLOCAL(in6p) ||
1152		    IN6_IS_ADDR_MC_INTFACELOCAL(in6p)) {
1153			sin6.sin6_scope_id =
1154			    ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
1155			sin6.sin6_addr.s6_addr[2] = 0;
1156			sin6.sin6_addr.s6_addr[3] = 0;
1157		}
1158#endif
1159		if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
1160		    hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
1161			strlcpy(hbuf, "?", sizeof hbuf);
1162		strlcpy(line, hbuf, sizeof(line));
1163	}
1164	return (line);
1165}
1166