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