summaryrefslogtreecommitdiffstats
path: root/src/knemod/backends
diff options
context:
space:
mode:
Diffstat (limited to 'src/knemod/backends')
-rw-r--r--src/knemod/backends/Makefile.am22
-rw-r--r--src/knemod/backends/backendbase.cpp38
-rw-r--r--src/knemod/backends/backendbase.h68
-rw-r--r--src/knemod/backends/daemonregistry.h54
-rw-r--r--src/knemod/backends/kcmregistry.h61
-rw-r--r--src/knemod/backends/nettoolsbackend.cpp498
-rw-r--r--src/knemod/backends/nettoolsbackend.h72
-rw-r--r--src/knemod/backends/sysbackend.cpp428
-rw-r--r--src/knemod/backends/sysbackend.h54
9 files changed, 1295 insertions, 0 deletions
diff --git a/src/knemod/backends/Makefile.am b/src/knemod/backends/Makefile.am
new file mode 100644
index 0000000..aab0fd0
--- /dev/null
+++ b/src/knemod/backends/Makefile.am
@@ -0,0 +1,22 @@
+## Makefile.am for knemo backends
+
+noinst_LTLIBRARIES = libknemo_backends.la
+
+# set the include path for X, qt and KDE
+INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../../common $(all_includes)
+
+# the library search path.
+libknemo_backends_la_LDFLAGS = -module -avoid-version $(all_libraries)
+
+# the libraries to link against.
+libknemo_backends_la_LIBADD = $(LIB_KIO) $(LIB_KUTILS)
+
+# which sources should be compiled as backends
+libknemo_backends_la_SOURCES = backendbase.cpp nettoolsbackend.cpp sysbackend.cpp
+
+# the headers of the backends
+noinst_HEADERS = backendbase.h nettoolsbackend.h sysbackend.h
+
+# let automoc handle all of the meta source files (moc)
+METASOURCES = AUTO
+
diff --git a/src/knemod/backends/backendbase.cpp b/src/knemod/backends/backendbase.cpp
new file mode 100644
index 0000000..82da372
--- /dev/null
+++ b/src/knemod/backends/backendbase.cpp
@@ -0,0 +1,38 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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 "backendbase.h"
+
+BackendBase::BackendBase( QDict<Interface>& interfaces )
+ : mInterfaces( interfaces )
+{
+}
+
+BackendBase::~BackendBase()
+{
+}
+
+void BackendBase::updateComplete()
+{
+ QDictIterator<Interface> ifIt( mInterfaces );
+ for ( ; ifIt.current(); ++ifIt )
+ {
+ ifIt.current()->activateMonitor();
+ }
+}
diff --git a/src/knemod/backends/backendbase.h b/src/knemod/backends/backendbase.h
new file mode 100644
index 0000000..183e40a
--- /dev/null
+++ b/src/knemod/backends/backendbase.h
@@ -0,0 +1,68 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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.
+*/
+
+#ifndef BACKENDBASE_H
+#define BACKENDBASE_H
+
+#include <qdict.h>
+#include <qstring.h>
+
+#include <klocale.h>
+
+#include "data.h"
+#include "interface.h"
+
+/**
+ * This is the baseclass for all backends. Every backend that
+ * should be used for KNemo must inherit from this class.
+ *
+ * @short Baseclass for all backends
+ * @author Percy Leonhardt <[email protected]>
+ */
+
+class BackendBase
+{
+public:
+ BackendBase( QDict<Interface>& interfaces );
+ virtual ~BackendBase();
+
+ /**
+ * Create an instance of this backend because KNemo
+ * does not know about the different types of backends.
+ */
+
+ /**
+ * This function is called from KNemo whenever the
+ * backend shall update the information of the
+ * interfaces in the QDict.
+ */
+ virtual void update() = 0;
+
+protected:
+ /**
+ * Call this function when you have completed the
+ * update. It will trigger the interfaces to check
+ * if there state has changed.
+ */
+ void updateComplete();
+
+ const QDict<Interface>& mInterfaces;
+};
+
+#endif // BACKENDBASE_H
diff --git a/src/knemod/backends/daemonregistry.h b/src/knemod/backends/daemonregistry.h
new file mode 100644
index 0000000..ba4638d
--- /dev/null
+++ b/src/knemod/backends/daemonregistry.h
@@ -0,0 +1,54 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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.
+*/
+
+#ifndef DAEMONREGISTRY_H
+#define DAEMONREGISTRY_H
+
+#include <qstring.h>
+
+#include <klocale.h>
+
+#include "backendbase.h"
+#include "sysbackend.h"
+#include "nettoolsbackend.h"
+
+/**
+ * This registry tells KNemo what backends are available
+ * and how they can be created. It is only used by the daemon
+ * to create the selected backend. Two registries were
+ * necessary to avoid linking the KCM module against all backends.
+ *
+ * @short Registry for all backends
+ * @author Percy Leonhardt <[email protected]>
+ */
+
+struct DaemonRegistryEntry
+{
+ QString name;
+ BackendBase* (*function) ( QDict<Interface>& );
+};
+
+DaemonRegistryEntry DaemonRegistry[] =
+{
+ { "Nettools", NetToolsBackend::createInstance },
+ { "Sys", SysBackend::createInstance },
+ { QString::null, 0 }
+};
+
+#endif // DAEMONREGISTRY_H
diff --git a/src/knemod/backends/kcmregistry.h b/src/knemod/backends/kcmregistry.h
new file mode 100644
index 0000000..23820ac
--- /dev/null
+++ b/src/knemod/backends/kcmregistry.h
@@ -0,0 +1,61 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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.
+*/
+
+#ifndef KCMREGISTRY_H
+#define KCMREGISTRY_H
+
+#include <qstring.h>
+
+#include <klocale.h>
+
+/**
+ * This registry tells the KCM module what backends are available
+ * and how they can be created. It also offers a short description
+ * for every backend that is used in the configuration dialog of KNemo.
+ * It should describe how a backend gathers its information.
+ *
+ * @short Registry for all backends
+ * @author Percy Leonhardt <[email protected]>
+ */
+
+struct KCMRegistryEntry
+{
+ QString name;
+ QString description;
+};
+
+KCMRegistryEntry KCMRegistry[] =
+{
+ { "Nettools",
+ i18n( "Uses the tools from the nettool packge like ifconfig, " \
+ "iwconfig and route to read the necessary information " \
+ "from the ouput of these commands.\n" \
+ "This backend works rather stable but causes a relativly " \
+ "high CPU load." ) },
+ { "Sys",
+ i18n( "Uses the sys filesystem available in 2.6 kernels and " \
+ "direct system calls to the Linux kernel.\n" \
+ "This backend is rather new, so expect minor problems. " \
+ "As an advantage this backend should reduce the CPU load " \
+ "and should not access the harddisc while gathering " \
+ "information." ) },
+ { QString::null, QString::null }
+};
+
+#endif // KCMREGISTRY_H
diff --git a/src/knemod/backends/nettoolsbackend.cpp b/src/knemod/backends/nettoolsbackend.cpp
new file mode 100644
index 0000000..dca42e1
--- /dev/null
+++ b/src/knemod/backends/nettoolsbackend.cpp
@@ -0,0 +1,498 @@
+/* This file is part of KNemo
+ Copyright (C) 2004, 2006 Percy Leonhardt <[email protected]>
+
+ 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 <qmap.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kio/global.h>
+
+#include "nettoolsbackend.h"
+
+#include "config.h"
+
+NetToolsBackend::NetToolsBackend( QDict<Interface>& interfaces )
+ : QObject(),
+ 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( QDict<Interface>& interfaces )
+{
+ return new NetToolsBackend( interfaces );
+}
+
+void NetToolsBackend::update()
+{
+ if ( !mIfconfigProcess )
+ {
+ mIfconfigStdout = QString::null;
+ mIfconfigProcess = new KProcess();
+ mIfconfigProcess->setEnvironment( "LANG", "C" );
+ mIfconfigProcess->setEnvironment( "LC_ALL", "C" );
+ *mIfconfigProcess << PATH_IFCONFIG << "-a";
+ connect( mIfconfigProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT( ifconfigProcessStdout( KProcess*, char*, int ) ) );
+ connect( mIfconfigProcess, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( ifconfigProcessExited( KProcess* ) ) );
+
+ if ( !mIfconfigProcess->start( KProcess::NotifyOnExit, KProcess::Stdout ) )
+ {
+ delete mIfconfigProcess;
+ mIfconfigProcess = 0L;
+ }
+ }
+
+#ifdef PATH_IWCONFIG
+ if ( !mIwconfigProcess )
+ {
+ mIwconfigStdout = QString::null;
+ mIwconfigProcess = new KProcess();
+ mIwconfigProcess->setEnvironment( "LANG", "C" );
+ mIwconfigProcess->setEnvironment( "LC_ALL", "C" );
+ *mIwconfigProcess << PATH_IWCONFIG;
+ connect( mIwconfigProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT( iwconfigProcessStdout( KProcess*, char*, int ) ) );
+ connect( mIwconfigProcess, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT( iwconfigProcessStdout( KProcess*, char*, int ) ) );
+ connect( mIwconfigProcess, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( iwconfigProcessExited( KProcess* ) ) );
+
+ if ( !mIwconfigProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) )
+ {
+ delete mIwconfigProcess;
+ mIwconfigProcess = 0L;
+ }
+ }
+#endif
+
+#ifdef PATH_ROUTE
+ if ( !mRouteProcess )
+ {
+ mRouteStdout = QString::null;
+ mRouteProcess = new KProcess();
+ mRouteProcess->setEnvironment( "LANG", "C" );
+ mRouteProcess->setEnvironment( "LC_ALL", "C" );
+ *mRouteProcess << PATH_ROUTE << "-n";
+ connect( mRouteProcess, SIGNAL( receivedStdout( KProcess*, char*, int ) ),
+ this, SLOT( routeProcessStdout( KProcess*, char*, int ) ) );
+ connect( mRouteProcess, SIGNAL( receivedStderr( KProcess*, char*, int ) ),
+ this, SLOT( routeProcessStdout( KProcess*, char*, int ) ) );
+ connect( mRouteProcess, SIGNAL( processExited( KProcess* ) ),
+ this, SLOT( routeProcessExited( KProcess* ) ) );
+
+ if ( !mRouteProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) )
+ {
+ delete mRouteProcess;
+ mRouteProcess = 0L;
+ }
+ }
+#endif
+}
+
+void NetToolsBackend::routeProcessExited( KProcess* process )
+{
+ if ( process == mRouteProcess )
+ {
+ mRouteProcess->deleteLater(); // we're in a slot connected to mRouteProcess
+ mRouteProcess = 0L;
+ parseRouteOutput();
+ }
+}
+
+void NetToolsBackend::routeProcessStdout( KProcess*, char* buffer, int buflen )
+{
+ mRouteStdout += QString::fromLatin1( buffer, buflen );
+}
+
+void NetToolsBackend::ifconfigProcessExited( KProcess* process )
+{
+ if ( process == mIfconfigProcess )
+ {
+ delete mIfconfigProcess;
+ mIfconfigProcess = 0L;
+ parseIfconfigOutput();
+ }
+}
+
+void NetToolsBackend::ifconfigProcessStdout( KProcess*, char* buffer, int buflen )
+{
+ mIfconfigStdout += QString::fromLatin1( buffer, buflen );
+}
+
+void NetToolsBackend::iwconfigProcessExited( KProcess* process )
+{
+ if ( process == mIwconfigProcess )
+ {
+ delete mIwconfigProcess;
+ mIwconfigProcess = 0L;
+ parseIwconfigOutput();
+ }
+}
+
+void NetToolsBackend::iwconfigProcessStdout( KProcess*, char* buffer, int buflen )
+{
+ mIwconfigStdout += QString::fromLatin1( buffer, buflen );
+}
+
+void NetToolsBackend::parseIfconfigOutput()
+{
+ /* mIfconfigStdout contains the complete output of 'ifconfig' which we
+ * are going to parse here.
+ */
+ QMap<QString, QString> configs;
+ QStringList ifList = QStringList::split( "\n\n", mIfconfigStdout );
+ QStringList::Iterator it;
+ for ( it = ifList.begin(); it != ifList.end(); ++it )
+ {
+ int index = ( *it ).find( ' ' );
+ if ( index == -1 )
+ continue;
+ QString 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'.
+ */
+ QDictIterator<Interface> ifIt( mInterfaces );
+ for ( ; ifIt.current(); ++ifIt )
+ {
+ QString 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( QString& config, InterfaceData& data, int type )
+{
+ QRegExp 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 = KIO::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 = KIO::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.
+ */
+ QMap<QString, QString> configs;
+ QStringList ifList = QStringList::split( "\n\n", mIwconfigStdout );
+ QStringList::Iterator it;
+ for ( it = ifList.begin(); it != ifList.end(); ++it )
+ {
+ int index = ( *it ).find( ' ' );
+ if ( index == -1 )
+ continue;
+ QString 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.
+ */
+ QDictIterator<Interface> ifIt( mInterfaces );
+ for ( ; ifIt.current(); ++ifIt )
+ {
+ QString 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( QString& config, WirelessData& data )
+{
+ QRegExp 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 = QString::null;
+ }
+
+ 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.
+ */
+ QMap<QString, QStringList> configs;
+ QStringList routeList = QStringList::split( "\n", mRouteStdout );
+ QStringList::Iterator it;
+ for ( it = routeList.begin(); it != routeList.end(); ++it )
+ {
+ QStringList routeParameter = QStringList::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.
+ */
+ QDictIterator<Interface> ifIt( mInterfaces );
+ for ( ; ifIt.current(); ++ifIt )
+ {
+ QString key = ifIt.currentKey();
+ Interface* interface = ifIt.current();
+
+ if ( configs.find( key ) != configs.end() )
+ {
+ // Update the default gateway.
+ QStringList routeParameter = configs[key];
+ interface->getData().defaultGateway = routeParameter[1];
+ }
+ else
+ {
+ // Reset the default gateway.
+ interface->getData().defaultGateway = QString::null;
+ }
+ }
+}
diff --git a/src/knemod/backends/nettoolsbackend.h b/src/knemod/backends/nettoolsbackend.h
new file mode 100644
index 0000000..788938c
--- /dev/null
+++ b/src/knemod/backends/nettoolsbackend.h
@@ -0,0 +1,72 @@
+/* This file is part of KNemo
+ Copyright (C) 2004 Percy Leonhardt <[email protected]>
+
+ 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.
+*/
+
+#ifndef NETTOOLSBACKEND_H
+#define NETTOOLSBACKEND_H
+
+#include <qobject.h>
+
+#include "backendbase.h"
+
+class KProcess;
+
+/**
+ * The nettools backend runs 'ifconfig', 'iwconfig' and 'route'
+ * and parses their output. It then triggers the interface
+ * monitor to look for changes in the state of the interface.
+ *
+ * @short Update the information of the interfaces via nettools
+ * @author Percy Leonhardt <[email protected]>
+ */
+
+class NetToolsBackend : public QObject, BackendBase
+{
+ Q_OBJECT
+public:
+ NetToolsBackend(QDict<Interface>& interfaces );
+ virtual ~NetToolsBackend();
+
+ static BackendBase* createInstance( QDict<Interface>& interfaces );
+
+ void update();
+
+private slots:
+ void routeProcessExited( KProcess* process );
+ void routeProcessStdout( KProcess* process, char* buffer, int buflen );
+ void ifconfigProcessExited( KProcess* process );
+ void ifconfigProcessStdout( KProcess* process, char* buffer, int buflen );
+ void iwconfigProcessExited( KProcess* process );
+ void iwconfigProcessStdout( KProcess* process, char* buffer, int buflen );
+
+private:
+ void parseRouteOutput();
+ void parseIfconfigOutput();
+ void updateInterfaceData( QString& config, InterfaceData& data, int type );
+ void parseIwconfigOutput();
+ void updateWirelessData( QString& config, WirelessData& data );
+
+ QString mRouteStdout;
+ QString mIfconfigStdout;
+ QString mIwconfigStdout;
+ KProcess* mRouteProcess;
+ KProcess* mIfconfigProcess;
+ KProcess* mIwconfigProcess;
+};
+
+#endif // NETTOOLSBACKEND_H
diff --git a/src/knemod/backends/sysbackend.cpp b/src/knemod/backends/sysbackend.cpp
new file mode 100644
index 0000000..2caf325
--- /dev/null
+++ b/src/knemod/backends/sysbackend.cpp
@@ -0,0 +1,428 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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 <stdio.h>
+#include <string.h>
+#include <arpa/inet.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <qmap.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <qstringlist.h>
+
+#include <kdebug.h>
+#include <kprocess.h>
+#include <kio/global.h>
+
+#include "sysbackend.h"
+
+#include "config.h"
+
+#ifdef HAVE_LIBIW
+#include <iwlib.h>
+#else
+#include <net/if.h>
+#endif
+
+#define RTF_GATEWAY 0x0002
+#define SYSPATH "/sys/class/net/"
+#define PROCROUTE "/proc/net/route"
+
+SysBackend::SysBackend( QDict<Interface>& interfaces )
+ : BackendBase( interfaces )
+{
+}
+
+SysBackend::~SysBackend()
+{
+}
+
+BackendBase* SysBackend::createInstance( QDict<Interface>& interfaces )
+{
+ return new SysBackend( interfaces );
+}
+
+void SysBackend::update()
+{
+ QDir dir( SYSPATH );
+ QStringList ifList = dir.entryList( QDir::Dirs );
+
+ QDictIterator<Interface> ifIt( mInterfaces );
+ for ( ; ifIt.current(); ++ifIt )
+ {
+ QString key = ifIt.currentKey();
+ Interface* interface = ifIt.current();
+
+ if ( ifList.find( key ) == ifList.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;
+ }
+ else
+ {
+ if ( QFile::exists( SYSPATH + key + "/wireless" ) )
+ {
+ interface->getData().wirelessDevice = true;
+ }
+
+ unsigned int carrier = 0;
+ if ( !readNumberFromFile( SYSPATH + key + "/carrier", carrier ) ||
+ carrier == 0 )
+ {
+ // The interface is there but not useable.
+ interface->getData().existing = true;
+ interface->getData().available = false;
+ }
+ else
+ {
+ // ...determine the type of the interface
+ unsigned int type = 0;
+ if ( readNumberFromFile( SYSPATH + key + "/type", type ) &&
+ type == 512 )
+ {
+ interface->setType( Interface::PPP );
+ }
+ else
+ {
+ interface->setType( Interface::ETHERNET );
+ }
+
+ // Update the interface.
+ interface->getData().existing = true;
+ interface->getData().available = true;
+ updateInterfaceData( key, interface->getData(), interface->getType() );
+
+ if ( interface->getData().wirelessDevice == true )
+ {
+ updateWirelessData( key, interface->getWirelessData() );
+ }
+ }
+ }
+ }
+ updateComplete();
+}
+
+bool SysBackend::readNumberFromFile( const QString& fileName, unsigned int& value )
+{
+ FILE* file = fopen( fileName.latin1(), "r" );
+ if ( file != NULL )
+ {
+ if ( fscanf( file, "%ul", &value ) > 0 )
+ {
+ fclose( file );
+ return true;
+ }
+ fclose( file );
+ }
+
+ return false;
+}
+
+bool SysBackend::readStringFromFile( const QString& fileName, QString& string )
+{
+ char buffer[64];
+ FILE* file = fopen( fileName.latin1(), "r" );
+ if ( file != NULL )
+ {
+ if ( fscanf( file, "%s", buffer ) > 0 )
+ {
+ fclose( file );
+ string = buffer;
+ return true;
+ }
+ fclose( file );
+ }
+
+ return false;
+}
+
+void SysBackend::updateInterfaceData( const QString& ifName, InterfaceData& data, int type )
+{
+ QString ifFolder = SYSPATH + ifName + "/";
+
+ unsigned int rxPackets = 0;
+ if ( readNumberFromFile( ifFolder + "statistics/rx_packets", rxPackets ) )
+ {
+ data.rxPackets = rxPackets;
+ }
+
+ unsigned int txPackets = 0;
+ if ( readNumberFromFile( ifFolder + "statistics/tx_packets", txPackets ) )
+ {
+ data.txPackets = txPackets;
+ }
+
+ unsigned int rxBytes = 0;
+ if ( readNumberFromFile( ifFolder + "statistics/rx_bytes", rxBytes ) )
+ {
+ // We count the traffic on ourself to avoid an overflow after
+ // 4GB of traffic.
+ if ( rxBytes < 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 = rxBytes;
+ // this is new: KNemo only counts the traffic transfered
+ // while it is running. Important to not falsify statistics!
+ data.prevRxBytes = rxBytes;
+ }
+ else
+ // afterwards only add difference to previous number of bytes
+ data.rxBytes += rxBytes - data.prevRxBytes;
+
+ data.incomingBytes = rxBytes - data.prevRxBytes;
+ data.prevRxBytes = rxBytes;
+ data.rxString = KIO::convertSize( data.rxBytes );
+ }
+
+ unsigned int txBytes = 0;
+ if ( readNumberFromFile( ifFolder + "statistics/tx_bytes", txBytes ) )
+ {
+ // We count the traffic on ourself to avoid an overflow after
+ // 4GB of traffic.
+ if ( txBytes < 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 received bytes
+ data.txBytes = txBytes;
+ // this is new: KNemo only counts the traffic transfered
+ // while it is running. Important to not falsify statistics!
+ data.prevTxBytes = txBytes;
+ }
+ else
+ // afterwards only add difference to previous number of bytes
+ data.txBytes += txBytes - data.prevTxBytes;
+
+ data.outgoingBytes = txBytes - data.prevTxBytes;
+ data.prevTxBytes = txBytes;
+ data.txString = KIO::convertSize( data.txBytes );
+ }
+
+ if ( type == Interface::ETHERNET )
+ {
+ QString hwAddress;
+ if ( readStringFromFile( ifFolder + "address", hwAddress ) )
+ {
+ data.hwAddress = hwAddress;
+ }
+
+ // for the default gateway we use the proc filesystem
+ QFile routeFile( PROCROUTE );
+ if ( routeFile.open( IO_ReadOnly ) )
+ {
+ QString routeData( routeFile.readAll().data() );
+ QStringList routeEntries = QStringList::split( "\n", routeData );
+ QStringList::Iterator it;
+ for ( it = routeEntries.begin(); it != routeEntries.end(); ++it )
+ {
+ QRegExp regExp( ".*\\s+[\\w\\d]{8}\\s+([\\w\\d]{8})\\s+(\\d{4})" );
+ if ( ( regExp.search( *it ) > -1 )
+ && ( regExp.cap( 2 ).toUInt() & RTF_GATEWAY ) )
+ {
+ bool ok;
+ struct in_addr in;
+ in.s_addr = regExp.cap( 1 ).toULong( &ok, 16 );
+ data.defaultGateway = inet_ntoa( in );
+ break;
+ }
+ }
+ routeFile.close();
+ }
+
+ }
+
+ // use ioctls for the rest
+ int fd;
+ struct ifreq ifr;
+ if ( ( fd = socket(AF_INET, SOCK_DGRAM, 0) ) > -1 )
+ {
+ strcpy( ifr.ifr_name, ifName.latin1() );
+ ifr.ifr_addr.sa_family = AF_INET;
+ if ( ioctl( fd, SIOCGIFADDR, &ifr ) > -1 )
+ {
+ data.ipAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr);
+ }
+ if ( ioctl( fd, SIOCGIFDSTADDR, &ifr) > -1 )
+ {
+ data.ptpAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_dstaddr)->sin_addr);
+ }
+
+ if ( ioctl( fd, SIOCGIFBRDADDR, &ifr ) > -1 )
+ {
+ data.broadcastAddress = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_broadaddr)->sin_addr);
+ }
+
+ if ( ioctl( fd, SIOCGIFNETMASK, &ifr ) > -1 )
+ {
+ data.subnetMask = inet_ntoa(((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr);
+ }
+ close( fd );
+ }
+}
+
+void SysBackend::updateWirelessData( const QString& ifName, WirelessData& data )
+{
+ QString wirelessFolder = SYSPATH + ifName + "/wireless/";
+
+ unsigned int link = 0;
+ if ( readNumberFromFile( wirelessFolder + "link", link ) )
+ {
+ data.linkQuality = QString::number( link );
+ }
+
+#ifdef HAVE_LIBIW
+ // The following code was taken from iwconfig.c and iwlib.c.
+ int fd;
+ if ( ( fd = iw_sockets_open() ) > 0 )
+ {
+ struct iwreq wrq;
+ char buffer[128];
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWFREQ, &wrq ) >= 0 )
+ {
+ int channel = -1;
+ double freq = iw_freq2float( &( wrq.u.freq ) );
+ struct iw_range range;
+ if( iw_get_range_info( fd, ifName.latin1(), &range ) >= 0 )
+ {
+ if ( freq < KILO )
+ {
+ channel = iw_channel_to_freq( (int) freq, &freq, &range );
+ }
+ else
+ {
+ channel = iw_freq_to_channel( freq, &range );
+ }
+ iw_print_freq_value( buffer, sizeof( buffer ), freq );
+ data.frequency = buffer;
+ data.channel = QString::number( channel );
+ }
+ }
+
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ memset( essid, 0, IW_ESSID_MAX_SIZE + 1 );
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ wrq.u.essid.flags = 0;
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWESSID, &wrq ) >= 0 )
+ {
+ if ( wrq.u.data.flags > 0 )
+ {
+ data.essid = essid;
+ }
+ else
+ {
+ data.essid = "any";
+ }
+ }
+
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWAP, &wrq ) >= 0 )
+ {
+ char ap_addr[128];
+ iw_ether_ntop( (const ether_addr*) wrq.u.ap_addr.sa_data, ap_addr);
+ data.accessPoint = ap_addr;
+ }
+
+ memset( essid, 0, IW_ESSID_MAX_SIZE + 1 );
+ wrq.u.essid.pointer = (caddr_t) essid;
+ wrq.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ wrq.u.essid.flags = 0;
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWNICKN, &wrq ) >= 0 )
+ {
+ if ( wrq.u.data.length > 1 )
+ {
+ data.nickName = essid;
+ }
+ else
+ {
+ data.nickName = QString::null;
+ }
+ }
+
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWRATE, &wrq ) >= 0 )
+ {
+ iwparam bitrate;
+ memcpy (&(bitrate), &(wrq.u.bitrate), sizeof (iwparam));
+ iw_print_bitrate( buffer, sizeof( buffer ), wrq.u.bitrate.value );
+ data.bitRate = buffer;
+ }
+
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWMODE, &wrq ) >= 0 )
+ {
+ int mode = wrq.u.mode;
+ if ( mode < IW_NUM_OPER_MODE && mode >= 0 )
+ {
+ data.mode = iw_operation_mode[mode];
+ }
+ else
+ {
+ data.mode = QString::null;
+ }
+ }
+
+ unsigned char key[IW_ENCODING_TOKEN_MAX];
+ wrq.u.data.pointer = (caddr_t) key;
+ wrq.u.data.length = IW_ENCODING_TOKEN_MAX;
+ wrq.u.data.flags = 0;
+ if ( iw_get_ext( fd, ifName.latin1(), SIOCGIWENCODE, &wrq ) >= 0 )
+ {
+ if ( ( wrq.u.data.flags & IW_ENCODE_DISABLED ) || ( wrq.u.data.length == 0 ) )
+ {
+ data.encryption = false;
+ }
+ else
+ {
+ data.encryption = true;
+ }
+ }
+ else
+ {
+ data.encryption = false;
+ }
+ close( fd );
+ }
+#endif
+}
+
diff --git a/src/knemod/backends/sysbackend.h b/src/knemod/backends/sysbackend.h
new file mode 100644
index 0000000..10650b6
--- /dev/null
+++ b/src/knemod/backends/sysbackend.h
@@ -0,0 +1,54 @@
+/* This file is part of KNemo
+ Copyright (C) 2006 Percy Leonhardt <[email protected]>
+
+ 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.
+*/
+
+#ifndef SYSBACKEND_H
+#define SYSBACKEND_H
+
+#include "backendbase.h"
+
+/**
+ * The sys backend uses the sys filesystem available in 2.6
+ * kernels. It reads all necessary information from the files
+ * and folders located at /sys and parses their output.
+ * It then triggers the interface monitor to look for changes
+ * in the state of the interface.
+ *
+ * @short Update the information of the interfaces via sys filesystem
+ * @author Percy Leonhardt <[email protected]>
+ */
+
+class SysBackend : public BackendBase
+{
+public:
+ SysBackend(QDict<Interface>& interfaces );
+ virtual ~SysBackend();
+
+ static BackendBase* createInstance( QDict<Interface>& interfaces );
+
+ void update();
+
+private:
+ bool readNumberFromFile( const QString& fileName, unsigned int& value );
+ bool readStringFromFile( const QString& fileName, QString& string );
+ void updateWirelessData( const QString& ifName, WirelessData& data );
+ void updateInterfaceData( const QString& ifName, InterfaceData& data, int type );
+
+};
+
+#endif // SYSBACKEND_H