2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
6
This program is free software; you can redistribute it and/or
7
modify it under the terms of version 2 of the GNU General Public
8
License as published by the Free Software Foundation.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
#include <config-workspace.h>
23
#include <sys/types.h>
32
#include "ksysguardd.h"
38
#define CALC( a, b, c, d, e, f ) \
41
if( NetDevs[i].oldInitialised) {\
42
if( a >= NetDevs[i].a ) \
43
NetDevs[ i ].delta##a = a - NetDevs[ i ].a; \
45
NetDevs[ i ].delta##a = a; \
47
NetDevs[ i ].delta##a = 0; \
52
#define REGISTERSENSOR( a, b, c, d, e, f ) \
54
snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", tag, b ); \
55
registerMonitor( mon, "float", printNetDev##a##0, printNetDev##a##0Info, NetDevSM ); \
57
snprintf( mon, MON_SIZE, "network/interfaces/%s/%sTotal", tag, b ); \
58
registerMonitor( mon, "float", printNetDev##a##1, printNetDev##a##1Info, NetDevSM ); \
62
#define UNREGISTERSENSOR( a, b, c, d, e, f ) \
64
snprintf( mon, MON_SIZE, "network/interfaces/%s/%s", NetDevs[ i ].name, b ); \
65
removeMonitor( mon ); \
67
snprintf( mon, MON_SIZE, "network/interfaces/%s/%sTotal", NetDevs[ i ].name, b ); \
68
removeMonitor( mon ); \
72
#define DEFMEMBERS( a, b, c, d, e, f ) \
73
unsigned long long delta##a; \
74
unsigned long long a; \
75
unsigned long a##Scale;
77
#define DEFWIFIMEMBERS( a, b, c, d, e, f ) \
78
signed long long delta##a; \
82
#define DEFVARS( a, b, c, d, e, f) \
85
#define DEFWIFIVARS( a, b, c, d, e, f) \
88
/* The sixth variable is 1 if the quantity variation must be provided, 0 if the absolute value must be provided */
90
a( recBytes, "receiver/data", "Received Data", "KB", 1024, 1) \
91
a( recPacks, "receiver/packets", "Received Packets", "", 1, 1 ) \
92
a( recErrs, "receiver/errors", "Receiver Errors", "", 1, 1 ) \
93
a( recDrop, "receiver/drops", "Receiver Drops", "", 1, 1 ) \
94
a( recFifo, "receiver/fifo", "Receiver FIFO Overruns", "", 1, 1 ) \
95
a( recFrame, "receiver/frame", "Receiver Frame Errors", "", 1, 1 ) \
96
a( recCompressed, "receiver/compressed", "Received Compressed Packets", "", 1, 1 ) \
97
a( recMulticast, "receiver/multicast", "Received Multicast Packets", "", 1, 1 ) \
98
a( sentBytes, "transmitter/data", "Sent Data", "KB", 1024, 1 ) \
99
a( sentPacks, "transmitter/packets", "Sent Packets", "", 1, 1 ) \
100
a( sentErrs, "transmitter/errors", "Transmitter Errors", "", 1, 1 ) \
101
a( sentDrop, "transmitter/drops", "Transmitter Drops", "", 1, 1 ) \
102
a( sentFifo, "transmitter/fifo", "Transmitter FIFO overruns", "", 1, 1 ) \
103
a( sentColls, "transmitter/collisions", "Transmitter Collisions", "", 1, 1 ) \
104
a( sentCarrier, "transmitter/carrier", "Transmitter Carrier losses", "", 1, 1 ) \
105
a( sentCompressed, "transmitter/compressed", "Transmitter Compressed Packets", "", 1, 1 )
107
#define FORALLWIFI( a ) \
108
a( linkQuality, "wifi/quality", "Link Quality", "", 1, 0) \
109
a( signalLevel, "wifi/signal", "Signal Level", "dBm", 1, 0) \
110
a( noiseLevel, "wifi/noise", "Noise Level", "dBm", 1, 0) \
111
a( nwid, "wifi/nwid", "Rx Invalid Nwid Packets", "", 1, 1) \
112
a( RxCrypt, "wifi/crypt", "Rx Invalid Crypt Packets", "", 1, 1) \
113
a( frag, "wifi/frag", "Rx Invalid Frag Packets", "", 1, 1) \
114
a( retry, "wifi/retry", "Tx Excessive Retries Packets", "", 1, 1) \
115
a( misc, "wifi/misc", "Invalid Misc Packets", "", 1, 1) \
116
a( beacon, "wifi/beacon", "Missed Beacon", "", 1, 1)
118
#define SETZERO( a, b, c, d, e, f ) \
121
#define SETMEMBERZERO( a, b, c, d, e, f ) \
122
NetDevs[ i ].a = 0; \
123
NetDevs[ i ].delta##a = 0; \
124
NetDevs[ i ].a##Scale = e;
126
#define DECLAREFUNC( a, b, c, d, e, f) \
127
void printNetDev##a##0( const char* cmd ); \
128
void printNetDev##a##0Info( const char* cmd ); \
129
void printNetDev##a##1( const char* cmd ); \
130
void printNetDev##a##1Info( const char* cmd ); \
135
FORALLWIFI( DEFWIFIMEMBERS )
141
/* We have observed deviations of up to 5% in the accuracy of the timer
142
* interrupts. So we try to measure the interrupt interval and use this
143
* value to calculate timing dependant values. */
144
static float timeInterval = 0;
145
static struct timeval lastSampling;
146
static struct timeval currSampling;
147
static struct SensorModul* NetDevSM;
149
#define NETDEVBUFSIZE 4096
150
static char NetDevBuf[ NETDEVBUFSIZE ];
151
static char NetDevWifiBuf[ NETDEVBUFSIZE ];
152
static int NetDevCnt = 0;
153
static int Dirty = 0;
154
static long OldHash = 0;
156
#define MAXNETDEVS 64
157
static NetDevInfo NetDevs[ MAXNETDEVS ];
159
void processNetDev( void );
161
FORALL( DECLAREFUNC )
162
FORALLWIFI( DECLAREFUNC )
164
static int processNetDev_( void )
168
char devFormat[ 16 ];
171
char* netDevBufP = NetDevBuf;
172
char* netDevWifiBufP = NetDevWifiBuf;
174
sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
175
sprintf( devFormat, "%%%ds", (int)sizeof( tag ) - 1 );
177
/*Update the values for the wifi interfaces if there is a /proc/net/wireless file*/
178
if (*netDevBufP != '\0') {
179
/* skip 2 first lines */
180
for (i = 0; i < 2; i++) {
181
sscanf(netDevBufP, format, buf);
182
buf[sizeof(buf) - 1] = '\0';
183
netDevBufP += strlen(buf) + 1; /* move netDevBufP to next line */
186
for (i = 0; sscanf(netDevBufP, format, buf) == 1; ++i) {
187
buf[sizeof(buf) - 1] = '\0';
188
netDevBufP += strlen(buf) + 1; /* move netDevBufP to next line */
190
if (sscanf(buf, devFormat, tag)) {
191
char* pos = strchr(tag, ':');
196
sscanf(buf + 7, "%llu %llu %llu %llu %llu %llu %llu %llu "
197
"%llu %llu %llu %llu %llu %llu %llu %llu",
198
&recBytes, &recPacks, &recErrs, &recDrop, &recFifo,
199
&recFrame, &recCompressed, &recMulticast,
200
&sentBytes, &sentPacks, &sentErrs, &sentDrop,
201
&sentFifo, &sentColls, &sentCarrier, &sentCompressed);
203
if (i >= NetDevCnt || strcmp(NetDevs[i].name, tag) != 0) {
204
/* The network device configuration has changed. We
205
* need to reconfigure the netdev module. */
209
if (!NetDevs[i].isWifi)
210
NetDevs[i].oldInitialised = 1;
215
if ( i != NetDevCnt )
221
/*Update the values for the wifi interfaces if there is a /proc/net/wireless file*/
222
if (*netDevWifiBufP != '\0') {
224
/* skip 2 first lines */
225
for (i = 0; i < 2; i++) {
226
sscanf(netDevWifiBufP, format, buf);
227
buf[sizeof(buf) - 1] = '\0';
228
netDevWifiBufP += strlen(buf) + 1; /* move netDevWifiBufP to next line */
231
for (j = 0; sscanf(netDevWifiBufP, format, buf) == 1; ++j) {
232
buf[sizeof(buf) - 1] = '\0';
233
netDevWifiBufP += strlen(buf) + 1; /* move netDevWifiBufP to next line */
235
if (sscanf(buf, devFormat, tag)) {
236
char* pos = strchr(tag, ':');
238
FORALLWIFI( DEFWIFIVARS );
241
for (i = 0; i < NetDevCnt; ++i) { /*find the corresponding interface*/
242
if (strcmp(tag, NetDevs[i].name) == 0) {
246
sscanf(buf + 12, " %lli. %lli. %lli. %lli %lli %lli %lli %lli %lli",
247
&linkQuality, &signalLevel, &noiseLevel, &nwid,
248
&RxCrypt, &frag, &retry, &misc, &beacon);
249
signalLevel -= 256; /*the units are dBm*/
252
NetDevs[i].oldInitialised = 1;
258
/* save exact time inverval between this and the last read of
260
timeInterval = currSampling.tv_sec - lastSampling.tv_sec +
261
( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0;
262
lastSampling = currSampling;
268
void processNetDev( void )
272
if ( NetDevCnt == 0 )
275
for ( i = 0; i < 5 && processNetDev_() < 0; ++i ) {
276
/* Values for other network devices are lost, but it is still better
277
* than not detecting any new devices */
279
initNetDev( NetDevSM );
282
/* If 5 reconfiguration attemts failed, something is very wrong and
283
* we close the netdev module for further use. */
289
================================ public part =================================
292
void initNetDev( struct SensorModul* sm )
296
char devFormat[ 16 ];
299
char* netDevBufP = NetDevBuf;
300
char* netDevWifiBufP = NetDevWifiBuf;
304
if ( updateNetDev() < 0 )
307
sprintf( format, "%%%d[^\n]\n", (int)sizeof( buf ) - 1 );
308
sprintf( devFormat, "%%%ds", (int)sizeof( tag ) - 1 );
310
/* skip 2 first lines */
311
for ( i = 0; i < 2; i++ ) {
312
sscanf( netDevBufP, format, buf );
313
buf[ sizeof( buf ) - 1 ] = '\0';
314
netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
317
for ( i = 0; sscanf( netDevBufP, format, buf ) == 1; ++i ) {
318
buf[ sizeof( buf ) - 1 ] = '\0';
319
netDevBufP += strlen( buf ) + 1; /* move netDevBufP to next line */
321
NetDevs[i].oldInitialised = 0;
322
if ( sscanf( buf, devFormat, tag ) ) {
323
char* pos = strchr( tag, ':' );
324
FORALL( SETMEMBERZERO );
326
char mon[ MON_SIZE ];
328
strncpy( NetDevs[ i ].name, tag, sizeof( NetDevs[ i ].name ) );
329
NetDevs[ i ].name[ sizeof( NetDevs[ i ].name )-1] = 0;
330
FORALL( REGISTERSENSOR );
331
sscanf( pos + 1, "%lli %lli %lli %lli %lli %lli %lli %lli"
332
"%lli %lli %lli %lli %lli %lli %lli %lli",
333
&NetDevs[ i ].recBytes, &NetDevs[ i ].recPacks,
334
&NetDevs[ i ].recErrs, &NetDevs[ i ].recDrop,
335
&NetDevs[ i ].recFifo, &NetDevs[ i ].recFrame,
336
&NetDevs[ i ].recCompressed, &NetDevs[ i ].recMulticast,
337
&NetDevs[ i ].sentBytes, &NetDevs[ i ].sentPacks,
338
&NetDevs[ i ].sentErrs, &NetDevs[ i ].sentDrop,
339
&NetDevs[ i ].sentFifo, &NetDevs[ i ].sentColls,
340
&NetDevs[ i ].sentCarrier, &NetDevs[ i ].sentCompressed );
346
/* detect the wifi interfaces*/
347
/* skip 2 first lines */
348
for ( i = 0; i < 2; i++ ) {
349
sscanf( netDevWifiBufP, format, buf );
350
buf[ sizeof( buf ) - 1 ] = '\0';
351
netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */
354
for ( j = 0; sscanf( netDevWifiBufP, format, buf ) == 1; ++j ) {
355
buf[ sizeof( buf ) - 1 ] = '\0';
356
netDevWifiBufP += strlen( buf ) + 1; /* move netDevWifiBufP to next line */
358
if ( sscanf( buf, devFormat, tag ) ) {
359
char * pos = strchr( tag, ':' );
361
char mon[ MON_SIZE ];
363
/*find and tag the corresponding NetDev as wifi enabled.
364
At the end of the loop, i is the index of the device.
365
This variable i is used in some macro */
366
for (i = 0 ; i < NetDevCnt ; ++i){
367
if ( strcmp(tag,NetDevs[ i ].name)==0){
368
NetDevs[ i ].isWifi = 1;
372
FORALLWIFI( REGISTERSENSOR );
374
FORALLWIFI( SETMEMBERZERO ); /* the variable i must point to the corrrect NetDevs[i]*/
378
/* Call processNetDev to elimitate initial peek values. */
382
void exitNetDev( void )
386
for ( i = 0; i < NetDevCnt; ++i ) {
387
char mon[ MON_SIZE ];
388
FORALL( UNREGISTERSENSOR );
389
if (NetDevs[ i ].isWifi)
390
FORALLWIFI( UNREGISTERSENSOR );
395
int updateNetDev( void )
397
/* We read the information about the network interfaces from
398
/proc/net/dev. The file should look like this:
400
Inter-| Receive | Transmit
401
face | bytes packets errs drop fifo frame compressed multicast| bytes packets errs drop fifo colls carrier compressed
402
lo:275135772 1437448 0 0 0 0 0 0 275135772 1437448 0 0 0 0 0 0
403
eth0:123648812 655251 0 0 0 0 0 0 246847871 889636 0 0 0 0 0 0
411
if ((fd = open("/proc/net/dev", O_RDONLY)) > 0) {
412
n = read(fd, NetDevBuf, NETDEVBUFSIZE - 1);
413
if (n == NETDEVBUFSIZE - 1 || n <= 0) {
414
log_error("Internal buffer too small to read \'/proc/net/dev\'");
419
gettimeofday(&currSampling, 0);
423
/* Calculate hash over the first 7 characters of each line starting
424
* after the first newline. This will detect whether any interfaces
425
* have either appeared or disappeared. */
426
for (p = NetDevBuf, hash = 0; *p; ++p)
428
for (++p; *p && *p != ':' && *p != '|'; ++p)
429
hash = ((hash << 6) + *p) % 390389;
431
if (OldHash != 0 && OldHash != hash) {
432
print_error("RECONFIGURE");
438
/* We read the information about the wifi from /proc/net/wireless and store it into NetDevWifiBuf */
439
if ( ( fd = open( "/proc/net/wireless", O_RDONLY ) ) < 0 ) {
440
/* /proc/net/wireless may not exist on some machines. */
441
NetDevWifiBuf[0]='\0';
442
} else if ( ( n = read( fd, NetDevWifiBuf, NETDEVBUFSIZE - 1 ) ) == NETDEVBUFSIZE - 1 ) {
443
log_error( "Internal buffer too small to read \'/proc/net/wireless\'" );
448
NetDevWifiBuf[ n ] = '\0';
455
void checkNetDev( void )
460
#define PRINTFUNC( a, b, c, d, e, f ) \
461
void printNetDev##a##0( const char* cmd ) \
468
beg = strchr( cmd, '/' ); \
469
beg = strchr( beg + 1, '/' ); \
470
end = strchr( beg + 1, '/' ); \
471
strncpy( dev, beg + 1, end - beg - 1 ); \
472
dev[ end - beg - 1 ] = '\0'; \
477
for ( i = 0; i < MAXNETDEVS; ++i ) \
478
if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \
479
if (f && timeInterval < 0.01) \
480
/*Time interval is very small. Can we really get an accurate value from this? Assume not*/ \
483
output( "%li\n", (long) \
484
( NetDevs[ i ].delta##a / ( NetDevs[ i ].a##Scale * timeInterval ) ) ); \
486
output( "%li\n", (long) NetDevs[ i ].a ); \
492
void printNetDev##a##0##Info( const char* cmd ) \
498
beg = strchr( cmd, '/' ); \
499
beg = strchr( beg + 1, '/' ); \
500
end = strchr( beg + 1, '/' ); \
501
strncpy( dev, beg + 1, end - beg - 1 ); \
502
dev[ end - beg - 1 ] = '\0'; \
505
output( "%s %s Rate\t0\t0\t1/s\n", dev, c); \
507
output( "%s %s Rate\t0\t0\t%s/s\n", dev, c, d ); \
509
output( "%s %s\t0\t0\t%s\n", dev, c, d ); \
511
void printNetDev##a##1( const char* cmd ) \
519
beg = strchr( cmd, '/' ); \
520
beg = strchr( beg + 1, '/' ); \
521
end = strchr( beg + 1, '/' ); \
522
strncpy( dev, beg + 1, end - beg - 1 ); \
523
dev[ end - beg - 1 ] = '\0'; \
528
for ( i = 0; i < MAXNETDEVS; ++i ) \
529
if ( strcmp( NetDevs[ i ].name, dev ) == 0) { \
530
output( "%li\n", (long) NetDevs[ i ].a / ( NetDevs[ i ].a##Scale) ); \
537
void printNetDev##a##1##Info( const char* cmd ) \
544
beg = strchr( cmd, '/' ); \
545
beg = strchr( beg + 1, '/' ); \
546
end = strchr( beg + 1, '/' ); \
547
strncpy( dev, beg + 1, end - beg - 1 ); \
548
dev[ end - beg - 1 ] = '\0'; \
550
output( "%s %s\t0\t0\t%s\n", dev, c, d ); \
556
FORALLWIFI( PRINTFUNC )