]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/netstat/inet6.c
This commit was generated by cvs2svn to compensate for changes in r170349,
[FreeBSD/FreeBSD.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 __unused, const char *name, int af1 __unused)
366 {
367         struct ip6stat ip6stat;
368         int first, i;
369         int mib[4];
370         size_t len;
371
372         mib[0] = CTL_NET;
373         mib[1] = PF_INET6;
374         mib[2] = IPPROTO_IPV6;
375         mib[3] = IPV6CTL_STATS;
376
377         len = sizeof ip6stat;
378         memset(&ip6stat, 0, len);
379         if (sysctl(mib, 4, &ip6stat, &len, (void *)0, 0) < 0)
380                 return;
381         printf("%s:\n", name);
382
383 #define p(f, m) if (ip6stat.f || sflag <= 1) \
384     printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
385 #define p1a(f, m) if (ip6stat.f || sflag <= 1) \
386     printf(m, (uintmax_t)ip6stat.f)
387
388         p(ip6s_total, "\t%ju total packet%s received\n");
389         p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n");
390         p1a(ip6s_tooshort, "\t%ju with data size < data length\n");
391         p1a(ip6s_badoptions, "\t%ju with bad options\n");
392         p1a(ip6s_badvers, "\t%ju with incorrect version number\n");
393         p(ip6s_fragments, "\t%ju fragment%s received\n");
394         p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n");
395         p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n");
396         p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n");
397         p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n");
398         p(ip6s_delivered, "\t%ju packet%s for this host\n");
399         p(ip6s_forward, "\t%ju packet%s forwarded\n");
400         p(ip6s_cantforward, "\t%ju packet%s not forwardable\n");
401         p(ip6s_redirectsent, "\t%ju redirect%s sent\n");
402         p(ip6s_localout, "\t%ju packet%s sent from this host\n");
403         p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n");
404         p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n");
405         p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n");
406         p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n");
407         p(ip6s_ofragments, "\t%ju fragment%s created\n");
408         p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n");
409         p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n");
410         p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n");
411         for (first = 1, i = 0; i < 256; i++)
412                 if (ip6stat.ip6s_nxthist[i] != 0) {
413                         if (first) {
414                                 printf("\tInput histogram:\n");
415                                 first = 0;
416                         }
417                         printf("\t\t%s: %ju\n", ip6nh[i],
418                             (uintmax_t)ip6stat.ip6s_nxthist[i]);
419                 }
420         printf("\tMbuf statistics:\n");
421         printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1);
422         for (first = 1, i = 0; i < 32; i++) {
423                 char ifbuf[IFNAMSIZ];
424                 if (ip6stat.ip6s_m2m[i] != 0) {         
425                         if (first) {
426                                 printf("\t\ttwo or more mbuf:\n");
427                                 first = 0;
428                         }
429                         printf("\t\t\t%s= %ju\n",
430                             if_indextoname(i, ifbuf),
431                             (uintmax_t)ip6stat.ip6s_m2m[i]);
432                 }
433         }
434         printf("\t\t%ju one ext mbuf\n",
435             (uintmax_t)ip6stat.ip6s_mext1);
436         printf("\t\t%ju two or more ext mbuf\n",
437             (uintmax_t)ip6stat.ip6s_mext2m);    
438         p(ip6s_exthdrtoolong,
439             "\t%ju packet%s whose headers are not continuous\n");
440         p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n");
441         p(ip6s_toomanyhdr,
442             "\t%ju packet%s discarded because of too many headers\n");
443
444         /* for debugging source address selection */
445 #define PRINT_SCOPESTAT(s,i) do {\
446                 switch(i) { /* XXX hardcoding in each case */\
447                 case 1:\
448                         p(s, "\t\t%ju node-local%s\n");\
449                         break;\
450                 case 2:\
451                         p(s,"\t\t%ju link-local%s\n");\
452                         break;\
453                 case 5:\
454                         p(s,"\t\t%ju site-local%s\n");\
455                         break;\
456                 case 14:\
457                         p(s,"\t\t%ju global%s\n");\
458                         break;\
459                 default:\
460                         printf("\t\t%ju addresses scope=%x\n",\
461                             (uintmax_t)ip6stat.s, i);\
462                 }\
463         } while (0);
464
465         p(ip6s_sources_none,
466           "\t%ju failure%s of source address selection\n");
467         for (first = 1, i = 0; i < 16; i++) {
468                 if (ip6stat.ip6s_sources_sameif[i]) {
469                         if (first) {
470                                 printf("\tsource addresses on an outgoing I/F\n");
471                                 first = 0;
472                         }
473                         PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
474                 }
475         }
476         for (first = 1, i = 0; i < 16; i++) {
477                 if (ip6stat.ip6s_sources_otherif[i]) {
478                         if (first) {
479                                 printf("\tsource addresses on a non-outgoing I/F\n");
480                                 first = 0;
481                         }
482                         PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
483                 }
484         }
485         for (first = 1, i = 0; i < 16; i++) {
486                 if (ip6stat.ip6s_sources_samescope[i]) {
487                         if (first) {
488                                 printf("\tsource addresses of same scope\n");
489                                 first = 0;
490                         }
491                         PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
492                 }
493         }
494         for (first = 1, i = 0; i < 16; i++) {
495                 if (ip6stat.ip6s_sources_otherscope[i]) {
496                         if (first) {
497                                 printf("\tsource addresses of a different scope\n");
498                                 first = 0;
499                         }
500                         PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
501                 }
502         }
503         for (first = 1, i = 0; i < 16; i++) {
504                 if (ip6stat.ip6s_sources_deprecated[i]) {
505                         if (first) {
506                                 printf("\tdeprecated source addresses\n");
507                                 first = 0;
508                         }
509                         PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
510                 }
511         }
512
513         p1a(ip6s_forward_cachehit, "\t%ju forward cache hit\n");
514         p1a(ip6s_forward_cachemiss, "\t%ju forward cache miss\n");
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         "multicast listener report",
715         "multicast 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         "#143",
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 __unused, const char *name, int af1 __unused)
846 {
847         struct icmp6stat icmp6stat;
848         int i, first;
849         int mib[4];
850         size_t len;
851
852         mib[0] = CTL_NET;
853         mib[1] = PF_INET6;
854         mib[2] = IPPROTO_ICMPV6;
855         mib[3] = ICMPV6CTL_STATS;
856
857         len = sizeof icmp6stat;
858         memset(&icmp6stat, 0, len);
859         if (sysctl(mib, 4, &icmp6stat, &len, (void *)0, 0) < 0)
860                 return;
861         printf("%s:\n", name);
862
863 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
864     printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
865 #define p_5(f, m) printf(m, (uintmax_t)icmp6stat.f)
866
867         p(icp6s_error, "\t%ju call%s to icmp6_error\n");
868         p(icp6s_canterror,
869             "\t%ju error%s not generated in response to an icmp6 message\n");
870         p(icp6s_toofreq,
871           "\t%ju error%s not generated because of rate limitation\n");
872 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
873         for (first = 1, i = 0; i < NELEM; i++)
874                 if (icmp6stat.icp6s_outhist[i] != 0) {
875                         if (first) {
876                                 printf("\tOutput histogram:\n");
877                                 first = 0;
878                         }
879                         printf("\t\t%s: %ju\n", icmp6names[i],
880                             (uintmax_t)icmp6stat.icp6s_outhist[i]);
881                 }
882 #undef NELEM
883         p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
884         p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
885         p(icp6s_checksum, "\t%ju bad checksum%s\n");
886         p(icp6s_badlen, "\t%ju message%s with bad length\n");
887 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
888         for (first = 1, i = 0; i < NELEM; i++)
889                 if (icmp6stat.icp6s_inhist[i] != 0) {
890                         if (first) {
891                                 printf("\tInput histogram:\n");
892                                 first = 0;
893                         }
894                         printf("\t\t%s: %ju\n", icmp6names[i],
895                             (uintmax_t)icmp6stat.icp6s_inhist[i]);
896                 }
897 #undef NELEM
898         printf("\tHistogram of error messages to be generated:\n");
899         p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
900         p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
901         p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
902         p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
903         p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
904         p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
905         p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
906         p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
907         p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
908         p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
909         p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
910         p_5(icp6s_oredirect, "\t\t%ju redirect\n");
911         p_5(icp6s_ounknown, "\t\t%ju unknown\n");
912
913         p(icp6s_reflect, "\t%ju message response%s generated\n");
914         p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
915         p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
916         p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
917         p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
918         p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
919         p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
920         p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
921         p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
922 #undef p
923 #undef p_5
924 }
925
926 /*
927  * Dump ICMPv6 per-interface statistics based on RFC 2466.
928  */
929 void
930 icmp6_ifstats(char *ifname)
931 {
932         struct in6_ifreq ifr;
933         int s;
934 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
935     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
936 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
937     printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
938
939         if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
940                 perror("Warning: socket(AF_INET6)");
941                 return;
942         }
943
944         strcpy(ifr.ifr_name, ifname);
945         printf("icmp6 on %s:\n", ifr.ifr_name);
946
947         if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
948                 perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
949                 goto end;
950         }
951
952         p(ifs6_in_msg, "\t%ju total input message%s\n");
953         p(ifs6_in_error, "\t%ju total input error message%s\n"); 
954         p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
955         p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
956         p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
957         p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
958         p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
959         p(ifs6_in_echo, "\t%ju input echo request%s\n");
960         p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
961         p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
962         p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
963         p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
964         p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
965         p(ifs6_in_redirect, "\t%ju input redirect%s\n");
966         p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
967         p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
968         p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
969
970         p(ifs6_out_msg, "\t%ju total output message%s\n");
971         p(ifs6_out_error, "\t%ju total output error message%s\n");
972         p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
973         p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
974         p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
975         p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
976         p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
977         p(ifs6_out_echo, "\t%ju output echo request%s\n");
978         p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
979         p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
980         p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
981         p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
982         p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
983         p(ifs6_out_redirect, "\t%ju output redirect%s\n");
984         p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
985         p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
986         p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
987
988   end:
989         close(s);
990 #undef p
991 }
992
993 /*
994  * Dump PIM statistics structure.
995  */
996 void
997 pim6_stats(u_long off __unused, const char *name, int af1 __unused)
998 {
999         struct pim6stat pim6stat, zerostat;
1000         size_t len = sizeof pim6stat;
1001
1002         /* TODO put back the KVM functionality for -M switch ie coredumps. */
1003         if (zflag)
1004                 memset(&zerostat, 0, len);
1005         if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1006             zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1007                 if (errno != ENOENT)
1008                         warn("sysctl: net.inet6.pim.stats");
1009                 return;
1010         }
1011         printf("%s:\n", name);
1012
1013 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1014     printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1015         p(pim6s_rcv_total, "\t%ju message%s received\n");
1016         p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
1017         p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
1018         p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
1019         p(pim6s_rcv_registers, "\t%ju register%s received\n");
1020         p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
1021         p(pim6s_snd_registers, "\t%ju register%s sent\n");
1022 #undef p
1023 }
1024
1025 /*
1026  * Dump raw ip6 statistics structure.
1027  */
1028 void
1029 rip6_stats(u_long off __unused, const char *name, int af1 __unused)
1030 {
1031         struct rip6stat rip6stat;
1032         u_quad_t delivered;
1033         int mib[4];
1034         size_t l;
1035
1036         mib[0] = CTL_NET;
1037         mib[1] = PF_INET6;
1038         mib[2] = IPPROTO_IPV6;
1039         mib[3] = IPV6CTL_RIP6STATS;
1040         l = sizeof(rip6stat);
1041         if (sysctl(mib, 4, &rip6stat, &l, NULL, 0) < 0) {
1042                 /* Just shut up if the kernel doesn't have ipv6. */
1043                 if (errno != ENOENT)
1044                         perror("Warning: sysctl(net.inet6.ip6.rip6stats)");
1045                 return;
1046         }
1047
1048         printf("%s:\n", name);
1049
1050 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1051     printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1052         p(rip6s_ipackets, "\t%ju message%s received\n");
1053         p(rip6s_isum, "\t%ju checksum calcuration%s on inbound\n");
1054         p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
1055         p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
1056         p(rip6s_nosockmcast,
1057             "\t%ju multicast message%s dropped due to no socket\n");
1058         p(rip6s_fullsock,
1059             "\t%ju message%s dropped due to full socket buffers\n");
1060         delivered = rip6stat.rip6s_ipackets -
1061                     rip6stat.rip6s_badsum -
1062                     rip6stat.rip6s_nosock -
1063                     rip6stat.rip6s_nosockmcast -
1064                     rip6stat.rip6s_fullsock;
1065         if (delivered || sflag <= 1)
1066                 printf("\t%ju delivered\n", (uintmax_t)delivered);
1067         p(rip6s_opackets, "\t%ju datagram%s output\n");
1068 #undef p
1069 }
1070
1071 /*
1072  * Pretty print an Internet address (net address + port).
1073  * Take numeric_addr and numeric_port into consideration.
1074  */
1075 #define GETSERVBYPORT6(port, proto, ret)\
1076 {\
1077         if (strcmp((proto), "tcp6") == 0)\
1078                 (ret) = getservbyport((int)(port), "tcp");\
1079         else if (strcmp((proto), "udp6") == 0)\
1080                 (ret) = getservbyport((int)(port), "udp");\
1081         else\
1082                 (ret) = getservbyport((int)(port), (proto));\
1083 };
1084
1085 void
1086 inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
1087 {
1088         struct servent *sp = 0;
1089         char line[80], *cp;
1090         int width;
1091
1092         sprintf(line, "%.*s.", Wflag ? 39 :
1093                 (Aflag && !numeric) ? 12 : 16, inet6name(in6));
1094         cp = index(line, '\0');
1095         if (!numeric && port)
1096                 GETSERVBYPORT6(port, proto, sp);
1097         if (sp || port == 0)
1098                 sprintf(cp, "%.8s", sp ? sp->s_name : "*");
1099         else
1100                 sprintf(cp, "%d", ntohs((u_short)port));
1101         width = Wflag ? 45 : Aflag ? 18 : 22;
1102         printf("%-*.*s ", width, width, line);
1103 }
1104
1105 /*
1106  * Construct an Internet address representation.
1107  * If the numeric_addr has been supplied, give
1108  * numeric value, otherwise try for symbolic name.
1109  */
1110
1111 char *
1112 inet6name(struct in6_addr *in6p)
1113 {
1114         char *cp;
1115         static char line[50];
1116         struct hostent *hp;
1117         static char domain[MAXHOSTNAMELEN];
1118         static int first = 1;
1119
1120         if (first && !numeric_addr) {
1121                 first = 0;
1122                 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1123                     (cp = index(domain, '.')))
1124                         (void) strcpy(domain, cp + 1);
1125                 else
1126                         domain[0] = 0;
1127         }
1128         cp = 0;
1129         if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1130                 hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
1131                 if (hp) {
1132                         if ((cp = index(hp->h_name, '.')) &&
1133                             !strcmp(cp + 1, domain))
1134                                 *cp = 0;
1135                         cp = hp->h_name;
1136                 }
1137         }
1138         if (IN6_IS_ADDR_UNSPECIFIED(in6p))
1139                 strcpy(line, "*");
1140         else if (cp)
1141                 strcpy(line, cp);
1142         else 
1143                 sprintf(line, "%s",
1144                         inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
1145                                 sizeof(ntop_buf)));
1146         return (line);
1147 }
1148 #endif /*INET6*/