You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/ksysguard/ksysguardd/NetBSD/netdev.c

306 lines
7.1 KiB

/*
KSysGuard, the KDE System Guard
Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of version 2 of the GNU General Public
License as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <net/route.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <ifaddrs.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;
static struct SensorModul *NetDevSM;
/* 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, NetDevSM);
else
removeMonitor(buffer);
}
}
}
}
void initNetDev(struct SensorModul* sm) {
int i;
NetDevSM = sm;
updateNetDev();
for (i=LEN(NetDevs); i--;) {
strcpy(NetDevs[i].name, newval[i].name);
}
NDreg(!0);
}
void exitNetDev(void) {
NDreg(0);
}
int updateNetDev(void) {
NetDevInfo *p, *q;
int n;
if (-1==(n = readSys(0)))
return 0;
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];
}
}
return 0;
}
void checkNetDev(void) {
if (readSys(!0) != NetDevCnt) {
/* interface has been added or removed
so we do a reset */
exitNetDev();
initNetDev(NetDevSM);
}
}
/* eof */