Subject: pkg/17521: patch for net/wmnet to support Solaris kstat(3) facility
To: None <gnats-bugs@gnats.netbsd.org>
From: Lubomir Sedlacik <salo@Xtrmntr.org>
List: netbsd-bugs
Date: 07/08/2002 17:36:55
>Number:         17521
>Category:       pkg
>Synopsis:       patch for net/wmnet to support Solaris kstat(3) facility
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Mon Jul 08 08:37:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Lubomir Sedlacik
>Release:        SunOS 5.9
>Organization:
>Environment:
>Description:

this patch provides kstat support for net/wmnet dockable network load monitor
to work on Solaris.  as stands in kstat(3KSTAT):

     The kstat facility is a general-purpose mechanism  for providing
     kernel statistics to users.

prior to this patch wmnet doesn't work on Solaris at all.  the patch was
written by Dan Price <dp at rampant dot org> and merged into pkgsrc by me.

>How-To-Repeat:
>Fix:

Index: distinfo
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/distinfo,v
retrieving revision 1.3
diff -u -u -r1.3 distinfo
--- distinfo	2001/06/30 09:55:57	1.3
+++ distinfo	2002/07/08 15:22:46
@@ -2,9 +2,9 @@
 
 SHA1 (wmnet-1.06.tar.gz) = 978364e0ab45c71730c196334e8fced4ac0a7853
 Size (wmnet-1.06.tar.gz) = 27506 bytes
-SHA1 (patch-aa) = be4c53294fbdf234f50900f5051d7a48c70e4481
-SHA1 (patch-ab) = 97418adde93c0299fa5cdfdafc435350cf99e22e
-SHA1 (patch-ac) = 9afb6353c121f8d935243d5cd34daa824005d6da
-SHA1 (patch-ad) = b8212251da24d60856f5ff0349a6b6abf732888b
-SHA1 (patch-ae) = bc43be18fc06090bf102ec927ce5c1bd6f9ab953
+SHA1 (patch-aa) = d999f66818c05f2f9a58571abc0e548bb2938a4b
+SHA1 (patch-ab) = 2c2fbc065a49bc27dd42660dda23393e02269714
+SHA1 (patch-ac) = f8793a06cdf4ffd9e852dd802054734a566edb30
+SHA1 (patch-ad) = 7a420d0dcef977549ba35a1046a0e5509a0c3643
+SHA1 (patch-ae) = 09d413422b0074c29da7c8a9c271d9ddb2be04fb
 SHA1 (patch-af) = 70c0917b465acf778b6b744bef587bc8e41e49fb
Index: patches/patch-aa
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/patches/patch-aa,v
retrieving revision 1.1
diff -u -u -r1.1 patch-aa
--- patch-aa	2000/07/31 17:02:25	1.1
+++ patch-aa	2002/07/08 15:22:46
@@ -1,8 +1,8 @@
 $NetBSD: patch-aa,v 1.1 2000/07/31 17:02:25 tron Exp $
 
 --- Imakefile.orig	Fri May  5 02:34:29 2000
-+++ Imakefile	Mon Jul 31 19:01:24 2000
-@@ -10,14 +10,16 @@
++++ Imakefile	Mon Jul  8 16:54:18 2002
+@@ -10,14 +10,21 @@
  LOCAL_LIBRARIES = $(XLIB) -lm 
  #endif
  
@@ -13,11 +13,16 @@
  INSTPGMFLAGS = -s -g kmem -m 2755 
  #endif
  
++#if defined (SunArchitecture)
++LOCAL_LIBRARIES = $(XLIB) -lm -lkstat
++CCOPTIONS =
++#endif
++
  LINTLIBS = $(LINTXLIB)
  
 -#if defined (FreeBSDArchitecture) || defined (OpenBSDArchitecture)
 +#if defined (FreeBSDArchitecture) || defined (OpenBSDArchitecture) || \
-+    defined (NetBSDArchitecture)
++    defined (NetBSDArchitecture) || defined (SunArchitecture)
  SRCS = wmnet.c drivers.c getopt.c getopt1.c
  OBJS = wmnet.o drivers.o getopt.o getopt1.o
  #else
Index: patches/patch-ab
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/patches/patch-ab,v
retrieving revision 1.1
diff -u -u -r1.1 patch-ab
--- patch-ab	2000/07/31 17:02:25	1.1
+++ patch-ab	2002/07/08 15:22:46
@@ -1,10 +1,29 @@
 $NetBSD: patch-ab,v 1.1 2000/07/31 17:02:25 tron Exp $
 
 --- config.h.orig	Fri May  5 02:34:29 2000
-+++ config.h	Mon Jul 31 19:00:30 2000
++++ config.h	Mon Jul  8 16:44:18 2002
 @@ -1,4 +1,4 @@
 -#if defined (__FreeBSD__) || defined (__OpenBSD__)
 +#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
  
  /* Our only FreeBSD driver, this goes straight into kernel memory 
   * and reads the raw structures from right underneath the kernel using the
+@@ -13,7 +13,18 @@
+ #endif
+ 
+ 
++#if defined (sun)
+ 
++/*
++ * This driver uses the Solaris kstat(3) mechanism to acquire interface
++ * statistics.  It's a lot more elegant than grovelling through kernel
++ * memory.
++ */
++#define USE_KSTAT
++
++#endif
++
++
+ #ifdef linux
+ 
+ /* this driver uses a socket ioctl() to get stats from a ppp type interface
Index: patches/patch-ac
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/patches/patch-ac,v
retrieving revision 1.3
diff -u -u -r1.3 patch-ac
--- patch-ac	2001/06/30 09:55:57	1.3
+++ patch-ac	2002/07/08 15:22:47
@@ -1,8 +1,24 @@
 $NetBSD: patch-ac,v 1.3 2001/06/30 09:55:57 wiz Exp $
 
 --- drivers.c.orig	Fri May  5 02:34:29 2000
-+++ drivers.c
-@@ -57,7 +57,7 @@
++++ drivers.c	Mon Jul  8 16:50:15 2002
+@@ -37,7 +37,15 @@
+ int kvm_updateStats(void);
+ #endif /* USE_KVM */
+ 
++/* For Solaris */
++#ifdef USE_KSTAT
++#include <kstat.h>
+ 
++int kstat_test(void);
++int kstat_updateStats(void);
++#endif /* USE_KSTAT */
++
++
+ #ifdef USE_LINUX_PPP
+ #include<net/ppp_defs.h>
+ 
+@@ -57,7 +65,7 @@
  #define ACCOUNT_IN_FOUND        1
  #define ACCOUNT_OUT_FOUND       2
  
@@ -11,7 +27,17 @@
  extern char *in_rule_string, *out_rule_string, *device;
  extern unsigned long totalbytes_in, totalbytes_out, lastbytes_in, lastbytes_out;
  extern unsigned long totalpackets_in, totalpackets_out, lastpackets_in, lastpackets_out;
-@@ -445,7 +445,7 @@
+@@ -104,6 +112,9 @@
+ #ifdef USE_KVM
+  {"kmem",kvm_updateStats, kvm_test},
+ #endif
++#ifdef USE_KSTAT
++ {"kstat", kstat_updateStats, kstat_test},
++#endif
+  {NULL, NULL}
+ };
+ 
+@@ -445,7 +456,7 @@
    if (((kvmfd = kvm_open(NULL, NULL, NULL, O_RDONLY, buffer)) == NULL) ||
        (kvm_nlist(kvmfd, symbols) < 0) ||
        kvm_read(kvmfd, (unsigned long)symbols[0].n_value, &ifnet_savedaddr, sizeof(unsigned long)) == -1 ) return False;
@@ -20,7 +46,7 @@
    fprintf(stderr, "wmnet: using kmem driver to monitor %s\n", device);
    return True;
  }
-@@ -457,7 +457,7 @@
+@@ -457,7 +468,7 @@
   int flag = 0;
   while (ifnet_addr && flag != (ACCOUNT_IN_FOUND|ACCOUNT_OUT_FOUND)) {
    kvm_read(kvmfd, ifnet_addr, buffer, sizeof(struct ifnet));
@@ -29,7 +55,7 @@
    snprintf(devname, 15, "%s", ifnet->if_xname);
  #else
    kvm_read(kvmfd, (unsigned long)ifnet->if_name, devname, 15);
-@@ -487,7 +487,7 @@
+@@ -487,7 +498,7 @@
          flag = (ACCOUNT_IN_FOUND|ACCOUNT_OUT_FOUND);
  
    } else {
@@ -38,3 +64,124 @@
          ifnet_addr = (unsigned long)ifnet->if_list.tqe_next;
  #else
          ifnet_addr = (unsigned long)ifnet->if_next;
+@@ -502,8 +513,119 @@
+ }
+ 
+ 
+-#endif
++#endif /* KVM */
+   
+ 
++#ifdef USE_KSTAT
+    
++kstat_ctl_t *kc = NULL;
++kstat_t *if_ksp = NULL;
++
++int kstat_test(void)
++{
++	kstat_t *ksp;
++
++	if (kc == NULL) {
++		if ((kc = kstat_open()) == NULL) {
++			perror("wmnet [kstat]: can't open /dev/kstat\n");
++			return (False);
++		}
++	}
++
++	/*
++	 * If no device given, take the first thing we find of class 'net'
++	 * which exports the four kstats we need.
++	 */
++	if (device == NULL) {
++		for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
++			if (strcmp(ksp->ks_class, "net") == 0) {
++				kstat_read(kc, ksp, NULL);
++				if (kstat_data_lookup(ksp, "ipackets") &&
++				    kstat_data_lookup(ksp, "opackets") &&
++				    kstat_data_lookup(ksp, "rbytes") &&
++				    kstat_data_lookup(ksp, "obytes")) {
++					if_ksp = ksp;
++					break;
++				}
++			}
++		}
++		if (if_ksp == NULL) {
++			fprintf(stderr, "wmnet [kstat]: no network interface "
++			    "exporting kstats found\n");
++			return (False);
++		} else {
++			fprintf(stderr, "wmnet [kstat]: monitoring %s\n",
++			    ksp->ks_name);
++		}
++	} else {
++		if ((if_ksp = (kstat_lookup(kc, NULL, -1, device))) == NULL) {
++			fprintf(stderr, "wmnet [kstat]: no network interface "
++			    "%s exporting kstats found\n", device);
++			return (False);
++		}
++	}
++
++	return (True);
++}
++
++int kstat_updateStats(void)
++{
++	kstat_named_t *in_pkt, *in_byte, *out_pkt, *out_byte;
++	tx = rx = False;
++
++	if (kstat_read(kc, if_ksp, NULL) == -1) {
++		(void) fprintf(stderr, "wmnet [kstat]: kstat_read failed\n");
++		exit (1);
++	}
++
++	if ((in_pkt = (kstat_named_t *) kstat_data_lookup(if_ksp, "ipackets"))
++	    == NULL) {
++		(void) fprintf(stderr, "wmnet [kstat]: kstat_data_lookup "
++		    "(ipackets) failed\n");
++		exit (1);
++	}
++
++	totalpackets_in = (in_pkt->value.ui32);
++	if (totalpackets_in != lastpackets_in) {
++		if ((in_byte = (kstat_named_t *) kstat_data_lookup(if_ksp,
++		    "rbytes")) == NULL) {
++			(void) fprintf(stderr, "wmnet [kstat]: "
++			    "kstat_data_lookup (rbytes) failed\n");
++			exit (1);
++		}
++		totalbytes_in = in_byte->value.ui32;
++		diffpackets_in += totalpackets_in - lastpackets_in;
++		diffbytes_in += totalbytes_in - lastbytes_in;
++		lastpackets_in = totalpackets_in;
++                lastbytes_in = totalbytes_in;
++                rx = True;
++	}
++
++	if ((out_pkt = (kstat_named_t *) kstat_data_lookup(if_ksp, "opackets"))
++	    == NULL) {
++		(void) fprintf(stderr, "wmnet [kstat]: kstat_data_lookup "
++		    "(opackets) failed\n");
++		exit (1);
++	}
++
++	totalpackets_out = (out_pkt->value.ui32);
++	if (totalpackets_out != lastpackets_out) {
++		if ((out_byte = (kstat_named_t *) kstat_data_lookup(if_ksp,
++		    "obytes")) == NULL) {
++			(void) fprintf(stderr, "wmnet [kstat]: "
++			    "kstat_data_lookup (obytes) failed\n");
++			exit (1);
++		}
++		totalbytes_out = out_byte->value.ui32;
++		diffpackets_out += totalpackets_out - lastpackets_out;
++		diffbytes_out += totalbytes_out - lastbytes_out;
++		lastpackets_out = totalpackets_out;
++                lastbytes_out = totalbytes_out;
++                tx = True;
++	}
++
++	return ((rx == current_rx) && (tx == current_tx));
++}
++
++#endif /* KSTAT */
+   
Index: patches/patch-ad
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/patches/patch-ad,v
retrieving revision 1.2
diff -u -u -r1.2 patch-ad
--- patch-ad	2001/03/27 02:29:18	1.2
+++ patch-ad	2002/07/08 15:22:47
@@ -1,8 +1,8 @@
 $NetBSD: patch-ad,v 1.2 2001/03/27 02:29:18 hubertf Exp $
 
 --- wmnet.c.orig	Fri May  5 03:01:14 2000
-+++ wmnet.c
-@@ -55,7 +55,7 @@
++++ wmnet.c	Mon Jul  8 16:52:30 2002
+@@ -55,9 +55,13 @@
  #include<X11/Xlib.h>
  #include<X11/Xutil.h>
  #include<X11/Xatom.h>
@@ -10,8 +10,14 @@
 +#if defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__)
  # include<sys/socket.h>
  # include"getopt.h"
++#elif defined (sun)
++# include<sys/socket.h>
++# include<sys/sockio.h>
++# include "getopt.h"
  #else
-@@ -97,17 +97,19 @@
+ # include<getopt.h>
+ #endif
+@@ -97,17 +101,19 @@
  	int c;
  	XColor thecolor;
  	struct sigaction signal_action;
@@ -34,7 +40,7 @@
  		{"logscale", no_argument, NULL, 'l'},
  		{"help", no_argument, NULL, 'h'},
  		{"execute", required_argument, NULL, 'e'}, 
-@@ -131,9 +133,9 @@
+@@ -131,9 +137,9 @@
  
  	/* Get options */
  #ifdef linux
@@ -46,7 +52,7 @@
  #endif
  		switch(c) {
  			case 'v':
-@@ -176,6 +178,15 @@
+@@ -176,6 +182,15 @@
  					exit(23);
  				}
  				break;
@@ -62,7 +68,7 @@
  			case 'F':
  				if (labelfgcolorString == NULL) {
  					labelfgcolorString = (char *)alloca(strlen(optarg)+1);
-@@ -228,6 +239,9 @@
+@@ -228,6 +243,9 @@
  			case 'n':
  				specified_state = NormalState;
  				break;
@@ -72,7 +78,7 @@
  			case 'u':
  				{
  					int fds;
-@@ -283,6 +297,7 @@
+@@ -283,6 +301,7 @@
                                         "  -L, --label=LABEL        display LABEL on bottom of window\n"
                                         "  -F, --labelfg=COLOR      foreground color for the label\n"
                                         "  -B, --labelbg=COLOR      background color for the label\n"
@@ -80,7 +86,7 @@
                                         "  -e, --execute=COMMAND    run COMMAND on click\n"
  #ifdef linux
  				       "  -T, --txrule=RULE        accounting rule number (ipfwadm) or\n"
-@@ -320,6 +335,7 @@
+@@ -320,6 +339,7 @@
  	if (rxcolorString == NULL) rxcolorString = "red";
  	if (labelfgcolorString == NULL) labelfgcolorString = "white";
  	if (labelbgcolorString == NULL) labelbgcolorString = "black";
@@ -88,7 +94,7 @@
  
  	/* Change dir to /, security precaution, and common courtesy */
  	if (chdir("/") == -1) {
-@@ -384,6 +400,14 @@
+@@ -384,6 +404,14 @@
  		XAllocColor(dpy, DefaultColormap(dpy, screen), &thecolor);
  		labelbg_pixel = thecolor.pixel;
  	}
@@ -103,7 +109,7 @@
  
  	/* usleep() in between polls to /proc/net/ip_acct */
  	if (delayTime <= 0) delayTime = 25000;
-@@ -442,7 +466,7 @@
+@@ -442,7 +470,7 @@
  	}
  	gcv.graphics_exposures = False;
  	gcv.foreground = tx_pixel[HIGH_INTENSITY]; 
@@ -112,7 +118,7 @@
  	gcv.font = XLoadFont(dpy, "5x8");
  	graphics_context = XCreateGC(dpy, root_window, (GCFont|GCGraphicsExposures|GCForeground|GCBackground), &gcv);
  	black_pixel = BlackPixel(dpy, screen);
-@@ -494,12 +518,12 @@
+@@ -494,12 +522,12 @@
  /* Handles Expose events, repaints the window */
  void redraw(XExposeEvent *ee) {
          static XRectangle cliprect = { 4, 51, 56, 9 };
@@ -127,34 +133,28 @@
  	XFillRectangle(dpy, *visible_window, graphics_context, TOPBOX_X, TOPBOX_Y, TOPBOX_WIDTH, TOPBOX_HEIGHT);
  	XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_LEFT, GRAPHBOX_Y_TOP, GRAPHBOX_X_LEFT, GRAPHBOX_Y_BOTTOM);
  	XDrawPoint(dpy, *visible_window, graphics_context, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_TOP);
-@@ -513,15 +537,19 @@
+@@ -513,15 +541,19 @@
  	}
  
  
--	XSetForeground(dpy, graphics_context, white_pixel);
--	XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, (GRAPHBOX_Y_TOP + 1)); 
--	XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_LEFT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM);
 +	if (! no3d) {
-+		XSetForeground(dpy, graphics_context, white_pixel);
-+		XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, (GRAPHBOX_Y_TOP + 1)); 
-+		XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_LEFT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM);
+ 	XSetForeground(dpy, graphics_context, white_pixel);
+ 	XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, (GRAPHBOX_Y_TOP + 1)); 
+ 	XDrawLine(dpy, *visible_window, graphics_context, GRAPHBOX_X_LEFT, GRAPHBOX_Y_BOTTOM, GRAPHBOX_X_RIGHT, GRAPHBOX_Y_BOTTOM);
 +	}
  
  
--	XSetForeground(dpy, graphics_context, grey_pixel);
--	XSetBackground(dpy, graphics_context, black_pixel);
--	XCopyPlane(dpy, arrow, *visible_window, graphics_context, 7, 0, 7, 9, 53, 5, 1);
--	XCopyPlane(dpy, arrow, *visible_window, graphics_context, 0, 0, 7, 9, 46, 5, 1);
 +	if (! no3d) { /* OK, this is cheating, but I don't want to add yet another switch; I have NFC what these arrows are for - HF */
-+		XSetForeground(dpy, graphics_context, grey_pixel);
+ 	XSetForeground(dpy, graphics_context, grey_pixel);
+-	XSetBackground(dpy, graphics_context, black_pixel);
 +		XSetBackground(dpy, graphics_context, bg_pixel);
-+		XCopyPlane(dpy, arrow, *visible_window, graphics_context, 7, 0, 7, 9, 53, 5, 1);
-+		XCopyPlane(dpy, arrow, *visible_window, graphics_context, 0, 0, 7, 9, 46, 5, 1);
+ 	XCopyPlane(dpy, arrow, *visible_window, graphics_context, 7, 0, 7, 9, 53, 5, 1);
+ 	XCopyPlane(dpy, arrow, *visible_window, graphics_context, 0, 0, 7, 9, 46, 5, 1);
 +	}
  }
  	
  	
-@@ -572,7 +600,7 @@
+@@ -572,7 +604,7 @@
  		if (blank < (GRAPH_WIDTH + 1) ) {
  			XCopyArea(dpy, *visible_window, *visible_window, graphics_context, GRAPH_X + 1,
  			   GRAPH_Y, GRAPH_WIDTH - 1, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y);
@@ -163,7 +163,7 @@
  			XDrawLine(dpy, *visible_window, graphics_context, GRAPH_X_RIGHT, y, GRAPH_X_RIGHT, yy);
  			if (( (yy == GRAPH_Y_UPPER && diffbytes_out > 0 && rate_rx > rate_tx) || (rate_rx >= rate_tx && yy != GRAPH_Y_UPPER)) ) {
  				drawColoredLine(GRAPH_Y_UPPER, yy, tx_pixel);				
-@@ -593,7 +621,7 @@
+@@ -593,7 +625,7 @@
  	if (!stat_gather()) {  /* Anything change? */
  		current_rx = rx;
  		current_tx = tx;
@@ -172,7 +172,7 @@
  		if(current_tx == True) {
  			XSetForeground(dpy, graphics_context, tx_pixel[HIGH_INTENSITY]);
  			XCopyPlane(dpy, arrow, *visible_window, graphics_context, 7, 0, 7, 9, 53, 5, 1);
-@@ -646,7 +674,7 @@
+@@ -646,7 +678,7 @@
  
  
  	if (!clear) {
Index: patches/patch-ae
===================================================================
RCS file: /cvsroot/pkgsrc/net/wmnet/patches/patch-ae,v
retrieving revision 1.3
diff -u -u -r1.3 patch-ae
--- patch-ae	2001/03/27 02:29:18	1.3
+++ patch-ae	2002/07/08 15:22:47
@@ -1,12 +1,12 @@
 $NetBSD: patch-ae,v 1.3 2001/03/27 02:29:18 hubertf Exp $
 
 --- wmnet.man.orig	Fri May  5 02:43:35 2000
-+++ wmnet.man
++++ wmnet.man	Mon Jul  8 17:09:42 2002
 @@ -1,6 +1,6 @@
  .\"             -*-Nroff-*-
  .\"
 -.TH wmnet 1x "4 May 2000"
-+.TH wmnet 1x "4 Mar 2001"
++.TH wmnet 1x "8 Jul 2002"
  .SH NAME
  wmnet \- an IP accounting monitoring tool
  .SH SYNOPSIS
@@ -40,7 +40,7 @@
  .B -e,--execute=\fICOMMAND
  executes \fICOMMAND \fPon a single click from button 1 (left mouse button).
  .TP
-@@ -147,9 +156,9 @@
+@@ -147,9 +156,13 @@
  Otherwise, the kernel will not collect the stats we need.
  .TP
  .B kmem
@@ -50,6 +50,10 @@
 +this driver is available on FreeBSD, OpenBSD and NetBSD systems and must be
 +passed a device through the \fI--device\fP option.  By default, it uses ppp0
 +but will accept any valid device name.
++.TP
++.B kstat
++this driver is available on Solaris and uses general-purpose kernel statistics
++facility provided by kstat device.
  .SH FILES
  .TP
  .I /proc/net/ip_acct /proc/net/dev /proc/net/ipchains
>Release-Note:
>Audit-Trail:
>Unformatted: