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