xref: /freebsd/usr.bin/netstat/inet6.c (revision dc60165b73e4c4d829a2cb9fed5cce585e93d9a9)
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, const char *name, int af1 __unused, int proto __unused)
366 {
367 	struct ip6stat ip6stat;
368 	int first, i;
369 	size_t len;
370 
371 	len = sizeof ip6stat;
372 	if (live) {
373 		memset(&ip6stat, 0, len);
374 		if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL,
375 		    0) < 0) {
376 			if (errno != ENOENT)
377 				warn("sysctl: net.inet6.ip6.stats");
378 			return;
379 		}
380 	} else
381 		kread(off, &ip6stat, len);
382 
383 	printf("%s:\n", name);
384 
385 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
386     printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
387 #define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
388     printf(m, (uintmax_t)ip6stat.f)
389 
390 	p(ip6s_total, "\t%ju total packet%s received\n");
391 	p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n");
392 	p1a(ip6s_tooshort, "\t%ju with data size < data length\n");
393 	p1a(ip6s_badoptions, "\t%ju with bad options\n");
394 	p1a(ip6s_badvers, "\t%ju with incorrect version number\n");
395 	p(ip6s_fragments, "\t%ju fragment%s received\n");
396 	p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n");
397 	p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n");
398 	p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n");
399 	p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n");
400 	p(ip6s_delivered, "\t%ju packet%s for this host\n");
401 	p(ip6s_forward, "\t%ju packet%s forwarded\n");
402 	p(ip6s_cantforward, "\t%ju packet%s not forwardable\n");
403 	p(ip6s_redirectsent, "\t%ju redirect%s sent\n");
404 	p(ip6s_localout, "\t%ju packet%s sent from this host\n");
405 	p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n");
406 	p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n");
407 	p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n");
408 	p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n");
409 	p(ip6s_ofragments, "\t%ju fragment%s created\n");
410 	p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n");
411 	p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n");
412 	p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n");
413 	for (first = 1, i = 0; i < 256; i++)
414 		if (ip6stat.ip6s_nxthist[i] != 0) {
415 			if (first) {
416 				printf("\tInput histogram:\n");
417 				first = 0;
418 			}
419 			printf("\t\t%s: %ju\n", ip6nh[i],
420 			    (uintmax_t)ip6stat.ip6s_nxthist[i]);
421 		}
422 	printf("\tMbuf statistics:\n");
423 	printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1);
424 	for (first = 1, i = 0; i < 32; i++) {
425 		char ifbuf[IFNAMSIZ];
426 		if (ip6stat.ip6s_m2m[i] != 0) {
427 			if (first) {
428 				printf("\t\ttwo or more mbuf:\n");
429 				first = 0;
430 			}
431 			printf("\t\t\t%s= %ju\n",
432 			    if_indextoname(i, ifbuf),
433 			    (uintmax_t)ip6stat.ip6s_m2m[i]);
434 		}
435 	}
436 	printf("\t\t%ju one ext mbuf\n",
437 	    (uintmax_t)ip6stat.ip6s_mext1);
438 	printf("\t\t%ju two or more ext mbuf\n",
439 	    (uintmax_t)ip6stat.ip6s_mext2m);
440 	p(ip6s_exthdrtoolong,
441 	    "\t%ju packet%s whose headers are not continuous\n");
442 	p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n");
443 	p(ip6s_toomanyhdr,
444 	    "\t%ju packet%s discarded because of too many headers\n");
445 
446 	/* for debugging source address selection */
447 #define	PRINT_SCOPESTAT(s,i) do {\
448 		switch(i) { /* XXX hardcoding in each case */\
449 		case 1:\
450 			p(s, "\t\t%ju node-local%s\n");\
451 			break;\
452 		case 2:\
453 			p(s,"\t\t%ju link-local%s\n");\
454 			break;\
455 		case 5:\
456 			p(s,"\t\t%ju site-local%s\n");\
457 			break;\
458 		case 14:\
459 			p(s,"\t\t%ju global%s\n");\
460 			break;\
461 		default:\
462 			printf("\t\t%ju addresses scope=%x\n",\
463 			    (uintmax_t)ip6stat.s, i);\
464 		}\
465 	} while (0);
466 
467 	p(ip6s_sources_none,
468 	  "\t%ju failure%s of source address selection\n");
469 	for (first = 1, i = 0; i < 16; i++) {
470 		if (ip6stat.ip6s_sources_sameif[i]) {
471 			if (first) {
472 				printf("\tsource addresses on an outgoing I/F\n");
473 				first = 0;
474 			}
475 			PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
476 		}
477 	}
478 	for (first = 1, i = 0; i < 16; i++) {
479 		if (ip6stat.ip6s_sources_otherif[i]) {
480 			if (first) {
481 				printf("\tsource addresses on a non-outgoing I/F\n");
482 				first = 0;
483 			}
484 			PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
485 		}
486 	}
487 	for (first = 1, i = 0; i < 16; i++) {
488 		if (ip6stat.ip6s_sources_samescope[i]) {
489 			if (first) {
490 				printf("\tsource addresses of same scope\n");
491 				first = 0;
492 			}
493 			PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
494 		}
495 	}
496 	for (first = 1, i = 0; i < 16; i++) {
497 		if (ip6stat.ip6s_sources_otherscope[i]) {
498 			if (first) {
499 				printf("\tsource addresses of a different scope\n");
500 				first = 0;
501 			}
502 			PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
503 		}
504 	}
505 	for (first = 1, i = 0; i < 16; i++) {
506 		if (ip6stat.ip6s_sources_deprecated[i]) {
507 			if (first) {
508 				printf("\tdeprecated source addresses\n");
509 				first = 0;
510 			}
511 			PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
512 		}
513 	}
514 
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, const char *name, int af1 __unused, int proto __unused)
846 {
847 	struct icmp6stat icmp6stat;
848 	int i, first;
849 	size_t len;
850 
851 	len = sizeof icmp6stat;
852 	if (live) {
853 		memset(&icmp6stat, 0, len);
854 		if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
855 		    NULL, 0) < 0) {
856 			if (errno != ENOENT)
857 				warn("sysctl: net.inet6.icmp6.stats");
858 			return;
859 		}
860 	} else
861 		kread(off, &icmp6stat, len);
862 
863 	printf("%s:\n", name);
864 
865 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
866     printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
867 #define	p_5(f, m) if (icmp6stat.f || sflag <= 1) \
868     printf(m, (uintmax_t)icmp6stat.f)
869 
870 	p(icp6s_error, "\t%ju call%s to icmp6_error\n");
871 	p(icp6s_canterror,
872 	    "\t%ju error%s not generated in response to an icmp6 message\n");
873 	p(icp6s_toofreq,
874 	  "\t%ju error%s not generated because of rate limitation\n");
875 #define	NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
876 	for (first = 1, i = 0; i < NELEM; i++)
877 		if (icmp6stat.icp6s_outhist[i] != 0) {
878 			if (first) {
879 				printf("\tOutput histogram:\n");
880 				first = 0;
881 			}
882 			printf("\t\t%s: %ju\n", icmp6names[i],
883 			    (uintmax_t)icmp6stat.icp6s_outhist[i]);
884 		}
885 #undef NELEM
886 	p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
887 	p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
888 	p(icp6s_checksum, "\t%ju bad checksum%s\n");
889 	p(icp6s_badlen, "\t%ju message%s with bad length\n");
890 #define	NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
891 	for (first = 1, i = 0; i < NELEM; i++)
892 		if (icmp6stat.icp6s_inhist[i] != 0) {
893 			if (first) {
894 				printf("\tInput histogram:\n");
895 				first = 0;
896 			}
897 			printf("\t\t%s: %ju\n", icmp6names[i],
898 			    (uintmax_t)icmp6stat.icp6s_inhist[i]);
899 		}
900 #undef NELEM
901 	printf("\tHistogram of error messages to be generated:\n");
902 	p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
903 	p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
904 	p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
905 	p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
906 	p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
907 	p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
908 	p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
909 	p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
910 	p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
911 	p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
912 	p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
913 	p_5(icp6s_oredirect, "\t\t%ju redirect\n");
914 	p_5(icp6s_ounknown, "\t\t%ju unknown\n");
915 
916 	p(icp6s_reflect, "\t%ju message response%s generated\n");
917 	p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
918 	p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
919 	p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
920 	p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
921 	p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
922 	p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
923 	p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
924 	p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
925 #undef p
926 #undef p_5
927 }
928 
929 /*
930  * Dump ICMPv6 per-interface statistics based on RFC 2466.
931  */
932 void
933 icmp6_ifstats(char *ifname)
934 {
935 	struct in6_ifreq ifr;
936 	int s;
937 #define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
938     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
939 #define	p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
940     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
941 
942 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
943 		perror("Warning: socket(AF_INET6)");
944 		return;
945 	}
946 
947 	strcpy(ifr.ifr_name, ifname);
948 	printf("icmp6 on %s:\n", ifr.ifr_name);
949 
950 	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
951 		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
952 		goto end;
953 	}
954 
955 	p(ifs6_in_msg, "\t%ju total input message%s\n");
956 	p(ifs6_in_error, "\t%ju total input error message%s\n");
957 	p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
958 	p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
959 	p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
960 	p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
961 	p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
962 	p(ifs6_in_echo, "\t%ju input echo request%s\n");
963 	p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
964 	p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
965 	p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
966 	p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
967 	p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
968 	p(ifs6_in_redirect, "\t%ju input redirect%s\n");
969 	p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
970 	p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
971 	p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
972 
973 	p(ifs6_out_msg, "\t%ju total output message%s\n");
974 	p(ifs6_out_error, "\t%ju total output error message%s\n");
975 	p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
976 	p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
977 	p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
978 	p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
979 	p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
980 	p(ifs6_out_echo, "\t%ju output echo request%s\n");
981 	p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
982 	p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
983 	p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
984 	p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
985 	p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
986 	p(ifs6_out_redirect, "\t%ju output redirect%s\n");
987 	p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
988 	p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
989 	p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
990 
991   end:
992 	close(s);
993 #undef p
994 }
995 
996 /*
997  * Dump PIM statistics structure.
998  */
999 void
1000 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1001 {
1002 	struct pim6stat pim6stat, zerostat;
1003 	size_t len = sizeof pim6stat;
1004 
1005 	if (live) {
1006 		if (zflag)
1007 			memset(&zerostat, 0, len);
1008 		if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1009 		    zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1010 			if (errno != ENOENT)
1011 				warn("sysctl: net.inet6.pim.stats");
1012 			return;
1013 		}
1014 	} else {
1015 		if (off == 0)
1016 			return;
1017 		kread(off, &pim6stat, len);
1018 	}
1019 
1020 	printf("%s:\n", name);
1021 
1022 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
1023     printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1024 	p(pim6s_rcv_total, "\t%ju message%s received\n");
1025 	p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1026 	p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1027 	p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
1028 	p(pim6s_rcv_registers, "\t%ju register%s received\n");
1029 	p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
1030 	p(pim6s_snd_registers, "\t%ju register%s sent\n");
1031 #undef p
1032 }
1033 
1034 /*
1035  * Dump raw ip6 statistics structure.
1036  */
1037 void
1038 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1039 {
1040 	struct rip6stat rip6stat;
1041 	u_quad_t delivered;
1042 	size_t len;
1043 
1044 	len = sizeof(rip6stat);
1045 	if (live) {
1046 		if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1047 		    NULL, 0) < 0) {
1048 			if (errno != ENOENT)
1049 				warn("sysctl: net.inet6.ip6.rip6stats");
1050 			return;
1051 		}
1052 	} else
1053 		kread(off, &rip6stat, len);
1054 
1055 	printf("%s:\n", name);
1056 
1057 #define	p(f, m) if (rip6stat.f || sflag <= 1) \
1058     printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1059 	p(rip6s_ipackets, "\t%ju message%s received\n");
1060 	p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n");
1061 	p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
1062 	p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
1063 	p(rip6s_nosockmcast,
1064 	    "\t%ju multicast message%s dropped due to no socket\n");
1065 	p(rip6s_fullsock,
1066 	    "\t%ju message%s dropped due to full socket buffers\n");
1067 	delivered = rip6stat.rip6s_ipackets -
1068 		    rip6stat.rip6s_badsum -
1069 		    rip6stat.rip6s_nosock -
1070 		    rip6stat.rip6s_nosockmcast -
1071 		    rip6stat.rip6s_fullsock;
1072 	if (delivered || sflag <= 1)
1073 		printf("\t%ju delivered\n", (uintmax_t)delivered);
1074 	p(rip6s_opackets, "\t%ju datagram%s output\n");
1075 #undef p
1076 }
1077 
1078 /*
1079  * Pretty print an Internet address (net address + port).
1080  * Take numeric_addr and numeric_port into consideration.
1081  */
1082 #define	GETSERVBYPORT6(port, proto, ret)\
1083 {\
1084 	if (strcmp((proto), "tcp6") == 0)\
1085 		(ret) = getservbyport((int)(port), "tcp");\
1086 	else if (strcmp((proto), "udp6") == 0)\
1087 		(ret) = getservbyport((int)(port), "udp");\
1088 	else\
1089 		(ret) = getservbyport((int)(port), (proto));\
1090 };
1091 
1092 void
1093 inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
1094 {
1095 	struct servent *sp = 0;
1096 	char line[80], *cp;
1097 	int width;
1098 
1099 	sprintf(line, "%.*s.", Wflag ? 39 :
1100 		(Aflag && !numeric) ? 12 : 16, inet6name(in6));
1101 	cp = index(line, '\0');
1102 	if (!numeric && port)
1103 		GETSERVBYPORT6(port, proto, sp);
1104 	if (sp || port == 0)
1105 		sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1106 	else
1107 		sprintf(cp, "%d", ntohs((u_short)port));
1108 	width = Wflag ? 45 : Aflag ? 18 : 22;
1109 	printf("%-*.*s ", width, width, line);
1110 }
1111 
1112 /*
1113  * Construct an Internet address representation.
1114  * If the numeric_addr has been supplied, give
1115  * numeric value, otherwise try for symbolic name.
1116  */
1117 
1118 char *
1119 inet6name(struct in6_addr *in6p)
1120 {
1121 	char *cp;
1122 	static char line[50];
1123 	struct hostent *hp;
1124 	static char domain[MAXHOSTNAMELEN];
1125 	static int first = 1;
1126 
1127 	if (first && !numeric_addr) {
1128 		first = 0;
1129 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1130 		    (cp = index(domain, '.')))
1131 			(void) strcpy(domain, cp + 1);
1132 		else
1133 			domain[0] = 0;
1134 	}
1135 	cp = 0;
1136 	if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1137 		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1138 		if (hp) {
1139 			if ((cp = index(hp->h_name, '.')) &&
1140 			    !strcmp(cp + 1, domain))
1141 				*cp = 0;
1142 			cp = hp->h_name;
1143 		}
1144 	}
1145 	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1146 		strcpy(line, "*");
1147 	else if (cp)
1148 		strcpy(line, cp);
1149 	else
1150 		sprintf(line, "%s",
1151 			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
1152 				sizeof(ntop_buf)));
1153 	return (line);
1154 }
1155 #endif /*INET6*/
1156