From nobody@FreeBSD.org  Sat Mar 17 06:51:58 2007
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id 32D1416A403
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 17 Mar 2007 06:51:58 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id 22D1913C465
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 17 Mar 2007 06:51:58 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.13.1/8.13.1) with ESMTP id l2H6pvrW053834
	for <freebsd-gnats-submit@FreeBSD.org>; Sat, 17 Mar 2007 06:51:58 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.13.1/8.13.1/Submit) id l2H6pvHA053831;
	Sat, 17 Mar 2007 06:51:57 GMT
	(envelope-from nobody)
Message-Id: <200703170651.l2H6pvHA053831@www.freebsd.org>
Date: Sat, 17 Mar 2007 06:51:57 GMT
From: Bruce Becker<hostmaster@whois.gts.net>
To: freebsd-gnats-submit@FreeBSD.org
Subject: rpc.rstatd returns bad info
X-Send-Pr-Version: www-3.0

>Number:         110426
>Category:       misc
>Synopsis:       [patch] rpc.rstatd(8) returns bad info
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Mar 17 07:00:11 GMT 2007
>Closed-Date:    Sun Mar 18 16:02:56 GMT 2007
>Last-Modified:  Sun Mar 18 16:02:56 GMT 2007
>Originator:     Bruce Becker
>Release:        4.11
>Organization:
G.T.S.
>Environment:
FreeBSD infra-gw 4.11-STABLE FreeBSD 4.11-STABLE #3: Wed Feb  7 16:21:26 EST 2007     root@infra-gw:/usr/obj/usr/src/sys/FW-YQ  i386

>Description:
4.x & 3.x seem to have issues with opackets systcl mib (always returns 0)

this fix uses the kmem interface as well as fixes some code botches

>How-To-Repeat:
view using SunOS/Solaris perfmeter or sysutils/xsysstats port
>Fix:
Patch included

Patch attached with submission follows:

--- rstat_proc.c~	Fri Apr  2 01:56:09 2004
+++ rstat_proc.c	Sat Jan 28 22:24:19 2006
@@ -63,7 +63,7 @@
 #include <devstat.h>
 
 #include <net/if.h>
-#include <net/if_mib.h>
+#include <net/if_var.h>
 
 #undef FSHIFT			 /* Use protocol's shift and scale values */
 #undef FSCALE
@@ -79,6 +79,8 @@
 	{ "_cp_time" },
 #define	X_CNT		1
 	{ "_cnt" },
+#define	X_IFNET		2
+	{ "_ifnet" },
 	{ "" },
 };
 
@@ -87,6 +89,8 @@
 void setup __P((void));
 int stats_service();
 
+int firstifnet, numintfs;
+
 extern int from_inetd;
 int sincelastreq = 0;		/* number of alarms since last request */
 extern int closedown;
@@ -140,6 +144,7 @@
     if (! stat_is_init)
         stat_init();
     sincelastreq = 0;
+    stats_all.s2.if_opackets = stats_all.s3.if_opackets;
     return(&stats_all.s2);
 }
 
@@ -151,6 +156,7 @@
     if (! stat_is_init)
         stat_init();
     sincelastreq = 0;
+    stats_all.s1.if_opackets = stats_all.s3.if_opackets;
     return(&stats_all.s1);
 }
 
@@ -187,10 +193,11 @@
 void
 updatestat()
 {
+	long off;
 	int i, hz;
 	struct clockinfo clockrate;
 	struct vmmeter cnt;
-	struct ifmibdata ifmd;
+	struct ifnet ifnet;
 	double avrun[3];
 	struct timeval tm, btm;
 	int mib[6];
@@ -229,13 +236,13 @@
 		exit(1);
 	}
 	for(i = 0; i < RSTAT_CPUSTATES ; i++)
-		stats_all.s1.cp_time[i] = bsd_cp_time[cp_time_xlat[i]];
+		stats_all.s3.cp_time[i] = bsd_cp_time[cp_time_xlat[i]];
 
         (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0]));
 
-	stats_all.s2.avenrun[0] = avrun[0] * FSCALE;
-	stats_all.s2.avenrun[1] = avrun[1] * FSCALE;
-	stats_all.s2.avenrun[2] = avrun[2] * FSCALE;
+	stats_all.s3.avenrun[0] = avrun[0] * FSCALE;
+	stats_all.s3.avenrun[1] = avrun[1] * FSCALE;
+	stats_all.s3.avenrun[2] = avrun[2] * FSCALE;
 
 	mib[0] = CTL_KERN;
 	mib[1] = KERN_BOOTTIME;
@@ -245,13 +252,13 @@
 		exit(1);
 	}
 
-	stats_all.s2.boottime.tv_sec = btm.tv_sec;
-	stats_all.s2.boottime.tv_usec = btm.tv_usec;
+	stats_all.s3.boottime.tv_sec = btm.tv_sec;
+	stats_all.s3.boottime.tv_usec = btm.tv_usec;
 
 
 #ifdef DEBUG
-	fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0],
-	    stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]);
+	fprintf(stderr, "%d %d %d %d\n", stats_all.s3.cp_time[0],
+	    stats_all.s3.cp_time[1], stats_all.s3.cp_time[2], stats_all.s3.cp_time[3]);
 #endif
 
 	/* XXX - should use sysctl */
@@ -259,54 +266,40 @@
 		syslog(LOG_ERR, "rstat: can't read cnt from kmem");
 		exit(1);
 	}
-	stats_all.s1.v_pgpgin = cnt.v_vnodepgsin;
-	stats_all.s1.v_pgpgout = cnt.v_vnodepgsout;
-	stats_all.s1.v_pswpin = cnt.v_swappgsin;
-	stats_all.s1.v_pswpout = cnt.v_swappgsout;
-	stats_all.s1.v_intr = cnt.v_intr;
+	stats_all.s3.v_pgpgin = cnt.v_vnodepgsin;
+	stats_all.s3.v_pgpgout = cnt.v_vnodepgsout;
+	stats_all.s3.v_pswpin = cnt.v_swappgsin;
+	stats_all.s3.v_pswpout = cnt.v_swappgsout;
+	stats_all.s3.v_intr = cnt.v_intr;
 	gettimeofday(&tm, (struct timezone *) 0);
-	stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
+	stats_all.s3.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
 	    hz*(tm.tv_usec - btm.tv_usec)/1000000;
-	stats_all.s2.v_swtch = cnt.v_swtch;
+	stats_all.s3.v_swtch = cnt.v_swtch;
 
 	/* update disk transfers */
-	updatexfers(RSTAT_DK_NDRIVE, stats_all.s1.dk_xfer);
+	updatexfers(RSTAT_DK_NDRIVE, stats_all.s3.dk_xfer);
 
-	mib[0] = CTL_NET;
-	mib[1] = PF_LINK;
-	mib[2] = NETLINK_GENERIC;
-	mib[3] = IFMIB_SYSTEM;
-	mib[4] = IFMIB_IFCOUNT;
-	len = sizeof ifcount;
-	if (sysctl(mib, 5, &ifcount, &len, 0, 0) < 0) {
-		syslog(LOG_ERR, "sysctl(net.link.generic.system.ifcount): %m");
-		exit(1);
-	}
-
-	stats_all.s1.if_ipackets = 0;
-	stats_all.s1.if_opackets = 0;
-	stats_all.s1.if_ierrors = 0;
-	stats_all.s1.if_oerrors = 0;
-	stats_all.s1.if_collisions = 0;
-	for (i = 1; i <= ifcount; i++) {
-		len = sizeof ifmd;
-		mib[3] = IFMIB_IFDATA;
-		mib[4] = i;
-		mib[5] = IFDATA_GENERAL;
-		if (sysctl(mib, 6, &ifmd, &len, 0, 0) < 0) {
-			syslog(LOG_ERR, "sysctl(net.link.ifdata.%d.general)"
-			       ": %m", i);
-			exit(1);
+	stats_all.s3.if_ipackets = 0;
+	stats_all.s3.if_opackets = 0;
+	stats_all.s3.if_ierrors = 0;
+	stats_all.s3.if_oerrors = 0;
+	stats_all.s3.if_collisions = 0;
+	for (off = firstifnet, i = 0; off && i < numintfs; i++) {
+		if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
+			syslog(LOG_ERR, "can't read ifnet from kmem");
+			exit(1);
+		}
+		stats_all.s3.if_ipackets += ifnet.if_data.ifi_ipackets;
+		stats_all.s3.if_opackets += ifnet.if_data.ifi_opackets;
+		stats_all.s3.if_ierrors += ifnet.if_data.ifi_ierrors;
+		stats_all.s3.if_oerrors += ifnet.if_data.ifi_oerrors;
+		stats_all.s3.if_collisions += ifnet.if_data.ifi_collisions;
+		off = (long)ifnet.if_list.tqe_next;
 		}
 
-		stats_all.s1.if_ipackets += ifmd.ifmd_data.ifi_ipackets;
-		stats_all.s1.if_opackets += ifmd.ifmd_data.ifi_opackets;
-		stats_all.s1.if_ierrors += ifmd.ifmd_data.ifi_ierrors;
-		stats_all.s1.if_oerrors += ifmd.ifmd_data.ifi_oerrors;
-		stats_all.s1.if_collisions += ifmd.ifmd_data.ifi_collisions;
-	}
-	gettimeofday((struct timeval *)&stats_all.s3.curtime,
-		(struct timezone *) 0);
+	gettimeofday(&tm, (struct timezone *) 0);
+	stats_all.s3.curtime.tv_sec = tm.tv_sec;
+	stats_all.s3.curtime.tv_usec = tm.tv_usec;
 	alarm(1);
 }
 
@@ -314,18 +307,46 @@
 setup()
 {
 	char errbuf[_POSIX2_LINE_MAX];
-
 	int en;
-
-	if ((kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf)) == NULL) {
-		syslog(LOG_ERR, "rpc.rstatd, %s", errbuf);
-		exit(1);
+	struct ifnet ifnet;
+	long off;
+	static int is_kd_setup = 0;
+
+	/*  setup() is called after each dormant->active
+	 *  transition.  Since we never close the kvm files
+	 *  (there's no reason), make sure we don't open them
+	 *  each time, as that can lead to exhaustion of all open
+	 *  files!  */
+	if (!is_kd_setup) {
+		kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+		if (kd == NULL) {
+		syslog(LOG_ERR, "%s", errbuf);
+		exit (1);
+		}
+		is_kd_setup = 1;
 	}
 
 	if ((en = kvm_nlist(kd, nl)) != 0) {
 		syslog(LOG_ERR, "rstatd: Can't get namelist. %d", en);
 		exit (1);
         }
+
+	if (kvm_read(kd, (long)nl[X_IFNET].n_value, &firstifnet,
+		    sizeof(int)) != sizeof(int))  {
+		syslog(LOG_ERR, "can't read firstifnet from kmem");
+		exit(1);
+	}
+
+	numintfs = 0;
+	for (off = firstifnet; off;) {
+		if (kvm_read(kd, off, (char *)&ifnet, sizeof ifnet) != sizeof ifnet) {
+			syslog(LOG_ERR, "can't read ifnet from kmem for ifcount");
+			exit(1);
+		}
+		numintfs++;
+		off = (long)ifnet.if_list.tqe_next;
+	}
+
 }
 
 /*
@@ -449,7 +470,7 @@
 
 	switch (rqstp->rq_proc) {
 	case NULLPROC:
-		(void)svc_sendreply(transp, xdr_void, (char *)NULL);
+		(void)svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
 		goto leave;
 
 	case RSTATPROC_STATS:
@@ -497,15 +518,15 @@
 		goto leave;
 	}
 	bzero((char *)&argument, sizeof(argument));
-	if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) {
+	if (!svc_getargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument)) {
 		svcerr_decode(transp);
 		goto leave;
 	}
 	result = (*local)(&argument, rqstp);
-	if (result != NULL && !svc_sendreply(transp, xdr_result, result)) {
+	if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result, result)) {
 		svcerr_systemerr(transp);
 	}
-	if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument))
+	if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (caddr_t)&argument))
 		errx(1, "unable to free arguments");
 leave:
         if (from_inetd)

>Release-Note:
>Audit-Trail:

From: Remko Lodder <remko@FreeBSD.org>
To: Bruce Becker <hostmaster@whois.gts.net>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: misc/110426: rpc.rstatd returns bad info
Date: Sun, 18 Mar 2007 17:01:13 +0100

 Bruce Becker wrote:
 >> Environment:
 > FreeBSD infra-gw 4.11-STABLE FreeBSD 4.11-STABLE #3: Wed Feb  7 16:21:26 EST 2007     root@infra-gw:/usr/obj/usr/src/sys/FW-YQ  i386
 > 
 >> Description:
 > 4.x & 3.x seem to have issues with opackets systcl mib (always returns 0)
 > 
 > this fix uses the kmem interface as well as fixes some code botches
 > 
 
 Hello,
 
 Both for this PR and the other one you submitted: can you confirm
 that this is fixed in 5.X already? We are -not- supporting <= 4.x
 anymore, so if someone wants to commit it, that's OK, but I dont
 want to keep 4.X specific PR's open (especially not new ones
 that were created after the EoL date for 4.X).
 
 Thanks,
 Remko
 
 -- 
 Kind regards,
 
       Remko Lodder               ** remko@elvandar.org
       FreeBSD                    ** remko@FreeBSD.org
 
       /* Quis custodiet ipsos custodes */
State-Changed-From-To: open->closed 
State-Changed-By: remko 
State-Changed-When: Sun Mar 18 16:02:52 UTC 2007 
State-Changed-Why:  
You are submitting 3.x and 4.x information (as I read it); and beyond 
that you do not appear to want feedback from me or anyone else (You are 
blocking my mailservers, which prevents us from getting anywhere). I 
will close this PR till you can fix your mailserver to accept regular 
actual email. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=110426 
>Unformatted:
