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