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: