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>
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 ierrors
;
104 unsigned long OLDierrors
;
105 unsigned long oerrors
;
106 unsigned long OLDoerrors
;
107 unsigned long collisions
;
108 unsigned long OLDcollisions
;
109 unsigned long multixmt
;
110 unsigned long OLDmultixmt
;
111 unsigned long multircv
;
112 unsigned long OLDmultircv
;
113 unsigned long brdcstxmt
;
114 unsigned long OLDbrdcstxmt
;
115 unsigned long brdcstrcv
;
116 unsigned long OLDbrdcstrcv
;
121 #define MAXNETDEVS 64
122 static NetDevInfo IfInfo
[MAXNETDEVS
];
124 static int NetDevCount
;
127 * insertnetdev() -- insert device name & flags into our list
129 int insertnetdev( const char *name
, const short flags
) {
134 * interface "aliases" don't seem to have
135 * separate kstat statistics, so we skip them
137 if( strchr( name
, (int) ':' ) != NULL
)
140 while( (i
< NetDevCount
) && (strcmp( IfInfo
[i
].Name
, name
) != 0) ) {
141 if( strcmp( IfInfo
[i
].Name
, name
) == 0 )
149 IfInfo
[i
].Name
= strdup( name
);
150 IfInfo
[i
].flags
= flags
;
151 IfInfo
[i
].ipackets
= 0L;
152 IfInfo
[i
].OLDipackets
= 0L;
153 IfInfo
[i
].opackets
= 0L;
154 IfInfo
[i
].OLDopackets
= 0L;
155 IfInfo
[i
].ierrors
= 0L;
156 IfInfo
[i
].OLDierrors
= 0L;
157 IfInfo
[i
].oerrors
= 0L;
158 IfInfo
[i
].OLDoerrors
= 0L;
159 IfInfo
[i
].collisions
= 0L;
160 IfInfo
[i
].OLDcollisions
= 0L;
161 IfInfo
[i
].multixmt
= 0L;
162 IfInfo
[i
].OLDmultixmt
= 0L;
163 IfInfo
[i
].multircv
= 0L;
164 IfInfo
[i
].OLDmultircv
= 0L;
165 IfInfo
[i
].brdcstxmt
= 0L;
166 IfInfo
[i
].OLDbrdcstxmt
= 0L;
167 IfInfo
[i
].brdcstrcv
= 0L;
168 IfInfo
[i
].OLDbrdcstrcv
= 0L;
171 /* XXX: need sanity checks! */
176 * getnetdevlist() -- get a list of all "up" interfaces
178 int getnetdevlist( void ) {
187 if( (fd
= socket( PF_INET
, SOCK_DGRAM
, 0 )) < 0 ) {
192 * get the interface list via iotl( SIOCGIFCONF )
193 * the following algorithm based on ideas from W.R. Stevens'
194 * "UNIX Network Programming", Vol. 1:
195 * Since the ioctl may return 0, indicating success, even if the
196 * ifreq buffer was too small, we have to make sure, it didn't
197 * get truncated by comparing our initial size guess with the
198 * actual returned size.
201 buffsize
= NBUFFERS
* sizeof( struct ifreq
);
203 if( (ifc
.ifc_buf
= malloc( buffsize
)) == NULL
)
206 ifc
.ifc_len
= buffsize
;
207 if( ioctl( fd
, SIOCGIFCONF
, &ifc
) < 0 ) {
208 if( errno
!= EINVAL
|| prevsize
!= 0 ) {
213 if( ifc
.ifc_len
== prevsize
)
216 prevsize
= ifc
.ifc_len
;
219 * initial buffer guessed too small, allocate a bigger one
222 buffsize
= (NBUFFERS
+ 10) * sizeof( struct ifreq
);
226 * get the names for all interfaces which are configured "up"
227 * we're not interested in the ifc data (address), so we reuse the
228 * same structure (with ifc.len set) for the next ioctl()
230 prevCount
= NetDevCount
;
231 for( ifr
= (struct ifreq
*) ifc
.ifc_buf
;
232 ifr
< (struct ifreq
*) (ifc
.ifc_buf
+ ifc
.ifc_len
);
234 if( ioctl( fd
, SIOCGIFFLAGS
, ifr
) < 0 ) {
238 if( ifr
->ifr_flags
& IFF_UP
)
239 insertnetdev( ifr
->ifr_name
, ifr
->ifr_flags
);
244 if( (prevCount
> 0) && (prevCount
!= NetDevCount
) ) {
245 print_error( "RECONFIGURE\n" );
246 prevCount
= NetDevCount
;
249 return( NetDevCount
);
252 void initNetDev( struct SensorModul
* sm
) {
258 for( i
= 0; i
< NetDevCount
; i
++ ) {
259 sprintf( mon
, "network/%s/ipackets", IfInfo
[i
].Name
);
260 registerMonitor( mon
, "integer",
261 printIPackets
, printIPacketsInfo
, sm
);
262 sprintf( mon
, "network/%s/opackets", IfInfo
[i
].Name
);
263 registerMonitor( mon
, "integer",
264 printOPackets
, printOPacketsInfo
, sm
);
266 * if this isn't a loopback interface,
267 * register additional monitors
269 if( ! (IfInfo
[i
].flags
& IFF_LOOPBACK
) ) {
273 sprintf( mon
, "network/%s/ierrors",
275 registerMonitor( mon
, "integer",
276 printIErrors
, printIErrorsInfo
, sm
);
280 sprintf( mon
, "network/%s/oerrors",
282 registerMonitor( mon
, "integer",
283 printOErrors
, printOErrorsInfo
, sm
);
287 sprintf( mon
, "network/%s/collisions",
289 registerMonitor( mon
, "integer",
290 printCollisions
, printCollisionsInfo
, sm
);
294 sprintf( mon
, "network/%s/multixmt",
296 registerMonitor( mon
, "integer",
297 printMultiXmits
, printMultiXmitsInfo
, sm
);
301 sprintf( mon
, "network/%s/multircv",
303 registerMonitor( mon
, "integer",
304 printMultiRecvs
, printMultiRecvsInfo
, sm
);
308 sprintf( mon
, "network/%s/brdcstxmt",
310 registerMonitor( mon
, "integer",
311 printBcastXmits
, printBcastXmitsInfo
, sm
);
315 sprintf( mon
, "network/%s/brdcstrcv",
317 registerMonitor( mon
, "integer",
318 printBcastRecvs
, printBcastRecvsInfo
, sm
);
324 void exitNetDev( void ) {
327 int updateNetDev( void ) {
332 kstat_named_t
*kdata
;
336 * get a kstat handle and update the user's kstat chain
338 if( (kctl
= kstat_open()) == NULL
)
340 while( kstat_chain_update( kctl
) != 0 )
343 for( i
= 0; i
< NetDevCount
; i
++ ) {
348 * chop off the trailing interface no
350 name
= strdup( IfInfo
[i
].Name
);
351 ptr
= name
+ strlen( name
) - 1;
352 while( (ptr
> name
) && isdigit( (int) *ptr
) ) {
358 * traverse the kstat chain
359 * to find the appropriate statistics
361 if( (ksp
= kstat_lookup( kctl
,
362 name
, 0, IfInfo
[i
].Name
)) == NULL
) {
366 if( kstat_read( kctl
, ksp
, NULL
) == -1 ) {
373 * lookup & store the data
375 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "ipackets" );
376 if( kdata
!= NULL
) {
377 IfInfo
[i
].OLDipackets
= IfInfo
[i
].ipackets
;
378 IfInfo
[i
].ipackets
= kdata
->value
.ul
;
380 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "opackets" );
381 if( kdata
!= NULL
) {
382 IfInfo
[i
].OLDopackets
= IfInfo
[i
].opackets
;
383 IfInfo
[i
].opackets
= kdata
->value
.ul
;
385 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "ierrors" );
386 if( kdata
!= NULL
) {
387 IfInfo
[i
].OLDierrors
= IfInfo
[i
].ierrors
;
388 IfInfo
[i
].ierrors
= kdata
->value
.ul
;
390 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "oerrors" );
391 if( kdata
!= NULL
) {
392 IfInfo
[i
].OLDoerrors
= IfInfo
[i
].oerrors
;
393 IfInfo
[i
].oerrors
= kdata
->value
.ul
;
395 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "collisions" );
396 if( kdata
!= NULL
) {
397 IfInfo
[i
].OLDcollisions
= IfInfo
[i
].collisions
;
398 IfInfo
[i
].collisions
= kdata
->value
.ul
;
400 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "multixmt" );
401 if( kdata
!= NULL
) {
402 IfInfo
[i
].OLDmultixmt
= IfInfo
[i
].multixmt
;
403 IfInfo
[i
].multixmt
= kdata
->value
.ul
;
405 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "multircv" );
406 if( kdata
!= NULL
) {
407 IfInfo
[i
].OLDmultircv
= IfInfo
[i
].multircv
;
408 IfInfo
[i
].multircv
= kdata
->value
.ul
;
410 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "brdcstxmt" );
411 if( kdata
!= NULL
) {
412 IfInfo
[i
].OLDbrdcstxmt
= IfInfo
[i
].brdcstxmt
;
413 IfInfo
[i
].brdcstxmt
= kdata
->value
.ul
;
415 kdata
= (kstat_named_t
*) kstat_data_lookup( ksp
, "brdcstrcv" );
416 if( kdata
!= NULL
) {
417 IfInfo
[i
].OLDbrdcstrcv
= IfInfo
[i
].brdcstrcv
;
418 IfInfo
[i
].brdcstrcv
= kdata
->value
.ul
;
423 #endif /* ! HAVE_KSTAT */
428 void printIPacketsInfo( const char *cmd
) {
429 fprintf(CurrentClient
, "Received Packets\t0\t0\tPackets\n" );
432 void printIPackets( const char *cmd
) {
434 char *cmdcopy
= strdup( cmd
);
438 ptr
= strchr( cmdcopy
, (int) '/' );
440 ptr
= strchr( name
, (int) '/' );
443 for( i
= 0; i
< NetDevCount
; i
++ ) {
444 if( (IfInfo
[i
].OLDipackets
> 0)
445 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
446 fprintf(CurrentClient
, "%ld\n",
447 IfInfo
[i
].ipackets
- IfInfo
[i
].OLDipackets
);
453 fprintf(CurrentClient
, "0\n" );
456 void printOPacketsInfo( const char *cmd
) {
457 fprintf(CurrentClient
, "Transmitted Packets\t0\t0\tPackets\n" );
460 void printOPackets( const char *cmd
) {
462 char *cmdcopy
= strdup( cmd
);
466 ptr
= strchr( cmdcopy
, (int) '/' );
468 ptr
= strchr( name
, (int) '/' );
471 for( i
= 0; i
< NetDevCount
; i
++ ) {
472 if( (IfInfo
[i
].OLDopackets
> 0)
473 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
474 fprintf(CurrentClient
, "%ld\n",
475 IfInfo
[i
].opackets
- IfInfo
[i
].OLDopackets
);
481 fprintf(CurrentClient
, "0\n" );
484 void printIErrorsInfo( const char *cmd
) {
485 fprintf(CurrentClient
, "Input Errors\t0\t0\tPackets\n" );
488 void printIErrors( const char *cmd
) {
490 char *cmdcopy
= strdup( cmd
);
494 ptr
= strchr( cmdcopy
, (int) '/' );
496 ptr
= strchr( name
, (int) '/' );
499 for( i
= 0; i
< NetDevCount
; i
++ ) {
500 if( (IfInfo
[i
].OLDierrors
> 0)
501 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
502 fprintf(CurrentClient
, "%ld\n",
503 IfInfo
[i
].ierrors
- IfInfo
[i
].OLDierrors
);
509 fprintf(CurrentClient
, "0\n" );
512 void printOErrorsInfo( const char *cmd
) {
513 fprintf(CurrentClient
, "Output Errors\t0\t0\tPackets\n" );
516 void printOErrors( const char *cmd
) {
518 char *cmdcopy
= strdup( cmd
);
522 ptr
= strchr( cmdcopy
, (int) '/' );
524 ptr
= strchr( name
, (int) '/' );
527 for( i
= 0; i
< NetDevCount
; i
++ ) {
528 if( (IfInfo
[i
].OLDoerrors
> 0)
529 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
530 fprintf(CurrentClient
, "%ld\n",
531 IfInfo
[i
].oerrors
- IfInfo
[i
].OLDoerrors
);
537 fprintf(CurrentClient
, "0\n" );
540 void printCollisionsInfo( const char *cmd
) {
541 fprintf(CurrentClient
, "Collisions\t0\t0\tPackets\n" );
544 void printCollisions( const char *cmd
) {
546 char *cmdcopy
= strdup( cmd
);
550 ptr
= strchr( cmdcopy
, (int) '/' );
552 ptr
= strchr( name
, (int) '/' );
555 for( i
= 0; i
< NetDevCount
; i
++ ) {
556 if( (IfInfo
[i
].OLDcollisions
> 0)
557 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
558 fprintf(CurrentClient
, "%ld\n",
559 IfInfo
[i
].collisions
- IfInfo
[i
].OLDcollisions
);
565 fprintf(CurrentClient
, "0\n" );
568 void printMultiXmitsInfo( const char *cmd
) {
569 fprintf(CurrentClient
, "Multicasts Sent\t0\t0\tPackets\n" );
572 void printMultiXmits( const char *cmd
) {
574 char *cmdcopy
= strdup( cmd
);
578 ptr
= strchr( cmdcopy
, (int) '/' );
580 ptr
= strchr( name
, (int) '/' );
583 for( i
= 0; i
< NetDevCount
; i
++ ) {
584 if( (IfInfo
[i
].OLDmultixmt
> 0)
585 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
586 fprintf(CurrentClient
, "%ld\n",
587 IfInfo
[i
].multixmt
- IfInfo
[i
].OLDmultixmt
);
593 fprintf(CurrentClient
, "0\n" );
596 void printMultiRecvsInfo( const char *cmd
) {
597 fprintf(CurrentClient
, "Multicasts Received\t0\t0\tPackets\n" );
600 void printMultiRecvs( const char *cmd
) {
602 char *cmdcopy
= strdup( cmd
);
606 ptr
= strchr( cmdcopy
, (int) '/' );
608 ptr
= strchr( name
, (int) '/' );
611 for( i
= 0; i
< NetDevCount
; i
++ ) {
612 if( (IfInfo
[i
].OLDmultircv
> 0)
613 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
614 fprintf(CurrentClient
, "%ld\n",
615 IfInfo
[i
].multircv
- IfInfo
[i
].OLDmultircv
);
621 fprintf(CurrentClient
, "0\n" );
624 void printBcastXmitsInfo( const char *cmd
) {
625 fprintf(CurrentClient
, "Broadcasts Sent\t0\t0\tPackets\n" );
628 void printBcastXmits( const char *cmd
) {
630 char *cmdcopy
= strdup( cmd
);
634 ptr
= strchr( cmdcopy
, (int) '/' );
636 ptr
= strchr( name
, (int) '/' );
639 for( i
= 0; i
< NetDevCount
; i
++ ) {
640 if( (IfInfo
[i
].OLDbrdcstxmt
> 0)
641 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
642 fprintf(CurrentClient
, "%ld\n",
643 IfInfo
[i
].brdcstxmt
- IfInfo
[i
].OLDbrdcstxmt
);
649 fprintf(CurrentClient
, "0\n" );
652 void printBcastRecvsInfo( const char *cmd
) {
653 fprintf(CurrentClient
, "Broadcasts Received\t0\t0\tPackets\n" );
656 void printBcastRecvs( const char *cmd
) {
658 char *cmdcopy
= strdup( cmd
);
662 ptr
= strchr( cmdcopy
, (int) '/' );
664 ptr
= strchr( name
, (int) '/' );
667 for( i
= 0; i
< NetDevCount
; i
++ ) {
668 if( (IfInfo
[i
].OLDbrdcstrcv
> 0)
669 && (strcmp( IfInfo
[i
].Name
, name
) == 0) ) {
670 fprintf(CurrentClient
, "%ld\n",
671 IfInfo
[i
].brdcstrcv
- IfInfo
[i
].OLDbrdcstrcv
);
677 fprintf(CurrentClient
, "0\n" );