2
KSysGuard, the KDE System Guard
4
Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
6
Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
8
This program is free software; you can redistribute it and/or
9
modify it under the terms of version 2 of the GNU General Public
10
License as published by the Free Software Foundation.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30
#include <sys/types.h>
31
#include <sys/socket.h>
32
#include <sys/sockio.h>
40
#include "ksysguardd.h"
45
* available network interface statistics through kstat(3):
48
* ----------------------------------------------------------------------
49
* for the loopback interface(s) we can get
50
* ipackets # packets received
51
* opackets # packets sent
52
* in addition to those, for "real" interfaces:
53
* oerrors # xmit errors
54
* ierrors # recv errors
55
* macxmt_errors # xmit errors reported by hardware?
56
* macrcv_errors # recv errors reported by hardware?
57
* opackets64 same as opackets (64bit)
58
* ipackets64 same as ipackets (64bit)
60
* rbytes # bytes received
61
* obytes64 same as obytes (64bit)
62
* rbytes64 same as ibytes (64bit)
63
* collisions # collisions
64
* multixmt # multicasts sent?
65
* multircv # multicasts received?
66
* brdcstxmt # broadcasts transmitted
67
* brdcstrcv # broadcasts received
74
* oflo # overflow errors
75
* uflo # underflow errors
85
* xmtretry # xmit retries?
86
* ifspeed interface speed: 10000000 for 10BaseT
87
* duplex "half" or "full"
88
* media e.g. "PHY/MII"
89
* promisc promiscuous mode (e.g. "off")
99
unsigned long ipackets;
100
unsigned long OLDipackets;
101
unsigned long opackets;
102
unsigned long OLDopackets;
103
unsigned long rbytes;
104
unsigned long OLDrbytes;
105
unsigned long obytes;
106
unsigned long OLDobytes;
107
unsigned long ierrors;
108
unsigned long OLDierrors;
109
unsigned long oerrors;
110
unsigned long OLDoerrors;
111
unsigned long collisions;
112
unsigned long OLDcollisions;
113
unsigned long multixmt;
114
unsigned long OLDmultixmt;
115
unsigned long multircv;
116
unsigned long OLDmultircv;
117
unsigned long brdcstxmt;
118
unsigned long OLDbrdcstxmt;
119
unsigned long brdcstrcv;
120
unsigned long OLDbrdcstrcv;
125
#define MAXNETDEVS 64
126
static NetDevInfo IfInfo[MAXNETDEVS];
128
static int NetDevCount;
129
static float timeInterval = 0;
130
static struct timeval lastSampling;
131
static struct timeval currSampling;
134
* insertnetdev() -- insert device name & flags into our list
136
int insertnetdev( const char *name, const short flags ) {
141
* interface "aliases" don't seem to have
142
* separate kstat statistics, so we skip them
144
if( strchr( name, (int) ':' ) != NULL )
147
while( (i < NetDevCount) && (strcmp( IfInfo[i].Name, name ) != 0) ) {
148
if( strcmp( IfInfo[i].Name, name ) == 0 )
156
IfInfo[i].Name = strdup( name );
157
IfInfo[i].flags = flags;
158
IfInfo[i].ipackets = 0L;
159
IfInfo[i].OLDipackets = 0L;
160
IfInfo[i].opackets = 0L;
161
IfInfo[i].OLDopackets = 0L;
162
IfInfo[i].ierrors = 0L;
163
IfInfo[i].OLDierrors = 0L;
164
IfInfo[i].oerrors = 0L;
165
IfInfo[i].OLDoerrors = 0L;
166
IfInfo[i].collisions = 0L;
167
IfInfo[i].OLDcollisions = 0L;
168
IfInfo[i].multixmt = 0L;
169
IfInfo[i].OLDmultixmt = 0L;
170
IfInfo[i].multircv = 0L;
171
IfInfo[i].OLDmultircv = 0L;
172
IfInfo[i].brdcstxmt = 0L;
173
IfInfo[i].OLDbrdcstxmt = 0L;
174
IfInfo[i].brdcstrcv = 0L;
175
IfInfo[i].OLDbrdcstrcv = 0L;
178
/* XXX: need sanity checks! */
183
* getnetdevlist() -- get a list of all "up" interfaces
185
int getnetdevlist( void ) {
194
if( (fd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) {
199
* get the interface list via iotl( SIOCGIFCONF )
200
* the following algorithm based on ideas from W.R. Stevens'
201
* "UNIX Network Programming", Vol. 1:
202
* Since the ioctl may return 0, indicating success, even if the
203
* ifreq buffer was too small, we have to make sure, it didn't
204
* get truncated by comparing our initial size guess with the
205
* actual returned size.
208
buffsize = NBUFFERS * sizeof( struct ifreq );
210
if( (ifc.ifc_buf = malloc( buffsize )) == NULL )
213
ifc.ifc_len = buffsize;
214
if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) {
215
if( errno != EINVAL || prevsize != 0 ) {
220
if( ifc.ifc_len == prevsize )
223
prevsize = ifc.ifc_len;
226
* initial buffer guessed too small, allocate a bigger one
229
buffsize = (NBUFFERS + 10) * sizeof( struct ifreq );
233
* get the names for all interfaces which are configured "up"
234
* we're not interested in the ifc data (address), so we reuse the
235
* same structure (with ifc.len set) for the next ioctl()
237
prevCount = NetDevCount;
238
for( ifr = (struct ifreq *) ifc.ifc_buf;
239
ifr < (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
241
if( ioctl( fd, SIOCGIFFLAGS, ifr ) < 0 ) {
245
if( ifr->ifr_flags & IFF_UP )
246
insertnetdev( ifr->ifr_name, ifr->ifr_flags );
251
if( (prevCount > 0) && (prevCount != NetDevCount) ) {
252
print_error( "RECONFIGURE" );
253
prevCount = NetDevCount;
256
return( NetDevCount );
259
void initNetDev( struct SensorModul* sm ) {
265
for( i = 0; i < NetDevCount; i++ ) {
266
sprintf( mon, "network/interfaces/%s/receiver/packets", IfInfo[i].Name );
267
registerMonitor( mon, "integer",
268
printIPackets, printIPacketsInfo, sm );
269
sprintf( mon, "network/interfaces/%s/transmitter/packets", IfInfo[i].Name );
270
registerMonitor( mon, "integer",
271
printOPackets, printOPacketsInfo, sm );
273
* if this isn't a loopback interface,
274
* register additional monitors
276
if( ! (IfInfo[i].flags & IFF_LOOPBACK) ) {
280
sprintf( mon, "network/interfaces/%s/receiver/errors",
282
registerMonitor( mon, "integer",
283
printIErrors, printIErrorsInfo, sm );
287
sprintf( mon, "network/interfaces/%s/transmitter/errors",
289
registerMonitor( mon, "integer",
290
printOErrors, printOErrorsInfo, sm );
294
sprintf( mon, "network/interfaces/%s/transmitter/collisions",
296
registerMonitor( mon, "integer",
297
printCollisions, printCollisionsInfo, sm );
301
sprintf( mon, "network/interfaces/%s/transmitter/multicast",
303
registerMonitor( mon, "integer",
304
printMultiXmits, printMultiXmitsInfo, sm );
308
sprintf( mon, "network/interfaces/%s/receiver/multicast",
310
registerMonitor( mon, "integer",
311
printMultiRecvs, printMultiRecvsInfo, sm );
315
sprintf( mon, "network/interfaces/%s/transmitter/broadcast",
317
registerMonitor( mon, "integer",
318
printBcastXmits, printBcastXmitsInfo, sm );
322
sprintf( mon, "network/interfaces/%s/receiver/broadcast",
324
registerMonitor( mon, "integer",
325
printBcastRecvs, printBcastRecvsInfo, sm );
328
* Transmitted/Received Data.
330
sprintf( mon, "network/interfaces/%s/receiver/data",
332
registerMonitor( mon, "integer",
333
printRBytes, printRBytesInfo, sm );
334
sprintf( mon, "network/interfaces/%s/transmitter/data",
336
registerMonitor( mon, "integer",
337
printOBytes, printOBytesInfo, sm );
340
gettimeofday(&lastSampling, 0);
344
void exitNetDev( void ) {
347
int updateNetDev( void ) {
352
kstat_named_t *kdata;
356
* get a kstat handle and update the user's kstat chain
358
if( (kctl = kstat_open()) == NULL )
360
while( kstat_chain_update( kctl ) != 0 )
363
gettimeofday(&currSampling, 0);
364
for( i = 0; i < NetDevCount; i++ ) {
369
* chop off the trailing interface no
371
name = strdup( IfInfo[i].Name );
372
ptr = name + strlen( name ) - 1;
373
while( (ptr > name) && isdigit( (int) *ptr ) ) {
379
* find the appropriate statistics; e.g. 'kstat e1000g:0:e1000g0'
381
if( (ksp = kstat_lookup( kctl, name, 0, IfInfo[i].Name )) == NULL ) {
383
* try module "link"; e.g. 'kstat link:0:e1000g0'
385
if( (ksp = kstat_lookup( kctl, "link", 0, IfInfo[i].Name )) == NULL ) {
390
if( kstat_read( kctl, ksp, NULL ) == -1 ) {
397
* lookup & store the data
399
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ipackets" );
400
if( kdata != NULL ) {
401
IfInfo[i].OLDipackets = IfInfo[i].ipackets;
402
IfInfo[i].ipackets = kdata->value.ul;
404
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "opackets" );
405
if( kdata != NULL ) {
406
IfInfo[i].OLDopackets = IfInfo[i].opackets;
407
IfInfo[i].opackets = kdata->value.ul;
409
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ierrors" );
410
if( kdata != NULL ) {
411
IfInfo[i].OLDierrors = IfInfo[i].ierrors;
412
IfInfo[i].ierrors = kdata->value.ul;
414
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "oerrors" );
415
if( kdata != NULL ) {
416
IfInfo[i].OLDoerrors = IfInfo[i].oerrors;
417
IfInfo[i].oerrors = kdata->value.ul;
419
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "collisions" );
420
if( kdata != NULL ) {
421
IfInfo[i].OLDcollisions = IfInfo[i].collisions;
422
IfInfo[i].collisions = kdata->value.ul;
424
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multixmt" );
425
if( kdata != NULL ) {
426
IfInfo[i].OLDmultixmt = IfInfo[i].multixmt;
427
IfInfo[i].multixmt = kdata->value.ul;
429
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multircv" );
430
if( kdata != NULL ) {
431
IfInfo[i].OLDmultircv = IfInfo[i].multircv;
432
IfInfo[i].multircv = kdata->value.ul;
434
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstxmt" );
435
if( kdata != NULL ) {
436
IfInfo[i].OLDbrdcstxmt = IfInfo[i].brdcstxmt;
437
IfInfo[i].brdcstxmt = kdata->value.ul;
439
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstrcv" );
440
if( kdata != NULL ) {
441
IfInfo[i].OLDbrdcstrcv = IfInfo[i].brdcstrcv;
442
IfInfo[i].brdcstrcv = kdata->value.ul;
444
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "rbytes" );
445
if( kdata != NULL ) {
446
IfInfo[i].OLDrbytes = IfInfo[i].rbytes;
447
IfInfo[i].rbytes = kdata->value.ul;
449
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "obytes" );
450
if( kdata != NULL ) {
451
IfInfo[i].OLDobytes = IfInfo[i].obytes;
452
IfInfo[i].obytes = kdata->value.ul;
457
timeInterval = currSampling.tv_sec - lastSampling.tv_sec +
458
( currSampling.tv_usec - lastSampling.tv_usec ) / 1000000.0;
459
lastSampling = currSampling;
460
#endif /* ! HAVE_KSTAT */
465
void printIPacketsInfo( const char *cmd ) {
466
fprintf(CurrentClient, "Received Packets\t0\t0\tPackets\n" );
469
void printIPackets( const char *cmd ) {
471
char *cmdcopy = strdup( cmd );
475
ptr = strchr( cmdcopy, (int) '/' );
477
ptr = strchr( name, (int) '/' );
479
ptr = strchr( name, (int) '/' );
482
for( i = 0; i < NetDevCount; i++ ) {
483
if( (IfInfo[i].OLDipackets > 0)
484
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
485
fprintf(CurrentClient, "%ld\n",
486
IfInfo[i].ipackets - IfInfo[i].OLDipackets);
492
fprintf(CurrentClient, "0\n" );
495
void printOPacketsInfo( const char *cmd ) {
496
fprintf(CurrentClient, "Transmitted Packets\t0\t0\tPackets\n" );
499
void printOPackets( const char *cmd ) {
501
char *cmdcopy = strdup( cmd );
505
ptr = strchr( cmdcopy, (int) '/' );
507
ptr = strchr( name, (int) '/' );
509
ptr = strchr( name, (int) '/' );
512
for( i = 0; i < NetDevCount; i++ ) {
513
if( (IfInfo[i].OLDopackets > 0)
514
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
515
fprintf(CurrentClient, "%ld\n",
516
IfInfo[i].opackets - IfInfo[i].OLDopackets );
522
fprintf(CurrentClient, "0\n" );
525
void printRBytesInfo( const char *cmd ) {
526
fprintf(CurrentClient, "Received Data\t0\t0\tKB/s\n" );
529
void printRBytes( const char *cmd ) {
531
char *cmdcopy = strdup( cmd );
535
ptr = strchr( cmdcopy, (int) '/' );
537
ptr = strchr( name, (int) '/' );
539
ptr = strchr( name, (int) '/' );
542
for( i = 0; i < NetDevCount; i++ ) {
543
if( (IfInfo[i].OLDrbytes > 0)
544
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
545
long rate = ((float)(IfInfo[i].rbytes - IfInfo[i].OLDrbytes) / timeInterval) / 1024;
546
fprintf(CurrentClient, "%ld\n", rate);
552
fprintf(CurrentClient, "0\n" );
555
void printOBytesInfo( const char *cmd ) {
556
fprintf(CurrentClient, "Transmitted Data\t0\t0\tKB/s\n" );
559
void printOBytes( const char *cmd ) {
561
char *cmdcopy = strdup( cmd );
565
ptr = strchr( cmdcopy, (int) '/' );
567
ptr = strchr( name, (int) '/' );
569
ptr = strchr( name, (int) '/' );
572
for( i = 0; i < NetDevCount; i++ ) {
573
if( (IfInfo[i].OLDobytes > 0)
574
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
575
long rate = ((float)(IfInfo[i].obytes - IfInfo[i].OLDobytes) / timeInterval) / 1024;
576
fprintf(CurrentClient, "%ld\n", rate);
582
fprintf(CurrentClient, "0\n" );
585
void printIErrorsInfo( const char *cmd ) {
586
fprintf(CurrentClient, "Input Errors\t0\t0\tPackets\n" );
589
void printIErrors( const char *cmd ) {
591
char *cmdcopy = strdup( cmd );
595
ptr = strchr( cmdcopy, (int) '/' );
597
ptr = strchr( name, (int) '/' );
599
ptr = strchr( name, (int) '/' );
602
for( i = 0; i < NetDevCount; i++ ) {
603
if( (IfInfo[i].OLDierrors > 0)
604
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
605
fprintf(CurrentClient, "%ld\n",
606
IfInfo[i].ierrors - IfInfo[i].OLDierrors );
612
fprintf(CurrentClient, "0\n" );
615
void printOErrorsInfo( const char *cmd ) {
616
fprintf(CurrentClient, "Output Errors\t0\t0\tPackets\n" );
619
void printOErrors( const char *cmd ) {
621
char *cmdcopy = strdup( cmd );
625
ptr = strchr( cmdcopy, (int) '/' );
627
ptr = strchr( name, (int) '/' );
629
ptr = strchr( name, (int) '/' );
632
for( i = 0; i < NetDevCount; i++ ) {
633
if( (IfInfo[i].OLDoerrors > 0)
634
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
635
fprintf(CurrentClient, "%ld\n",
636
IfInfo[i].oerrors - IfInfo[i].OLDoerrors );
642
fprintf(CurrentClient, "0\n" );
645
void printCollisionsInfo( const char *cmd ) {
646
fprintf(CurrentClient, "Collisions\t0\t0\tPackets\n" );
649
void printCollisions( const char *cmd ) {
651
char *cmdcopy = strdup( cmd );
655
ptr = strchr( cmdcopy, (int) '/' );
657
ptr = strchr( name, (int) '/' );
659
ptr = strchr( name, (int) '/' );
662
for( i = 0; i < NetDevCount; i++ ) {
663
if( (IfInfo[i].OLDcollisions > 0)
664
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
665
fprintf(CurrentClient, "%ld\n",
666
IfInfo[i].collisions - IfInfo[i].OLDcollisions );
672
fprintf(CurrentClient, "0\n" );
675
void printMultiXmitsInfo( const char *cmd ) {
676
fprintf(CurrentClient, "Multicasts Sent\t0\t0\tPackets\n" );
679
void printMultiXmits( const char *cmd ) {
681
char *cmdcopy = strdup( cmd );
685
ptr = strchr( cmdcopy, (int) '/' );
687
ptr = strchr( name, (int) '/' );
689
ptr = strchr( name, (int) '/' );
692
for( i = 0; i < NetDevCount; i++ ) {
693
if( (IfInfo[i].OLDmultixmt > 0)
694
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
695
fprintf(CurrentClient, "%ld\n",
696
IfInfo[i].multixmt - IfInfo[i].OLDmultixmt );
702
fprintf(CurrentClient, "0\n" );
705
void printMultiRecvsInfo( const char *cmd ) {
706
fprintf(CurrentClient, "Multicasts Received\t0\t0\tPackets\n" );
709
void printMultiRecvs( const char *cmd ) {
711
char *cmdcopy = strdup( cmd );
715
ptr = strchr( cmdcopy, (int) '/' );
717
ptr = strchr( name, (int) '/' );
719
ptr = strchr( name, (int) '/' );
722
for( i = 0; i < NetDevCount; i++ ) {
723
if( (IfInfo[i].OLDmultircv > 0)
724
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
725
fprintf(CurrentClient, "%ld\n",
726
IfInfo[i].multircv - IfInfo[i].OLDmultircv );
732
fprintf(CurrentClient, "0\n" );
735
void printBcastXmitsInfo( const char *cmd ) {
736
fprintf(CurrentClient, "Broadcasts Sent\t0\t0\tPackets\n" );
739
void printBcastXmits( const char *cmd ) {
741
char *cmdcopy = strdup( cmd );
745
ptr = strchr( cmdcopy, (int) '/' );
747
ptr = strchr( name, (int) '/' );
749
ptr = strchr( name, (int) '/' );
752
for( i = 0; i < NetDevCount; i++ ) {
753
if( (IfInfo[i].OLDbrdcstxmt > 0)
754
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
755
fprintf(CurrentClient, "%ld\n",
756
IfInfo[i].brdcstxmt - IfInfo[i].OLDbrdcstxmt );
762
fprintf(CurrentClient, "0\n" );
765
void printBcastRecvsInfo( const char *cmd ) {
766
fprintf(CurrentClient, "Broadcasts Received\t0\t0\tPackets\n" );
769
void printBcastRecvs( const char *cmd ) {
771
char *cmdcopy = strdup( cmd );
775
ptr = strchr( cmdcopy, (int) '/' );
777
ptr = strchr( name, (int) '/' );
779
ptr = strchr( name, (int) '/' );
782
for( i = 0; i < NetDevCount; i++ ) {
783
if( (IfInfo[i].OLDbrdcstrcv > 0)
784
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
785
fprintf(CurrentClient, "%ld\n",
786
IfInfo[i].brdcstrcv - IfInfo[i].OLDbrdcstrcv );
792
fprintf(CurrentClient, "0\n" );