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.
306 lines
7.1 KiB
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 */
|