summaryrefslogtreecommitdiffstats
path: root/usr.bin/netstat
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2013-04-10 20:29:23 +0000
committerglebius <glebius@FreeBSD.org>2013-04-10 20:29:23 +0000
commit21122c283428cb5befbc9946b8191cc085c8d996 (patch)
tree60c79ab7327265f2bed643c9aafe36baf2ee239d /usr.bin/netstat
parent147dda2e5e80203cec822fed13a97e3e1531cbaf (diff)
downloadFreeBSD-src-21122c283428cb5befbc9946b8191cc085c8d996.zip
FreeBSD-src-21122c283428cb5befbc9946b8191cc085c8d996.tar.gz
Use kvm_counter_u64_fetch() to fix obtaining ipstat and tcpstat from
kernel core files. Sponsored by: Nginx, Inc.
Diffstat (limited to 'usr.bin/netstat')
-rw-r--r--usr.bin/netstat/inet.c18
-rw-r--r--usr.bin/netstat/main.c79
-rw-r--r--usr.bin/netstat/netstat.h1
3 files changed, 69 insertions, 29 deletions
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 4d52eb7..a04cc9a 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -603,8 +603,13 @@ tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
warn("sysctl: net.inet.tcp.stats");
return;
}
- } else
- kread(off, &tcpstat, len);
+ } else {
+ u_long tcpstat_p[sizeof(struct tcpstat)/sizeof(uint64_t)];
+
+ kread(off, &tcpstat_p, sizeof(tcpstat_p));
+ kread_counters(tcpstat_p, (uint64_t *)&tcpstat,
+ sizeof(struct tcpstat)/sizeof(uint64_t));
+ }
printf ("%s:\n", name);
@@ -858,8 +863,13 @@ ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
warn("sysctl: net.inet.ip.stats");
return;
}
- } else
- kread(off, &ipstat, len);
+ } else {
+ u_long ipstat_p[sizeof(struct ipstat)/sizeof(uint64_t)];
+
+ kread(off, &ipstat_p, sizeof(ipstat_p));
+ kread_counters(ipstat_p, (uint64_t *)&ipstat,
+ sizeof(struct ipstat)/sizeof(uint64_t));
+ }
printf("%s:\n", name);
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 2a996ae..ce4ff95 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -147,11 +147,11 @@ static struct nlist nl[] = {
#define N_IPCOMPSTAT 37
{ .n_name = "_ipcompstat" },
#define N_TCPSTAT 38
- { .n_name = "_tcpstat" },
+ { .n_name = "_tcpstatp" },
#define N_UDPSTAT 39
{ .n_name = "_udpstat" },
#define N_IPSTAT 40
- { .n_name = "_ipstat" },
+ { .n_name = "_ipstatp" },
#define N_ICMPSTAT 41
{ .n_name = "_icmpstat" },
#define N_IGMPSTAT 42
@@ -696,37 +696,50 @@ printproto(struct protox *tp, const char *name)
(*pr)(off, name, af, tp->pr_protocol);
}
+static int
+kvmd_init(void)
+{
+ char errbuf[_POSIX2_LINE_MAX];
+
+ if (kvmd != NULL)
+ return (0);
+
+ kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ setgid(getgid());
+
+ if (kvmd == NULL) {
+ warnx("kvm not available: %s", errbuf);
+ return (-1);
+ }
+
+ 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");
+ }
+
+ return (0);
+}
+
/*
* 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 (kvmd_init() < 0)
+ return (-1);
- 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) {
@@ -736,6 +749,22 @@ kread(u_long addr, void *buf, size_t size)
return (0);
}
+/*
+ * Read an array of N counters in kernel memory into array of N uint64_t's.
+ */
+int
+kread_counters(u_long *addr, uint64_t *rval, size_t count)
+{
+
+ if (kvmd_init() < 0)
+ return (-1);
+
+ for (u_int i = 0; i < count; i++, addr++, rval++)
+ *rval = kvm_counter_u64_fetch(kvmd, *addr);
+
+ return (0);
+}
+
const char *
plural(uintmax_t n)
{
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index 9b545d8..32bea79 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -60,6 +60,7 @@ 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);
+int kread_counters(u_long *addr, uint64_t *rval, size_t count);
const char *plural(uintmax_t);
const char *plurales(uintmax_t);
const char *pluralies(uintmax_t);
OpenPOWER on IntegriCloud