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