Import NetBSD netstat(1)

The port forces the use of sysctl(7), as obtaining information through
KVM is not and will never be viable.  The sysctl mode of netstat(1) is
currently somewhat limited and buggy, though.  We fix a few minimal
issues, but more improvements will have to come from NetBSD reimports.

Some of netstat(1)'s views are currently not supported by the
operating system.  Later improvements on this point will not require
changes to the imported code, though.

Change-Id: If74a6811f0fc81bd1ecc31010a28379b14b2a0eb
This commit is contained in:
David van Moolenbroek 2017-02-15 12:35:47 +00:00
parent 483e595557
commit 66dfcc8533
26 changed files with 8394 additions and 1 deletions

View File

@ -454,6 +454,7 @@
./usr/bin/netpgp minix-base crypto
./usr/bin/netpgpkeys minix-base crypto
./usr/bin/netpgpverify minix-base crypto
./usr/bin/netstat minix-base
./usr/bin/newgrp minix-base
./usr/bin/nice minix-base
./usr/bin/nl minix-base

View File

@ -360,6 +360,7 @@
./usr/libdata/debug/usr/bin/netpgp.debug minix-debug debug
./usr/libdata/debug/usr/bin/netpgpkeys.debug minix-debug debug
./usr/libdata/debug/usr/bin/netpgpverify.debug minix-debug debug
./usr/libdata/debug/usr/bin/netstat.debug minix-debug debug
./usr/libdata/debug/usr/bin/newgrp.debug minix-debug debug
./usr/libdata/debug/usr/bin/nice.debug minix-debug debug
./usr/libdata/debug/usr/bin/nl.debug minix-debug debug

View File

@ -238,6 +238,7 @@
./usr/man/man1/netpgp.1 minix-man crypto
./usr/man/man1/netpgpkeys.1 minix-man crypto
./usr/man/man1/netpgpverify.1 minix-man crypto
./usr/man/man1/netstat.1 minix-man
./usr/man/man1/newfs_mfs.1 minix-man
./usr/man/man1/newgrp.1 minix-man
./usr/man/man1/nice.1 minix-man

View File

@ -19,7 +19,7 @@ SUBDIR= asa \
machine make man menuc mesg \
mkcsmapper mkdep mkesdb mkfifo mklocale mkstr mktemp \
msgc \
nbperf newgrp nice nl nohup \
nbperf netstat newgrp nice nl nohup \
pagesize passwd paste patch pathchk pr \
printenv printf pwhash \
renice rev rsh \

46
usr.bin/netstat/Makefile Normal file
View File

@ -0,0 +1,46 @@
# $NetBSD: Makefile,v 1.43 2015/06/06 13:48:37 joerg Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/12/93
.include <bsd.own.mk>
USE_FORT?= yes # setgid
RUMPPRG=netstat
#SRCS= atalk.c bpf.c fast_ipsec.c if.c inet.c inet6.c
SRCS= atalk.c bpf.c if.c inet.c inet6.c \
main.c mbuf.c mroute.c mroute6.c pfkey.c pfsync.c route.c \
unix.c vtw.c rtutil.c
.if !defined(__MINIX)
BINGRP= kmem
BINMODE=2555
.endif # !defined(__MINIX)
LDADD= -lutil -lkvm
DPADD= ${LIBUTIL} ${LIBKVM}
.if !defined(__MINIX)
CPPFLAGS+= -DIPSEC -I${.CURDIR}
.else # defined(__MINIX)
CPPFLAGS+= -I${.CURDIR}
.endif # defined(__MINIX)
CPPFLAGS+= -I${NETBSDSRCDIR}/sys/dist/pf
CPPFLAGS+= -I${NETBSDSRCDIR}/sbin/route
.PATH: ${.CURDIR}/../../lib/libc/gen
.PATH: ${.CURDIR}/../../lib/libc/net
.PATH: ${.CURDIR}/../../sbin/route
CPPFLAGS+= -DRUMP_ACTION
RUMPSRCS+= sysctlbyname.c sysctlgetmibinfo.c sysctlnametomib.c
RUMPSRCS+= if_indextoname.c getifaddrs.c getnameinfo.c
.if (${USE_INET6} != "no")
CPPFLAGS+= -DINET6
.endif
.if defined(__MINIX)
# FIXME: compilation on ARM fails on a format string warning because of a
# mismatch between the PRIxPTR format and the uintptr_t type, which should not
# be possible. This is a bug in the ARM port, but I have no idea how to solve
# that. For now, simply do not fail the build on this error. --dcvmoole
CPPFLAGS+= -Wno-error=format
.endif # defined(__MINIX)
.include <bsd.prog.mk>

314
usr.bin/netstat/atalk.c Normal file
View File

@ -0,0 +1,314 @@
/* $NetBSD: atalk.c,v 1.16 2015/06/06 13:08:31 joerg 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from @(#)atalk.c 1.1 (Whistle) 6/6/96";
#else
__RCSID("$NetBSD: atalk.c,v 1.16 2015/06/06 13:08:31 joerg Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/sysctl.h>
#include <net/route.h>
#include <net/if.h>
#include <netinet/tcp_fsm.h>
#include <netatalk/at.h>
#include <netatalk/ddp_var.h>
#include <err.h>
#include <nlist.h>
#include <kvm.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "netstat.h"
struct ddpcb ddpcb;
struct socket sockb;
static int first = 1;
/*
* Print a summary of connections related to a Network Systems
* protocol. For XXX, also give state of connection.
* Listening processes (aflag) are suppressed unless the
* -a (all) flag is specified.
*/
static const char *
at_pr_net(const struct sockaddr_at *sat, int numeric)
{
static char mybuf[50];
if (!numeric) {
switch (sat->sat_addr.s_net) {
case 0xffff:
return "????";
case ATADDR_ANYNET:
return ("*");
}
}
(void)snprintf(mybuf, sizeof(mybuf), "%hu", ntohs(sat->sat_addr.s_net));
return (mybuf);
}
static const char *
at_pr_host(const struct sockaddr_at *sat, int numeric)
{
static char mybuf[50];
if (!numeric) {
switch (sat->sat_addr.s_node) {
case ATADDR_BCAST:
return "bcast";
case ATADDR_ANYNODE:
return ("*");
}
}
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int)sat->sat_addr.s_node);
return (mybuf);
}
static const char *
at_pr_port(const struct sockaddr_at *sat)
{
static char mybuf[50];
switch (sat->sat_port) {
case ATADDR_ANYPORT:
return ("*");
case 0xff:
return "????";
default:
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int)sat->sat_port);
return (mybuf);
}
}
static const char *
at_pr_range(const struct sockaddr_at *sat)
{
static char mybuf[50];
if (sat->sat_range.r_netrange.nr_firstnet
!= sat->sat_range.r_netrange.nr_lastnet) {
(void)snprintf(mybuf, sizeof(mybuf), "%d-%d",
ntohs(sat->sat_range.r_netrange.nr_firstnet),
ntohs(sat->sat_range.r_netrange.nr_lastnet));
} else {
(void)snprintf(mybuf, sizeof(mybuf), "%d",
ntohs(sat->sat_range.r_netrange.nr_firstnet));
}
return (mybuf);
}
/* what == 0 for addr only == 3
* 1 for net
* 2 for host
* 4 for port
* 8 for numeric only
*/
const char *
atalk_print(const struct sockaddr *sa, int what)
{
const struct sockaddr_at *sat = (const struct sockaddr_at *) sa;
static char mybuf[50];
int numeric = (what & 0x08);
mybuf[0] = 0;
switch (what & 0x13) {
case 0:
mybuf[0] = 0;
break;
case 1:
(void)snprintf(mybuf, sizeof(mybuf), "%s",
at_pr_net(sat, numeric));
break;
case 2:
(void)snprintf(mybuf, sizeof(mybuf), "%s",
at_pr_host(sat, numeric));
break;
case 3:
(void)snprintf(mybuf, sizeof(mybuf), "%s.%s",
at_pr_net(sat, numeric),
at_pr_host(sat, numeric));
break;
case 0x10:
(void)snprintf(mybuf, sizeof(mybuf), "%s", at_pr_range(sat));
}
if (what & 4) {
(void)snprintf(mybuf + strlen(mybuf),
sizeof(mybuf) - strlen(mybuf), ".%s", at_pr_port(sat));
}
return (mybuf);
}
const char *
atalk_print2(const struct sockaddr *sa, const struct sockaddr *mask, int what)
{
int n, l;
static char buf[100];
const struct sockaddr_at *sat1, *sat2;
struct sockaddr_at thesockaddr;
struct sockaddr *sa2;
sat1 = (const struct sockaddr_at *) sa;
sat2 = (const struct sockaddr_at *) mask;
sa2 = (struct sockaddr *) & thesockaddr;
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net &
sat2->sat_addr.s_net;
n = snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 | (what & 8)));
if (n >= (int)sizeof(buf))
n = sizeof(buf) - 1;
else if (n == -1)
n = 0; /* What else can be done ? */
if (sat2->sat_addr.s_net != 0xFFFF) {
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net |
~sat2->sat_addr.s_net;
l = snprintf(buf + n, sizeof(buf) - n,
"-%s", atalk_print(sa2, 1 | (what & 8)));
if (l >= (int)(sizeof(buf) - n))
l = sizeof(buf) - n - 1;
if (l > 0)
n += l;
}
if (what & 2) {
l = snprintf(buf + n, sizeof(buf) - n, ".%s",
atalk_print(sa, what & (~1)));
if (l >= (int)(sizeof(buf) - n))
l = sizeof(buf) - n - 1;
if (l > 0)
n += l;
}
return (buf);
}
void
atalkprotopr(u_long off, const char *name)
{
struct ddpcb *next;
struct ddpcb *initial;
int width = 22;
if (off == 0)
return;
if (kread(off, (char *)&initial, sizeof(struct ddpcb *)) < 0)
return;
for (next = initial; next != NULL;) {
u_long ppcb = (u_long)next;
if (kread((u_long)next, (char *)&ddpcb, sizeof(ddpcb)) < 0)
return;
next = ddpcb.ddp_next;
#if 0
if (!aflag && atalk_nullhost(ddpcb.ddp_lsat)) {
continue;
}
#endif
if (kread((u_long)ddpcb.ddp_socket,
(char *)&sockb, sizeof(sockb)) < 0)
return;
if (first) {
printf("Active ATALK connections");
if (aflag)
printf(" (including servers)");
putchar('\n');
if (Aflag) {
width = 18;
printf("%-8.8s ", "PCB");
}
printf("%-5.5s %-6.6s %-6.6s %*.*s %*.*s %s\n",
"Proto", "Recv-Q", "Send-Q",
-width, width, "Local Address",
-width, width, "Foreign Address", "(state)");
first = 0;
}
if (Aflag)
printf("%8lx ", ppcb);
printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc,
sockb.so_snd.sb_cc);
printf(" %*.*s", -width, width,
atalk_print((struct sockaddr *)&ddpcb.ddp_lsat, 7));
printf(" %*.*s", -width, width,
atalk_print((struct sockaddr *)&ddpcb.ddp_fsat, 7));
putchar('\n');
}
}
#define ANY(x,y,z) \
((sflag==1 || (x)) ? printf("\t%llu %s%s%s\n",(unsigned long long)x,y,plural(x),z) : 0)
/*
* Dump DDP statistics structure.
*/
void
ddp_stats(u_long off, const char *name)
{
uint64_t ddpstat[DDP_NSTATS];
if (use_sysctl) {
size_t size = sizeof(ddpstat);
if (sysctlbyname("net.atalk.ddp.stats", ddpstat, &size,
NULL, 0) == -1)
return;
} else {
warnx("%s stats not available via KVM.", name);
return;
}
printf("%s:\n", name);
ANY(ddpstat[DDP_STAT_SHORT], "packet", " with short headers ");
ANY(ddpstat[DDP_STAT_LONG], "packet", " with long headers ");
ANY(ddpstat[DDP_STAT_NOSUM], "packet", " with no checksum ");
ANY(ddpstat[DDP_STAT_TOOSHORT], "packet", " too short ");
ANY(ddpstat[DDP_STAT_BADSUM], "packet", " with bad checksum ");
ANY(ddpstat[DDP_STAT_TOOSMALL], "packet", " with not enough data ");
ANY(ddpstat[DDP_STAT_FORWARD], "packet", " forwarded ");
ANY(ddpstat[DDP_STAT_ENCAP], "packet", " encapsulated ");
ANY(ddpstat[DDP_STAT_CANTFORWARD], "packet", " rcvd for unreachable dest ");
ANY(ddpstat[DDP_STAT_NOSOCKSPACE], "packet", " dropped due to no socket space ");
}
#undef ANY

175
usr.bin/netstat/bpf.c Normal file
View File

@ -0,0 +1,175 @@
/* $NetBSD: bpf.c,v 1.11 2012/12/14 08:15:44 msaitoh Exp $ */
/*
* Copyright (c) 2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Rui Paulo.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <kvm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <net/bpfdesc.h>
#include <net/bpf.h>
#include "netstat.h"
#include "prog_ops.h"
void
bpf_stats(void)
{
struct bpf_stat bpf_s;
size_t len = sizeof(bpf_s);
if (use_sysctl) {
if (sysctlbyname("net.bpf.stats", &bpf_s, &len, NULL, 0) == -1)
err(1, "net.bpf.stats");
printf("bpf:\n");
printf("\t%" PRIu64 " total packets received\n",
bpf_s.bs_recv);
printf("\t%" PRIu64 " total packets captured\n",
bpf_s.bs_capt);
printf("\t%" PRIu64 " total packets dropped\n",
bpf_s.bs_drop);
} else {
warnx("BPF stats not available via KVM.");
}
}
void
bpf_dump(const char *bpfif)
{
struct bpf_d_ext *dpe;
if (use_sysctl) {
int name[CTL_MAXNAME], rc;
size_t i, sz, szproc;
u_int namelen;
void *v;
struct kinfo_proc2 p;
/* adapted from sockstat.c by Andrew Brown */
sz = CTL_MAXNAME;
if (sysctlnametomib("net.bpf.peers", &name[0], &sz) == -1)
err(1, "sysctlnametomib: net.bpf.peers");
namelen = sz;
name[namelen++] = sizeof(*dpe);
name[namelen++] = INT_MAX;
v = NULL;
sz = 0;
do {
rc = prog_sysctl(&name[0], namelen,
v, &sz, NULL, 0);
if (rc == -1 && errno != ENOMEM)
err(1, "sysctl: net.bpf.peers");
if (rc == -1 && v != NULL) {
free(v);
v = NULL;
}
if (v == NULL) {
v = malloc(sz);
rc = -1;
}
if (v == NULL)
err(1, "malloc");
} while (rc == -1);
dpe = v;
puts("Active BPF peers\nPID\tInt\tRecv Drop Capt" \
" Flags Bufsize Comm");
#define BPFEXT(entry) dpe->entry
for (i = 0; i < (sz / sizeof(*dpe)); i++, dpe++) {
if (bpfif &&
strncmp(BPFEXT(bde_ifname), bpfif, IFNAMSIZ))
continue;
printf("%-7d ", BPFEXT(bde_pid));
printf("%-7s ",
(BPFEXT(bde_ifname)[0] == '\0') ? "-" :
BPFEXT(bde_ifname));
printf("%-8" PRIu64 " %-8" PRIu64 " %-8" PRIu64 " ",
BPFEXT(bde_rcount), BPFEXT(bde_dcount),
BPFEXT(bde_ccount));
switch (BPFEXT(bde_state)) {
case BPF_IDLE:
printf("I");
break;
case BPF_WAITING:
printf("W");
break;
case BPF_TIMED_OUT:
printf("T");
break;
default:
printf("-");
break;
}
printf("%c", BPFEXT(bde_promisc) ? 'P' : '-');
printf("%c", BPFEXT(bde_immediate) ? 'R' : '-');
printf("%c", BPFEXT(bde_seesent) ? 'S' : '-');
printf("%c", BPFEXT(bde_hdrcmplt) ? 'H' : '-');
printf(" %-8d ", BPFEXT(bde_bufsize));
szproc = sizeof(p);
namelen = 0;
name[namelen++] = CTL_KERN;
name[namelen++] = KERN_PROC2;
name[namelen++] = KERN_PROC_PID;
name[namelen++] = BPFEXT(bde_pid);
name[namelen++] = szproc;
name[namelen++] = 1;
if (prog_sysctl(&name[0], namelen, &p, &szproc,
NULL, 0) == -1)
printf("-\n");
else
printf("%s\n", p.p_comm);
#undef BPFEXT
}
free(v);
} else {
/* XXX */
errx(1, "bpf_dump not implemented using kvm");
}
}

View File

@ -0,0 +1,307 @@
/* $NetBSD: fast_ipsec.c,v 1.20 2013/04/15 21:20:39 christos Exp $ */
/* $FreeBSD: src/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $ */
/*-
* Copyright (c) 2003, 2004 Jonathan Stone
* Copyright (c) 2002, 2003 Sam Leffler, Errno Consulting
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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/tools/tools/crypto/ipsecstats.c,v 1.1.4.1 2003/06/03 00:13:13 sam Exp $
*/
#include <sys/cdefs.h>
#ifndef lint
#ifdef __NetBSD__
__RCSID("$NetBSD: fast_ipsec.c,v 1.20 2013/04/15 21:20:39 christos Exp $");
#endif
#endif /* not lint*/
/* Kernel headers required, but not included, by netstat.h */
#include <sys/types.h>
#include <sys/socket.h>
/* Kernel headers for sysctl(3). */
#include <sys/param.h>
#include <sys/sysctl.h>
/* Kernel headers for FAST_IPSEC statistics */
#include <net/pfkeyv2.h>
#include <netipsec/esp_var.h>
#include <netipsec/ah_var.h>
#include <netipsec/ipip_var.h>
#include <netipsec/ipcomp_var.h>
#include <netipsec/ipsec_var.h>
#include <machine/int_fmtio.h>
#include <kvm.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "netstat.h"
/*
* Table-driven mapping from SADB algorithm codes to string names.
*/
struct alg {
int a;
const char *name;
};
static const struct alg aalgs[] = {
{ SADB_AALG_NONE, "none", },
{ SADB_AALG_MD5HMAC, "hmac-md5", },
{ SADB_AALG_SHA1HMAC, "hmac-sha1", },
{ SADB_X_AALG_MD5, "md5", },
{ SADB_X_AALG_SHA, "sha", },
{ SADB_X_AALG_NULL, "null", },
{ SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
{ SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
{ SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
{ SADB_X_AALG_AES128GMAC, "aes-128-gmac", },
{ SADB_X_AALG_AES192GMAC, "aes-192-gmac", },
{ SADB_X_AALG_AES256GMAC, "aes-256-gmac", },
};
static const struct alg espalgs[] = {
{ SADB_EALG_NONE, "none", },
{ SADB_EALG_DESCBC, "des-cbc", },
{ SADB_EALG_3DESCBC, "3des-cbc", },
{ SADB_EALG_NULL, "null", },
{ SADB_X_EALG_CAST128CBC, "cast128-cbc", },
{ SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
{ SADB_X_EALG_RIJNDAELCBC, "aes-cbc", },
{ SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
{ SADB_X_EALG_AESCTR, "aes-ctr", },
{ SADB_X_EALG_AESGCM16, "aes-gcm-16", },
{ SADB_X_EALG_AESGMAC, "aes-gmac", },
};
static const struct alg ipcompalgs[] = {
{ SADB_X_CALG_NONE, "none", },
{ SADB_X_CALG_OUI, "oui", },
{ SADB_X_CALG_DEFLATE, "deflate", },
{ SADB_X_CALG_LZS, "lzs", },
};
#define N(a) (sizeof(a)/sizeof(a[0]))
static const char*
algname(int a, const struct alg algs[], int nalgs)
{
static char buf[80];
int i;
for (i = 0; i < nalgs; i++)
if (algs[i].a == a)
return algs[i].name;
snprintf(buf, sizeof(buf), "alg#%u", a);
return buf;
}
/*
* Print the fast_ipsec statistics.
* Since NetBSD's netstat(1) seems not to find us for "netstat -s",
* but does(?) find KAME, be prepared to be called explicitly from
* netstat's main program for "netstat -s"; but silently do nothing
* if that happens when we are running on KAME IPsec.
*/
void
fast_ipsec_stats(u_long off, const char *name)
{
uint64_t ipsecstats[IPSEC_NSTATS];
uint64_t ahstats[AH_NSTATS];
uint64_t espstats[ESP_NSTATS];
uint64_t ipcs[IPCOMP_NSTATS];
uint64_t ipips[IPIP_NSTATS];
int status;
size_t slen;
int i;
if (! use_sysctl) {
warnx("IPsec stats not available via KVM.");
return;
}
memset(ipsecstats, 0, sizeof(ipsecstats));
memset(ahstats, 0, sizeof(ahstats));
memset(espstats, 0, sizeof(espstats));
memset(ipcs, 0, sizeof(ipcs));
memset(ipips, 0, sizeof(ipips));
slen = sizeof(ipsecstats);
status = sysctlbyname("net.inet.ipsec.ipsecstats", ipsecstats, &slen,
NULL, 0);
if (status < 0) {
if (errno == ENOENT)
return;
if (errno != ENOMEM)
err(1, "net.inet.ipsec.ipsecstats");
}
slen = sizeof (ahstats);
status = sysctlbyname("net.inet.ah.ah_stats", ahstats, &slen, NULL, 0);
if (status < 0 && errno != ENOMEM)
err(1, "net.inet.ah.ah_stats");
slen = sizeof (espstats);
status = sysctlbyname("net.inet.esp.esp_stats", espstats, &slen, NULL, 0);
if (status < 0 && errno != ENOMEM)
err(1, "net.inet.esp.esp_stats");
slen = sizeof(ipcs);
status = sysctlbyname("net.inet.ipcomp.ipcomp_stats", ipcs, &slen, NULL, 0);
if (status < 0 && errno != ENOMEM)
err(1, "net.inet.ipcomp.ipcomp_stats");
slen = sizeof(ipips);
status = sysctlbyname("net.inet.ipip.ipip_stats", ipips, &slen, NULL, 0);
if (status < 0 && errno != ENOMEM)
err(1, "net.inet.ipip.ipip_stats");
printf("(Fast) IPsec:\n");
#define STAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" " fmt "\n", x)
if (ipsecstats[IPSEC_STAT_IN_POLVIO]+ipsecstats[IPSEC_STAT_OUT_POLVIO])
printf("\t%"PRIu64" policy violations: %"PRIu64" input %"PRIu64" output\n",
ipsecstats[IPSEC_STAT_IN_POLVIO] + ipsecstats[IPSEC_STAT_OUT_POLVIO],
ipsecstats[IPSEC_STAT_IN_POLVIO], ipsecstats[IPSEC_STAT_OUT_POLVIO]);
STAT(ipsecstats[IPSEC_STAT_OUT_NOSA], "no SA found (output)");
STAT(ipsecstats[IPSEC_STAT_OUT_NOMEM], "no memory available (output)");
STAT(ipsecstats[IPSEC_STAT_OUT_NOROUTE], "no route available (output)");
STAT(ipsecstats[IPSEC_STAT_OUT_INVAL], "generic errors (output)");
STAT(ipsecstats[IPSEC_STAT_OUT_BUNDLESA], "bundled SA processed (output)");
STAT(ipsecstats[IPSEC_STAT_SPDCACHELOOKUP], "SPD cache lookups");
STAT(ipsecstats[IPSEC_STAT_SPDCACHEMISS], "SPD cache misses");
#undef STAT
printf("\n");
printf("IPsec ah:\n");
#define AHSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" ah " fmt "\n", x)
AHSTAT(ahstats[AH_STAT_INPUT], "input packets processed");
AHSTAT(ahstats[AH_STAT_OUTPUT], "output packets processed");
AHSTAT(ahstats[AH_STAT_HDROPS], "headers too short");
AHSTAT(ahstats[AH_STAT_NOPF], "headers for unsupported address family");
AHSTAT(ahstats[AH_STAT_NOTDB], "packets with no SA");
AHSTAT(ahstats[AH_STAT_BADKCR], "packets dropped by crypto returning NULL mbuf");
AHSTAT(ahstats[AH_STAT_BADAUTH], "packets with bad authentication");
AHSTAT(ahstats[AH_STAT_NOXFORM], "packets with no xform");
AHSTAT(ahstats[AH_STAT_QFULL], "packets dropped due to queue full");
AHSTAT(ahstats[AH_STAT_WRAP], "packets dropped for replay counter wrap");
AHSTAT(ahstats[AH_STAT_REPLAY], "packets dropped for possible replay");
AHSTAT(ahstats[AH_STAT_BADAUTHL],"packets dropped for bad authenticator length");
AHSTAT(ahstats[AH_STAT_INVALID], "packets with an invalid SA");
AHSTAT(ahstats[AH_STAT_TOOBIG], "packets too big");
AHSTAT(ahstats[AH_STAT_PDROPS], "packets blocked due to policy");
AHSTAT(ahstats[AH_STAT_CRYPTO], "failed crypto requests");
AHSTAT(ahstats[AH_STAT_TUNNEL], "tunnel sanity check failures");
printf("\tah histogram:\n");
for (i = 0; i < AH_ALG_MAX; i++)
if (ahstats[AH_STAT_HIST + i])
printf("\t\tah packets with %s: %"PRIu64"\n"
, algname(i, aalgs, N(aalgs))
, ahstats[AH_STAT_HIST + i]
);
AHSTAT(ahstats[AH_STAT_IBYTES], "bytes received");
AHSTAT(ahstats[AH_STAT_OBYTES], "bytes transmitted");
#undef AHSTAT
printf("\n");
printf("IPsec esp:\n");
#define ESPSTAT(x,fmt) if ((x) || sflag <= 1) printf("\t%"PRIu64" esp " fmt "\n", x)
ESPSTAT(espstats[ESP_STAT_INPUT],"input packets processed");
ESPSTAT(espstats[ESP_STAT_OUTPUT],"output packets processed");
ESPSTAT(espstats[ESP_STAT_HDROPS],"headers too short");
ESPSTAT(espstats[ESP_STAT_NOPF], "headers for unsupported address family");
ESPSTAT(espstats[ESP_STAT_NOTDB],"packets with no SA");
ESPSTAT(espstats[ESP_STAT_BADKCR],"packets dropped by crypto returning NULL mbuf");
ESPSTAT(espstats[ESP_STAT_QFULL],"packets dropped due to queue full");
ESPSTAT(espstats[ESP_STAT_NOXFORM],"packets with no xform");
ESPSTAT(espstats[ESP_STAT_BADILEN],"packets with bad ilen");
ESPSTAT(espstats[ESP_STAT_BADENC],"packets with bad encryption");
ESPSTAT(espstats[ESP_STAT_BADAUTH],"packets with bad authentication");
ESPSTAT(espstats[ESP_STAT_WRAP], "packets dropped for replay counter wrap");
ESPSTAT(espstats[ESP_STAT_REPLAY],"packets dropped for possible replay");
ESPSTAT(espstats[ESP_STAT_INVALID],"packets with an invalid SA");
ESPSTAT(espstats[ESP_STAT_TOOBIG],"packets too big");
ESPSTAT(espstats[ESP_STAT_PDROPS],"packets blocked due to policy");
ESPSTAT(espstats[ESP_STAT_CRYPTO],"failed crypto requests");
ESPSTAT(espstats[ESP_STAT_TUNNEL],"tunnel sanity check failures");
printf("\tesp histogram:\n");
for (i = 0; i < ESP_ALG_MAX; i++)
if (espstats[ESP_STAT_HIST + i])
printf("\t\tesp packets with %s: %"PRIu64"\n"
, algname(i, espalgs, N(espalgs))
, espstats[ESP_STAT_HIST + i]
);
ESPSTAT(espstats[ESP_STAT_IBYTES], "bytes received");
ESPSTAT(espstats[ESP_STAT_OBYTES], "bytes transmitted");
#undef ESPSTAT
printf("IPsec ipip:\n");
#define IPIPSTAT(x,fmt) \
if ((x) || sflag <= 1) printf("\t%"PRIu64" ipip " fmt "\n", x)
IPIPSTAT(ipips[IPIP_STAT_IPACKETS],"total input packets");
IPIPSTAT(ipips[IPIP_STAT_OPACKETS],"total output packets");
IPIPSTAT(ipips[IPIP_STAT_HDROPS],"packets too short for header length");
IPIPSTAT(ipips[IPIP_STAT_QFULL],"packets dropped due to queue full");
IPIPSTAT(ipips[IPIP_STAT_PDROPS],"packets blocked due to policy");
IPIPSTAT(ipips[IPIP_STAT_SPOOF],"IP spoofing attempts");
IPIPSTAT(ipips[IPIP_STAT_FAMILY],"protocol family mismatched");
IPIPSTAT(ipips[IPIP_STAT_UNSPEC],"missing tunnel-endpoint address");
IPIPSTAT(ipips[IPIP_STAT_IBYTES],"input bytes received");
IPIPSTAT(ipips[IPIP_STAT_OBYTES],"output bytes processed");
#undef IPIPSTAT
printf("IPsec ipcomp:\n");
#define IPCOMP(x,fmt) \
if ((x) || sflag <= 1) printf("\t%"PRIu64" ipcomp " fmt "\n", x)
IPCOMP(ipcs[IPCOMP_STAT_HDROPS],"packets too short for header length");
IPCOMP(ipcs[IPCOMP_STAT_NOPF], "protocol family not supported");
IPCOMP(ipcs[IPCOMP_STAT_NOTDB], "packets with no SA");
IPCOMP(ipcs[IPCOMP_STAT_BADKCR],"packets dropped by crypto returning NULL mbuf");
IPCOMP(ipcs[IPCOMP_STAT_QFULL], "queue full");
IPCOMP(ipcs[IPCOMP_STAT_NOXFORM],"no support for transform");
IPCOMP(ipcs[IPCOMP_STAT_WRAP], "packets dropped for replay counter wrap");
IPCOMP(ipcs[IPCOMP_STAT_INPUT], "input IPcomp packets");
IPCOMP(ipcs[IPCOMP_STAT_OUTPUT],"output IPcomp packets");
IPCOMP(ipcs[IPCOMP_STAT_INVALID],"packets with an invalid SA");
IPCOMP(ipcs[IPCOMP_STAT_TOOBIG],"packets decompressed as too big");
IPCOMP(ipcs[IPCOMP_STAT_MINLEN], "packets too short to be compressed");
IPCOMP(ipcs[IPCOMP_STAT_USELESS],"packet for which compression was useless");
IPCOMP(ipcs[IPCOMP_STAT_PDROPS],"packets blocked due to policy");
IPCOMP(ipcs[IPCOMP_STAT_CRYPTO],"failed crypto requests");
printf("\tIPcomp histogram:\n");
for (i = 0; i < IPCOMP_ALG_MAX; i++)
if (ipcs[IPCOMP_STAT_HIST + i])
printf("\t\tIPcomp packets with %s: %"PRIu64"\n"
, algname(i, ipcompalgs, N(ipcompalgs))
, ipcs[IPCOMP_STAT_HIST + i]
);
IPCOMP(ipcs[IPCOMP_STAT_IBYTES],"input bytes");
IPCOMP(ipcs[IPCOMP_STAT_OBYTES],"output bytes");
#undef IPCOMP
}

1050
usr.bin/netstat/if.c Normal file

File diff suppressed because it is too large Load Diff

1037
usr.bin/netstat/inet.c Normal file

File diff suppressed because it is too large Load Diff

1533
usr.bin/netstat/inet6.c Normal file

File diff suppressed because it is too large Load Diff

883
usr.bin/netstat/main.c Normal file
View File

@ -0,0 +1,883 @@
/* $NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $ */
/*
* Copyright (c) 1983, 1988, 1993
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\
Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94";
#else
__RCSID("$NetBSD: main.c,v 1.95 2014/11/12 03:34:59 christos Exp $");
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/file.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <kvm.h>
#include <limits.h>
#include <netdb.h>
#include <nlist.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#include "rtutil.h"
#include "prog_ops.h"
struct nlist nl[] = {
#define N_MBSTAT 0
{ "_mbstat", 0, 0, 0, 0 },
#define N_IPSTAT 1
{ "_ipstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_TCBTABLE 2
{ "_tcbtable", 0, 0, 0, 0 },
#define N_TCPSTAT 3
{ "_tcpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_UDBTABLE 4
{ "_udbtable", 0, 0, 0, 0 },
#define N_UDPSTAT 5
{ "_udpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_IFNET_LIST 6
{ "_ifnet_list", 0, 0, 0, 0 },
#define N_ICMPSTAT 7
{ "_icmpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_RTSTAT 8
{ "_rtstat", 0, 0, 0, 0 },
#define N_UNIXSW 9
{ "_unixsw", 0, 0, 0, 0 },
#define N_RTREE 10
{ "_rt_tables", 0, 0, 0, 0 },
#define N_NFILE 11
{ "_nfile", 0, 0, 0, 0 },
#define N_IGMPSTAT 12
{ "_igmpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_MRTPROTO 13
{ "_ip_mrtproto", 0, 0, 0, 0 },
#define N_MRTSTAT 14
{ "_mrtstat", 0, 0, 0, 0 },
#define N_MFCHASHTBL 15
{ "_mfchashtbl", 0, 0, 0, 0 },
#define N_MFCHASH 16
{ "_mfchash", 0, 0, 0, 0 },
#define N_VIFTABLE 17
{ "_viftable", 0, 0, 0, 0 },
#define N_MSIZE 18
{ "_msize", 0, 0, 0, 0 },
#define N_MCLBYTES 19
{ "_mclbytes", 0, 0, 0, 0 },
#define N_DDPSTAT 20
{ "_ddpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_DDPCB 21
{ "_ddpcb", 0, 0, 0, 0 },
#define N_MBPOOL 22
{ "_mbpool", 0, 0, 0, 0 },
#define N_MCLPOOL 23
{ "_mclpool", 0, 0, 0, 0 },
#define N_IP6STAT 24
{ "_ip6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_TCP6STAT 25
{ "_tcp6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_UDP6STAT 26
{ "_udp6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_ICMP6STAT 27
{ "_icmp6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_IPSECSTAT 28
{ "_ipsecstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_IPSEC6STAT 29
{ "_ipsec6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_PIM6STAT 30
{ "_pim6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_MRT6PROTO 31
{ "_ip6_mrtproto", 0, 0, 0, 0 },
#define N_MRT6STAT 32
{ "_mrt6stat", 0, 0, 0, 0 },
#define N_MF6CTABLE 33
{ "_mf6ctable", 0, 0, 0, 0 },
#define N_MIF6TABLE 34
{ "_mif6table", 0, 0, 0, 0 },
#define N_PFKEYSTAT 35
{ "_pfkeystat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_ARPSTAT 36
{ "_arpstat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_RIP6STAT 37
{ "_rip6stat", 0, 0, 0, 0 }, /* not available via kvm */
#define N_ARPINTRQ 38
{ "_arpintrq", 0, 0, 0, 0 },
#define N_IPINTRQ 39
{ "_ipintrq", 0, 0, 0, 0 },
#define N_IP6INTRQ 40
{ "_ip6intrq", 0, 0, 0, 0 },
#define N_ATINTRQ1 41
{ "_atintrq1", 0, 0, 0, 0 },
#define N_ATINTRQ2 42
{ "_atintrq2", 0, 0, 0, 0 },
#define N_NSINTRQ 43
{ "_nsintrq", 0, 0, 0, 0 },
#define N_LLCINTRQ 44
{ "_llcintrq", 0, 0, 0, 0 },
#define N_HDINTRQ 45
{ "_hdintrq", 0, 0, 0, 0 },
#define N_NATMINTRQ 46
{ "_natmintrq", 0, 0, 0, 0 },
#define N_PPPOEDISCINQ 47
{ "_ppoediscinq", 0, 0, 0, 0 },
#define N_PPPOEINQ 48
{ "_ppoeinq", 0, 0, 0, 0 },
#define N_PKINTRQ 49
{ "_pkintrq", 0, 0, 0, 0 },
#define N_HARDCLOCK_TICKS 50
{ "_hardclock_ticks", 0, 0, 0, 0 },
#define N_PIMSTAT 51
{ "_pimstat", 0, 0, 0, 0 },
#define N_CARPSTAT 52
{ "_carpstats", 0, 0, 0, 0 }, /* not available via kvm */
#define N_PFSYNCSTAT 53
{ "_pfsyncstats", 0, 0, 0, 0}, /* not available via kvm */
{ "", 0, 0, 0, 0 },
};
struct protox {
u_char pr_index; /* index into nlist of cb head */
u_char pr_sindex; /* index into nlist of stat block */
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
void (*pr_cblocks) /* control blocks printing routine */
__P((u_long, const char *));
void (*pr_stats) /* statistics printing routine */
__P((u_long, const char *));
void (*pr_istats)
__P((const char *)); /* per/if statistics printing routine */
void (*pr_dump) /* PCB state dump routine */
__P((u_long, const char *, u_long));
const char *pr_name; /* well-known name */
} protox[] = {
{ N_TCBTABLE, N_TCPSTAT, 1, protopr,
tcp_stats, NULL, tcp_dump, "tcp" },
{ N_UDBTABLE, N_UDPSTAT, 1, protopr,
udp_stats, NULL, 0, "udp" },
{ -1, N_IPSTAT, 1, 0,
ip_stats, NULL, 0, "ip" },
{ -1, N_ICMPSTAT, 1, 0,
icmp_stats, NULL, 0, "icmp" },
{ -1, N_IGMPSTAT, 1, 0,
igmp_stats, NULL, 0, "igmp" },
{ -1, N_CARPSTAT, 1, 0,
carp_stats, NULL, 0, "carp" },
#ifdef IPSEC
{ -1, N_IPSECSTAT, 1, 0,
fast_ipsec_stats, NULL, 0, "ipsec" },
#endif
{ -1, N_PIMSTAT, 1, 0,
pim_stats, NULL, 0, "pim" },
{ -1, N_PFSYNCSTAT, 1, 0,
pfsync_stats, NULL, 0, "pfsync" },
{ -1, -1, 0, 0,
0, NULL, 0, 0 }
};
#ifdef INET6
struct protox ip6protox[] = {
{ -1, N_IP6STAT, 1, 0,
ip6_stats, ip6_ifstats, 0, "ip6" },
{ -1, N_ICMP6STAT, 1, 0,
icmp6_stats, icmp6_ifstats, 0, "icmp6" },
#ifdef TCP6
{ N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
tcp6_stats, NULL, tcp6_dump, "tcp6" },
#else
{ N_TCBTABLE, N_TCP6STAT, 1, ip6protopr,
tcp_stats, NULL, tcp6_dump, "tcp6" },
#endif
{ N_UDBTABLE, N_UDP6STAT, 1, ip6protopr,
udp6_stats, NULL, 0, "udp6" },
#ifdef IPSEC
{ -1, N_IPSEC6STAT, 1, 0,
fast_ipsec_stats, NULL, 0, "ipsec6" },
#endif
{ -1, N_PIM6STAT, 1, 0,
pim6_stats, NULL, 0, "pim6" },
{ -1, N_RIP6STAT, 1, 0,
rip6_stats, NULL, 0, "rip6" },
{ -1, -1, 0, 0,
0, NULL, 0, 0 }
};
#endif
struct protox arpprotox[] = {
{ -1, N_ARPSTAT, 1, 0,
arp_stats, NULL, 0, "arp" },
{ -1, -1, 0, 0,
0, NULL, 0, 0 }
};
#ifdef IPSEC
struct protox pfkeyprotox[] = {
{ -1, N_PFKEYSTAT, 1, 0,
pfkey_stats, NULL, 0, "pfkey" },
{ -1, -1, 0, 0,
0, NULL, 0, 0 }
};
#endif
#ifndef SMALL
struct protox atalkprotox[] = {
{ N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
ddp_stats, NULL, 0, "ddp" },
{ -1, -1, 0, 0,
0, NULL, 0, NULL }
};
#endif
struct protox *protoprotox[] = { protox,
#ifdef INET6
ip6protox,
#endif
arpprotox,
#ifdef IPSEC
pfkeyprotox,
#endif
#ifndef SMALL
atalkprotox,
#endif
NULL };
const struct softintrq {
const char *siq_name;
int siq_index;
} softintrq[] = {
{ "arpintrq", N_ARPINTRQ },
{ "ipintrq", N_IPINTRQ },
{ "ip6intrq", N_IP6INTRQ },
{ "atintrq1", N_ATINTRQ1 },
{ "atintrq2", N_ATINTRQ2 },
{ "llcintrq", N_LLCINTRQ },
{ "hdintrq", N_HDINTRQ },
{ "natmintrq", N_NATMINTRQ },
{ "ppoediscinq", N_PPPOEDISCINQ },
{ "ppoeinq", N_PPPOEINQ },
{ "pkintrq", N_PKINTRQ },
{ NULL, -1 },
};
int main __P((int, char *[]));
static void printproto __P((struct protox *, const char *));
static void print_softintrq __P((void));
__dead static void usage(void);
static struct protox *name2protox __P((const char *));
static struct protox *knownname __P((const char *));
static void prepare(const char *, const char *, struct protox *tp);
static kvm_t *prepare_kvmd(const char *, const char *, char *);
static kvm_t *kvmd = NULL;
gid_t egid;
int interval; /* repeat interval for i/f stats */
static const char *nlistf = NULL, *memf = NULL;
kvm_t *
get_kvmd(void)
{
char buf[_POSIX2_LINE_MAX];
if (kvmd != NULL)
return kvmd;
if ((kvmd = prepare_kvmd(nlistf, memf, buf)) == NULL)
errx(1, "kvm error: %s", buf);
return kvmd;
}
static kvm_t *
prepare_kvmd(const char *nf, const char *mf, char *errbuf)
{
kvm_t *k;
(void)setegid(egid);
k = kvm_openfiles(nf, mf, NULL, O_RDONLY, errbuf);
(void)setgid(getgid());
return k;
}
void
prepare(const char *nf, const char *mf, struct protox *tp)
{
char buf[_POSIX2_LINE_MAX];
/*
* Try to figure out if we can use sysctl or not.
*/
if (nf != NULL || mf != NULL) {
/* Of course, we can't use sysctl with dumps. */
if (force_sysctl)
errx(EXIT_FAILURE, "can't use sysctl with dumps");
/*
* If we have -M or -N, we're not dealing with live memory
* or want to use kvm interface explicitly. It is sometimes
* useful to dig inside of kernel without extending
* sysctl interface (i.e., without rebuilding kernel).
*/
use_sysctl = 0;
} else if (qflag ||
iflag ||
#ifndef SMALL
gflag ||
#endif
(pflag && tp->pr_sindex == N_PIMSTAT) ||
Pflag) {
/* These flags are not yet supported via sysctl(3). */
use_sysctl = 0;
} else {
/* We can use sysctl(3). */
use_sysctl = 1;
}
if (force_sysctl && !use_sysctl) {
/* Let the user know what's about to happen. */
warnx("forcing sysctl usage even though it might not be "\
"supported");
use_sysctl = 1;
}
#ifdef __minix
use_sysctl = 1;
#endif /* __minix */
kvmd = prepare_kvmd(nf, mf, buf);
if (!use_sysctl) {
if (kvmd == NULL)
errx(1, "kvm error: %s", buf);
if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
if (nf)
errx(1, "%s: no namelist", nf);
else
errx(1, "no namelist");
}
} else
(void)setgid(getgid());
}
int
main(int argc, char *argv[])
{
struct protoent *p;
struct protox *tp; /* for printing cblocks & stats */
int ch;
char *cp;
char *afname, *afnames;
u_long pcbaddr;
if (prog_init) {
if (prog_init() == -1)
err(1, "init failed");
force_sysctl = 1; /* cheap trick */
}
egid = getegid();
(void)setegid(getgid());
tp = NULL;
af = AF_UNSPEC;
afnames = NULL;
pcbaddr = 0;
while ((ch = getopt(argc, argv,
"AabBdf:ghI:LliM:mN:nP:p:qrsStTuVvw:X")) != -1)
switch (ch) {
case 'A':
Aflag = RT_AFLAG;
break;
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'B':
Bflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'f':
afnames = optarg;
break;
#ifndef SMALL
case 'g':
gflag = 1;
break;
#endif
case 'h':
hflag = 1;
break;
case 'I':
iflag = 1;
interface = optarg;
break;
case 'i':
iflag = 1;
break;
case 'L':
Lflag = RT_LFLAG;
break;
case 'l':
lflag = 1;
break;
case 'M':
memf = optarg;
break;
case 'm':
mflag = 1;
break;
case 'N':
nlistf = optarg;
break;
case 'n':
numeric_addr = numeric_port = nflag = RT_NFLAG;
break;
case 'P':
errno = 0;
pcbaddr = strtoul(optarg, &cp, 16);
if (*cp != '\0' || errno == ERANGE)
errx(1, "invalid PCB address %s",
optarg);
Pflag = 1;
break;
case 'p':
if ((tp = name2protox(optarg)) == NULL)
errx(1, "%s: unknown or uninstrumented protocol",
optarg);
pflag = 1;
break;
case 'q':
qflag = 1;
break;
case 'r':
rflag = 1;
break;
case 's':
++sflag;
break;
case 'S':
numeric_addr = 1;
break;
case 't':
tflag = 1;
break;
case 'T':
tagflag = RT_TFLAG;
break;
case 'u':
af = AF_LOCAL;
break;
case 'V':
Vflag++;
break;
case 'v':
vflag = RT_VFLAG;
break;
case 'w':
interval = atoi(optarg);
iflag = 1;
break;
case 'X':
force_sysctl = 1;
break;
case '?':
default:
usage();
}
argv += optind;
argc -= optind;
#define BACKWARD_COMPATIBILITY
#ifdef BACKWARD_COMPATIBILITY
if (*argv) {
if (isdigit((unsigned char)**argv)) {
interval = atoi(*argv);
if (interval <= 0)
usage();
++argv;
iflag = 1;
}
if (*argv) {
nlistf = *argv;
if (*++argv)
memf = *argv;
}
}
#endif
prepare(nlistf, memf, tp);
#ifndef SMALL
if (Bflag) {
if (sflag)
bpf_stats();
else
bpf_dump(interface);
exit(0);
}
#endif
if (mflag) {
mbpr(nl[N_MBSTAT].n_value, nl[N_MSIZE].n_value,
nl[N_MCLBYTES].n_value, nl[N_MBPOOL].n_value,
nl[N_MCLPOOL].n_value);
exit(0);
}
if (Pflag) {
if (tp == NULL) {
/* Default to TCP. */
tp = name2protox("tcp");
}
if (tp->pr_dump)
(*tp->pr_dump)(nl[tp->pr_index].n_value, tp->pr_name,
pcbaddr);
else
printf("%s: no PCB dump routine\n", tp->pr_name);
exit(0);
}
if (pflag) {
if (iflag && tp->pr_istats)
intpr(interval, nl[N_IFNET_LIST].n_value, tp->pr_istats);
else if (tp->pr_stats)
(*tp->pr_stats)(nl[tp->pr_sindex].n_value,
tp->pr_name);
else
printf("%s: no stats routine\n", tp->pr_name);
exit(0);
}
if (qflag) {
print_softintrq();
exit(0);
}
/*
* Keep file descriptors open to avoid overhead
* of open/close on each call to get* routines.
*/
sethostent(1);
setnetent(1);
/*
* If -f was used afnames != NULL, loop over the address families.
* Otherwise do this at least once (with af == AF_UNSPEC).
*/
afname = NULL;
do {
if (afnames != NULL) {
afname = strsep(&afnames, ",");
if (afname == NULL)
break; /* Exit early */
if (strcmp(afname, "inet") == 0)
af = AF_INET;
else if (strcmp(afname, "inet6") == 0)
af = AF_INET6;
else if (strcmp(afname, "arp") == 0)
af = AF_ARP;
else if (strcmp(afname, "pfkey") == 0)
af = PF_KEY;
else if (strcmp(afname, "unix") == 0
|| strcmp(afname, "local") == 0)
af = AF_LOCAL;
else if (strcmp(afname, "atalk") == 0)
af = AF_APPLETALK;
else if (strcmp(afname, "mpls") == 0)
af = AF_MPLS;
else {
warnx("%s: unknown address family",
afname);
continue;
}
}
if (iflag) {
if (af != AF_UNSPEC)
goto protostat;
intpr(interval, nl[N_IFNET_LIST].n_value, NULL);
break;
}
if (rflag) {
if (sflag)
rt_stats(use_sysctl ? 0 : nl[N_RTSTAT].n_value);
else {
if (use_sysctl)
p_rttables(af,
nflag|tagflag|vflag|Lflag, 0, ~0);
else
routepr(nl[N_RTREE].n_value);
}
break;
}
#ifndef SMALL
if (gflag) {
if (sflag) {
if (af == AF_INET || af == AF_UNSPEC)
mrt_stats(nl[N_MRTPROTO].n_value,
nl[N_MRTSTAT].n_value);
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
mrt6_stats(nl[N_MRT6PROTO].n_value,
nl[N_MRT6STAT].n_value);
#endif
}
else {
if (af == AF_INET || af == AF_UNSPEC)
mroutepr(nl[N_MRTPROTO].n_value,
nl[N_MFCHASHTBL].n_value,
nl[N_MFCHASH].n_value,
nl[N_VIFTABLE].n_value);
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
mroute6pr(nl[N_MRT6PROTO].n_value,
nl[N_MF6CTABLE].n_value,
nl[N_MIF6TABLE].n_value);
#endif
}
break;
}
#endif
protostat:
if (af == AF_INET || af == AF_UNSPEC) {
setprotoent(1);
setservent(1);
/* ugh, this is O(MN) ... why do we do this? */
while ((p = getprotoent()) != NULL) {
for (tp = protox; tp->pr_name; tp++)
if (strcmp(tp->pr_name, p->p_name) == 0)
break;
if (tp->pr_name == 0 || tp->pr_wanted == 0)
continue;
printproto(tp, p->p_name);
tp->pr_wanted = 0;
}
endprotoent();
for (tp = protox; tp->pr_name; tp++)
if (tp->pr_wanted)
printproto(tp, tp->pr_name);
}
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
for (tp = ip6protox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif
if (af == AF_ARP || af == AF_UNSPEC)
for (tp = arpprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#ifdef IPSEC
if (af == PF_KEY || af == AF_UNSPEC)
for (tp = pfkeyprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif
#ifndef SMALL
if (af == AF_APPLETALK || af == AF_UNSPEC)
for (tp = atalkprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
if ((af == AF_LOCAL || af == AF_UNSPEC) && !sflag)
unixpr(nl[N_UNIXSW].n_value);
#endif
} while (afnames != NULL && afname != NULL);
exit(0);
}
/*
* Print out protocol statistics or control blocks (per sflag).
* If the interface was not specifically requested, and the symbol
* is not in the namelist, ignore this one.
*/
static void
printproto(struct protox *tp, const char *name)
{
void (*pr) __P((u_long, const char *));
u_long off;
if (sflag) {
if (iflag) {
if (tp->pr_istats)
intpr(interval, nl[N_IFNET_LIST].n_value,
tp->pr_istats);
return;
}
else {
pr = tp->pr_stats;
off = nl[tp->pr_sindex].n_value;
}
} else {
pr = tp->pr_cblocks;
off = nl[tp->pr_index].n_value;
}
if (pr != NULL && ((off || af != AF_UNSPEC) || use_sysctl)) {
(*pr)(off, name);
}
}
/*
* Print softintrq status.
*/
void
print_softintrq(void)
{
struct ifqueue intrq, *ifq = &intrq;
const struct softintrq *siq;
u_long off;
for (siq = softintrq; siq->siq_name != NULL; siq++) {
off = nl[siq->siq_index].n_value;
if (off == 0)
continue;
kread(off, (char *)ifq, sizeof(*ifq));
printf("%s:\n", siq->siq_name);
printf("\tqueue length: %d\n", ifq->ifq_len);
printf("\tmaximum queue length: %d\n", ifq->ifq_maxlen);
printf("\tpackets dropped: %d\n", ifq->ifq_drops);
}
}
/*
* Read kernel memory, return 0 on success.
*/
int
kread(u_long addr, char *buf, int size)
{
if (kvm_read(kvmd, addr, buf, size) != size) {
warnx("%s", kvm_geterr(kvmd));
return (-1);
}
return (0);
}
const char *
plural(int n)
{
return (n != 1 ? "s" : "");
}
const char *
plurales(int n)
{
return (n != 1 ? "es" : "");
}
int
get_hardticks(void)
{
int hardticks;
kread(nl[N_HARDCLOCK_TICKS].n_value, (char *)&hardticks,
sizeof(hardticks));
return (hardticks);
}
/*
* Find the protox for the given "well-known" name.
*/
static struct protox *
knownname(const char *name)
{
struct protox **tpp, *tp;
for (tpp = protoprotox; *tpp; tpp++)
for (tp = *tpp; tp->pr_name; tp++)
if (strcmp(tp->pr_name, name) == 0)
return (tp);
return (NULL);
}
/*
* Find the protox corresponding to name.
*/
static struct protox *
name2protox(const char *name)
{
struct protox *tp;
char **alias; /* alias from p->aliases */
struct protoent *p;
/*
* Try to find the name in the list of "well-known" names. If that
* fails, check if name is an alias for an Internet protocol.
*/
if ((tp = knownname(name)) != NULL)
return (tp);
setprotoent(1); /* make protocol lookup cheaper */
while ((p = getprotoent()) != NULL) {
/* assert: name not same as p->name */
for (alias = p->p_aliases; *alias; alias++)
if (strcmp(name, *alias) == 0) {
endprotoent();
return (knownname(p->p_name));
}
}
endprotoent();
return (NULL);
}
static void
usage(void)
{
const char *progname = getprogname();
(void)fprintf(stderr,
"usage: %s [-Aan] [-f address_family[,family ...]] [-M core] [-N system]\n", progname);
(void)fprintf(stderr,
" %s [-bdgiLmnqrsSv] [-f address_family[,family ...]] [-M core] [-N system]\n",
progname);
(void)fprintf(stderr,
" %s [-dn] [-I interface] [-M core] [-N system] [-w wait]\n", progname);
(void)fprintf(stderr,
" %s [-p protocol] [-M core] [-N system]\n", progname);
(void)fprintf(stderr,
" %s [-p protocol] [-M core] [-N system] -P pcbaddr\n", progname);
(void)fprintf(stderr,
" %s [-p protocol] [-i] [-I Interface] \n", progname);
(void)fprintf(stderr,
" %s [-s] [-f address_family[,family ...]] [-i] [-I Interface]\n", progname);
(void)fprintf(stderr,
" %s [-s] [-B] [-I interface]\n", progname);
exit(1);
}

273
usr.bin/netstat/mbuf.c Normal file
View File

@ -0,0 +1,273 @@
/* $NetBSD: mbuf.c,v 1.33 2015/07/28 19:46:42 christos 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)mbuf.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: mbuf.c,v 1.33 2015/07/28 19:46:42 christos Exp $");
#endif
#endif /* not lint */
#define __POOL_EXPOSE
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/mbuf.h>
#include <sys/pool.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <kvm.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <err.h>
#include "netstat.h"
#include "prog_ops.h"
#define YES 1
struct mbstat mbstat;
struct pool mbpool, mclpool;
struct pool_allocator mbpa, mclpa;
static struct mbtypes {
int mt_type;
const char *mt_name;
} mbtypes[] = {
{ MT_DATA, "data" },
{ MT_OOBDATA, "oob data" },
{ MT_CONTROL, "ancillary data" },
{ MT_HEADER, "packet headers" },
{ MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */
{ MT_SONAME, "socket names and addresses" },
{ MT_SOOPTS, "socket options" },
{ 0, 0 }
};
const int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short);
bool seen[256]; /* "have we seen this type yet?" */
int mbstats_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_STATS };
int mowners_ctl[] = { CTL_KERN, KERN_MBUF, MBUF_MOWNERS };
/*
* Print mbuf statistics.
*/
void
mbpr(u_long mbaddr, u_long msizeaddr, u_long mclbaddr, u_long mbpooladdr,
u_long mclpooladdr)
{
u_long totmem, totused, totpct;
u_int totmbufs;
int i, lines;
struct mbtypes *mp;
size_t len;
void *data;
struct mowner_user *mo;
int mclbytes, msize;
if (nmbtypes != 256) {
fprintf(stderr,
"%s: unexpected change to mbstat; check source\n",
getprogname());
return;
}
if (use_sysctl) {
size_t mbstatlen = sizeof(mbstat);
if (prog_sysctl(mbstats_ctl,
sizeof(mbstats_ctl) / sizeof(mbstats_ctl[0]),
&mbstat, &mbstatlen, NULL, 0) < 0) {
warn("mbstat: sysctl failed");
return;
}
goto printit;
}
if (mbaddr == 0) {
fprintf(stderr, "%s: mbstat: symbol not in namelist\n",
getprogname());
return;
}
/*XXX*/
if (msizeaddr != 0)
kread(msizeaddr, (char *)&msize, sizeof (msize));
else
msize = MSIZE;
if (mclbaddr != 0)
kread(mclbaddr, (char *)&mclbytes, sizeof (mclbytes));
else
mclbytes = MCLBYTES;
/*XXX*/
if (kread(mbaddr, (char *)&mbstat, sizeof (mbstat)))
return;
if (kread(mbpooladdr, (char *)&mbpool, sizeof (mbpool)))
return;
if (kread(mclpooladdr, (char *)&mclpool, sizeof (mclpool)))
return;
mbpooladdr = (u_long) mbpool.pr_alloc;
mclpooladdr = (u_long) mclpool.pr_alloc;
if (kread(mbpooladdr, (char *)&mbpa, sizeof (mbpa)))
return;
if (kread(mclpooladdr, (char *)&mclpa, sizeof (mclpa)))
return;
printit:
totmbufs = 0;
for (mp = mbtypes; mp->mt_name; mp++)
totmbufs += mbstat.m_mtypes[mp->mt_type];
printf("%u mbufs in use:\n", totmbufs);
for (mp = mbtypes; mp->mt_name; mp++)
if (mbstat.m_mtypes[mp->mt_type]) {
seen[mp->mt_type] = YES;
printf("\t%u mbufs allocated to %s\n",
mbstat.m_mtypes[mp->mt_type], mp->mt_name);
}
seen[MT_FREE] = YES;
for (i = 0; i < nmbtypes; i++)
if (!seen[i] && mbstat.m_mtypes[i]) {
printf("\t%u mbufs allocated to <mbuf type %d>\n",
mbstat.m_mtypes[i], i);
}
if (use_sysctl) /* XXX */
goto dump_drain;
printf("%lu/%lu mapped pages in use\n",
(u_long)(mclpool.pr_nget - mclpool.pr_nput),
((u_long)mclpool.pr_npages * mclpool.pr_itemsperpage));
totmem = (mbpool.pr_npages << mbpa.pa_pageshift) +
(mclpool.pr_npages << mclpa.pa_pageshift);
totused = (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size +
(mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
if (totmem == 0)
totpct = 0;
else if (totused < (ULONG_MAX/100))
totpct = (totused * 100)/totmem;
else {
u_long totmem1 = totmem/100;
u_long totused1 = totused/100;
totpct = (totused1 * 100)/totmem1;
}
printf("%lu Kbytes allocated to network (%lu%% in use)\n",
totmem / 1024, totpct);
dump_drain:
printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
if (sflag < 2)
return;
if (!use_sysctl)
return;
if (prog_sysctl(mowners_ctl,
sizeof(mowners_ctl)/sizeof(mowners_ctl[0]),
NULL, &len, NULL, 0) < 0) {
if (errno == ENOENT)
return;
warn("mowners: sysctl test");
return;
}
len += 10 * sizeof(*mo); /* add some slop */
data = malloc(len);
if (data == NULL) {
warn("malloc(%lu)", (u_long)len);
return;
}
if (prog_sysctl(mowners_ctl,
sizeof(mowners_ctl)/sizeof(mowners_ctl[0]),
data, &len, NULL, 0) < 0) {
warn("mowners: sysctl get");
free(data);
return;
}
for (mo = (void *) data, lines = 0; len >= sizeof(*mo);
len -= sizeof(*mo), mo++) {
char buf[32];
if (vflag == 1 &&
mo->mo_counter[MOWNER_COUNTER_CLAIMS] == 0 &&
mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] == 0 &&
mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] == 0)
continue;
if (vflag == 0 &&
mo->mo_counter[MOWNER_COUNTER_CLAIMS] ==
mo->mo_counter[MOWNER_COUNTER_RELEASES] &&
mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] ==
mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES] &&
mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] ==
mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES])
continue;
snprintf(buf, sizeof(buf), "%16s %-13s",
mo->mo_name, mo->mo_descr);
if ((lines % 24) == 0 || lines > 24) {
printf("%30s %-8s %10s %10s %10s\n",
"", "", "small", "ext", "cluster");
lines = 1;
}
printf("%30s %-8s %10lu %10lu %10lu\n",
buf, "inuse",
mo->mo_counter[MOWNER_COUNTER_CLAIMS] -
mo->mo_counter[MOWNER_COUNTER_RELEASES],
mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS] -
mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES],
mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS] -
mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]);
lines++;
if (vflag) {
printf("%30s %-8s %10lu %10lu %10lu\n",
"", "claims",
mo->mo_counter[MOWNER_COUNTER_CLAIMS],
mo->mo_counter[MOWNER_COUNTER_EXT_CLAIMS],
mo->mo_counter[MOWNER_COUNTER_CLUSTER_CLAIMS]);
printf("%30s %-8s %10lu %10lu %10lu\n",
"", "releases",
mo->mo_counter[MOWNER_COUNTER_RELEASES],
mo->mo_counter[MOWNER_COUNTER_EXT_RELEASES],
mo->mo_counter[MOWNER_COUNTER_CLUSTER_RELEASES]);
lines += 2;
}
}
free(data);
}

397
usr.bin/netstat/mroute.c Normal file
View File

@ -0,0 +1,397 @@
/* $NetBSD: mroute.c,v 1.25 2014/11/06 21:30:09 christos Exp $ */
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* 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. 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.
*
* from: @(#)mroute.c 8.1 (Berkeley) 6/6/93
*/
/*
* Copyright (c) 1989 Stephen Deering
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* 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.
*
* from: @(#)mroute.c 8.1 (Berkeley) 6/6/93
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)mroute.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: mroute.c,v 1.25 2014/11/06 21:30:09 christos Exp $");
#endif
#endif /* not lint */
/*
* Print multicast routing structures and statistics.
*
* MROUTING 1.0
*/
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/igmp.h>
#define _KERNEL
#include <netinet/ip_mroute.h>
#undef _KERNEL
#include <stdio.h>
#include <stdlib.h>
#include <kvm.h>
#include "netstat.h"
#include "rtutil.h"
static char *pktscale(u_long);
static void print_bw_meter(struct bw_meter *, int *);
static char *
pktscale(u_long n)
{
static char buf[20];
char t;
if (n < 1024)
t = ' ';
else if (n < 1024 * 1024) {
t = 'k';
n /= 1024;
} else {
t = 'm';
n /= 1048576;
}
(void)snprintf(buf, sizeof buf, "%lu%c", n, t);
return (buf);
}
void
mroutepr(u_long mrpaddr, u_long mfchashtbladdr, u_long mfchashaddr,
u_long vifaddr)
{
u_int mrtproto;
LIST_HEAD(, mfc) *mfchashtbl;
u_long mfchash, i;
struct vif viftable[MAXVIFS];
struct mfc *mfcp, mfc;
struct vif *v;
vifi_t vifi;
int banner_printed;
int saved_numeric_addr;
int numvifs;
int nmfc; /* No. of cache entries */
if (mrpaddr == 0) {
printf("ip_mrtproto: symbol not in namelist\n");
return;
}
kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
switch (mrtproto) {
case 0:
printf("no multicast routing compiled into this system\n");
return;
case IGMP_DVMRP:
break;
default:
printf("multicast routing protocol %u, unknown\n", mrtproto);
return;
}
if (mfchashtbladdr == 0) {
printf("mfchashtbl: symbol not in namelist\n");
return;
}
if (mfchashaddr == 0) {
printf("mfchash: symbol not in namelist\n");
return;
}
if (vifaddr == 0) {
printf("viftable: symbol not in namelist\n");
return;
}
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
kread(vifaddr, (char *)&viftable, sizeof(viftable));
banner_printed = 0;
numvifs = 0;
for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
if (v->v_lcl_addr.s_addr == 0)
continue;
numvifs = vifi;
if (!banner_printed) {
printf("\nVirtual Interface Table\n %s%s",
"Vif Thresh Limit Local-Address ",
"Remote-Address Pkt_in Pkt_out\n");
banner_printed = 1;
}
printf(" %3u %3u %5u %-15.15s",
vifi, v->v_threshold, v->v_rate_limit,
routename4(v->v_lcl_addr.s_addr, nflag));
printf(" %-15.15s %6lu %7lu\n", (v->v_flags & VIFF_TUNNEL) ?
routename4(v->v_rmt_addr.s_addr, nflag) : "",
v->v_pkt_in, v->v_pkt_out);
}
if (!banner_printed)
printf("\nVirtual Interface Table is empty\n");
kread(mfchashtbladdr, (char *)&mfchashtbl, sizeof(mfchashtbl));
kread(mfchashaddr, (char *)&mfchash, sizeof(mfchash));
banner_printed = 0;
nmfc = 0;
if (mfchashtbl != 0)
for (i = 0; i <= mfchash; ++i) {
kread((u_long)&mfchashtbl[i], (char *)&mfcp, sizeof(mfcp));
for (; mfcp != 0; mfcp = mfc.mfc_hash.le_next) {
if (!banner_printed) {
printf("\nMulticast Forwarding Cache\n %s%s",
"Hash Origin Mcastgroup ",
"Traffic In-Vif Out-Vifs/Forw-ttl\n");
banner_printed = 1;
}
kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
printf(" %3lu %-15.15s",
i, routename4(mfc.mfc_origin.s_addr, nflag));
printf(" %-15.15s %7s %3u ",
routename4(mfc.mfc_mcastgrp.s_addr, nflag),
pktscale(mfc.mfc_pkt_cnt), mfc.mfc_parent);
for (vifi = 0; vifi <= numvifs; ++vifi)
if (mfc.mfc_ttls[vifi])
printf(" %u/%u", vifi, mfc.mfc_ttls[vifi]);
printf("\n");
/* Print the bw meter information */
{
struct bw_meter bw_meter, *bwm;
int banner_printed2 = 0;
bwm = mfc.mfc_bw_meter;
while (bwm) {
kread((u_long)bwm,
(char *)&bw_meter,
sizeof bw_meter);
print_bw_meter(&bw_meter,
&banner_printed2);
bwm = bw_meter.bm_mfc_next;
}
#if 0 /* Don't ever print it? */
if (! banner_printed2)
printf("\n No Bandwidth Meters\n");
#endif
}
nmfc++;
}
}
if (!banner_printed)
printf("\nMulticast Forwarding Cache is empty\n");
else
printf("\nTotal no. of entries in cache: %d\n", nmfc);
printf("\n");
numeric_addr = saved_numeric_addr;
}
static void
print_bw_meter(struct bw_meter *bw_meter, int *banner_printed)
{
char s0[256], s1[256], s2[256], s3[256];
struct timeval now, end, delta;
gettimeofday(&now, NULL);
if (! *banner_printed) {
printf(" Bandwidth Meters\n");
printf(" %-30s", "Measured(Start|Packets|Bytes)");
printf(" %s", "Type");
printf(" %-30s", "Thresh(Interval|Packets|Bytes)");
printf(" Remain");
printf("\n");
*banner_printed = 1;
}
/* The measured values */
if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
sprintf(s1, "%llu", (unsigned long long)bw_meter->bm_measured.b_packets);
else
sprintf(s1, "?");
if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
sprintf(s2, "%llu", (unsigned long long)bw_meter->bm_measured.b_bytes);
else
sprintf(s2, "?");
sprintf(s0, "%lld.%ld|%s|%s",
(long long)bw_meter->bm_start_time.tv_sec,
(long)bw_meter->bm_start_time.tv_usec,
s1, s2);
printf(" %-30s", s0);
/* The type of entry */
sprintf(s0, "%s", "?");
if (bw_meter->bm_flags & BW_METER_GEQ)
sprintf(s0, "%s", ">=");
else if (bw_meter->bm_flags & BW_METER_LEQ)
sprintf(s0, "%s", "<=");
printf(" %-3s", s0);
/* The threshold values */
if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
sprintf(s1, "%llu", (unsigned long long)bw_meter->bm_threshold.b_packets);
else
sprintf(s1, "?");
if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
sprintf(s2, "%llu", (unsigned long long)bw_meter->bm_threshold.b_bytes);
else
sprintf(s2, "?");
sprintf(s0, "%lld.%ld|%s|%s",
(long long)bw_meter->bm_threshold.b_time.tv_sec,
(long)bw_meter->bm_threshold.b_time.tv_usec,
s1, s2);
printf(" %-30s", s0);
/* Remaining time */
timeradd(&bw_meter->bm_start_time,
&bw_meter->bm_threshold.b_time, &end);
if (timercmp(&now, &end, <=)) {
timersub(&end, &now, &delta);
sprintf(s3, "%lld.%ld",
(long long)delta.tv_sec, (long)delta.tv_usec);
} else {
/* Negative time */
timersub(&now, &end, &delta);
sprintf(s3, "-%lld.%ld",
(long long)delta.tv_sec, (long)delta.tv_usec);
}
printf(" %s", s3);
printf("\n");
}
void
mrt_stats(u_long mrpaddr, u_long mstaddr)
{
u_int mrtproto;
struct mrtstat mrtstat;
if (mrpaddr == 0) {
printf("ip_mrtproto: symbol not in namelist\n");
return;
}
kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
switch (mrtproto) {
case 0:
printf("no multicast routing compiled into this system\n");
return;
case IGMP_DVMRP:
break;
default:
printf("multicast routing protocol %u, unknown\n", mrtproto);
return;
}
if (mstaddr == 0) {
printf("mrtstat: symbol not in namelist\n");
return;
}
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
printf("multicast routing:\n");
printf("\t%lu datagram%s with no route for origin\n",
mrtstat.mrts_no_route, plural(mrtstat.mrts_no_route));
printf("\t%lu upcall%s made to mrouted\n",
mrtstat.mrts_upcalls, plural(mrtstat.mrts_upcalls));
printf("\t%lu datagram%s with malformed tunnel options\n",
mrtstat.mrts_bad_tunnel, plural(mrtstat.mrts_bad_tunnel));
printf("\t%lu datagram%s with no room for tunnel options\n",
mrtstat.mrts_cant_tunnel, plural(mrtstat.mrts_cant_tunnel));
printf("\t%lu datagram%s arrived on wrong interface\n",
mrtstat.mrts_wrong_if, plural(mrtstat.mrts_wrong_if));
printf("\t%lu datagram%s dropped due to upcall Q overflow\n",
mrtstat.mrts_upq_ovflw, plural(mrtstat.mrts_upq_ovflw));
printf("\t%lu datagram%s dropped due to upcall socket overflow\n",
mrtstat.mrts_upq_sockfull, plural(mrtstat.mrts_upq_sockfull));
printf("\t%lu datagram%s cleaned up by the cache\n",
mrtstat.mrts_cache_cleanups, plural(mrtstat.mrts_cache_cleanups));
printf("\t%lu datagram%s dropped selectively by ratelimiter\n",
mrtstat.mrts_drop_sel, plural(mrtstat.mrts_drop_sel));
printf("\t%lu datagram%s dropped - bucket Q overflow\n",
mrtstat.mrts_q_overflow, plural(mrtstat.mrts_q_overflow));
printf("\t%lu datagram%s dropped - larger than bkt size\n",
mrtstat.mrts_pkt2large, plural(mrtstat.mrts_pkt2large));
}

301
usr.bin/netstat/mroute6.c Normal file
View File

@ -0,0 +1,301 @@
/* $NetBSD: mroute6.c,v 1.15 2014/11/06 21:30:09 christos Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* 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. 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.
*
* @(#)mroute.c 8.2 (Berkeley) 4/28/95
*/
/*
* Copyright (c) 1989 Stephen Deering
*
* This code is derived from software contributed to Berkeley by
* Stephen Deering of Stanford University.
*
* 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.
*
* @(#)mroute.c 8.2 (Berkeley) 4/28/95
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/protosw.h>
#include <net/if.h>
#include <netinet/in.h>
#define _KERNEL 1
#include <netinet6/ip6_mroute.h>
#undef _KERNEL
#include <stdio.h>
#include <kvm.h>
#include "netstat.h"
#include "rtutil.h"
#ifdef INET6
#define WID_ORG (lflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
#define WID_GRP (lflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
void
mroute6pr(u_long mrpaddr, u_long mfcaddr, u_long mifaddr)
{
u_int mrtproto;
struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
struct mif6 mif6table[MAXMIFS];
struct mf6c mfc;
struct rtdetq rte, *rtep;
register struct mif6 *mifp;
register mifi_t mifi;
register int i;
register int banner_printed;
register int saved_numeric_addr;
int waitings;
if (mrpaddr == 0) {
printf("mroute6pr: symbol not in namelist\n");
return;
}
kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
switch (mrtproto) {
case 0:
printf("no IPv6 multicast routing compiled into this system\n");
return;
case IPPROTO_PIM:
break;
default:
printf("IPv6 multicast routing protocol %u, unknown\n",
mrtproto);
return;
}
if (mfcaddr == 0) {
printf("mf6ctable: symbol not in namelist\n");
return;
}
if (mifaddr == 0) {
printf("miftable: symbol not in namelist\n");
return;
}
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
kread(mifaddr, (char *)&mif6table, sizeof(mif6table));
banner_printed = 0;
for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
struct ifnet ifnet;
char ifname[IFNAMSIZ];
if (mifp->m6_ifp == NULL)
continue;
kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet));
if (!banner_printed) {
printf("\nIPv6 Multicast Interface Table\n"
" Mif Rate PhyIF Pkts-In Pkts-Out\n");
banner_printed = 1;
}
printf(" %2u %4d", mifi, mifp->m6_rate_limit);
printf(" %5s", (mifp->m6_flags & MIFF_REGISTER) ?
"reg0" : if_indextoname(ifnet.if_index, ifname));
printf(" %9llu %9llu\n", (unsigned long long)mifp->m6_pkt_in,
(unsigned long long)mifp->m6_pkt_out);
}
if (!banner_printed)
printf("\nIPv6 Multicast Interface Table is empty\n");
kread(mfcaddr, (char *)&mf6ctable, sizeof(mf6ctable));
banner_printed = 0;
for (i = 0; i < MF6CTBLSIZ; ++i) {
mfcp = mf6ctable[i];
while(mfcp) {
kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
if (!banner_printed) {
printf ("\nIPv6 Multicast Forwarding Cache\n");
printf(" %-*.*s %-*.*s %s",
WID_ORG, WID_ORG, "Origin",
WID_GRP, WID_GRP, "Group",
" Packets Waits In-Mif Out-Mifs\n");
banner_printed = 1;
}
printf(" %-*.*s", WID_ORG, WID_ORG,
routename6(&mfc.mf6c_origin, nflag));
printf(" %-*.*s", WID_GRP, WID_GRP,
routename6(&mfc.mf6c_mcastgrp, nflag));
printf(" %9llu", (unsigned long long)mfc.mf6c_pkt_cnt);
for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
waitings++;
kread((u_long)rtep, (char *)&rte, sizeof(rte));
rtep = rte.next;
}
printf(" %3d", waitings);
if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
printf(" --- ");
else
printf(" %3d ", mfc.mf6c_parent);
for (mifi = 0; mifi <= MAXMIFS; mifi++) {
if (IF_ISSET(mifi, &mfc.mf6c_ifset))
printf(" %u", mifi);
}
printf("\n");
mfcp = mfc.mf6c_next;
}
}
if (!banner_printed)
printf("\nIPv6 Multicast Routing Table is empty\n");
printf("\n");
numeric_addr = saved_numeric_addr;
}
void
mrt6_stats(u_long mrpaddr, u_long mstaddr)
{
#define p(f, m) printf(m, (unsigned long long)mrtstat.f, plural(mrtstat.f))
#define pes(f, m) printf(m, (unsigned long long)mrtstat.f, plurales(mrtstat.f))
u_int mrtproto;
struct mrt6stat mrtstat;
if (mrpaddr == 0) {
printf("mrt6_stats: symbol not in namelist\n");
return;
}
kread(mrpaddr, (char *)&mrtproto, sizeof(mrtproto));
switch (mrtproto) {
case 0:
printf("no IPv6 multicast routing compiled into this system\n");
return;
case IPPROTO_PIM:
break;
default:
printf("IPv6 multicast routing protocol %u, unknown\n",
mrtproto);
return;
}
if (mstaddr == 0) {
printf("mrt6_stats: symbol not in namelist\n");
return;
}
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
printf("multicast forwarding:\n");
p(mrt6s_mfc_lookups, " %10llu multicast forwarding cache lookup%s\n");
pes(mrt6s_mfc_misses, " %10llu multicast forwarding cache miss%s\n");
p(mrt6s_upcalls, " %10llu upcall%s to mrouted\n");
p(mrt6s_upq_ovflw, " %10llu upcall queue overflow%s\n");
p(mrt6s_upq_sockfull,
" %10llu upcall%s dropped due to full socket buffer\n");
p(mrt6s_cache_cleanups, " %10llu cache cleanup%s\n");
p(mrt6s_no_route, " %10llu datagram%s with no route for origin\n");
p(mrt6s_bad_tunnel, " %10llu datagram%s arrived with bad tunneling\n");
p(mrt6s_cant_tunnel, " %10llu datagram%s could not be tunneled\n");
p(mrt6s_wrong_if, " %10llu datagram%s arrived on wrong interface\n");
p(mrt6s_drop_sel, " %10llu datagram%s selectively dropped\n");
p(mrt6s_q_overflow,
" %10llu datagram%s dropped due to queue overflow\n");
p(mrt6s_pkt2large, " %10llu datagram%s dropped for being too large\n");
#undef p
#undef pes
}
#endif /*INET6*/

476
usr.bin/netstat/netstat.1 Normal file
View File

@ -0,0 +1,476 @@
.\" $NetBSD: netstat.1,v 1.72 2015/03/23 18:33:17 roy Exp $
.\"
.\" Copyright (c) 1983, 1990, 1992, 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. 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.
.\"
.\" @(#)netstat.1 8.8 (Berkeley) 4/18/94
.\"
.Dd March 19, 2015
.Dt NETSTAT 1
.Os
.Sh NAME
.Nm netstat
.Nd show network status
.Sh SYNOPSIS
.ds address_family Fl f Ar address_family Ns Op , Ns Ar family ...
.Nm
.Op Fl Aan
.Op \*[address_family]
.Op Fl M Ar core
.Op Fl N Ar system
.Nm
.Op Fl bdghiLlmnqrSsTtv
.Op \*[address_family]
.Op Fl M Ar core
.Op Fl N Ar system
.Nm
.Op Fl dn
.Op Fl I Ar interface
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl w Ar wait
.Nm
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl p Ar protocol
.Nm
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl p Ar protocol
.Fl P Ar pcbaddr
.Nm
.Op Fl i
.Op Fl I Ar Interface
.Op Fl p Ar protocol
.Nm
.Op Fl is
.Op \*[address_family]
.Op Fl I Ar Interface
.Nm
.Op Fl s
.Op Fl I Ar Interface
.Fl B
.Sh DESCRIPTION
The
.Nm
command symbolically displays the contents of various network-related
data structures.
There are a number of output formats,
depending on the options for the information presented.
The first form of the command displays a list of active sockets for
each protocol.
The second form presents the contents of one of the other network
data structures according to the option selected.
Using the third form, with a
.Ar wait
interval specified,
.Nm
will continuously display the information regarding packet
traffic on the configured network interfaces.
The fourth form displays statistics about the named protocol.
The fifth and sixth forms display per interface statistics for
the specified protocol or address family.
.Pp
The options have the following meaning:
.Bl -tag -width flag
.It Fl A
With the default display,
show the address of any protocol control blocks associated with sockets; used
for debugging.
.It Fl a
With the default display,
show the state of all sockets; normally sockets used by
server processes are not shown.
.It Fl B
With the default display,
show the current
.Xr bpf 4
peers.
To show only the peers listening to a specific interface,
use the
.Fl I
option.
If the
.Fl s
option is present, show the current
.Xr bpf 4
statistics.
.It Fl b
With the interface display (option
.Fl i ) ,
show bytes in and out, instead of packets in and out.
.It Fl d
With either interface display (option
.Fl i
or an interval, as described below),
show the number of dropped packets.
.It \*[address_family]
Limit statistics or address control block reports to those
of the specified
.Ar address_families .
The following address families
are recognized:
.Ar inet ,
for
.Dv AF_INET ;
.Ar inet6 ,
for
.Dv AF_INET6 ;
.Ar arp ,
for
.Dv AF_ARP ;
.Ar ns ,
for
.Dv AF_NS ;
.Ar atalk ,
for
.Dv AF_APPLETALK ;
.Ar mpls ,
for
.Dv AF_MPLS ;
and
.Ar local
or
.Ar unix ,
for
.Dv AF_LOCAL .
.It Fl g
Show information related to multicast (group address) routing.
By default, show the IP Multicast virtual-interface and routing tables.
If the
.Fl s
option is also present, show multicast routing statistics.
.It Fl h
When used with
.Fl b
in combination with either
.Fl i
or
.Fl I ,
output "human-readable" byte counts.
.It Fl I Ar interface
Show information about the specified interface;
used with a
.Ar wait
interval as described below.
If the
.Fl f Ar address_family
option (with the
.Fl s
option) or the
.Fl p Ar protocol
option is present, show per-interface statistics on the
.Ar interface
for the specified
.Ar address_family
or
.Ar protocol ,
respectively.
.It Fl i
Show the state of interfaces which have been auto-configured
(interfaces statically configured into a system, but not
located at boot time are not shown).
If the
.Fl a
options is also present, multicast addresses currently in use are shown
for each Ethernet interface and for each IP interface address.
Multicast addresses are shown on separate lines following the interface
address with which they are associated.
If the
.Fl f Ar address_family
option (with the
.Fl s
option) or the
.Fl p Ar protocol
option is present, show per-interface statistics on all interfaces
for the specified
.Ar address_family
or
.Ar protocol ,
respectively.
.It Fl L
Don't show link-level routes (e.g., IPv4 ARP or IPv6 neighbour cache).
.It Fl l
With the
.Fl g
option, display wider fields for the IPv6 multicast routing table
.Qq Origin
and
.Qq Group
columns.
.It Fl M Ar core
Use
.Xr kvm 3
instead of
.Xr sysctl 3
to retrieve information and
extract values associated with the name list from the specified core.
If the
.Fl M
option is not given but the
.Fl N
option is given, the default
.Pa /dev/mem
is used.
.It Fl m
Show statistics recorded by the mbuf memory management routines
(the network manages a private pool of memory buffers).
.It Fl N Ar system
Use
.Xr kvm 3
instead of
.Xr sysctl 3
to retrieve information and extract the name list from the specified system.
For the default behavior when only
.Fl M
option is given, see the description about when
.Fa execfile
is
.Dv NULL
in
.Xr kvm_openfiles 3 .
.It Fl n
Show network addresses and ports as numbers (normally
.Nm
interprets addresses and ports and attempts to display them
symbolically).
This option may be used with any of the display formats.
.It Fl P Ar pcbaddr
Dump the contents of the protocol control block (PCB) located at kernel
virtual address
.Ar pcbaddr .
This address may be obtained using the
.Fl A
flag.
The default protocol is TCP, but may be overridden using the
.Fl p
flag.
.It Fl p Ar protocol
Show statistics about
.Ar protocol ,
which is either a well-known name for a protocol or an alias for it.
Some protocol names and aliases are listed in the file
.Pa /etc/protocols .
A null response typically means that there are no interesting numbers to
report.
The program will complain if
.Ar protocol
is unknown or if there is no statistics routine for it.
.It Fl q
Show software interrupt queue setting/statistics for all protocols.
.It Fl r
Show the routing tables.
When
.Fl s
is also present, show routing statistics instead.
.It Fl S
Show network addresses as numbers (as with
.Fl n ,
but show ports symbolically).
.It Fl s
Show per-protocol statistics.
If this option is repeated, counters with a value of zero are suppressed.
.It Fl T
Show MPLS Tags for the routing tables.
If multiple tags exists, they will
be comma separated, first tag being the BoS one.
.It Fl t
With the
.Fl i
option, display the current value of the watchdog timer function.
.It Fl v
Show extra (verbose) detail for the routing tables
.Pq Fl r ,
or avoid truncation of long addresses.
.It Fl w Ar wait
Show network interface statistics at intervals of
.Ar wait
seconds.
.It Fl X
Force use of
.Xr sysctl 3
when retrieving information.
Some features of
.Nm
may not be (fully) supported when using
.Xr sysctl 3 .
This flag forces the use of the latter regardless, and emits a message if a
not yet fully supported feature is used in conjunction with it.
This flag might be removed at any time; do not rely on its presence.
.El
.Pp
The default display, for active sockets, shows the local
and remote addresses, send and receive queue sizes (in bytes), protocol,
and the internal state of the protocol.
Address formats are of the form ``host.port'' or ``network.port''
if a socket's address specifies a network but no specific host address.
When known the host and network addresses are displayed symbolically
according to the data bases
.Pa /etc/hosts
and
.Pa /etc/networks ,
respectively.
If a symbolic name for an address is unknown, or if
the
.Fl n
option is specified, the address is printed numerically, according
to the address family.
For more information regarding
the Internet ``dot format,''
refer to
.Xr inet 3 ) .
Unspecified,
or ``wildcard'', addresses and ports appear as ``*''.
You can use the
.Xr fstat 1
command to find out which process or processes hold references to a socket.
.Pp
The interface display provides a table of cumulative
statistics regarding packets transferred, errors, and collisions.
The network addresses of the interface
and the maximum transmission unit (``mtu'') are also displayed.
.Pp
The routing table display indicates the available routes and
their status.
Each route consists of a destination host or network
and a gateway to use in forwarding packets.
The flags field shows
a collection of information about the route stored as
binary choices.
The individual flags are discussed in more
detail in the
.Xr route 8
and
.Xr route 4
manual pages.
The mapping between letters and flags is:
.Bl -column XXXX RTF_BLACKHOLE
.It 1 RTF_PROTO1 Protocol specific routing flag #1
.It 2 RTF_PROTO2 Protocol specific routing flag #2
.It B RTF_BLACKHOLE Just discard pkts (during updates)
.It b RTF_BROADCAST Route represents a broadcast address
.It C RTF_CLONING Generate new routes on use
.It c RTF_CLONED Cloned routes (generated from RTF_CLONING)
.It D RTF_DYNAMIC Created dynamically (by redirect)
.It G RTF_GATEWAY Destination requires forwarding by intermediary
.It H RTF_HOST Host entry (net otherwise)
.It L RTF_LLINFO Valid protocol to link address translation.
.It l RTF_LOCAL Route represents a local address
.It M RTF_MODIFIED Modified dynamically (by redirect)
.It p RTF_ANNOUNCE Link level proxy
.It R RTF_REJECT Host or net unreachable
.It S RTF_STATIC Manually added
.It U RTF_UP Route usable
.It X RTF_XRESOLVE External daemon translates proto to link address
.El
.Pp
Direct routes are created for each
interface attached to the local host;
the gateway field for such entries shows the address of the outgoing interface.
The refcnt field gives the
current number of active uses of the route.
Connection oriented
protocols normally hold on to a single route for the duration of
a connection while connectionless protocols obtain a route while sending
to the same destination.
The use field provides a count of the number of packets
sent using that route.
The mtu entry shows the mtu associated with
that route.
This mtu value is used as the basis for the TCP maximum
segment size.
The 'L' flag appended to the mtu value indicates that
the value is locked, and that path mtu discovery is turned off for
that route.
A
.Sq -
indicates that the mtu for this route has not been set, and a default
TCP maximum segment size will be used.
The interface entry indicates
the network interface used for the route.
.Pp
When
.Nm
is invoked with the
.Fl w
option and a
.Ar wait
interval argument, it displays a running count of statistics related to
network interfaces.
An obsolescent version of this option used a numeric parameter
with no option, and is currently supported for backward compatibility.
This display consists of a column for the primary interface (the first
interface found during autoconfiguration) and a column summarizing
information for all interfaces.
The primary interface may be replaced with another interface with the
.Fl I
option.
The first line of each screen of information contains a summary since the
system was last rebooted.
Subsequent lines of output show values
accumulated over the preceding interval.
.Pp
The first character of the flags column in the
.Fl B
option shows the status of the
.Xr bpf 4
descriptor which has three different values:
Idle ('I'), Waiting ('W') and Timed Out ('T').
The second character indicates whether the promisc flag is set.
The third character indicates the status of the immediate mode.
The fourth character indicates whether the peer will have the ability
to see the packets sent.
And the fifth character shows the header complete flag status.
.Sh SEE ALSO
.Xr fstat 1 ,
.Xr nfsstat 1 ,
.Xr ps 1 ,
.Xr sockstat 1 ,
.Xr vmstat 1 ,
.Xr inet 3 ,
.Xr bpf 4 ,
.Xr hosts 5 ,
.Xr networks 5 ,
.Xr protocols 5 ,
.Xr services 5 ,
.Xr iostat 8 ,
.Xr trpt 8
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.2 .
IPv6 support was added by WIDE/KAME project.
.\" .Sh FILES
.\" .Bl -tag -width /dev/mem -compact
.\" .It Pa /netbsd
.\" default kernel namelist
.\" .It Pa /dev/mem
.\" default memory file
.\" .El
.Sh BUGS
The notion of errors is ill-defined.

149
usr.bin/netstat/netstat.h Normal file
View File

@ -0,0 +1,149 @@
/* $NetBSD: netstat.h,v 1.51 2014/11/06 21:30:09 christos Exp $ */
/*
* Copyright (c) 1992, 1993
* 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. 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.
*
* from: @(#)netstat.h 8.2 (Berkeley) 1/4/94
*/
#include <sys/cdefs.h>
#include <kvm.h>
int Aflag; /* show addresses of protocol control block */
int aflag; /* show all sockets (including servers) */
int Bflag; /* show Berkeley Packet Filter information */
int bflag; /* show i/f byte stats */
int dflag; /* show i/f dropped packets */
#ifndef SMALL
int gflag; /* show group (multicast) routing or stats */
#endif
int hflag; /* humanize byte counts */
int iflag; /* show interfaces */
int Lflag; /* don't show LLINFO entries */
int lflag; /* show routing table with use and ref */
int mflag; /* show memory stats */
int numeric_addr; /* show addresses numerically */
int numeric_port; /* show ports numerically */
int nflag; /* same as above, for show.c compat */
int Pflag; /* dump a PCB */
int pflag; /* show given protocol */
int qflag; /* show softintrq */
int rflag; /* show routing tables (or routing stats) */
int sflag; /* show protocol statistics */
int tagflag; /* show route tags */
int tflag; /* show i/f watchdog timers */
int Vflag; /* show Vestigial TIME_WAIT (VTW) information */
int vflag; /* verbose route information or don't truncate names */
char *interface; /* desired i/f for stats, or NULL for all i/fs */
int af; /* address family */
int use_sysctl; /* use sysctl instead of kmem */
int force_sysctl; /* force use of sysctl (or exit) - for testing */
int kread(u_long addr, char *buf, int size);
const char *plural(int);
const char *plurales(int);
int get_hardticks(void);
void protopr(u_long, const char *);
void tcp_stats(u_long, const char *);
void tcp_dump(u_long, const char *, u_long);
void udp_stats(u_long, const char *);
void ip_stats(u_long, const char *);
void icmp_stats(u_long, const char *);
void igmp_stats(u_long, const char *);
void pim_stats(u_long, const char *);
void arp_stats(u_long, const char *);
void carp_stats(u_long, const char *);
void pfsync_stats(u_long, const char*);
#ifdef IPSEC
void fast_ipsec_stats(u_long, const char *);
#endif
#ifdef INET6
struct sockaddr_in6;
struct in6_addr;
void ip6protopr(u_long, const char *);
void tcp6_stats(u_long, const char *);
void tcp6_dump(u_long, const char *, u_long);
void udp6_stats(u_long, const char *);
void ip6_stats(u_long, const char *);
void ip6_ifstats(const char *);
void icmp6_stats(u_long, const char *);
void icmp6_ifstats(const char *);
void pim6_stats(u_long, const char *);
void rip6_stats(u_long, const char *);
void mroute6pr(u_long, u_long, u_long);
void mrt6_stats(u_long, u_long);
#endif /*INET6*/
#ifdef IPSEC
void pfkey_stats(u_long, const char *);
#endif
void mbpr(u_long, u_long, u_long, u_long, u_long);
void hostpr(u_long, u_long);
void impstats(u_long, u_long);
void rt_stats(u_long);
char *ns_phost(struct sockaddr *);
const char *atalk_print(const struct sockaddr *, int);
const char *atalk_print2(const struct sockaddr *, const struct sockaddr *,
int);
char *ns_print(struct sockaddr *);
void nsprotopr(u_long, const char *);
void spp_stats(u_long, const char *);
void idp_stats(u_long, const char *);
void nserr_stats(u_long, const char *);
void atalkprotopr(u_long, const char *);
void ddp_stats(u_long, const char *);
void intpr(int, u_long, void (*)(const char *));
void unixpr(u_long);
void routepr(u_long);
void mroutepr(u_long, u_long, u_long, u_long);
void mrt_stats(u_long, u_long);
void bpf_stats(void);
void bpf_dump(const char *);
kvm_t *get_kvmd(void);
char *mpls_ntoa(const struct sockaddr *);
struct kinfo_pcb *getpcblist_sysctl(const char *, size_t *);
#define PLEN (LONG_BIT / 4 + 2)

View File

@ -0,0 +1,41 @@
/* $NetBSD: netstat_hostops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: netstat_hostops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <sys/sysctl.h>
#include "prog_ops.h"
const struct prog_ops prog_ops = {
.op_sysctl = sysctl,
};

View File

@ -0,0 +1,46 @@
/* $NetBSD: netstat_rumpops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: netstat_rumpops.c,v 1.1 2010/12/13 21:15:30 pooka Exp $");
#endif /* !lint */
#include <sys/types.h>
#include <rump/rump.h>
#include <rump/rumpclient.h>
#include <rump/rump_syscalls.h>
#include "prog_ops.h"
const struct prog_ops prog_ops = {
.op_init = rumpclient_init,
.op_sysctl = rump_sys___sysctl,
};

180
usr.bin/netstat/pfkey.c Normal file
View File

@ -0,0 +1,180 @@
/* $NetBSD: pfkey.c,v 1.1 2012/01/06 14:21:16 drochner Exp $ */
/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
* 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. Neither the name of the project 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 PROJECT 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 PROJECT 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.
*/
/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
#else
#ifdef __NetBSD__
__RCSID("$NetBSD: pfkey.c,v 1.1 2012/01/06 14:21:16 drochner Exp $");
#endif
#endif
#endif /* not lint */
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#ifdef IPSEC
#include <netipsec/keysock.h>
#endif
#include <err.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#ifdef IPSEC
static const char *pfkey_msgtypenames[] = {
"reserved", "getspi", "update", "add", "delete",
"get", "acquire", "register", "expire", "flush",
"dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
"x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
"x_spdsetidx", "x_spdexpire", "x_spddelete2"
};
static const char *pfkey_msgtype_names(int);
static const char *
pfkey_msgtype_names(int x)
{
const int max =
sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
static char buf[20];
if (x < max && pfkey_msgtypenames[x])
return pfkey_msgtypenames[x];
snprintf(buf, sizeof(buf), "#%d", x);
return buf;
}
void
pfkey_stats(u_long off, const char *name)
{
uint64_t pfkeystat[PFKEY_NSTATS];
int first, type;
if (use_sysctl) {
size_t size = sizeof(pfkeystat);
if (sysctlbyname("net.key.stats", pfkeystat, &size,
NULL, 0) == -1)
return;
} else {
warnx("%s stats not available via KVM.", name);
return;
}
printf ("%s:\n", name);
#define p(f, m) if (pfkeystat[f] || sflag <= 1) \
printf(m, (unsigned long long)pfkeystat[f], plural(pfkeystat[f]))
/* userland -> kernel */
p(PFKEY_STAT_OUT_TOTAL, "\t%llu request%s sent from userland\n");
p(PFKEY_STAT_OUT_BYTES, "\t%llu byte%s sent from userland\n");
for (first = 1, type = 0; type < 256; type++) {
if (pfkeystat[PFKEY_STAT_OUT_MSGTYPE + type] == 0)
continue;
if (first) {
printf("\thistogram by message type:\n");
first = 0;
}
printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
(unsigned long long)pfkeystat[PFKEY_STAT_OUT_MSGTYPE + type]);
}
p(PFKEY_STAT_OUT_INVLEN, "\t%llu message%s with invalid length field\n");
p(PFKEY_STAT_OUT_INVVER, "\t%llu message%s with invalid version field\n");
p(PFKEY_STAT_OUT_INVMSGTYPE, "\t%llu message%s with invalid message type field\n");
p(PFKEY_STAT_OUT_TOOSHORT, "\t%llu message%s too short\n");
p(PFKEY_STAT_OUT_NOMEM, "\t%llu message%s with memory allocation failure\n");
p(PFKEY_STAT_OUT_DUPEXT, "\t%llu message%s with duplicate extension\n");
p(PFKEY_STAT_OUT_INVEXTTYPE, "\t%llu message%s with invalid extension type\n");
p(PFKEY_STAT_OUT_INVSATYPE, "\t%llu message%s with invalid sa type\n");
p(PFKEY_STAT_OUT_INVADDR, "\t%llu message%s with invalid address extension\n");
/* kernel -> userland */
p(PFKEY_STAT_IN_TOTAL, "\t%llu request%s sent to userland\n");
p(PFKEY_STAT_IN_BYTES, "\t%llu byte%s sent to userland\n");
for (first = 1, type = 0; type < 256; type++) {
if (pfkeystat[PFKEY_STAT_IN_MSGTYPE + type] == 0)
continue;
if (first) {
printf("\thistogram by message type:\n");
first = 0;
}
printf("\t\t%s: %llu\n", pfkey_msgtype_names(type),
(unsigned long long)pfkeystat[PFKEY_STAT_IN_MSGTYPE + type]);
}
p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_ONE,
"\t%llu message%s toward single socket\n");
p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_ALL,
"\t%llu message%s toward all sockets\n");
p(PFKEY_STAT_IN_MSGTARGET + KEY_SENDUP_REGISTERED,
"\t%llu message%s toward registered sockets\n");
p(PFKEY_STAT_IN_NOMEM, "\t%llu message%s with memory allocation failure\n");
#undef p
}
#endif /*IPSEC*/

119
usr.bin/netstat/pfsync.c Normal file
View File

@ -0,0 +1,119 @@
/* $NetBSD: pfsync.c,v 1.1 2011/03/01 19:01:59 dyoung 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: pfsync.c,v 1.1 2011/03/01 19:01:59 dyoung Exp $");
#endif /* not lint */
#define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/sysctl.h>
#include <net/if_arp.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_icmp.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif
#include <net/pfvar.h>
#include <net/if_pfsync.h>
#include <arpa/inet.h>
#include <kvm.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include "netstat.h"
#include "prog_ops.h"
/*
* Dump PFSYNC statistics structure.
*/
void
pfsync_stats(u_long off, const char *name)
{
uint64_t pfsyncstat[PFSYNC_NSTATS];
if (use_sysctl) {
size_t size = sizeof(pfsyncstat);
if (sysctlbyname("net.inet.pfsync.stats", pfsyncstat, &size,
NULL, 0) == -1)
return;
} else {
warnx("%s stats not available via KVM.", name);
return;
}
printf("%s:\n", name);
#define p(f, m) if (pfsyncstat[f] || sflag <= 1) \
printf(m, pfsyncstat[f], plural(pfsyncstat[f]))
#define p2(f, m) if (pfsyncstat[f] || sflag <= 1) \
printf(m, pfsyncstat[f])
p(PFSYNC_STAT_IPACKETS, "\t%" PRIu64 " packet%s received (IPv4)\n");
p(PFSYNC_STAT_IPACKETS6,"\t%" PRIu64 " packet%s received (IPv6)\n");
p(PFSYNC_STAT_BADIF, "\t\t%" PRIu64 " packet%s discarded for bad interface\n");
p(PFSYNC_STAT_BADTTL, "\t\t%" PRIu64 " packet%s discarded for bad ttl\n");
p(PFSYNC_STAT_HDROPS, "\t\t%" PRIu64 " packet%s shorter than header\n");
p(PFSYNC_STAT_BADVER, "\t\t%" PRIu64 " packet%s discarded for bad version\n");
p(PFSYNC_STAT_BADAUTH, "\t\t%" PRIu64 " packet%s discarded for bad HMAC\n");
p(PFSYNC_STAT_BADACT,"\t\t%" PRIu64 " packet%s discarded for bad action\n");
p(PFSYNC_STAT_BADLEN, "\t\t%" PRIu64 " packet%s discarded for short packet\n");
p(PFSYNC_STAT_BADVAL, "\t\t%" PRIu64 " state%s discarded for bad values\n");
p(PFSYNC_STAT_STALE, "\t\t%" PRIu64 " stale state%s\n");
p(PFSYNC_STAT_BADSTATE, "\t\t%" PRIu64 " failed state lookup/insert%s\n");
p(PFSYNC_STAT_OPACKETS, "\t%" PRIu64 " packet%s sent (IPv4)\n");
p(PFSYNC_STAT_OPACKETS6, "\t%" PRIu64 " packet%s sent (IPv6)\n");
p2(PFSYNC_STAT_ONOMEM, "\t\t%" PRIu64 " send failed due to mbuf memory error\n");
p2(PFSYNC_STAT_OERRORS, "\t\t%" PRIu64 " send error\n");
#undef p
#undef p2
}

View File

@ -0,0 +1,50 @@
/* $NetBSD: prog_ops.h,v 1.2 2010/12/15 11:22:41 pooka Exp $ */
/*
* Copyright (c) 2010 The NetBSD Foundation, Inc.
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
#ifndef _PROG_OPS_H_
#define _PROG_OPS_H_
#include <sys/types.h>
#ifndef CRUNCHOPS
struct prog_ops {
int (*op_init)(void);
int (*op_sysctl)(const int *, u_int, void *, size_t *,
const void *, size_t);
};
extern const struct prog_ops prog_ops;
#define prog_init prog_ops.op_init
#define prog_sysctl prog_ops.op_sysctl
#else
#define prog_init ((int (*)(void))NULL)
#define prog_sysctl sysctl
#endif
#endif /* _PROG_OPS_H_ */

334
usr.bin/netstat/route.c Normal file
View File

@ -0,0 +1,334 @@
/* $NetBSD: route.c,v 1.84 2015/05/25 03:56:20 manu 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
#else
__RCSID("$NetBSD: route.c,v 1.84 2015/05/25 03:56:20 manu Exp $");
#endif
#endif /* not lint */
#include <stdbool.h>
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/mbuf.h>
#include <sys/un.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netatalk/at.h>
#include <netmpls/mpls.h>
#include <sys/sysctl.h>
#include <arpa/inet.h>
#include <err.h>
#include <kvm.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#include "rtutil.h"
#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
/*
* XXX we put all of the sockaddr types in here to force the alignment
* to be correct.
*/
static union sockaddr_union {
struct sockaddr u_sa;
struct sockaddr_in u_in;
struct sockaddr_un u_un;
struct sockaddr_at u_at;
struct sockaddr_dl u_dl;
u_short u_data[128];
int u_dummy; /* force word-alignment */
} pt_u;
int do_rtent = 0;
struct rtentry rtentry;
struct radix_node rnode;
struct radix_mask rmask;
static struct sockaddr *kgetsa(const struct sockaddr *);
static void p_tree(struct radix_node *);
static void p_rtnode(void);
static void p_krtentry(struct rtentry *);
/*
* Print routing tables.
*/
void
routepr(u_long rtree)
{
struct radix_node_head *rnh, head;
struct radix_node_head *rt_nodes[AF_MAX+1];
int i;
printf("Routing tables\n");
if (rtree == 0) {
printf("rt_tables: symbol not in namelist\n");
return;
}
kget(rtree, rt_nodes);
for (i = 0; i <= AF_MAX; i++) {
if ((rnh = rt_nodes[i]) == 0)
continue;
kget(rnh, head);
if (i == AF_UNSPEC) {
if (Aflag && (af == 0 || af == 0xff)) {
printf("Netmasks:\n");
p_tree(head.rnh_treetop);
}
} else if (af == AF_UNSPEC || af == i) {
p_family(i);
do_rtent = 1;
p_rthdr(i, Aflag);
p_tree(head.rnh_treetop);
}
}
}
static struct sockaddr *
kgetsa(const struct sockaddr *dst)
{
kget(dst, pt_u.u_sa);
if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
return (&pt_u.u_sa);
}
static void
p_tree(struct radix_node *rn)
{
again:
kget(rn, rnode);
if (rnode.rn_b < 0) {
if (Aflag)
printf("%-8.8lx ", (u_long) rn);
if (rnode.rn_flags & RNF_ROOT) {
if (Aflag)
printf("(root node)%s",
rnode.rn_dupedkey ? " =>\n" : "\n");
} else if (do_rtent) {
kget(rn, rtentry);
p_krtentry(&rtentry);
if (Aflag)
p_rtnode();
} else {
p_sockaddr(kgetsa((const struct sockaddr *)rnode.rn_key),
NULL, 0, 44, nflag);
putchar('\n');
}
if ((rn = rnode.rn_dupedkey) != NULL)
goto again;
} else {
if (Aflag && do_rtent) {
printf("%-8.8lx ", (u_long) rn);
p_rtnode();
}
rn = rnode.rn_r;
p_tree(rnode.rn_l);
p_tree(rn);
}
}
static void
p_rtnode(void)
{
struct radix_mask *rm = rnode.rn_mklist;
char nbuf[20];
if (rnode.rn_b < 0) {
if (rnode.rn_mask) {
printf("\t mask ");
p_sockaddr(kgetsa((const struct sockaddr *)rnode.rn_mask),
NULL, 0, -1, nflag);
} else if (rm == 0)
return;
} else {
(void)snprintf(nbuf, sizeof nbuf, "(%d)", rnode.rn_b);
printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long) rnode.rn_l,
(u_long) rnode.rn_r);
}
while (rm) {
kget(rm, rmask);
(void)snprintf(nbuf, sizeof nbuf, " %d refs, ", rmask.rm_refs);
printf(" mk = %8.8lx {(%d),%s", (u_long) rm,
-1 - rmask.rm_b, rmask.rm_refs ? nbuf : " ");
if (rmask.rm_flags & RNF_NORMAL) {
struct radix_node rnode_aux;
printf(" <normal>, ");
kget(rmask.rm_leaf, rnode_aux);
p_sockaddr(kgetsa((const struct sockaddr *)rnode_aux.rn_mask),
NULL, 0, -1, nflag);
} else
p_sockaddr(kgetsa((const struct sockaddr *)rmask.rm_mask),
NULL, 0, -1, nflag);
putchar('}');
if ((rm = rmask.rm_mklist) != NULL)
printf(" ->");
}
putchar('\n');
}
static struct sockaddr *sockcopy(struct sockaddr *, union sockaddr_union *);
/*
* copy a sockaddr into an allocated region, allocate at least sockaddr
* bytes and zero unused
*/
static struct sockaddr *
sockcopy(struct sockaddr *sp, union sockaddr_union *dp)
{
int len;
if (sp == 0 || sp->sa_len == 0)
(void)memset(dp, 0, sizeof (*sp));
else {
len = (sp->sa_len >= sizeof (*sp)) ? sp->sa_len : sizeof (*sp);
(void)memcpy(dp, sp, len);
}
return ((struct sockaddr *)dp);
}
static void
p_krtentry(struct rtentry *rt)
{
static struct ifnet ifnet, *lastif;
union sockaddr_union addr_un, mask_un;
struct sockaddr *addr, *mask;
if (Lflag && (rt->rt_flags & RTF_LLINFO))
return;
memset(&addr_un, 0, sizeof(addr_un));
memset(&mask_un, 0, sizeof(mask_un));
addr = sockcopy(kgetsa(rt_getkey(rt)), &addr_un);
if (rt_mask(rt))
mask = sockcopy(kgetsa(rt_mask(rt)), &mask_un);
else
mask = sockcopy(NULL, &mask_un);
p_addr(addr, mask, rt->rt_flags, nflag);
p_gwaddr(kgetsa(rt->rt_gateway), kgetsa(rt->rt_gateway)->sa_family, nflag);
p_flags(rt->rt_flags);
printf("%6d %8"PRIu64" ", rt->rt_refcnt, rt->rt_use);
if (rt->rt_rmx.rmx_mtu)
printf("%6"PRIu64, rt->rt_rmx.rmx_mtu);
else
printf("%6s", "-");
putchar((rt->rt_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
if (tagflag == 1) {
#ifndef SMALL
if (rt->rt_tag != NULL) {
const struct sockaddr *tagsa = kgetsa(rt->rt_tag);
char *tagstr;
if (tagsa->sa_family == AF_MPLS) {
tagstr = mpls_ntoa(tagsa);
if (strlen(tagstr) < 7)
printf("%7s", tagstr);
else
printf("%s", tagstr);
}
else
printf("%7s", "-");
} else
#endif
printf("%7s", "-");
}
if (rt->rt_ifp) {
if (rt->rt_ifp != lastif) {
kget(rt->rt_ifp, ifnet);
lastif = rt->rt_ifp;
}
printf(" %.16s%s", ifnet.if_xname,
rt->rt_nodes[0].rn_dupedkey ? " =>" : "");
}
putchar('\n');
#ifndef SMALL
if (vflag)
p_rtrmx(&rt->rt_rmx);
#endif
}
/*
* Print routing statistics
*/
void
rt_stats(u_long off)
{
struct rtstat rtstats;
if (use_sysctl) {
size_t rtsize = sizeof(rtstats);
if (sysctlbyname("net.route.stats", &rtstats, &rtsize,
NULL, 0) == -1)
err(1, "rt_stats: sysctl");
} else if (off == 0) {
printf("rtstat: symbol not in namelist\n");
return;
} else
kread(off, (char *)&rtstats, sizeof(rtstats));
printf("routing:\n");
printf("\t%llu bad routing redirect%s\n",
(unsigned long long)rtstats.rts_badredirect,
plural(rtstats.rts_badredirect));
printf("\t%llu dynamically created route%s\n",
(unsigned long long)rtstats.rts_dynamic,
plural(rtstats.rts_dynamic));
printf("\t%llu new gateway%s due to redirects\n",
(unsigned long long)rtstats.rts_newgateway,
plural(rtstats.rts_newgateway));
printf("\t%llu destination%s found unreachable\n",
(unsigned long long)rtstats.rts_unreach,
plural(rtstats.rts_unreach));
printf("\t%llu use%s of a wildcard route\n",
(unsigned long long)rtstats.rts_wildcard,
plural(rtstats.rts_wildcard));
}

231
usr.bin/netstat/unix.c Normal file
View File

@ -0,0 +1,231 @@
/* $NetBSD: unix.c,v 1.34 2012/03/20 20:34:58 matt 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)unix.c 8.1 (Berkeley) 6/6/93";
#else
__RCSID("$NetBSD: unix.c,v 1.34 2012/03/20 20:34:58 matt Exp $");
#endif
#endif /* not lint */
/*
* Display protocol blocks in the unix domain.
*/
#define _KERNEL
#include <sys/types.h>
#undef _KERNEL
#include <sys/param.h>
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/sysctl.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#define _KERNEL
#include <sys/file.h>
#undef _KERNEL
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <kvm.h>
#include <err.h>
#include "netstat.h"
#include "prog_ops.h"
static void unixdomainprhdr(void);
static void unixdomainpr0(u_long, u_long, u_long, u_long, u_long, u_long,
u_long, u_long, u_long, struct sockaddr_un *, int);
static void unixdomainpr(struct socket *, void *);
static struct file *file, *fileNFILE;
static int ns_nfiles;
static void
unixdomainprhdr(void)
{
printf("Active UNIX domain sockets\n");
printf("%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n",
"Address", "Type", "Recv-Q", "Send-Q", "Inode", "Conn", "Refs",
"Nextref");
}
static const char * const socktype[] =
{ "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
static void
unixdomainpr0(u_long so_pcb, u_long so_type, u_long rcvq, u_long sndq,
u_long inode, u_long conn, u_long refs, u_long nextref,
u_long addr, struct sockaddr_un *sun, int remote)
{
printf("%8lx %-6.6s %6ld %6ld %8lx %8lx %8lx %8lx",
so_pcb, socktype[so_type], rcvq, sndq, inode, conn, refs,
nextref);
if (addr || remote)
printf((remote ? " -> %.*s" : " %.*s"),
(int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
sun->sun_path);
putchar('\n');
}
static void
unixdomainpr(struct socket *so, void *soaddr)
{
struct unpcb unp, runp;
struct sockaddr_un sun, rsun;
static int first = 1;
int remote = 0;
if (kread((u_long)so->so_pcb, (char *)&unp, sizeof (unp)))
return;
if (unp.unp_addr)
if (kread((u_long)unp.unp_addr, (char *)&sun, sizeof (sun)))
unp.unp_addr = 0;
if (!unp.unp_addr) {
memset(&rsun, 0, sizeof(rsun));
if (unp.unp_conn &&
kread((u_long)unp.unp_conn, (char *)&runp, sizeof (runp)) == 0 &&
runp.unp_addr &&
kread((u_long)runp.unp_addr, (char *)&rsun, sizeof (rsun)) == 0 &&
rsun.sun_path[0] != '\0')
remote = 1;
}
if (first) {
unixdomainprhdr();
first = 0;
}
unixdomainpr0((u_long)so->so_pcb, so->so_type, so->so_rcv.sb_cc,
so->so_snd.sb_cc, (u_long)unp.unp_vnode,
(u_long)unp.unp_conn, (u_long)unp.unp_refs,
(u_long)unp.unp_nextref, (u_long)unp.unp_addr,
remote ? &rsun : &sun, remote);
}
void
unixpr(u_long off)
{
struct file *fp;
struct socket sock, *so = &sock;
char *filebuf;
struct protosw *unixsw = (struct protosw *)off;
if (use_sysctl) {
struct kinfo_pcb *pcblist;
int mib[8];
size_t namelen = 0, size = 0, i;
const char *mibnames[] = {
"net.local.stream.pcblist",
"net.local.dgram.pcblist",
"net.local.seqpacket.pcblist",
NULL,
};
const char **mibname;
static int first = 1;
for (mibname = mibnames; *mibname; mibname++) {
memset(mib, 0, sizeof(mib));
if (sysctlnametomib(*mibname, mib,
&namelen) == -1)
err(1, "sysctlnametomib: %s", *mibname);
if (prog_sysctl(mib, sizeof(mib) / sizeof(*mib),
NULL, &size, NULL, 0) == -1)
err(1, "sysctl (query)");
if ((pcblist = malloc(size)) == NULL)
err(1, "malloc");
memset(pcblist, 0, size);
mib[6] = sizeof(*pcblist);
mib[7] = size / sizeof(*pcblist);
if (prog_sysctl(mib, sizeof(mib) / sizeof(*mib),
pcblist, &size, NULL, 0) == -1)
err(1, "sysctl (copy)");
for (i = 0; i < size / sizeof(*pcblist); i++) {
struct kinfo_pcb *ki = &pcblist[i];
struct sockaddr_un *sun;
int remote = 0;
if (first) {
unixdomainprhdr();
first = 0;
}
sun = (struct sockaddr_un *)&ki->ki_dst;
if (sun->sun_path[0] != '\0') {
remote = 1;
} else {
sun = (struct sockaddr_un *)&ki->ki_src;
}
unixdomainpr0(ki->ki_pcbaddr, ki->ki_type,
ki->ki_rcvq, ki->ki_sndq,
ki->ki_vnode, ki->ki_conn,
ki->ki_refs, ki->ki_nextref,
ki->ki_sockaddr, sun, remote);
}
free(pcblist);
}
} else {
filebuf = (char *)kvm_getfiles(get_kvmd(), KERN_FILE,
0, &ns_nfiles);
if (filebuf == 0) {
printf("file table read error: %s",
kvm_geterr(get_kvmd()));
return;
}
file = (struct file *)(filebuf + sizeof(fp));
fileNFILE = file + ns_nfiles;
for (fp = file; fp < fileNFILE; fp++) {
if (fp->f_count == 0 || fp->f_type != DTYPE_SOCKET)
continue;
if (kread((u_long)fp->f_data, (char *)so, sizeof (*so)))
continue;
/* kludge */
if (so->so_proto >= unixsw && so->so_proto <= unixsw + 2)
if (so->so_pcb)
unixdomainpr(so, fp->f_data);
}
}
}

439
usr.bin/netstat/vtw.c Normal file
View File

@ -0,0 +1,439 @@
/* $NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $ */
/*
* Copyright (c) 2011 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Coyote Point Systems, Inc.
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
*/
/*
* 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. 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.
*/
#include <sys/cdefs.h>
#ifndef lint
#if 0
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
#else
__RCSID("$NetBSD: vtw.c,v 1.8 2015/06/16 22:54:10 christos Exp $");
#endif
#endif /* not lint */
#define _CALLOUT_PRIVATE /* for defs in sys/callout.h */
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/sysctl.h>
#include <net/if_arp.h>
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/ip_icmp.h>
#ifdef INET6
#include <netinet/ip6.h>
#endif
#include <netinet/icmp_var.h>
#include <netinet/igmp_var.h>
#include <netinet/ip_var.h>
#include <netinet/pim_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <netinet/tcp_seq.h>
#include <netinet/tcp_fsm.h>
#include <netinet/tcp_timer.h>
#include <netinet/tcp_var.h>
#include <netinet/tcp_debug.h>
#include <netinet/udp.h>
#include <netinet/ip_carp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp_vtw.h>
#include <arpa/inet.h>
#include <kvm.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <err.h>
#include "netstat.h"
#include "vtw.h"
#include "prog_ops.h"
static void snarf(const void *, void *, size_t);
static void *lookup(const char *);
static void process_vtw(const vtw_ctl_t *, void (*)(const vtw_t *));
static void
snarf(const void *addr, void *buf, size_t len)
{
size_t cc;
memset(buf, 0, len);
cc = kvm_read(get_kvmd(), (unsigned long) addr, buf, len);
if (cc != len) {
warnx("%s: short read at %p, len %zx cc %zx", __func__, addr,
len, cc);
}
}
static void *
lookup(const char *name)
{
kvm_t *k;
struct nlist nl[2];
nl[0].n_name = name;
nl[0].n_value = 0;
nl[1].n_name = NULL;
if ((k = get_kvmd()) == NULL) {
if (Vflag)
errx(EXIT_FAILURE, "kvm not available");
return NULL;
}
switch (kvm_nlist(k, &nl[0])) {
case -1:
err(EXIT_FAILURE, "kvm_nlist");
break;
case 0:
return (void *)nl[0].n_value;
default:
if (Vflag)
errx(EXIT_FAILURE, "%s missing in symbol table", name);
break;
}
return NULL;
}
void
timebase(struct timeval *tv)
{
void *p;
struct bintime timebasebin;
p = lookup("timebasebin");
if (!p)
return;
snarf(p, &timebasebin, sizeof(timebasebin));
bintime2timeval(&timebasebin, tv);
}
static void
process_vtw(const vtw_ctl_t * ctl, void (*print)(const vtw_t *))
{
vtw_t *vp;
for (vp = ctl->base.v; vp && vp <= ctl->lim.v;) {
(*print)(vp);
if (ctl->is_v4) {
vtw_v4_t *v4 = (vtw_v4_t *)vp;
vp = &(++v4)->common;
} else if (ctl->is_v6) {
vtw_v6_t *v6 = (vtw_v6_t *)vp;
vp = &(++v6)->common;
}
}
}
void
show_vtw_stats(void)
{
vtw_stats_t stats;
void *p;
if (!Vflag)
return;
if ((p = lookup("vtw_stats")) == NULL)
return;
snarf(p, &stats, sizeof(stats));
printf("\t\t%" PRIu64 " inserts\n", stats.ins);
printf("\t\t%" PRIu64 " deletes\n", stats.del);
printf("\t\t%" PRIu64 " assassinations\n", stats.kill);
printf("\tvestigial time-wait lookup_connect\n");
printf("\t\t%" PRIu64 " look\n", stats.look[0]);
printf("\t\t%" PRIu64 " hit\n", stats.hit[0]);
printf("\t\t%" PRIu64 " miss\n", stats.miss[0]);
printf("\t\t%" PRIu64 " probe\n", stats.probe[0]);
printf("\t\t%" PRIu64 " losing\n", stats.losing[0]);
printf("\t\t%" PRIu64 " max_chain\n", stats.max_chain[0]);
printf("\t\t%" PRIu64 " max_probe\n", stats.max_probe[0]);
printf("\t\t%" PRIu64 " max_loss\n", stats.max_loss[0]);
printf("\tvestigial time-wait lookup_port\n");
printf("\t\t%" PRIu64 " look\n", stats.look[1]);
printf("\t\t%" PRIu64 " hit\n", stats.hit[1]);
printf("\t\t%" PRIu64 " miss\n", stats.miss[1]);
printf("\t\t%" PRIu64 " probe\n", stats.probe[1]);
printf("\t\t%" PRIu64 " losing\n", stats.losing[1]);
printf("\t\t%" PRIu64 " max_chain\n", stats.max_chain[1]);
printf("\t\t%" PRIu64 " max_probe\n", stats.max_probe[1]);
printf("\t\t%" PRIu64 " max_loss\n", stats.max_loss[1]);
}
void
show_vtw_v4(void (*print)(const vtw_t *))
{
fatp_t *base, *lim;
fatp_t **hash, **port;
size_t n;
fatp_ctl_t fat_tcpv4;
vtw_ctl_t vtw_tcpv4[VTW_NCLASS];
int i;
int mem = 0;
void *p;
if ((p = lookup("fat_tcpv4")) == NULL)
return;
snarf(p, &fat_tcpv4, sizeof(fat_tcpv4));
if ((p = lookup("vtw_tcpv4")) == NULL)
return;
snarf(p, &vtw_tcpv4[0], sizeof(vtw_tcpv4));
mem += sizeof(fat_tcpv4);
mem += sizeof(vtw_tcpv4);
/* snarf/adjust vtw_ctl */
for (i = 0; i < VTW_NCLASS; ++i) {
vtw_v4_t *kbase, *klim;
vtw_v4_t *ubase;
ptrdiff_t delta;
kbase = vtw_tcpv4[i].base.v4;
klim = vtw_tcpv4[i].lim.v4;
if (!kbase | !klim)
continue;
n = (klim - kbase + 1);
if (!i) {
if ((ubase = malloc(n * sizeof(*kbase))) == NULL)
err(EXIT_FAILURE, NULL);
snarf(kbase, ubase, n * sizeof(*ubase));
mem += n * sizeof(*ubase);
} else {
ubase = vtw_tcpv4[0].base.v4;
}
delta = ubase - kbase;
vtw_tcpv4[i].base.v4 += delta;
vtw_tcpv4[i].lim.v4 += delta;
vtw_tcpv4[i].alloc.v4 += delta;
vtw_tcpv4[i].fat = &fat_tcpv4;
if (vtw_tcpv4[i].oldest.v4)
vtw_tcpv4[i].oldest.v4 += delta;
}
/* snarf/adjust fat_ctl */
base = fat_tcpv4.base;
lim = fat_tcpv4.lim;
if (!base | !lim)
goto end;
mem += (lim - base + 1) * sizeof(*base);
fat_tcpv4.base = malloc((lim - base + 1) * sizeof(*base));
if (fat_tcpv4.base == NULL)
err(EXIT_FAILURE, NULL);
fat_tcpv4.lim = fat_tcpv4.base + (lim - base);
snarf(base, fat_tcpv4.base, sizeof(*base) * (lim - base + 1));
fat_tcpv4.vtw = &vtw_tcpv4[0];
fat_tcpv4.free = fat_tcpv4.base + (fat_tcpv4.free - base);
n = fat_tcpv4.mask + 1;
hash = fat_tcpv4.hash;
port = fat_tcpv4.port;
fat_tcpv4.hash = malloc(n * sizeof(*hash));
fat_tcpv4.port = malloc(n * sizeof(*port));
if (fat_tcpv4.hash == NULL || fat_tcpv4.port == NULL)
err(EXIT_FAILURE, NULL);
snarf(hash, fat_tcpv4.hash, n * sizeof(*hash));
snarf(port, fat_tcpv4.port, n * sizeof(*port));
end:
process_vtw(&vtw_tcpv4[0], print);
#if 0
if (Vflag && vflag) {
printf("total memory for VTW in current config: %d bytes %f MB\n"
,mem
,mem / (1024.0 * 1024));
}
#endif
}
void
show_vtw_v6(void (*print)(const vtw_t *))
{
fatp_t *base, *lim;
fatp_t **hash, **port;
size_t n;
fatp_ctl_t fat_tcpv6;
vtw_ctl_t vtw_tcpv6[VTW_NCLASS];
int i;
int mem = 0;
void *p;
if ((p = lookup("fat_tcpv6")) == NULL)
return;
snarf(p, &fat_tcpv6, sizeof(fat_tcpv6));
if ((p = lookup("vtw_tcpv6")) == NULL)
return;
snarf(p, &vtw_tcpv6[0], sizeof(vtw_tcpv6));
mem += sizeof(fat_tcpv6);
mem += sizeof(vtw_tcpv6);
for (i = 0; i < VTW_NCLASS; ++i) {
vtw_v6_t *kbase, *klim;
vtw_v6_t *ubase;
ptrdiff_t delta;
kbase = vtw_tcpv6[i].base.v6;
klim = vtw_tcpv6[i].lim.v6;
if (!kbase | !klim)
continue;
n = (klim - kbase + 1);
if (!i) {
if ((ubase = malloc(n * sizeof(*kbase))) == NULL)
err(EXIT_FAILURE, NULL);
snarf(kbase, ubase, n * sizeof(*ubase));
mem += n * sizeof(*ubase);
} else {
ubase = vtw_tcpv6[0].base.v6;
}
delta = ubase - kbase;
vtw_tcpv6[i].base.v6 += delta;
vtw_tcpv6[i].lim.v6 += delta;
vtw_tcpv6[i].alloc.v6 += delta;
vtw_tcpv6[i].fat = &fat_tcpv6;
if (vtw_tcpv6[i].oldest.v6)
vtw_tcpv6[i].oldest.v6 += delta;
}
base = fat_tcpv6.base;
lim = fat_tcpv6.lim;
if (!base | !lim)
goto end;
mem += (lim - base + 1) * sizeof(*base);
fat_tcpv6.base = malloc((lim - base + 1) * sizeof(*base));
if (fat_tcpv6.base == NULL)
err(EXIT_FAILURE, NULL);
fat_tcpv6.lim = fat_tcpv6.base + (lim - base);
snarf(base, fat_tcpv6.base, sizeof(*base) * (lim - base + 1));
fat_tcpv6.vtw = &vtw_tcpv6[0];
fat_tcpv6.free = fat_tcpv6.base + (fat_tcpv6.free - base);
n = fat_tcpv6.mask + 1;
hash = fat_tcpv6.hash;
port = fat_tcpv6.port;
fat_tcpv6.hash = malloc(n * sizeof(*hash));
fat_tcpv6.port = malloc(n * sizeof(*port));
if (fat_tcpv6.hash == NULL || fat_tcpv6.port == NULL)
err(EXIT_FAILURE, NULL);
snarf(hash, fat_tcpv6.hash, n * sizeof(*hash));
snarf(port, fat_tcpv6.port, n * sizeof(*port));
end:
process_vtw(&vtw_tcpv6[0], print);
#if 0
if (Vflag && vflag) {
printf("total memory for VTW in current config: %d bytes %f MB\n"
,mem
,mem / (1024.0 * 1024));
}
#endif
}

9
usr.bin/netstat/vtw.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef _NETSTAT_VTW_H
#define _NETSTAT_VTW_H
void show_vtw_stats(void);
void show_vtw_v4(void (*)(const vtw_t *));
void show_vtw_v6(void (*)(const vtw_t *));
void timebase(struct timeval *);
#endif /* _NETSTAT_VTW_H */