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