version 1.105, 2015/02/09 12:25:03 |
version 1.106, 2015/02/12 01:49:02 |
|
|
#include "netstat.h" |
#include "netstat.h" |
|
|
struct nlist nl[] = { |
struct nlist nl[] = { |
#define N_TCBTABLE 0 |
#define N_RTREE 0 |
{ "_tcbtable" }, |
|
#define N_UDBTABLE 1 |
|
{ "_udbtable" }, |
|
|
|
#define N_RTREE 7 |
|
{ "_rt_tables"}, |
{ "_rt_tables"}, |
#define N_RTMASK 8 |
#define N_RTMASK 1 |
{ "_mask_rnhead" }, |
{ "_mask_rnhead" }, |
#define N_AF2RTAFIDX 9 |
#define N_AF2RTAFIDX 2 |
{ "_af2rtafidx" }, |
{ "_af2rtafidx" }, |
#define N_RTBLIDMAX 10 |
#define N_RTBLIDMAX 3 |
{ "_rtbl_id_max" }, |
{ "_rtbl_id_max" }, |
|
|
#define N_RAWIPTABLE 11 |
|
{ "_rawcbtable" }, |
|
#define N_RAWIP6TABLE 12 |
|
{ "_rawin6pcbtable" }, |
|
#define N_DIVBTABLE 13 |
|
{ "_divbtable" }, |
|
#define N_DIVB6TABLE 14 |
|
{ "_divb6table" }, |
|
|
|
{ "" } |
{ "" } |
}; |
}; |
|
|
struct protox { |
struct protox { |
u_char pr_index; /* index into nlist of cb head */ |
|
void (*pr_cblocks)(u_long, char *, int, u_int, u_long); |
|
/* control blocks printing routine */ |
|
void (*pr_stats)(char *); /* statistics printing routine */ |
void (*pr_stats)(char *); /* statistics printing routine */ |
char *pr_name; /* well-known name */ |
char *pr_name; /* well-known name */ |
|
int pr_proto; /* protocol number */ |
} protox[] = { |
} protox[] = { |
{ N_TCBTABLE, protopr, tcp_stats, "tcp" }, |
{ ip_stats, "ip", IPPROTO_IPV4 }, |
{ N_UDBTABLE, protopr, udp_stats, "udp" }, |
{ icmp_stats, "icmp", 0 }, |
{ N_RAWIPTABLE, protopr, ip_stats, "ip" }, |
{ igmp_stats, "igmp", 0 }, |
{ N_DIVBTABLE, protopr, div_stats, "divert" }, |
{ ipip_stats, "ipencap", 0 }, |
{ -1, NULL, icmp_stats, "icmp" }, |
{ tcp_stats, "tcp", IPPROTO_TCP }, |
{ -1, NULL, igmp_stats, "igmp" }, |
{ udp_stats, "udp", IPPROTO_UDP }, |
{ -1, NULL, ah_stats, "ah" }, |
{ esp_stats, "esp", 0 }, |
{ -1, NULL, esp_stats, "esp" }, |
{ ah_stats, "ah", 0 }, |
{ -1, NULL, ipip_stats, "ipencap" }, |
{ etherip_stats,"etherip", 0 }, |
{ -1, NULL, etherip_stats, "etherip" }, |
{ ipcomp_stats, "ipcomp", 0 }, |
{ -1, NULL, ipcomp_stats, "ipcomp" }, |
{ carp_stats, "carp", 0 }, |
{ -1, NULL, carp_stats, "carp" }, |
{ pfsync_stats, "pfsync", 0 }, |
{ -1, NULL, pfsync_stats, "pfsync" }, |
{ div_stats, "divert", IPPROTO_DIVERT }, |
{ -1, NULL, pim_stats, "pim" }, |
{ pim_stats, "pim", 0 }, |
{ -1, NULL, pflow_stats, "pflow" }, |
{ pflow_stats, "pflow", 0 }, |
{ -1, NULL, NULL, NULL } |
{ NULL, NULL, 0 } |
}; |
}; |
|
|
struct protox ip6protox[] = { |
struct protox ip6protox[] = { |
{ N_TCBTABLE, protopr, NULL, "tcp" }, |
{ ip6_stats, "ip6", IPPROTO_IPV6 }, |
{ N_UDBTABLE, protopr, NULL, "udp" }, |
{ div6_stats, "divert6", IPPROTO_DIVERT }, |
{ N_RAWIP6TABLE,protopr, ip6_stats, "ip6" }, |
{ icmp6_stats, "icmp6", 0 }, |
{ N_DIVB6TABLE, protopr, div6_stats, "divert6" }, |
{ pim6_stats, "pim6", 0 }, |
{ -1, NULL, icmp6_stats, "icmp6" }, |
{ rip6_stats, "rip6", 0 }, |
{ -1, NULL, pim6_stats, "pim6" }, |
{ NULL, NULL, 0 } |
{ -1, NULL, rip6_stats, "rip6" }, |
|
{ -1, NULL, NULL, NULL } |
|
}; |
}; |
|
|
struct protox *protoprotox[] = { |
struct protox *protoprotox[] = { |
protox, ip6protox, NULL |
protox, ip6protox, NULL |
}; |
}; |
|
|
static void printproto(struct protox *, char *, int, u_int, u_long); |
|
static void usage(void); |
static void usage(void); |
static struct protox *name2protox(char *); |
static struct protox *name2protox(char *); |
static struct protox *knownname(char *); |
static struct protox *knownname(char *); |
u_int gettable(const char *); |
u_int gettable(const char *); |
|
|
int hideroot; |
|
|
|
kvm_t *kvmd; |
kvm_t *kvmd; |
|
|
int |
int |
|
|
extern char *optarg; |
extern char *optarg; |
extern int optind; |
extern int optind; |
const char *errstr; |
const char *errstr; |
struct protoent *p; |
|
struct protox *tp = NULL; /* for printing cblocks & stats */ |
struct protox *tp = NULL; /* for printing cblocks & stats */ |
int ch; |
int ch; |
char *nlistf = NULL, *memf = NULL, *ep; |
char *nlistf = NULL, *memf = NULL, *ep; |
char buf[_POSIX2_LINE_MAX]; |
char buf[_POSIX2_LINE_MAX]; |
gid_t gid; |
|
u_long pcbaddr = 0; |
u_long pcbaddr = 0; |
u_int tableid; |
u_int tableid; |
int Tflag = 0; |
int Tflag = 0; |
int repeatcount = 0; |
int repeatcount = 0; |
|
int proto = 0; |
int need_nlist; |
int need_nlist; |
|
|
hideroot = getuid(); |
|
|
|
af = AF_UNSPEC; |
af = AF_UNSPEC; |
tableid = getrtable(); |
tableid = getrtable(); |
|
|
|
|
af = AF_UNIX; |
af = AF_UNIX; |
else if (strcmp(optarg, "mpls") == 0) |
else if (strcmp(optarg, "mpls") == 0) |
af = AF_MPLS; |
af = AF_MPLS; |
else if (strcmp(optarg, "pflow") == 0) |
|
af = PF_PFLOW; |
|
else if (strcmp(optarg, "mask") == 0) |
else if (strcmp(optarg, "mask") == 0) |
af = 0xff; |
af = 0xff; |
else { |
else { |
|
|
argv += optind; |
argv += optind; |
argc -= optind; |
argc -= optind; |
|
|
/* |
|
* Show per-interface statistics which don't need access to |
|
* kernel memory (they're using IOCTLs) |
|
*/ |
|
if (Wflag) { |
|
if (interface == NULL) |
|
usage(); |
|
net80211_ifstats(interface); |
|
exit(0); |
|
} |
|
|
|
#define BACKWARD_COMPATIBILITY |
#define BACKWARD_COMPATIBILITY |
#ifdef BACKWARD_COMPATIBILITY |
#ifdef BACKWARD_COMPATIBILITY |
if (*argv) { |
if (*argv) { |
|
|
} |
} |
#endif |
#endif |
|
|
need_nlist = !mflag && (pflag || nlistf != NULL || memf != NULL || |
|
(!iflag && !sflag && !gflag && (rflag ? Aflag : |
|
(af != AF_UNIX || Pflag)))); |
|
|
|
/* |
/* |
* Discard setgid privileges if not the running kernel so that bad |
* Show per-interface statistics which don't need access to |
* guys can't print interesting stuff from kernel memory. |
* kernel memory (they're using IOCTLs) |
* Dumping PCB info is also restricted. |
|
*/ |
*/ |
gid = getgid(); |
if (Wflag) { |
if (nlistf != NULL || memf != NULL || Pflag) |
if (interface == NULL) |
if (setresgid(gid, gid, gid) == -1) |
usage(); |
err(1, "setresgid"); |
net80211_ifstats(interface); |
|
exit(0); |
if ((kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY | |
|
(need_nlist ? 0 : KVM_NO_FILES), buf)) == NULL) { |
|
fprintf(stderr, "%s: kvm_openfiles: %s\n", __progname, buf); |
|
exit(1); |
|
} |
} |
|
|
if (nlistf == NULL && memf == NULL && !Pflag) |
|
if (setresgid(gid, gid, gid) == -1) |
|
err(1, "setresgid"); |
|
|
|
if (need_nlist && (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0)) { |
|
if (nlistf) |
|
fprintf(stderr, "%s: %s: no namelist\n", __progname, |
|
nlistf); |
|
else |
|
fprintf(stderr, "%s: no namelist\n", __progname); |
|
exit(1); |
|
} |
|
if (mflag) { |
if (mflag) { |
mbpr(); |
mbpr(); |
exit(0); |
exit(0); |
} |
} |
if (pflag) { |
|
printproto(tp, tp->pr_name, af, tableid, pcbaddr); |
|
exit(0); |
|
} |
|
if (iflag) { |
if (iflag) { |
intpr(interval, repeatcount); |
intpr(interval, repeatcount); |
exit(0); |
exit(0); |
} |
} |
if (rflag) { |
if (sflag) { |
if (sflag) |
if (rflag) { |
rt_stats(); |
rt_stats(); |
else if (Aflag || nlistf != NULL || memf != NULL) |
} else if (gflag) { |
routepr(nl[N_RTREE].n_value, nl[N_RTMASK].n_value, |
|
nl[N_AF2RTAFIDX].n_value, nl[N_RTBLIDMAX].n_value, |
|
tableid); |
|
else |
|
p_rttables(af, tableid); |
|
exit(0); |
|
} |
|
if (gflag) { |
|
if (sflag) { |
|
if (af == AF_INET || af == AF_UNSPEC) |
if (af == AF_INET || af == AF_UNSPEC) |
mrt_stats(); |
mrt_stats(); |
if (af == AF_INET6 || af == AF_UNSPEC) |
if (af == AF_INET6 || af == AF_UNSPEC) |
mrt6_stats(); |
mrt6_stats(); |
|
} else if (pflag && tp->pr_name) { |
|
(*tp->pr_stats)(tp->pr_name); |
} else { |
} else { |
if (af == AF_INET || af == AF_UNSPEC) |
if (af == AF_INET || af == AF_UNSPEC) |
mroutepr(); |
for (tp = protox; tp->pr_name; tp++) |
|
(*tp->pr_stats)(tp->pr_name); |
if (af == AF_INET6 || af == AF_UNSPEC) |
if (af == AF_INET6 || af == AF_UNSPEC) |
mroute6pr(); |
for (tp = ip6protox; tp->pr_name; tp++) |
|
(*tp->pr_stats)(tp->pr_name); |
} |
} |
exit(0); |
exit(0); |
} |
} |
if (af == AF_INET || af == AF_UNSPEC) { |
if (gflag) { |
setprotoent(1); |
if (af == AF_INET || af == AF_UNSPEC) |
setservent(1); |
mroutepr(); |
/* ugh, this is O(MN) ... why do we do this? */ |
if (af == AF_INET6 || af == AF_UNSPEC) |
while ((p = getprotoent())) { |
mroute6pr(); |
for (tp = protox; tp->pr_name; tp++) |
exit(0); |
if (strcmp(tp->pr_name, p->p_name) == 0) |
|
break; |
|
if (tp->pr_name == 0) |
|
continue; |
|
printproto(tp, p->p_name, AF_INET, tableid, pcbaddr); |
|
} |
|
endprotoent(); |
|
} |
} |
if (af == PF_PFLOW || af == AF_UNSPEC) { |
|
tp = name2protox("pflow"); |
/* |
printproto(tp, tp->pr_name, af, tableid, pcbaddr); |
* The remaining code may need kvm so lets try to open it. |
|
* -r and -P are the only bits left that actually can use this. |
|
*/ |
|
need_nlist = nlistf != NULL || memf != NULL || Pflag || (Aflag && rflag); |
|
|
|
if ((kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY | |
|
(need_nlist ? 0 : KVM_NO_FILES), buf)) == NULL) |
|
errx(1, "kvm_openfiles: %s", buf); |
|
|
|
if (need_nlist && (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0)) { |
|
if (nlistf) |
|
errx(1, "%s: no namelist", nlistf); |
|
else |
|
errx(1, "no namelist"); |
} |
} |
if (af == AF_INET6 || af == AF_UNSPEC) |
|
for (tp = ip6protox; tp->pr_name; tp++) |
|
printproto(tp, tp->pr_name, AF_INET6, tableid, |
|
pcbaddr); |
|
if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag) |
|
unixpr(kvmd, pcbaddr); |
|
exit(0); |
|
} |
|
|
|
/* |
if (rflag) { |
* Print out protocol statistics or control blocks (per sflag). |
if (Aflag || nlistf != NULL || memf != NULL) |
* If the interface was not specifically requested, and the symbol |
routepr(nl[N_RTREE].n_value, nl[N_RTMASK].n_value, |
* is not in the namelist, ignore this one. |
nl[N_AF2RTAFIDX].n_value, nl[N_RTBLIDMAX].n_value, |
*/ |
tableid); |
static void |
else |
printproto(struct protox *tp, char *name, int af, u_int tableid, |
p_rttables(af, tableid); |
u_long pcbaddr) |
exit(0); |
{ |
|
if (sflag) { |
|
if (tp->pr_stats != NULL) |
|
(*tp->pr_stats)(name); |
|
} else { |
|
u_char i = tp->pr_index; |
|
if (tp->pr_cblocks != NULL && |
|
i < sizeof(nl) / sizeof(nl[0]) && |
|
(nl[i].n_value || af != AF_UNSPEC)) |
|
(*tp->pr_cblocks)(nl[i].n_value, name, af, tableid, |
|
pcbaddr); |
|
} |
} |
|
|
|
if (pflag) { |
|
if (tp->pr_proto == 0) |
|
errx(1, "no protocol handler for protocol %s", |
|
tp->pr_name); |
|
else |
|
proto = tp->pr_proto; |
|
} |
|
|
|
protopr(kvmd, pcbaddr, tableid, proto); |
|
exit(0); |
} |
} |
|
|
/* |
/* |