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