netstat: New command - Almost completely compiles

Currently disable in Makefile until all builds. Adding it so
others can assist in debugging issues.
This commit is contained in:
Joel Sherrill 2012-09-07 12:50:18 -05:00
parent db068df3c4
commit f1710b69d4
18 changed files with 9492 additions and 0 deletions

View File

@ -0,0 +1,293 @@
/*-
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)atalk.c 1.1 (Whistle) 6/6/96";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <arpa/inet.h>
#include <net/route.h>
#include <netatalk/at.h>
#include <netatalk/ddp_var.h>
#include <errno.h>
#include <nlist.h>
#include <netdb.h>
#include <stdint.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(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("*");
}
}
sprintf(mybuf,"%hu",ntohs(sat->sat_addr.s_net));
return mybuf;
}
static const char *
at_pr_host(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("*");
}
}
sprintf(mybuf,"%d",(unsigned int)sat->sat_addr.s_node);
return mybuf;
}
static const char *
at_pr_port(struct sockaddr_at *sat)
{
static char mybuf[50];
struct servent *serv;
switch(sat->sat_port) {
case ATADDR_ANYPORT:
return("*");
case 0xff:
return "????";
default:
if (numeric_port) {
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int)sat->sat_port);
} else {
serv = getservbyport(sat->sat_port, "ddp");
if (serv == NULL)
(void)snprintf(mybuf, sizeof(mybuf), "%d",
(unsigned int) sat->sat_port);
else
(void) snprintf(mybuf, sizeof(mybuf), "%s",
serv->s_name);
}
}
return mybuf;
}
static char *
at_pr_range(struct sockaddr_at *sat)
{
static char mybuf[50];
if(sat->sat_range.r_netrange.nr_firstnet
!= sat->sat_range.r_netrange.nr_lastnet) {
sprintf(mybuf,"%d-%d",
ntohs(sat->sat_range.r_netrange.nr_firstnet),
ntohs(sat->sat_range.r_netrange.nr_lastnet));
} else {
sprintf(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 */
char *
atalk_print(struct sockaddr *sa, int what)
{
struct sockaddr_at *sat = (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:
sprintf(mybuf,"%s",at_pr_net(sat, numeric));
break;
case 2:
sprintf(mybuf,"%s",at_pr_host(sat, numeric));
break;
case 3:
sprintf(mybuf,"%s.%s",
at_pr_net(sat, numeric),
at_pr_host(sat, numeric));
break;
case 0x10:
sprintf(mybuf,"%s", at_pr_range(sat));
}
if (what & 4) {
sprintf(mybuf+strlen(mybuf),".%s",at_pr_port(sat));
}
return mybuf;
}
char *
atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
{
int n;
static char buf[100];
struct sockaddr_at *sat1, *sat2;
struct sockaddr_at thesockaddr;
struct sockaddr *sa2;
sat1 = (struct sockaddr_at *)sa;
sat2 = (struct sockaddr_at *)mask;
sa2 = (struct sockaddr *)&thesockaddr;
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net & sat2->sat_addr.s_net;
snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 |(what & 8)));
if(sat2->sat_addr.s_net != 0xFFFF) {
thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net | ~sat2->sat_addr.s_net;
n = strlen(buf);
snprintf(buf + n, sizeof(buf) - n, "-%s", atalk_print(sa2, 1 |(what & 8)));
}
if(what & 2) {
n = strlen(buf);
snprintf(buf + n, sizeof(buf) - n, ".%s", atalk_print(sa, what & (~1)));
}
return(buf);
}
void
atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
int proto __unused)
{
struct ddpcb *this, *next;
if (off == 0)
return;
kread(off, (char *)&this, sizeof (struct ddpcb *));
for ( ; this != NULL; this = next) {
kread((u_long)this, (char *)&ddpcb, sizeof (ddpcb));
next = ddpcb.ddp_next;
#if 0
if (!aflag && atalk_nullhost(ddpcb.ddp_lsat) ) {
continue;
}
#endif
kread((u_long)ddpcb.ddp_socket, (char *)&sockb, sizeof (sockb));
if (first) {
printf("Active ATALK connections");
if (aflag)
printf(" (including servers)");
putchar('\n');
if (Aflag)
printf("%-8.8s ", "PCB");
printf(Aflag ?
"%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
"%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
"Proto", "Recv-Q", "Send-Q",
"Local Address", "Foreign Address", "(state)");
first = 0;
}
if (Aflag)
printf("%8lx ", (u_long) this);
printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
sockb.so_snd.sb_cc);
printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
(struct sockaddr *)&ddpcb.ddp_lsat,7));
printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
(struct sockaddr *)&ddpcb.ddp_fsat,7));
putchar('\n');
}
}
#define ANY(x,y,z) if (x || sflag <= 1) \
printf("\t%lu %s%s%s\n",x,y,plural(x),z)
/*
* Dump DDP statistics structure.
*/
void
ddp_stats(u_long off __unused, const char *name, int af1 __unused,
int proto __unused)
{
struct ddpstat ddpstat;
if (off == 0)
return;
kread(off, (char *)&ddpstat, sizeof (ddpstat));
printf("%s:\n", name);
ANY(ddpstat.ddps_short, "packet", " with short headers ");
ANY(ddpstat.ddps_long, "packet", " with long headers ");
ANY(ddpstat.ddps_nosum, "packet", " with no checksum ");
ANY(ddpstat.ddps_tooshort, "packet", " too short ");
ANY(ddpstat.ddps_badsum, "packet", " with bad checksum ");
ANY(ddpstat.ddps_toosmall, "packet", " with not enough data ");
ANY(ddpstat.ddps_forward, "packet", " forwarded ");
ANY(ddpstat.ddps_encap, "packet", " encapsulated ");
ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest ");
ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space ");
}

View File

@ -0,0 +1,158 @@
/*-
* Copyright (c) 2005 Christian S.J. Peron
* 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.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/param.h>
#ifndef __rtems__
#include <sys/user.h>
#endif
#include <net/if.h>
#ifdef __rtems__
#include <freebsd/net/if_var.h>
#include <freebsd/net/bpf.h>
#include <freebsd/net/bpfdesc.h>
#else
#include <net/if_var.h>
#include <net/bpf.h>
#include <net/bpfdesc.h>
#endif
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
/* print bpf stats */
static char *
bpf_pidname(pid_t pid)
{
#ifdef __rtems__
return "rtems";
#else
struct kinfo_proc newkp;
int error, mib[4];
size_t size;
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = pid;
size = sizeof(newkp);
error = sysctl(mib, 4, &newkp, &size, NULL, 0);
if (error < 0) {
warn("kern.proc.pid failed");
return (strdup("??????"));
}
return (strdup(newkp.ki_comm));
#endif
}
static void
bpf_flags(struct xbpf_d *bd, char *flagbuf)
{
*flagbuf++ = bd->bd_promisc ? 'p' : '-';
*flagbuf++ = bd->bd_immediate ? 'i' : '-';
*flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
*flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' :
((bd->bd_direction == BPF_D_OUT) ? 'o' : 's');
*flagbuf++ = bd->bd_feedback ? 'b' : '-';
*flagbuf++ = bd->bd_async ? 'a' : '-';
*flagbuf++ = bd->bd_locked ? 'l' : '-';
*flagbuf++ = '\0';
}
void
bpf_stats(char *ifname)
{
struct xbpf_d *d, *bd, zerostat;
char *pname, flagbuf[12];
size_t size;
if (zflag) {
bzero(&zerostat, sizeof(zerostat));
if (sysctlbyname("net.bpf.stats", NULL, NULL,
&zerostat, sizeof(zerostat)) < 0)
warn("failed to zero bpf counters");
return;
}
if (sysctlbyname("net.bpf.stats", NULL, &size,
NULL, 0) < 0) {
warn("net.bpf.stats");
return;
}
if (size == 0)
return;
bd = malloc(size);
if (bd == NULL) {
warn("malloc failed");
return;
}
if (sysctlbyname("net.bpf.stats", bd, &size,
NULL, 0) < 0) {
warn("net.bpf.stats");
free(bd);
return;
}
(void) printf("%5s %6s %7s %9s %9s %9s %5s %5s %s\n",
"Pid", "Netif", "Flags", "Recv", "Drop", "Match", "Sblen",
"Hblen", "Command");
for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) {
if (d->bd_structsize != sizeof(*d)) {
warnx("bpf_stats_extended: version mismatch");
return;
}
if (ifname && strcmp(ifname, d->bd_ifname) != 0)
continue;
bpf_flags(d, flagbuf);
pname = bpf_pidname(d->bd_pid);
(void) printf("%5d %6s %7s %9ju %9ju %9ju %5d %5d %s\n",
d->bd_pid, d->bd_ifname, flagbuf,
d->bd_rcount, d->bd_dcount, d->bd_fcount,
d->bd_slen, d->bd_hlen, pname);
free(pname);
}
free(bd);
}

View File

@ -0,0 +1,735 @@
/*-
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <net/if.h>
#ifdef __rtems__
#include <freebsd/net/if_var.h>
#else
#include <net/if_var.h>
#endif
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/ethernet.h>
#ifdef __rtems__
#include <freebsd/net/pfvar.h>
#include <freebsd/net/if_pfsync.h>
#include <netinet/in.h>
#include <freebsd/netinet/in_var.h>
/* IPX not on RTEMS */
/* #include <netipx/ipx.h> */
/* #include <netipx/ipx_if.h> */
#else
#include <net/pfvar.h>
#include <net/if_pfsync.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
#include <netipx/ipx.h>
#include <netipx/ipx_if.h>
#endif
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#ifdef __rtems__
/* apparently libutil.h is not needed */
#else
#include <libutil.h>
#endif
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#define YES 1
#define NO 0
static void sidewaysintpr(int, u_long);
static void catchalarm(int);
#ifdef INET6
static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
#endif
/*
* Dump pfsync statistics structure.
*/
void
pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct pfsyncstats pfsyncstat, zerostat;
size_t len = sizeof(struct pfsyncstats);
if (live) {
if (zflag)
memset(&zerostat, 0, len);
if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
if (errno != ENOENT)
warn("sysctl: net.inet.pfsync.stats");
return;
}
} else
kread(off, &pfsyncstat, len);
printf("%s:\n", name);
#define p(f, m) if (pfsyncstat.f || sflag <= 1) \
printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
#define p2(f, m) if (pfsyncstat.f || sflag <= 1) \
printf(m, (uintmax_t)pfsyncstat.f)
p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n");
p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n");
p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n");
p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n");
p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n");
p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n");
p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n");
p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n");
p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n");
p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n");
p(pfsyncs_stale, "\t\t%ju stale state%s\n");
p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n");
p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n");
p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n");
p2(pfsyncs_onomem, "\t\t%ju send failed due to mbuf memory error\n");
p2(pfsyncs_oerrors, "\t\t%ju send error\n");
#undef p
#undef p2
}
/*
* Display a formatted value, or a '-' in the same space.
*/
static void
show_stat(const char *fmt, int width, u_long value, short showvalue)
{
const char *lsep, *rsep;
char newfmt[32];
lsep = "";
if (strncmp(fmt, "LS", 2) == 0) {
lsep = " ";
fmt += 2;
}
rsep = " ";
if (strncmp(fmt, "NRS", 3) == 0) {
rsep = "";
fmt += 3;
}
if (showvalue == 0) {
/* Print just dash. */
sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
printf(newfmt, "-");
return;
}
if (hflag) {
char buf[5];
/* Format in human readable form. */
humanize_number(buf, sizeof(buf), (int64_t)value, "",
HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
printf(newfmt, buf);
} else {
/* Construct the format string. */
sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
printf(newfmt, value);
}
}
/*
* Print a description of the network interfaces.
*/
void
intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
{
struct ifnet ifnet;
struct ifnethead ifnethead;
union {
struct ifaddr ifa;
struct in_ifaddr in;
#ifdef INET6
struct in6_ifaddr in6;
#endif
struct ipx_ifaddr ipx;
} ifaddr;
u_long ifaddraddr;
u_long ifaddrfound;
u_long ifnetfound;
u_long opackets;
u_long ipackets;
u_long obytes;
u_long ibytes;
u_long omcasts;
u_long imcasts;
u_long oerrors;
u_long ierrors;
u_long idrops;
u_long collisions;
short timer;
int drops;
struct sockaddr *sa = NULL;
char name[IFNAMSIZ];
short network_layer;
short link_layer;
if (ifnetaddr == 0) {
printf("ifnet: symbol not defined\n");
return;
}
if (interval1) {
sidewaysintpr(interval1, ifnetaddr);
return;
}
if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0)
return;
ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
return;
if (!pfunc) {
if (Wflag)
printf("%-7.7s", "Name");
else
printf("%-5.5s", "Name");
printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s %5.5s",
"Mtu", "Network", "Address", "Ipkts", "Ierrs", "Idrop");
if (bflag)
printf(" %10.10s","Ibytes");
printf(" %8.8s %5.5s", "Opkts", "Oerrs");
if (bflag)
printf(" %10.10s","Obytes");
printf(" %5s", "Coll");
if (tflag)
printf(" %s", "Time");
if (dflag)
printf(" %s", "Drop");
putchar('\n');
}
ifaddraddr = 0;
while (ifnetaddr || ifaddraddr) {
struct sockaddr_in *sockin;
#ifdef INET6
struct sockaddr_in6 *sockin6;
#endif
char *cp;
int n, m;
network_layer = 0;
link_layer = 0;
if (ifaddraddr == 0) {
ifnetfound = ifnetaddr;
if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
return;
strlcpy(name, ifnet.if_xname, sizeof(name));
ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
if (interface != 0 && strcmp(name, interface) != 0)
continue;
cp = index(name, '\0');
if (pfunc) {
(*pfunc)(name);
continue;
}
if ((ifnet.if_flags&IFF_UP) == 0)
*cp++ = '*';
*cp = '\0';
ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
}
ifaddrfound = ifaddraddr;
/*
* Get the interface stats. These may get
* overriden below on a per-interface basis.
*/
opackets = ifnet.if_opackets;
ipackets = ifnet.if_ipackets;
obytes = ifnet.if_obytes;
ibytes = ifnet.if_ibytes;
omcasts = ifnet.if_omcasts;
imcasts = ifnet.if_imcasts;
oerrors = ifnet.if_oerrors;
ierrors = ifnet.if_ierrors;
idrops = ifnet.if_iqdrops;
collisions = ifnet.if_collisions;
timer = ifnet.if_timer;
drops = ifnet.if_snd.ifq_drops;
if (ifaddraddr == 0) {
if (Wflag)
printf("%-7.7s", name);
else
printf("%-5.5s", name);
printf(" %5lu ", ifnet.if_mtu);
printf("%-13.13s ", "none");
printf("%-17.17s ", "none");
} else {
if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)
!= 0) {
ifaddraddr = 0;
continue;
}
#define CP(x) ((char *)(x))
cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
CP(&ifaddr);
sa = (struct sockaddr *)cp;
if (af != AF_UNSPEC && sa->sa_family != af) {
ifaddraddr =
(u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
continue;
}
if (Wflag)
printf("%-7.7s", name);
else
printf("%-5.5s", name);
printf(" %5lu ", ifnet.if_mtu);
switch (sa->sa_family) {
case AF_UNSPEC:
printf("%-13.13s ", "none");
printf("%-15.15s ", "none");
break;
case AF_INET:
sockin = (struct sockaddr_in *)sa;
#ifdef notdef
/* can't use inet_makeaddr because kernel
* keeps nets unshifted.
*/
in = inet_makeaddr(ifaddr.in.ia_subnet,
INADDR_ANY);
printf("%-13.13s ", netname(in.s_addr,
ifaddr.in.ia_subnetmask));
#else
printf("%-13.13s ",
netname(htonl(ifaddr.in.ia_subnet),
ifaddr.in.ia_subnetmask));
#endif
printf("%-17.17s ",
routename(sockin->sin_addr.s_addr));
network_layer = 1;
break;
#ifdef INET6
case AF_INET6:
sockin6 = (struct sockaddr_in6 *)sa;
printf("%-13.13s ",
netname6(&ifaddr.in6.ia_addr,
&ifaddr.in6.ia_prefixmask.sin6_addr));
printf("%-17.17s ",
inet_ntop(AF_INET6,
&sockin6->sin6_addr,
ntop_buf, sizeof(ntop_buf)));
network_layer = 1;
break;
#endif /*INET6*/
case AF_IPX:
{
struct sockaddr_ipx *sipx =
(struct sockaddr_ipx *)sa;
u_long net;
char netnum[10];
*(union ipx_net *) &net = sipx->sipx_addr.x_net;
sprintf(netnum, "%lx", (u_long)ntohl(net));
printf("ipx:%-8s ", netnum);
/* printf("ipx:%-8s ", netname(net, 0L)); */
printf("%-17s ",
ipx_phost((struct sockaddr *)sipx));
}
network_layer = 1;
break;
case AF_APPLETALK:
printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
printf("%-11.11s ",atalk_print(sa,0x0b) );
break;
case AF_LINK:
{
struct sockaddr_dl *sdl =
(struct sockaddr_dl *)sa;
char linknum[10];
cp = (char *)LLADDR(sdl);
n = sdl->sdl_alen;
sprintf(linknum, "<Link#%d>", sdl->sdl_index);
m = printf("%-13.13s ", linknum);
}
goto hexprint;
default:
m = printf("(%d)", sa->sa_family);
for (cp = sa->sa_len + (char *)sa;
--cp > sa->sa_data && (*cp == 0);) {}
n = cp - sa->sa_data + 1;
cp = sa->sa_data;
hexprint:
while (--n >= 0)
m += printf("%02x%c", *cp++ & 0xff,
n > 0 ? ':' : ' ');
m = 32 - m;
while (m-- > 0)
putchar(' ');
link_layer = 1;
break;
}
/*
* Fixup the statistics for interfaces that
* update stats for their network addresses
*/
if (network_layer) {
opackets = ifaddr.in.ia_ifa.if_opackets;
ipackets = ifaddr.in.ia_ifa.if_ipackets;
obytes = ifaddr.in.ia_ifa.if_obytes;
ibytes = ifaddr.in.ia_ifa.if_ibytes;
}
ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
}
show_stat("lu", 8, ipackets, link_layer|network_layer);
show_stat("lu", 5, ierrors, link_layer);
show_stat("lu", 5, idrops, link_layer);
if (bflag)
show_stat("lu", 10, ibytes, link_layer|network_layer);
show_stat("lu", 8, opackets, link_layer|network_layer);
show_stat("lu", 5, oerrors, link_layer);
if (bflag)
show_stat("lu", 10, obytes, link_layer|network_layer);
show_stat("NRSlu", 5, collisions, link_layer);
if (tflag)
show_stat("LSd", 4, timer, link_layer);
if (dflag)
show_stat("LSd", 4, drops, link_layer);
putchar('\n');
if (aflag && ifaddrfound) {
/*
* Print family's multicast addresses
*/
struct ifmultiaddr *multiaddr;
struct ifmultiaddr ifma;
union {
struct sockaddr sa;
struct sockaddr_in in;
#ifdef INET6
struct sockaddr_in6 in6;
#endif /* INET6 */
struct sockaddr_dl dl;
} msa;
const char *fmt;
TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
if (kread((u_long)multiaddr, (char *)&ifma,
sizeof ifma) != 0)
break;
multiaddr = &ifma;
if (kread((u_long)ifma.ifma_addr, (char *)&msa,
sizeof msa) != 0)
break;
if (msa.sa.sa_family != sa->sa_family)
continue;
fmt = 0;
switch (msa.sa.sa_family) {
case AF_INET:
fmt = routename(msa.in.sin_addr.s_addr);
break;
#ifdef INET6
case AF_INET6:
printf("%*s %-19.19s(refs: %d)\n",
Wflag ? 27 : 25, "",
inet_ntop(AF_INET6,
&msa.in6.sin6_addr,
ntop_buf,
sizeof(ntop_buf)),
ifma.ifma_refcount);
break;
#endif /* INET6 */
case AF_LINK:
switch (msa.dl.sdl_type) {
case IFT_ETHER:
case IFT_FDDI:
fmt = ether_ntoa(
(struct ether_addr *)
LLADDR(&msa.dl));
break;
}
break;
}
if (fmt) {
printf("%*s %-17.17s",
Wflag ? 27 : 25, "", fmt);
if (msa.sa.sa_family == AF_LINK) {
printf(" %8lu", imcasts);
printf("%*s",
bflag ? 17 : 6, "");
printf(" %8lu", omcasts);
}
putchar('\n');
}
}
}
}
}
struct iftot {
SLIST_ENTRY(iftot) chain;
char ift_name[IFNAMSIZ]; /* interface name */
u_long ift_ip; /* input packets */
u_long ift_ie; /* input errors */
u_long ift_id; /* input drops */
u_long ift_op; /* output packets */
u_long ift_oe; /* output errors */
u_long ift_co; /* collisions */
u_int ift_dr; /* drops */
u_long ift_ib; /* input bytes */
u_long ift_ob; /* output bytes */
};
u_char signalled; /* set if alarm goes off "early" */
/*
* Print a running summary of interface statistics.
* Repeat display every interval1 seconds, showing statistics
* collected over that interval. Assumes that interval1 is non-zero.
* First line printed at top of screen is always cumulative.
* XXX - should be rewritten to use ifmib(4).
*/
static void
sidewaysintpr(int interval1, u_long off)
{
struct ifnet ifnet;
u_long firstifnet;
struct ifnethead ifnethead;
struct itimerval interval_it;
struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
int line;
int oldmask, first;
u_long interesting_off;
if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0)
return;
firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
printf("malloc failed\n");
exit(1);
}
memset(iftot, 0, sizeof(struct iftot));
interesting = NULL;
interesting_off = 0;
for (off = firstifnet, ip = iftot; off;) {
char name[IFNAMSIZ];
if (kread(off, (char *)&ifnet, sizeof ifnet) != 0)
break;
strlcpy(name, ifnet.if_xname, sizeof(name));
if (interface && strcmp(name, interface) == 0) {
interesting = ip;
interesting_off = off;
}
snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);;
if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
printf("malloc failed\n");
exit(1);
}
memset(ipn, 0, sizeof(struct iftot));
SLIST_NEXT(ip, chain) = ipn;
ip = ipn;
off = (u_long)TAILQ_NEXT(&ifnet, if_link);
}
if (interface && interesting == NULL)
errx(1, "%s: unknown interface", interface);
if ((total = malloc(sizeof(struct iftot))) == NULL) {
printf("malloc failed\n");
exit(1);
}
memset(total, 0, sizeof(struct iftot));
if ((sum = malloc(sizeof(struct iftot))) == NULL) {
printf("malloc failed\n");
exit(1);
}
memset(sum, 0, sizeof(struct iftot));
(void)signal(SIGALRM, catchalarm);
signalled = NO;
interval_it.it_interval.tv_sec = interval1;
interval_it.it_interval.tv_usec = 0;
interval_it.it_value = interval_it.it_interval;
setitimer(ITIMER_REAL, &interval_it, NULL);
first = 1;
banner:
printf("%17s %14s %16s", "input",
interesting ? interesting->ift_name : "(Total)", "output");
putchar('\n');
printf("%10s %5s %5s %10s %10s %5s %10s %5s",
"packets", "errs", "idrops", "bytes", "packets", "errs", "bytes",
"colls");
if (dflag)
printf(" %5.5s", "drops");
putchar('\n');
fflush(stdout);
line = 0;
loop:
if (interesting != NULL) {
ip = interesting;
if (kread(interesting_off, (char *)&ifnet, sizeof ifnet) != 0) {
printf("???\n");
exit(1);
};
if (!first) {
show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1);
show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1);
show_stat("lu", 5, ifnet.if_iqdrops - ip->ift_id, 1);
show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1);
show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1);
show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1);
show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1);
show_stat("NRSlu", 5,
ifnet.if_collisions - ip->ift_co, 1);
if (dflag)
show_stat("LSu", 5,
ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
}
ip->ift_ip = ifnet.if_ipackets;
ip->ift_ie = ifnet.if_ierrors;
ip->ift_id = ifnet.if_iqdrops;
ip->ift_ib = ifnet.if_ibytes;
ip->ift_op = ifnet.if_opackets;
ip->ift_oe = ifnet.if_oerrors;
ip->ift_ob = ifnet.if_obytes;
ip->ift_co = ifnet.if_collisions;
ip->ift_dr = ifnet.if_snd.ifq_drops;
} else {
sum->ift_ip = 0;
sum->ift_ie = 0;
sum->ift_id = 0;
sum->ift_ib = 0;
sum->ift_op = 0;
sum->ift_oe = 0;
sum->ift_ob = 0;
sum->ift_co = 0;
sum->ift_dr = 0;
for (off = firstifnet, ip = iftot;
off && SLIST_NEXT(ip, chain) != NULL;
ip = SLIST_NEXT(ip, chain)) {
if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) {
off = 0;
continue;
}
sum->ift_ip += ifnet.if_ipackets;
sum->ift_ie += ifnet.if_ierrors;
sum->ift_id += ifnet.if_iqdrops;
sum->ift_ib += ifnet.if_ibytes;
sum->ift_op += ifnet.if_opackets;
sum->ift_oe += ifnet.if_oerrors;
sum->ift_ob += ifnet.if_obytes;
sum->ift_co += ifnet.if_collisions;
sum->ift_dr += ifnet.if_snd.ifq_drops;
off = (u_long)TAILQ_NEXT(&ifnet, if_link);
}
if (!first) {
show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1);
show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1);
show_stat("lu", 5, sum->ift_id - total->ift_id, 1);
show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1);
show_stat("lu", 10, sum->ift_op - total->ift_op, 1);
show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1);
show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1);
show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
if (dflag)
show_stat("LSu", 5,
sum->ift_dr - total->ift_dr, 1);
}
*total = *sum;
}
if (!first)
putchar('\n');
fflush(stdout);
if ((noutputs != 0) && (--noutputs == 0))
exit(0);
oldmask = sigblock(sigmask(SIGALRM));
while (!signalled)
sigpause(0);
signalled = NO;
sigsetmask(oldmask);
line++;
first = 0;
if (line == 21)
goto banner;
else
goto loop;
/*NOTREACHED*/
}
/*
* Set a flag to indicate that a signal from the periodic itimer has been
* caught.
*/
static void
catchalarm(int signo __unused)
{
signalled = YES;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,481 @@
/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
/*-
* Copyright (c) 2005 NTT Multimedia Communications Laboratories, 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 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.
*/
/*-
* 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. 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.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
#ifdef IPSEC
#ifdef __rtems__
#include <freebsd/netipsec/ipsec.h>
#include <freebsd/netipsec/ah_var.h>
#include <freebsd/netipsec/esp_var.h>
#include <freebsd/netipsec/ipcomp_var.h>
#else
#include <netipsec/ipsec.h>
#include <netipsec/ah_var.h>
#include <netipsec/esp_var.h>
#include <netipsec/ipcomp_var.h>
#endif
#endif
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#ifdef IPSEC
struct val2str {
int val;
const char *str;
};
static struct val2str ipsec_ahnames[] = {
{ 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", },
#ifdef SADB_X_AALG_SHA2_256
{ SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
#endif
#ifdef SADB_X_AALG_SHA2_384
{ SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
#endif
#ifdef SADB_X_AALG_SHA2_512
{ SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
#endif
#ifdef SADB_X_AALG_RIPEMD160HMAC
{ SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
#endif
#ifdef SADB_X_AALG_AES_XCBC_MAC
{ SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
#endif
{ -1, NULL },
};
static struct val2str ipsec_espnames[] = {
{ 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", },
#ifdef SADB_X_EALG_RIJNDAELCBC
{ SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", },
#endif
#ifdef SADB_X_EALG_AESCTR
{ SADB_X_EALG_AESCTR, "aes-ctr", },
#endif
{ -1, NULL },
};
static struct val2str ipsec_compnames[] = {
{ SADB_X_CALG_NONE, "none", },
{ SADB_X_CALG_OUI, "oui", },
{ SADB_X_CALG_DEFLATE, "deflate", },
{ SADB_X_CALG_LZS, "lzs", },
{ -1, NULL },
};
static void ipsec_hist(const u_quad_t *hist, size_t histmax,
const struct val2str *name, const char *title);
static void print_ipsecstats(const struct ipsecstat *ipsecstat);
/*
* Dump IPSEC statistics structure.
*/
static void
ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name,
const char *title)
{
int first;
size_t proto;
const struct val2str *p;
first = 1;
for (proto = 0; proto < histmax; proto++) {
if (hist[proto] <= 0)
continue;
if (first) {
printf("\t%s histogram:\n", title);
first = 0;
}
for (p = name; p && p->str; p++) {
if (p->val == (int)proto)
break;
}
if (p && p->str) {
printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]);
} else {
printf("\t\t#%ld: %ju\n", (long)proto,
(uintmax_t)hist[proto]);
}
}
}
static void
print_ipsecstats(const struct ipsecstat *ipsecstat)
{
#define p(f, m) if (ipsecstat->f || sflag <= 1) \
printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f))
#define pes(f, m) if (ipsecstat->f || sflag <= 1) \
printf(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f))
#define hist(f, n, t) \
ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t));
p(in_success, "\t%ju inbound packet%s processed successfully\n");
p(in_polvio, "\t%ju inbound packet%s violated process security "
"policy\n");
p(in_nosa, "\t%ju inbound packet%s with no SA available\n");
p(in_inval, "\t%ju invalid inbound packet%s\n");
p(in_nomem, "\t%ju inbound packet%s failed due to insufficient memory\n");
p(in_badspi, "\t%ju inbound packet%s failed getting SPI\n");
p(in_ahreplay, "\t%ju inbound packet%s failed on AH replay check\n");
p(in_espreplay, "\t%ju inbound packet%s failed on ESP replay check\n");
p(in_ahauthsucc, "\t%ju inbound packet%s considered authentic\n");
p(in_ahauthfail, "\t%ju inbound packet%s failed on authentication\n");
hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input");
hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input");
hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input");
p(out_success, "\t%ju outbound packet%s processed successfully\n");
p(out_polvio, "\t%ju outbound packet%s violated process security "
"policy\n");
p(out_nosa, "\t%ju outbound packet%s with no SA available\n");
p(out_inval, "\t%ju invalid outbound packet%s\n");
p(out_nomem, "\t%ju outbound packet%s failed due to insufficient memory\n");
p(out_noroute, "\t%ju outbound packet%s with no route\n");
hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output");
hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output");
hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output");
p(spdcachelookup, "\t%ju SPD cache lookup%s\n");
pes(spdcachemiss, "\t%ju SPD cache miss%s\n");
#undef pes
#undef hist
p(ips_in_polvio, "\t%ju inbound packet%s violated process "
"security policy\n");
p(ips_out_polvio, "\t%ju outbound packet%s violated process "
"security policy\n");
p(ips_out_nosa, "\t%ju outbound packet%s with no SA available\n");
p(ips_out_nomem, "\t%ju outbound packet%s failed due to "
"insufficient memory\n");
p(ips_out_noroute, "\t%ju outbound packet%s with no route "
"available\n");
p(ips_out_inval, "\t%ju invalid outbound packet%s\n");
p(ips_out_bundlesa, "\t%ju outbound packet%s with bundled SAs\n");
p(ips_mbcoalesced, "\t%ju mbuf%s coalesced during clone\n");
p(ips_clcoalesced, "\t%ju cluster%s coalesced during clone\n");
p(ips_clcopied, "\t%ju cluster%s copied during clone\n");
p(ips_mbinserted, "\t%ju mbuf%s inserted during makespace\n");
#undef p
}
void
ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipsecstat ipsecstat;
if (off == 0)
return;
printf ("%s:\n", name);
kread(off, (char *)&ipsecstat, sizeof(ipsecstat));
print_ipsecstats(&ipsecstat);
}
static void ipsec_hist_new(const u_int32_t *hist, size_t histmax,
const struct val2str *name, const char *title);
static void print_ahstats(const struct ahstat *ahstat);
static void print_espstats(const struct espstat *espstat);
static void print_ipcompstats(const struct ipcompstat *ipcompstat);
/*
* Dump IPSEC statistics structure.
*/
static void
ipsec_hist_new(const u_int32_t *hist, size_t histmax,
const struct val2str *name, const char *title)
{
int first;
size_t proto;
const struct val2str *p;
first = 1;
for (proto = 0; proto < histmax; proto++) {
if (hist[proto] <= 0)
continue;
if (first) {
printf("\t%s histogram:\n", title);
first = 0;
}
for (p = name; p && p->str; p++) {
if (p->val == (int)proto)
break;
}
if (p && p->str) {
printf("\t\t%s: %u\n", p->str, hist[proto]);
} else {
printf("\t\t#%lu: %u\n", (unsigned long)proto,
hist[proto]);
}
}
}
static void
print_ahstats(const struct ahstat *ahstat)
{
#define p32(f, m) if (ahstat->f || sflag <= 1) \
printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f))
#define p64(f, m) if (ahstat->f || sflag <= 1) \
printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f))
#define hist(f, n, t) \
ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
p32(ahs_hdrops, " packet%s shorter than header shows\n");
p32(ahs_nopf, " packet%s dropped; protocol family not supported\n");
p32(ahs_notdb, " packet%s dropped; no TDB\n");
p32(ahs_badkcr, " packet%s dropped; bad KCR\n");
p32(ahs_qfull, " packet%s dropped; queue full\n");
p32(ahs_noxform, " packet%s dropped; no transform\n");
p32(ahs_wrap, " replay counter wrap%s\n");
p32(ahs_badauth, " packet%s dropped; bad authentication detected\n");
p32(ahs_badauthl, " packet%s dropped; bad authentication length\n");
p32(ahs_replay, " possible replay packet%s detected\n");
p32(ahs_input, " packet%s in\n");
p32(ahs_output, " packet%s out\n");
p32(ahs_invalid, " packet%s dropped; invalid TDB\n");
p64(ahs_ibytes, " byte%s in\n");
p64(ahs_obytes, " byte%s out\n");
p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
p32(ahs_pdrops, " packet%s blocked due to policy\n");
p32(ahs_crypto, " crypto processing failure%s\n");
p32(ahs_tunnel, " tunnel sanity check failure%s\n");
hist(ahstat->ahs_hist, ipsec_ahnames, "AH output");
#undef p32
#undef p64
#undef hist
}
void
ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct ahstat ahstat;
if (off == 0)
return;
printf ("%s:\n", name);
kread(off, (char *)&ahstat, sizeof(ahstat));
print_ahstats(&ahstat);
}
static void
print_espstats(const struct espstat *espstat)
{
#define p32(f, m) if (espstat->f || sflag <= 1) \
printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f))
#define p64(f, m) if (espstat->f || sflag <= 1) \
printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f))
#define hist(f, n, t) \
ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
p32(esps_hdrops, " packet%s shorter than header shows\n");
p32(esps_nopf, " packet%s dropped; protocol family not supported\n");
p32(esps_notdb, " packet%s dropped; no TDB\n");
p32(esps_badkcr, " packet%s dropped; bad KCR\n");
p32(esps_qfull, " packet%s dropped; queue full\n");
p32(esps_noxform, " packet%s dropped; no transform\n");
p32(esps_badilen, " packet%s dropped; bad ilen\n");
p32(esps_wrap, " replay counter wrap%s\n");
p32(esps_badenc, " packet%s dropped; bad encryption detected\n");
p32(esps_badauth, " packet%s dropped; bad authentication detected\n");
p32(esps_replay, " possible replay packet%s detected\n");
p32(esps_input, " packet%s in\n");
p32(esps_output, " packet%s out\n");
p32(esps_invalid, " packet%s dropped; invalid TDB\n");
p64(esps_ibytes, " byte%s in\n");
p64(esps_obytes, " byte%s out\n");
p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
p32(esps_pdrops, " packet%s blocked due to policy\n");
p32(esps_crypto, " crypto processing failure%s\n");
p32(esps_tunnel, " tunnel sanity check failure%s\n");
hist(espstat->esps_hist, ipsec_espnames, "ESP output");
#undef p32
#undef p64
#undef hist
}
void
esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
{
struct espstat espstat;
if (off == 0)
return;
printf ("%s:\n", name);
kread(off, (char *)&espstat, sizeof(espstat));
print_espstats(&espstat);
}
static void
print_ipcompstats(const struct ipcompstat *ipcompstat)
{
uint32_t version;
#define p32(f, m) if (ipcompstat->f || sflag <= 1) \
printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f))
#define p64(f, m) if (ipcompstat->f || sflag <= 1) \
printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f))
#define hist(f, n, t) \
ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
#ifndef IPCOMPSTAT_VERSION
version = 0;
#else
version = ipcompstat->version;
#endif
p32(ipcomps_hdrops, " packet%s shorter than header shows\n");
p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n");
p32(ipcomps_notdb, " packet%s dropped; no TDB\n");
p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n");
p32(ipcomps_qfull, " packet%s dropped; queue full\n");
p32(ipcomps_noxform, " packet%s dropped; no transform\n");
p32(ipcomps_wrap, " replay counter wrap%s\n");
p32(ipcomps_input, " packet%s in\n");
p32(ipcomps_output, " packet%s out\n");
p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n");
p64(ipcomps_ibytes, " byte%s in\n");
p64(ipcomps_obytes, " byte%s out\n");
p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
p32(ipcomps_pdrops, " packet%s blocked due to policy\n");
p32(ipcomps_crypto, " crypto processing failure%s\n");
hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output");
if (version >= 1) {
p32(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n");
p32(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n");
}
#undef p32
#undef p64
#undef hist
}
void
ipcomp_stats(u_long off, const char *name, int family __unused,
int proto __unused)
{
struct ipcompstat ipcompstat;
if (off == 0)
return;
printf ("%s:\n", name);
kread(off, (char *)&ipcompstat, sizeof(ipcompstat));
print_ipcompstats(&ipcompstat);
}
#endif /*IPSEC*/

View File

@ -0,0 +1,354 @@
/*-
* Copyright (c) 2004, Robert N. M. Watson
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)ns.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <net/route.h>
#define TCPSTATES
#include <netinet/tcp_fsm.h>
#include <netipx/ipx.h>
#include <netipx/ipx_pcb.h>
#include <netipx/ipx_var.h>
#ifdef IPXERRORMSGS
#include <netipx/ipx_error.h>
#endif
#include <netipx/spx.h>
#include <netipx/spx_timer.h>
#include <netipx/spx_var.h>
#define SANAMES
#include <netipx/spx_debug.h>
#include <nlist.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "netstat.h"
static char *ipx_prpr(struct ipx_addr *);
/*
* Print a summary of connections related to a Network Systems
* protocol. For SPX, also give state of connection.
* Listening processes (aflag) are suppressed unless the
* -a (all) flag is specified.
*/
void
ipxprotopr(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipxpcbhead cb;
struct ipxpcb *ipxp;
struct ipxpcb ipxpcb;
struct spxpcb spxpcb;
struct socket sockb;
static int first = 1;
int isspx;
if (off == 0)
return;
isspx = strcmp(name, "spx") == 0;
kread(off, (char *)&cb, sizeof (struct ipxpcbhead));
ipxp = LIST_FIRST(&cb);
while (ipxp != NULL) {
u_long ppcb;
kread((u_long)ipxp, (char *)&ipxpcb, sizeof (ipxpcb));
ipxp = LIST_NEXT(&ipxpcb, ipxp_list);
if (!aflag && ipx_nullhost(ipxpcb.ipxp_faddr) ) {
continue;
}
kread((u_long)ipxpcb.ipxp_socket,
(char *)&sockb, sizeof (sockb));
ppcb = (u_long) ipxpcb.ipxp_pcb;
if (ppcb) {
if (isspx) {
kread(ppcb, (char *)&spxpcb, sizeof (spxpcb));
} else continue;
} else
if (isspx) continue;
if (first) {
printf("Active IPX connections");
if (aflag)
printf(" (including servers)");
putchar('\n');
if (Aflag)
printf("%-8.8s ", "PCB");
printf(Aflag ?
"%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
"%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
"Proto", "Recv-Q", "Send-Q",
"Local Address", "Foreign Address", "(state)");
first = 0;
}
if (Aflag)
printf("%8lx ", ppcb);
printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
sockb.so_snd.sb_cc);
printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_laddr));
printf(Aflag?" %-18.18s":" %-22.22s", ipx_prpr(&ipxpcb.ipxp_faddr));
if (isspx) {
if (spxpcb.s_state >= TCP_NSTATES)
printf(" %d", spxpcb.s_state);
else
printf(" %s", tcpstates[spxpcb.s_state]);
}
putchar('\n');
}
}
#define ANY(x,y,z) \
if (x || sflag <= 1) printf("\t%u %s%s%s\n", x, y, plural(x), z)
#define ANYl(x,y,z) \
if (x || sflag <= 1) printf("\t%lu %s%s%s\n", x, y, plural(x), z)
/*
* Dump SPX statistics structure.
*/
void
spx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct spx_istat spx_istat;
#define spxstat spx_istat.newstats
if (off == 0)
return;
kread(off, (char *)&spx_istat, sizeof (spx_istat));
printf("%s:\n", name);
ANY(spx_istat.nonucn, "connection", " dropped due to no new sockets ");
ANY(spx_istat.gonawy, "connection", " terminated due to our end dying");
ANY(spx_istat.nonucn, "connection",
" dropped due to inability to connect");
ANY(spx_istat.noconn, "connection",
" dropped due to inability to connect");
ANY(spx_istat.notme, "connection",
" incompleted due to mismatched id's");
ANY(spx_istat.wrncon, "connection", " dropped due to mismatched id's");
ANY(spx_istat.bdreas, "packet", " dropped out of sequence");
ANY(spx_istat.lstdup, "packet", " duplicating the highest packet");
ANY(spx_istat.notyet, "packet", " refused as exceeding allocation");
ANYl(spxstat.spxs_connattempt, "connection", " initiated");
ANYl(spxstat.spxs_accepts, "connection", " accepted");
ANYl(spxstat.spxs_connects, "connection", " established");
ANYl(spxstat.spxs_drops, "connection", " dropped");
ANYl(spxstat.spxs_conndrops, "embryonic connection", " dropped");
ANYl(spxstat.spxs_closed, "connection", " closed (includes drops)");
ANYl(spxstat.spxs_segstimed, "packet", " where we tried to get rtt");
ANYl(spxstat.spxs_rttupdated, "time", " we got rtt");
ANYl(spxstat.spxs_delack, "delayed ack", " sent");
ANYl(spxstat.spxs_timeoutdrop, "connection",
" dropped in rxmt timeout");
ANYl(spxstat.spxs_rexmttimeo, "retransmit timeout", "");
ANYl(spxstat.spxs_persisttimeo, "persist timeout", "");
ANYl(spxstat.spxs_keeptimeo, "keepalive timeout", "");
ANYl(spxstat.spxs_keepprobe, "keepalive probe", " sent");
ANYl(spxstat.spxs_keepdrops, "connection", " dropped in keepalive");
ANYl(spxstat.spxs_sndtotal, "total packet", " sent");
ANYl(spxstat.spxs_sndpack, "data packet", " sent");
ANYl(spxstat.spxs_sndbyte, "data byte", " sent");
ANYl(spxstat.spxs_sndrexmitpack, "data packet", " retransmitted");
ANYl(spxstat.spxs_sndrexmitbyte, "data byte", " retransmitted");
ANYl(spxstat.spxs_sndacks, "ack-only packet", " sent");
ANYl(spxstat.spxs_sndprobe, "window probe", " sent");
ANYl(spxstat.spxs_sndurg, "packet", " sent with URG only");
ANYl(spxstat.spxs_sndwinup, "window update-only packet", " sent");
ANYl(spxstat.spxs_sndctrl, "control (SYN|FIN|RST) packet", " sent");
ANYl(spxstat.spxs_sndvoid, "request", " to send a non-existant packet");
ANYl(spxstat.spxs_rcvtotal, "total packet", " received");
ANYl(spxstat.spxs_rcvpack, "packet", " received in sequence");
ANYl(spxstat.spxs_rcvbyte, "byte", " received in sequence");
ANYl(spxstat.spxs_rcvbadsum, "packet", " received with ccksum errs");
ANYl(spxstat.spxs_rcvbadoff, "packet", " received with bad offset");
ANYl(spxstat.spxs_rcvshort, "packet", " received too short");
ANYl(spxstat.spxs_rcvduppack, "duplicate-only packet", " received");
ANYl(spxstat.spxs_rcvdupbyte, "duplicate-only byte", " received");
ANYl(spxstat.spxs_rcvpartduppack, "packet",
" with some duplicate data");
ANYl(spxstat.spxs_rcvpartdupbyte, "dup. byte", " in part-dup. packet");
ANYl(spxstat.spxs_rcvoopack, "out-of-order packet", " received");
ANYl(spxstat.spxs_rcvoobyte, "out-of-order byte", " received");
ANYl(spxstat.spxs_rcvpackafterwin, "packet", " with data after window");
ANYl(spxstat.spxs_rcvbyteafterwin, "byte", " rcvd after window");
ANYl(spxstat.spxs_rcvafterclose, "packet", " rcvd after 'close'");
ANYl(spxstat.spxs_rcvwinprobe, "rcvd window probe packet", "");
ANYl(spxstat.spxs_rcvdupack, "rcvd duplicate ack", "");
ANYl(spxstat.spxs_rcvacktoomuch, "rcvd ack", " for unsent data");
ANYl(spxstat.spxs_rcvackpack, "rcvd ack packet", "");
ANYl(spxstat.spxs_rcvackbyte, "byte", " acked by rcvd acks");
ANYl(spxstat.spxs_rcvwinupd, "rcvd window update packet", "");
}
/*
* Dump IPX statistics structure.
*/
void
ipx_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct ipxstat ipxstat;
if (off == 0)
return;
kread(off, (char *)&ipxstat, sizeof (ipxstat));
printf("%s:\n", name);
ANYl(ipxstat.ipxs_total, "total packet", " received");
ANYl(ipxstat.ipxs_badsum, "packet", " with bad checksums");
ANYl(ipxstat.ipxs_tooshort, "packet", " smaller than advertised");
ANYl(ipxstat.ipxs_toosmall, "packet", " smaller than a header");
ANYl(ipxstat.ipxs_forward, "packet", " forwarded");
ANYl(ipxstat.ipxs_cantforward, "packet", " not forwardable");
ANYl(ipxstat.ipxs_delivered, "packet", " for this host");
ANYl(ipxstat.ipxs_localout, "packet", " sent from this host");
ANYl(ipxstat.ipxs_odropped, "packet", " dropped due to no bufs, etc.");
ANYl(ipxstat.ipxs_noroute, "packet", " discarded due to no route");
ANYl(ipxstat.ipxs_mtutoosmall, "packet", " too big");
}
#ifdef IPXERRORMSGS
static struct {
u_short code;
char *name;
char *where;
} ipx_errnames[] = {
{0, "Unspecified Error", " at Destination"},
{1, "Bad Checksum", " at Destination"},
{2, "No Listener", " at Socket"},
{3, "Packet", " Refused due to lack of space at Destination"},
{01000, "Unspecified Error", " while gatewayed"},
{01001, "Bad Checksum", " while gatewayed"},
{01002, "Packet", " forwarded too many times"},
{01003, "Packet", " too large to be forwarded"},
{-1, 0, 0},
};
/*
* Dump IPX Error statistics structure.
*/
/*ARGSUSED*/
void
ipxerr_stats(u_long off, const char *name, int af __unused, int proto __unused)
{
struct ipx_errstat ipx_errstat;
int j;
int histoprint = 1;
int z;
if (off == 0)
return;
kread(off, (char *)&ipx_errstat, sizeof (ipx_errstat));
printf("IPX error statistics:\n");
ANY(ipx_errstat.ipx_es_error, "call", " to ipx_error");
ANY(ipx_errstat.ipx_es_oldshort, "error",
" ignored due to insufficient addressing");
ANY(ipx_errstat.ipx_es_oldipx_err, "error request",
" in response to error packets");
ANY(ipx_errstat.ipx_es_tooshort, "error packet",
" received incomplete");
ANY(ipx_errstat.ipx_es_badcode, "error packet",
" received of unknown type");
for(j = 0; j < IPX_ERR_MAX; j ++) {
z = ipx_errstat.ipx_es_outhist[j];
if (z && histoprint) {
printf("Output Error Histogram:\n");
histoprint = 0;
}
ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
}
histoprint = 1;
for(j = 0; j < IPX_ERR_MAX; j ++) {
z = ipx_errstat.ipx_es_inhist[j];
if (z && histoprint) {
printf("Input Error Histogram:\n");
histoprint = 0;
}
ipx_erputil(z, ipx_errstat.ipx_es_codes[j]);
}
}
static void
ipx_erputil(int z, int c)
{
int j;
char codebuf[30];
char *name, *where;
for(j = 0;; j ++) {
if ((name = ipx_errnames[j].name) == 0)
break;
if (ipx_errnames[j].code == c)
break;
}
if (name == 0) {
if (c > 01000)
where = "in transit";
else
where = "at destination";
sprintf(codebuf, "Unknown IPX error code 0%o", c);
name = codebuf;
} else
where = ipx_errnames[j].where;
ANY(z, name, where);
}
#endif /* IPXERRORMSGS */
static struct sockaddr_ipx ssipx = { .sipx_family = AF_IPX };
static
char *ipx_prpr(struct ipx_addr *x)
{
struct sockaddr_ipx *sipx = &ssipx;
sipx->sipx_addr = *x;
return(ipx_print((struct sockaddr *)sipx));
}

View File

@ -0,0 +1,805 @@
/*-
* 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. 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.
*/
#ifndef lint
char const copyright[] =
"@(#) Copyright (c) 1983, 1988, 1993\n\
Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#if 0
#ifndef lint
static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/file.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
#ifdef NETGRAPH
#include <netgraph/ng_socket.h>
#endif
#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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
static struct nlist nl[] = {
#define N_IFNET 0
{ .n_name = "_ifnet" },
#define N_RTSTAT 1
{ .n_name = "_rtstat" },
#define N_RTREE 2
{ .n_name = "_rt_tables"},
#define N_MRTSTAT 3
{ .n_name = "_mrtstat" },
#define N_MFCHASHTBL 4
{ .n_name = "_mfchashtbl" },
#define N_VIFTABLE 5
{ .n_name = "_viftable" },
#define N_IPX 6
{ .n_name = "_ipxpcb_list"},
#define N_IPXSTAT 7
{ .n_name = "_ipxstat"},
#define N_SPXSTAT 8
{ .n_name = "_spx_istat"},
#define N_DDPSTAT 9
{ .n_name = "_ddpstat"},
#define N_DDPCB 10
{ .n_name = "_ddpcb"},
#define N_NGSOCKS 11
{ .n_name = "_ngsocklist"},
#define N_IP6STAT 12
{ .n_name = "_ip6stat" },
#define N_ICMP6STAT 13
{ .n_name = "_icmp6stat" },
#define N_IPSECSTAT 14
{ .n_name = "_ipsec4stat" },
#define N_IPSEC6STAT 15
{ .n_name = "_ipsec6stat" },
#define N_PIM6STAT 16
{ .n_name = "_pim6stat" },
#define N_MRT6STAT 17
{ .n_name = "_mrt6stat" },
#define N_MF6CTABLE 18
{ .n_name = "_mf6ctable" },
#define N_MIF6TABLE 19
{ .n_name = "_mif6table" },
#define N_PFKEYSTAT 20
{ .n_name = "_pfkeystat" },
#define N_MBSTAT 21
{ .n_name = "_mbstat" },
#define N_MBTYPES 22
{ .n_name = "_mbtypes" },
#define N_NMBCLUSTERS 23
{ .n_name = "_nmbclusters" },
#define N_NMBUFS 24
{ .n_name = "_nmbufs" },
#define N_MBHI 25
{ .n_name = "_mbuf_hiwm" },
#define N_CLHI 26
{ .n_name = "_clust_hiwm" },
#define N_NCPUS 27
{ .n_name = "_smp_cpus" },
#define N_PAGESZ 28
{ .n_name = "_pagesize" },
#define N_MBPSTAT 29
{ .n_name = "_mb_statpcpu" },
#define N_RTTRASH 30
{ .n_name = "_rttrash" },
#define N_MBLO 31
{ .n_name = "_mbuf_lowm" },
#define N_CLLO 32
{ .n_name = "_clust_lowm" },
#define N_CARPSTAT 33
{ .n_name = "_carpstats" },
#define N_PFSYNCSTAT 34
{ .n_name = "_pfsyncstats" },
#define N_AHSTAT 35
{ .n_name = "_ahstat" },
#define N_ESPSTAT 36
{ .n_name = "_espstat" },
#define N_IPCOMPSTAT 37
{ .n_name = "_ipcompstat" },
#define N_TCPSTAT 38
{ .n_name = "_tcpstat" },
#define N_UDPSTAT 39
{ .n_name = "_udpstat" },
#define N_IPSTAT 40
{ .n_name = "_ipstat" },
#define N_ICMPSTAT 41
{ .n_name = "_icmpstat" },
#define N_IGMPSTAT 42
{ .n_name = "_igmpstat" },
#define N_PIMSTAT 43
{ .n_name = "_pimstat" },
#define N_TCBINFO 44
{ .n_name = "_tcbinfo" },
#define N_UDBINFO 45
{ .n_name = "_udbinfo" },
#define N_DIVCBINFO 46
{ .n_name = "_divcbinfo" },
#define N_RIPCBINFO 47
{ .n_name = "_ripcbinfo" },
#define N_UNP_COUNT 48
{ .n_name = "_unp_count" },
#define N_UNP_GENCNT 49
{ .n_name = "_unp_gencnt" },
#define N_UNP_DHEAD 50
{ .n_name = "_unp_dhead" },
#define N_UNP_SHEAD 51
{ .n_name = "_unp_shead" },
#define N_RIP6STAT 52
{ .n_name = "_rip6stat" },
#define N_SCTPSTAT 53
{ .n_name = "_sctpstat" },
#define N_MFCTABLESIZE 54
{ .n_name = "_mfctablesize" },
#define N_ARPSTAT 55
{ .n_name = "_arpstat" },
{ .n_name = NULL },
};
struct protox {
int pr_index; /* index into nlist of cb head */
int pr_sindex; /* index into nlist of stat block */
u_char pr_wanted; /* 1 if wanted, 0 otherwise */
void (*pr_cblocks)(u_long, const char *, int, int);
/* control blocks printing routine */
void (*pr_stats)(u_long, const char *, int, int);
/* statistics printing routine */
void (*pr_istats)(char *); /* per/if statistics printing routine */
const char *pr_name; /* well-known name */
int pr_usesysctl; /* non-zero if we use sysctl, not kvm */
int pr_protocol;
} protox[] = {
{ N_TCBINFO, N_TCPSTAT, 1, protopr,
tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
{ N_UDBINFO, N_UDPSTAT, 1, protopr,
udp_stats, NULL, "udp", 1, IPPROTO_UDP },
#ifdef SCTP
{ -1, N_SCTPSTAT, 1, sctp_protopr,
sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
#endif
{ N_DIVCBINFO, -1, 1, protopr,
NULL, NULL, "divert", 1, IPPROTO_DIVERT },
{ N_RIPCBINFO, N_IPSTAT, 1, protopr,
ip_stats, NULL, "ip", 1, IPPROTO_RAW },
{ N_RIPCBINFO, N_ICMPSTAT, 1, protopr,
icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
{ N_RIPCBINFO, N_IGMPSTAT, 1, protopr,
igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
#ifdef IPSEC
{ -1, N_IPSECSTAT, 1, NULL, /* keep as compat */
ipsec_stats, NULL, "ipsec", 0, 0},
{ -1, N_AHSTAT, 1, NULL,
ah_stats, NULL, "ah", 0, 0},
{ -1, N_ESPSTAT, 1, NULL,
esp_stats, NULL, "esp", 0, 0},
{ -1, N_IPCOMPSTAT, 1, NULL,
ipcomp_stats, NULL, "ipcomp", 0, 0},
#endif
{ N_RIPCBINFO, N_PIMSTAT, 1, protopr,
pim_stats, NULL, "pim", 1, IPPROTO_PIM },
{ -1, N_CARPSTAT, 1, NULL,
carp_stats, NULL, "carp", 1, 0 },
{ -1, N_PFSYNCSTAT, 1, NULL,
pfsync_stats, NULL, "pfsync", 1, 0 },
{ -1, N_ARPSTAT, 1, NULL,
arp_stats, NULL, "arp", 1, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, NULL, 0, 0 }
};
#ifdef INET6
struct protox ip6protox[] = {
{ N_TCBINFO, N_TCPSTAT, 1, protopr,
tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
{ N_UDBINFO, N_UDPSTAT, 1, protopr,
udp_stats, NULL, "udp", 1, IPPROTO_UDP },
{ N_RIPCBINFO, N_IP6STAT, 1, protopr,
ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
{ N_RIPCBINFO, N_ICMP6STAT, 1, protopr,
icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
#ifdef IPSEC
{ -1, N_IPSEC6STAT, 1, NULL,
ipsec_stats, NULL, "ipsec6", 0, 0 },
#endif
#ifdef notyet
{ -1, N_PIM6STAT, 1, NULL,
pim6_stats, NULL, "pim6", 1, 0 },
#endif
{ -1, N_RIP6STAT, 1, NULL,
rip6_stats, NULL, "rip6", 1, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, NULL, 0, 0 }
};
#endif /*INET6*/
#ifdef IPSEC
struct protox pfkeyprotox[] = {
{ -1, N_PFKEYSTAT, 1, NULL,
pfkey_stats, NULL, "pfkey", 0, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, NULL, 0, 0 }
};
#endif
struct protox atalkprotox[] = {
{ N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
ddp_stats, NULL, "ddp", 0, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, NULL, 0, 0 }
};
#ifdef NETGRAPH
struct protox netgraphprotox[] = {
{ N_NGSOCKS, -1, 1, netgraphprotopr,
NULL, NULL, "ctrl", 0, 0 },
{ N_NGSOCKS, -1, 1, netgraphprotopr,
NULL, NULL, "data", 0, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, NULL, 0, 0 }
};
#endif
#ifdef IPX
struct protox ipxprotox[] = {
{ N_IPX, N_IPXSTAT, 1, ipxprotopr,
ipx_stats, NULL, "ipx", 0, 0 },
{ N_IPX, N_SPXSTAT, 1, ipxprotopr,
spx_stats, NULL, "spx", 0, 0 },
{ -1, -1, 0, NULL,
NULL, NULL, 0, 0, 0 }
};
#endif
struct protox *protoprotox[] = {
protox,
#ifdef INET6
ip6protox,
#endif
#ifdef IPSEC
pfkeyprotox,
#endif
#ifdef IPX
ipxprotox,
#endif
atalkprotox, NULL };
static void printproto(struct protox *, const char *);
static void usage(void);
static struct protox *name2protox(const char *);
static struct protox *knownname(const char *);
static kvm_t *kvmd;
static char *nlistf = NULL, *memf = NULL;
int Aflag; /* show addresses of protocol control block */
int aflag; /* show all sockets (including servers) */
int Bflag; /* show information about bpf consumers */
int bflag; /* show i/f total bytes in/out */
int dflag; /* show i/f dropped packets */
int gflag; /* show group (multicast) routing or stats */
int hflag; /* show counters in human readable format */
int iflag; /* show interfaces */
int Lflag; /* show size of listen queues */
int mflag; /* show memory stats */
int noutputs = 0; /* how much outputs before we exit */
int numeric_addr; /* show addresses numerically */
int numeric_port; /* show ports numerically */
static int pflag; /* show given protocol */
int rflag; /* show routing tables (or routing stats) */
int sflag; /* show protocol statistics */
int tflag; /* show i/f watchdog timers */
int Wflag; /* wide display */
int xflag; /* extra information, includes all socket buffer info */
int zflag; /* zero stats */
int interval; /* repeat interval for i/f stats */
char *interface; /* desired i/f for stats, or NULL for all i/fs */
int unit; /* unit number for above */
int af; /* address family */
int live; /* true if we are examining a live system */
int
main(int argc, char *argv[])
{
struct protox *tp = NULL; /* for printing cblocks & stats */
int ch;
af = AF_UNSPEC;
while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
switch(ch) {
case 'A':
Aflag = 1;
break;
case 'a':
aflag = 1;
break;
case 'B':
Bflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'd':
dflag = 1;
break;
case 'f':
if (strcmp(optarg, "ipx") == 0)
af = AF_IPX;
else if (strcmp(optarg, "inet") == 0)
af = AF_INET;
#ifdef INET6
else if (strcmp(optarg, "inet6") == 0)
af = AF_INET6;
#endif
#ifdef IPSEC
else if (strcmp(optarg, "pfkey") == 0)
af = PF_KEY;
#endif
else if (strcmp(optarg, "unix") == 0)
af = AF_UNIX;
else if (strcmp(optarg, "atalk") == 0)
af = AF_APPLETALK;
#ifdef NETGRAPH
else if (strcmp(optarg, "ng") == 0
|| strcmp(optarg, "netgraph") == 0)
af = AF_NETGRAPH;
#endif
else if (strcmp(optarg, "link") == 0)
af = AF_LINK;
else {
errx(1, "%s: unknown address family", optarg);
}
break;
case 'g':
gflag = 1;
break;
case 'h':
hflag = 1;
break;
case 'I': {
char *cp;
iflag = 1;
for (cp = interface = optarg; isalpha(*cp); cp++)
continue;
unit = atoi(cp);
break;
}
case 'i':
iflag = 1;
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 = 1;
break;
case 'p':
if ((tp = name2protox(optarg)) == NULL) {
errx(1,
"%s: unknown or uninstrumented protocol",
optarg);
}
pflag = 1;
break;
case 'q':
noutputs = atoi(optarg);
if (noutputs != 0)
noutputs++;
break;
case 'r':
rflag = 1;
break;
case 's':
++sflag;
break;
case 'S':
numeric_addr = 1;
break;
case 't':
tflag = 1;
break;
case 'u':
af = AF_UNIX;
break;
case 'W':
case 'l':
Wflag = 1;
break;
case 'w':
interval = atoi(optarg);
iflag = 1;
break;
case 'x':
xflag = 1;
break;
case 'z':
zflag = 1;
break;
case '?':
default:
usage();
}
argv += optind;
argc -= optind;
#define BACKWARD_COMPATIBILITY
#ifdef BACKWARD_COMPATIBILITY
if (*argv) {
if (isdigit(**argv)) {
interval = atoi(*argv);
if (interval <= 0)
usage();
++argv;
iflag = 1;
}
if (*argv) {
nlistf = *argv;
if (*++argv)
memf = *argv;
}
}
#endif
/*
* Discard setgid privileges if not the running kernel so that bad
* guys can't print interesting stuff from kernel memory.
*/
live = (nlistf == NULL && memf == NULL);
if (!live)
setgid(getgid());
if (Bflag) {
if (!live)
usage();
bpf_stats(interface);
exit(0);
}
if (mflag) {
if (!live) {
if (kread(0, NULL, 0) == 0)
mbpr(kvmd, nl[N_MBSTAT].n_value);
} else
mbpr(NULL, 0);
exit(0);
}
#if 0
/*
* Keep file descriptors open to avoid overhead
* of open/close on each call to get* routines.
*/
sethostent(1);
setnetent(1);
#else
/*
* This does not make sense any more with DNS being default over
* the files. Doing a setXXXXent(1) causes a tcp connection to be
* used for the queries, which is slower.
*/
#endif
kread(0, NULL, 0);
if (iflag && !sflag) {
intpr(interval, nl[N_IFNET].n_value, NULL);
exit(0);
}
if (rflag) {
if (sflag)
rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
else
routepr(nl[N_RTREE].n_value);
exit(0);
}
if (gflag) {
if (sflag) {
if (af == AF_INET || af == AF_UNSPEC)
mrt_stats(nl[N_MRTSTAT].n_value);
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
mrt6_stats(nl[N_MRT6STAT].n_value);
#endif
} else {
if (af == AF_INET || af == AF_UNSPEC)
mroutepr(nl[N_MFCHASHTBL].n_value,
nl[N_MFCTABLESIZE].n_value,
nl[N_VIFTABLE].n_value);
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
mroute6pr(nl[N_MF6CTABLE].n_value,
nl[N_MIF6TABLE].n_value);
#endif
}
exit(0);
}
if (tp) {
printproto(tp, tp->pr_name);
exit(0);
}
if (af == AF_INET || af == AF_UNSPEC)
for (tp = protox; tp->pr_name; tp++)
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 /*INET6*/
#ifdef IPSEC
if (af == PF_KEY || af == AF_UNSPEC)
for (tp = pfkeyprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif /*IPSEC*/
#ifdef IPX
if (af == AF_IPX || af == AF_UNSPEC) {
for (tp = ipxprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
}
#endif /* IPX */
if (af == AF_APPLETALK || af == AF_UNSPEC)
for (tp = atalkprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#ifdef NETGRAPH
if (af == AF_NETGRAPH || af == AF_UNSPEC)
for (tp = netgraphprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif /* NETGRAPH */
if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
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(tp, name)
struct protox *tp;
const char *name;
{
void (*pr)(u_long, const char *, int, int);
u_long off;
if (sflag) {
if (iflag) {
if (tp->pr_istats)
intpr(interval, nl[N_IFNET].n_value,
tp->pr_istats);
else if (pflag)
printf("%s: no per-interface stats routine\n",
tp->pr_name);
return;
} else {
pr = tp->pr_stats;
if (!pr) {
if (pflag)
printf("%s: no stats routine\n",
tp->pr_name);
return;
}
if (tp->pr_usesysctl && live)
off = 0;
else if (tp->pr_sindex < 0) {
if (pflag)
printf(
"%s: stats routine doesn't work on cores\n",
tp->pr_name);
return;
} else
off = nl[tp->pr_sindex].n_value;
}
} else {
pr = tp->pr_cblocks;
if (!pr) {
if (pflag)
printf("%s: no PCB routine\n", tp->pr_name);
return;
}
if (tp->pr_usesysctl && live)
off = 0;
else if (tp->pr_index < 0) {
if (pflag)
printf(
"%s: PCB routine doesn't work on cores\n",
tp->pr_name);
return;
} else
off = nl[tp->pr_index].n_value;
}
if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
af != AF_UNSPEC))
(*pr)(off, name, af, tp->pr_protocol);
}
/*
* Read kernel memory, return 0 on success.
*/
int
kread(u_long addr, void *buf, size_t size)
{
char errbuf[_POSIX2_LINE_MAX];
if (kvmd == NULL) {
kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
setgid(getgid());
if (kvmd != NULL) {
if (kvm_nlist(kvmd, nl) < 0) {
if (nlistf)
errx(1, "%s: kvm_nlist: %s", nlistf,
kvm_geterr(kvmd));
else
errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
}
if (nl[0].n_type == 0) {
if (nlistf)
errx(1, "%s: no namelist", nlistf);
else
errx(1, "no namelist");
}
} else {
warnx("kvm not available: %s", errbuf);
return(-1);
}
}
if (!buf)
return (0);
if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
warnx("%s", kvm_geterr(kvmd));
return (-1);
}
return (0);
}
const char *
plural(uintmax_t n)
{
return (n != 1 ? "s" : "");
}
const char *
plurales(uintmax_t n)
{
return (n != 1 ? "es" : "");
}
const char *
pluralies(uintmax_t n)
{
return (n != 1 ? "ies" : "y");
}
/*
* 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)
{
(void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
" [-M core] [-N system]",
" netstat -i | -I interface [-abdhntW] [-f address_family]\n"
" [-M core] [-N system]",
" netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
" netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
" [-M core] [-N system]",
" netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
" [-M core] [-N system]",
" netstat -m [-M core] [-N system]",
" netstat -B [-I interface]",
" netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
" netstat -rs [-s] [-M core] [-N system]",
" netstat -g [-W] [-f address_family] [-M core] [-N system]",
" netstat -gs [-s] [-f address_family] [-M core] [-N system]");
exit(1);
}

View File

@ -0,0 +1,323 @@
/*-
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California.
* Copyright (c) 2005 Robert N. M. Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#ifdef __rtems__
#include <stdint.h>
#include <freebsd/sys/mbuf.h>
#include <freebsd/sys/protosw.h>
#else
#include <sys/mbuf.h>
#include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <err.h>
#ifdef __rtems__
/* XXX what to do? */
#else
#include <kvm.h>
#include <memstat.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "netstat.h"
/*
* Print mbuf statistics.
*/
void
mbpr(void *kvmd, u_long mbaddr)
{
struct memory_type_list *mtlp;
struct memory_type *mtp;
uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free;
uintmax_t cluster_failures, cluster_size;
uintmax_t packet_count, packet_bytes, packet_free, packet_failures;
uintmax_t tag_count, tag_bytes;
uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free;
uintmax_t jumbop_failures, jumbop_size;
uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free;
uintmax_t jumbo9_failures, jumbo9_size;
uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free;
uintmax_t jumbo16_failures, jumbo16_size;
uintmax_t bytes_inuse, bytes_incache, bytes_total;
int nsfbufs, nsfbufspeak, nsfbufsused;
struct mbstat mbstat;
size_t mlen;
int error;
mtlp = memstat_mtl_alloc();
if (mtlp == NULL) {
warn("memstat_mtl_alloc");
return;
}
/*
* Use memstat_*_all() because some mbuf-related memory is in uma(9),
* and some malloc(9).
*/
if (live) {
if (memstat_sysctl_all(mtlp, 0) < 0) {
warnx("memstat_sysctl_all: %s",
memstat_strerror(memstat_mtl_geterror(mtlp)));
goto out;
}
} else {
if (memstat_kvm_all(mtlp, kvmd) < 0) {
error = memstat_mtl_geterror(mtlp);
if (error == MEMSTAT_ERROR_KVM)
warnx("memstat_kvm_all: %s",
kvm_geterr(kvmd));
else
warnx("memstat_kvm_all: %s",
memstat_strerror(error));
goto out;
}
}
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME);
goto out;
}
mbuf_count = memstat_get_count(mtp);
mbuf_bytes = memstat_get_bytes(mtp);
mbuf_free = memstat_get_free(mtp);
mbuf_failures = memstat_get_failures(mtp);
mbuf_size = memstat_get_size(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found",
MBUF_PACKET_MEM_NAME);
goto out;
}
packet_count = memstat_get_count(mtp);
packet_bytes = memstat_get_bytes(mtp);
packet_free = memstat_get_free(mtp);
packet_failures = memstat_get_failures(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found",
MBUF_CLUSTER_MEM_NAME);
goto out;
}
cluster_count = memstat_get_count(mtp);
cluster_bytes = memstat_get_bytes(mtp);
cluster_limit = memstat_get_countlimit(mtp);
cluster_free = memstat_get_free(mtp);
cluster_failures = memstat_get_failures(mtp);
cluster_size = memstat_get_size(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: malloc type %s not found",
MBUF_TAG_MEM_NAME);
goto out;
}
tag_count = memstat_get_count(mtp);
tag_bytes = memstat_get_bytes(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found",
MBUF_JUMBOP_MEM_NAME);
goto out;
}
jumbop_count = memstat_get_count(mtp);
jumbop_bytes = memstat_get_bytes(mtp);
jumbop_limit = memstat_get_countlimit(mtp);
jumbop_free = memstat_get_free(mtp);
jumbop_failures = memstat_get_failures(mtp);
jumbop_size = memstat_get_size(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found",
MBUF_JUMBO9_MEM_NAME);
goto out;
}
jumbo9_count = memstat_get_count(mtp);
jumbo9_bytes = memstat_get_bytes(mtp);
jumbo9_limit = memstat_get_countlimit(mtp);
jumbo9_free = memstat_get_free(mtp);
jumbo9_failures = memstat_get_failures(mtp);
jumbo9_size = memstat_get_size(mtp);
mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME);
if (mtp == NULL) {
warnx("memstat_mtl_find: zone %s not found",
MBUF_JUMBO16_MEM_NAME);
goto out;
}
jumbo16_count = memstat_get_count(mtp);
jumbo16_bytes = memstat_get_bytes(mtp);
jumbo16_limit = memstat_get_countlimit(mtp);
jumbo16_free = memstat_get_free(mtp);
jumbo16_failures = memstat_get_failures(mtp);
jumbo16_size = memstat_get_size(mtp);
printf("%ju/%ju/%ju mbufs in use (current/cache/total)\n",
mbuf_count + packet_count, mbuf_free + packet_free,
mbuf_count + packet_count + mbuf_free + packet_free);
printf("%ju/%ju/%ju/%ju mbuf clusters in use "
"(current/cache/total/max)\n",
cluster_count - packet_free, cluster_free + packet_free,
cluster_count + cluster_free, cluster_limit);
printf("%ju/%ju mbuf+clusters out of packet secondary zone in use "
"(current/cache)\n",
packet_count, packet_free);
printf("%ju/%ju/%ju/%ju %juk (page size) jumbo clusters in use "
"(current/cache/total/max)\n",
jumbop_count, jumbop_free, jumbop_count + jumbop_free,
jumbop_limit, jumbop_size / 1024);
printf("%ju/%ju/%ju/%ju 9k jumbo clusters in use "
"(current/cache/total/max)\n",
jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free,
jumbo9_limit);
printf("%ju/%ju/%ju/%ju 16k jumbo clusters in use "
"(current/cache/total/max)\n",
jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free,
jumbo16_limit);
#if 0
printf("%ju mbuf tags in use\n", tag_count);
#endif
/*-
* Calculate in-use bytes as:
* - straight mbuf memory
* - mbuf memory in packets
* - the clusters attached to packets
* - and the rest of the non-packet-attached clusters.
* - m_tag memory
* This avoids counting the clusters attached to packets in the cache.
* This currently excludes sf_buf space.
*/
bytes_inuse =
mbuf_bytes + /* straight mbuf memory */
packet_bytes + /* mbufs in packets */
(packet_count * cluster_size) + /* clusters in packets */
/* other clusters */
((cluster_count - packet_count - packet_free) * cluster_size) +
tag_bytes +
(jumbop_count * jumbop_size) + /* jumbo clusters */
(jumbo9_count * jumbo9_size) +
(jumbo16_count * jumbo16_size);
/*
* Calculate in-cache bytes as:
* - cached straught mbufs
* - cached packet mbufs
* - cached packet clusters
* - cached straight clusters
* This currently excludes sf_buf space.
*/
bytes_incache =
(mbuf_free * mbuf_size) + /* straight free mbufs */
(packet_free * mbuf_size) + /* mbufs in free packets */
(packet_free * cluster_size) + /* clusters in free packets */
(cluster_free * cluster_size) + /* free clusters */
(jumbop_free * jumbop_size) + /* jumbo clusters */
(jumbo9_free * jumbo9_size) +
(jumbo16_free * jumbo16_size);
/*
* Total is bytes in use + bytes in cache. This doesn't take into
* account various other misc data structures, overhead, etc, but
* gives the user something useful despite that.
*/
bytes_total = bytes_inuse + bytes_incache;
printf("%juK/%juK/%juK bytes allocated to network "
"(current/cache/total)\n", bytes_inuse / 1024,
bytes_incache / 1024, bytes_total / 1024);
printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/"
"mbuf+clusters)\n", mbuf_failures, cluster_failures,
packet_failures);
printf("%ju/%ju/%ju requests for jumbo clusters denied "
"(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures,
jumbo16_failures, jumbop_size / 1024);
if (live) {
mlen = sizeof(nsfbufs);
if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL,
0) &&
!sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused,
&mlen, NULL, 0) &&
!sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak,
&mlen, NULL, 0))
printf("%d/%d/%d sfbufs in use (current/peak/max)\n",
nsfbufsused, nsfbufspeak, nsfbufs);
mlen = sizeof(mbstat);
if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
warn("kern.ipc.mbstat");
goto out;
}
} else {
if (kread(mbaddr, (char *)&mbstat, sizeof mbstat) != 0)
goto out;
}
printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail);
printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait);
printf("%lu requests for I/O initiated by sendfile\n",
mbstat.sf_iocnt);
printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
out:
memstat_mtl_free(mtlp);
}

View File

@ -0,0 +1,391 @@
/*-
* Copyright (c) 1989 Stephen Deering
* 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. 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/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Print multicast routing structures and statistics.
*
* MROUTING 1.0
*/
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#ifdef __rtems__
#include <freebsd/sys/mbuf.h>
#else
#include <sys/mbuf.h>
#endif
#include <sys/time.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/igmp.h>
#include <net/route.h>
#define _KERNEL 1
#ifdef __rtems__
#include <freebsd/netinet/ip_mroute.h>
#else
#include <netinet/ip_mroute.h>
#endif
#undef _KERNEL
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "netstat.h"
static void print_bw_meter(struct bw_meter *, int *);
static void print_mfc(struct mfc *, int, int *);
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, "%ju", (uintmax_t)bw_meter->bm_measured.b_packets);
else
sprintf(s1, "?");
if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_measured.b_bytes);
else
sprintf(s2, "?");
sprintf(s0, "%lu.%lu|%s|%s",
(u_long)bw_meter->bm_start_time.tv_sec,
(u_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, "%ju", (uintmax_t)bw_meter->bm_threshold.b_packets);
else
sprintf(s1, "?");
if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_threshold.b_bytes);
else
sprintf(s2, "?");
sprintf(s0, "%lu.%lu|%s|%s",
(u_long)bw_meter->bm_threshold.b_time.tv_sec,
(u_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, "%lu.%lu",
(u_long)delta.tv_sec,
(u_long)delta.tv_usec);
} else {
/* Negative time */
timersub(&now, &end, &delta);
sprintf(s3, "-%lu.%lu",
(u_long)delta.tv_sec,
(u_long)delta.tv_usec);
}
printf(" %s", s3);
printf("\n");
}
static void
print_mfc(struct mfc *m, int maxvif, int *banner_printed)
{
struct bw_meter bw_meter, *bwm;
int bw_banner_printed;
int error;
vifi_t vifi;
bw_banner_printed = 0;
if (! *banner_printed) {
printf("\nIPv4 Multicast Forwarding Table\n"
" Origin Group "
" Packets In-Vif Out-Vifs:Ttls\n");
*banner_printed = 1;
}
printf(" %-15.15s", routename(m->mfc_origin.s_addr));
printf(" %-15.15s", routename(m->mfc_mcastgrp.s_addr));
printf(" %9lu", m->mfc_pkt_cnt);
printf(" %3d ", m->mfc_parent);
for (vifi = 0; vifi <= maxvif; vifi++) {
if (m->mfc_ttls[vifi] > 0)
printf(" %u:%u", vifi, m->mfc_ttls[vifi]);
}
printf("\n");
/*
* XXX We break the rules and try to use KVM to read the
* bandwidth meters, they are not retrievable via sysctl yet.
*/
bwm = m->mfc_bw_meter;
while (bwm != NULL) {
error = kread((u_long)bwm, (char *)&bw_meter,
sizeof(bw_meter));
if (error)
break;
print_bw_meter(&bw_meter, &bw_banner_printed);
bwm = bw_meter.bm_mfc_next;
}
}
void
mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
{
struct vif viftable[MAXVIFS];
struct vif *v;
struct mfc *m;
int banner_printed;
int saved_numeric_addr;
size_t len;
vifi_t vifi, maxvif;
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
/*
* TODO:
* The VIF table will move to hanging off the struct if_info for
* each IPv4 configured interface. Currently it is statically
* allocated, and retrieved either using KVM or an opaque SYSCTL.
*
* This can't happen until the API documented in multicast(4)
* is itself refactored. The historical reason why VIFs use
* a separate ifindex space is entirely due to the legacy
* capability of the MROUTING code to create IPIP tunnels on
* the fly to support DVMRP. When gif(4) became available, this
* functionality was deprecated, as PIM does not use it.
*/
maxvif = 0;
len = sizeof(viftable);
if (live) {
if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
0) < 0) {
warn("sysctl: net.inet.ip.viftable");
return;
}
} else
kread(pviftbl, (char *)viftable, sizeof(viftable));
banner_printed = 0;
for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
if (v->v_lcl_addr.s_addr == 0)
continue;
maxvif = vifi;
if (!banner_printed) {
printf("\nIPv4 Virtual Interface Table\n"
" Vif Thresh Local-Address "
"Remote-Address Pkts-In Pkts-Out\n");
banner_printed = 1;
}
printf(" %2u %6u %-15.15s",
/* opposite math of add_vif() */
vifi, v->v_threshold,
routename(v->v_lcl_addr.s_addr));
printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ?
routename(v->v_rmt_addr.s_addr) : "");
printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out);
}
if (!banner_printed)
printf("\nIPv4 Virtual Interface Table is empty\n");
banner_printed = 0;
/*
* TODO:
* The MFC table will move into the AF_INET radix trie in future.
* In 8.x, it becomes a dynamically allocated structure referenced
* by a hashed LIST, allowing more than 256 entries w/o kernel tuning.
*
* If retrieved via opaque SYSCTL, the kernel will coalesce it into
* a static table for us.
* If retrieved via KVM, the hash list pointers must be followed.
*/
if (live) {
struct mfc *mfctable;
len = 0;
if (sysctlbyname("net.inet.ip.mfctable", NULL, &len, NULL,
0) < 0) {
warn("sysctl: net.inet.ip.mfctable");
return;
}
mfctable = malloc(len);
if (mfctable == NULL) {
warnx("malloc %lu bytes", (u_long)len);
return;
}
if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
0) < 0) {
free(mfctable);
warn("sysctl: net.inet.ip.mfctable");
return;
}
m = mfctable;
while (len >= sizeof(*m)) {
print_mfc(m++, maxvif, &banner_printed);
len -= sizeof(*m);
}
if (len != 0)
warnx("print_mfc: %lu trailing bytes", (u_long)len);
free(mfctable);
} else {
LIST_HEAD(, mfc) *mfchashtbl;
u_long i, mfctablesize;
struct mfc mfc;
int error;
error = kread(pmfctablesize, (char *)&mfctablesize,
sizeof(u_long));
if (error) {
warn("kread: mfctablesize");
return;
}
len = sizeof(*mfchashtbl) * mfctablesize;
mfchashtbl = malloc(len);
if (mfchashtbl == NULL) {
warnx("malloc %lu bytes", (u_long)len);
return;
}
kread(pmfchashtbl, (char *)&mfchashtbl, len);
for (i = 0; i < mfctablesize; i++) {
LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
kread((u_long)m, (char *)&mfc, sizeof(mfc));
print_mfc(m, maxvif, &banner_printed);
}
}
free(mfchashtbl);
}
if (!banner_printed)
printf("\nIPv4 Multicast Forwarding Table is empty\n");
printf("\n");
numeric_addr = saved_numeric_addr;
}
void
mrt_stats(u_long mstaddr)
{
struct mrtstat mrtstat;
size_t len = sizeof mrtstat;
if (live) {
if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
0) < 0) {
warn("sysctl: net.inet.ip.mrtstat");
return;
}
} else
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
printf("IPv4 multicast forwarding:\n");
#define p(f, m) if (mrtstat.f || sflag <= 1) \
printf(m, mrtstat.f, plural(mrtstat.f))
#define p2(f, m) if (mrtstat.f || sflag <= 1) \
printf(m, mrtstat.f, plurales(mrtstat.f))
p(mrts_mfc_lookups, "\t%lu multicast forwarding cache lookup%s\n");
p2(mrts_mfc_misses, "\t%lu multicast forwarding cache miss%s\n");
p(mrts_upcalls, "\t%lu upcall%s to multicast routing daemon\n");
p(mrts_upq_ovflw, "\t%lu upcall queue overflow%s\n");
p(mrts_upq_sockfull,
"\t%lu upcall%s dropped due to full socket buffer\n");
p(mrts_cache_cleanups, "\t%lu cache cleanup%s\n");
p(mrts_no_route, "\t%lu datagram%s with no route for origin\n");
p(mrts_bad_tunnel, "\t%lu datagram%s arrived with bad tunneling\n");
p(mrts_cant_tunnel, "\t%lu datagram%s could not be tunneled\n");
p(mrts_wrong_if, "\t%lu datagram%s arrived on wrong interface\n");
p(mrts_drop_sel, "\t%lu datagram%s selectively dropped\n");
p(mrts_q_overflow, "\t%lu datagram%s dropped due to queue overflow\n");
p(mrts_pkt2large, "\t%lu datagram%s dropped for being too large\n");
#undef p2
#undef p
}

View File

@ -0,0 +1,268 @@
/*-
* 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) 1989 Stephen Deering
* 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. 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/cdefs.h>
__FBSDID("$FreeBSD$");
#ifdef INET6
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#ifdef __rtems__
#include <freebsd/sys/mbuf.h>
#else
#include <sys/mbuf.h>
#endif
#include <sys/time.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/route.h>
#include <netinet/in.h>
#include <err.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define KERNEL 1
#include <netinet6/ip6_mroute.h>
#undef KERNEL
#include "netstat.h"
#define WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
#define WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
void
mroute6pr(u_long mfcaddr, u_long mifaddr)
{
struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
struct mif6 mif6table[MAXMIFS];
struct mf6c mfc;
struct rtdetq rte, *rtep;
struct mif6 *mifp;
mifi_t mifi;
int i;
int banner_printed;
int saved_numeric_addr;
mifi_t maxmif = 0;
long int waitings;
size_t len;
len = sizeof(mif6table);
if (live) {
if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
NULL, 0) < 0) {
warn("sysctl: net.inet6.ip6.mif6table");
return;
}
} else
kread(mifaddr, (char *)mif6table, sizeof(mif6table));
saved_numeric_addr = numeric_addr;
numeric_addr = 1;
banner_printed = 0;
for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
struct ifnet ifnet;
char ifname[IFNAMSIZ];
if (mifp->m6_ifp == NULL)
continue;
/* XXX KVM */
kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet));
maxmif = mifi;
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(" %9ju %9ju\n", (uintmax_t)mifp->m6_pkt_in,
(uintmax_t)mifp->m6_pkt_out);
}
if (!banner_printed)
printf("\nIPv6 Multicast Interface Table is empty\n");
len = sizeof(mf6ctable);
if (live) {
if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len,
NULL, 0) < 0) {
warn("sysctl: net.inet6.ip6.mf6ctable");
return;
}
} else
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));
printf(" %-*.*s", WID_GRP, WID_GRP,
routename6(&mfc.mf6c_mcastgrp));
printf(" %9ju", (uintmax_t)mfc.mf6c_pkt_cnt);
for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
waitings++;
/* XXX KVM */
kread((u_long)rtep, (char *)&rte, sizeof(rte));
rtep = rte.next;
}
printf(" %3ld", waitings);
if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
printf(" --- ");
else
printf(" %3d ", mfc.mf6c_parent);
for (mifi = 0; mifi <= maxmif; mifi++) {
if (IF_ISSET(mifi, &mfc.mf6c_ifset))
printf(" %u", mifi);
}
printf("\n");
mfcp = mfc.mf6c_next;
}
}
if (!banner_printed)
printf("\nIPv6 Multicast Forwarding Table is empty\n");
printf("\n");
numeric_addr = saved_numeric_addr;
}
void
mrt6_stats(u_long mstaddr)
{
struct mrt6stat mrtstat;
size_t len = sizeof mrtstat;
if (live) {
if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
NULL, 0) < 0) {
warn("sysctl: net.inet6.ip6.mrt6stat");
return;
}
} else
kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
printf("IPv6 multicast forwarding:\n");
#define p(f, m) if (mrtstat.f || sflag <= 1) \
printf(m, (uintmax_t)mrtstat.f, plural(mrtstat.f))
#define p2(f, m) if (mrtstat.f || sflag <= 1) \
printf(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f))
p(mrt6s_mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n");
p2(mrt6s_mfc_misses, "\t%ju multicast forwarding cache miss%s\n");
p(mrt6s_upcalls, "\t%ju upcall%s to multicast routing daemon\n");
p(mrt6s_upq_ovflw, "\t%ju upcall queue overflow%s\n");
p(mrt6s_upq_sockfull,
"\t%ju upcall%s dropped due to full socket buffer\n");
p(mrt6s_cache_cleanups, "\t%ju cache cleanup%s\n");
p(mrt6s_no_route, "\t%ju datagram%s with no route for origin\n");
p(mrt6s_bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n");
p(mrt6s_cant_tunnel, "\t%ju datagram%s could not be tunneled\n");
p(mrt6s_wrong_if, "\t%ju datagram%s arrived on wrong interface\n");
p(mrt6s_drop_sel, "\t%ju datagram%s selectively dropped\n");
p(mrt6s_q_overflow,
"\t%ju datagram%s dropped due to queue overflow\n");
p(mrt6s_pkt2large, "\t%ju datagram%s dropped for being too large\n");
#undef p2
#undef p
}
#endif /*INET6*/

View File

@ -0,0 +1,196 @@
/*-
* Copyright (c) 1996-1999 Whistle Communications, Inc.
* All rights reserved.
*
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* provided, however, that:
* 1. Any and all reproductions of the source or object code must include the
* copyright notice above and the following disclaimer of warranties; and
* 2. No rights are granted, in any manner or form, to use Whistle
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
*
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
* WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
* REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
* SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
* IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
* RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
* WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER 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 WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#include <freebsd/sys/linker.h>
#else
#include <sys/protosw.h>
#include <sys/linker.h>
#endif
#include <net/route.h>
#include <netgraph.h>
#include <netgraph/ng_message.h>
#include <netgraph/ng_socket.h>
#include <netgraph/ng_socketvar.h>
#include <nlist.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <err.h>
#include "netstat.h"
static int first = 1;
static int csock = -1;
void
netgraphprotopr(u_long off, const char *name, int af1 __unused,
int proto __unused)
{
struct ngpcb *this, *next;
struct ngpcb ngpcb;
struct ngsock info;
struct socket sockb;
int debug = 1;
/* If symbol not found, try looking in the KLD module */
if (off == 0) {
const char *const modname = "ng_socket.ko";
/* XXX We should get "mpath" from "sysctl kern.module_path" */
const char *mpath[] = { "/", "/boot/", "/modules/", NULL };
struct nlist sym[] = { { .n_name = "_ngsocklist" },
{ .n_name = NULL } };
const char **pre;
struct kld_file_stat ks;
int fileid;
/* Can't do this for core dumps. */
if (!live)
return;
/* See if module is loaded */
if ((fileid = kldfind(modname)) < 0) {
if (debug)
warn("kldfind(%s)", modname);
return;
}
/* Get module info */
memset(&ks, 0, sizeof(ks));
ks.version = sizeof(struct kld_file_stat);
if (kldstat(fileid, &ks) < 0) {
if (debug)
warn("kldstat(%d)", fileid);
return;
}
/* Get symbol table from module file */
for (pre = mpath; *pre; pre++) {
char path[MAXPATHLEN];
snprintf(path, sizeof(path), "%s%s", *pre, modname);
if (nlist(path, sym) == 0)
break;
}
/* Did we find it? */
if (sym[0].n_value == 0) {
if (debug)
warnx("%s not found", modname);
return;
}
/* Symbol found at load address plus symbol offset */
off = (u_long) ks.address + sym[0].n_value;
}
/* Get pointer to first socket */
kread(off, (char *)&this, sizeof(this));
/* Get my own socket node */
if (csock == -1)
NgMkSockNode(NULL, &csock, NULL);
for (; this != NULL; this = next) {
u_char rbuf[sizeof(struct ng_mesg) + sizeof(struct nodeinfo)];
struct ng_mesg *resp = (struct ng_mesg *) rbuf;
struct nodeinfo *ni = (struct nodeinfo *) resp->data;
char path[64];
/* Read in ngpcb structure */
kread((u_long)this, (char *)&ngpcb, sizeof(ngpcb));
next = LIST_NEXT(&ngpcb, socks);
/* Read in socket structure */
kread((u_long)ngpcb.ng_socket, (char *)&sockb, sizeof(sockb));
/* Check type of socket */
if (strcmp(name, "ctrl") == 0 && ngpcb.type != NG_CONTROL)
continue;
if (strcmp(name, "data") == 0 && ngpcb.type != NG_DATA)
continue;
/* Do headline */
if (first) {
printf("Netgraph sockets\n");
if (Aflag)
printf("%-8.8s ", "PCB");
printf("%-5.5s %-6.6s %-6.6s %-14.14s %s\n",
"Type", "Recv-Q", "Send-Q",
"Node Address", "#Hooks");
first = 0;
}
/* Show socket */
if (Aflag)
printf("%8lx ", (u_long) this);
printf("%-5.5s %6u %6u ",
name, sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc);
/* Get ngsock structure */
if (ngpcb.sockdata == NULL) /* unconnected data socket */
goto finish;
kread((u_long)ngpcb.sockdata, (char *)&info, sizeof(info));
/* Get info on associated node */
if (info.node_id == 0 || csock == -1)
goto finish;
snprintf(path, sizeof(path), "[%x]:", info.node_id);
if (NgSendMsg(csock, path,
NGM_GENERIC_COOKIE, NGM_NODEINFO, NULL, 0) < 0)
goto finish;
if (NgRecvMsg(csock, resp, sizeof(rbuf), NULL) < 0)
goto finish;
/* Display associated node info */
if (*ni->name != '\0')
snprintf(path, sizeof(path), "%s:", ni->name);
printf("%-14.14s %4d", path, ni->hooks);
finish:
putchar('\n');
}
}

View File

@ -0,0 +1,523 @@
.\" 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. 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.
.\"
.\" @(#)netstat.1 8.8 (Berkeley) 4/18/94
.\" $FreeBSD$
.\"
.Dd January 10, 2010
.Dt NETSTAT 1
.Os
.Sh NAME
.Nm netstat
.Nd show network status
.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.
.Bl -tag -width indent
.It Xo
.Bk -words
.Nm
.Op Fl AaLnSWx
.Op Fl f Ar protocol_family | Fl p Ar protocol
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display a list of active sockets
(protocol control blocks)
for each network protocol,
for a particular
.Ar protocol_family ,
or for a single
.Ar protocol .
If
.Fl A
is also present,
show the address of a protocol control block (PCB)
associated with a socket; used for debugging.
If
.Fl a
is also present,
show the state of all sockets;
normally sockets used by server processes are not shown.
If
.Fl L
is also present,
show the size of the various listen queues.
The first count shows the number of unaccepted connections,
the second count shows the amount of unaccepted incomplete connections,
and the third count is the maximum number of queued connections.
If
.Fl S
is also present,
show network addresses as numbers (as with
.Fl n )
but show ports symbolically.
If
.Fl x
is present display full socket buffer statistics for each internet socket.
.It Xo
.Bk -words
.Nm
.Fl i | I Ar interface
.Op Fl abdhntW
.Op Fl f Ar address_family
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Show the state of all network interfaces or a single
.Ar interface
which have been auto-configured
(interfaces statically configured into a system, but not
located at boot time are not shown).
An asterisk
.Pq Dq Li *
after an interface name indicates that the interface is
.Dq down .
If
.Fl a
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
.Fl b
is also present, show the number of bytes in and out.
If
.Fl d
is also present, show the number of dropped packets.
If
.Fl h
is also present, print all counters in human readable form.
If
.Fl t
is also present, show the contents of watchdog timers.
If
.Fl W
is also present, print interface names using a wider field size.
.It Xo
.Bk -words
.Nm
.Fl w Ar wait
.Op Fl I Ar interface
.Op Fl d
.Op Fl M Ar core
.Op Fl N Ar system
.Op Fl q Ar howmany
.Ek
.Xc
At intervals of
.Ar wait
seconds,
display the information regarding packet
traffic on all configured network interfaces
or a single
.Ar interface .
If
.Fl q
is also present, exit after
.Ar howmany
outputs.
If
.Fl d
is also present, show the number of dropped packets.
.It Xo
.Bk -words
.Nm
.Fl s Op Fl s
.Op Fl z
.Op Fl f Ar protocol_family | Fl p Ar protocol
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display system-wide statistics for each network protocol,
for a particular
.Ar protocol_family ,
or for a single
.Ar protocol .
If
.Fl s
is repeated, counters with a value of zero are suppressed.
If
.Fl z
is also present, reset statistic counters after displaying them.
.It Xo
.Bk -words
.Nm
.Fl i | I Ar interface Fl s
.Op Fl f Ar protocol_family | Fl p Ar protocol
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display per-interface statistics for each network protocol,
for a particular
.Ar protocol_family ,
or for a single
.Ar protocol .
.It Xo
.Bk -words
.Nm
.Fl m
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Show statistics recorded by the memory management routines
.Pq Xr mbuf 9 .
The network manages a private pool of memory buffers.
.It Xo
.Bk -words
.Nm
.Fl B
.Op Fl z
.Op Fl I Ar interface
.Ek
.Xc
Show statistics about
.Xr bpf 4
peers.
This includes information like
how many packets have been matched, dropped and received by the
bpf device, also information about current buffer sizes and device
states.
.It Xo
.Bk -words
.Nm
.Fl r
.Op Fl AanW
.Op Fl f Ar address_family
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display the contents of all routing tables,
or a routing table for a particular
.Ar address_family .
If
.Fl A
is also present,
show the contents of the internal Patricia tree
structures; used for debugging.
If
.Fl a
is also present,
show protocol-cloned routes
(routes generated by an
.Dv RTF_PRCLONING
parent route);
normally these routes are not shown.
When
.Fl W
is also present,
show the path MTU
for each route,
and print interface
names with a wider
field size.
.It Xo
.Bk -words
.Nm
.Fl rs
.Op Fl s
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display routing statistics.
If
.Fl s
is repeated, counters with a value of zero are suppressed.
.It Xo
.Bk -words
.Nm
.Fl g
.Op Fl W
.Op Fl f Ar address_family
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Display the contents of the multicast virtual interface tables,
and multicast forwarding caches.
Entries in these tables will appear only when the kernel is
actively forwarding multicast sessions.
This option is applicable only to the
.Cm inet
and
.Cm inet6
address families.
.It Xo
.Bk -words
.Nm
.Fl gs
.Op Fl s
.Op Fl f Ar address_family
.Op Fl M Ar core
.Op Fl N Ar system
.Ek
.Xc
Show multicast routing statistics.
If
.Fl s
is repeated, counters with a value of zero are suppressed.
.El
.Pp
Some options have the general meaning:
.Bl -tag -width flag
.It Fl f Ar address_family , Fl p Ar protocol
Limit display to those records
of the specified
.Ar address_family
or a single
.Ar protocol .
The following address families and protocols are recognized:
.Pp
.Bl -tag -width ".Cm netgraph , ng Pq Dv AF_NETGRAPH" -compact
.It Em Family
.Em Protocols
.It Cm inet Pq Dv AF_INET
.Cm divert , icmp , igmp , ip , ipsec , pim, sctp , tcp , udp
.It Cm inet6 Pq Dv AF_INET6
.Cm icmp6 , ip6 , ipsec6 , rip6 , tcp , udp
.It Cm pfkey Pq Dv PF_KEY
.Cm pfkey
.It Cm atalk Pq Dv AF_APPLETALK
.Cm ddp
.It Cm netgraph , ng Pq Dv AF_NETGRAPH
.Cm ctrl , data
.It Cm ipx Pq Dv AF_IPX
.Cm ipx , spx
.\".It Cm ns Pq Dv AF_NS
.\".Cm idp , ns_err , spp
.\".It Cm iso Pq Dv AF_ISO
.\".Cm clnp , cltp , esis , tp
.It Cm unix Pq Dv AF_UNIX
.It Cm link Pq Dv AF_LINK
.El
.Pp
The program will complain if
.Ar protocol
is unknown or if there is no statistics routine for it.
.It Fl M
Extract values associated with the name list from the specified core
instead of the default
.Pa /dev/kmem .
.It Fl N
Extract the name list from the specified system instead of the default,
which is the kernel image the system has booted from.
.It Fl n
Show network addresses and ports as numbers.
Normally
.Nm
attempts to resolve addresses and ports,
and display them symbolically.
.It Fl W
In certain displays, avoid truncating addresses even if this causes
some fields to overflow.
.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
.Dq host.port
or
.Dq 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 databases
.Xr hosts 5
and
.Xr networks 5 ,
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 IPv4
.Dq dot format ,
refer to
.Xr inet 3 .
Unspecified,
or
.Dq wildcard ,
addresses and ports appear as
.Dq Li * .
.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
.Pq Dq 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 ".Li W" ".Dv RTF_WASCLONED"
.It Li 1 Ta Dv RTF_PROTO1 Ta "Protocol specific routing flag #1"
.It Li 2 Ta Dv RTF_PROTO2 Ta "Protocol specific routing flag #2"
.It Li 3 Ta Dv RTF_PROTO3 Ta "Protocol specific routing flag #3"
.It Li B Ta Dv RTF_BLACKHOLE Ta "Just discard pkts (during updates)"
.It Li b Ta Dv RTF_BROADCAST Ta "The route represents a broadcast address"
.It Li C Ta Dv RTF_CLONING Ta "Generate new routes on use"
.It Li c Ta Dv RTF_PRCLONING Ta "Protocol-specified generate new routes on use"
.It Li D Ta Dv RTF_DYNAMIC Ta "Created dynamically (by redirect)"
.It Li G Ta Dv RTF_GATEWAY Ta "Destination requires forwarding by intermediary"
.It Li H Ta Dv RTF_HOST Ta "Host entry (net otherwise)"
.It Li L Ta Dv RTF_LLINFO Ta "Valid protocol to link address translation"
.It Li M Ta Dv RTF_MODIFIED Ta "Modified dynamically (by redirect)"
.It Li R Ta Dv RTF_REJECT Ta "Host or net unreachable"
.It Li S Ta Dv RTF_STATIC Ta "Manually added"
.It Li U Ta Dv RTF_UP Ta "Route usable"
.It Li W Ta Dv RTF_WASCLONED Ta "Route was generated as a result of cloning"
.It Li X Ta Dv RTF_XRESOLVE Ta "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 interface entry indicates the network interface utilized 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.
By default, this display summarizes information for all interfaces.
Information for a specific interface may be displayed with the
.Fl I
option.
.Pp
The
.Xr bpf 4
flags displayed when
.Nm
is invoked with the
.Fl B
option represent the underlying parameters of the bpf peer.
Each flag is
represented as a single lower case letter.
The mapping between the letters and flags in order of appearance are:
.Bl -column ".Li i"
.It Li p Ta Set if listening promiscuously
.It Li i Ta Dv BIOCIMMEDIATE No has been set on the device
.It Li f Ta Dv BIOCGHDRCMPLT No status: source link addresses are being
filled automatically
.It Li s Ta Dv BIOCGSEESENT No status: see packets originating locally and
remotely on the interface.
.It Li a Ta Packet reception generates a signal
.It Li l Ta Dv BIOCLOCK No status: descriptor has been locked
.El
.Pp
For more information about these flags, please refer to
.Xr bpf 4 .
.Pp
The
.Fl x
flag causes
.Nm
to output all the information recorded about data
stored in the socket buffers.
The fields are:
.Bl -column ".Li R-MBUF"
.It Li R-MBUF Ta Number of mbufs in the receive queue.
.It Li S-MBUF Ta Number of mbufs in the send queue.
.It Li R-CLUS Ta Number of clusters, of any type, in the receive
queue.
.It Li S-CLUS Ta Number of clusters, of any type, in the send queue.
.It Li R-HIWA Ta Receive buffer high water mark, in bytes.
.It Li S-HIWA Ta Send buffer high water mark, in bytes.
.It Li R-LOWA Ta Receive buffer low water mark, in bytes.
.It Li S-LOWA Ta Send buffer low water mark, in bytes.
.It Li R-BCNT Ta Receive buffer byte count.
.It Li S-BCNT Ta Send buffer byte count.
.It Li R-BMAX Ta Maximum bytes that can be used in the receive buffer.
.It Li S-BMAX Ta Maximum bytes that can be used in the send buffer.
.El
.Sh SEE ALSO
.Xr fstat 1 ,
.Xr nfsstat 1 ,
.Xr procstat 1 ,
.Xr ps 1 ,
.Xr sockstat 1 ,
.Xr bpf 4 ,
.Xr inet 4 ,
.Xr route 4 ,
.Xr unix 4 ,
.Xr hosts 5 ,
.Xr networks 5 ,
.Xr protocols 5 ,
.Xr services 5 ,
.Xr iostat 8 ,
.Xr route 8 ,
.Xr trpt 8 ,
.Xr vmstat 8 ,
.Xr mbuf 9
.Sh HISTORY
The
.Nm
command appeared in
.Bx 4.2 .
.Pp
IPv6 support was added by WIDE/KAME project.
.Sh BUGS
The notion of errors is ill-defined.

View File

@ -0,0 +1,167 @@
/*-
* 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. 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.
*
* @(#)netstat.h 8.2 (Berkeley) 1/4/94
* $FreeBSD$
*/
#include <sys/cdefs.h>
extern int Aflag; /* show addresses of protocol control block */
extern int aflag; /* show all sockets (including servers) */
extern int bflag; /* show i/f total bytes in/out */
extern int dflag; /* show i/f dropped packets */
extern int gflag; /* show group (multicast) routing or stats */
extern int hflag; /* show counters in human readable format */
extern int iflag; /* show interfaces */
extern int Lflag; /* show size of listen queues */
extern int mflag; /* show memory stats */
extern int noutputs; /* how much outputs before we exit */
extern int numeric_addr; /* show addresses numerically */
extern int numeric_port; /* show ports numerically */
extern int rflag; /* show routing tables (or routing stats) */
extern int sflag; /* show protocol statistics */
extern int tflag; /* show i/f watchdog timers */
extern int Wflag; /* wide display */
extern int xflag; /* extended display, includes all socket buffer info */
extern int zflag; /* zero stats */
extern int interval; /* repeat interval for i/f stats */
extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
extern int unit; /* unit number for above */
extern int af; /* address family */
extern int live; /* true if we are examining a live system */
int kread(u_long addr, void *buf, size_t size);
const char *plural(uintmax_t);
const char *plurales(uintmax_t);
const char *pluralies(uintmax_t);
int sotoxsocket(struct socket *, struct xsocket *);
void protopr(u_long, const char *, int, int);
void tcp_stats(u_long, const char *, int, int);
void udp_stats(u_long, const char *, int, int);
#ifdef SCTP
void sctp_protopr(u_long, const char *, int, int);
void sctp_stats(u_long, const char *, int, int);
#endif
void arp_stats(u_long, const char *, int, int);
void ip_stats(u_long, const char *, int, int);
void icmp_stats(u_long, const char *, int, int);
void igmp_stats(u_long, const char *, int, int);
void pim_stats(u_long, const char *, int, int);
void carp_stats(u_long, const char *, int, int);
void pfsync_stats(u_long, const char *, int, int);
#ifdef IPSEC
void ipsec_stats(u_long, const char *, int, int);
void esp_stats(u_long, const char *, int, int);
void ah_stats(u_long, const char *, int, int);
void ipcomp_stats(u_long, const char *, int, int);
#endif
#ifdef INET6
void ip6_stats(u_long, const char *, int, int);
void ip6_ifstats(char *);
void icmp6_stats(u_long, const char *, int, int);
void icmp6_ifstats(char *);
void pim6_stats(u_long, const char *, int, int);
void rip6_stats(u_long, const char *, int, int);
void mroute6pr(u_long, u_long);
void mrt6_stats(u_long);
struct sockaddr_in6;
struct in6_addr;
char *routename6(struct sockaddr_in6 *);
const char *netname6(struct sockaddr_in6 *, struct in6_addr *);
void inet6print(struct in6_addr *, int, const char *, int);
#endif /*INET6*/
#ifdef IPSEC
void pfkey_stats(u_long, const char *, int, int);
#endif
void mbpr(void *, u_long);
void hostpr(u_long, u_long);
void impstats(u_long, u_long);
void intpr(int, u_long, void (*)(char *));
void pr_rthdr(int);
void pr_family(int);
void rt_stats(u_long, u_long);
char *ipx_pnet(struct sockaddr *);
char *ipx_phost(struct sockaddr *);
char *ns_phost(struct sockaddr *);
void upHex(char *);
char *routename(in_addr_t);
char *netname(in_addr_t, u_long);
char *atalk_print(struct sockaddr *, int);
char *atalk_print2(struct sockaddr *, struct sockaddr *, int);
char *ipx_print(struct sockaddr *);
char *ns_print(struct sockaddr *);
void routepr(u_long);
void ipxprotopr(u_long, const char *, int, int);
void spx_stats(u_long, const char *, int, int);
void ipx_stats(u_long, const char *, int, int);
void ipxerr_stats(u_long, const char *, int, int);
void nsprotopr(u_long, const char *, int, int);
void spp_stats(u_long, const char *, int, int);
void idp_stats(u_long, const char *, int, int);
void nserr_stats(u_long, const char *, int, int);
void atalkprotopr(u_long, const char *, int, int);
void ddp_stats(u_long, const char *, int, int);
#ifdef NETGRAPH
void netgraphprotopr(u_long, const char *, int, int);
#endif
void unixpr(u_long, u_long, u_long, u_long);
void esis_stats(u_long, const char *, int, int);
void clnp_stats(u_long, const char *, int, int);
void cltp_stats(u_long, const char *, int, int);
void iso_protopr(u_long, const char *, int, int);
void iso_protopr1(u_long, int);
void tp_protopr(u_long, const char *, int, int);
void tp_inproto(u_long);
void tp_stats(caddr_t, caddr_t);
void mroutepr(u_long, u_long, u_long);
void mrt_stats(u_long);
void bpf_stats(char *);

View File

@ -0,0 +1,184 @@
/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */
/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 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. 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.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <netinet/in.h>
#ifdef IPSEC
#ifdef __rtems__
#include <freebsd/netipsec/keysock.h>
#else
#include <netipsec/keysock.h>
#endif
#endif
#include <stdint.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, int family __unused,
int proto __unused)
{
struct pfkeystat pfkeystat;
unsigned first, type;
if (off == 0)
return;
printf ("%s:\n", name);
kread(off, (char *)&pfkeystat, sizeof(pfkeystat));
#define p(f, m) if (pfkeystat.f || sflag <= 1) \
printf(m, (uintmax_t)pfkeystat.f, plural(pfkeystat.f))
/* userland -> kernel */
p(out_total, "\t%ju request%s sent from userland\n");
p(out_bytes, "\t%ju byte%s sent from userland\n");
for (first = 1, type = 0;
type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
type++) {
if (pfkeystat.out_msgtype[type] <= 0)
continue;
if (first) {
printf("\thistogram by message type:\n");
first = 0;
}
printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
(uintmax_t)pfkeystat.out_msgtype[type]);
}
p(out_invlen, "\t%ju message%s with invalid length field\n");
p(out_invver, "\t%ju message%s with invalid version field\n");
p(out_invmsgtype, "\t%ju message%s with invalid message type field\n");
p(out_tooshort, "\t%ju message%s too short\n");
p(out_nomem, "\t%ju message%s with memory allocation failure\n");
p(out_dupext, "\t%ju message%s with duplicate extension\n");
p(out_invexttype, "\t%ju message%s with invalid extension type\n");
p(out_invsatype, "\t%ju message%s with invalid sa type\n");
p(out_invaddr, "\t%ju message%s with invalid address extension\n");
/* kernel -> userland */
p(in_total, "\t%ju request%s sent to userland\n");
p(in_bytes, "\t%ju byte%s sent to userland\n");
for (first = 1, type = 0;
type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
type++) {
if (pfkeystat.in_msgtype[type] <= 0)
continue;
if (first) {
printf("\thistogram by message type:\n");
first = 0;
}
printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
(uintmax_t)pfkeystat.in_msgtype[type]);
}
p(in_msgtarget[KEY_SENDUP_ONE],
"\t%ju message%s toward single socket\n");
p(in_msgtarget[KEY_SENDUP_ALL],
"\t%ju message%s toward all sockets\n");
p(in_msgtarget[KEY_SENDUP_REGISTERED],
"\t%ju message%s toward registered sockets\n");
p(in_nomem, "\t%ju message%s with memory allocation failure\n");
#undef p
}
#endif /* IPSEC */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,703 @@
/*-
* Copyright (c) 2001-2007, by Weongyo Jeong. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* a) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* b) 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.
*
* c) Neither the name of Cisco Systems, Inc. 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)sctp.c 0.1 (Berkeley) 4/18/2007";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <netinet/in.h>
#ifdef __rtems__
#include <freebsd/netinet/sctp.h>
#include <freebsd/netinet/sctp_constants.h>
#else
#include <netinet/sctp.h>
#include <netinet/sctp_constants.h>
#endif
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#ifdef __rtems__
/* apparently libutil.h is not needed */
#else
#include <libutil.h>
#endif
#include <netdb.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#ifdef SCTP
void inetprint(struct in_addr *, int, const char *, int);
static void sctp_statesprint(uint32_t state);
#define NETSTAT_SCTP_STATES_CLOSED 0x0
#define NETSTAT_SCTP_STATES_BOUND 0x1
#define NETSTAT_SCTP_STATES_LISTEN 0x2
#define NETSTAT_SCTP_STATES_COOKIE_WAIT 0x3
#define NETSTAT_SCTP_STATES_COOKIE_ECHOED 0x4
#define NETSTAT_SCTP_STATES_ESTABLISHED 0x5
#define NETSTAT_SCTP_STATES_SHUTDOWN_SENT 0x6
#define NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED 0x7
#define NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT 0x8
#define NETSTAT_SCTP_STATES_SHUTDOWN_PENDING 0x9
char *sctpstates[] = {
"CLOSED",
"BOUND",
"LISTEN",
"COOKIE_WAIT",
"COOKIE_ECHOED",
"ESTABLISHED",
"SHUTDOWN_SENT",
"SHUTDOWN_RECEIVED",
"SHUTDOWN_ACK_SENT",
"SHUTDOWN_PENDING"
};
LIST_HEAD(xladdr_list, xladdr_entry) xladdr_head;
struct xladdr_entry {
struct xsctp_laddr *xladdr;
LIST_ENTRY(xladdr_entry) xladdr_entries;
};
LIST_HEAD(xraddr_list, xraddr_entry) xraddr_head;
struct xraddr_entry {
struct xsctp_raddr *xraddr;
LIST_ENTRY(xraddr_entry) xraddr_entries;
};
static int
sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
{
int exist_tcb = 0;
struct xsctp_tcb *xstcb;
struct xsctp_raddr *xraddr;
struct xsctp_laddr *xladdr;
while (*offset < buflen) {
xladdr = (struct xsctp_laddr *)(buf + *offset);
*offset += sizeof(struct xsctp_laddr);
if (xladdr->last == 1)
break;
}
while (*offset < buflen) {
xstcb = (struct xsctp_tcb *)(buf + *offset);
*offset += sizeof(struct xsctp_tcb);
if (xstcb->last == 1)
break;
exist_tcb = 1;
while (*offset < buflen) {
xladdr = (struct xsctp_laddr *)(buf + *offset);
*offset += sizeof(struct xsctp_laddr);
if (xladdr->last == 1)
break;
}
while (*offset < buflen) {
xraddr = (struct xsctp_raddr *)(buf + *offset);
*offset += sizeof(struct xsctp_raddr);
if (xraddr->last == 1)
break;
}
}
/*
* If Lflag is set, we don't care about the return value.
*/
if (Lflag)
return 0;
return exist_tcb;
}
static void
sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
char *buf, const size_t buflen, size_t *offset, int *indent)
{
int i, xl_total = 0, xr_total = 0, x_max;
struct sockaddr *sa;
struct xsctp_raddr *xraddr;
struct xsctp_laddr *xladdr;
struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
#ifdef INET6
struct sockaddr_in6 *in6;
#endif
LIST_INIT(&xladdr_head);
LIST_INIT(&xraddr_head);
/*
* Make `struct xladdr_list' list and `struct xraddr_list' list
* to handle the address flexibly.
*/
while (*offset < buflen) {
xladdr = (struct xsctp_laddr *)(buf + *offset);
*offset += sizeof(struct xsctp_laddr);
if (xladdr->last == 1)
break;
prev_xl = xl;
xl = malloc(sizeof(struct xladdr_entry));
if (xl == NULL) {
warnx("malloc %lu bytes",
(u_long)sizeof(struct xladdr_entry));
goto out;
}
xl->xladdr = xladdr;
if (prev_xl == NULL)
LIST_INSERT_HEAD(&xladdr_head, xl, xladdr_entries);
else
LIST_INSERT_AFTER(prev_xl, xl, xladdr_entries);
xl_total++;
}
while (*offset < buflen) {
xraddr = (struct xsctp_raddr *)(buf + *offset);
*offset += sizeof(struct xsctp_raddr);
if (xraddr->last == 1)
break;
prev_xr = xr;
xr = malloc(sizeof(struct xraddr_entry));
if (xr == NULL) {
warnx("malloc %lu bytes",
(u_long)sizeof(struct xraddr_entry));
goto out;
}
xr->xraddr = xraddr;
if (prev_xr == NULL)
LIST_INSERT_HEAD(&xraddr_head, xr, xraddr_entries);
else
LIST_INSERT_AFTER(prev_xr, xr, xraddr_entries);
xr_total++;
}
/*
* Let's print the address infos.
*/
xl = LIST_FIRST(&xladdr_head);
xr = LIST_FIRST(&xraddr_head);
x_max = (xl_total > xr_total) ? xl_total : xr_total;
for (i = 0; i < x_max; i++) {
if (((*indent == 0) && i > 0) || *indent > 0)
printf("%-11s ", " ");
if (xl != NULL) {
sa = &(xl->xladdr->address.sa);
if ((sa->sa_family) == AF_INET)
inetprint(&((struct sockaddr_in *)sa)->sin_addr,
htons(xstcb->local_port),
name, numeric_port);
#ifdef INET6
else {
in6 = (struct sockaddr_in6 *)sa;
inet6print(&in6->sin6_addr,
htons(xstcb->local_port),
name, numeric_port);
}
#endif
}
if (xr != NULL && !Lflag) {
sa = &(xr->xraddr->address.sa);
if ((sa->sa_family) == AF_INET)
inetprint(&((struct sockaddr_in *)sa)->sin_addr,
htons(xstcb->remote_port),
name, numeric_port);
#ifdef INET6
else {
in6 = (struct sockaddr_in6 *)sa;
inet6print(&in6->sin6_addr,
htons(xstcb->remote_port),
name, numeric_port);
}
#endif
}
if (xl != NULL)
xl = LIST_NEXT(xl, xladdr_entries);
if (xr != NULL)
xr = LIST_NEXT(xr, xraddr_entries);
if (i == 0 && !Lflag)
sctp_statesprint(xstcb->state);
if (i < x_max)
putchar('\n');
}
out:
/*
* Free the list which be used to handle the address.
*/
xl = LIST_FIRST(&xladdr_head);
while (xl != NULL) {
xl_tmp = LIST_NEXT(xl, xladdr_entries);
free(xl);
xl = xl_tmp;
}
xr = LIST_FIRST(&xraddr_head);
while (xr != NULL) {
xr_tmp = LIST_NEXT(xr, xraddr_entries);
free(xr);
xr = xr_tmp;
}
}
#ifdef SCTP_DEBUG
uint32_t sctp_pdup[64];
int sctp_pcnt = 0;
#endif
static void
sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
char *buf, const size_t buflen, size_t *offset)
{
int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
static int first = 1;
char *tname;
struct xsctp_tcb *xstcb;
struct xsctp_laddr *xladdr;
struct sockaddr *sa;
#ifdef INET6
struct sockaddr_in6 *in6;
#endif
if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
is_listening = 1;
if (!Lflag && !is_listening &&
!(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
#ifdef SCTP_DEBUG
int i, found = 0;
for (i = 0; i < sctp_pcnt; i++) {
if (sctp_pdup[i] == xinpcb->flags) {
found = 1;
break;
}
}
if (!found) {
sctp_pdup[sctp_pcnt++] = xinpcb->flags;
if (sctp_pcnt >= 64)
sctp_pcnt = 0;
printf("[0x%08x]", xinpcb->flags);
}
#endif
offset_backup = *offset;
if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
return;
*offset = offset_backup;
}
if (first) {
if (!Lflag) {
printf("Active SCTP associations");
if (aflag)
printf(" (including servers)");
} else
printf("Current listen queue sizes (qlen/maxqlen)");
putchar('\n');
if (Aflag)
printf("%-8.8s ", "Socket");
if (Lflag)
printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
"Proto", "Type", "Listen", "Local Address");
else
printf((Aflag && !Wflag) ?
"%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
"%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
"Proto", "Type",
"Local Address", "Foreign Address",
"(state)");
first = 0;
}
if (Lflag && xinpcb->maxqlen == 0) {
(int)sctp_skip_xinpcb_ifneed(buf, buflen, offset);
return;
}
if (Aflag)
printf("%8lx ", (u_long)xinpcb);
printf("%-5.5s ", name);
if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
tname = "1to1";
else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
tname = "1toN";
else
return;
printf("%-5.5s ", tname);
if (Lflag) {
char buf1[9];
snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
printf("%-8.8s ", buf1);
}
/*
* process the local address. This routine are used for Lflag.
*/
while (*offset < buflen) {
xladdr = (struct xsctp_laddr *)(buf + *offset);
*offset += sizeof(struct xsctp_laddr);
if (xladdr->last == 1)
break;
if (!Lflag && !is_listening)
continue;
if (xladdr_total != 0)
putchar('\n');
if (xladdr_total > 0)
printf((Lflag) ?
"%-20.20s " : "%-11.11s ", " ");
sa = &(xladdr->address.sa);
if ((sa->sa_family) == AF_INET)
inetprint(&((struct sockaddr_in *)sa)->sin_addr,
htons(xinpcb->local_port), name, numeric_port);
#ifdef INET6
else {
in6 = (struct sockaddr_in6 *)sa;
inet6print(&in6->sin6_addr,
htons(xinpcb->local_port), name, numeric_port);
}
#endif
if (!Lflag && xladdr_total == 0 && is_listening == 1)
printf("%-22.22s LISTEN", " ");
xladdr_total++;
}
xstcb = (struct xsctp_tcb *)(buf + *offset);
*offset += sizeof(struct xsctp_tcb);
while (xstcb->last == 0 && *offset < buflen) {
sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
indent++;
xstcb = (struct xsctp_tcb *)(buf + *offset);
*offset += sizeof(struct xsctp_tcb);
}
putchar('\n');
}
/*
* Print a summary of SCTP connections related to an Internet
* protocol.
*/
void
sctp_protopr(u_long off __unused,
const char *name, int af1, int proto)
{
char *buf;
const char *mibvar = "net.inet.sctp.assoclist";
size_t offset = 0;
size_t len = 0;
struct xsctp_inpcb *xinpcb;
if (proto != IPPROTO_SCTP)
return;
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
if (errno != ENOENT)
warn("sysctl: %s", mibvar);
return;
}
if ((buf = malloc(len)) == 0) {
warnx("malloc %lu bytes", (u_long)len);
return;
}
if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
warn("sysctl: %s", mibvar);
free(buf);
return;
}
xinpcb = (struct xsctp_inpcb *)(buf + offset);
offset += sizeof(struct xsctp_inpcb);
while (xinpcb->last == 0 && offset < len) {
sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
&offset);
xinpcb = (struct xsctp_inpcb *)(buf + offset);
offset += sizeof(struct xsctp_inpcb);
}
free(buf);
}
static void
sctp_statesprint(uint32_t state)
{
int idx;
switch (state) {
case SCTP_STATE_COOKIE_WAIT:
idx = NETSTAT_SCTP_STATES_COOKIE_WAIT;
break;
case SCTP_STATE_COOKIE_ECHOED:
idx = NETSTAT_SCTP_STATES_COOKIE_ECHOED;
break;
case SCTP_STATE_OPEN:
idx = NETSTAT_SCTP_STATES_ESTABLISHED;
break;
case SCTP_STATE_SHUTDOWN_SENT:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_SENT;
break;
case SCTP_STATE_SHUTDOWN_RECEIVED:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED;
break;
case SCTP_STATE_SHUTDOWN_ACK_SENT:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT;
break;
case SCTP_STATE_SHUTDOWN_PENDING:
idx = NETSTAT_SCTP_STATES_SHUTDOWN_PENDING;
break;
default:
printf("UNKNOWN 0x%08x", state);
return;
}
printf("%s", sctpstates[idx]);
}
/*
* Dump SCTP statistics structure.
*/
void
sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
{
struct sctpstat sctpstat, zerostat;
size_t len = sizeof(sctpstat);
if (live) {
if (zflag)
memset(&zerostat, 0, len);
if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
warn("sysctl: net.inet.sctp.stats");
return;
}
} else
kread(off, &sctpstat, len);
printf ("%s:\n", name);
#define p(f, m) if (sctpstat.f || sflag <= 1) \
printf(m, (uintmax_t)sctpstat.f, plural(sctpstat.f))
#define p1a(f, m) if (sctpstat.f || sflag <= 1) \
printf(m, (uintmax_t)sctpstat.f)
/*
* input statistics
*/
p(sctps_recvpackets, "\t%ju input packet%s\n");
p(sctps_recvdatagrams, "\t\t%ju datagram%s\n");
p(sctps_recvpktwithdata, "\t\t%ju packet%s that had data\n");
p(sctps_recvsacks, "\t\t%ju input SACK chunk%s\n");
p(sctps_recvdata, "\t\t%ju input DATA chunk%s\n");
p(sctps_recvdupdata, "\t\t%ju duplicate DATA chunk%s\n");
p(sctps_recvheartbeat, "\t\t%ju input HB chunk%s\n");
p(sctps_recvheartbeatack, "\t\t%ju HB-ACK chunk%s\n");
p(sctps_recvecne, "\t\t%ju input ECNE chunk%s\n");
p(sctps_recvauth, "\t\t%ju input AUTH chunk%s\n");
p(sctps_recvauthmissing, "\t\t%ju chunk%s missing AUTH\n");
p(sctps_recvivalhmacid, "\t\t%ju invalid HMAC id%s received\n");
p(sctps_recvivalkeyid, "\t\t%ju invalid secret id%s received\n");
p1a(sctps_recvauthfailed, "\t\t%ju auth failed\n");
p1a(sctps_recvexpress, "\t\t%ju fast path receives all one chunk\n");
p1a(sctps_recvexpressm, "\t\t%ju fast path multi-part data\n");
/*
* output statistics
*/
p(sctps_sendpackets, "\t%ju output packet%s\n");
p(sctps_sendsacks, "\t\t%ju output SACK%s\n");
p(sctps_senddata, "\t\t%ju output DATA chunk%s\n");
p(sctps_sendretransdata, "\t\t%ju retransmitted DATA chunk%s\n");
p(sctps_sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n");
p(sctps_sendmultfastretrans, "\t\t%ju FR'%s that happened more "
"than once to same chunk\n");
p(sctps_sendheartbeat, "\t\t%ju intput HB chunk%s\n");
p(sctps_sendecne, "\t\t%ju output ECNE chunk%s\n");
p(sctps_sendauth, "\t\t%ju output AUTH chunk%s\n");
p1a(sctps_senderrors, "\t\t%ju ip_output error counter\n");
/*
* PCKDROPREP statistics
*/
printf("\tPacket drop statistics:\n");
p1a(sctps_pdrpfmbox, "\t\t%ju from middle box\n");
p1a(sctps_pdrpfehos, "\t\t%ju from end host\n");
p1a(sctps_pdrpmbda, "\t\t%ju with data\n");
p1a(sctps_pdrpmbct, "\t\t%ju non-data, non-endhost\n");
p1a(sctps_pdrpbwrpt, "\t\t%ju non-endhost, bandwidth rep only\n");
p1a(sctps_pdrpcrupt, "\t\t%ju not enough for chunk header\n");
p1a(sctps_pdrpnedat, "\t\t%ju not enough data to confirm\n");
p1a(sctps_pdrppdbrk, "\t\t%ju where process_chunk_drop said break\n");
p1a(sctps_pdrptsnnf, "\t\t%ju failed to find TSN\n");
p1a(sctps_pdrpdnfnd, "\t\t%ju attempt reverse TSN lookup\n");
p1a(sctps_pdrpdiwnp, "\t\t%ju e-host confirms zero-rwnd\n");
p1a(sctps_pdrpdizrw, "\t\t%ju midbox confirms no space\n");
p1a(sctps_pdrpbadd, "\t\t%ju data did not match TSN\n");
p(sctps_pdrpmark, "\t\t%ju TSN'%s marked for Fast Retran\n");
/*
* Timeouts
*/
printf("\tTimeouts:\n");
p(sctps_timoiterator, "\t\t%ju iterator timer%s fired\n");
p(sctps_timodata, "\t\t%ju T3 data time out%s\n");
p(sctps_timowindowprobe, "\t\t%ju window probe (T3) timer%s fired\n");
p(sctps_timoinit, "\t\t%ju INIT timer%s fired\n");
p(sctps_timosack, "\t\t%ju sack timer%s fired\n");
p(sctps_timoshutdown, "\t\t%ju shutdown timer%s fired\n");
p(sctps_timoheartbeat, "\t\t%ju heartbeat timer%s fired\n");
p1a(sctps_timocookie, "\t\t%ju a cookie timeout fired\n");
p1a(sctps_timosecret, "\t\t%ju an endpoint changed its cookie"
"secret\n");
p(sctps_timopathmtu, "\t\t%ju PMTU timer%s fired\n");
p(sctps_timoshutdownack, "\t\t%ju shutdown ack timer%s fired\n");
p(sctps_timoshutdownguard, "\t\t%ju shutdown guard timer%s fired\n");
p(sctps_timostrmrst, "\t\t%ju stream reset timer%s fired\n");
p(sctps_timoearlyfr, "\t\t%ju early FR timer%s fired\n");
p1a(sctps_timoasconf, "\t\t%ju an asconf timer fired\n");
p1a(sctps_timoautoclose, "\t\t%ju auto close timer fired\n");
p(sctps_timoassockill, "\t\t%ju asoc free timer%s expired\n");
p(sctps_timoinpkill, "\t\t%ju inp free timer%s expired\n");
#if 0
/*
* Early fast retransmission counters
*/
p(sctps_earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n");
p(sctps_earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n");
p(sctps_earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n");
p(sctps_earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n");
p(sctps_earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n");
p(sctps_earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n");
p(sctps_earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n");
p(sctps_earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n");
p(sctps_earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n");
p(sctps_earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n");
p(sctps_earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n");
#endif
/*
* Others
*/
p1a(sctps_hdrops, "\t%ju packet shorter than header\n");
p1a(sctps_badsum, "\t%ju checksum error\n");
p1a(sctps_noport, "\t%ju no endpoint for port\n");
p1a(sctps_badvtag, "\t%ju bad v-tag\n");
p1a(sctps_badsid, "\t%ju bad SID\n");
p1a(sctps_nomem, "\t%ju no memory\n");
p1a(sctps_fastretransinrtt, "\t%ju number of multiple FR in a RTT "
"window\n");
#if 0
p(sctps_markedretrans, "\t%ju TODO:sctps_markedretrans\n");
#endif
p1a(sctps_naglesent, "\t%ju RFC813 allowed sending\n");
p1a(sctps_naglequeued, "\t%ju RFC813 does not allow sending\n");
p1a(sctps_maxburstqueued, "\t%ju times max burst prohibited sending\n");
p1a(sctps_ifnomemqueued, "\t%ju look ahead tells us no memory in "
"interface\n");
p(sctps_windowprobed, "\t%ju number%s of window probes sent\n");
p(sctps_lowlevelerr, "\t%ju time%s an output error to clamp "
"down on next user send\n");
p(sctps_lowlevelerrusr, "\t%ju time%s sctp_senderrors were "
"caused from a user\n");
p(sctps_datadropchklmt, "\t%ju number of in data drop%s due to "
"chunk limit reached\n");
p(sctps_datadroprwnd, "\t%ju number of in data drop%s due to rwnd "
"limit reached\n");
p(sctps_ecnereducedcwnd, "\t%ju time%s a ECN reduced "
"the cwnd\n");
p1a(sctps_vtagexpress, "\t%ju used express lookup via vtag\n");
p1a(sctps_vtagbogus, "\t%ju collision in express lookup\n");
p(sctps_primary_randry, "\t%ju time%s the sender ran dry "
"of user data on primary\n");
p1a(sctps_cmt_randry, "\t%ju same for above\n");
p(sctps_slowpath_sack, "\t%ju sack%s the slow way\n");
p(sctps_wu_sacks_sent, "\t%ju window update only sack%s sent\n");
p(sctps_sends_with_flags, "\t%ju send%s with sinfo_flags !=0\n");
p(sctps_sends_with_unord, "\t%ju unordered send%s\n");
p(sctps_sends_with_eof, "\t%ju send%s with EOF flag set\n");
p(sctps_sends_with_abort, "\t%ju send%s with ABORT flag set\n");
p(sctps_protocol_drain_calls, "\t%ju time%s protocol drain called\n");
p(sctps_protocol_drains_done, "\t%ju time%s we did a protocol "
"drain\n");
p(sctps_read_peeks, "\t%ju time%s recv was called with peek\n");
p(sctps_cached_chk, "\t%ju cached chunk%s used\n");
p1a(sctps_cached_strmoq, "\t%ju cached stream oq's used\n");
p(sctps_left_abandon, "\t%ju unread message%s abandonded by close\n");
p1a(sctps_send_burst_avoid, "\t%ju send burst avoidance, already "
"max burst inflight to net\n");
p1a(sctps_send_cwnd_avoid, "\t%ju send cwnd full avoidance, already "
"max burst inflight to net\n");
p(sctps_fwdtsn_map_over, "\t%ju number of map array over-run%s via "
"fwd-tsn's\n");
#undef p
#undef p1a
}
#endif /* SCTP */

View File

@ -0,0 +1,294 @@
/*-
* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#if 0
#ifndef lint
static char sccsid[] = "@(#)unix.c 8.1 (Berkeley) 6/6/93";
#endif /* not lint */
#endif
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* Display protocol blocks in the unix domain.
*/
#include <sys/param.h>
#include <sys/queue.h>
#ifdef __rtems__
#include <freebsd/sys/protosw.h>
#else
#include <sys/protosw.h>
#endif
#include <sys/socket.h>
#include <sys/socketvar.h>
#ifdef __rtems__
#include <freebsd/sys/mbuf.h>
#else
#include <sys/mbuf.h>
#endif
#include <sys/sysctl.h>
#include <sys/un.h>
#include <sys/unpcb.h>
#include <netinet/in.h>
#include <errno.h>
#include <err.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <kvm.h>
#include "netstat.h"
static void unixdomainpr(struct xunpcb *, struct xsocket *);
static const char *const socktype[] =
{ "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
static int
pcblist_sysctl(int type, char **bufp)
{
char *buf;
size_t len;
char mibvar[sizeof "net.local.seqpacket.pcblist"];
sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
len = 0;
if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
if (errno != ENOENT)
warn("sysctl: %s", mibvar);
return (-1);
}
if ((buf = malloc(len)) == 0) {
warnx("malloc %lu bytes", (u_long)len);
return (-2);
}
if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
warn("sysctl: %s", mibvar);
free(buf);
return (-2);
}
*bufp = buf;
return (0);
}
static int
pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
{
struct unp_head head;
struct unpcb *unp, unp_conn;
u_char sun_len;
struct socket so;
struct xunpgen xug;
struct xunpcb xu;
unp_gen_t unp_gencnt;
u_int unp_count;
char *buf, *p;
size_t len;
if (count_off == 0 || gencnt_off == 0)
return (-2);
if (head_off == 0)
return (-1);
kread(count_off, &unp_count, sizeof(unp_count));
len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
if ((buf = malloc(len)) == 0) {
warnx("malloc %lu bytes", (u_long)len);
return (-2);
}
p = buf;
#define COPYOUT(obj, size) do { \
if (len < (size)) { \
warnx("buffer size exceeded"); \
goto fail; \
} \
bcopy((obj), p, (size)); \
len -= (size); \
p += (size); \
} while (0)
#define KREAD(off, buf, len) do { \
if (kread((uintptr_t)(off), (buf), (len)) != 0) \
goto fail; \
} while (0)
/* Write out header. */
kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
xug.xug_len = sizeof xug;
xug.xug_count = unp_count;
xug.xug_gen = unp_gencnt;
xug.xug_sogen = 0;
COPYOUT(&xug, sizeof xug);
/* Walk the PCB list. */
xu.xu_len = sizeof xu;
KREAD(head_off, &head, sizeof(head));
LIST_FOREACH(unp, &head, unp_link) {
xu.xu_unpp = unp;
KREAD(unp, &xu.xu_unp, sizeof (*unp));
unp = &xu.xu_unp;
if (unp->unp_gencnt > unp_gencnt)
continue;
if (unp->unp_addr != NULL) {
KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
}
if (unp->unp_conn != NULL) {
KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
if (unp_conn.unp_addr != NULL) {
KREAD(unp_conn.unp_addr, &sun_len,
sizeof(sun_len));
KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
}
}
KREAD(unp->unp_socket, &so, sizeof(so));
if (sotoxsocket(&so, &xu.xu_socket) != 0)
goto fail;
COPYOUT(&xu, sizeof(xu));
}
/* Reread the counts and write the footer. */
kread(count_off, &unp_count, sizeof(unp_count));
kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
xug.xug_count = unp_count;
xug.xug_gen = unp_gencnt;
COPYOUT(&xug, sizeof xug);
*bufp = buf;
return (0);
fail:
free(buf);
return (-1);
#undef COPYOUT
#undef KREAD
}
void
unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off)
{
char *buf;
int ret, type;
struct xsocket *so;
struct xunpgen *xug, *oxug;
struct xunpcb *xunp;
for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
if (live)
ret = pcblist_sysctl(type, &buf);
else
ret = pcblist_kvm(count_off, gencnt_off,
type == SOCK_STREAM ? shead_off :
(type == SOCK_DGRAM ? dhead_off : 0), &buf);
if (ret == -1)
continue;
if (ret < 0)
return;
oxug = xug = (struct xunpgen *)buf;
for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
xug->xug_len > sizeof(struct xunpgen);
xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
xunp = (struct xunpcb *)xug;
so = &xunp->xu_socket;
/* Ignore PCBs which were freed during copyout. */
if (xunp->xu_unp.unp_gencnt > oxug->xug_gen)
continue;
unixdomainpr(xunp, so);
}
if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
if (oxug->xug_count > xug->xug_count) {
printf("Some %s sockets may have been deleted.\n",
socktype[type]);
} else if (oxug->xug_count < xug->xug_count) {
printf("Some %s sockets may have been created.\n",
socktype[type]);
} else {
printf("Some %s sockets may have been created or deleted",
socktype[type]);
}
}
free(buf);
}
}
static void
unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
{
struct unpcb *unp;
struct sockaddr_un *sa;
static int first = 1;
char buf1[15];
unp = &xunp->xu_unp;
if (unp->unp_addr)
sa = &xunp->xu_addr;
else
sa = (struct sockaddr_un *)0;
if (first && !Lflag) {
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");
first = 0;
}
if (Lflag && so->so_qlimit == 0)
return;
if (Lflag) {
snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
so->so_incqlen, so->so_qlimit);
printf("unix %-14.14s", buf1);
} else {
printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx",
(long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn,
(long)LIST_FIRST(&unp->unp_refs),
(long)LIST_NEXT(unp, unp_reflink));
}
if (sa)
printf(" %.*s",
(int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
sa->sun_path);
putchar('\n');
}