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