diff options
Diffstat (limited to 'src/networkinterface.cpp')
-rw-r--r-- | src/networkinterface.cpp | 563 |
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; + } +} |