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 * 3. 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>
48 #include <net/route.h>
50 #include <netinet/in.h>
51 #include <netinet/ip6.h>
52 #include <netinet/icmp6.h>
53 #include <netinet/in_systm.h>
54 #include <netinet6/in6_pcb.h>
55 #include <netinet6/in6_var.h>
56 #include <netinet6/ip6_var.h>
57 #include <netinet6/pim6_var.h>
58 #include <netinet6/raw_ip6.h>
60 #include <arpa/inet.h>
73 static char ntop_buf[INET6_ADDRSTRLEN];
75 static const char *ip6nh[] = {
136 "destination option",
334 static const char *srcrule_str[] = {
338 "deprecated address",
340 "outgoing interface",
342 "public/temporary address",
344 "better virtual status",
354 * Dump IP6 statistics structure.
357 ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
359 struct ip6stat ip6stat;
362 if (fetch_stats("net.inet6.ip6.stats", off, &ip6stat,
363 sizeof(ip6stat), kread_counters) != 0)
366 xo_open_container(name);
367 xo_emit("{T:/%s}:\n", name);
369 #define p(f, m) if (ip6stat.f || sflag <= 1) \
370 xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
371 #define p1a(f, m) if (ip6stat.f || sflag <= 1) \
372 xo_emit(m, (uintmax_t)ip6stat.f)
374 p(ip6s_total, "\t{:received-packets/%ju} "
375 "{N:/total packet%s received}\n");
376 p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
377 "{N:/with size smaller than minimum}\n");
378 p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
379 "{N:/with data size < data length}\n");
380 p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
381 "{N:/with bad options}\n");
382 p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
383 "{N:/with incorrect version number}\n");
384 p(ip6s_fragments, "\t{:received-fragments/%ju} "
385 "{N:/fragment%s received}\n");
386 p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
387 "{N:/fragment%s dropped (dup or out of space)}\n");
388 p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
389 "{N:/fragment%s dropped after timeout}\n");
390 p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
391 "{N:/fragment%s that exceeded limit}\n");
392 p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
393 "{N:/packet%s reassembled ok}\n");
394 p(ip6s_delivered, "\t{:received-local-packets/%ju} "
395 "{N:/packet%s for this host}\n");
396 p(ip6s_forward, "\t{:forwarded-packets/%ju} "
397 "{N:/packet%s forwarded}\n");
398 p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
399 "{N:/packet%s not forwardable}\n");
400 p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
401 "{N:/redirect%s sent}\n");
402 p(ip6s_localout, "\t{:sent-packets/%ju} "
403 "{N:/packet%s sent from this host}\n");
404 p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
405 "{N:/packet%s sent with fabricated ip header}\n");
406 p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
407 "{N:/output packet%s dropped due to no bufs, etc.}\n");
408 p(ip6s_noroute, "\t{:discard-no-route/%ju} "
409 "{N:/output packet%s discarded due to no route}\n");
410 p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
411 "{N:/output datagram%s fragmented}\n");
412 p(ip6s_ofragments, "\t{:fragments-created/%ju} "
413 "{N:/fragment%s created}\n");
414 p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
415 "{N:/datagram%s that can't be fragmented}\n");
416 p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
417 "{N:/packet%s that violated scope rules}\n");
418 p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
419 "{N:/multicast packet%s which we don't join}\n");
420 for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
421 if (ip6stat.ip6s_nxthist[i] != 0) {
423 xo_emit("\t{T:Input histogram}:\n");
424 xo_open_list("input-histogram");
427 xo_open_instance("input-histogram");
428 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
429 (uintmax_t)ip6stat.ip6s_nxthist[i]);
430 xo_close_instance("input-histogram");
433 xo_close_list("input-histogram");
435 xo_open_container("mbuf-statistics");
436 xo_emit("\t{T:Mbuf statistics}:\n");
437 xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
438 (uintmax_t)ip6stat.ip6s_m1);
439 for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
440 char ifbuf[IFNAMSIZ];
441 if (ip6stat.ip6s_m2m[i] != 0) {
443 xo_emit("\t\t{N:two or more mbuf}:\n");
444 xo_open_list("mbuf-data");
447 xo_open_instance("mbuf-data");
448 xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
449 if_indextoname(i, ifbuf),
450 (uintmax_t)ip6stat.ip6s_m2m[i]);
451 xo_close_instance("mbuf-data");
455 xo_close_list("mbuf-data");
456 xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
457 (uintmax_t)ip6stat.ip6s_mext1);
458 xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
459 "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
460 xo_close_container("mbuf-statistics");
462 p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
463 "{N:/packet%s whose headers are not contiguous}\n");
464 p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
465 "{N:/tunneling packet%s that can't find gif}\n");
466 p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
467 "{N:/packet%s discarded because of too many headers}\n");
469 /* for debugging source address selection */
470 #define PRINT_SCOPESTAT(s,i) do {\
471 switch(i) { /* XXX hardcoding in each case */\
473 p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
474 "{N:/interface-local%s}\n"); \
477 p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
478 "{N:/link-local%s}\n"); \
481 p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
482 "{N:/site-local%s}\n");\
485 p(s,"\t\t{ke:name/globals}{:count/%ju} " \
489 xo_emit("\t\t{qke:name/%#x}{:count/%ju} " \
490 "{N:/addresses scope=%#x}\n",\
491 i, (uintmax_t)ip6stat.s, i); \
495 xo_open_container("source-address-selection");
496 p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
497 "{N:/failure%s of source address selection}\n");
499 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
500 if (ip6stat.ip6s_sources_sameif[i]) {
502 xo_open_list("outgoing-interface");
503 xo_emit("\tsource addresses on an outgoing "
507 xo_open_instance("outgoing-interface");
508 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
509 xo_close_instance("outgoing-interface");
513 xo_close_list("outgoing-interface");
515 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
516 if (ip6stat.ip6s_sources_otherif[i]) {
518 xo_open_list("non-outgoing-interface");
519 xo_emit("\tsource addresses on a non-outgoing "
523 xo_open_instance("non-outgoing-interface");
524 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
525 xo_close_instance("non-outgoing-interface");
529 xo_close_list("non-outgoing-interface");
531 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
532 if (ip6stat.ip6s_sources_samescope[i]) {
534 xo_open_list("same-source");
535 xo_emit("\tsource addresses of same scope\n");
538 xo_open_instance("same-source");
539 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
540 xo_close_instance("same-source");
544 xo_close_list("same-source");
546 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
547 if (ip6stat.ip6s_sources_otherscope[i]) {
549 xo_open_list("different-scope");
550 xo_emit("\tsource addresses of a different "
554 xo_open_instance("different-scope");
555 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
556 xo_close_instance("different-scope");
560 xo_close_list("different-scope");
562 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
563 if (ip6stat.ip6s_sources_deprecated[i]) {
565 xo_open_list("deprecated-source");
566 xo_emit("\tdeprecated source addresses\n");
569 xo_open_instance("deprecated-source");
570 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
571 xo_close_instance("deprecated-source");
575 xo_close_list("deprecated-source");
577 for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
578 if (ip6stat.ip6s_sources_rule[i]) {
580 xo_open_list("rules-applied");
581 xo_emit("\t{T:Source addresses selection "
585 xo_open_instance("rules-applied");
586 xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
588 (uintmax_t)ip6stat.ip6s_sources_rule[i],
590 xo_close_instance("rules-applied");
594 xo_close_list("rules-applied");
596 xo_close_container("source-address-selection");
600 xo_close_container(name);
604 * Dump IPv6 per-interface statistics based on RFC 2465.
607 ip6_ifstats(char *ifname)
609 struct in6_ifreq ifr;
612 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
613 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, \
614 plural(ifr.ifr_ifru.ifru_stat.f))
616 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
617 xo_warn("Warning: socket(AF_INET6)");
621 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
622 if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
623 if (errno != EPFNOSUPPORT)
624 xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
628 xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
630 xo_open_instance("ip6-interface-statistics");
631 xo_emit("{ke:name/%s}", ifr.ifr_name);
633 p(ifs6_in_receive, "\t{:received-packets/%ju} "
634 "{N:/total input datagram%s}\n");
635 p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
636 "{N:/datagram%s with invalid header received}\n");
637 p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
638 "{N:/datagram%s exceeded MTU received}\n");
639 p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
640 "{N:/datagram%s with no route received}\n");
641 p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
642 "{N:/datagram%s with invalid dst received}\n");
643 p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
644 "{N:/datagram%s with unknown proto received}\n");
645 p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
646 "{N:/truncated datagram%s received}\n");
647 p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
648 "{N:/input datagram%s discarded}\n");
649 p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
650 "{N:/datagram%s delivered to an upper layer protocol}\n");
651 p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
652 "{N:/datagram%s forwarded to this interface}\n");
653 p(ifs6_out_request, "\t{:sent-packets/%ju} "
654 "{N:/datagram%s sent from an upper layer protocol}\n");
655 p(ifs6_out_discard, "\t{:discard-packets/%ju} "
656 "{N:/total discarded output datagram%s}\n");
657 p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
658 "{N:/output datagram%s fragmented}\n");
659 p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
660 "{N:/output datagram%s failed on fragment}\n");
661 p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
662 "{N:/output datagram%s succeeded on fragment}\n");
663 p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
664 "{N:/incoming datagram%s fragmented}\n");
665 p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
666 "{N:/datagram%s reassembled}\n");
667 p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
668 "{N:/datagram%s failed on reassembly}\n");
669 p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
670 "{N:/multicast datagram%s received}\n");
671 p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
672 "{N:/multicast datagram%s sent}\n");
675 xo_close_instance("ip6-interface-statistics");
681 static const char *icmp6names[] = {
812 "multicast listener query",
813 "MLDv1 listener report",
814 "MLDv1 listener done",
815 "router solicitation",
816 "router advertisement",
817 "neighbor solicitation",
818 "neighbor advertisement",
820 "router renumbering",
821 "node information request",
822 "node information reply",
823 "inverse neighbor solicitation",
824 "inverse neighbor advertisement",
825 "MLDv2 listener report",
941 * Dump ICMP6 statistics.
944 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
946 struct icmp6stat icmp6stat;
949 if (fetch_stats("net.inet6.icmp6.stats", off, &icmp6stat,
950 sizeof(icmp6stat), kread_counters) != 0)
953 xo_emit("{T:/%s}:\n", name);
954 xo_open_container(name);
956 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
957 xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
958 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
959 xo_emit(m, (uintmax_t)icmp6stat.f)
961 p(icp6s_error, "\t{:icmp6-calls/%ju} "
962 "{N:/call%s to icmp6_error}\n");
963 p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
964 "{N:/error%s not generated in response to an icmp6 message}\n");
965 p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
966 "{N:/error%s not generated because of rate limitation}\n");
967 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
968 for (first = 1, i = 0; i < NELEM; i++)
969 if (icmp6stat.icp6s_outhist[i] != 0) {
971 xo_open_list("output-histogram");
972 xo_emit("\t{T:Output histogram}:\n");
975 xo_open_instance("output-histogram");
976 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
978 (uintmax_t)icmp6stat.icp6s_outhist[i]);
979 xo_close_instance("output-histogram");
982 xo_close_list("output-histogram");
985 p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
986 "{N:/message%s with bad code fields}\n");
987 p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
988 "{N:/message%s < minimum length}\n");
989 p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
990 "{N:/bad checksum%s}\n");
991 p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
992 "{N:/message%s with bad length}\n");
993 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
994 for (first = 1, i = 0; i < NELEM; i++)
995 if (icmp6stat.icp6s_inhist[i] != 0) {
997 xo_open_list("input-histogram");
998 xo_emit("\t{T:Input histogram}:\n");
1001 xo_open_instance("input-histogram");
1002 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1004 (uintmax_t)icmp6stat.icp6s_inhist[i]);
1005 xo_close_instance("input-histogram");
1008 xo_close_list("input-histogram");
1010 xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1011 xo_open_container("errors");
1012 p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1014 p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1015 "{N:/administratively prohibited}\n");
1016 p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1017 "{N:/beyond scope}\n");
1018 p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1019 "{N:/address unreachable}\n");
1020 p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1021 "{N:/port unreachable}\n");
1022 p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1023 "{N:/packet too big}\n");
1024 p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1025 "{N:/time exceed transit}\n");
1026 p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1027 "{N:/time exceed reassembly}\n");
1028 p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1029 "{N:/erroneous header field}\n");
1030 p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1031 "{N:/unrecognized next header}\n");
1032 p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1033 "{N:/unrecognized option}\n");
1034 p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1036 p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1038 p(icp6s_reflect, "\t{:reflect/%ju} "
1039 "{N:/message response%s generated}\n");
1040 p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1041 "{N:/message%s with too many ND options}\n");
1042 p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1043 "{N:/message%s with bad ND options}\n");
1044 p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1045 "{N:/bad neighbor solicitation message%s}\n");
1046 p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1047 "{N:/bad neighbor advertisement message%s}\n");
1048 p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1049 "{N:/bad router solicitation message%s}\n");
1050 p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1051 "{N:/bad router advertisement message%s}\n");
1052 p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1053 "{N:/bad redirect message%s}\n");
1054 xo_close_container("errors");
1055 p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1058 xo_close_container(name);
1062 * Dump ICMPv6 per-interface statistics based on RFC 2466.
1065 icmp6_ifstats(char *ifname)
1067 struct in6_ifreq ifr;
1070 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1071 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1072 plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1073 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1074 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1075 pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1077 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1078 xo_warn("Warning: socket(AF_INET6)");
1082 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1083 if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1084 if (errno != EPFNOSUPPORT)
1085 xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1089 xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1091 xo_open_instance("icmp6-interface-statistics");
1092 xo_emit("{ke:name/%s}", ifr.ifr_name);
1093 p(ifs6_in_msg, "\t{:received-packets/%ju} "
1094 "{N:/total input message%s}\n");
1095 p(ifs6_in_error, "\t{:received-errors/%ju} "
1096 "{N:/total input error message%s}\n");
1097 p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1098 "{N:/input destination unreachable error%s}\n");
1099 p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1100 "{N:/input administratively prohibited error%s}\n");
1101 p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1102 "{N:/input time exceeded error%s}\n");
1103 p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1104 "{N:/input parameter problem error%s}\n");
1105 p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1106 "{N:/input packet too big error%s}\n");
1107 p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1108 "{N:/input echo request%s}\n");
1109 p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1110 "{N:/input echo repl%s}\n");
1111 p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1112 "{N:/input router solicitation%s}\n");
1113 p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1114 "{N:/input router advertisement%s}\n");
1115 p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1116 "{N:/input neighbor solicitation%s}\n");
1117 p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1118 "{N:/input neighbor advertisement%s}\n");
1119 p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1120 "{N:/input redirect%s}\n");
1121 p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1122 "{N:/input MLD quer%s}\n");
1123 p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1124 "{N:/input MLD report%s}\n");
1125 p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1126 "{N:/input MLD done%s}\n");
1128 p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1129 "{N:/total output message%s}\n");
1130 p(ifs6_out_error, "\t{:sent-errors/%ju} "
1131 "{N:/total output error message%s}\n");
1132 p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1133 "{N:/output destination unreachable error%s}\n");
1134 p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1135 "{N:/output administratively prohibited error%s}\n");
1136 p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1137 "{N:/output time exceeded error%s}\n");
1138 p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1139 "{N:/output parameter problem error%s}\n");
1140 p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1141 "{N:/output packet too big error%s}\n");
1142 p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1143 "{N:/output echo request%s}\n");
1144 p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1145 "{N:/output echo repl%s}\n");
1146 p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1147 "{N:/output router solicitation%s}\n");
1148 p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1149 "{N:/output router advertisement%s}\n");
1150 p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1151 "{N:/output neighbor solicitation%s}\n");
1152 p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1153 "{N:/output neighbor advertisement%s}\n");
1154 p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1155 "{N:/output redirect%s}\n");
1156 p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1157 "{N:/output MLD quer%s}\n");
1158 p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1159 "{N:/output MLD report%s}\n");
1160 p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1161 "{N:/output MLD done%s}\n");
1164 xo_close_instance("icmp6-interface-statistics");
1170 * Dump PIM statistics structure.
1173 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1175 struct pim6stat pim6stat;
1177 if (fetch_stats("net.inet6.pim.stats", off, &pim6stat,
1178 sizeof(pim6stat), kread) != 0)
1181 xo_emit("{T:/%s}:\n", name);
1182 xo_open_container(name);
1184 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1185 xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1187 p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1188 "{N:/message%s received}\n");
1189 p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1190 "{N:/message%s received with too few bytes}\n");
1191 p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1192 "{N:/message%s received with bad checksum}\n");
1193 p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1194 "{N:/message%s received with bad version}\n");
1195 p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1196 "{N:/register%s received}\n");
1197 p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1198 "{N:/bad register%s received}\n");
1199 p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1200 "{N:/register%s sent}\n");
1202 xo_close_container(name);
1206 * Dump raw ip6 statistics structure.
1209 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1211 struct rip6stat rip6stat;
1214 if (fetch_stats("net.inet6.ip6.rip6stats", off, &rip6stat,
1215 sizeof(rip6stat), kread_counters) != 0)
1218 xo_emit("{T:/%s}:\n", name);
1219 xo_open_container(name);
1221 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1222 xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1224 p(rip6s_ipackets, "\t{:received-packets/%ju} "
1225 "{N:/message%s received}\n");
1226 p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1227 "{N:/checksum calculation%s on inbound}\n");
1228 p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1229 "{N:/message%s with bad checksum}\n");
1230 p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1231 "{N:/message%s dropped due to no socket}\n");
1232 p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1233 "{N:/multicast message%s dropped due to no socket}\n");
1234 p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1235 "{N:/message%s dropped due to full socket buffers}\n");
1236 delivered = rip6stat.rip6s_ipackets -
1237 rip6stat.rip6s_badsum -
1238 rip6stat.rip6s_nosock -
1239 rip6stat.rip6s_nosockmcast -
1240 rip6stat.rip6s_fullsock;
1241 if (delivered || sflag <= 1)
1242 xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1243 (uintmax_t)delivered);
1244 p(rip6s_opackets, "\t{:sent-packets/%ju} "
1245 "{N:/datagram%s output}\n");
1247 xo_close_container(name);
1251 * Pretty print an Internet address (net address + port).
1252 * Take numeric_addr and numeric_port into consideration.
1254 #define GETSERVBYPORT6(port, proto, ret)\
1256 if (strcmp((proto), "tcp6") == 0)\
1257 (ret) = getservbyport((int)(port), "tcp");\
1258 else if (strcmp((proto), "udp6") == 0)\
1259 (ret) = getservbyport((int)(port), "udp");\
1261 (ret) = getservbyport((int)(port), (proto));\
1265 inet6print(const char *container, struct in6_addr *in6, int port,
1266 const char *proto, int numeric)
1268 struct servent *sp = 0;
1274 xo_open_container(container);
1276 snprintf(line, sizeof(line), "%.*s.",
1277 Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1279 alen = strlen(line);
1281 if (!numeric && port)
1282 GETSERVBYPORT6(port, proto, sp);
1283 if (sp || port == 0)
1284 snprintf(cp, sizeof(line) - alen,
1285 "%.15s", sp ? sp->s_name : "*");
1287 snprintf(cp, sizeof(line) - alen,
1288 "%d", ntohs((u_short)port));
1289 width = Wflag ? 45 : Aflag ? 18 : 22;
1291 xo_emit("{d:target/%-*.*s} ", width, width, line);
1295 xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1299 xo_close_container(container);
1303 * Construct an Internet address representation.
1304 * If the numeric_addr has been supplied, give
1305 * numeric value, otherwise try for symbolic name.
1309 inet6name(struct in6_addr *in6p)
1311 struct sockaddr_in6 sin6;
1312 char hbuf[NI_MAXHOST], *cp;
1313 static char line[NI_MAXHOST];
1314 static char domain[MAXHOSTNAMELEN];
1315 static int first = 1;
1318 if (IN6_IS_ADDR_UNSPECIFIED(in6p)) {
1322 if (first && !numeric_addr) {
1324 if (gethostname(domain, sizeof(domain)) == 0 &&
1325 (cp = strchr(domain, '.')))
1326 strlcpy(domain, cp + 1, sizeof(domain));
1330 memset(&sin6, 0, sizeof(sin6));
1331 memcpy(&sin6.sin6_addr, in6p, sizeof(*in6p));
1332 sin6.sin6_family = AF_INET6;
1333 /* XXX: in6p.s6_addr[2] can contain scopeid. */
1334 in6_fillscopeid(&sin6);
1335 flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1336 error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1337 sizeof(hbuf), NULL, 0, flags);
1339 if ((flags & NI_NUMERICHOST) == 0 &&
1340 (cp = strchr(hbuf, '.')) &&
1341 !strcmp(cp + 1, domain))
1343 strlcpy(line, hbuf, sizeof(line));
1345 /* XXX: this should not happen. */
1346 snprintf(line, sizeof(line), "%s",
1347 inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,