/* KSysGuard, the KDE System Guard Copyright (c) 2001 Tobias Koenig 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 #include #include #include #include #include #include #include #include #include #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; ptrrtm_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; iDrecv[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 */