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.
499 lines
16 KiB
499 lines
16 KiB
/* This file is part of KNemo
|
|
Copyright (C) 2004, 2006 Percy Leonhardt <percy@eris23.de>
|
|
|
|
KNemo is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Library General Public License as
|
|
published by the Free Software Foundation; either version 2 of
|
|
the License, or (at your option) any later version.
|
|
|
|
KNemo 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 Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include <tqmap.h>
|
|
#include <tqregexp.h>
|
|
#include <tqstringlist.h>
|
|
|
|
#include <kdebug.h>
|
|
#include <kprocess.h>
|
|
#include <tdeio/global.h>
|
|
|
|
#include "nettoolsbackend.h"
|
|
|
|
#include "config.h"
|
|
|
|
NetToolsBackend::NetToolsBackend( TQDict<Interface>& interfaces )
|
|
: TQObject(),
|
|
BackendBase( interfaces ),
|
|
mRouteProcess(0L),
|
|
mIfconfigProcess(0L),
|
|
mIwconfigProcess(0L)
|
|
{
|
|
}
|
|
|
|
NetToolsBackend::~NetToolsBackend()
|
|
{
|
|
if ( mRouteProcess )
|
|
{
|
|
mRouteProcess->kill();
|
|
delete mRouteProcess;
|
|
}
|
|
if ( mIfconfigProcess )
|
|
{
|
|
mIfconfigProcess->kill();
|
|
delete mIfconfigProcess;
|
|
}
|
|
if ( mIwconfigProcess )
|
|
{
|
|
mIwconfigProcess->kill();
|
|
delete mIwconfigProcess;
|
|
}
|
|
}
|
|
|
|
BackendBase* NetToolsBackend::createInstance( TQDict<Interface>& interfaces )
|
|
{
|
|
return new NetToolsBackend( interfaces );
|
|
}
|
|
|
|
void NetToolsBackend::update()
|
|
{
|
|
if ( !mIfconfigProcess )
|
|
{
|
|
mIfconfigStdout = TQString();
|
|
mIfconfigProcess = new TDEProcess();
|
|
mIfconfigProcess->setEnvironment( "LANG", "C" );
|
|
mIfconfigProcess->setEnvironment( "LC_ALL", "C" );
|
|
*mIfconfigProcess << PATH_IFCONFIG << "-a";
|
|
connect( mIfconfigProcess, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
|
|
this, TQT_SLOT( ifconfigProcessStdout( TDEProcess*, char*, int ) ) );
|
|
connect( mIfconfigProcess, TQT_SIGNAL( processExited( TDEProcess* ) ),
|
|
this, TQT_SLOT( ifconfigProcessExited( TDEProcess* ) ) );
|
|
|
|
if ( !mIfconfigProcess->start( TDEProcess::NotifyOnExit, TDEProcess::Stdout ) )
|
|
{
|
|
delete mIfconfigProcess;
|
|
mIfconfigProcess = 0L;
|
|
}
|
|
}
|
|
|
|
#ifdef PATH_IWCONFIG
|
|
if ( !mIwconfigProcess )
|
|
{
|
|
mIwconfigStdout = TQString();
|
|
mIwconfigProcess = new TDEProcess();
|
|
mIwconfigProcess->setEnvironment( "LANG", "C" );
|
|
mIwconfigProcess->setEnvironment( "LC_ALL", "C" );
|
|
*mIwconfigProcess << PATH_IWCONFIG;
|
|
connect( mIwconfigProcess, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
|
|
this, TQT_SLOT( iwconfigProcessStdout( TDEProcess*, char*, int ) ) );
|
|
connect( mIwconfigProcess, TQT_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ),
|
|
this, TQT_SLOT( iwconfigProcessStdout( TDEProcess*, char*, int ) ) );
|
|
connect( mIwconfigProcess, TQT_SIGNAL( processExited( TDEProcess* ) ),
|
|
this, TQT_SLOT( iwconfigProcessExited( TDEProcess* ) ) );
|
|
|
|
if ( !mIwconfigProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ) )
|
|
{
|
|
delete mIwconfigProcess;
|
|
mIwconfigProcess = 0L;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef PATH_ROUTE
|
|
if ( !mRouteProcess )
|
|
{
|
|
mRouteStdout = TQString();
|
|
mRouteProcess = new TDEProcess();
|
|
mRouteProcess->setEnvironment( "LANG", "C" );
|
|
mRouteProcess->setEnvironment( "LC_ALL", "C" );
|
|
*mRouteProcess << PATH_ROUTE << "-n";
|
|
connect( mRouteProcess, TQT_SIGNAL( receivedStdout( TDEProcess*, char*, int ) ),
|
|
this, TQT_SLOT( routeProcessStdout( TDEProcess*, char*, int ) ) );
|
|
connect( mRouteProcess, TQT_SIGNAL( receivedStderr( TDEProcess*, char*, int ) ),
|
|
this, TQT_SLOT( routeProcessStdout( TDEProcess*, char*, int ) ) );
|
|
connect( mRouteProcess, TQT_SIGNAL( processExited( TDEProcess* ) ),
|
|
this, TQT_SLOT( routeProcessExited( TDEProcess* ) ) );
|
|
|
|
if ( !mRouteProcess->start( TDEProcess::NotifyOnExit, TDEProcess::AllOutput ) )
|
|
{
|
|
delete mRouteProcess;
|
|
mRouteProcess = 0L;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void NetToolsBackend::routeProcessExited( TDEProcess* process )
|
|
{
|
|
if ( process == mRouteProcess )
|
|
{
|
|
mRouteProcess->deleteLater(); // we're in a slot connected to mRouteProcess
|
|
mRouteProcess = 0L;
|
|
parseRouteOutput();
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::routeProcessStdout( TDEProcess*, char* buffer, int buflen )
|
|
{
|
|
mRouteStdout += TQString::fromLatin1( buffer, buflen );
|
|
}
|
|
|
|
void NetToolsBackend::ifconfigProcessExited( TDEProcess* process )
|
|
{
|
|
if ( process == mIfconfigProcess )
|
|
{
|
|
delete mIfconfigProcess;
|
|
mIfconfigProcess = 0L;
|
|
parseIfconfigOutput();
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::ifconfigProcessStdout( TDEProcess*, char* buffer, int buflen )
|
|
{
|
|
mIfconfigStdout += TQString::fromLatin1( buffer, buflen );
|
|
}
|
|
|
|
void NetToolsBackend::iwconfigProcessExited( TDEProcess* process )
|
|
{
|
|
if ( process == mIwconfigProcess )
|
|
{
|
|
delete mIwconfigProcess;
|
|
mIwconfigProcess = 0L;
|
|
parseIwconfigOutput();
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::iwconfigProcessStdout( TDEProcess*, char* buffer, int buflen )
|
|
{
|
|
mIwconfigStdout += TQString::fromLatin1( buffer, buflen );
|
|
}
|
|
|
|
void NetToolsBackend::parseIfconfigOutput()
|
|
{
|
|
/* mIfconfigStdout contains the complete output of 'ifconfig' which we
|
|
* are going to parse here.
|
|
*/
|
|
TQMap<TQString, TQString> configs;
|
|
TQStringList ifList = TQStringList::split( "\n\n", mIfconfigStdout );
|
|
TQStringList::Iterator it;
|
|
for ( it = ifList.begin(); it != ifList.end(); ++it )
|
|
{
|
|
int index = ( *it ).find( ' ' );
|
|
if ( index == -1 )
|
|
continue;
|
|
TQString key = ( *it ).left( index );
|
|
configs[key] = ( *it ).mid( index );
|
|
}
|
|
|
|
/* We loop over the interfaces the user wishs to monitor.
|
|
* If we find the interface in the output of 'ifconfig'
|
|
* we update its data, otherwise we mark it as
|
|
* 'not existing'.
|
|
*/
|
|
TQDictIterator<Interface> ifIt( mInterfaces );
|
|
for ( ; ifIt.current(); ++ifIt )
|
|
{
|
|
TQString key = ifIt.currentKey();
|
|
Interface* interface = ifIt.current();
|
|
|
|
if ( configs.find( key ) == configs.end() )
|
|
{
|
|
// The interface does not exist. Meaning the driver
|
|
// isn't loaded and/or the interface has not been created.
|
|
interface->getData().existing = false;
|
|
interface->getData().available = false;
|
|
}
|
|
// JJ 2005-07-18: use RUNNING instead of UP to detect whether interface is connected
|
|
else if ( !configs[key].contains( "inet " ) ||
|
|
!configs[key].contains( "RUNNING" ) )
|
|
{
|
|
// The interface is up or has an IP assigned but not both
|
|
interface->getData().existing = true;
|
|
interface->getData().available = false;
|
|
}
|
|
else
|
|
{
|
|
// ...determine the type of the interface
|
|
if ( configs[key].contains( "Ethernet" ) )
|
|
interface->setType( Interface::ETHERNET );
|
|
else
|
|
interface->setType( Interface::PPP );
|
|
|
|
// Update the interface.
|
|
interface->getData().existing = true;
|
|
interface->getData().available = true;
|
|
updateInterfaceData( configs[key], interface->getData(), interface->getType() );
|
|
}
|
|
}
|
|
updateComplete();
|
|
}
|
|
|
|
void NetToolsBackend::updateInterfaceData( TQString& config, InterfaceData& data, int type )
|
|
{
|
|
TQRegExp regExp( ".*RX.*:(\\d+).*:\\d+.*:\\d+.*:\\d+" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.rxPackets = regExp.cap( 1 ).toULong();
|
|
|
|
regExp.setPattern( ".*TX.*:(\\d+).*:\\d+.*:\\d+.*:\\d+" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.txPackets = regExp.cap( 1 ).toULong();
|
|
|
|
regExp.setPattern( "RX bytes:(\\d+)\\s*\\(\\d+\\.\\d+\\s*\\w+\\)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
// We count the traffic on ourself to avoid an overflow after
|
|
// 4GB of traffic.
|
|
unsigned long currentRxBytes = regExp.cap( 1 ).toULong();
|
|
if ( currentRxBytes < data.prevRxBytes )
|
|
{
|
|
// there was an overflow
|
|
if ( type == Interface::ETHERNET )
|
|
{
|
|
// This makes data counting more accurate but will not work
|
|
// for interfaces that reset the transfered data to zero
|
|
// when deactivated like ppp does.
|
|
data.rxBytes += 0xFFFFFFFF - data.prevRxBytes;
|
|
}
|
|
data.prevRxBytes = 0L;
|
|
}
|
|
if ( data.rxBytes == 0L )
|
|
{
|
|
// on startup set to currently received bytes
|
|
data.rxBytes = currentRxBytes;
|
|
// this is new: KNemo only counts the traffic transfered
|
|
// while it is running. Important to not falsify statistics!
|
|
data.prevRxBytes = currentRxBytes;
|
|
}
|
|
else
|
|
// afterwards only add difference to previous number of bytes
|
|
data.rxBytes += currentRxBytes - data.prevRxBytes;
|
|
|
|
data.incomingBytes = currentRxBytes - data.prevRxBytes;
|
|
data.prevRxBytes = currentRxBytes;
|
|
data.rxString = TDEIO::convertSize( data.rxBytes );
|
|
}
|
|
|
|
regExp.setPattern( "TX bytes:(\\d+)\\s*\\(\\d+\\.\\d+\\s*\\w+\\)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
// We count the traffic on ourself to avoid an overflow after
|
|
// 4GB of traffic.
|
|
unsigned long currentTxBytes = regExp.cap( 1 ).toULong();
|
|
if ( currentTxBytes < data.prevTxBytes )
|
|
{
|
|
// there was an overflow
|
|
if ( type == Interface::ETHERNET )
|
|
{
|
|
// This makes data counting more accurate but will not work
|
|
// for interfaces that reset the transfered data to zero
|
|
// when deactivated like ppp does.
|
|
data.txBytes += 0xFFFFFFFF - data.prevTxBytes;
|
|
}
|
|
data.prevTxBytes = 0L;
|
|
}
|
|
if ( data.txBytes == 0L )
|
|
{
|
|
// on startup set to currently transmitted bytes
|
|
data.txBytes = currentTxBytes;
|
|
// this is new: KNemo only counts the traffic transfered
|
|
// while it is running. Important to not falsify statistics!
|
|
data.prevTxBytes = currentTxBytes;
|
|
}
|
|
else
|
|
// afterwards only add difference to previous number of bytes
|
|
data.txBytes += currentTxBytes - data.prevTxBytes;
|
|
|
|
data.outgoingBytes = currentTxBytes - data.prevTxBytes;
|
|
data.prevTxBytes = currentTxBytes;
|
|
data.txString = TDEIO::convertSize( data.txBytes );
|
|
}
|
|
|
|
regExp.setPattern( "inet\\s+\\w+:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.ipAddress = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
data.broadcastAddress = regExp.cap( 2 );
|
|
data.subnetMask = regExp.cap( 3 );
|
|
}
|
|
|
|
if ( type == Interface::ETHERNET )
|
|
{
|
|
regExp.setPattern( "(.{2}:.{2}:.{2}:.{2}:.{2}:.{2})" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.hwAddress = regExp.cap( 1 );
|
|
}
|
|
else if ( type == Interface::PPP )
|
|
{
|
|
regExp.setPattern( "(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}).*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.ptpAddress = regExp.cap( 2 );
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::parseIwconfigOutput()
|
|
{
|
|
/* mIwconfigStdout contains the complete output of 'iwconfig' which we
|
|
* are going to parse here.
|
|
*/
|
|
TQMap<TQString, TQString> configs;
|
|
TQStringList ifList = TQStringList::split( "\n\n", mIwconfigStdout );
|
|
TQStringList::Iterator it;
|
|
for ( it = ifList.begin(); it != ifList.end(); ++it )
|
|
{
|
|
int index = ( *it ).find( ' ' );
|
|
if ( index == -1 )
|
|
continue;
|
|
TQString key = ( *it ).left( index );
|
|
configs[key] = ( *it ).mid( index );
|
|
}
|
|
|
|
/* We loop over the interfaces the user wishs to monitor.
|
|
* If we find the interface in the output of 'iwconfig'
|
|
* we update its data.
|
|
*/
|
|
TQDictIterator<Interface> ifIt( mInterfaces );
|
|
for ( ; ifIt.current(); ++ifIt )
|
|
{
|
|
TQString key = ifIt.currentKey();
|
|
Interface* interface = ifIt.current();
|
|
|
|
if ( configs.find( key ) == configs.end() )
|
|
{
|
|
// The interface was not found.
|
|
continue;
|
|
}
|
|
else if ( configs[key].contains( "no wireless extensions" ) )
|
|
{
|
|
// The interface isn't a wireless device.
|
|
interface->getData().wirelessDevice = false;
|
|
}
|
|
else
|
|
{
|
|
// Update the wireless data of the interface.
|
|
interface->getData().wirelessDevice = true;
|
|
updateWirelessData( configs[key], interface->getWirelessData() );
|
|
}
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::updateWirelessData( TQString& config, WirelessData& data )
|
|
{
|
|
TQRegExp regExp( "ESSID:([^\"][\\S]*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.essid = regExp.cap( 1 );
|
|
else
|
|
{
|
|
regExp.setPattern( "ESSID:\"([^\"]*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.essid = regExp.cap( 1 );
|
|
else
|
|
data.essid = TQString();
|
|
}
|
|
|
|
regExp.setPattern( "Mode:(\\w*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.mode = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "Frequency:([\\w|\\.]*\\s*\\w*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
data.frequency = regExp.cap( 1 );
|
|
data.channel = "-";
|
|
}
|
|
else
|
|
{
|
|
data.frequency = "-";
|
|
regExp.setPattern( "Channel:(\\d*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.channel = regExp.cap( 1 );
|
|
else
|
|
data.channel = "-";
|
|
}
|
|
|
|
regExp.setPattern( "Bit Rate[=:](\\d*\\s*[\\w/]*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.bitRate = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "(.{2}:.{2}:.{2}:.{2}:.{2}:.{2})" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.accessPoint = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "Nickname:\"(\\w*)\"" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.nickName = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "Link Quality[=:]([\\d]*)" );
|
|
if ( regExp.search( config ) > -1 )
|
|
data.linkQuality = regExp.cap( 1 );
|
|
|
|
regExp.setPattern( "Encryption key:" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
regExp.setPattern( "Encryption key:off" );
|
|
if ( regExp.search( config ) > -1 )
|
|
{
|
|
data.encryption = false;
|
|
}
|
|
else
|
|
{
|
|
data.encryption = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
data.encryption = false;
|
|
}
|
|
}
|
|
|
|
void NetToolsBackend::parseRouteOutput()
|
|
{
|
|
/* mRouteStdout contains the complete output of 'route' which we
|
|
* are going to parse here.
|
|
*/
|
|
TQMap<TQString, TQStringList> configs;
|
|
TQStringList routeList = TQStringList::split( "\n", mRouteStdout );
|
|
TQStringList::Iterator it;
|
|
for ( it = routeList.begin(); it != routeList.end(); ++it )
|
|
{
|
|
TQStringList routeParameter = TQStringList::split( " ", *it );
|
|
if ( routeParameter.count() < 8 ) // no routing entry
|
|
continue;
|
|
if ( routeParameter[0] != "0.0.0.0" ) // no default route
|
|
continue;
|
|
configs[routeParameter[7]] = routeParameter;
|
|
}
|
|
|
|
/* We loop over the interfaces the user wishs to monitor.
|
|
* If we find the interface in the output of 'route' we update
|
|
* the data of the interface.
|
|
*/
|
|
TQDictIterator<Interface> ifIt( mInterfaces );
|
|
for ( ; ifIt.current(); ++ifIt )
|
|
{
|
|
TQString key = ifIt.currentKey();
|
|
Interface* interface = ifIt.current();
|
|
|
|
if ( configs.find( key ) != configs.end() )
|
|
{
|
|
// Update the default gateway.
|
|
TQStringList routeParameter = configs[key];
|
|
interface->getData().defaultGateway = routeParameter[1];
|
|
}
|
|
else
|
|
{
|
|
// Reset the default gateway.
|
|
interface->getData().defaultGateway = TQString();
|
|
}
|
|
}
|
|
}
|