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 <net/if_var.h>
52 #include <netinet/in.h>
53 #include <netinet/ip6.h>
54 #include <netinet/icmp6.h>
55 #include <netinet/in_systm.h>
56 #include <netinet6/in6_pcb.h>
57 #include <netinet6/in6_var.h>
58 #include <netinet6/ip6_var.h>
59 #include <netinet6/pim6_var.h>
60 #include <netinet6/raw_ip6.h>
62 #include <arpa/inet.h>
77 char *inet6name(struct in6_addr *);
79 static char ntop_buf[INET6_ADDRSTRLEN];
81 static const char *ip6nh[] = {
142 "destination option",
340 static const char *srcrule_str[] = {
344 "deprecated address",
346 "outgoing interface",
348 "public/temporary address",
350 "better virtual status",
360 * Dump IP6 statistics structure.
363 ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
365 struct ip6stat ip6stat, zerostat;
369 len = sizeof ip6stat;
371 memset(&ip6stat, 0, len);
373 memset(&zerostat, 0, len);
374 if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len,
375 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
377 xo_warn("sysctl: net.inet6.ip6.stats");
381 kread_counters(off, &ip6stat, len);
382 xo_open_container(name);
383 xo_emit("{T:/%s}:\n", name);
385 #define p(f, m) if (ip6stat.f || sflag <= 1) \
386 xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
387 #define p1a(f, m) if (ip6stat.f || sflag <= 1) \
388 xo_emit(m, (uintmax_t)ip6stat.f)
390 p(ip6s_total, "\t{:received-packets/%ju} "
391 "{N:/total packet%s received}\n");
392 p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
393 "{N:/with size smaller than minimum}\n");
394 p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
395 "{N:/with data size < data length}\n");
396 p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
397 "{N:/with bad options}\n");
398 p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
399 "{N:/with incorrect version number}\n");
400 p(ip6s_fragments, "\t{:received-fragments/%ju} "
401 "{N:/fragment%s received}\n");
402 p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
403 "{N:/fragment%s dropped (dup or out of space)}\n");
404 p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
405 "{N:/fragment%s dropped after timeout}\n");
406 p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
407 "{N:/fragment%s that exceeded limit}\n");
408 p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
409 "{N:/packet%s reassembled ok}\n");
410 p(ip6s_delivered, "\t{:received-local-packets/%ju} "
411 "{N:/packet%s for this host}\n");
412 p(ip6s_forward, "\t{:forwarded-packets/%ju} "
413 "{N:/packet%s forwarded}\n");
414 p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
415 "{N:/packet%s not forwardable}\n");
416 p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
417 "{N:/redirect%s sent}\n");
418 p(ip6s_localout, "\t{:sent-packets/%ju} "
419 "{N:/packet%s sent from this host}\n");
420 p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
421 "{N:/packet%s sent with fabricated ip header}\n");
422 p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
423 "{N:/output packet%s dropped due to no bufs, etc.}\n");
424 p(ip6s_noroute, "\t{:discard-no-route/%ju} "
425 "{N:/output packet%s discarded due to no route}\n");
426 p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
427 "{N:/output datagram%s fragmented}\n");
428 p(ip6s_ofragments, "\t{:fragments-created/%ju} "
429 "{N:/fragment%s created}\n");
430 p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
431 "{N:/datagram%s that can't be fragmented}\n");
432 p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
433 "{N:/packet%s that violated scope rules}\n");
434 p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
435 "{N:/multicast packet%s which we don't join}\n");
436 for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
437 if (ip6stat.ip6s_nxthist[i] != 0) {
439 xo_emit("\t{T:Input histogram}:\n");
440 xo_open_list("input-histogram");
443 xo_open_instance("input-histogram");
444 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
445 (uintmax_t)ip6stat.ip6s_nxthist[i]);
446 xo_close_instance("input-histogram");
449 xo_close_list("input-histogram");
451 xo_open_container("mbuf-statistics");
452 xo_emit("\t{T:Mbuf statistics}:\n");
453 xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
454 (uintmax_t)ip6stat.ip6s_m1);
455 for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
456 char ifbuf[IFNAMSIZ];
457 if (ip6stat.ip6s_m2m[i] != 0) {
459 xo_emit("\t\t{N:two or more mbuf}:\n");
460 xo_open_list("mbuf-data");
463 xo_open_instance("mbuf-data");
464 xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
465 if_indextoname(i, ifbuf),
466 (uintmax_t)ip6stat.ip6s_m2m[i]);
467 xo_close_instance("mbuf-data");
471 xo_close_list("mbuf-data");
472 xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
473 (uintmax_t)ip6stat.ip6s_mext1);
474 xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
475 "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
476 xo_close_container("mbuf-statistics");
478 p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
479 "{N:/packet%s whose headers are not contiguous}\n");
480 p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
481 "{N:/tunneling packet%s that can't find gif}\n");
482 p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
483 "{N:/packet%s discarded because of too many headers}\n");
485 /* for debugging source address selection */
486 #define PRINT_SCOPESTAT(s,i) do {\
487 switch(i) { /* XXX hardcoding in each case */\
489 p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
490 "{N:/interface-local%s}\n"); \
493 p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
494 "{N:/link-local%s}\n"); \
497 p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
498 "{N:/site-local%s}\n");\
501 p(s,"\t\t{ke:name/globals}{:count/%ju} " \
505 xo_emit("\t\t{qke:name/%x}{:count/%ju} " \
506 "addresses scope=%x\n",\
507 i, (uintmax_t)ip6stat.s, i); \
511 xo_open_container("source-address-selection");
512 p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
513 "{N:/failure%s of source address selection}\n");
515 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
516 if (ip6stat.ip6s_sources_sameif[i]) {
518 xo_open_list("outgoing-interface");
519 xo_emit("\tsource addresses on an outgoing "
523 xo_open_instance("outgoing-interface");
524 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
525 xo_close_instance("outgoing-interface");
529 xo_close_list("outgoing-interface");
531 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
532 if (ip6stat.ip6s_sources_otherif[i]) {
534 xo_open_list("non-outgoing-interface");
535 xo_emit("\tsource addresses on a non-outgoing "
539 xo_open_instance("non-outgoing-interface");
540 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
541 xo_close_instance("non-outgoing-interface");
545 xo_close_list("non-outgoing-interface");
547 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
548 if (ip6stat.ip6s_sources_samescope[i]) {
550 xo_open_list("same-source");
551 xo_emit("\tsource addresses of same scope\n");
554 xo_open_instance("same-source");
555 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
556 xo_close_instance("same-source");
560 xo_close_list("same-source");
562 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
563 if (ip6stat.ip6s_sources_otherscope[i]) {
565 xo_open_list("different-scope");
566 xo_emit("\tsource addresses of a different "
570 xo_open_instance("different-scope");
571 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
572 xo_close_instance("different-scope");
576 xo_close_list("different-scope");
578 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
579 if (ip6stat.ip6s_sources_deprecated[i]) {
581 xo_open_list("deprecated-source");
582 xo_emit("\tdeprecated source addresses\n");
585 xo_open_instance("deprecated-source");
586 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
587 xo_close_instance("deprecated-source");
591 xo_close_list("deprecated-source");
593 for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
594 if (ip6stat.ip6s_sources_rule[i]) {
596 xo_open_list("rules-applied");
597 xo_emit("\t{T:Source addresses selection "
601 xo_open_instance("rules-applied");
602 xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
604 (uintmax_t)ip6stat.ip6s_sources_rule[i],
606 xo_close_instance("rules-applied");
610 xo_close_list("rules-applied");
612 xo_close_container("source-address-selection");
616 xo_close_container(name);
620 * Dump IPv6 per-interface statistics based on RFC 2465.
623 ip6_ifstats(char *ifname)
625 struct in6_ifreq ifr;
628 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
629 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, \
630 plural(ifr.ifr_ifru.ifru_stat.f))
632 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
633 xo_warn("Warning: socket(AF_INET6)");
637 strcpy(ifr.ifr_name, ifname);
638 if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
639 if (errno != EPFNOSUPPORT)
640 xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
644 xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
646 xo_open_instance("ip6-interface-statistics");
647 xo_emit("{ke:name/%s}", ifr.ifr_name);
649 p(ifs6_in_receive, "\t{:received-packets/%ju} "
650 "{N:/total input datagram%s}\n");
651 p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
652 "{N:/datagram%s with invalid header received}\n");
653 p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
654 "{N:/datagram%s exceeded MTU received}\n");
655 p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
656 "{N:/datagram%s with no route received}\n");
657 p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
658 "{N:/datagram%s with invalid dst received}\n");
659 p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
660 "{N:/datagram%s with unknown proto received}\n");
661 p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
662 "{N:/truncated datagram%s received}\n");
663 p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
664 "{N:/input datagram%s discarded}\n");
665 p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
666 "{N:/datagram%s delivered to an upper layer protocol}\n");
667 p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
668 "{N:/datagram%s forwarded to this interface}\n");
669 p(ifs6_out_request, "\t{:sent-packets/%ju} "
670 "{N:/datagram%s sent from an upper layer protocol}\n");
671 p(ifs6_out_discard, "\t{:discard-packets/%ju} "
672 "{N:/total discarded output datagram%s}\n");
673 p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
674 "{N:/output datagram%s fragmented}\n");
675 p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
676 "{N:/output datagram%s failed on fragment}\n");
677 p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
678 "{N:/output datagram%s succeeded on fragment}\n");
679 p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
680 "{N:/incoming datagram%s fragmented}\n");
681 p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
682 "{N:/datagram%s reassembled}\n");
683 p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
684 "{N:/datagram%s failed on reassembly}\n");
685 p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
686 "{N:/multicast datagram%s received}\n");
687 p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
688 "{N:/multicast datagram%s sent}\n");
691 xo_close_instance("ip6-interface-statistics");
697 static const char *icmp6names[] = {
828 "multicast listener query",
829 "MLDv1 listener report",
830 "MLDv1 listener done",
831 "router solicitation",
832 "router advertisement",
833 "neighbor solicitation",
834 "neighbor advertisement",
836 "router renumbering",
837 "node information request",
838 "node information reply",
839 "inverse neighbor solicitation",
840 "inverse neighbor advertisement",
841 "MLDv2 listener report",
957 * Dump ICMP6 statistics.
960 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
962 struct icmp6stat icmp6stat, zerostat;
966 len = sizeof icmp6stat;
968 memset(&icmp6stat, 0, len);
970 memset(&zerostat, 0, len);
971 if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
972 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
974 xo_warn("sysctl: net.inet6.icmp6.stats");
978 kread_counters(off, &icmp6stat, len);
980 xo_emit("{T:/%s}:\n", name);
981 xo_open_container(name);
983 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
984 xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
985 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
986 xo_emit(m, (uintmax_t)icmp6stat.f)
988 p(icp6s_error, "\t{:icmp6-calls/%ju} "
989 "{N:/call%s to icmp6_error}\n");
990 p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
991 "{N:/error%s not generated in response to an icmp6 message}\n");
992 p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
993 "{N:/error%s not generated because of rate limitation}\n");
994 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
995 for (first = 1, i = 0; i < NELEM; i++)
996 if (icmp6stat.icp6s_outhist[i] != 0) {
998 xo_open_list("output-histogram");
999 xo_emit("\t{T:Output histogram}:\n");
1002 xo_open_instance("output-histogram");
1003 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1005 (uintmax_t)icmp6stat.icp6s_outhist[i]);
1006 xo_close_instance("output-histogram");
1009 xo_close_list("output-histogram");
1012 p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
1013 "{N:/message%s with bad code fields}\n");
1014 p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
1015 "{N:/message%s < minimum length}\n");
1016 p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
1017 "{N:/bad checksum%s}\n");
1018 p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
1019 "{N:/message%s with bad length}\n");
1020 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
1021 for (first = 1, i = 0; i < NELEM; i++)
1022 if (icmp6stat.icp6s_inhist[i] != 0) {
1024 xo_open_list("input-histogram");
1025 xo_emit("\t{T:Input histogram}:\n");
1028 xo_open_instance("input-histogram");
1029 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1031 (uintmax_t)icmp6stat.icp6s_inhist[i]);
1032 xo_close_instance("input-histogram");
1035 xo_close_list("input-histogram");
1037 xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1038 xo_open_container("errors");
1039 p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1041 p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1042 "{N:/administratively prohibited}\n");
1043 p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1044 "{N:/beyond scope}\n");
1045 p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1046 "{N:/address unreachable}\n");
1047 p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1048 "{N:/port unreachable}\n");
1049 p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1050 "{N:/packet too big}\n");
1051 p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1052 "{N:/time exceed transit}\n");
1053 p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1054 "{N:/time exceed reassembly}\n");
1055 p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1056 "{N:/erroneous header field}\n");
1057 p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1058 "{N:/unrecognized next header}\n");
1059 p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1060 "{N:/unrecognized option}\n");
1061 p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1063 p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1065 p(icp6s_reflect, "\t{:reflect/%ju} "
1066 "{N:/message response%s generated}\n");
1067 p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1068 "{N:/message%s with too many ND options}\n");
1069 p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1070 "{N:/message%s with bad ND options}\n");
1071 p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1072 "{N:/bad neighbor solicitation message%s}\n");
1073 p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1074 "{N:/bad neighbor advertisement message%s}\n");
1075 p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1076 "{N:/bad router solicitation message%s}\n");
1077 p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1078 "{N:/bad router advertisement message%s}\n");
1079 p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1080 "{N:/bad redirect message%s}\n");
1081 xo_close_container("errors");
1082 p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1085 xo_close_container(name);
1089 * Dump ICMPv6 per-interface statistics based on RFC 2466.
1092 icmp6_ifstats(char *ifname)
1094 struct in6_ifreq ifr;
1097 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1098 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1099 plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1100 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1101 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1102 pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1104 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1105 xo_warn("Warning: socket(AF_INET6)");
1109 strcpy(ifr.ifr_name, ifname);
1110 if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1111 if (errno != EPFNOSUPPORT)
1112 xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1116 xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1118 xo_open_instance("icmp6-interface-statistics");
1119 xo_emit("{ke:name/%s}", ifr.ifr_name);
1120 p(ifs6_in_msg, "\t{:received-packets/%ju} "
1121 "{N:/total input message%s}\n");
1122 p(ifs6_in_error, "\t{:received-errors/%ju} "
1123 "{N:/total input error message%s}\n");
1124 p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1125 "{N:/input destination unreachable error%s}\n");
1126 p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1127 "{N:/input administratively prohibited error%s}\n");
1128 p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1129 "{N:/input time exceeded error%s}\n");
1130 p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1131 "{N:/input parameter problem error%s}\n");
1132 p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1133 "{N:/input packet too big error%s}\n");
1134 p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1135 "{N:/input echo request%s}\n");
1136 p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1137 "{N:/input echo repl%s}\n");
1138 p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1139 "{N:/input router solicitation%s}\n");
1140 p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1141 "{N:/input router advertisement%s}\n");
1142 p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1143 "{N:/input neighbor solicitation%s}\n");
1144 p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1145 "{N:/input neighbor advertisement%s}\n");
1146 p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1147 "{N:/input redirect%s}\n");
1148 p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1149 "{N:/input MLD quer%s}\n");
1150 p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1151 "{N:/input MLD report%s}\n");
1152 p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1153 "{N:/input MLD done%s}\n");
1155 p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1156 "{N:/total output message%s}\n");
1157 p(ifs6_out_error, "\t{:sent-errors/%ju} "
1158 "{N:/total output error message%s}\n");
1159 p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1160 "{N:/output destination unreachable error%s}\n");
1161 p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1162 "{N:/output administratively prohibited error%s}\n");
1163 p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1164 "{N:/output time exceeded error%s}\n");
1165 p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1166 "{N:/output parameter problem error%s}\n");
1167 p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1168 "{N:/output packet too big error%s}\n");
1169 p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1170 "{N:/output echo request%s}\n");
1171 p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1172 "{N:/output echo repl%s}\n");
1173 p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1174 "{N:/output router solicitation%s}\n");
1175 p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1176 "{N:/output router advertisement%s}\n");
1177 p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1178 "{N:/output neighbor solicitation%s}\n");
1179 p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1180 "{N:/output neighbor advertisement%s}\n");
1181 p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1182 "{N:/output redirect%s}\n");
1183 p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1184 "{N:/output MLD quer%s}\n");
1185 p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1186 "{N:/output MLD report%s}\n");
1187 p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1188 "{N:/output MLD done%s}\n");
1191 xo_close_instance("icmp6-interface-statistics");
1197 * Dump PIM statistics structure.
1200 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1202 struct pim6stat pim6stat, zerostat;
1203 size_t len = sizeof pim6stat;
1207 memset(&zerostat, 0, len);
1208 if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
1209 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1210 if (errno != ENOENT)
1211 xo_warn("sysctl: net.inet6.pim.stats");
1217 kread(off, &pim6stat, len);
1220 xo_emit("{T:/%s}:\n", name);
1221 xo_open_container(name);
1223 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1224 xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1226 p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1227 "{N:/message%s received}\n");
1228 p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1229 "{N:/message%s received with too few bytes}\n");
1230 p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1231 "{N:/message%s received with bad checksum}\n");
1232 p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1233 "{N:/message%s received with bad version}\n");
1234 p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1235 "{N:/register%s received}\n");
1236 p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1237 "{N:/bad register%s received}\n");
1238 p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1239 "{N:/register%s sent}\n");
1241 xo_close_container(name);
1245 * Dump raw ip6 statistics structure.
1248 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1250 struct rip6stat rip6stat, zerostat;
1254 len = sizeof(rip6stat);
1257 memset(&zerostat, 0, len);
1258 if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
1259 zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
1260 if (errno != ENOENT)
1261 xo_warn("sysctl: net.inet6.ip6.rip6stats");
1265 kread_counters(off, &rip6stat, len);
1267 xo_emit("{T:/%s}:\n", name);
1268 xo_open_container(name);
1270 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1271 xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1273 p(rip6s_ipackets, "\t{:received-packets/%ju} "
1274 "{N:/message%s received}\n");
1275 p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1276 "{N:/checksum calculation%s on inbound}\n");
1277 p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1278 "{N:/message%s with bad checksum}\n");
1279 p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1280 "{N:/message%s dropped due to no socket}\n");
1281 p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1282 "{N:/multicast message%s dropped due to no socket}\n");
1283 p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1284 "{N:/message%s dropped due to full socket buffers}\n");
1285 delivered = rip6stat.rip6s_ipackets -
1286 rip6stat.rip6s_badsum -
1287 rip6stat.rip6s_nosock -
1288 rip6stat.rip6s_nosockmcast -
1289 rip6stat.rip6s_fullsock;
1290 if (delivered || sflag <= 1)
1291 xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1292 (uintmax_t)delivered);
1293 p(rip6s_opackets, "\t{:sent-packets/%ju} "
1294 "{N:/datagram%s output}\n");
1296 xo_close_container(name);
1300 * Pretty print an Internet address (net address + port).
1301 * Take numeric_addr and numeric_port into consideration.
1303 #define GETSERVBYPORT6(port, proto, ret)\
1305 if (strcmp((proto), "tcp6") == 0)\
1306 (ret) = getservbyport((int)(port), "tcp");\
1307 else if (strcmp((proto), "udp6") == 0)\
1308 (ret) = getservbyport((int)(port), "udp");\
1310 (ret) = getservbyport((int)(port), (proto));\
1314 inet6print(const char *container, struct in6_addr *in6, int port,
1315 const char *proto, int numeric)
1317 struct servent *sp = 0;
1322 xo_open_container(container);
1324 sprintf(line, "%.*s.", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1326 cp = strchr(line, '\0');
1327 if (!numeric && port)
1328 GETSERVBYPORT6(port, proto, sp);
1329 if (sp || port == 0)
1330 sprintf(cp, "%.15s", sp ? sp->s_name : "*");
1332 sprintf(cp, "%d", ntohs((u_short)port));
1333 width = Wflag ? 45 : Aflag ? 18 : 22;
1335 xo_emit("{d:target/%-*.*s} ", width, width, line);
1337 int alen = cp - line - 1, plen = strlen(cp) - 1;
1338 xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1342 xo_close_container(container);
1346 * Construct an Internet address representation.
1347 * If the numeric_addr has been supplied, give
1348 * numeric value, otherwise try for symbolic name.
1352 inet6name(struct in6_addr *in6p)
1354 struct sockaddr_in6 sin6;
1355 char hbuf[NI_MAXHOST], *cp;
1356 static char line[50];
1357 static char domain[MAXHOSTNAMELEN];
1358 static int first = 1;
1361 if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1365 if (first && !numeric_addr) {
1367 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
1368 (cp = strchr(domain, '.')))
1369 (void) strcpy(domain, cp + 1);
1373 memset(&sin6, 0, sizeof(sin6));
1374 memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1375 sin6.sin6_family = AF_INET6;
1376 /* XXX: in6p.s6_addr[2] can contain scopeid. */
1377 in6_fillscopeid(&sin6);
1378 flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1379 error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1380 sizeof(hbuf), NULL, 0, flags);
1382 if ((flags & NI_NUMERICHOST) == 0 &&
1383 (cp = strchr(hbuf, '.')) &&
1384 !strcmp(cp + 1, domain))
1388 /* XXX: this should not happen. */
1390 inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,