summaryrefslogtreecommitdiffstats
path: root/src/networkinterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/networkinterface.cpp')
-rw-r--r--src/networkinterface.cpp563
1 files changed, 563 insertions, 0 deletions
diff --git a/src/networkinterface.cpp b/src/networkinterface.cpp
new file mode 100644
index 0000000..e757339
--- /dev/null
+++ b/src/networkinterface.cpp
@@ -0,0 +1,563 @@
+/***************************************************************************
+* Copyright (C) 2004 by Christoph Thielecke *
+* crissi99@gmx.de *
+* *
+* This program is free software; you can redistribute it and/or modify *
+* it under the terms of the GNU General Public License as published by *
+* the Free Software Foundation; either version 2 of the License, or *
+* (at your option) any later version. *
+* *
+* 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., *
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
+***************************************************************************/
+//BEGIN INCLUDES
+#include "networkinterface.h"
+#include <iostream>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kglobal.h>
+#include <kstddirs.h>
+#include <qnetwork.h>
+#include <qurloperator.h>
+#include <kmessagebox.h>
+#include <arpa/inet.h>
+#include <linux/sockios.h>
+#include <linux/if.h>
+#include <sys/ioctl.h>
+//END INCLUDES
+
+NetworkInterface::NetworkInterface( KVpncConfig* GlobalConfig,QApplication *app, QObject *parent, const char *name ) : QObject( parent, name )
+{
+
+ this->app = app;
+ interfaceTest = false;
+ retrieveInterfaceAddress = false;
+ QPtrList<QString>*InterfaceList = new QPtrList<QString>();
+ InterfaceList->setAutoDelete( TRUE ); // the list owns the objects
+ QString InterfaceIP = "";
+ QString InterfaceAddress = "";
+ IPforInterface = "";
+ tmpInterface = "";
+ interfaceExists = false;
+ defaultinterface="default";
+ readOutput=false;
+ env = new QStringList();
+ *env << "LC_ALL=C" << "LANG=C" << "PATH=/bin:/usr/bin:/usr/sbin:/sbin";
+ this->GlobalConfig = GlobalConfig;
+}
+
+NetworkInterface::~NetworkInterface()
+{
+ //delete proc;
+ if (defaultinterface == "default")
+ defaultinterface == "";
+}
+
+bool NetworkInterface::interfaceExist( QString Interface )
+{
+ if ( !Interface.isEmpty() )
+ {
+ QFile NetdevFile( "/proc/net/dev" );
+ QTextStream stream ( &NetdevFile );
+ if ( NetdevFile.open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ if ( line.find ( ':' ) > -1 )
+ {
+ QString tmpdev = line.section( ':', 0, 0 ).stripWhiteSpace();
+ if ( tmpdev == Interface )
+ {
+ NetdevFile.close();
+ return true;
+ }
+ }
+ }
+ }
+ NetdevFile.close();
+ }
+ return false;
+}
+
+QStringList NetworkInterface::getAllNetworkInterfaces()
+{
+ QFile NetdevFile( "/proc/net/dev" );
+ QTextStream stream ( &NetdevFile );
+ if ( NetdevFile.open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ if ( line.find ( ':' ) > -1 )
+ {
+ InterfaceList.append( line.section( ':', 0, 0 ).stripWhiteSpace());
+ }
+ }
+ }
+ NetdevFile.close();
+ InterfaceList.sort();
+ return InterfaceList;
+}
+
+QString NetworkInterface::getInterfaceIP( QString Interface )
+{
+
+//FIXME why this dont work on ppp0 device of l2tp tunnel?
+// if ( !Interface.isEmpty() )
+// {
+// int fd=-1;
+// QString tmpip="";
+// struct ifreq ifr;
+// fd = socket(AF_INET, SOCK_STREAM, 0);
+// if (fd >= 0){
+// strcpy(ifr.ifr_name, Interface.ascii());
+// ifr.ifr_addr.sa_family = AF_INET;
+// if (ioctl(fd, SIOCGIFADDR, &ifr) == 0){
+// tmpip = inet_ntoa(((struct sockaddr_in *) &ifr. ifr_addr)->sin_addr);
+// return tmpip;
+// }
+// else
+// return QString("");
+// }
+// else
+// return QString("");
+// }
+// else
+// return QString("");
+ return getInterfaceIP2(Interface);
+}
+
+QString NetworkInterface::getInterfaceIP2( QString Interface )
+{
+ if ( !Interface.isEmpty() )
+ {
+
+ InterfaceIpProc = new QProcess(this);
+ InterfaceIpProc->addArgument( GlobalConfig->pathToIp );
+ InterfaceIpProc->addArgument("addr");
+ InterfaceIpProc->addArgument("show");
+ InterfaceIpProc->addArgument(Interface);
+
+ retrieveInterfaceIP=true;
+ readOutput=true;
+
+ connect( InterfaceIpProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout_interfaceip() ) );
+ connect( InterfaceIpProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr_interfaceip() ) );
+ connect( InterfaceIpProc, SIGNAL( processExited () ), this, SLOT( processHasFinished() ) );
+
+ if ( !InterfaceIpProc->start(env) )
+ {
+ GlobalConfig->appendLogEntry(i18n("unable to start proc (%1)!").arg(i18n("getting IP address from interface")), KVpncConfig::error);
+ }
+ else
+ {
+ while ( retrieveInterfaceIP && InterfaceIpProc->isRunning() )
+ {
+ if (GlobalConfig->appPointer->hasPendingEvents())
+ GlobalConfig->appPointer->processEvents();
+ usleep(500);
+ }
+ /*
+ while ( readOutput)
+ GlobalConfig->appPointer->processEvents();*/
+ }
+ disconnect( InterfaceIpProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout_interfaceip() ) );
+ disconnect( InterfaceIpProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr_interfaceip() ) );
+ disconnect( InterfaceIpProc, SIGNAL( processExited () ), this, SLOT( processHasFinished() ) );
+ delete InterfaceIpProc;
+ InterfaceIpProc=0L;
+ }
+ return InterfaceIP;
+
+}
+
+QString NetworkInterface::getInterfaceAddress( QString IPforInterface )
+{
+ /*
+ // TODO fixme
+ if ( !IPforInterface.isEmpty() )
+ {
+ this->IPforInterface = IPforInterface;
+ QStringList devlist = getAllNetworkInterfaces();
+ tmpfile = new KTempFile();
+ QString tmpPath = locateLocal ( "data", "kvpnc/" );
+ QString GetIpForInterfaceScript = tmpPath + "get_interface_for_ip_"+IPforInterface+".sh";
+
+ QFile file ( GetIpForInterfaceScript );
+ QTextStream stream( &file );
+ if ( file.open( IO_WriteOnly ) )
+ {
+ stream << "# generated by kvpnc. Do not edit it." << "\n";
+ stream << "\n";
+ stream << GlobalConfig->pathToIfconfig +" | grep -B1 "+IPforInterface+" | head -n1 |awk {'print $1'} > "+ tmpfile->name()+"\n";
+ file.close();
+
+
+
+ InterfaceAddressProc = new QProcess(this);
+ InterfaceAddressProc->addArgument( GlobalConfig->InterpreterShell );
+ InterfaceAddressProc->addArgument(GetIpForInterfaceScript);
+ retrieveInterfaceAddress=true;
+ readOutput=true;
+
+ //connect( InterfaceAddressProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout_interfaceaddress() ) );
+ // connect( InterfaceAddressProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr_interfaceaddress() ) );
+ connect( InterfaceAddressProc, SIGNAL( processExited () ), this, SLOT( processHasFinished() ) );
+
+
+ if ( !InterfaceAddressProc->start(env) )
+ {
+ GlobalConfig->appendLogEntry(i18n("unable to start proc (%1)!").arg(i18n("script for get interface from IP address")), KVpncConfig::error);
+ }
+
+ else
+ {
+ while ( InterfaceAddressProc->isRunning() )
+ {
+ usleep(250);
+// GlobalConfig->appPointer->processEvents();
+ }
+
+ while ( readOutput && retrieveInterfaceAddress == true )
+ {
+ usleep(250);
+// GlobalConfig->appPointer->processEvents();
+ }
+
+ // disconnect( InterfaceAddressProc, SIGNAL( readyReadStdout() ), this, SLOT( readFromStdout_interfaceaddress() ) );
+ // disconnect( InterfaceAddressProc, SIGNAL( readyReadStderr() ), this, SLOT( readFromStderr_interfaceaddress() ) );
+ disconnect( InterfaceAddressProc, SIGNAL( processExited () ), this, SLOT( processHasFinished() ) );
+ //delete InterfaceAddressProc;
+ }
+ }
+ }
+*/
+ if ( !IPforInterface.isEmpty() )
+ {
+ this->IPforInterface = IPforInterface;
+ QStringList devlist = getAllNetworkInterfaces();
+ if (!devlist.isEmpty())
+ {
+ for ( QStringList::Iterator it = devlist.begin(); it != devlist.end(); ++it ) {
+ if (getInterfaceIP(*it) == IPforInterface)
+ return QString(*it);
+ }
+ }
+ else
+ return "";
+ }
+
+ return InterfaceAddress;
+
+}
+
+QString NetworkInterface::getNetmaskOfInterface(QString interface)
+{
+ QFile NetRouteFile ( "/proc/net/route" );
+ QTextStream stream ( &NetRouteFile );
+ QString tmpmask;
+ if ( NetRouteFile .open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+
+ // FIXME netmask is guess to be ok if not 0.0.0.0 or 255.255.255.255
+ if ( line.simplifyWhiteSpace().section( ' ', 1, 1 ) != "00000000" && line.simplifyWhiteSpace().section( ' ', 7, 7 ) != "FFFFFFFF" && line.simplifyWhiteSpace().section( ' ', 0, 0 ) == interface)
+ {
+ struct sockaddr_in name;
+ bool ok=true;
+ std::cout << "netmask of interface "<< interface.ascii() << ": " << line.simplifyWhiteSpace().section( ' ', 7, 7 ).ascii() << "\n";
+ name.sin_addr.s_addr = line.simplifyWhiteSpace().section( ' ', 7, 7 ).toUInt(&ok,16);
+ tmpmask = inet_ntoa(name.sin_addr); // return the value of the netmask
+ NetRouteFile .close();
+ return tmpmask;
+ }
+ }
+ }
+ NetRouteFile .close();
+
+ return "0.0.0.0";
+}
+
+QString NetworkInterface::getDefaultInterface()
+{
+ QFile NetRouteFile ( "/proc/net/route" );
+ QTextStream stream ( &NetRouteFile );
+ QString tmpdev;
+ if ( NetRouteFile .open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ QString tmptarget = line.simplifyWhiteSpace().section( ' ', 1, 1 ); // return the value of the target which is 0.0.0.0
+ if ( tmptarget == "00000000" )
+ {
+ tmpdev = line.simplifyWhiteSpace().section( ' ', 0, 0 ); // return the value of the target which is 0.0.0.0
+ NetRouteFile.close();
+ return tmpdev;
+ }
+ }
+ }
+ NetRouteFile.close();
+
+ return "";
+}
+
+int NetworkInterface::getDefaultRouteCount()
+{
+ QFile NetRouteFile ( "/proc/net/route" );
+ QTextStream stream ( &NetRouteFile );
+ int defaultroutecount=0;
+ if ( NetRouteFile .open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ QString tmptarget = line.simplifyWhiteSpace().section( ' ', 1, 1 ); // return the value of the target which is 0.0.0.0
+ if ( tmptarget == "00000000" )
+ defaultroutecount++;
+ }
+ NetRouteFile.close();
+ }
+
+ return defaultroutecount;
+}
+
+QString NetworkInterface::getGatewayOfInterface(QString interface)
+{
+ QFile NetRouteFile ( "/proc/net/route" );
+ QTextStream stream ( &NetRouteFile );
+ QString tmpgw;
+ if ( NetRouteFile .open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ if (line.simplifyWhiteSpace().section( ' ', 0, 0 ) == interface && line.simplifyWhiteSpace().section( ' ', 1, 1 ) != "00000000")
+ {
+ struct sockaddr_in name;
+ bool ok=true;
+// std::cout << "gateway of interface "<< interface.ascii() << ": " << line.simplifyWhiteSpace().section( ' ', 2, 2 ).ascii() << "\n";
+ name.sin_addr.s_addr = line.simplifyWhiteSpace().section( ' ', 2, 2 ).toUInt(&ok,16);
+ tmpgw = inet_ntoa(name.sin_addr); // return the value of the gateway
+ NetRouteFile .close();
+ return tmpgw;
+ }
+ }
+ }
+ NetRouteFile .close();
+
+ return "0.0.0.0";
+}
+
+QString NetworkInterface::getGatewayOfDefaultInterface()
+{
+ QFile NetRouteFile ( "/proc/net/route" );
+ QTextStream stream ( &NetRouteFile );
+ QString tmpgw;
+ if ( NetRouteFile .open ( IO_ReadOnly ) )
+ {
+ QString line = "";
+ while ( !stream.atEnd() )
+ {
+ line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
+ std::cout << "line: \"" << line << "\"" << "\n";
+ if (line.simplifyWhiteSpace().section( ' ', 1, 1 ) == "00000000" )
+ {
+ struct sockaddr_in name;
+ bool ok=true;
+// std::cout << "gateway of default interface " << ": " << line.simplifyWhiteSpace().section( ' ', 2, 2 ).ascii() << "\n";
+ name.sin_addr.s_addr = line.simplifyWhiteSpace().section( ' ', 2, 2 ).toUInt(&ok,16);
+// std::cout << "s_addr: " << QString().setNum(line.simplifyWhiteSpace().section( ' ', 2, 2 ).stripWhiteSpace().toUInt(&ok,16)) << std::endl;
+ tmpgw = inet_ntoa(name.sin_addr); // return the value of the gateway
+ NetRouteFile .close();
+// std::cout << "gateway of default interface (ascii)" << ": " << tmpgw<< "\n";
+ return tmpgw;
+ }
+ }
+ NetRouteFile .close();
+ }
+ else
+ {
+ std::cerr << "/proc/net/route cant be opened" << std::endl;
+ }
+
+ return "";
+}
+
+QString NetworkInterface::getExternalIpAddress()
+{
+ qInitNetworkProtocols();
+ ExternalIpAddress="";
+ getExternalIpAddressRunning=true;
+ http = new QHttp();
+ connect (http,SIGNAL(readyRead(const QHttpResponseHeader &)), this, SLOT(externalIpDataRecieved(const QHttpResponseHeader &)));
+
+ // FIXME how it could be better?
+ http->setHost( "checkip.dyndns.org" );
+
+ http->get
+ ( "/" );
+ while ( getExternalIpAddressRunning )
+ {
+ usleep(250);
+// GlobalConfig->appPointer->processEvents();
+ }
+ delete http;
+ return ExternalIpAddress;
+}
+
+bool NetworkInterface::inSameNetwork(QString ip1,QString Netmask1,QString ip2,QString Netmask2)
+{
+ // FIXME add valid ipv4 ip check
+ // FIXME add netmask check (subnetworks!)
+ if (ip1==ip2)
+ {
+ std::cout << "ip1 == ip2" << std::endl;
+ return true;
+ }
+ else
+ {
+ std::cout << "ip1: " << ip1.section( '.', 0, 2 ) << " , ip2: " << ip2.section( '.', 0, 2 ) << std::endl;
+ if (ip1.section( '.', 0, 2 ) == ip2.section( '.', 0, 2 ))
+ {
+ if (Netmask1 == Netmask2)
+ {
+ std::cout << "interface1 == interface2 and netmask1 == netmask2" << std::endl;
+ return true;
+ }
+ else
+ return false;
+ }
+ else
+ return false;
+
+ }
+}
+
+void NetworkInterface::readFromStdout()
+{
+ while ( proc->canReadLineStdout() )
+ {
+ QString line = proc->readLineStdout() ;
+ // QString line = QString(proc->readStdout());
+
+
+ /*
+ example for one interface
+
+ eth0 Protokoll:Ethernet Hardware Adresse 00:10:4B:B2:19:00
+ inet Adresse:192.168.0.99 Bcast:192.168.0.255 Maske:255.255.255.0
+ inet6 Adresse: fe80::210:4bff:feb2:1900/64 Gltigkeitsbereich:Verbindung
+ UP BROADCAST NOTRAILERS RUNNING MULTICAST MTU:1500 Metric:1
+ RX packets:31549 errors:0 dropped:0 overruns:0 frame:0
+ TX packets:34046 errors:0 dropped:0 overruns:0 carrier:0
+ Kollisionen:0 Sendewarteschlangenlï¿œge:1000
+ RX bytes:11308743 (10.7 Mb) TX bytes:3701511 (3.5 Mb)
+ Interrupt:10 Basisadresse:0xdc00
+ */
+
+ if ( interfaceTest )
+ {
+ if ( line.find( "proto", 0 , FALSE ) != -1 )
+ {
+ interfaceExists = true;
+ interfaceTest = false;
+ }
+ }
+
+
+ }
+}
+
+void NetworkInterface::readFromStderr()
+{
+ //while ( proc->canReadLineStderr() ) {
+ // QString line = proc->readLineStderr() ;
+ QString line = QString( proc->readStderr() );
+
+ if ( interfaceTest )
+ {
+ interfaceExists = false;
+ interfaceTest = false;
+ }
+ //std::cerr << "dbg err: " << line << std::endl;
+ //}
+}
+
+void NetworkInterface::processHasFinished()
+{
+
+// std::cout << "dbg: processHasFinished():" << std::endl;// << proc->exitStatus() << std::endl;;
+
+ if (retrieveInterfaceAddress )
+ {
+// std::cout << "tmp file: " << tmpfile->name() << std::endl;
+ InterfaceAddress = QString(tmpfile->file()->readAll()).stripWhiteSpace();
+// KMessageBox::information( 0,this->defaultinterface,"default if");
+ // tmpfile->unlink();
+ retrieveInterfaceAddress=false;
+ }
+
+ if (retrieveInterfaceIP)
+ retrieveInterfaceIP=false;
+
+ readOutput=false;
+}
+
+void NetworkInterface::externalIpDataRecieved(const QHttpResponseHeader &)
+{
+ ExternalIpAddress=QString(http->readAll()).stripWhiteSpace().remove ("Current IP Address: ").stripWhiteSpace();
+ getExternalIpAddressRunning=false;
+}
+
+void NetworkInterface::readFromStdout_interfaceip()
+{
+ while ( InterfaceIpProc && InterfaceIpProc->canReadLineStdout() )
+ {
+ QString line = InterfaceIpProc->readLineStdout() ;
+ // QString line = QString(InterfaceIpProc->readStdout());
+
+ if (line.find( "inet ", 0 , FALSE ) != -1 )
+ {
+
+ InterfaceIP = line.simplifyWhiteSpace().section(' ', 1,1).section('/',0,0); // inet 192.168.10.100/24 brd 192.168.10.255 scope global
+ retrieveInterfaceIP=false;
+ // it could more than one ip addresses on a interface. we only need the first.
+ break;
+ }
+ }
+}
+
+void NetworkInterface::readFromStderr_interfaceip()
+{
+ while ( InterfaceIpProc && InterfaceIpProc->canReadLineStderr() )
+ {
+ QString line = InterfaceIpProc->readLineStderr() ;
+ // QString line = QString( InterfaceIpProc->readStderr() );
+
+ if ( interfaceTest )
+ {
+ interfaceExists = false;
+ interfaceTest = false;
+ }
+ //std::cerr << "dbg err: " << line << std::endl;
+ }
+}