]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - usr.bin/netstat/inet6.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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         p1a(ip6s_forward_cachehit, "\t%ju forward cache hit\n");
516         p1a(ip6s_forward_cachemiss, "\t%ju forward cache miss\n");
517         printf("\tSource addresses selection rule applied:\n");
518         for (i = 0; i < 16; i++) {
519                 if (ip6stat.ip6s_sources_rule[i])
520                         printf("\t\t%ju %s\n",
521                                (uintmax_t)ip6stat.ip6s_sources_rule[i],
522                                srcrule_str[i]);
523         }
524 #undef p
525 #undef p1a
526 }
527
528 /*
529  * Dump IPv6 per-interface statistics based on RFC 2465.
530  */
531 void
532 ip6_ifstats(char *ifname)
533 {
534         struct in6_ifreq ifr;
535         int s;
536 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
537     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
538 #define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
539     printf(m, (uintmax_t)ip6stat.f)
540
541         if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
542                 perror("Warning: socket(AF_INET6)");
543                 return;
544         }
545
546         strcpy(ifr.ifr_name, ifname);
547         printf("ip6 on %s:\n", ifr.ifr_name);
548
549         if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
550                 perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
551                 goto end;
552         }
553
554         p(ifs6_in_receive, "\t%ju total input datagram%s\n");
555         p(ifs6_in_hdrerr, "\t%ju datagram%s with invalid header received\n");
556         p(ifs6_in_toobig, "\t%ju datagram%s exceeded MTU received\n");
557         p(ifs6_in_noroute, "\t%ju datagram%s with no route received\n");
558         p(ifs6_in_addrerr, "\t%ju datagram%s with invalid dst received\n");
559         p(ifs6_in_protounknown, "\t%ju datagram%s with unknown proto received\n");
560         p(ifs6_in_truncated, "\t%ju truncated datagram%s received\n");
561         p(ifs6_in_discard, "\t%ju input datagram%s discarded\n");
562         p(ifs6_in_deliver,
563           "\t%ju datagram%s delivered to an upper layer protocol\n");
564         p(ifs6_out_forward, "\t%ju datagram%s forwarded to this interface\n");
565         p(ifs6_out_request,
566           "\t%ju datagram%s sent from an upper layer protocol\n");
567         p(ifs6_out_discard, "\t%ju total discarded output datagram%s\n");
568         p(ifs6_out_fragok, "\t%ju output datagram%s fragmented\n");
569         p(ifs6_out_fragfail, "\t%ju output datagram%s failed on fragment\n");
570         p(ifs6_out_fragcreat, "\t%ju output datagram%s succeeded on fragment\n");
571         p(ifs6_reass_reqd, "\t%ju incoming datagram%s fragmented\n");
572         p(ifs6_reass_ok, "\t%ju datagram%s reassembled\n");
573         p(ifs6_reass_fail, "\t%ju datagram%s failed on reassembly\n");
574         p(ifs6_in_mcast, "\t%ju multicast datagram%s received\n");
575         p(ifs6_out_mcast, "\t%ju multicast datagram%s sent\n");
576
577   end:
578         close(s);
579
580 #undef p
581 #undef p_5
582 }
583
584 static  const char *icmp6names[] = {
585         "#0",
586         "unreach",
587         "packet too big",
588         "time exceed",
589         "parameter problem",
590         "#5",
591         "#6",
592         "#7",
593         "#8",
594         "#9",
595         "#10",
596         "#11",
597         "#12",
598         "#13",
599         "#14",
600         "#15",
601         "#16",
602         "#17",
603         "#18",
604         "#19",
605         "#20",
606         "#21",
607         "#22",
608         "#23",
609         "#24",
610         "#25",
611         "#26",
612         "#27",
613         "#28",
614         "#29",
615         "#30",
616         "#31",
617         "#32",
618         "#33",
619         "#34",
620         "#35",
621         "#36",
622         "#37",
623         "#38",
624         "#39",
625         "#40",
626         "#41",
627         "#42",
628         "#43",
629         "#44",
630         "#45",
631         "#46",
632         "#47",
633         "#48",
634         "#49",
635         "#50",
636         "#51",
637         "#52",
638         "#53",
639         "#54",
640         "#55",
641         "#56",
642         "#57",
643         "#58",
644         "#59",
645         "#60",
646         "#61",
647         "#62",
648         "#63",
649         "#64",
650         "#65",
651         "#66",
652         "#67",
653         "#68",
654         "#69",
655         "#70",
656         "#71",
657         "#72",
658         "#73",
659         "#74",
660         "#75",
661         "#76",
662         "#77",
663         "#78",
664         "#79",
665         "#80",
666         "#81",
667         "#82",
668         "#83",
669         "#84",
670         "#85",
671         "#86",
672         "#87",
673         "#88",
674         "#89",
675         "#80",
676         "#91",
677         "#92",
678         "#93",
679         "#94",
680         "#95",
681         "#96",
682         "#97",
683         "#98",
684         "#99",
685         "#100",
686         "#101",
687         "#102",
688         "#103",
689         "#104",
690         "#105",
691         "#106",
692         "#107",
693         "#108",
694         "#109",
695         "#110",
696         "#111",
697         "#112",
698         "#113",
699         "#114",
700         "#115",
701         "#116",
702         "#117",
703         "#118",
704         "#119",
705         "#120",
706         "#121",
707         "#122",
708         "#123",
709         "#124",
710         "#125",
711         "#126",
712         "#127",
713         "echo",
714         "echo reply",
715         "multicast listener query",
716         "multicast listener report",
717         "multicast listener done",
718         "router solicitation",
719         "router advertisement",
720         "neighbor solicitation",
721         "neighbor advertisement",
722         "redirect",
723         "router renumbering",
724         "node information request",
725         "node information reply",
726         "inverse neighbor solicitation",
727         "inverse neighbor advertisement",
728         "#143",
729         "#144",
730         "#145",
731         "#146",
732         "#147",
733         "#148",
734         "#149",
735         "#150",
736         "#151",
737         "#152",
738         "#153",
739         "#154",
740         "#155",
741         "#156",
742         "#157",
743         "#158",
744         "#159",
745         "#160",
746         "#161",
747         "#162",
748         "#163",
749         "#164",
750         "#165",
751         "#166",
752         "#167",
753         "#168",
754         "#169",
755         "#170",
756         "#171",
757         "#172",
758         "#173",
759         "#174",
760         "#175",
761         "#176",
762         "#177",
763         "#178",
764         "#179",
765         "#180",
766         "#181",
767         "#182",
768         "#183",
769         "#184",
770         "#185",
771         "#186",
772         "#187",
773         "#188",
774         "#189",
775         "#180",
776         "#191",
777         "#192",
778         "#193",
779         "#194",
780         "#195",
781         "#196",
782         "#197",
783         "#198",
784         "#199",
785         "#200",
786         "#201",
787         "#202",
788         "#203",
789         "#204",
790         "#205",
791         "#206",
792         "#207",
793         "#208",
794         "#209",
795         "#210",
796         "#211",
797         "#212",
798         "#213",
799         "#214",
800         "#215",
801         "#216",
802         "#217",
803         "#218",
804         "#219",
805         "#220",
806         "#221",
807         "#222",
808         "#223",
809         "#224",
810         "#225",
811         "#226",
812         "#227",
813         "#228",
814         "#229",
815         "#230",
816         "#231",
817         "#232",
818         "#233",
819         "#234",
820         "#235",
821         "#236",
822         "#237",
823         "#238",
824         "#239",
825         "#240",
826         "#241",
827         "#242",
828         "#243",
829         "#244",
830         "#245",
831         "#246",
832         "#247",
833         "#248",
834         "#249",
835         "#250",
836         "#251",
837         "#252",
838         "#253",
839         "#254",
840         "#255",
841 };
842
843 /*
844  * Dump ICMP6 statistics.
845  */
846 void
847 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
848 {
849         struct icmp6stat icmp6stat;
850         int i, first;
851         size_t len;
852
853         len = sizeof icmp6stat;
854         if (live) {
855                 memset(&icmp6stat, 0, len);
856                 if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
857                     NULL, 0) < 0) {
858                         if (errno != ENOENT)
859                                 warn("sysctl: net.inet6.icmp6.stats");
860                         return;
861                 }
862         } else
863                 kread(off, &icmp6stat, len);
864
865         printf("%s:\n", name);
866
867 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
868     printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
869 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
870     printf(m, (uintmax_t)icmp6stat.f)
871
872         p(icp6s_error, "\t%ju call%s to icmp6_error\n");
873         p(icp6s_canterror,
874             "\t%ju error%s not generated in response to an icmp6 message\n");
875         p(icp6s_toofreq,
876           "\t%ju error%s not generated because of rate limitation\n");
877 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
878         for (first = 1, i = 0; i < NELEM; i++)
879                 if (icmp6stat.icp6s_outhist[i] != 0) {
880                         if (first) {
881                                 printf("\tOutput histogram:\n");
882                                 first = 0;
883                         }
884                         printf("\t\t%s: %ju\n", icmp6names[i],
885                             (uintmax_t)icmp6stat.icp6s_outhist[i]);
886                 }
887 #undef NELEM
888         p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
889         p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
890         p(icp6s_checksum, "\t%ju bad checksum%s\n");
891         p(icp6s_badlen, "\t%ju message%s with bad length\n");
892 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
893         for (first = 1, i = 0; i < NELEM; i++)
894                 if (icmp6stat.icp6s_inhist[i] != 0) {
895                         if (first) {
896                                 printf("\tInput histogram:\n");
897                                 first = 0;
898                         }
899                         printf("\t\t%s: %ju\n", icmp6names[i],
900                             (uintmax_t)icmp6stat.icp6s_inhist[i]);
901                 }
902 #undef NELEM
903         printf("\tHistogram of error messages to be generated:\n");
904         p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
905         p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
906         p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
907         p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
908         p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
909         p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
910         p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
911         p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
912         p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
913         p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
914         p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
915         p_5(icp6s_oredirect, "\t\t%ju redirect\n");
916         p_5(icp6s_ounknown, "\t\t%ju unknown\n");
917
918         p(icp6s_reflect, "\t%ju message response%s generated\n");
919         p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
920         p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
921         p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
922         p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
923         p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
924         p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
925         p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
926         p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
927 #undef p
928 #undef p_5
929 }
930
931 /*
932  * Dump ICMPv6 per-interface statistics based on RFC 2466.
933  */
934 void
935 icmp6_ifstats(char *ifname)
936 {
937         struct in6_ifreq ifr;
938         int s;
939 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
940     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
941 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
942     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
943
944         if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
945                 perror("Warning: socket(AF_INET6)");
946                 return;
947         }
948
949         strcpy(ifr.ifr_name, ifname);
950         printf("icmp6 on %s:\n", ifr.ifr_name);
951
952         if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
953                 perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
954                 goto end;
955         }
956
957         p(ifs6_in_msg, "\t%ju total input message%s\n");
958         p(ifs6_in_error, "\t%ju total input error message%s\n");
959         p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
960         p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
961         p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
962         p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
963         p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
964         p(ifs6_in_echo, "\t%ju input echo request%s\n");
965         p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
966         p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
967         p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
968         p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
969         p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
970         p(ifs6_in_redirect, "\t%ju input redirect%s\n");
971         p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
972         p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
973         p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
974
975         p(ifs6_out_msg, "\t%ju total output message%s\n");
976         p(ifs6_out_error, "\t%ju total output error message%s\n");
977         p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
978         p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
979         p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
980         p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
981         p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
982         p(ifs6_out_echo, "\t%ju output echo request%s\n");
983         p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
984         p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
985         p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
986         p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
987         p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
988         p(ifs6_out_redirect, "\t%ju output redirect%s\n");
989         p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
990         p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
991         p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
992
993   end:
994         close(s);
995 #undef p
996 }
997
998 /*
999  * Dump PIM statistics structure.
1000  */
1001 void
1002 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1003 {
1004         struct pim6stat pim6stat, zerostat;
1005         size_t len = sizeof pim6stat;
1006
1007         if (live) {
1008                 if (zflag)
1009                         memset(&zerostat, 0, len);
1010                 if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1011                     zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1012                         if (errno != ENOENT)
1013                                 warn("sysctl: net.inet6.pim.stats");
1014                         return;
1015                 }
1016         } else {
1017                 if (off == 0)
1018                         return;
1019                 kread(off, &pim6stat, len);
1020         }
1021
1022         printf("%s:\n", name);
1023
1024 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1025     printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1026         p(pim6s_rcv_total, "\t%ju message%s received\n");
1027         p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1028         p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1029         p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
1030         p(pim6s_rcv_registers, "\t%ju register%s received\n");
1031         p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
1032         p(pim6s_snd_registers, "\t%ju register%s sent\n");
1033 #undef p
1034 }
1035
1036 /*
1037  * Dump raw ip6 statistics structure.
1038  */
1039 void
1040 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1041 {
1042         struct rip6stat rip6stat;
1043         u_quad_t delivered;
1044         size_t len;
1045
1046         len = sizeof(rip6stat);
1047         if (live) {
1048                 if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1049                     NULL, 0) < 0) {
1050                         if (errno != ENOENT)
1051                                 warn("sysctl: net.inet6.ip6.rip6stats");
1052                         return;
1053                 }
1054         } else
1055                 kread(off, &rip6stat, len);
1056
1057         printf("%s:\n", name);
1058
1059 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1060     printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1061         p(rip6s_ipackets, "\t%ju message%s received\n");
1062         p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n");
1063         p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
1064         p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
1065         p(rip6s_nosockmcast,
1066             "\t%ju multicast message%s dropped due to no socket\n");
1067         p(rip6s_fullsock,
1068             "\t%ju message%s dropped due to full socket buffers\n");
1069         delivered = rip6stat.rip6s_ipackets -
1070                     rip6stat.rip6s_badsum -
1071                     rip6stat.rip6s_nosock -
1072                     rip6stat.rip6s_nosockmcast -
1073                     rip6stat.rip6s_fullsock;
1074         if (delivered || sflag <= 1)
1075                 printf("\t%ju delivered\n", (uintmax_t)delivered);
1076         p(rip6s_opackets, "\t%ju datagram%s output\n");
1077 #undef p
1078 }
1079
1080 /*
1081  * Pretty print an Internet address (net address + port).
1082  * Take numeric_addr and numeric_port into consideration.
1083  */
1084 #define GETSERVBYPORT6(port, proto, ret)\
1085 {\
1086         if (strcmp((proto), "tcp6") == 0)\
1087                 (ret) = getservbyport((int)(port), "tcp");\
1088         else if (strcmp((proto), "udp6") == 0)\
1089                 (ret) = getservbyport((int)(port), "udp");\
1090         else\
1091                 (ret) = getservbyport((int)(port), (proto));\
1092 };
1093
1094 void
1095 inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
1096 {
1097         struct servent *sp = 0;
1098         char line[80], *cp;
1099         int width;
1100
1101         sprintf(line, "%.*s.", Wflag ? 39 :
1102                 (Aflag && !numeric) ? 12 : 16, inet6name(in6));
1103         cp = index(line, '\0');
1104         if (!numeric && port)
1105                 GETSERVBYPORT6(port, proto, sp);
1106         if (sp || port == 0)
1107                 sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1108         else
1109                 sprintf(cp, "%d", ntohs((u_short)port));
1110         width = Wflag ? 45 : Aflag ? 18 : 22;
1111         printf("%-*.*s ", width, width, line);
1112 }
1113
1114 /*
1115  * Construct an Internet address representation.
1116  * If the numeric_addr has been supplied, give
1117  * numeric value, otherwise try for symbolic name.
1118  */
1119
1120 char *
1121 inet6name(struct in6_addr *in6p)
1122 {
1123         char *cp;
1124         static char line[50];
1125         struct hostent *hp;
1126         static char domain[MAXHOSTNAMELEN];
1127         static int first = 1;
1128
1129         if (first && !numeric_addr) {
1130                 first = 0;
1131                 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1132                     (cp = index(domain, '.')))
1133                         (void) strcpy(domain, cp + 1);
1134                 else
1135                         domain[0] = 0;
1136         }
1137         cp = 0;
1138         if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1139                 hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1140                 if (hp) {
1141                         if ((cp = index(hp->h_name, '.')) &&
1142                             !strcmp(cp + 1, domain))
1143                                 *cp = 0;
1144                         cp = hp->h_name;
1145                 }
1146         }
1147         if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1148                 strcpy(line, "*");
1149         else if (cp)
1150                 strcpy(line, cp);
1151         else
1152                 sprintf(line, "%s",
1153                         inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
1154                                 sizeof(ntop_buf)));
1155         return (line);
1156 }
1157 #endif /*INET6*/