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