X-Git-Url: https://git.saurik.com/apple/network_cmds.git/blobdiff_plain/7ba0088d6898d7fd2873f736f1f556673a8be855..fa34b6f5f32f696bb2fe92a877dfaec960fcd850:/netstat.tproj/inet6.c diff --git a/netstat.tproj/inet6.c b/netstat.tproj/inet6.c index 8fefbeb..a741196 100644 --- a/netstat.tproj/inet6.c +++ b/netstat.tproj/inet6.c @@ -1,3 +1,31 @@ +/* + * Copyright (c) 2008-2015 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 @@ -34,24 +62,17 @@ * $FreeBSD: src/usr.bin/netstat/inet6.c,v 1.3.2.9 2001/08/10 09:07:09 ru Exp $ */ -#ifndef lint -/* -static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94"; -*/ -#endif /* not lint */ - #ifdef INET6 #include #include #include #include -#include -#include #include #include #include #include +#include #include #include #include @@ -59,7 +80,6 @@ static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94"; #include #include #include -#include #include #include @@ -70,16 +90,13 @@ static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94"; #include #include "netstat.h" -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(__unused) #define __unused #endif -struct socket sockb; char *inet6name (struct in6_addr *); void inet6print (struct in6_addr *, int, char *, int); -static char ntop_buf[INET6_ADDRSTRLEN]; - static char *ip6nh[] = { "hop by hop", "ICMP", @@ -143,7 +160,7 @@ static char *ip6nh[] = { "no next header", "destination option", "#61", - "#62", + "mobility", "#63", "#64", "#65", @@ -339,16 +356,52 @@ static char *ip6nh[] = { "#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 addresses in a prefix advertised by the next-hop", + // IP6S_SRCRULE_5_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 +}; + /* * Dump IP6 statistics structure. */ void -ip6_stats(u_long off __unused, char *name, int af __unused) +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; @@ -359,140 +412,227 @@ ip6_stats(u_long off __unused, char *name, int af __unused) 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 p(f, m) if (ip6stat.f || sflag <= 1) \ - printf(m, (unsigned long long)ip6stat.f, plural(ip6stat.f)) -#define p1a(f, m) if (ip6stat.f || sflag <= 1) \ - printf(m, (unsigned long long)ip6stat.f) +#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%llu with size smaller than minimum\n"); - p1a(ip6s_tooshort, "\t%llu with data size < data length\n"); - p1a(ip6s_badoptions, "\t%llu with bad options\n"); - p1a(ip6s_badvers, "\t%llu with incorrect version number\n"); - p(ip6s_fragments, "\t%llu fragment%s received\n"); - p(ip6s_fragdropped, "\t%llu fragment%s dropped (dup or out of space)\n"); - p(ip6s_fragtimeout, "\t%llu fragment%s dropped after timeout\n"); - p(ip6s_fragoverflow, "\t%llu fragment%s that exceeded limit\n"); - p(ip6s_reassembled, "\t%llu packet%s reassembled ok\n"); - p(ip6s_delivered, "\t%llu packet%s for this host\n"); - p(ip6s_forward, "\t%llu packet%s forwarded\n"); - p(ip6s_cantforward, "\t%llu packet%s not forwardable\n"); - p(ip6s_redirectsent, "\t%llu redirect%s sent\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"); + 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"); + +#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%llu packet%s sent with fabricated ip header\n"); - p(ip6s_odropped, "\t%llu output packet%s dropped due to no bufs, etc.\n"); - p(ip6s_noroute, "\t%llu output packet%s discarded due to no route\n"); - p(ip6s_fragmented, "\t%llu output datagram%s fragmented\n"); - p(ip6s_ofragments, "\t%llu fragment%s created\n"); - p(ip6s_cantfrag, "\t%llu datagram%s that can't be fragmented\n"); - p(ip6s_badscope, "\t%llu packet%s that violated scope rules\n"); - p(ip6s_notmember, "\t%llu multicast packet%s which we don't join\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"); + +#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 (ip6stat.ip6s_nxthist[i] != 0) { + 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)ip6stat.ip6s_nxthist[i]); + (unsigned long long)IP6DIFF(ip6s_nxthist[i])); } printf("\tMbuf statistics:\n"); - printf("\t\t%llu one mbuf\n", (unsigned long long)ip6stat.ip6s_m1); + 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 (ip6stat.ip6s_m2m[i] != 0) { + 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)ip6stat.ip6s_m2m[i]); + (unsigned long long)IP6DIFF(ip6s_m2m[i])); } } printf("\t\t%llu one ext mbuf\n", - (unsigned long long)ip6stat.ip6s_mext1); + (unsigned long long)IP6DIFF(ip6s_mext1)); printf("\t\t%llu two or more ext mbuf\n", - (unsigned long long)ip6stat.ip6s_mext2m); - p(ip6s_exthdrtoolong, - "\t%llu packet%s whose headers are not continuous\n"); - p(ip6s_nogif, "\t%llu tunneling packet%s that can't find gif\n"); - p(ip6s_toomanyhdr, - "\t%llu packet%s discarded due to too may headers\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%llu node-local%s\n");\ + p(s, "\t\t\t%llu node-local%s\n");\ break;\ case 2:\ - p(s,"\t\t%llu link-local%s\n");\ + p(s,"\t\t\t%llu link-local%s\n");\ break;\ case 5:\ - p(s,"\t\t%llu site-local%s\n");\ + p(s,"\t\t\t%llu site-local%s\n");\ break;\ case 14:\ - p(s,"\t\t%llu global%s\n");\ + p(s,"\t\t\t%llu global%s\n");\ break;\ default:\ - printf("\t\t%llu addresses scope=%x\n",\ - (unsigned long long)ip6stat.s, i);\ + printf("\t\t\t%llu addresses scope=%x\n",\ + (unsigned long long)IP6DIFF(s), i);\ }\ } while (0); p(ip6s_sources_none, - "\t%llu failure%s of source address selection\n"); - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_sameif[i]) { + "\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("\tsource addresses on an outgoing I/F\n"); + 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 < 16; i++) { - if (ip6stat.ip6s_sources_otherif[i]) { + for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) { + if (IP6DIFF(ip6s_sources_otherif[i]) || 1) { if (first) { - printf("\tsource addresses on a non-outgoing I/F\n"); + 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 < 16; i++) { - if (ip6stat.ip6s_sources_samescope[i]) { + for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) { + if (IP6DIFF(ip6s_sources_samescope[i]) || 1) { if (first) { - printf("\tsource addresses of same scope\n"); + printf("\t\tsource addresses of same scope\n"); first = 0; } PRINT_SCOPESTAT(ip6s_sources_samescope[i], i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_otherscope[i]) { + for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) { + if (IP6DIFF(ip6s_sources_otherscope[i]) || 1) { if (first) { - printf("\tsource addresses of a different scope\n"); + printf("\t\tsource addresses of a different scope\n"); first = 0; } PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i); } } - for (first = 1, i = 0; i < 16; i++) { - if (ip6stat.ip6s_sources_deprecated[i]) { + for (first = 1, i = 0; i < SCOPE6_ID_MAX; i++) { + if (IP6DIFF(ip6s_sources_deprecated[i]) || 1) { if (first) { - printf("\tdeprecated source addresses\n"); + 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); - p1a(ip6s_forward_cachehit, "\t%llu forward cache hit\n"); - p1a(ip6s_forward_cachemiss, "\t%llu forward cache miss\n"); + for (first = 1, i = 0; i < IP6S_SRCRULE_COUNT; i++) { + if (IP6DIFF(ip6s_sources_rule[i]) || 1) { + if (first) { + printf("\t\tsource addresse 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_sources_skip_expensive_secondary_if, "\t\t%llu times%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 } @@ -515,7 +655,9 @@ ip6_ifstats(char *ifname) return; } - strcpy(ifr.ifr_name, ifname); + 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) { @@ -685,8 +827,8 @@ static char *icmp6names[] = { "echo", "echo reply", "multicast listener query", - "multicast listener report", - "multicast listener done", + "MLDv1 listener report", + "MLDv1 listener done", "router solicitation", "router advertisement", "neighbor solicitation", @@ -697,7 +839,7 @@ static char *icmp6names[] = { "node information reply", "inverse neighbor solicitation", "inverse neighbor advertisement", - "#143", + "MLDv2 listener report", "#144", "#145", "#146", @@ -816,8 +958,9 @@ static char *icmp6names[] = { * Dump ICMP6 statistics. */ void -icmp6_stats(u_long off __unused, char *name, int af __unused) +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]; @@ -832,11 +975,14 @@ icmp6_stats(u_long off __unused, char *name, int af __unused) 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 p(f, m) if (icmp6stat.f || sflag <= 1) \ - printf(m, (unsigned long long)icmp6stat.f, plural(icmp6stat.f)) -#define p_5(f, m) printf(m, (unsigned long long)icmp6stat.f) +#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, @@ -845,13 +991,13 @@ icmp6_stats(u_long off __unused, char *name, int af __unused) "\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 (icmp6stat.icp6s_outhist[i] != 0) { + 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)icmp6stat.icp6s_outhist[i]); + (unsigned long long)ICMP6DIFF(icp6s_outhist[i])); } #undef NELEM p(icp6s_badcode, "\t%llu message%s with bad code fields\n"); @@ -860,13 +1006,13 @@ icmp6_stats(u_long off __unused, char *name, int af __unused) 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 (icmp6stat.icp6s_inhist[i] != 0) { + 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)icmp6stat.icp6s_inhist[i]); + (unsigned long long)ICMP6DIFF(icp6s_inhist[i])); } #undef NELEM printf("\tHistogram of error messages to be generated:\n"); @@ -893,6 +1039,11 @@ icmp6_stats(u_long off __unused, char *name, int af __unused) 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"); + + if (interval > 0) + bcopy(&icmp6stat, &picmp6stat, len); + +#undef ICMP6DIFF #undef p #undef p_5 } @@ -913,7 +1064,9 @@ icmp6_ifstats(char *ifname) return; } - strcpy(ifr.ifr_name, ifname); + 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) { @@ -962,37 +1115,13 @@ icmp6_ifstats(char *ifname) #undef p } -/* - * Dump PIM statistics structure. - */ -void -pim6_stats(u_long off __unused, char *name, int af __unused) -{ - struct pim6stat pim6stat; - - if (off == 0) - return; - kread(off, (char *)&pim6stat, sizeof(pim6stat)); - printf("%s:\n", name); - -#define p(f, m) if (pim6stat.f || sflag <= 1) \ - printf(m, (unsigned long long)pim6stat.f, plural(pim6stat.f)) - p(pim6s_rcv_total, "\t%llu message%s received\n"); - p(pim6s_rcv_tooshort, "\t%llu message%s received with too few bytes\n"); - p(pim6s_rcv_badsum, "\t%llu message%s received with bad checksum\n"); - p(pim6s_rcv_badversion, "\t%llu message%s received with bad version\n"); - p(pim6s_rcv_registers, "\t%llu register%s received\n"); - p(pim6s_rcv_badregisters, "\t%llu bad register%s received\n"); - p(pim6s_snd_registers, "\t%llu register%s sent\n"); -#undef p -} - /* * Dump raw ip6 statistics structure. */ void -rip6_stats(u_long off __unused, char *name, int af __unused) +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]; @@ -1008,10 +1137,13 @@ rip6_stats(u_long off __unused, char *name, int af __unused) return; } + if (interval && vflag > 0) + print_time(); printf("%s:\n", name); -#define p(f, m) if (rip6stat.f || sflag <= 1) \ - printf(m, (unsigned long long)rip6stat.f, plural(rip6stat.f)) +#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 calcuration%s on inbound\n"); p(rip6s_badsum, "\t%llu message%s with bad checksum\n"); @@ -1020,14 +1152,19 @@ rip6_stats(u_long off __unused, char *name, int af __unused) "\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 = rip6stat.rip6s_ipackets - - rip6stat.rip6s_badsum - - rip6stat.rip6s_nosock - - rip6stat.rip6s_nosockmcast - - rip6stat.rip6s_fullsock; + 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 } @@ -1035,6 +1172,19 @@ rip6_stats(u_long off __unused, char *name, int af __unused) * 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)\ @@ -1044,7 +1194,7 @@ rip6_stats(u_long off __unused, char *name, int af __unused) else\ (ret) = getservbyport((int)(port), (proto));\ }; - +#endif void inet6print(struct in6_addr *in6, int port, char *proto, int numeric) { @@ -1052,15 +1202,15 @@ inet6print(struct in6_addr *in6, int port, char *proto, int numeric) char line[80], *cp; int width; - sprintf(line, "%.*s.", lflag ? 39 : + 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) - sprintf(cp, "%.8s", sp ? sp->s_name : "*"); + snprintf(cp, sizeof(line) - (cp - line), "%.8s", sp ? sp->s_name : "*"); else - sprintf(cp, "%d", ntohs((u_short)port)); + snprintf(cp, sizeof(line) - (cp - line), "%d", ntohs((u_short)port)); width = lflag ? 45 : Aflag ? 18 : 22; printf("%-*.*s ", width, width, line); } @@ -1079,12 +1229,15 @@ inet6name(struct in6_addr *in6p) 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) strcpy(domain, cp + 1); + (void) memmove(domain, cp + 1, strlen(cp + 1) + 1); else domain[0] = 0; } @@ -1099,13 +1252,29 @@ inet6name(struct in6_addr *in6p) } } if (IN6_IS_ADDR_UNSPECIFIED(in6p)) - strcpy(line, "*"); + strlcpy(line, "*", sizeof(line)); else if (cp) - strcpy(line, cp); - else - sprintf(line, "%s", - inet_ntop(AF_INET6, (void *)in6p, ntop_buf, - sizeof(ntop_buf))); + 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*/