Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / ksysguard / ksysguardd / Tru64 / NetDev.c
blob0699b929aa0d4f2d1b236ea15b8c581a554d0338
1 /*
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.
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stropts.h>
29 #include <ctype.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <net/if.h>
34 #include "config.h"
36 #ifdef HAVE_KSTAT
37 #include <kstat.h>
38 #endif
40 #include "ksysguardd.h"
41 #include "Command.h"
42 #include "NetDev.h"
45 * available network interface statistics through kstat(3):
47 * kstat name value
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)
59 * obytes # bytes sent
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
68 * unknowns
69 * blocked
70 * ex_collisions
71 * defer_xmts
72 * align_errors
73 * fcs_errors
74 * oflo # overflow errors
75 * uflo # underflow errors
76 * runt_errors
77 * missed
78 * tx_late_collisions
79 * carrier_errors
80 * noxmtbuf
81 * norcvbuf
82 * xmt_badinterp
83 * rcv_badinterp
84 * intr # interrupts?
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")
90 * first_collisions
91 * multi_collisions
92 * sqe_errors
93 * toolong_errors
96 typedef struct {
97 char *Name;
98 short flags;
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;
117 } NetDevInfo;
120 #define NBUFFERS 64
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 ) {
131 int i = 0;
134 * interface "aliases" don't seem to have
135 * separate kstat statistics, so we skip them
137 if( strchr( name, (int) ':' ) != NULL )
138 return( 0 );
140 while( (i < NetDevCount) && (strcmp( IfInfo[i].Name, name ) != 0) ) {
141 if( strcmp( IfInfo[i].Name, name ) == 0 )
142 return( 0 );
143 i++;
147 * init new slot
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;
169 NetDevCount = ++i;
171 /* XXX: need sanity checks! */
172 return( 0 );
176 * getnetdevlist() -- get a list of all "up" interfaces
178 int getnetdevlist( void ) {
180 int fd;
181 int buffsize;
182 int prevsize;
183 int prevCount;
184 struct ifconf ifc;
185 struct ifreq *ifr;
187 if( (fd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) {
188 return( -1 );
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.
200 prevsize = 0;
201 buffsize = NBUFFERS * sizeof( struct ifreq );
202 while( 1 ) {
203 if( (ifc.ifc_buf = malloc( buffsize )) == NULL )
204 return( -1 );
206 ifc.ifc_len = buffsize;
207 if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) {
208 if( errno != EINVAL || prevsize != 0 ) {
209 free( ifc.ifc_buf );
210 return( -1 );
212 } else {
213 if( ifc.ifc_len == prevsize )
214 /* success */
215 break;
216 prevsize = ifc.ifc_len;
219 * initial buffer guessed too small, allocate a bigger one
221 free( ifc.ifc_buf );
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);
233 ifr++ ) {
234 if( ioctl( fd, SIOCGIFFLAGS, ifr ) < 0 ) {
235 free( ifc.ifc_buf );
236 return( -1 );
238 if( ifr->ifr_flags & IFF_UP )
239 insertnetdev( ifr->ifr_name, ifr->ifr_flags );
241 free( ifc.ifc_buf );
242 close( fd );
244 if( (prevCount > 0) && (prevCount != NetDevCount) ) {
245 print_error( "RECONFIGURE\n" );
246 prevCount = NetDevCount;
249 return( NetDevCount );
252 void initNetDev( struct SensorModul* sm ) {
253 #ifdef HAVE_KSTAT
254 char mon[128];
255 int i;
257 getnetdevlist();
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) ) {
271 * recv errors
273 sprintf( mon, "network/%s/ierrors",
274 IfInfo[i].Name );
275 registerMonitor( mon, "integer",
276 printIErrors, printIErrorsInfo, sm );
278 * xmit errors
280 sprintf( mon, "network/%s/oerrors",
281 IfInfo[i].Name );
282 registerMonitor( mon, "integer",
283 printOErrors, printOErrorsInfo, sm );
285 * collisions
287 sprintf( mon, "network/%s/collisions",
288 IfInfo[i].Name );
289 registerMonitor( mon, "integer",
290 printCollisions, printCollisionsInfo, sm );
292 * multicast xmits
294 sprintf( mon, "network/%s/multixmt",
295 IfInfo[i].Name );
296 registerMonitor( mon, "integer",
297 printMultiXmits, printMultiXmitsInfo, sm );
299 * multicast recvs
301 sprintf( mon, "network/%s/multircv",
302 IfInfo[i].Name );
303 registerMonitor( mon, "integer",
304 printMultiRecvs, printMultiRecvsInfo, sm );
306 * broadcast xmits
308 sprintf( mon, "network/%s/brdcstxmt",
309 IfInfo[i].Name );
310 registerMonitor( mon, "integer",
311 printBcastXmits, printBcastXmitsInfo, sm );
313 * broadcast recvs
315 sprintf( mon, "network/%s/brdcstrcv",
316 IfInfo[i].Name );
317 registerMonitor( mon, "integer",
318 printBcastRecvs, printBcastRecvsInfo, sm );
321 #endif
324 void exitNetDev( void ) {
327 int updateNetDev( void ) {
329 #ifdef HAVE_KSTAT
330 kstat_ctl_t *kctl;
331 kstat_t *ksp;
332 kstat_named_t *kdata;
333 int i;
336 * get a kstat handle and update the user's kstat chain
338 if( (kctl = kstat_open()) == NULL )
339 return( 0 );
340 while( kstat_chain_update( kctl ) != 0 )
343 for( i = 0; i < NetDevCount; i++ ) {
344 char *name;
345 char *ptr;
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 ) ) {
353 *ptr = '\0';
354 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 ) {
363 free( name );
364 return( 0 );
366 if( kstat_read( kctl, ksp, NULL ) == -1 ) {
367 free( name );
368 return( 0 );
370 free( name );
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;
422 kstat_close( kctl );
423 #endif /* ! HAVE_KSTAT */
425 return( 0 );
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 );
435 char *name, *ptr;
436 int i;
438 ptr = strchr( cmdcopy, (int) '/' );
439 name = ++ptr;
440 ptr = strchr( name, (int) '/' );
441 *ptr = '\0';
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);
448 free( cmdcopy );
449 return;
452 free( cmdcopy );
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 );
463 char *name, *ptr;
464 int i;
466 ptr = strchr( cmdcopy, (int) '/' );
467 name = ++ptr;
468 ptr = strchr( name, (int) '/' );
469 *ptr = '\0';
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 );
476 free( cmdcopy );
477 return;
480 free( cmdcopy );
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 );
491 char *name, *ptr;
492 int i;
494 ptr = strchr( cmdcopy, (int) '/' );
495 name = ++ptr;
496 ptr = strchr( name, (int) '/' );
497 *ptr = '\0';
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 );
504 free( cmdcopy );
505 return;
508 free( cmdcopy );
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 );
519 char *name, *ptr;
520 int i;
522 ptr = strchr( cmdcopy, (int) '/' );
523 name = ++ptr;
524 ptr = strchr( name, (int) '/' );
525 *ptr = '\0';
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 );
532 free( cmdcopy );
533 return;
536 free( cmdcopy );
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 );
547 char *name, *ptr;
548 int i;
550 ptr = strchr( cmdcopy, (int) '/' );
551 name = ++ptr;
552 ptr = strchr( name, (int) '/' );
553 *ptr = '\0';
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 );
560 free( cmdcopy );
561 return;
564 free( cmdcopy );
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 );
575 char *name, *ptr;
576 int i;
578 ptr = strchr( cmdcopy, (int) '/' );
579 name = ++ptr;
580 ptr = strchr( name, (int) '/' );
581 *ptr = '\0';
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 );
588 free( cmdcopy );
589 return;
592 free( cmdcopy );
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 );
603 char *name, *ptr;
604 int i;
606 ptr = strchr( cmdcopy, (int) '/' );
607 name = ++ptr;
608 ptr = strchr( name, (int) '/' );
609 *ptr = '\0';
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 );
616 free( cmdcopy );
617 return;
620 free( cmdcopy );
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 );
631 char *name, *ptr;
632 int i;
634 ptr = strchr( cmdcopy, (int) '/' );
635 name = ++ptr;
636 ptr = strchr( name, (int) '/' );
637 *ptr = '\0';
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 );
644 free( cmdcopy );
645 return;
648 free( cmdcopy );
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 );
659 char *name, *ptr;
660 int i;
662 ptr = strchr( cmdcopy, (int) '/' );
663 name = ++ptr;
664 ptr = strchr( name, (int) '/' );
665 *ptr = '\0';
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 );
672 free( cmdcopy );
673 return;
676 free( cmdcopy );
677 fprintf(CurrentClient, "0\n" );