]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.bin/netstat/inet6.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.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  * 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         "MLDv1 listener report",
715         "MLDv1 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         "MLDv2 listener report",
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*/