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