/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include //END INCLUDES NetworkInterface::NetworkInterface( KVpncConfig* GlobalConfig,QApplication *app, QObject *parent, const char *name ) : QObject( parent, name ) { this->app = app; interfaceTest = false; retrieveInterfaceAddress = false; QPtrList*InterfaceList = new QPtrList(); 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; } }