diff options
author | glebius <glebius@FreeBSD.org> | 2013-04-10 20:29:23 +0000 |
---|---|---|
committer | glebius <glebius@FreeBSD.org> | 2013-04-10 20:29:23 +0000 |
commit | 21122c283428cb5befbc9946b8191cc085c8d996 (patch) | |
tree | 60c79ab7327265f2bed643c9aafe36baf2ee239d /usr.bin/netstat | |
parent | 147dda2e5e80203cec822fed13a97e3e1531cbaf (diff) | |
download | FreeBSD-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.c | 18 | ||||
-rw-r--r-- | usr.bin/netstat/main.c | 79 | ||||
-rw-r--r-- | usr.bin/netstat/netstat.h | 1 |
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); |