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.
kvpnc/src/networkinterface.cpp

564 lines
18 KiB

/***************************************************************************
* 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;
}
}