aboutsummaryrefslogtreecommitdiffstats
path: root/network_cmds/netstat.tproj/inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'network_cmds/netstat.tproj/inet6.c')
-rw-r--r--network_cmds/netstat.tproj/inet6.c1333
1 files changed, 1333 insertions, 0 deletions
diff --git a/network_cmds/netstat.tproj/inet6.c b/network_cmds/netstat.tproj/inet6.c
new file mode 100644
index 0000000..4bc757c
--- /dev/null
+++ b/network_cmds/netstat.tproj/inet6.c
@@ -0,0 +1,1333 @@
+/*
+ * Copyright (c) 2008-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/usr.bin/netstat/inet6.c,v 1.3.2.9 2001/08/10 09:07:09 ru Exp $
+ */
+
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#include <net/if_var.h>
+#include <net/net_perf.h>
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in_systm.h>
+#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/raw_ip6.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#if defined(__APPLE__) && !defined(__unused)
+#define __unused
+#endif
+
+char *inet6name (struct in6_addr *);
+void inet6print (struct in6_addr *, int, char *, int);
+
+static char *ip6nh[] = {
+ "hop by hop",
+ "ICMP",
+ "IGMP",
+ "#3",
+ "IP",
+ "#5",
+ "TCP",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "UDP",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "IDP",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "TP",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "IP6",
+ "#42",
+ "routing",
+ "fragment",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "ESP",
+ "AH",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "ICMP6",
+ "no next header",
+ "destination option",
+ "#61",
+ "mobility",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "ISOIP",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "OSPF",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "Ethernet",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "PIM",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "#128",
+ "#129",
+ "#130",
+ "#131",
+ "#132",
+ "#133",
+ "#134",
+ "#135",
+ "#136",
+ "#137",
+ "#138",
+ "#139",
+ "#140",
+ "#141",
+ "#142",
+ "#143",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+
+static const char *srcrulenames[IP6S_SRCRULE_COUNT] = {
+ "default", // IP6S_SRCRULE_0
+ "prefer same address", // IP6S_SRCRULE_1
+ "prefer appropriate scope", // IP6S_SRCRULE_2
+ "avoid deprecated addresses", // IP6S_SRCRULE_3
+ "prefer home addresses", // IP6S_SRCRULE_4
+ "prefer outgoing interface", // IP6S_SRCRULE_5
+ "prefer matching label", // IP6S_SRCRULE_6
+ "prefer temporary addresses", // IP6S_SRCRULE_7
+ "prefer addresses on alive interfaces", // IP6S_SRCRULE_7x
+ "use longest matching prefix", // IP6S_SRCRULE_8
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*
+ * Dump IP6 statistics structure.
+ */
+void
+ip6_stats(uint32_t off __unused, char *name, int af __unused)
+{
+ static struct ip6stat pip6stat;
+ struct ip6stat ip6stat;
+ int first, i;
+ int mib[4];
+ size_t len;
+ static net_perf_t pout_net_perf, pin_net_perf;
+ net_perf_t out_net_perf, in_net_perf;
+ size_t out_net_perf_len = sizeof (out_net_perf);
+ size_t in_net_perf_len = sizeof (in_net_perf);
+
+ if (sysctlbyname("net.inet6.ip6.output_perf_data", &out_net_perf, &out_net_perf_len, 0, 0) < 0) {
+ perror("sysctl: net.inet6.ip6.output_perf_data");
+ return;
+ }
+
+ if (sysctlbyname("net.inet6.ip6.input_perf_data", &in_net_perf, &in_net_perf_len, 0, 0) < 0) {
+ perror("sysctl: net.inet6.ip6.input_perf_data");
+ return;
+ }
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_IPV6;
+ mib[3] = IPV6CTL_STATS;
+
+ len = sizeof ip6stat;
+ memset(&ip6stat, 0, len);
+ if (sysctl(mib, 4, &ip6stat, &len, (void *)0, 0) < 0)
+ return;
+ if (interval && vflag > 0)
+ print_time();
+ printf("%s:\n", name);
+
+#define IP6DIFF(f) (ip6stat.f - pip6stat.f)
+#define p(f, m) if (IP6DIFF(f) || sflag <= 1) \
+ printf(m, (unsigned long long)IP6DIFF(f), plural(IP6DIFF(f)))
+#define p1a(f, m) if (IP6DIFF(f) || sflag <= 1) \
+ printf(m, (unsigned long long)IP6DIFF(f))
+
+ p(ip6s_total, "\t%llu total packet%s received\n");
+ p1a(ip6s_toosmall, "\t\t%llu with size smaller than minimum\n");
+ p1a(ip6s_tooshort, "\t\t%llu with data size < data length\n");
+ p1a(ip6s_adj, "\t\t%llu with data size > data length\n");
+ p(ip6s_adj_hwcsum_clr,
+ "\t\t\t%llu packet%s forced to software checksum\n");
+ p1a(ip6s_badoptions, "\t\t%llu with bad options\n");
+ p1a(ip6s_badvers, "\t\t%llu with incorrect version number\n");
+ p(ip6s_fragments, "\t\t%llu fragment%s received\n");
+ p1a(ip6s_fragdropped,
+ "\t\t\t%llu dropped (dup or out of space)\n");
+ p1a(ip6s_fragtimeout, "\t\t\t%llu dropped after timeout\n");
+ p1a(ip6s_fragoverflow, "\t\t\t%llu exceeded limit\n");
+ p1a(ip6s_reassembled, "\t\t\t%llu reassembled ok\n");
+ p1a(ip6s_atmfrag_rcvd, "\t\t\t%llu atomic fragments received\n");
+ p(ip6s_delivered, "\t\t%llu packet%s for this host\n");
+ p(ip6s_forward, "\t\t%llu packet%s forwarded\n");
+ p(ip6s_cantforward, "\t\t%llu packet%s not forwardable\n");
+ p(ip6s_redirectsent, "\t\t%llu redirect%s sent\n");
+ p(ip6s_notmember, "\t\t%llu multicast packet%s which we don't join\n");
+ p(ip6s_exthdrtoolong,
+ "\t\t%llu packet%s whose headers are not continuous\n");
+ p(ip6s_nogif, "\t\t%llu tunneling packet%s that can't find gif\n");
+ p(ip6s_toomanyhdr,
+ "\t\t%llu packet%s discarded due to too may headers\n");
+ p1a(ip6s_forward_cachehit, "\t\t%llu forward cache hit\n");
+ p1a(ip6s_forward_cachemiss, "\t\t%llu forward cache miss\n");
+ p(ip6s_pktdropcntrl,
+ "\t\t%llu packet%s dropped due to no bufs for control data\n");
+ /* CLAT46 input stats */
+ p(ip6s_clat464_in_tooshort_drop,
+ "\t\t%llu input packet%s dropped due to too short length \n");
+ p(ip6s_clat464_in_nov6addr_drop,
+ "\t\t%llu input packet%s dropped due to missing CLAT46 IPv6 address\n");
+ p(ip6s_clat464_in_nov4addr_drop,
+ "\t\t%llu input packet%s dropped due to missing CLAT46 IPv4 address\n");
+ p(ip6s_clat464_in_v4synthfail_drop,
+ "\t\t%llu input packet%s dropped due to CLAT46 IPv4 address derivation failure\n");
+ p(ip6s_clat464_in_64transfail_drop,
+ "\t\t%llu input packet%s dropped due to CLAT46 IP header translation failure\n");
+ p(ip6s_clat464_in_64proto_transfail_drop,
+ "\t\t%llu input packet%s dropped due to CLAT46 protocol translation failure\n");
+ p(ip6s_clat464_in_64frag_transfail_drop,
+ "\t\t%llu input packet%s dropped due to CLAT46 fragment translation failure\n");
+ p(ip6s_clat464_in_invalpbuf_drop,
+ "\t\t%llu input packet%s dropped due to invalid pbuf\n");
+ p(ip6s_clat464_in_v4_drop,
+ "\t\t%llu input IPv4 packet%s dropped on CLAT46 enabled interface\n");
+ p(ip6s_clat464_in_drop,
+ "\t\t%llu input packet%s dropped due to CLAT46 failures\n");
+ p(ip6s_clat464_in_success,
+ "\t\t%llu input packet%s successfully translated from IPv6 to IPv4\n");
+
+#define INPERFDIFF(f) (in_net_perf.f - pin_net_perf.f)
+ if (INPERFDIFF(np_total_pkts) > 0 && in_net_perf.np_total_usecs > 0) {
+ printf("\tInput Performance Stats:\n");
+ printf("\t\t%llu total packets measured\n", INPERFDIFF(np_total_pkts));
+ printf("\t\t%llu total usec elapsed\n", INPERFDIFF(np_total_usecs));
+ printf("\t\t%f usec per packet\n",
+ (double)in_net_perf.np_total_usecs/(double)in_net_perf.np_total_pkts);
+ printf("\t\tPerformance Histogram:\n");
+ printf("\t\t\t x <= %u: %llu\n", in_net_perf.np_hist_bars[0],
+ INPERFDIFF(np_hist1));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ in_net_perf.np_hist_bars[0], in_net_perf.np_hist_bars[1],
+ INPERFDIFF(np_hist2));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ in_net_perf.np_hist_bars[1], in_net_perf.np_hist_bars[2],
+ INPERFDIFF(np_hist3));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ in_net_perf.np_hist_bars[2], in_net_perf.np_hist_bars[3],
+ INPERFDIFF(np_hist4));
+ printf("\t\t\t %u < x: %llu\n",
+ in_net_perf.np_hist_bars[3], INPERFDIFF(np_hist5));
+ }
+#undef INPERFDIFF
+
+ p(ip6s_localout, "\t%llu packet%s sent from this host\n");
+ p(ip6s_rawout, "\t\t%llu packet%s sent with fabricated ip header\n");
+ p(ip6s_odropped,
+ "\t\t%llu output packet%s dropped due to no bufs, etc.\n");
+ p(ip6s_noroute, "\t\t%llu output packet%s discarded due to no route\n");
+ p(ip6s_fragmented, "\t\t%llu output datagram%s fragmented\n");
+ p(ip6s_ofragments, "\t\t%llu fragment%s created\n");
+ p(ip6s_cantfrag, "\t\t%llu datagram%s that can't be fragmented\n");
+ p(ip6s_badscope, "\t\t%llu packet%s that violated scope rules\n");
+ p(ip6s_necp_policy_drop, "\t\t%llu packet%s dropped due to NECP policy\n");
+ /* CLAT46 output stats */
+ p(ip6s_clat464_out_nov6addr_drop,
+ "\t\t%llu output packet%s dropped due to missing CLAT46 IPv6 address\n");
+ p(ip6s_clat464_out_v6synthfail_drop,
+ "\t\t%llu output packet%s dropped due to CLAT46 IPv6 address synthesis failure\n");
+ p(ip6s_clat464_out_46transfail_drop,
+ "\t\t%llu output packet%s dropped due to CLAT46 IP header translation failure\n");
+ p(ip6s_clat464_out_46proto_transfail_drop,
+ "\t\t%llu output packet%s dropped due to CLAT46 protocol translation failure\n");
+ p(ip6s_clat464_out_46frag_transfail_drop,
+ "\t\t%llu output packet%s dropped due to CLAT46 fragment translation failure\n");
+ p(ip6s_clat464_out_invalpbuf_drop,
+ "\t\t%llu output packet%s dropped due to invalid pbuf\n");
+ p(ip6s_clat464_out_drop,
+ "\t\t%llu output packet%s dropped due to CLAT46 failures\n");
+ p(ip6s_clat464_out_success,
+ "\t\t%llu output packet%s successfully translated from IPv4 to IPv6\n");
+ p(ip6s_rcv_if_weak_match,
+ "\t\t%llu input packet%s that passed the weak ES interface address match\n");
+ p(ip6s_rcv_if_no_match,
+ "\t\t%llu input packet%s with no interface address match\n");
+
+#define OUTPERFDIFF(f) (out_net_perf.f - pout_net_perf.f)
+ if (OUTPERFDIFF(np_total_pkts) > 0 && out_net_perf.np_total_usecs > 0) {
+ printf("\tOutput Performance Stats:\n");
+ printf("\t\t%llu total packets measured\n", OUTPERFDIFF(np_total_pkts));
+ printf("\t\t%llu total usec elapsed\n", OUTPERFDIFF(np_total_usecs));
+ printf("\t\t%f usec per packet\n",
+ (double)out_net_perf.np_total_usecs/(double)out_net_perf.np_total_pkts);
+ printf("\t\tHistogram:\n");
+ printf("\t\t\t x <= %u: %llu\n", out_net_perf.np_hist_bars[0],
+ OUTPERFDIFF(np_hist1));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ out_net_perf.np_hist_bars[0], out_net_perf.np_hist_bars[1],
+ OUTPERFDIFF(np_hist2));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ out_net_perf.np_hist_bars[1], out_net_perf.np_hist_bars[2],
+ OUTPERFDIFF(np_hist3));
+ printf("\t\t\t %u < x <= %u: %llu\n",
+ out_net_perf.np_hist_bars[2], out_net_perf.np_hist_bars[3],
+ OUTPERFDIFF(np_hist4));
+ printf("\t\t\t %u < x: %llu\n",
+ out_net_perf.np_hist_bars[3], OUTPERFDIFF(np_hist5));
+ }
+#undef OUTPERFDIFF
+
+ for (first = 1, i = 0; i < 256; i++)
+ if (IP6DIFF(ip6s_nxthist[i]) != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", ip6nh[i],
+ (unsigned long long)IP6DIFF(ip6s_nxthist[i]));
+ }
+ printf("\tMbuf statistics:\n");
+ printf("\t\t%llu one mbuf\n", (unsigned long long)IP6DIFF(ip6s_m1));
+ for (first = 1, i = 0; i < 32; i++) {
+ char ifbuf[IFNAMSIZ];
+ if (IP6DIFF(ip6s_m2m[i]) != 0) {
+ if (first) {
+ printf("\t\ttwo or more mbuf:\n");
+ first = 0;
+ }
+ printf("\t\t\t%s= %llu\n",
+ if_indextoname(i, ifbuf),
+ (unsigned long long)IP6DIFF(ip6s_m2m[i]));
+ }
+ }
+ printf("\t\t%llu one ext mbuf\n",
+ (unsigned long long)IP6DIFF(ip6s_mext1));
+ printf("\t\t%llu two or more ext mbuf\n",
+ (unsigned long long)IP6DIFF(ip6s_mext2m));
+
+ /* for debugging source address selection */
+#define PRINT_SCOPESTAT(s,i) do {\
+ switch(i) { /* XXX hardcoding in each case */\
+ case 1:\
+ p(s, "\t\t\t%llu node-local%s\n");\
+ break;\
+ case 2:\
+ p(s,"\t\t\t%llu link-local%s\n");\
+ break;\
+ case 5:\
+ p(s,"\t\t\t%llu site-local%s\n");\
+ break;\
+ case 14:\
+ p(s,"\t\t\t%llu global%s\n");\
+ break;\
+ default:\
+ printf("\t\t\t%llu addresses scope=%x\n",\
+ (unsigned long long)IP6DIFF(s), i);\
+ }\
+ } while (0);
+
+ p(ip6s_sources_none,
+ "\t\t%llu failure%s of source address selection\n");
+ for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) {
+ if (IP6DIFF(ip6s_sources_sameif[i]) || 1) {
+ if (first) {
+ printf("\t\tsource addresses on an outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) {
+ if (IP6DIFF(ip6s_sources_otherif[i]) || 1) {
+ if (first) {
+ printf("\t\tsource addresses on a non-outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) {
+ if (IP6DIFF(ip6s_sources_samescope[i]) || 1) {
+ if (first) {
+ printf("\t\tsource addresses of same scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) {
+ if (IP6DIFF(ip6s_sources_otherscope[i]) || 1) {
+ if (first) {
+ printf("\t\tsource addresses of a different scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) {
+ if (IP6DIFF(ip6s_sources_deprecated[i]) || 1) {
+ if (first) {
+ printf("\t\tdeprecated source addresses\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
+ }
+ }
+#define PRINT_SRCRULESTAT(s,i) do {\
+ if (srcrulenames[i] != NULL) \
+ printf("\t\t\t%llu rule%s %s\n", \
+ (unsigned long long)IP6DIFF(s), \
+ plural(IP6DIFF(s)), \
+ srcrulenames[i]); \
+} while (0);
+
+ for (first = 1, i = 0; i < IP6S_SRCRULE_COUNT; i++) {
+ if (IP6DIFF(ip6s_sources_rule[i]) || 1) {
+ if (first) {
+ printf("\t\tsource address selection\n");
+ first = 0;
+ }
+ PRINT_SRCRULESTAT(ip6s_sources_rule[i], i);
+ }
+ }
+
+ p(ip6s_dad_collide, "\t\t%llu duplicate address detection collision%s\n");
+
+ p(ip6s_dad_loopcount, "\t\t%llu duplicate address detection NS loop%s\n");
+
+ p(ip6s_sources_skip_expensive_secondary_if, "\t\t%llu time%s ignored source on secondary expensive I/F\n");
+
+ if (interval > 0) {
+ bcopy(&ip6stat, &pip6stat, len);
+ bcopy(&in_net_perf, &pin_net_perf, in_net_perf_len);
+ bcopy(&out_net_perf, &pout_net_perf, out_net_perf_len);
+ }
+#undef IP6DIFF
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump IPv6 per-interface statistics based on RFC 2465.
+ */
+void
+ip6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
+#define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ip6stat.f)
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ if (interval && vflag > 0)
+ print_time();
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ printf("ip6 on %s:\n", ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
+ goto end;
+ }
+
+ p(ifs6_in_receive, "\t%llu total input datagram%s\n");
+ p(ifs6_in_hdrerr, "\t%llu datagram%s with invalid header received\n");
+ p(ifs6_in_toobig, "\t%llu datagram%s exceeded MTU received\n");
+ p(ifs6_in_noroute, "\t%llu datagram%s with no route received\n");
+ p(ifs6_in_addrerr, "\t%llu datagram%s with invalid dst received\n");
+ p(ifs6_in_protounknown, "\t%llu datagram%s with unknown proto received\n");
+ p(ifs6_in_truncated, "\t%llu truncated datagram%s received\n");
+ p(ifs6_in_discard, "\t%llu input datagram%s discarded\n");
+ p(ifs6_in_deliver,
+ "\t%llu datagram%s delivered to an upper layer protocol\n");
+ p(ifs6_out_forward, "\t%llu datagram%s forwarded to this interface\n");
+ p(ifs6_out_request,
+ "\t%llu datagram%s sent from an upper layer protocol\n");
+ p(ifs6_out_discard, "\t%llu total discarded output datagram%s\n");
+ p(ifs6_out_fragok, "\t%llu output datagram%s fragmented\n");
+ p(ifs6_out_fragfail, "\t%llu output datagram%s failed on fragment\n");
+ p(ifs6_out_fragcreat, "\t%llu output datagram%s succeeded on fragment\n");
+ p(ifs6_reass_reqd, "\t%llu incoming datagram%s fragmented\n");
+ p(ifs6_reass_ok, "\t%llu datagram%s reassembled\n");
+ p(ifs6_atmfrag_rcvd, "\t%llu atomic fragments%s received\n");
+ p(ifs6_reass_fail, "\t%llu datagram%s failed on reassembling\n");
+ p(ifs6_in_mcast, "\t%llu multicast datagram%s received\n");
+ p(ifs6_out_mcast, "\t%llu multicast datagram%s sent\n");
+
+ p(ifs6_cantfoward_icmp6, "\t%llu ICMPv6 packet%s received for unreachable destination\n");
+ p(ifs6_addr_expiry_cnt, "\t%llu address expiry event%s reported\n");
+ p(ifs6_pfx_expiry_cnt, "\t%llu prefix expiry event%s reported\n");
+ p(ifs6_defrtr_expiry_cnt, "\t%llu default router expiry event%s reported\n");
+ end:
+ close(s);
+
+#undef p
+#undef p_5
+}
+
+static char *icmp6names[] = {
+ "#0",
+ "unreach",
+ "packet too big",
+ "time exceed",
+ "parameter problem",
+ "#5",
+ "#6",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "#17",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "#41",
+ "#42",
+ "#43",
+ "#44",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "#50",
+ "#51",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "#58",
+ "#59",
+ "#60",
+ "#61",
+ "#62",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "#80",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "#89",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "#97",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "#103",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "echo",
+ "echo reply",
+ "multicast listener query",
+ "MLDv1 listener report",
+ "MLDv1 listener done",
+ "router solicitation",
+ "router advertisement",
+ "neighbor solicitation",
+ "neighbor advertisement",
+ "redirect",
+ "router renumbering",
+ "node information request",
+ "node information reply",
+ "inverse neighbor solicitation",
+ "inverse neighbor advertisement",
+ "MLDv2 listener report",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+/*
+ * Dump ICMP6 statistics.
+ */
+void
+icmp6_stats(uint32_t off __unused, char *name, int af __unused)
+{
+ static struct icmp6stat picmp6stat;
+ struct icmp6stat icmp6stat;
+ register int i, first;
+ int mib[4];
+ size_t len;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_ICMPV6;
+ mib[3] = ICMPV6CTL_STATS;
+
+ len = sizeof icmp6stat;
+ memset(&icmp6stat, 0, len);
+ if (sysctl(mib, 4, &icmp6stat, &len, (void *)0, 0) < 0)
+ return;
+ if (interval && vflag > 0)
+ print_time();
+ printf("%s:\n", name);
+
+#define ICMP6DIFF(f) (icmp6stat.f - picmp6stat.f)
+#define p(f, m) if (ICMP6DIFF(f) || sflag <= 1) \
+ printf(m, (unsigned long long)ICMP6DIFF(f), plural(ICMP6DIFF(f)))
+#define p_5(f, m) printf(m, (unsigned long long)ICMP6DIFF(f))
+
+ p(icp6s_error, "\t%llu call%s to icmp_error\n");
+ p(icp6s_canterror,
+ "\t%llu error%s not generated because old message was icmp error or so\n");
+ p(icp6s_toofreq,
+ "\t%llu error%s not generated because rate limitation\n");
+#define NELEM (sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (ICMP6DIFF(icp6s_outhist[i]) != 0) {
+ if (first) {
+ printf("\tOutput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", icmp6names[i],
+ (unsigned long long)ICMP6DIFF(icp6s_outhist[i]));
+ }
+#undef NELEM
+ p(icp6s_badcode, "\t%llu message%s with bad code fields\n");
+ p(icp6s_tooshort, "\t%llu message%s < minimum length\n");
+ p(icp6s_checksum, "\t%llu bad checksum%s\n");
+ p(icp6s_badlen, "\t%llu message%s with bad length\n");
+#define NELEM (sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (ICMP6DIFF(icp6s_inhist[i]) != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %llu\n", icmp6names[i],
+ (unsigned long long)ICMP6DIFF(icp6s_inhist[i]));
+ }
+#undef NELEM
+ printf("\tHistogram of error messages to be generated:\n");
+ p_5(icp6s_odst_unreach_noroute, "\t\t%llu no route\n");
+ p_5(icp6s_odst_unreach_admin, "\t\t%llu administratively prohibited\n");
+ p_5(icp6s_odst_unreach_beyondscope, "\t\t%llu beyond scope\n");
+ p_5(icp6s_odst_unreach_addr, "\t\t%llu address unreachable\n");
+ p_5(icp6s_odst_unreach_noport, "\t\t%llu port unreachable\n");
+ p_5(icp6s_opacket_too_big, "\t\t%llu packet too big\n");
+ p_5(icp6s_otime_exceed_transit, "\t\t%llu time exceed transit\n");
+ p_5(icp6s_otime_exceed_reassembly, "\t\t%llu time exceed reassembly\n");
+ p_5(icp6s_oparamprob_header, "\t\t%llu erroneous header field\n");
+ p_5(icp6s_oparamprob_nextheader, "\t\t%llu unrecognized next header\n");
+ p_5(icp6s_oparamprob_option, "\t\t%llu unrecognized option\n");
+ p_5(icp6s_oredirect, "\t\t%llu redirect\n");
+ p_5(icp6s_ounknown, "\t\t%llu unknown\n");
+
+ p(icp6s_reflect, "\t%llu message response%s generated\n");
+ p(icp6s_nd_toomanyopt, "\t%llu message%s with too many ND options\n");
+ p(icp6s_nd_badopt, "\t%qu message%s with bad ND options\n");
+ p(icp6s_badns, "\t%qu bad neighbor solicitation message%s\n");
+ p(icp6s_badna, "\t%qu bad neighbor advertisement message%s\n");
+ p(icp6s_badrs, "\t%qu bad router solicitation message%s\n");
+ p(icp6s_badra, "\t%qu bad router advertisement message%s\n");
+ p(icp6s_badredirect, "\t%qu bad redirect message%s\n");
+ p(icp6s_pmtuchg, "\t%llu path MTU change%s\n");
+ p(icp6s_rfc6980_drop, "\t%qu dropped fragmented NDP message%s\n");
+
+ if (interval > 0)
+ bcopy(&icmp6stat, &picmp6stat, len);
+
+#undef ICMP6DIFF
+#undef p
+#undef p_5
+}
+
+/*
+ * Dump ICMPv6 per-interface statistics based on RFC 2466.
+ */
+void
+icmp6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ printf(m, (unsigned long long)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ if (interval && vflag > 0)
+ print_time();
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ printf("icmp6 on %s:\n", ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
+ goto end;
+ }
+
+ p(ifs6_in_msg, "\t%llu total input message%s\n");
+ p(ifs6_in_error, "\t%llu total input error message%s\n");
+ p(ifs6_in_dstunreach, "\t%llu input destination unreachable error%s\n");
+ p(ifs6_in_adminprohib, "\t%llu input administratively prohibited error%s\n");
+ p(ifs6_in_timeexceed, "\t%llu input time exceeded error%s\n");
+ p(ifs6_in_paramprob, "\t%llu input parameter problem error%s\n");
+ p(ifs6_in_pkttoobig, "\t%llu input packet too big error%s\n");
+ p(ifs6_in_echo, "\t%llu input echo request%s\n");
+ p(ifs6_in_echoreply, "\t%llu input echo reply%s\n");
+ p(ifs6_in_routersolicit, "\t%llu input router solicitation%s\n");
+ p(ifs6_in_routeradvert, "\t%llu input router advertisement%s\n");
+ p(ifs6_in_neighborsolicit, "\t%llu input neighbor solicitation%s\n");
+ p(ifs6_in_neighboradvert, "\t%llu input neighbor advertisement%s\n");
+ p(ifs6_in_redirect, "\t%llu input redirect%s\n");
+ p(ifs6_in_mldquery, "\t%llu input MLD query%s\n");
+ p(ifs6_in_mldreport, "\t%llu input MLD report%s\n");
+ p(ifs6_in_mlddone, "\t%llu input MLD done%s\n");
+
+ p(ifs6_out_msg, "\t%llu total output message%s\n");
+ p(ifs6_out_error, "\t%llu total output error message%s\n");
+ p(ifs6_out_dstunreach, "\t%llu output destination unreachable error%s\n");
+ p(ifs6_out_adminprohib, "\t%llu output administratively prohibited error%s\n");
+ p(ifs6_out_timeexceed, "\t%llu output time exceeded error%s\n");
+ p(ifs6_out_paramprob, "\t%llu output parameter problem error%s\n");
+ p(ifs6_out_pkttoobig, "\t%llu output packet too big error%s\n");
+ p(ifs6_out_echo, "\t%llu output echo request%s\n");
+ p(ifs6_out_echoreply, "\t%llu output echo reply%s\n");
+ p(ifs6_out_routersolicit, "\t%llu output router solicitation%s\n");
+ p(ifs6_out_routeradvert, "\t%llu output router advertisement%s\n");
+ p(ifs6_out_neighborsolicit, "\t%llu output neighbor solicitation%s\n");
+ p(ifs6_out_neighboradvert, "\t%llu output neighbor advertisement%s\n");
+ p(ifs6_out_redirect, "\t%llu output redirect%s\n");
+ p(ifs6_out_mldquery, "\t%llu output MLD query%s\n");
+ p(ifs6_out_mldreport, "\t%llu output MLD report%s\n");
+ p(ifs6_out_mlddone, "\t%llu output MLD done%s\n");
+
+ end:
+ close(s);
+#undef p
+}
+
+/*
+ * Dump raw ip6 statistics structure.
+ */
+void
+rip6_stats(uint32_t off __unused, char *name, int af __unused)
+{
+ static struct rip6stat prip6stat;
+ struct rip6stat rip6stat;
+ u_quad_t delivered;
+ int mib[4];
+ size_t l;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET6;
+ mib[2] = IPPROTO_IPV6;
+ mib[3] = IPV6CTL_RIP6STATS;
+ l = sizeof(rip6stat);
+ if (sysctl(mib, 4, &rip6stat, &l, NULL, 0) < 0) {
+ perror("Warning: sysctl(net.inet6.ip6.rip6stats)");
+ return;
+ }
+
+ if (interval && vflag > 0)
+ print_time();
+ printf("%s:\n", name);
+
+#define RIP6DIFF(f) (rip6stat.f - prip6stat.f)
+#define p(f, m) if (RIP6DIFF(f) || sflag <= 1) \
+ printf(m, (unsigned long long)RIP6DIFF(f), plural(RIP6DIFF(f)))
+ p(rip6s_ipackets, "\t%llu message%s received\n");
+ p(rip6s_isum, "\t%llu checksum calculation%s on inbound\n");
+ p(rip6s_badsum, "\t%llu message%s with bad checksum\n");
+ p(rip6s_nosock, "\t%llu message%s dropped due to no socket\n");
+ p(rip6s_nosockmcast,
+ "\t%llu multicast message%s dropped due to no socket\n");
+ p(rip6s_fullsock,
+ "\t%llu message%s dropped due to full socket buffers\n");
+ delivered = RIP6DIFF(rip6s_ipackets) -
+ RIP6DIFF(rip6s_badsum) -
+ RIP6DIFF(rip6s_nosock) -
+ RIP6DIFF(rip6s_nosockmcast) -
+ RIP6DIFF(rip6s_fullsock);
+ if (delivered || sflag <= 1)
+ printf("\t%llu delivered\n", (unsigned long long)delivered);
+ p(rip6s_opackets, "\t%llu datagram%s output\n");
+
+ if (interval > 0)
+ bcopy(&rip6stat, &prip6stat, l);
+
+#undef RIP6DIFF
+#undef p
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * If the nflag was specified, use numbers instead of names.
+ */
+#ifdef SRVCACHE
+extern struct servent * _serv_cache_getservbyport(int port, char *proto);
+
+#define GETSERVBYPORT6(port, proto, ret)\
+{\
+ if (strcmp((proto), "tcp6") == 0)\
+ (ret) = _serv_cache_getservbyport((int)(port), "tcp");\
+ else if (strcmp((proto), "udp6") == 0)\
+ (ret) = _serv_cache_getservbyport((int)(port), "udp");\
+ else\
+ (ret) = _serv_cache_getservbyport((int)(port), (proto));\
+};
+#else
+#define GETSERVBYPORT6(port, proto, ret)\
+{\
+ if (strcmp((proto), "tcp6") == 0)\
+ (ret) = getservbyport((int)(port), "tcp");\
+ else if (strcmp((proto), "udp6") == 0)\
+ (ret) = getservbyport((int)(port), "udp");\
+ else\
+ (ret) = getservbyport((int)(port), (proto));\
+};
+#endif
+void
+inet6print(struct in6_addr *in6, int port, char *proto, int numeric)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+
+ snprintf(line, sizeof(line), "%.*s.", lflag ? 39 :
+ (Aflag && !numeric) ? 12 : 16, inet6name(in6));
+ cp = index(line, '\0');
+ if (!numeric && port)
+ GETSERVBYPORT6(port, proto, sp);
+ if (sp || port == 0)
+ snprintf(cp, sizeof(line) - (cp - line), "%.15s", sp ? sp->s_name : "*");
+ else
+ snprintf(cp, sizeof(line) - (cp - line), "%d", ntohs((u_short)port));
+ width = lflag ? 45 : Aflag ? 18 : 22;
+ printf("%-*.*s ", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the nflag has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+
+char *
+inet6name(struct in6_addr *in6p)
+{
+ register char *cp;
+ static char line[50];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN];
+ static int first = 1;
+ char hbuf[NI_MAXHOST];
+ struct sockaddr_in6 sin6;
+ const int niflag = NI_NUMERICHOST;
+
+ if (first && !nflag) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = index(domain, '.')))
+ (void) memmove(domain, cp + 1, strlen(cp + 1) + 1);
+ else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+ hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
+ if (hp) {
+ if ((cp = index(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+ strlcpy(line, "*", sizeof(line));
+ else if (cp)
+ strlcpy(line, cp, sizeof(line));
+ else {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_len = sizeof(sin6);
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr = *in6p;
+
+ if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
+ IN6_IS_ADDR_MC_NODELOCAL(in6p) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
+ strlcpy(hbuf, "?", sizeof(hbuf));
+ strlcpy(line, hbuf, sizeof(line));
+ }
+ return (line);
+}
+#endif /*INET6*/