Author: glebius
Date: Wed Apr 10 20:29:23 2013
New Revision: 249345
URL: http://svnweb.freebsd.org/changeset/base/249345

Log:
  Use kvm_counter_u64_fetch() to fix obtaining ipstat and tcpstat from
  kernel core files.
  
  Sponsored by: Nginx, Inc.

Modified:
  head/usr.bin/netstat/inet.c
  head/usr.bin/netstat/main.c
  head/usr.bin/netstat/netstat.h

Modified: head/usr.bin/netstat/inet.c
==============================================================================
--- head/usr.bin/netstat/inet.c Wed Apr 10 20:26:53 2013        (r249344)
+++ head/usr.bin/netstat/inet.c Wed Apr 10 20:29:23 2013        (r249345)
@@ -603,8 +603,13 @@ tcp_stats(u_long off, const char *name, 
                        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, i
                        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);
 

Modified: head/usr.bin/netstat/main.c
==============================================================================
--- head/usr.bin/netstat/main.c Wed Apr 10 20:26:53 2013        (r249344)
+++ head/usr.bin/netstat/main.c Wed Apr 10 20:29:23 2013        (r249345)
@@ -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
                (*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 siz
        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)
 {

Modified: head/usr.bin/netstat/netstat.h
==============================================================================
--- head/usr.bin/netstat/netstat.h      Wed Apr 10 20:26:53 2013        
(r249344)
+++ head/usr.bin/netstat/netstat.h      Wed Apr 10 20:29:23 2013        
(r249345)
@@ -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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to