Subject: pkg/17981: new source file for kdebase3
To: None <gnats-bugs@gnats.netbsd.org>
From: None <hclsmith@yahoo.ca>
List: netbsd-bugs
Date: 08/18/2002 13:01:37
>Number:         17981
>Category:       pkg
>Synopsis:       ksysguardd can now show network interface traffic
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Aug 18 08:41:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     
>Release:        NetBSD 1.5.3
>Organization:
>Environment:
System: NetBSD gussie.hclsmith 1.5.3 NetBSD 1.5.3 (GUSSIE) #0: Sat Aug 17 13:27:21 ADT 2002 kwantus@gussie.hclsmith:/mnt/B/hclsmith/usr/src/sys/arch/i386/compile/GUSSIE i386
Architecture: i386
Machine: i386
>Description:
	the existing patch for kdebase-3.0.2/ksysguard/ksysguardd/FreeBSD/netdev.c
	is useless (in fact it's harmful as I pointed out in PR 17962)
	I have written a replacement file which doesn't leak and which provides
	some data.
>How-To-Repeat:
	
>Fix:
	set up the pkgsrc to replace
	kdebase-3.0.2/ksysguard/ksysguardd/FreeBSD/netdev.c
	with the following:



#include <sys/types.h> /* for sys/socket.h, ifaddrs.h */
#include <ifaddrs.h>
#include <sys/socket.h>
#include <sys/param.h> /* for sys/sysctl.h */
#include <sys/sysctl.h>
#include <net/route.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <stdlib.h>
#include <string.h>

#include "Command.h"
#include "ksysguardd.h"
#include "netdev.h"

#define I_bytes 0
#define I_packs 1
#define I_errs 2
#define I_mcasts 3
#define I_lost 4
typedef struct {
	char name[32];
	u_long recv[5],Drecv[5],sent[5],Dsent[5];
} NetDevInfo;

#define LEN(X) (sizeof(X)/sizeof(X[0]))

#define MAXNETDEVS 64
static NetDevInfo NetDevs[MAXNETDEVS], newval[MAXNETDEVS];
static int NetDevCnt = 0;


/* Read the system's traffic registers.
 * Merely count the IFs if countp nonzero.
 * Returns count of IFs read, or -1; the data are written into newval.
 * Based on getifaddrs source; getifaddrs itself seems to
 * compile incorrectly, omitting the traffic data. (It also
 * does things this doesn't need, thus this is slightly more efficient.)
 */
static int readSys(int countp) {
	size_t len;
	char *bfr, *ptr;
	struct rt_msghdr *rtm;
	NetDevInfo *nv;
	static int mib[] = {
		/* see sysctl(3): */
		CTL_NET,
    	PF_ROUTE,
		0, /* `currently always 0' */
		0, /* `may be set to 0 to select all address families' */
    	NET_RT_IFLIST,
		0 /* ignored but six levels are needed */
	};

	if (-1==sysctl(mib, LEN(mib), NULL, &len, NULL, 0))
		return -1;
	if (!(bfr = malloc(len)))
		return -1;
	if (-1==sysctl(mib, LEN(mib), bfr, &len, NULL, 0)) {
		free(bfr);
		return -1;
	}
	nv = newval;
	for (ptr=bfr; ptr<bfr+len; ptr+=rtm->rtm_msglen) {
		struct if_msghdr *ifm;

		rtm = (void*)ptr; /* chg ptr type to router msg */
		if (rtm->rtm_version != RTM_VERSION) continue;
		if (rtm->rtm_type != RTM_IFINFO) continue;
		ifm = (void*)rtm; /* chg ptr type to interface msg */
		if (!(ifm->ifm_flags & IFF_UP)) continue;

		if (!countp) {
			/* a sdl is concat'd to the if msg */
			struct sockaddr_dl *sdl = (void*)(ifm+1);

			/* copy and terminate the name */
			/*fixme: check for overruns */
			memcpy(nv->name, sdl->sdl_data, sdl->sdl_nlen);
			nv->name[sdl->sdl_nlen] = 0;

			/* copy the data */
			nv->recv[I_bytes]  = ifm->ifm_data.ifi_ibytes;
			nv->recv[I_packs]  = ifm->ifm_data.ifi_ipackets;
			nv->recv[I_errs]   = ifm->ifm_data.ifi_ierrors;
			nv->recv[I_mcasts] = ifm->ifm_data.ifi_imcasts;
			nv->recv[I_lost]   = ifm->ifm_data.ifi_iqdrops;
			nv->sent[I_bytes]  = ifm->ifm_data.ifi_obytes;
			nv->sent[I_packs]  = ifm->ifm_data.ifi_opackets;
			nv->sent[I_errs]   = ifm->ifm_data.ifi_oerrors;
			nv->sent[I_mcasts] = ifm->ifm_data.ifi_omcasts;
			nv->sent[I_lost]   = ifm->ifm_data.ifi_collisions;
		}

		/*fixme: guard against buffer overrun */
		nv++;
	}
	free(bfr);
	return nv-newval;
}




/* ------------------------------ public part --------------------------- */

static void prVal(const char*, int);
void printNetDevRecv(const char *cmd) { prVal(cmd,0); }
void printNetDevSent(const char *cmd) { prVal(cmd,1); }

static void prInfo(const char*, int);
void printNetDevRecvInfo(const char *cmd) { prInfo(cmd,0); }
void printNetDevSentInfo(const char *cmd) { prInfo(cmd,1); }

static struct {
	char *label;
	cmdExecutor read, inform;
	struct {
		char *label, *info;
		int index;
	} op[5];
} opTable[] = {
	{"receiver",
	 printNetDevRecv, printNetDevRecvInfo,
	 {{"data", "Received Data\t0\t0\tB/s\n", I_bytes},
	  {"packets", "Received Packets\t0\t0\tHz\n", I_packs},
	  {"errors", "Receiver Errors\t0\t0\tHz\n", I_errs},
	  {"multicast", "Received Multicast Packets\t0\t0\tHz\n", I_mcasts},
	  {"drops", "Receiver Drops\t0\t0\tHz\n", I_lost}}},
	{"transmitter",
	 printNetDevSent, printNetDevSentInfo,
     {{"data", "Sent Data\t0\t0\tB/s\n", I_bytes},
	  {"packets", "Sent Packets\t0\t0\tHz\n", I_packs},
	  {"errors", "Transmitter Errors\t0\t0\tHz\n", I_errs},
	  {"multicast", "Sent Multicast Packets\t0\t0\tHz\n", I_mcasts},
	  {"collisions", "Transmitter Collisions\t0\t0\tHz\n", I_lost}}}
};


static void prVal(const char *cmd, int N) {
	char *p, *q, *r;
	int i, d;

	if (!(p=rindex(cmd, '/')))
		return;
	*p=0;
	q=rindex(cmd, '/');
	*q=0;
	r=rindex(cmd, '/');
	r++;
	for (d=NetDevCnt; d--; )
		if (!strcmp(r, NetDevs[d].name))
			break;
	*q=*p='/';

	if (-1 == d) return;

	p++;
	for (i=0; i<LEN(opTable[0].op); i++)
		if (!strcmp(p, opTable[N].op[i].label))
			fprintf(CurrentClient, "%lu",
			 /*fixme: ugly and presumptuous */
			 (N?NetDevs[d].Dsent:NetDevs[d].Drecv)[opTable[N].op[i].index]);
	fprintf(CurrentClient, "\n");
}


static void prInfo(const char *cmd, int N) {
	char *p, *q;
	int i;

	if (!(p=rindex(cmd, '/'))) return;
	p++;

	q = p+strlen(p)-1;
	if ('?' != *q) return;
	*q=0;

	for (i=0; i<LEN(opTable[0].op); i++)
		if (!strcmp(p, opTable[N].op[i].label))
			fputs(opTable[N].op[i].info, CurrentClient);

	*q='?';
}


static void NDreg(int setp) {
	int i;

	for (i = 0; i<NetDevCnt; i++) {
		int j;

		for (j=0; j<LEN(opTable); j++) {
			int k;

			for (k=0; k<LEN(opTable[0].op); k++) {
				char buffer[1024];

				snprintf(buffer, sizeof(buffer),
				 "network/interfaces/%s/%s/%s",
				 NetDevs[i].name,
				 opTable[j].label,
				 opTable[j].op[k].label);

				/* printf("%d %d %d %s\n",i,j,k,buffer); */

				if (setp)
					registerMonitor(buffer,
					 "integer",
					 opTable[j].read,
					 opTable[j].inform);
				else
					removeMonitor(buffer);
			}
		}
	}
}

void initNetDev(void) {
	int i;
	updateNetDev();
	for (i=LEN(NetDevs); i--;)
		strcpy(NetDevs[i].name, newval[i].name);
	NDreg(!0);
}

void exitNetDev(void) {
	NDreg(0);
}

void updateNetDev(void) {
	NetDevInfo *p, *q;
	int n;

	if (-1==(n = readSys(0)))
		return;

	NetDevCnt = n;
	/*fixme: assumes the interfaces are in the same order each time */
	for (p=NetDevs, q=newval; n--; p++, q++) {
		int i;
		/* calculate deltas */
		for (i=0; i<5; i++) {
			p->Drecv[i] = q->recv[i]-p->recv[i];
			p->recv[i]  = q->recv[i];
			p->Dsent[i] = q->sent[i]-p->sent[i];
			p->sent[i]  = q->sent[i];
		}
	}
}


void checkNetDev(void) {
	if (readSys(!0) != NetDevCnt) {
		/* interface has been added or removed
		   so we do a reset */
		exitNetDev();
		initNetDev();
	}
}


/* eof */
>Release-Note:
>Audit-Trail:
>Unformatted: