xref: /freebsd/usr.bin/netstat/inet6.c (revision daf1cffce2e07931f27c6c6998652e90df6ba87e)
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 #include <sys/param.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/ioctl.h>
47 #include <sys/mbuf.h>
48 #include <sys/protosw.h>
49 
50 #include <net/route.h>
51 #include <net/if.h>
52 #include <net/if_var.h>
53 #include <netinet/in.h>
54 #include <netinet/ip6.h>
55 #include <netinet/icmp6.h>
56 #include <netinet/in_systm.h>
57 #include <netinet6/in6_pcb.h>
58 #include <netinet6/in6_var.h>
59 #include <netinet6/ip6_var.h>
60 #include <netinet6/pim6_var.h>
61 
62 #include <arpa/inet.h>
63 #include <netdb.h>
64 
65 #include <stdio.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include "netstat.h"
69 
70 struct	socket sockb;
71 
72 char	*inet6name __P((struct in6_addr *));
73 void	inet6print __P((struct in6_addr *, int, char *, int));
74 
75 static char ntop_buf[INET6_ADDRSTRLEN];
76 
77 static	char *ip6nh[] = {
78 	"hop by hop",
79 	"ICMP",
80 	"IGMP",
81 	"#3",
82 	"IP",
83 	"#5",
84 	"TCP",
85 	"#7",
86 	"#8",
87 	"#9",
88 	"#10",
89 	"#11",
90 	"#12",
91 	"#13",
92 	"#14",
93 	"#15",
94 	"#16",
95 	"UDP",
96 	"#18",
97 	"#19",
98 	"#20",
99 	"#21",
100 	"IDP",
101 	"#23",
102 	"#24",
103 	"#25",
104 	"#26",
105 	"#27",
106 	"#28",
107 	"TP",
108 	"#30",
109 	"#31",
110 	"#32",
111 	"#33",
112 	"#34",
113 	"#35",
114 	"#36",
115 	"#37",
116 	"#38",
117 	"#39",
118 	"#40",
119 	"IP6",
120 	"#42",
121 	"routing",
122 	"fragment",
123 	"#45",
124 	"#46",
125 	"#47",
126 	"#48",
127 	"#49",
128 	"ESP",
129 	"AH",
130 	"#52",
131 	"#53",
132 	"#54",
133 	"#55",
134 	"#56",
135 	"#57",
136 	"ICMP6",
137 	"no next header",
138 	"destination option",
139 	"#61",
140 	"#62",
141 	"#63",
142 	"#64",
143 	"#65",
144 	"#66",
145 	"#67",
146 	"#68",
147 	"#69",
148 	"#70",
149 	"#71",
150 	"#72",
151 	"#73",
152 	"#74",
153 	"#75",
154 	"#76",
155 	"#77",
156 	"#78",
157 	"#79",
158 	"ISOIP",
159 	"#81",
160 	"#82",
161 	"#83",
162 	"#84",
163 	"#85",
164 	"#86",
165 	"#87",
166 	"#88",
167 	"#89",
168 	"#80",
169 	"#91",
170 	"#92",
171 	"#93",
172 	"#94",
173 	"#95",
174 	"#96",
175 	"Ethernet",
176 	"#98",
177 	"#99",
178 	"#100",
179 	"#101",
180 	"#102",
181 	"PIM",
182 	"#104",
183 	"#105",
184 	"#106",
185 	"#107",
186 	"#108",
187 	"#109",
188 	"#110",
189 	"#111",
190 	"#112",
191 	"#113",
192 	"#114",
193 	"#115",
194 	"#116",
195 	"#117",
196 	"#118",
197 	"#119",
198 	"#120",
199 	"#121",
200 	"#122",
201 	"#123",
202 	"#124",
203 	"#125",
204 	"#126",
205 	"#127",
206 	"#128",
207 	"#129",
208 	"#130",
209 	"#131",
210 	"#132",
211 	"#133",
212 	"#134",
213 	"#135",
214 	"#136",
215 	"#137",
216 	"#138",
217 	"#139",
218 	"#140",
219 	"#141",
220 	"#142",
221 	"#143",
222 	"#144",
223 	"#145",
224 	"#146",
225 	"#147",
226 	"#148",
227 	"#149",
228 	"#150",
229 	"#151",
230 	"#152",
231 	"#153",
232 	"#154",
233 	"#155",
234 	"#156",
235 	"#157",
236 	"#158",
237 	"#159",
238 	"#160",
239 	"#161",
240 	"#162",
241 	"#163",
242 	"#164",
243 	"#165",
244 	"#166",
245 	"#167",
246 	"#168",
247 	"#169",
248 	"#170",
249 	"#171",
250 	"#172",
251 	"#173",
252 	"#174",
253 	"#175",
254 	"#176",
255 	"#177",
256 	"#178",
257 	"#179",
258 	"#180",
259 	"#181",
260 	"#182",
261 	"#183",
262 	"#184",
263 	"#185",
264 	"#186",
265 	"#187",
266 	"#188",
267 	"#189",
268 	"#180",
269 	"#191",
270 	"#192",
271 	"#193",
272 	"#194",
273 	"#195",
274 	"#196",
275 	"#197",
276 	"#198",
277 	"#199",
278 	"#200",
279 	"#201",
280 	"#202",
281 	"#203",
282 	"#204",
283 	"#205",
284 	"#206",
285 	"#207",
286 	"#208",
287 	"#209",
288 	"#210",
289 	"#211",
290 	"#212",
291 	"#213",
292 	"#214",
293 	"#215",
294 	"#216",
295 	"#217",
296 	"#218",
297 	"#219",
298 	"#220",
299 	"#221",
300 	"#222",
301 	"#223",
302 	"#224",
303 	"#225",
304 	"#226",
305 	"#227",
306 	"#228",
307 	"#229",
308 	"#230",
309 	"#231",
310 	"#232",
311 	"#233",
312 	"#234",
313 	"#235",
314 	"#236",
315 	"#237",
316 	"#238",
317 	"#239",
318 	"#240",
319 	"#241",
320 	"#242",
321 	"#243",
322 	"#244",
323 	"#245",
324 	"#246",
325 	"#247",
326 	"#248",
327 	"#249",
328 	"#250",
329 	"#251",
330 	"#252",
331 	"#253",
332 	"#254",
333 	"#255",
334 };
335 
336 /*
337  * Dump IP6 statistics structure.
338  */
339 void
340 ip6_stats(off, name)
341 	u_long off;
342 	char *name;
343 {
344 	struct ip6stat ip6stat;
345 	int first, i;
346 
347 	if (off == 0)
348 		return;
349 
350 	kread(off, (char *)&ip6stat, sizeof (ip6stat));
351 	printf("%s:\n", name);
352 
353 #define	p(f, m) if (ip6stat.f || sflag <= 1) \
354     printf(m, ip6stat.f, plural(ip6stat.f))
355 #define	p1a(f, m) if (ip6stat.f || sflag <= 1) \
356     printf(m, ip6stat.f)
357 
358 	p(ip6s_total, "\t%lu total packet%s received\n");
359 	p1a(ip6s_toosmall, "\t%lu with size smaller than minimum\n");
360 	p1a(ip6s_tooshort, "\t%lu with data size < data length\n");
361 	p1a(ip6s_badoptions, "\t%lu with bad options\n");
362 	p1a(ip6s_badvers, "\t%lu with incorrect version number\n");
363 	p(ip6s_fragments, "\t%lu fragment%s received\n");
364 	p(ip6s_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
365 	p(ip6s_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
366 	p(ip6s_fragoverflow, "\t%lu fragment%s that exceeded limit\n");
367 	p(ip6s_reassembled, "\t%lu packet%s reassembled ok\n");
368 	p(ip6s_delivered, "\t%lu packet%s for this host\n");
369 	p(ip6s_forward, "\t%lu packet%s forwarded\n");
370 	p(ip6s_cantforward, "\t%lu packet%s not forwardable\n");
371 	p(ip6s_redirectsent, "\t%lu redirect%s sent\n");
372 	p(ip6s_localout, "\t%lu packet%s sent from this host\n");
373 	p(ip6s_rawout, "\t%lu packet%s sent with fabricated ip header\n");
374 	p(ip6s_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n");
375 	p(ip6s_noroute, "\t%lu output packet%s discarded due to no route\n");
376 	p(ip6s_fragmented, "\t%lu output datagram%s fragmented\n");
377 	p(ip6s_ofragments, "\t%lu fragment%s created\n");
378 	p(ip6s_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
379 	p(ip6s_badscope, "\t%lu packet%s that violated scope rules\n");
380 	p(ip6s_notmember, "\t%lu multicast packet%s which we don't join\n");
381 	for (first = 1, i = 0; i < 256; i++)
382 		if (ip6stat.ip6s_nxthist[i] != 0) {
383 			if (first) {
384 				printf("\tInput histogram:\n");
385 				first = 0;
386 			}
387 			printf("\t\t%s: %lu\n", ip6nh[i],
388 			       ip6stat.ip6s_nxthist[i]);
389 		}
390 	printf("\tMbuf statistics:\n");
391 	printf("\t\t%lu one mbuf\n", ip6stat.ip6s_m1);
392 	for (first = 1, i = 0; i < 32; i++) {
393 		char ifbuf[IFNAMSIZ];
394 		if (ip6stat.ip6s_m2m[i] != 0) {
395 			if (first) {
396 				printf("\t\ttwo or more mbuf:\n");
397 				first = 0;
398 			}
399 			printf("\t\t\t%s= %ld\n",
400 			       if_indextoname(i, ifbuf),
401 			       ip6stat.ip6s_m2m[i]);
402 		}
403 	}
404 	printf("\t\t%lu one ext mbuf\n", ip6stat.ip6s_mext1);
405 	printf("\t\t%lu two or more ext mbuf\n", ip6stat.ip6s_mext2m);
406 	p(ip6s_exthdrtoolong, "\t%lu packet%s whose headers are not continuous\n");
407 	p(ip6s_nogif, "\t%lu tunneling packet%s that can't find gif\n");
408 	p(ip6s_toomanyhdr, "\t%lu packet%s discarded due to too may headers\n");
409 #undef p
410 }
411 
412 /*
413  * Dump IPv6 per-interface statistics based on RFC 2465.
414  */
415 void
416 ip6_ifstats(ifname)
417 	char *ifname;
418 {
419 	struct in6_ifreq ifr;
420 	int s;
421 #define	p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
422     printf(m, ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
423 #define	p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
424     printf(m, ip6stat.f)
425 
426 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
427 		perror("Warning: socket(AF_INET6)");
428 		return;
429 	}
430 
431 	strcpy(ifr.ifr_name, ifname);
432 	printf("ip6 on %s:\n", ifr.ifr_name);
433 
434 	if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
435 		perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
436 		goto end;
437 	}
438 
439 	p(ifs6_in_receive, "\t%qu total input datagram%s\n");
440 	p(ifs6_in_hdrerr, "\t%qu datagram%s with invalid header received\n");
441 	p(ifs6_in_toobig, "\t%qu datagram%s exceeded MTU received\n");
442 	p(ifs6_in_noroute, "\t%qu datagram%s with no route received\n");
443 	p(ifs6_in_addrerr, "\t%qu datagram%s with invalid dst received\n");
444 	p(ifs6_in_protounknown, "\t%qu datagram%s with unknown proto received\n");
445 	p(ifs6_in_truncated, "\t%qu truncated datagram%s received\n");
446 	p(ifs6_in_discard, "\t%qu input datagram%s discarded\n");
447 	p(ifs6_in_deliver,
448 	  "\t%qu datagram%s delivered to an upper layer protocol\n");
449 	p(ifs6_out_forward, "\t%qu datagram%s forwarded to this interface\n");
450 	p(ifs6_out_request,
451 	  "\t%qu datagram%s sent from an upper layer protocol\n");
452 	p(ifs6_out_discard, "\t%qu total discarded output datagram%s\n");
453 	p(ifs6_out_fragok, "\t%qu output datagram%s fragmented\n");
454 	p(ifs6_out_fragfail, "\t%qu output datagram%s failed on fragment\n");
455 	p(ifs6_out_fragcreat, "\t%qu output datagram%s succeeded on fragment\n");
456 	p(ifs6_reass_reqd, "\t%qu incoming datagram%s fragmented\n");
457 	p(ifs6_reass_ok, "\t%qu datagram%s reassembled\n");
458 	p(ifs6_reass_fail, "\t%qu datagram%s failed on reassembling\n");
459 	p(ifs6_in_mcast, "\t%qu multicast datagram%s received\n");
460 	p(ifs6_out_mcast, "\t%qu multicast datagram%s sent\n");
461 
462   end:
463 	close(s);
464 
465 #undef p
466 #undef p_5
467 }
468 
469 static	char *icmp6names[] = {
470 	"#0",
471 	"unreach",
472 	"packet too big",
473 	"time exceed",
474 	"parameter problem",
475 	"#5",
476 	"#6",
477 	"#7",
478 	"#8",
479 	"#9",
480 	"#10",
481 	"#11",
482 	"#12",
483 	"#13",
484 	"#14",
485 	"#15",
486 	"#16",
487 	"#17",
488 	"#18",
489 	"#19",
490 	"#20",
491 	"#21",
492 	"#22",
493 	"#23",
494 	"#24",
495 	"#25",
496 	"#26",
497 	"#27",
498 	"#28",
499 	"#29",
500 	"#30",
501 	"#31",
502 	"#32",
503 	"#33",
504 	"#34",
505 	"#35",
506 	"#36",
507 	"#37",
508 	"#38",
509 	"#39",
510 	"#40",
511 	"#41",
512 	"#42",
513 	"#43",
514 	"#44",
515 	"#45",
516 	"#46",
517 	"#47",
518 	"#48",
519 	"#49",
520 	"#50",
521 	"#51",
522 	"#52",
523 	"#53",
524 	"#54",
525 	"#55",
526 	"#56",
527 	"#57",
528 	"#58",
529 	"#59",
530 	"#60",
531 	"#61",
532 	"#62",
533 	"#63",
534 	"#64",
535 	"#65",
536 	"#66",
537 	"#67",
538 	"#68",
539 	"#69",
540 	"#70",
541 	"#71",
542 	"#72",
543 	"#73",
544 	"#74",
545 	"#75",
546 	"#76",
547 	"#77",
548 	"#78",
549 	"#79",
550 	"#80",
551 	"#81",
552 	"#82",
553 	"#83",
554 	"#84",
555 	"#85",
556 	"#86",
557 	"#87",
558 	"#88",
559 	"#89",
560 	"#80",
561 	"#91",
562 	"#92",
563 	"#93",
564 	"#94",
565 	"#95",
566 	"#96",
567 	"#97",
568 	"#98",
569 	"#99",
570 	"#100",
571 	"#101",
572 	"#102",
573 	"#103",
574 	"#104",
575 	"#105",
576 	"#106",
577 	"#107",
578 	"#108",
579 	"#109",
580 	"#110",
581 	"#111",
582 	"#112",
583 	"#113",
584 	"#114",
585 	"#115",
586 	"#116",
587 	"#117",
588 	"#118",
589 	"#119",
590 	"#120",
591 	"#121",
592 	"#122",
593 	"#123",
594 	"#124",
595 	"#125",
596 	"#126",
597 	"#127",
598 	"echo",
599 	"echo reply",
600 	"multicast listener query",
601 	"multicast listener report",
602 	"multicast listener done",
603 	"router solicitation",
604 	"router advertisment",
605 	"neighbor solicitation",
606 	"neighbor advertisment",
607 	"redirect",
608 	"router renumbering",
609 	"node information request",
610 	"node information reply",
611 	"#141",
612 	"#142",
613 	"#143",
614 	"#144",
615 	"#145",
616 	"#146",
617 	"#147",
618 	"#148",
619 	"#149",
620 	"#150",
621 	"#151",
622 	"#152",
623 	"#153",
624 	"#154",
625 	"#155",
626 	"#156",
627 	"#157",
628 	"#158",
629 	"#159",
630 	"#160",
631 	"#161",
632 	"#162",
633 	"#163",
634 	"#164",
635 	"#165",
636 	"#166",
637 	"#167",
638 	"#168",
639 	"#169",
640 	"#170",
641 	"#171",
642 	"#172",
643 	"#173",
644 	"#174",
645 	"#175",
646 	"#176",
647 	"#177",
648 	"#178",
649 	"#179",
650 	"#180",
651 	"#181",
652 	"#182",
653 	"#183",
654 	"#184",
655 	"#185",
656 	"#186",
657 	"#187",
658 	"#188",
659 	"#189",
660 	"#180",
661 	"#191",
662 	"#192",
663 	"#193",
664 	"#194",
665 	"#195",
666 	"#196",
667 	"#197",
668 	"#198",
669 	"#199",
670 	"#200",
671 	"#201",
672 	"#202",
673 	"#203",
674 	"#204",
675 	"#205",
676 	"#206",
677 	"#207",
678 	"#208",
679 	"#209",
680 	"#210",
681 	"#211",
682 	"#212",
683 	"#213",
684 	"#214",
685 	"#215",
686 	"#216",
687 	"#217",
688 	"#218",
689 	"#219",
690 	"#220",
691 	"#221",
692 	"#222",
693 	"#223",
694 	"#224",
695 	"#225",
696 	"#226",
697 	"#227",
698 	"#228",
699 	"#229",
700 	"#230",
701 	"#231",
702 	"#232",
703 	"#233",
704 	"#234",
705 	"#235",
706 	"#236",
707 	"#237",
708 	"#238",
709 	"#239",
710 	"#240",
711 	"#241",
712 	"#242",
713 	"#243",
714 	"#244",
715 	"#245",
716 	"#246",
717 	"#247",
718 	"#248",
719 	"#249",
720 	"#250",
721 	"#251",
722 	"#252",
723 	"#253",
724 	"#254",
725 	"#255",
726 };
727 
728 /*
729  * Dump ICMP6 statistics.
730  */
731 void
732 icmp6_stats(off, name)
733 	u_long off;
734 	char *name;
735 {
736 	struct icmp6stat icmp6stat;
737 	register int i, first;
738 
739 	if (off == 0)
740 		return;
741 	kread(off, (char *)&icmp6stat, sizeof (icmp6stat));
742 	printf("%s:\n", name);
743 
744 #define	p(f, m) if (icmp6stat.f || sflag <= 1) \
745     printf(m, icmp6stat.f, plural(icmp6stat.f))
746 
747 	p(icp6s_error, "\t%lu call%s to icmp_error\n");
748 	p(icp6s_canterror,
749 	    "\t%lu error%s not generated because old message was icmp error or so\n");
750 	p(icp6s_toofreq,
751 	  "\t%lu error%s not generated because rate limitation\n");
752 	for (first = 1, i = 0; i < 256; i++)
753 		if (icmp6stat.icp6s_outhist[i] != 0) {
754 			if (first) {
755 				printf("\tOutput histogram:\n");
756 				first = 0;
757 			}
758 			printf("\t\t%s: %lu\n", icmp6names[i],
759 				icmp6stat.icp6s_outhist[i]);
760 		}
761 	p(icp6s_badcode, "\t%lu message%s with bad code fields\n");
762 	p(icp6s_tooshort, "\t%lu message%s < minimum length\n");
763 	p(icp6s_checksum, "\t%lu bad checksum%s\n");
764 	p(icp6s_badlen, "\t%lu message%s with bad length\n");
765 	for (first = 1, i = 0; i < ICMP6_MAXTYPE; i++)
766 		if (icmp6stat.icp6s_inhist[i] != 0) {
767 			if (first) {
768 				printf("\tInput histogram:\n");
769 				first = 0;
770 			}
771 			printf("\t\t%s: %lu\n", icmp6names[i],
772 				icmp6stat.icp6s_inhist[i]);
773 		}
774 	p(icp6s_reflect, "\t%lu message response%s generated\n");
775 #undef p
776 #undef p_5
777 }
778 
779 /*
780  * Dump ICMPv6 per-interface statistics based on RFC 2466.
781  */
782 void
783 icmp6_ifstats(ifname)
784 	char *ifname;
785 {
786 	struct in6_ifreq ifr;
787 	int s;
788 #define	p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
789     printf(m, (u_quad_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
790 
791 	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
792 		perror("Warning: socket(AF_INET6)");
793 		return;
794 	}
795 
796 	strcpy(ifr.ifr_name, ifname);
797 	printf("icmp6 on %s:\n", ifr.ifr_name);
798 
799 	if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
800 		perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
801 		goto end;
802 	}
803 
804 	p(ifs6_in_msg, "\t%qu total input message%s\n");
805 	p(ifs6_in_error, "\t%qu total input error message%s\n");
806 	p(ifs6_in_dstunreach, "\t%qu input destination unreachable error%s\n");
807 	p(ifs6_in_adminprohib, "\t%qu input administratively prohibited error%s\n");
808 	p(ifs6_in_timeexceed, "\t%qu input time exceeded error%s\n");
809 	p(ifs6_in_paramprob, "\t%qu input parameter problem error%s\n");
810 	p(ifs6_in_pkttoobig, "\t%qu input packet too big error%s\n");
811 	p(ifs6_in_echo, "\t%qu input echo request%s\n");
812 	p(ifs6_in_echoreply, "\t%qu input echo reply%s\n");
813 	p(ifs6_in_routersolicit, "\t%qu input router solicitation%s\n");
814 	p(ifs6_in_routeradvert, "\t%qu input router advertisement%s\n");
815 	p(ifs6_in_neighborsolicit, "\t%qu input neighbor solicitation%s\n");
816 	p(ifs6_in_neighboradvert, "\t%qu input neighbor advertisement%s\n");
817 	p(ifs6_in_redirect, "\t%qu input redirect%s\n");
818 	p(ifs6_in_mldquery, "\t%qu input MLD query%s\n");
819 	p(ifs6_in_mldreport, "\t%qu input MLD report%s\n");
820 	p(ifs6_in_mlddone, "\t%qu input MLD done%s\n");
821 
822 	p(ifs6_out_msg, "\t%qu total output message%s\n");
823 	p(ifs6_out_error, "\t%qu total output error message%s\n");
824 	p(ifs6_out_dstunreach, "\t%qu output destination unreachable error%s\n");
825 	p(ifs6_out_adminprohib, "\t%qu output administratively prohibited error%s\n");
826 	p(ifs6_out_timeexceed, "\t%qu output time exceeded error%s\n");
827 	p(ifs6_out_paramprob, "\t%qu output parameter problem error%s\n");
828 	p(ifs6_out_pkttoobig, "\t%qu output packet too big error%s\n");
829 	p(ifs6_out_echo, "\t%qu output echo request%s\n");
830 	p(ifs6_out_echoreply, "\t%qu output echo reply%s\n");
831 	p(ifs6_out_routersolicit, "\t%qu output router solicitation%s\n");
832 	p(ifs6_out_routeradvert, "\t%qu output router advertisement%s\n");
833 	p(ifs6_out_neighborsolicit, "\t%qu output neighbor solicitation%s\n");
834 	p(ifs6_out_neighboradvert, "\t%qu output neighbor advertisement%s\n");
835 	p(ifs6_out_redirect, "\t%qu output redirect%s\n");
836 	p(ifs6_out_mldquery, "\t%qu output MLD query%s\n");
837 	p(ifs6_out_mldreport, "\t%qu output MLD report%s\n");
838 	p(ifs6_out_mlddone, "\t%qu output MLD done%s\n");
839 
840   end:
841 	close(s);
842 #undef p
843 }
844 
845 /*
846  * Dump PIM statistics structure.
847  */
848 void
849 pim6_stats(off, name)
850 	u_long off;
851 	char *name;
852 {
853 	struct pim6stat pim6stat;
854 
855 	if (off == 0)
856 		return;
857 	kread(off, (char *)&pim6stat, sizeof(pim6stat));
858 	printf("%s:\n", name);
859 
860 #define	p(f, m) if (pim6stat.f || sflag <= 1) \
861     printf(m, pim6stat.f, plural(pim6stat.f))
862 	p(pim6s_rcv_total, "\t%u message%s received\n");
863 	p(pim6s_rcv_tooshort, "\t%u message%s received with too few bytes\n");
864 	p(pim6s_rcv_badsum, "\t%u message%s received with bad checksum\n");
865 	p(pim6s_rcv_badversion, "\t%u message%s received with bad version\n");
866 	p(pim6s_rcv_registers, "\t%u register%s received\n");
867 	p(pim6s_rcv_badregisters, "\t%u bad register%s received\n");
868 	p(pim6s_snd_registers, "\t%u register%s sent\n");
869 #undef p
870 }
871 
872 /*
873  * Pretty print an Internet address (net address + port).
874  * If the nflag was specified, use numbers instead of names.
875  */
876 #define GETSERVBYPORT6(port, proto, ret)\
877 {\
878 	if (strcmp((proto), "tcp6") == 0)\
879 		(ret) = getservbyport((int)(port), "tcp");\
880 	else if (strcmp((proto), "udp6") == 0)\
881 		(ret) = getservbyport((int)(port), "udp");\
882 	else\
883 		(ret) = getservbyport((int)(port), (proto));\
884 };
885 
886 void
887 inet6print(in6, port, proto, numeric)
888 	register struct in6_addr *in6;
889 	int port;
890 	char *proto;
891 	int numeric;
892 {
893 	struct servent *sp = 0;
894 	char line[80], *cp;
895 	int width;
896 
897 	sprintf(line, "%.*s.", lflag ? 39 :
898 		(Aflag && !numeric) ? 12 : 16, inet6name(in6));
899 	cp = index(line, '\0');
900 	if (!numeric && port)
901 		GETSERVBYPORT6(port, proto, sp);
902 	if (sp || port == 0)
903 		sprintf(cp, "%.8s", sp ? sp->s_name : "*");
904 	else
905 		sprintf(cp, "%d", ntohs((u_short)port));
906 	width = lflag ? 45 : Aflag ? 18 : 22;
907 	printf("%-*.*s ", width, width, line);
908 }
909 
910 /*
911  * Construct an Internet address representation.
912  * If the nflag has been supplied, give
913  * numeric value, otherwise try for symbolic name.
914  */
915 
916 char *
917 inet6name(in6p)
918 	struct in6_addr *in6p;
919 {
920 	register char *cp;
921 	static char line[50];
922 	struct hostent *hp;
923 	static char domain[MAXHOSTNAMELEN + 1];
924 	static int first = 1;
925 
926 	if (first && !nflag) {
927 		first = 0;
928 		if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
929 		    (cp = index(domain, '.')))
930 			(void) strcpy(domain, cp + 1);
931 		else
932 			domain[0] = 0;
933 	}
934 	cp = 0;
935 	if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
936 		hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
937 		if (hp) {
938 			if ((cp = index(hp->h_name, '.')) &&
939 			    !strcmp(cp + 1, domain))
940 				*cp = 0;
941 			cp = hp->h_name;
942 		}
943 	}
944 	if (IN6_IS_ADDR_UNSPECIFIED(in6p))
945 		strcpy(line, "*");
946 	else if (cp)
947 		strcpy(line, cp);
948 	else
949 		sprintf(line, "%s",
950 			inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
951 				sizeof(ntop_buf)));
952 	return (line);
953 }
954