You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdebase/ksysguard/ksysguardd/Solaris/NetDev.c

680 lines
16 KiB

/*
KSysGuard, the KDE System Guard
Copyright (c) 1999, 2000 Chris Schlaeger <cs@kde.org>
Solaris support by Torsten Kasch <tk@Genetik.Uni-Bielefeld.DE>
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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stropts.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
#include "config.h"
#ifdef HAVE_KSTAT
#include <kstat.h>
#endif
#include "ksysguardd.h"
#include "Command.h"
#include "NetDev.h"
/*
* available network interface statistics through kstat(3):
*
* kstat name value
* ----------------------------------------------------------------------
* for the loopback interface(s) we can get
* ipackets # packets received
* opackets # packets sent
* in addition to those, for "real" interfaces:
* oerrors # xmit errors
* ierrors # recv errors
* macxmt_errors # xmit errors reported by hardware?
* macrcv_errors # recv errors reported by hardware?
* opackets64 same as opackets (64bit)
* ipackets64 same as ipackets (64bit)
* obytes # bytes sent
* rbytes # bytes received
* obytes64 same as obytes (64bit)
* rbytes64 same as ibytes (64bit)
* collisions # collisions
* multixmt # multicasts sent?
* multircv # multicasts received?
* brdcstxmt # broadcasts transmitted
* brdcstrcv # broadcasts received
* unknowns
* blocked
* ex_collisions
* defer_xmts
* align_errors
* fcs_errors
* oflo # overflow errors
* uflo # underflow errors
* runt_errors
* missed
* tx_late_collisions
* carrier_errors
* noxmtbuf
* norcvbuf
* xmt_badinterp
* rcv_badinterp
* intr # interrupts?
* xmtretry # xmit retries?
* ifspeed interface speed: 10000000 for 10BaseT
* duplex "half" or "full"
* media e.g. "PHY/MII"
* promisc promiscuous mode (e.g. "off")
* first_collisions
* multi_collisions
* sqe_errors
* toolong_errors
*/
typedef struct {
char *Name;
short flags;
unsigned long ipackets;
unsigned long OLDipackets;
unsigned long opackets;
unsigned long OLDopackets;
unsigned long ierrors;
unsigned long OLDierrors;
unsigned long oerrors;
unsigned long OLDoerrors;
unsigned long collisions;
unsigned long OLDcollisions;
unsigned long multixmt;
unsigned long OLDmultixmt;
unsigned long multircv;
unsigned long OLDmultircv;
unsigned long brdcstxmt;
unsigned long OLDbrdcstxmt;
unsigned long brdcstrcv;
unsigned long OLDbrdcstrcv;
} NetDevInfo;
#define NBUFFERS 64
#define MAXNETDEVS 64
static NetDevInfo IfInfo[MAXNETDEVS];
static int NetDevCount;
/*
* insertnetdev() -- insert device name & flags into our list
*/
int insertnetdev( const char *name, const short flags ) {
int i = 0;
/*
* interface "aliases" don't seem to have
* separate kstat statistics, so we skip them
*/
if( strchr( name, (int) ':' ) != NULL )
return( 0 );
while( (i < NetDevCount) && (strcmp( IfInfo[i].Name, name ) != 0) ) {
if( strcmp( IfInfo[i].Name, name ) == 0 )
return( 0 );
i++;
}
/*
* init new slot
*/
IfInfo[i].Name = strdup( name );
IfInfo[i].flags = flags;
IfInfo[i].ipackets = 0L;
IfInfo[i].OLDipackets = 0L;
IfInfo[i].opackets = 0L;
IfInfo[i].OLDopackets = 0L;
IfInfo[i].ierrors = 0L;
IfInfo[i].OLDierrors = 0L;
IfInfo[i].oerrors = 0L;
IfInfo[i].OLDoerrors = 0L;
IfInfo[i].collisions = 0L;
IfInfo[i].OLDcollisions = 0L;
IfInfo[i].multixmt = 0L;
IfInfo[i].OLDmultixmt = 0L;
IfInfo[i].multircv = 0L;
IfInfo[i].OLDmultircv = 0L;
IfInfo[i].brdcstxmt = 0L;
IfInfo[i].OLDbrdcstxmt = 0L;
IfInfo[i].brdcstrcv = 0L;
IfInfo[i].OLDbrdcstrcv = 0L;
NetDevCount = ++i;
/* XXX: need sanity checks! */
return( 0 );
}
/*
* getnetdevlist() -- get a list of all "up" interfaces
*/
int getnetdevlist( void ) {
int fd;
int buffsize;
int prevsize;
int prevCount;
struct ifconf ifc;
struct ifreq *ifr;
if( (fd = socket( PF_INET, SOCK_DGRAM, 0 )) < 0 ) {
return( -1 );
}
/*
* get the interface list via iotl( SIOCGIFCONF )
* the following algorithm based on ideas from W.R. Stevens'
* "UNIX Network Programming", Vol. 1:
* Since the ioctl may return 0, indicating success, even if the
* ifreq buffer was too small, we have to make sure, it didn't
* get truncated by comparing our initial size guess with the
* actual returned size.
*/
prevsize = 0;
buffsize = NBUFFERS * sizeof( struct ifreq );
while( 1 ) {
if( (ifc.ifc_buf = malloc( buffsize )) == NULL )
return( -1 );
ifc.ifc_len = buffsize;
if( ioctl( fd, SIOCGIFCONF, &ifc ) < 0 ) {
if( errno != EINVAL || prevsize != 0 ) {
free( ifc.ifc_buf );
return( -1 );
}
} else {
if( ifc.ifc_len == prevsize )
/* success */
break;
prevsize = ifc.ifc_len;
}
/*
* initial buffer guessed too small, allocate a bigger one
*/
free( ifc.ifc_buf );
buffsize = (NBUFFERS + 10) * sizeof( struct ifreq );
}
/*
* get the names for all interfaces which are configured "up"
* we're not interested in the ifc data (address), so we reuse the
* same structure (with ifc.len set) for the next ioctl()
*/
prevCount = NetDevCount;
for( ifr = (struct ifreq *) ifc.ifc_buf;
ifr < (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
ifr++ ) {
if( ioctl( fd, SIOCGIFFLAGS, ifr ) < 0 ) {
free( ifc.ifc_buf );
return( -1 );
}
if( ifr->ifr_flags & IFF_UP )
insertnetdev( ifr->ifr_name, ifr->ifr_flags );
}
free( ifc.ifc_buf );
close( fd );
if( (prevCount > 0) && (prevCount != NetDevCount) ) {
print_error( "RECONFIGURE\n" );
prevCount = NetDevCount;
}
return( NetDevCount );
}
void initNetDev( struct SensorModul* sm ) {
#ifdef HAVE_KSTAT
char mon[128];
int i;
getnetdevlist();
for( i = 0; i < NetDevCount; i++ ) {
sprintf( mon, "network/%s/ipackets", IfInfo[i].Name );
registerMonitor( mon, "integer",
printIPackets, printIPacketsInfo, sm );
sprintf( mon, "network/%s/opackets", IfInfo[i].Name );
registerMonitor( mon, "integer",
printOPackets, printOPacketsInfo, sm );
/*
* if this isn't a loopback interface,
* register additional monitors
*/
if( ! (IfInfo[i].flags & IFF_LOOPBACK) ) {
/*
* recv errors
*/
sprintf( mon, "network/%s/ierrors",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printIErrors, printIErrorsInfo, sm );
/*
* xmit errors
*/
sprintf( mon, "network/%s/oerrors",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printOErrors, printOErrorsInfo, sm );
/*
* collisions
*/
sprintf( mon, "network/%s/collisions",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printCollisions, printCollisionsInfo, sm );
/*
* multicast xmits
*/
sprintf( mon, "network/%s/multixmt",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printMultiXmits, printMultiXmitsInfo, sm );
/*
* multicast recvs
*/
sprintf( mon, "network/%s/multircv",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printMultiRecvs, printMultiRecvsInfo, sm );
/*
* broadcast xmits
*/
sprintf( mon, "network/%s/brdcstxmt",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printBcastXmits, printBcastXmitsInfo, sm );
/*
* broadcast recvs
*/
sprintf( mon, "network/%s/brdcstrcv",
IfInfo[i].Name );
registerMonitor( mon, "integer",
printBcastRecvs, printBcastRecvsInfo, sm );
}
}
#endif
}
void exitNetDev( void ) {
}
int updateNetDev( void ) {
#ifdef HAVE_KSTAT
kstat_ctl_t *kctl;
kstat_t *ksp;
kstat_named_t *kdata;
int i;
/*
* get a kstat handle and update the user's kstat chain
*/
if( (kctl = kstat_open()) == NULL )
return( 0 );
while( kstat_chain_update( kctl ) != 0 )
;
for( i = 0; i < NetDevCount; i++ ) {
char *name;
char *ptr;
/*
* chop off the trailing interface no
*/
name = strdup( IfInfo[i].Name );
ptr = name + strlen( name ) - 1;
while( (ptr > name) && isdigit( (int) *ptr ) ) {
*ptr = '\0';
ptr--;
}
/*
* traverse the kstat chain
* to find the appropriate statistics
*/
if( (ksp = kstat_lookup( kctl,
name, 0, IfInfo[i].Name )) == NULL ) {
free( name );
return( 0 );
}
if( kstat_read( kctl, ksp, NULL ) == -1 ) {
free( name );
return( 0 );
}
free( name );
/*
* lookup & store the data
*/
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ipackets" );
if( kdata != NULL ) {
IfInfo[i].OLDipackets = IfInfo[i].ipackets;
IfInfo[i].ipackets = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "opackets" );
if( kdata != NULL ) {
IfInfo[i].OLDopackets = IfInfo[i].opackets;
IfInfo[i].opackets = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "ierrors" );
if( kdata != NULL ) {
IfInfo[i].OLDierrors = IfInfo[i].ierrors;
IfInfo[i].ierrors = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "oerrors" );
if( kdata != NULL ) {
IfInfo[i].OLDoerrors = IfInfo[i].oerrors;
IfInfo[i].oerrors = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "collisions" );
if( kdata != NULL ) {
IfInfo[i].OLDcollisions = IfInfo[i].collisions;
IfInfo[i].collisions = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multixmt" );
if( kdata != NULL ) {
IfInfo[i].OLDmultixmt = IfInfo[i].multixmt;
IfInfo[i].multixmt = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "multircv" );
if( kdata != NULL ) {
IfInfo[i].OLDmultircv = IfInfo[i].multircv;
IfInfo[i].multircv = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstxmt" );
if( kdata != NULL ) {
IfInfo[i].OLDbrdcstxmt = IfInfo[i].brdcstxmt;
IfInfo[i].brdcstxmt = kdata->value.ul;
}
kdata = (kstat_named_t *) kstat_data_lookup( ksp, "brdcstrcv" );
if( kdata != NULL ) {
IfInfo[i].OLDbrdcstrcv = IfInfo[i].brdcstrcv;
IfInfo[i].brdcstrcv = kdata->value.ul;
}
}
kstat_close( kctl );
#endif /* ! HAVE_KSTAT */
return( 0 );
}
void printIPacketsInfo( const char *cmd ) {
fprintf(CurrentClient, "Received Packets\t0\t0\tPackets\n" );
}
void printIPackets( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDipackets > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].ipackets - IfInfo[i].OLDipackets);
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printOPacketsInfo( const char *cmd ) {
fprintf(CurrentClient, "Transmitted Packets\t0\t0\tPackets\n" );
}
void printOPackets( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDopackets > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].opackets - IfInfo[i].OLDopackets );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printIErrorsInfo( const char *cmd ) {
fprintf(CurrentClient, "Input Errors\t0\t0\tPackets\n" );
}
void printIErrors( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDierrors > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].ierrors - IfInfo[i].OLDierrors );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printOErrorsInfo( const char *cmd ) {
fprintf(CurrentClient, "Output Errors\t0\t0\tPackets\n" );
}
void printOErrors( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDoerrors > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].oerrors - IfInfo[i].OLDoerrors );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printCollisionsInfo( const char *cmd ) {
fprintf(CurrentClient, "Collisions\t0\t0\tPackets\n" );
}
void printCollisions( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDcollisions > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].collisions - IfInfo[i].OLDcollisions );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printMultiXmitsInfo( const char *cmd ) {
fprintf(CurrentClient, "Multicasts Sent\t0\t0\tPackets\n" );
}
void printMultiXmits( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDmultixmt > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].multixmt - IfInfo[i].OLDmultixmt );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printMultiRecvsInfo( const char *cmd ) {
fprintf(CurrentClient, "Multicasts Received\t0\t0\tPackets\n" );
}
void printMultiRecvs( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDmultircv > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].multircv - IfInfo[i].OLDmultircv );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printBcastXmitsInfo( const char *cmd ) {
fprintf(CurrentClient, "Broadcasts Sent\t0\t0\tPackets\n" );
}
void printBcastXmits( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDbrdcstxmt > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].brdcstxmt - IfInfo[i].OLDbrdcstxmt );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}
void printBcastRecvsInfo( const char *cmd ) {
fprintf(CurrentClient, "Broadcasts Received\t0\t0\tPackets\n" );
}
void printBcastRecvs( const char *cmd ) {
char *cmdcopy = strdup( cmd );
char *name, *ptr;
int i;
ptr = strchr( cmdcopy, (int) '/' );
name = ++ptr;
ptr = strchr( name, (int) '/' );
*ptr = '\0';
for( i = 0; i < NetDevCount; i++ ) {
if( (IfInfo[i].OLDbrdcstrcv > 0)
&& (strcmp( IfInfo[i].Name, name ) == 0) ) {
fprintf(CurrentClient, "%ld\n",
IfInfo[i].brdcstrcv - IfInfo[i].OLDbrdcstrcv );
free( cmdcopy );
return;
}
}
free( cmdcopy );
fprintf(CurrentClient, "0\n" );
}