diff options
Diffstat (limited to 'ksysguard/ksysguardd/NetBSD/netdev.c')
-rw-r--r-- | ksysguard/ksysguardd/NetBSD/netdev.c | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/ksysguard/ksysguardd/NetBSD/netdev.c b/ksysguard/ksysguardd/NetBSD/netdev.c new file mode 100644 index 000000000..477acc40e --- /dev/null +++ b/ksysguard/ksysguardd/NetBSD/netdev.c @@ -0,0 +1,304 @@ +/* + KSysGuard, the KDE System Guard + + Copyright (c) 2001 Tobias Koenig <[email protected]> + + 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); +} + +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(NetDevSM); + } +} + + +/* eof */ |