1 /* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
3 * Copyright (c) 1983, 1988, 1993
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94";
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
41 #include <sys/param.h>
42 #include <sys/socket.h>
43 #include <sys/socketvar.h>
44 #include <sys/ioctl.h>
46 #include <sys/protosw.h>
47 #include <sys/sysctl.h>
49 #include <net/route.h>
51 #include <netinet/in.h>
52 #include <netinet/ip6.h>
53 #include <netinet/icmp6.h>
54 #include <netinet/in_systm.h>
55 #include <netinet6/in6_pcb.h>
56 #include <netinet6/in6_var.h>
57 #include <netinet6/ip6_var.h>
58 #include <netinet6/pim6_var.h>
59 #include <netinet6/raw_ip6.h>
61 #include <arpa/inet.h>
76 char *inet6name(struct in6_addr *);
78 static char ntop_buf[INET6_ADDRSTRLEN];
80 static const char *ip6nh[] = {
141 "destination option",
339 static const char *srcrule_str[] = {
343 "deprecated address",
345 "outgoing interface",
347 "public/temporary address",
349 "better virtual status",
359 * Dump IP6 statistics structure.
362 ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
364 struct ip6stat ip6stat, zerostat;
368 len = sizeof ip6stat;
370 memset(&ip6stat, 0, len);
372 memset(&zerostat, 0, len);
373 if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len,
374 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
376 xo_warn("sysctl: net.inet6.ip6.stats");
380 kread_counters(off, &ip6stat, len);
381 xo_open_container(name);
382 xo_emit("{T:/%s}:\n", name);
384 #define p(f, m) if (ip6stat.f || sflag <= 1) \
385 xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
386 #define p1a(f, m) if (ip6stat.f || sflag <= 1) \
387 xo_emit(m, (uintmax_t)ip6stat.f)
389 p(ip6s_total, "\t{:received-packets/%ju} "
390 "{N:/total packet%s received}\n");
391 p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
392 "{N:/with size smaller than minimum}\n");
393 p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
394 "{N:/with data size < data length}\n");
395 p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
396 "{N:/with bad options}\n");
397 p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
398 "{N:/with incorrect version number}\n");
399 p(ip6s_fragments, "\t{:received-fragments/%ju} "
400 "{N:/fragment%s received}\n");
401 p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
402 "{N:/fragment%s dropped (dup or out of space)}\n");
403 p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
404 "{N:/fragment%s dropped after timeout}\n");
405 p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
406 "{N:/fragment%s that exceeded limit}\n");
407 p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
408 "{N:/packet%s reassembled ok}\n");
409 p(ip6s_delivered, "\t{:received-local-packets/%ju} "
410 "{N:/packet%s for this host}\n");
411 p(ip6s_forward, "\t{:forwarded-packets/%ju} "
412 "{N:/packet%s forwarded}\n");
413 p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
414 "{N:/packet%s not forwardable}\n");
415 p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
416 "{N:/redirect%s sent}\n");
417 p(ip6s_localout, "\t{:sent-packets/%ju} "
418 "{N:/packet%s sent from this host}\n");
419 p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
420 "{N:/packet%s sent with fabricated ip header}\n");
421 p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
422 "{N:/output packet%s dropped due to no bufs, etc.}\n");
423 p(ip6s_noroute, "\t{:discard-no-route/%ju} "
424 "{N:/output packet%s discarded due to no route}\n");
425 p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
426 "{N:/output datagram%s fragmented}\n");
427 p(ip6s_ofragments, "\t{:fragments-created/%ju} "
428 "{N:/fragment%s created}\n");
429 p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
430 "{N:/datagram%s that can't be fragmented}\n");
431 p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
432 "{N:/packet%s that violated scope rules}\n");
433 p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
434 "{N:/multicast packet%s which we don't join}\n");
435 for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
436 if (ip6stat.ip6s_nxthist[i] != 0) {
438 xo_emit("\t{T:Input histogram}:\n");
439 xo_open_list("input-histogram");
442 xo_open_instance("input-histogram");
443 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
444 (uintmax_t)ip6stat.ip6s_nxthist[i]);
445 xo_close_instance("input-histogram");
448 xo_close_list("input-histogram");
450 xo_open_container("mbuf-statistics");
451 xo_emit("\t{T:Mbuf statistics}:\n");
452 xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
453 (uintmax_t)ip6stat.ip6s_m1);
454 for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
455 char ifbuf[IFNAMSIZ];
456 if (ip6stat.ip6s_m2m[i] != 0) {
458 xo_emit("\t\t{N:two or more mbuf}:\n");
459 xo_open_list("mbuf-data");
462 xo_open_instance("mbuf-data");
463 xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
464 if_indextoname(i, ifbuf),
465 (uintmax_t)ip6stat.ip6s_m2m[i]);
466 xo_close_instance("mbuf-data");
470 xo_close_list("mbuf-data");
471 xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
472 (uintmax_t)ip6stat.ip6s_mext1);
473 xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
474 "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
475 xo_close_container("mbuf-statistics");
477 p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
478 "{N:/packet%s whose headers are not contiguous}\n");
479 p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
480 "{N:/tunneling packet%s that can't find gif}\n");
481 p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
482 "{N:/packet%s discarded because of too many headers}\n");
484 /* for debugging source address selection */
485 #define PRINT_SCOPESTAT(s,i) do {\
486 switch(i) { /* XXX hardcoding in each case */\
488 p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
489 "{N:/interface-local%s}\n"); \
492 p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
493 "{N:/link-local%s}\n"); \
496 p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
497 "{N:/site-local%s}\n");\
500 p(s,"\t\t{ke:name/globals}{:count/%ju} " \
504 xo_emit("\t\t{qke:name/%x}{:count/%ju} " \
505 "addresses scope=%x\n",\
506 i, (uintmax_t)ip6stat.s, i); \
510 xo_open_container("source-address-selection");
511 p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
512 "{N:/failure%s of source address selection}\n");
514 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
515 if (ip6stat.ip6s_sources_sameif[i]) {
517 xo_open_list("outgoing-interface");
518 xo_emit("\tsource addresses on an outgoing "
522 xo_open_instance("outgoing-interface");
523 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
524 xo_close_instance("outgoing-interface");
528 xo_close_list("outgoing-interface");
530 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
531 if (ip6stat.ip6s_sources_otherif[i]) {
533 xo_open_list("non-outgoing-interface");
534 xo_emit("\tsource addresses on a non-outgoing "
538 xo_open_instance("non-outgoing-interface");
539 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
540 xo_close_instance("non-outgoing-interface");
544 xo_close_list("non-outgoing-interface");
546 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
547 if (ip6stat.ip6s_sources_samescope[i]) {
549 xo_open_list("same-source");
550 xo_emit("\tsource addresses of same scope\n");
553 xo_open_instance("same-source");
554 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
555 xo_close_instance("same-source");
559 xo_close_list("same-source");
561 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
562 if (ip6stat.ip6s_sources_otherscope[i]) {
564 xo_open_list("different-scope");
565 xo_emit("\tsource addresses of a different "
569 xo_open_instance("different-scope");
570 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
571 xo_close_instance("different-scope");
575 xo_close_list("different-scope");
577 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
578 if (ip6stat.ip6s_sources_deprecated[i]) {
580 xo_open_list("deprecated-source");
581 xo_emit("\tdeprecated source addresses\n");
584 xo_open_instance("deprecated-source");
585 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
586 xo_close_instance("deprecated-source");
590 xo_close_list("deprecated-source");
592 for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
593 if (ip6stat.ip6s_sources_rule[i]) {
595 xo_open_list("rules-applied");
596 xo_emit("\t{T:Source addresses selection "
600 xo_open_instance("rules-applied");
601 xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
603 (uintmax_t)ip6stat.ip6s_sources_rule[i],
605 xo_close_instance("rules-applied");
609 xo_close_list("rules-applied");
611 xo_close_container("source-address-selection");
615 xo_close_container(name);
619 * Dump IPv6 per-interface statistics based on RFC 2465.
622 ip6_ifstats(char *ifname)
624 struct in6_ifreq ifr;
627 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
628 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, \
629 plural(ifr.ifr_ifru.ifru_stat.f))
631 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
632 xo_warn("Warning: socket(AF_INET6)");
636 strcpy(ifr.ifr_name, ifname);
637 if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
638 if (errno != EPFNOSUPPORT)
639 xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
643 xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
645 xo_open_instance("ip6-interface-statistics");
646 xo_emit("{ke:name/%s}", ifr.ifr_name);
648 p(ifs6_in_receive, "\t{:received-packets/%ju} "
649 "{N:/total input datagram%s}\n");
650 p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
651 "{N:/datagram%s with invalid header received}\n");
652 p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
653 "{N:/datagram%s exceeded MTU received}\n");
654 p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
655 "{N:/datagram%s with no route received}\n");
656 p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
657 "{N:/datagram%s with invalid dst received}\n");
658 p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
659 "{N:/datagram%s with unknown proto received}\n");
660 p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
661 "{N:/truncated datagram%s received}\n");
662 p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
663 "{N:/input datagram%s discarded}\n");
664 p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
665 "{N:/datagram%s delivered to an upper layer protocol}\n");
666 p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
667 "{N:/datagram%s forwarded to this interface}\n");
668 p(ifs6_out_request, "\t{:sent-packets/%ju} "
669 "{N:/datagram%s sent from an upper layer protocol}\n");
670 p(ifs6_out_discard, "\t{:discard-packets/%ju} "
671 "{N:/total discarded output datagram%s}\n");
672 p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
673 "{N:/output datagram%s fragmented}\n");
674 p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
675 "{N:/output datagram%s failed on fragment}\n");
676 p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
677 "{N:/output datagram%s succeeded on fragment}\n");
678 p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
679 "{N:/incoming datagram%s fragmented}\n");
680 p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
681 "{N:/datagram%s reassembled}\n");
682 p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
683 "{N:/datagram%s failed on reassembly}\n");
684 p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
685 "{N:/multicast datagram%s received}\n");
686 p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
687 "{N:/multicast datagram%s sent}\n");
690 xo_close_instance("ip6-interface-statistics");
696 static const char *icmp6names[] = {
827 "multicast listener query",
828 "MLDv1 listener report",
829 "MLDv1 listener done",
830 "router solicitation",
831 "router advertisement",
832 "neighbor solicitation",
833 "neighbor advertisement",
835 "router renumbering",
836 "node information request",
837 "node information reply",
838 "inverse neighbor solicitation",
839 "inverse neighbor advertisement",
840 "MLDv2 listener report",
956 * Dump ICMP6 statistics.
959 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
961 struct icmp6stat icmp6stat, zerostat;
965 len = sizeof icmp6stat;
967 memset(&icmp6stat, 0, len);
969 memset(&zerostat, 0, len);
970 if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
971 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
973 xo_warn("sysctl: net.inet6.icmp6.stats");
977 kread_counters(off, &icmp6stat, len);
979 xo_emit("{T:/%s}:\n", name);
980 xo_open_container(name);
982 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
983 xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
984 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
985 xo_emit(m, (uintmax_t)icmp6stat.f)
987 p(icp6s_error, "\t{:icmp6-calls/%ju} "
988 "{N:/call%s to icmp6_error}\n");
989 p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
990 "{N:/error%s not generated in response to an icmp6 message}\n");
991 p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
992 "{N:/error%s not generated because of rate limitation}\n");
993 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
994 for (first = 1, i = 0; i < NELEM; i++)
995 if (icmp6stat.icp6s_outhist[i] != 0) {
997 xo_open_list("output-histogram");
998 xo_emit("\t{T:Output histogram}:\n");
1001 xo_open_instance("output-histogram");
1002 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1004 (uintmax_t)icmp6stat.icp6s_outhist[i]);
1005 xo_close_instance("output-histogram");
1008 xo_close_list("output-histogram");
1011 p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
1012 "{N:/message%s with bad code fields}\n");
1013 p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
1014 "{N:/message%s < minimum length}\n");
1015 p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
1016 "{N:/bad checksum%s}\n");
1017 p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
1018 "{N:/message%s with bad length}\n");
1019 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
1020 for (first = 1, i = 0; i < NELEM; i++)
1021 if (icmp6stat.icp6s_inhist[i] != 0) {
1023 xo_open_list("input-histogram");
1024 xo_emit("\t{T:Input histogram}:\n");
1027 xo_open_instance("input-histogram");
1028 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1030 (uintmax_t)icmp6stat.icp6s_inhist[i]);
1031 xo_close_instance("input-histogram");
1034 xo_close_list("input-histogram");
1036 xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1037 xo_open_container("errors");
1038 p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1040 p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1041 "{N:/administratively prohibited}\n");
1042 p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1043 "{N:/beyond scope}\n");
1044 p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1045 "{N:/address unreachable}\n");
1046 p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1047 "{N:/port unreachable}\n");
1048 p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1049 "{N:/packet too big}\n");
1050 p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1051 "{N:/time exceed transit}\n");
1052 p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1053 "{N:/time exceed reassembly}\n");
1054 p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1055 "{N:/erroneous header field}\n");
1056 p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1057 "{N:/unrecognized next header}\n");
1058 p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1059 "{N:/unrecognized option}\n");
1060 p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1062 p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1064 p(icp6s_reflect, "\t{:reflect/%ju} "
1065 "{N:/message response%s generated}\n");
1066 p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1067 "{N:/message%s with too many ND options}\n");
1068 p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1069 "{N:/message%s with bad ND options}\n");
1070 p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1071 "{N:/bad neighbor solicitation message%s}\n");
1072 p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1073 "{N:/bad neighbor advertisement message%s}\n");
1074 p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1075 "{N:/bad router solicitation message%s}\n");
1076 p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1077 "{N:/bad router advertisement message%s}\n");
1078 p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1079 "{N:/bad redirect message%s}\n");
1080 xo_close_container("errors");
1081 p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1084 xo_close_container(name);
1088 * Dump ICMPv6 per-interface statistics based on RFC 2466.
1091 icmp6_ifstats(char *ifname)
1093 struct in6_ifreq ifr;
1096 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1097 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1098 plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1099 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1100 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1101 pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1103 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1104 xo_warn("Warning: socket(AF_INET6)");
1108 strcpy(ifr.ifr_name, ifname);
1109 if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1110 if (errno != EPFNOSUPPORT)
1111 xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1115 xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1117 xo_open_instance("icmp6-interface-statistics");
1118 xo_emit("{ke:name/%s}", ifr.ifr_name);
1119 p(ifs6_in_msg, "\t{:received-packets/%ju} "
1120 "{N:/total input message%s}\n");
1121 p(ifs6_in_error, "\t{:received-errors/%ju} "
1122 "{N:/total input error message%s}\n");
1123 p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1124 "{N:/input destination unreachable error%s}\n");
1125 p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1126 "{N:/input administratively prohibited error%s}\n");
1127 p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1128 "{N:/input time exceeded error%s}\n");
1129 p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1130 "{N:/input parameter problem error%s}\n");
1131 p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1132 "{N:/input packet too big error%s}\n");
1133 p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1134 "{N:/input echo request%s}\n");
1135 p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1136 "{N:/input echo repl%s}\n");
1137 p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1138 "{N:/input router solicitation%s}\n");
1139 p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1140 "{N:/input router advertisement%s}\n");
1141 p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1142 "{N:/input neighbor solicitation%s}\n");
1143 p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1144 "{N:/input neighbor advertisement%s}\n");
1145 p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1146 "{N:/input redirect%s}\n");
1147 p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1148 "{N:/input MLD quer%s}\n");
1149 p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1150 "{N:/input MLD report%s}\n");
1151 p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1152 "{N:/input MLD done%s}\n");
1154 p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1155 "{N:/total output message%s}\n");
1156 p(ifs6_out_error, "\t{:sent-errors/%ju} "
1157 "{N:/total output error message%s}\n");
1158 p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1159 "{N:/output destination unreachable error%s}\n");
1160 p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1161 "{N:/output administratively prohibited error%s}\n");
1162 p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1163 "{N:/output time exceeded error%s}\n");
1164 p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1165 "{N:/output parameter problem error%s}\n");
1166 p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1167 "{N:/output packet too big error%s}\n");
1168 p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1169 "{N:/output echo request%s}\n");
1170 p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1171 "{N:/output echo repl%s}\n");
1172 p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1173 "{N:/output router solicitation%s}\n");
1174 p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1175 "{N:/output router advertisement%s}\n");
1176 p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1177 "{N:/output neighbor solicitation%s}\n");
1178 p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1179 "{N:/output neighbor advertisement%s}\n");
1180 p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1181 "{N:/output redirect%s}\n");
1182 p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1183 "{N:/output MLD quer%s}\n");
1184 p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1185 "{N:/output MLD report%s}\n");
1186 p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1187 "{N:/output MLD done%s}\n");
1190 xo_close_instance("icmp6-interface-statistics");
1196 * Dump PIM statistics structure.
1199 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1201 struct pim6stat pim6stat, zerostat;
1202 size_t len = sizeof pim6stat;
1206 memset(&zerostat, 0, len);
1207 if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1208 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1209 if (errno != ENOENT)
1210 xo_warn("sysctl: net.inet6.pim.stats");
1216 kread(off, &pim6stat, len);
1219 xo_emit("{T:/%s}:\n", name);
1220 xo_open_container(name);
1222 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1223 xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1225 p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1226 "{N:/message%s received}\n");
1227 p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1228 "{N:/message%s received with too few bytes}\n");
1229 p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1230 "{N:/message%s received with bad checksum}\n");
1231 p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1232 "{N:/message%s received with bad version}\n");
1233 p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1234 "{N:/register%s received}\n");
1235 p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1236 "{N:/bad register%s received}\n");
1237 p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1238 "{N:/register%s sent}\n");
1240 xo_close_container(name);
1244 * Dump raw ip6 statistics structure.
1247 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1249 struct rip6stat rip6stat, zerostat;
1253 len = sizeof(rip6stat);
1256 memset(&zerostat, 0, len);
1257 if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1258 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1259 if (errno != ENOENT)
1260 xo_warn("sysctl: net.inet6.ip6.rip6stats");
1264 kread_counters(off, &rip6stat, len);
1266 xo_emit("{T:/%s}:\n", name);
1267 xo_open_container(name);
1269 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1270 xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1272 p(rip6s_ipackets, "\t{:received-packets/%ju} "
1273 "{N:/message%s received}\n");
1274 p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1275 "{N:/checksum calculation%s on inbound}\n");
1276 p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1277 "{N:/message%s with bad checksum}\n");
1278 p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1279 "{N:/message%s dropped due to no socket}\n");
1280 p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1281 "{N:/multicast message%s dropped due to no socket}\n");
1282 p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1283 "{N:/message%s dropped due to full socket buffers}\n");
1284 delivered = rip6stat.rip6s_ipackets -
1285 rip6stat.rip6s_badsum -
1286 rip6stat.rip6s_nosock -
1287 rip6stat.rip6s_nosockmcast -
1288 rip6stat.rip6s_fullsock;
1289 if (delivered || sflag <= 1)
1290 xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1291 (uintmax_t)delivered);
1292 p(rip6s_opackets, "\t{:sent-packets/%ju} "
1293 "{N:/datagram%s output}\n");
1295 xo_close_container(name);
1299 * Pretty print an Internet address (net address + port).
1300 * Take numeric_addr and numeric_port into consideration.
1302 #define GETSERVBYPORT6(port, proto, ret)\
1304 if (strcmp((proto), "tcp6") == 0)\
1305 (ret) = getservbyport((int)(port), "tcp");\
1306 else if (strcmp((proto), "udp6") == 0)\
1307 (ret) = getservbyport((int)(port), "udp");\
1309 (ret) = getservbyport((int)(port), (proto));\
1313 inet6print(const char *container, struct in6_addr *in6, int port,
1314 const char *proto, int numeric)
1316 struct servent *sp = 0;
1321 xo_open_container(container);
1323 sprintf(line, "%.*s.", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1325 cp = strchr(line, '\0');
1326 if (!numeric && port)
1327 GETSERVBYPORT6(port, proto, sp);
1328 if (sp || port == 0)
1329 sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1331 sprintf(cp, "%d", ntohs((u_short)port));
1332 width = Wflag ? 45 : Aflag ? 18 : 22;
1334 xo_emit("{d:target/%-*.*s} ", width, width, line);
1336 int alen = cp - line - 1, plen = strlen(cp) - 1;
1337 xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1341 xo_close_container(container);
1345 * Construct an Internet address representation.
1346 * If the numeric_addr has been supplied, give
1347 * numeric value, otherwise try for symbolic name.
1351 inet6name(struct in6_addr *in6p)
1353 struct sockaddr_in6 sin6;
1354 char hbuf[NI_MAXHOST], *cp;
1355 static char line[50];
1356 static char domain[MAXHOSTNAMELEN];
1357 static int first = 1;
1360 if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1364 if (first && !numeric_addr) {
1366 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1367 (cp = strchr(domain, '.')))
1368 (void) strcpy(domain, cp + 1);
1372 memset(&sin6, 0, sizeof(sin6));
1373 memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1374 sin6.sin6_family = AF_INET6;
1375 /* XXX: in6p.s6_addr[2] can contain scopeid. */
1376 in6_fillscopeid(&sin6);
1377 flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1378 error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1379 sizeof(hbuf), NULL, 0, flags);
1381 if ((flags & NI_NUMERICHOST) == 0 &&
1382 (cp = strchr(hbuf, '.')) &&
1383 !strcmp(cp + 1, domain))
1387 /* XXX: this should not happen. */
1389 inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,