1 /* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
3 * SPDX-License-Identifier: BSD-3-Clause
5 * Copyright (c) 1983, 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94";
39 #include <sys/cdefs.h>
40 __FBSDID("$FreeBSD$");
43 #include <sys/param.h>
44 #include <sys/socket.h>
45 #include <sys/socketvar.h>
46 #include <sys/ioctl.h>
48 #include <sys/protosw.h>
50 #include <net/route.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>
75 static char ntop_buf[INET6_ADDRSTRLEN];
77 static const char *ip6nh[] = {
138 "destination option",
336 static const char *srcrule_str[] = {
340 "deprecated address",
342 "outgoing interface",
344 "public/temporary address",
346 "better virtual status",
356 * Dump IP6 statistics structure.
359 ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
361 struct ip6stat ip6stat;
364 if (fetch_stats("net.inet6.ip6.stats", off, &ip6stat,
365 sizeof(ip6stat), kread_counters) != 0)
368 xo_open_container(name);
369 xo_emit("{T:/%s}:\n", name);
371 #define p(f, m) if (ip6stat.f || sflag <= 1) \
372 xo_emit(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
373 #define p1a(f, m) if (ip6stat.f || sflag <= 1) \
374 xo_emit(m, (uintmax_t)ip6stat.f)
376 p(ip6s_total, "\t{:received-packets/%ju} "
377 "{N:/total packet%s received}\n");
378 p1a(ip6s_toosmall, "\t{:dropped-below-minimum-size/%ju} "
379 "{N:/with size smaller than minimum}\n");
380 p1a(ip6s_tooshort, "\t{:dropped-short-packets/%ju} "
381 "{N:/with data size < data length}\n");
382 p1a(ip6s_badoptions, "\t{:dropped-bad-options/%ju} "
383 "{N:/with bad options}\n");
384 p1a(ip6s_badvers, "\t{:dropped-bad-version/%ju} "
385 "{N:/with incorrect version number}\n");
386 p(ip6s_fragments, "\t{:received-fragments/%ju} "
387 "{N:/fragment%s received}\n");
388 p(ip6s_fragdropped, "\t{:dropped-fragment/%ju} "
389 "{N:/fragment%s dropped (dup or out of space)}\n");
390 p(ip6s_fragtimeout, "\t{:dropped-fragment-after-timeout/%ju} "
391 "{N:/fragment%s dropped after timeout}\n");
392 p(ip6s_fragoverflow, "\t{:dropped-fragments-overflow/%ju} "
393 "{N:/fragment%s that exceeded limit}\n");
394 p(ip6s_atomicfrags, "\t{:atomic-fragments/%ju} "
395 "{N:/atomic fragment%s}\n");
396 p(ip6s_reassembled, "\t{:reassembled-packets/%ju} "
397 "{N:/packet%s reassembled ok}\n");
398 p(ip6s_delivered, "\t{:received-local-packets/%ju} "
399 "{N:/packet%s for this host}\n");
400 p(ip6s_forward, "\t{:forwarded-packets/%ju} "
401 "{N:/packet%s forwarded}\n");
402 p(ip6s_cantforward, "\t{:packets-not-forwardable/%ju} "
403 "{N:/packet%s not forwardable}\n");
404 p(ip6s_redirectsent, "\t{:sent-redirects/%ju} "
405 "{N:/redirect%s sent}\n");
406 p(ip6s_localout, "\t{:sent-packets/%ju} "
407 "{N:/packet%s sent from this host}\n");
408 p(ip6s_rawout, "\t{:send-packets-fabricated-header/%ju} "
409 "{N:/packet%s sent with fabricated ip header}\n");
410 p(ip6s_odropped, "\t{:discard-no-mbufs/%ju} "
411 "{N:/output packet%s dropped due to no bufs, etc.}\n");
412 p(ip6s_noroute, "\t{:discard-no-route/%ju} "
413 "{N:/output packet%s discarded due to no route}\n");
414 p(ip6s_fragmented, "\t{:sent-fragments/%ju} "
415 "{N:/output datagram%s fragmented}\n");
416 p(ip6s_ofragments, "\t{:fragments-created/%ju} "
417 "{N:/fragment%s created}\n");
418 p(ip6s_cantfrag, "\t{:discard-cannot-fragment/%ju} "
419 "{N:/datagram%s that can't be fragmented}\n");
420 p(ip6s_badscope, "\t{:discard-scope-violations/%ju} "
421 "{N:/packet%s that violated scope rules}\n");
422 p(ip6s_notmember, "\t{:multicast-no-join-packets/%ju} "
423 "{N:/multicast packet%s which we don't join}\n");
424 for (first = 1, i = 0; i < IP6S_HDRCNT; i++)
425 if (ip6stat.ip6s_nxthist[i] != 0) {
427 xo_emit("\t{T:Input histogram}:\n");
428 xo_open_list("input-histogram");
431 xo_open_instance("input-histogram");
432 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n", ip6nh[i],
433 (uintmax_t)ip6stat.ip6s_nxthist[i]);
434 xo_close_instance("input-histogram");
437 xo_close_list("input-histogram");
439 xo_open_container("mbuf-statistics");
440 xo_emit("\t{T:Mbuf statistics}:\n");
441 xo_emit("\t\t{:one-mbuf/%ju} {N:/one mbuf}\n",
442 (uintmax_t)ip6stat.ip6s_m1);
443 for (first = 1, i = 0; i < IP6S_M2MMAX; i++) {
444 char ifbuf[IFNAMSIZ];
445 if (ip6stat.ip6s_m2m[i] != 0) {
447 xo_emit("\t\t{N:two or more mbuf}:\n");
448 xo_open_list("mbuf-data");
451 xo_open_instance("mbuf-data");
452 xo_emit("\t\t\t{k:name/%s}= {:count/%ju}\n",
453 if_indextoname(i, ifbuf),
454 (uintmax_t)ip6stat.ip6s_m2m[i]);
455 xo_close_instance("mbuf-data");
459 xo_close_list("mbuf-data");
460 xo_emit("\t\t{:one-extra-mbuf/%ju} {N:one ext mbuf}\n",
461 (uintmax_t)ip6stat.ip6s_mext1);
462 xo_emit("\t\t{:two-or-more-extra-mbufs/%ju} "
463 "{N:/two or more ext mbuf}\n", (uintmax_t)ip6stat.ip6s_mext2m);
464 xo_close_container("mbuf-statistics");
466 p(ip6s_exthdrtoolong, "\t{:dropped-header-too-long/%ju} "
467 "{N:/packet%s whose headers are not contiguous}\n");
468 p(ip6s_nogif, "\t{:discard-tunnel-no-gif/%ju} "
469 "{N:/tunneling packet%s that can't find gif}\n");
470 p(ip6s_toomanyhdr, "\t{:dropped-too-many-headers/%ju} "
471 "{N:/packet%s discarded because of too many headers}\n");
473 /* for debugging source address selection */
474 #define PRINT_SCOPESTAT(s,i) do {\
475 switch(i) { /* XXX hardcoding in each case */\
477 p(s, "\t\t{ke:name/interface-locals}{:count/%ju} " \
478 "{N:/interface-local%s}\n"); \
481 p(s,"\t\t{ke:name/link-locals}{:count/%ju} " \
482 "{N:/link-local%s}\n"); \
485 p(s,"\t\t{ke:name/site-locals}{:count/%ju} " \
486 "{N:/site-local%s}\n");\
489 p(s,"\t\t{ke:name/globals}{:count/%ju} " \
493 xo_emit("\t\t{qke:name/%#x}{:count/%ju} " \
494 "{N:/addresses scope=%#x}\n",\
495 i, (uintmax_t)ip6stat.s, i); \
499 xo_open_container("source-address-selection");
500 p(ip6s_sources_none, "\t{:address-selection-failures/%ju} "
501 "{N:/failure%s of source address selection}\n");
503 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
504 if (ip6stat.ip6s_sources_sameif[i]) {
506 xo_open_list("outgoing-interface");
507 xo_emit("\tsource addresses on an outgoing "
511 xo_open_instance("outgoing-interface");
512 PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
513 xo_close_instance("outgoing-interface");
517 xo_close_list("outgoing-interface");
519 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
520 if (ip6stat.ip6s_sources_otherif[i]) {
522 xo_open_list("non-outgoing-interface");
523 xo_emit("\tsource addresses on a non-outgoing "
527 xo_open_instance("non-outgoing-interface");
528 PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
529 xo_close_instance("non-outgoing-interface");
533 xo_close_list("non-outgoing-interface");
535 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
536 if (ip6stat.ip6s_sources_samescope[i]) {
538 xo_open_list("same-source");
539 xo_emit("\tsource addresses of same scope\n");
542 xo_open_instance("same-source");
543 PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
544 xo_close_instance("same-source");
548 xo_close_list("same-source");
550 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
551 if (ip6stat.ip6s_sources_otherscope[i]) {
553 xo_open_list("different-scope");
554 xo_emit("\tsource addresses of a different "
558 xo_open_instance("different-scope");
559 PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
560 xo_close_instance("different-scope");
564 xo_close_list("different-scope");
566 for (first = 1, i = 0; i < IP6S_SCOPECNT; i++) {
567 if (ip6stat.ip6s_sources_deprecated[i]) {
569 xo_open_list("deprecated-source");
570 xo_emit("\tdeprecated source addresses\n");
573 xo_open_instance("deprecated-source");
574 PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
575 xo_close_instance("deprecated-source");
579 xo_close_list("deprecated-source");
581 for (first = 1, i = 0; i < IP6S_RULESMAX; i++) {
582 if (ip6stat.ip6s_sources_rule[i]) {
584 xo_open_list("rules-applied");
585 xo_emit("\t{T:Source addresses selection "
589 xo_open_instance("rules-applied");
590 xo_emit("\t\t{ke:name/%s}{:count/%ju} {d:name/%s}\n",
592 (uintmax_t)ip6stat.ip6s_sources_rule[i],
594 xo_close_instance("rules-applied");
598 xo_close_list("rules-applied");
600 xo_close_container("source-address-selection");
604 xo_close_container(name);
608 * Dump IPv6 per-interface statistics based on RFC 2465.
611 ip6_ifstats(char *ifname)
613 struct in6_ifreq ifr;
616 #define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
617 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, \
618 plural(ifr.ifr_ifru.ifru_stat.f))
620 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
621 xo_warn("Warning: socket(AF_INET6)");
625 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
626 if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
627 if (errno != EPFNOSUPPORT)
628 xo_warn("Warning: ioctl(SIOCGIFSTAT_IN6)");
632 xo_emit("{T:/ip6 on %s}:\n", ifr.ifr_name);
634 xo_open_instance("ip6-interface-statistics");
635 xo_emit("{ke:name/%s}", ifr.ifr_name);
637 p(ifs6_in_receive, "\t{:received-packets/%ju} "
638 "{N:/total input datagram%s}\n");
639 p(ifs6_in_hdrerr, "\t{:dropped-invalid-header/%ju} "
640 "{N:/datagram%s with invalid header received}\n");
641 p(ifs6_in_toobig, "\t{:dropped-mtu-exceeded/%ju} "
642 "{N:/datagram%s exceeded MTU received}\n");
643 p(ifs6_in_noroute, "\t{:dropped-no-route/%ju} "
644 "{N:/datagram%s with no route received}\n");
645 p(ifs6_in_addrerr, "\t{:dropped-invalid-destination/%ju} "
646 "{N:/datagram%s with invalid dst received}\n");
647 p(ifs6_in_protounknown, "\t{:dropped-unknown-protocol/%ju} "
648 "{N:/datagram%s with unknown proto received}\n");
649 p(ifs6_in_truncated, "\t{:dropped-truncated/%ju} "
650 "{N:/truncated datagram%s received}\n");
651 p(ifs6_in_discard, "\t{:dropped-discarded/%ju} "
652 "{N:/input datagram%s discarded}\n");
653 p(ifs6_in_deliver, "\t{:received-valid-packets/%ju} "
654 "{N:/datagram%s delivered to an upper layer protocol}\n");
655 p(ifs6_out_forward, "\t{:sent-forwarded/%ju} "
656 "{N:/datagram%s forwarded to this interface}\n");
657 p(ifs6_out_request, "\t{:sent-packets/%ju} "
658 "{N:/datagram%s sent from an upper layer protocol}\n");
659 p(ifs6_out_discard, "\t{:discard-packets/%ju} "
660 "{N:/total discarded output datagram%s}\n");
661 p(ifs6_out_fragok, "\t{:discard-fragments/%ju} "
662 "{N:/output datagram%s fragmented}\n");
663 p(ifs6_out_fragfail, "\t{:fragments-failed/%ju} "
664 "{N:/output datagram%s failed on fragment}\n");
665 p(ifs6_out_fragcreat, "\t{:fragments-created/%ju} "
666 "{N:/output datagram%s succeeded on fragment}\n");
667 p(ifs6_reass_reqd, "\t{:reassembly-required/%ju} "
668 "{N:/incoming datagram%s fragmented}\n");
669 p(ifs6_reass_ok, "\t{:reassembled-packets/%ju} "
670 "{N:/datagram%s reassembled}\n");
671 p(ifs6_reass_fail, "\t{:reassembly-failed/%ju} "
672 "{N:/datagram%s failed on reassembly}\n");
673 p(ifs6_in_mcast, "\t{:received-multicast/%ju} "
674 "{N:/multicast datagram%s received}\n");
675 p(ifs6_out_mcast, "\t{:sent-multicast/%ju} "
676 "{N:/multicast datagram%s sent}\n");
679 xo_close_instance("ip6-interface-statistics");
685 static const char *icmp6names[] = {
816 "multicast listener query",
817 "MLDv1 listener report",
818 "MLDv1 listener done",
819 "router solicitation",
820 "router advertisement",
821 "neighbor solicitation",
822 "neighbor advertisement",
824 "router renumbering",
825 "node information request",
826 "node information reply",
827 "inverse neighbor solicitation",
828 "inverse neighbor advertisement",
829 "MLDv2 listener report",
945 * Dump ICMP6 statistics.
948 icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
950 struct icmp6stat icmp6stat;
953 if (fetch_stats("net.inet6.icmp6.stats", off, &icmp6stat,
954 sizeof(icmp6stat), kread_counters) != 0)
957 xo_emit("{T:/%s}:\n", name);
958 xo_open_container(name);
960 #define p(f, m) if (icmp6stat.f || sflag <= 1) \
961 xo_emit(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
962 #define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
963 xo_emit(m, (uintmax_t)icmp6stat.f)
965 p(icp6s_error, "\t{:icmp6-calls/%ju} "
966 "{N:/call%s to icmp6_error}\n");
967 p(icp6s_canterror, "\t{:errors-not-generated-from-message/%ju} "
968 "{N:/error%s not generated in response to an icmp6 message}\n");
969 p(icp6s_toofreq, "\t{:errors-discarded-by-rate-limitation/%ju} "
970 "{N:/error%s not generated because of rate limitation}\n");
971 #define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
972 for (first = 1, i = 0; i < NELEM; i++)
973 if (icmp6stat.icp6s_outhist[i] != 0) {
975 xo_open_list("output-histogram");
976 xo_emit("\t{T:Output histogram}:\n");
979 xo_open_instance("output-histogram");
980 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
982 (uintmax_t)icmp6stat.icp6s_outhist[i]);
983 xo_close_instance("output-histogram");
986 xo_close_list("output-histogram");
989 p(icp6s_badcode, "\t{:dropped-bad-code/%ju} "
990 "{N:/message%s with bad code fields}\n");
991 p(icp6s_tooshort, "\t{:dropped-too-short/%ju} "
992 "{N:/message%s < minimum length}\n");
993 p(icp6s_checksum, "\t{:dropped-bad-checksum/%ju} "
994 "{N:/bad checksum%s}\n");
995 p(icp6s_badlen, "\t{:dropped-bad-length/%ju} "
996 "{N:/message%s with bad length}\n");
997 #define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
998 for (first = 1, i = 0; i < NELEM; i++)
999 if (icmp6stat.icp6s_inhist[i] != 0) {
1001 xo_open_list("input-histogram");
1002 xo_emit("\t{T:Input histogram}:\n");
1005 xo_open_instance("input-histogram");
1006 xo_emit("\t\t{k:name/%s}: {:count/%ju}\n",
1008 (uintmax_t)icmp6stat.icp6s_inhist[i]);
1009 xo_close_instance("input-histogram");
1012 xo_close_list("input-histogram");
1014 xo_emit("\t{T:Histogram of error messages to be generated}:\n");
1015 xo_open_container("errors");
1016 p_5(icp6s_odst_unreach_noroute, "\t\t{:no-route/%ju} "
1018 p_5(icp6s_odst_unreach_admin, "\t\t{:admin-prohibited/%ju} "
1019 "{N:/administratively prohibited}\n");
1020 p_5(icp6s_odst_unreach_beyondscope, "\t\t{:beyond-scope/%ju} "
1021 "{N:/beyond scope}\n");
1022 p_5(icp6s_odst_unreach_addr, "\t\t{:address-unreachable/%ju} "
1023 "{N:/address unreachable}\n");
1024 p_5(icp6s_odst_unreach_noport, "\t\t{:port-unreachable/%ju} "
1025 "{N:/port unreachable}\n");
1026 p_5(icp6s_opacket_too_big, "\t\t{:packet-too-big/%ju} "
1027 "{N:/packet too big}\n");
1028 p_5(icp6s_otime_exceed_transit, "\t\t{:time-exceed-transmit/%ju} "
1029 "{N:/time exceed transit}\n");
1030 p_5(icp6s_otime_exceed_reassembly, "\t\t{:time-exceed-reassembly/%ju} "
1031 "{N:/time exceed reassembly}\n");
1032 p_5(icp6s_oparamprob_header, "\t\t{:bad-header/%ju} "
1033 "{N:/erroneous header field}\n");
1034 p_5(icp6s_oparamprob_nextheader, "\t\t{:bad-next-header/%ju} "
1035 "{N:/unrecognized next header}\n");
1036 p_5(icp6s_oparamprob_option, "\t\t{:bad-option/%ju} "
1037 "{N:/unrecognized option}\n");
1038 p_5(icp6s_oredirect, "\t\t{:redirects/%ju} "
1040 p_5(icp6s_ounknown, "\t\t{:unknown/%ju} {N:unknown}\n");
1042 p(icp6s_reflect, "\t{:reflect/%ju} "
1043 "{N:/message response%s generated}\n");
1044 p(icp6s_nd_toomanyopt, "\t{:too-many-nd-options/%ju} "
1045 "{N:/message%s with too many ND options}\n");
1046 p(icp6s_nd_badopt, "\t{:bad-nd-options/%ju} "
1047 "{N:/message%s with bad ND options}\n");
1048 p(icp6s_badns, "\t{:bad-neighbor-solicitation/%ju} "
1049 "{N:/bad neighbor solicitation message%s}\n");
1050 p(icp6s_badna, "\t{:bad-neighbor-advertisement/%ju} "
1051 "{N:/bad neighbor advertisement message%s}\n");
1052 p(icp6s_badrs, "\t{:bad-router-solicitation/%ju} "
1053 "{N:/bad router solicitation message%s}\n");
1054 p(icp6s_badra, "\t{:bad-router-advertisement/%ju} "
1055 "{N:/bad router advertisement message%s}\n");
1056 p(icp6s_badredirect, "\t{:bad-redirect/%ju} "
1057 "{N:/bad redirect message%s}\n");
1058 xo_close_container("errors");
1059 p(icp6s_pmtuchg, "\t{:path-mtu-changes/%ju} {N:/path MTU change%s}\n");
1062 xo_close_container(name);
1066 * Dump ICMPv6 per-interface statistics based on RFC 2466.
1069 icmp6_ifstats(char *ifname)
1071 struct in6_ifreq ifr;
1074 #define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1075 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1076 plural(ifr.ifr_ifru.ifru_icmp6stat.f))
1077 #define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
1078 xo_emit(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, \
1079 pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
1081 if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1082 xo_warn("Warning: socket(AF_INET6)");
1086 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
1087 if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
1088 if (errno != EPFNOSUPPORT)
1089 xo_warn("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
1093 xo_emit("{T:/icmp6 on %s}:\n", ifr.ifr_name);
1095 xo_open_instance("icmp6-interface-statistics");
1096 xo_emit("{ke:name/%s}", ifr.ifr_name);
1097 p(ifs6_in_msg, "\t{:received-packets/%ju} "
1098 "{N:/total input message%s}\n");
1099 p(ifs6_in_error, "\t{:received-errors/%ju} "
1100 "{N:/total input error message%s}\n");
1101 p(ifs6_in_dstunreach, "\t{:received-destination-unreachable/%ju} "
1102 "{N:/input destination unreachable error%s}\n");
1103 p(ifs6_in_adminprohib, "\t{:received-admin-prohibited/%ju} "
1104 "{N:/input administratively prohibited error%s}\n");
1105 p(ifs6_in_timeexceed, "\t{:received-time-exceeded/%ju} "
1106 "{N:/input time exceeded error%s}\n");
1107 p(ifs6_in_paramprob, "\t{:received-bad-parameter/%ju} "
1108 "{N:/input parameter problem error%s}\n");
1109 p(ifs6_in_pkttoobig, "\t{:received-packet-too-big/%ju} "
1110 "{N:/input packet too big error%s}\n");
1111 p(ifs6_in_echo, "\t{:received-echo-requests/%ju} "
1112 "{N:/input echo request%s}\n");
1113 p2(ifs6_in_echoreply, "\t{:received-echo-replies/%ju} "
1114 "{N:/input echo repl%s}\n");
1115 p(ifs6_in_routersolicit, "\t{:received-router-solicitation/%ju} "
1116 "{N:/input router solicitation%s}\n");
1117 p(ifs6_in_routeradvert, "\t{:received-router-advertisement/%ju} "
1118 "{N:/input router advertisement%s}\n");
1119 p(ifs6_in_neighborsolicit, "\t{:received-neighbor-solicitation/%ju} "
1120 "{N:/input neighbor solicitation%s}\n");
1121 p(ifs6_in_neighboradvert, "\t{:received-neighbor-advertisement/%ju} "
1122 "{N:/input neighbor advertisement%s}\n");
1123 p(ifs6_in_redirect, "\t{received-redirects/%ju} "
1124 "{N:/input redirect%s}\n");
1125 p2(ifs6_in_mldquery, "\t{:received-mld-queries/%ju} "
1126 "{N:/input MLD quer%s}\n");
1127 p(ifs6_in_mldreport, "\t{:received-mld-reports/%ju} "
1128 "{N:/input MLD report%s}\n");
1129 p(ifs6_in_mlddone, "\t{:received-mld-done/%ju} "
1130 "{N:/input MLD done%s}\n");
1132 p(ifs6_out_msg, "\t{:sent-packets/%ju} "
1133 "{N:/total output message%s}\n");
1134 p(ifs6_out_error, "\t{:sent-errors/%ju} "
1135 "{N:/total output error message%s}\n");
1136 p(ifs6_out_dstunreach, "\t{:sent-destination-unreachable/%ju} "
1137 "{N:/output destination unreachable error%s}\n");
1138 p(ifs6_out_adminprohib, "\t{:sent-admin-prohibited/%ju} "
1139 "{N:/output administratively prohibited error%s}\n");
1140 p(ifs6_out_timeexceed, "\t{:sent-time-exceeded/%ju} "
1141 "{N:/output time exceeded error%s}\n");
1142 p(ifs6_out_paramprob, "\t{:sent-bad-parameter/%ju} "
1143 "{N:/output parameter problem error%s}\n");
1144 p(ifs6_out_pkttoobig, "\t{:sent-packet-too-big/%ju} "
1145 "{N:/output packet too big error%s}\n");
1146 p(ifs6_out_echo, "\t{:sent-echo-requests/%ju} "
1147 "{N:/output echo request%s}\n");
1148 p2(ifs6_out_echoreply, "\t{:sent-echo-replies/%ju} "
1149 "{N:/output echo repl%s}\n");
1150 p(ifs6_out_routersolicit, "\t{:sent-router-solicitation/%ju} "
1151 "{N:/output router solicitation%s}\n");
1152 p(ifs6_out_routeradvert, "\t{:sent-router-advertisement/%ju} "
1153 "{N:/output router advertisement%s}\n");
1154 p(ifs6_out_neighborsolicit, "\t{:sent-neighbor-solicitation/%ju} "
1155 "{N:/output neighbor solicitation%s}\n");
1156 p(ifs6_out_neighboradvert, "\t{:sent-neighbor-advertisement/%ju} "
1157 "{N:/output neighbor advertisement%s}\n");
1158 p(ifs6_out_redirect, "\t{:sent-redirects/%ju} "
1159 "{N:/output redirect%s}\n");
1160 p2(ifs6_out_mldquery, "\t{:sent-mld-queries/%ju} "
1161 "{N:/output MLD quer%s}\n");
1162 p(ifs6_out_mldreport, "\t{:sent-mld-reports/%ju} "
1163 "{N:/output MLD report%s}\n");
1164 p(ifs6_out_mlddone, "\t{:sent-mld-dones/%ju} "
1165 "{N:/output MLD done%s}\n");
1168 xo_close_instance("icmp6-interface-statistics");
1174 * Dump PIM statistics structure.
1177 pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1179 struct pim6stat pim6stat;
1181 if (fetch_stats("net.inet6.pim.stats", off, &pim6stat,
1182 sizeof(pim6stat), kread) != 0)
1185 xo_emit("{T:/%s}:\n", name);
1186 xo_open_container(name);
1188 #define p(f, m) if (pim6stat.f || sflag <= 1) \
1189 xo_emit(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
1191 p(pim6s_rcv_total, "\t{:received-packets/%ju} "
1192 "{N:/message%s received}\n");
1193 p(pim6s_rcv_tooshort, "\t{:dropped-too-short/%ju} "
1194 "{N:/message%s received with too few bytes}\n");
1195 p(pim6s_rcv_badsum, "\t{:dropped-bad-checksum/%ju} "
1196 "{N:/message%s received with bad checksum}\n");
1197 p(pim6s_rcv_badversion, "\t{:dropped-bad-version/%ju} "
1198 "{N:/message%s received with bad version}\n");
1199 p(pim6s_rcv_registers, "\t{:received-registers/%ju} "
1200 "{N:/register%s received}\n");
1201 p(pim6s_rcv_badregisters, "\t{:received-bad-registers/%ju} "
1202 "{N:/bad register%s received}\n");
1203 p(pim6s_snd_registers, "\t{:sent-registers/%ju} "
1204 "{N:/register%s sent}\n");
1206 xo_close_container(name);
1210 * Dump raw ip6 statistics structure.
1213 rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
1215 struct rip6stat rip6stat;
1218 if (fetch_stats("net.inet6.ip6.rip6stats", off, &rip6stat,
1219 sizeof(rip6stat), kread_counters) != 0)
1222 xo_emit("{T:/%s}:\n", name);
1223 xo_open_container(name);
1225 #define p(f, m) if (rip6stat.f || sflag <= 1) \
1226 xo_emit(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
1228 p(rip6s_ipackets, "\t{:received-packets/%ju} "
1229 "{N:/message%s received}\n");
1230 p(rip6s_isum, "\t{:input-checksum-computation/%ju} "
1231 "{N:/checksum calculation%s on inbound}\n");
1232 p(rip6s_badsum, "\t{:received-bad-checksum/%ju} "
1233 "{N:/message%s with bad checksum}\n");
1234 p(rip6s_nosock, "\t{:dropped-no-socket/%ju} "
1235 "{N:/message%s dropped due to no socket}\n");
1236 p(rip6s_nosockmcast, "\t{:dropped-multicast-no-socket/%ju} "
1237 "{N:/multicast message%s dropped due to no socket}\n");
1238 p(rip6s_fullsock, "\t{:dropped-full-socket-buffer/%ju} "
1239 "{N:/message%s dropped due to full socket buffers}\n");
1240 delivered = rip6stat.rip6s_ipackets -
1241 rip6stat.rip6s_badsum -
1242 rip6stat.rip6s_nosock -
1243 rip6stat.rip6s_nosockmcast -
1244 rip6stat.rip6s_fullsock;
1245 if (delivered || sflag <= 1)
1246 xo_emit("\t{:delivered-packets/%ju} {N:/delivered}\n",
1247 (uintmax_t)delivered);
1248 p(rip6s_opackets, "\t{:sent-packets/%ju} "
1249 "{N:/datagram%s output}\n");
1251 xo_close_container(name);
1255 * Pretty print an Internet address (net address + port).
1256 * Take numeric_addr and numeric_port into consideration.
1258 #define GETSERVBYPORT6(port, proto, ret)\
1260 if (strcmp((proto), "tcp6") == 0)\
1261 (ret) = getservbyport((int)(port), "tcp");\
1262 else if (strcmp((proto), "udp6") == 0)\
1263 (ret) = getservbyport((int)(port), "udp");\
1265 (ret) = getservbyport((int)(port), (proto));\
1269 inet6print(const char *container, struct in6_addr *in6, int port,
1270 const char *proto, int numeric)
1272 struct servent *sp = 0;
1278 xo_open_container(container);
1280 snprintf(line, sizeof(line), "%.*s.",
1281 Wflag ? 39 : (Aflag && !numeric) ? 12 : 16,
1283 alen = strlen(line);
1285 if (!numeric && port)
1286 GETSERVBYPORT6(port, proto, sp);
1287 if (sp || port == 0)
1288 snprintf(cp, sizeof(line) - alen,
1289 "%.15s", sp ? sp->s_name : "*");
1291 snprintf(cp, sizeof(line) - alen,
1292 "%d", ntohs((u_short)port));
1293 width = Wflag ? 45 : Aflag ? 18 : 22;
1295 xo_emit("{d:target/%-*.*s} ", width, width, line);
1299 xo_emit("{e:address/%*.*s}{e:port/%*.*s}", alen, alen, line, plen,
1303 xo_close_container(container);
1307 * Construct an Internet address representation.
1308 * If the numeric_addr has been supplied, give
1309 * numeric value, otherwise try for symbolic name.
1313 inet6name(struct in6_addr *ia6)
1315 struct sockaddr_in6 sin6;
1316 char hbuf[NI_MAXHOST], *cp;
1317 static char line[NI_MAXHOST];
1318 static char domain[MAXHOSTNAMELEN];
1319 static int first = 1;
1322 if (IN6_IS_ADDR_UNSPECIFIED(ia6)) {
1326 if (first && !numeric_addr) {
1328 if (gethostname(domain, sizeof(domain)) == 0 &&
1329 (cp = strchr(domain, '.')))
1330 strlcpy(domain, cp + 1, sizeof(domain));
1334 memset(&sin6, 0, sizeof(sin6));
1335 memcpy(&sin6.sin6_addr, ia6, sizeof(*ia6));
1336 sin6.sin6_family = AF_INET6;
1337 /* XXX: ia6.s6_addr[2] can contain scopeid. */
1338 in6_fillscopeid(&sin6);
1339 flags = (numeric_addr) ? NI_NUMERICHOST : 0;
1340 error = getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), hbuf,
1341 sizeof(hbuf), NULL, 0, flags);
1343 if ((flags & NI_NUMERICHOST) == 0 &&
1344 (cp = strchr(hbuf, '.')) &&
1345 !strcmp(cp + 1, domain))
1347 strlcpy(line, hbuf, sizeof(line));
1349 /* XXX: this should not happen. */
1350 snprintf(line, sizeof(line), "%s",
1351 inet_ntop(AF_INET6, (void *)&sin6.sin6_addr, ntop_buf,