#ifndef lint
char const copyright[] =
"@(#) Copyright (c) 1983, 1988, 1993\n\
Regents of the University of California. All rights reserved.\n";
#endif
#include <sys/param.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/sys_domain.h>
#include <netinet/in.h>
#include <net/pfkeyv2.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <netdb.h>
#include <nlist.h>
#include <paths.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "netstat.h"
#include <sys/types.h>
#include <sys/sysctl.h>
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
struct protox {
void (*pr_cblocks)(uint32_t, char *, int);
void (*pr_stats)(uint32_t, char *, int);
void (*pr_istats)(char *);
char *pr_name;
int pr_protocol;
} protox[] = {
{ protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP },
{ protopr, udp_stats, NULL, "udp", IPPROTO_UDP },
{ protopr, NULL, NULL, "divert", IPPROTO_DIVERT },
{ protopr, ip_stats, NULL, "ip", IPPROTO_RAW },
{ protopr, icmp_stats, NULL, "icmp", IPPROTO_ICMP },
{ protopr, igmp_stats, NULL, "igmp", IPPROTO_IGMP },
#ifdef IPSEC
{ NULL, ipsec_stats, NULL, "ipsec", IPPROTO_ESP},
#endif
{ NULL, arp_stats, NULL, "arp", 0 },
{ mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP },
{ NULL, NULL, NULL, NULL, 0 }
};
#ifdef INET6
struct protox ip6protox[] = {
{ protopr, tcp_stats, NULL, "tcp", IPPROTO_TCP },
{ protopr, udp_stats, NULL, "udp", IPPROTO_UDP },
{ protopr, ip6_stats, ip6_ifstats, "ip6", IPPROTO_RAW },
{ protopr, icmp6_stats, icmp6_ifstats, "icmp6",IPPROTO_ICMPV6 },
#ifdef IPSEC
{ NULL, ipsec_stats, NULL, "ipsec6", IPPROTO_ESP },
#endif
{ NULL, rip6_stats, NULL, "rip6", IPPROTO_RAW },
{ mptcppr, mptcp_stats, NULL, "mptcp", IPPROTO_TCP },
{ NULL, NULL, NULL, NULL, 0 }
};
#endif
#ifdef IPSEC
struct protox pfkeyprotox[] = {
{ NULL, pfkey_stats, NULL, "pfkey", PF_KEY_V2 },
{ NULL, NULL, NULL, NULL, 0 }
};
#endif
struct protox systmprotox[] = {
{ systmpr, NULL, NULL, "reg", 0 },
{ systmpr, kevt_stats, NULL, "kevt", SYSPROTO_EVENT },
{ systmpr, kctl_stats, NULL, "kctl", SYSPROTO_CONTROL },
{ NULL, NULL, NULL, NULL, 0 }
};
struct protox nstatprotox[] = {
{ NULL, print_nstat_stats, NULL, "nstat", 0 },
{ NULL, NULL, NULL, NULL, 0 }
};
struct protox ipcprotox[] = {
{ NULL, print_extbkidle_stats, NULL, "xbkidle", 0 },
{ NULL, NULL, NULL, NULL, 0 }
};
struct protox kernprotox[] = {
{ NULL, print_net_api_stats, NULL, "net_api", 0 },
{ NULL, NULL, NULL, NULL, 0 }
};
#ifdef AF_VSOCK
struct protox vsockprotox[] = {
{ vsockpr, NULL, NULL, "vsock", 0 },
{ NULL, NULL, NULL, NULL, 0 }
};
#endif
struct protox *protoprotox[] = {
protox,
#ifdef INET6
ip6protox,
#endif
#ifdef IPSEC
pfkeyprotox,
#endif
systmprotox,
nstatprotox,
ipcprotox,
kernprotox,
#ifdef AF_VSOCK
vsockprotox,
#endif
NULL
};
static void printproto (struct protox *, char *);
static void usage (void);
static struct protox *name2protox (char *);
static struct protox *knownname (char *);
#ifdef SRVCACHE
extern void _serv_cache_close();
#endif
int Aflag;
int aflag;
int bflag;
int cflag;
int dflag;
int Fflag;
#if defined(__APPLE__)
int gflag;
#endif
int iflag;
int lflag;
int Lflag;
int mflag;
int nflag;
static int pflag;
int prioflag = -1;
int Rflag;
int rflag;
int sflag;
int Sflag;
int tflag;
int vflag;
int Wflag;
int qflag;
int Qflag;
int xflag;
int zflag;
int cq = -1;
int interval;
char *interface;
int unit;
int af;
int
main(argc, argv)
int argc;
char *argv[];
{
register struct protox *tp = NULL;
int ch;
af = AF_UNSPEC;
while ((ch = getopt(argc, argv, "Aabc:dFf:gI:ikLlmnP:p:qQrRsStuvWw:xz")) != -1)
switch(ch) {
case 'A':
Aflag = 1;
break;
case 'a':
aflag = 1;
break;
case 'b':
bflag = 1;
break;
case 'c':
cflag = 1;
cq = atoi(optarg);
break;
case 'd':
dflag = 1;
break;
case 'F':
Fflag = 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 INET6
else if (strcmp(optarg, "pfkey") == 0)
af = PF_KEY;
#endif
else if (strcmp(optarg, "unix") == 0)
af = AF_UNIX;
else if (strcmp(optarg, "systm") == 0)
af = AF_SYSTEM;
else {
errx(1, "%s: unknown address family", optarg);
}
break;
#if defined(__APPLE__)
case 'g':
gflag = 1;
break;
#endif
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 'L':
Lflag = 1;
break;
case 'm':
mflag++;
break;
case 'n':
nflag = 1;
break;
case 'P':
prioflag = atoi(optarg);
break;
case 'p':
if ((tp = name2protox(optarg)) == NULL) {
errx(1,
"%s: unknown or uninstrumented protocol",
optarg);
}
pflag = 1;
break;
case 'q':
qflag++;
break;
case 'Q':
Qflag++;
break;
case 'R':
Rflag = 1;
break;
case 'r':
rflag = 1;
break;
case 's':
++sflag;
break;
case 'S':
Sflag = 1;
break;
case 't':
tflag = 1;
break;
case 'u':
af = AF_UNIX;
break;
case 'v':
vflag++;
break;
case 'W':
Wflag = 1;
break;
case 'w':
interval = atoi(optarg);
iflag = 1;
break;
case 'x':
xflag = 1;
Rflag = 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;
}
}
#endif
if (mflag) {
mbpr();
exit(0);
}
if (iflag && !sflag && !Sflag && !gflag && !qflag && !Qflag) {
if (Rflag)
intpr_ri(NULL);
else
intpr(NULL);
exit(0);
}
if (rflag) {
if (sflag)
rt_stats();
else
routepr();
exit(0);
}
if (qflag || Qflag) {
if (interface == NULL) {
fprintf(stderr, "%s statistics option "
"requires interface name\n", qflag ? "Queue" :
"Polling");
} else if (qflag) {
aqstatpr();
} else {
rxpollstatpr();
}
exit(0);
}
if (Sflag) {
if (interface == NULL) {
fprintf(stderr, "additional link status option"
" requires interface name\n");
} else {
print_link_status(interface);
}
exit(0);
}
#if defined(__APPLE__)
if (gflag) {
ifmalist_dump();
exit(0);
}
#endif
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
#ifdef IPSEC
if (af == PF_KEY || af == AF_UNSPEC)
for (tp = pfkeyprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif
if ((af == AF_UNIX || af == AF_UNSPEC) && !Lflag && !sflag)
unixpr();
if ((af == AF_SYSTEM || af == AF_UNSPEC) && !Lflag)
for (tp = systmprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#if TARGET_OS_IPHONE
if (af == AF_UNSPEC && !Lflag)
for (tp = nstatprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif
if (af == AF_UNSPEC && !Lflag)
for (tp = ipcprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
if (af == AF_UNSPEC && !Lflag)
for (tp = kernprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#ifdef AF_VSOCK
if (af == AF_VSOCK || af == AF_UNSPEC)
for (tp = vsockprotox; tp->pr_name; tp++)
printproto(tp, tp->pr_name);
#endif
#ifdef SRVCACHE
_serv_cache_close();
#endif
exit(0);
}
static void
printproto(tp, name)
register struct protox *tp;
char *name;
{
void (*pr)(uint32_t, char *, int);
uint32_t off;
if (sflag) {
if (iflag && !pflag) {
if (tp->pr_istats)
intpr(tp->pr_istats);
else if (vflag)
printf("%s: no per-interface stats routine\n",
tp->pr_name);
return;
}
else {
pr = tp->pr_stats;
if (!pr) {
if (pflag && vflag)
printf("%s: no stats routine\n",
tp->pr_name);
return;
}
off = tp->pr_protocol;
}
} else {
pr = tp->pr_cblocks;
if (!pr) {
if (pflag && vflag)
printf("%s: no PCB routine\n", tp->pr_name);
return;
}
off = tp->pr_protocol;
}
if (pr != NULL) {
if (sflag && iflag && pflag)
intervalpr(pr, off, name, af);
else
(*pr)(off, name, af);
} else {
printf("### no stats for %s\n", name);
}
}
char *
plural(int n)
{
return (n > 1 ? "s" : "");
}
char *
plurales(int n)
{
return (n > 1 ? "es" : "");
}
char *
pluralies(int n)
{
return (n > 1 ? "ies" : "y");
}
static struct protox *
knownname(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);
}
static struct protox *
name2protox(char *name)
{
struct protox *tp;
char **alias;
struct protoent *p;
if ((tp = knownname(name)) != NULL)
return (tp);
setprotoent(1);
while ((p = getprotoent()) != NULL) {
for (alias = p->p_aliases; *alias; alias++)
if (strcmp(name, *alias) == 0) {
endprotoent();
return (knownname(p->p_name));
}
}
endprotoent();
return (NULL);
}
#define NETSTAT_USAGE "\
Usage: netstat [-AaLlnW] [-f address_family | -p protocol]\n\
netstat [-gilns] [-f address_family]\n\
netstat -i | -I interface [-w wait] [-abdgRtS]\n\
netstat -s [-s] [-f address_family | -p protocol] [-w wait]\n\
netstat -i | -I interface -s [-f address_family | -p protocol]\n\
netstat -m [-m]\n\
netstat -r [-Aaln] [-f address_family]\n\
netstat -rs [-s]\n\
"
static void
usage(void)
{
(void) fprintf(stderr, "%s\n", NETSTAT_USAGE);
exit(1);
}
int
print_time(void)
{
time_t now;
struct tm tm;
int num_written = 0;
(void) time(&now);
(void) localtime_r(&now, &tm);
num_written += printf("%02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec);
return (num_written);
}