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

565 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 <tqfile.h>
#include <tqtextstream.h>
#include <tdemessagebox.h>
#include <tdelocale.h>
#include <tdeglobal.h>
#include <kstddirs.h>
#include <tqnetwork.h>
#include <tqurloperator.h>
#include <tdemessagebox.h>
#include <arpa/inet.h>
#include <linux/sockios.h>
#include <linux/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
//END INCLUDES
NetworkInterface::NetworkInterface( KVpncConfig* GlobalConfig,TQApplication *app, TQObject *parent, const char *name ) : TQObject( parent, name )
{
this->app = app;
interfaceTest = false;
retrieveInterfaceAddress = false;
TQPtrList<TQString>*InterfaceList = new TQPtrList<TQString>();
InterfaceList->setAutoDelete( TRUE ); // the list owns the objects
TQString InterfaceIP = "";
TQString InterfaceAddress = "";
IPforInterface = "";
tmpInterface = "";
interfaceExists = false;
defaultinterface="default";
readOutput=false;
env = new TQStringList();
*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( TQString Interface )
{
if ( !Interface.isEmpty() )
{
TQFile NetdevFile( "/proc/net/dev" );
TQTextStream stream ( &NetdevFile );
if ( NetdevFile.open ( IO_ReadOnly ) )
{
TQString line = "";
while ( !stream.atEnd() )
{
line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
if ( line.find ( ':' ) > -1 )
{
TQString tmpdev = line.section( ':', 0, 0 ).stripWhiteSpace();
if ( tmpdev == Interface )
{
NetdevFile.close();
return true;
}
}
}
}
NetdevFile.close();
}
return false;
}
TQStringList NetworkInterface::getAllNetworkInterfaces()
{
TQFile NetdevFile( "/proc/net/dev" );
TQTextStream stream ( &NetdevFile );
if ( NetdevFile.open ( IO_ReadOnly ) )
{
TQString 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;
}
TQString NetworkInterface::getInterfaceIP( TQString Interface )
{
//FIXME why this dont work on ppp0 device of l2tp tunnel?
// if ( !Interface.isEmpty() )
// {
// int fd=-1;
// TQString 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 TQString("");
// }
// else
// return TQString("");
// }
// else
// return TQString("");
return getInterfaceIP2(Interface);
}
TQString NetworkInterface::getInterfaceIP2( TQString Interface )
{
if ( !Interface.isEmpty() )
{
InterfaceIpProc = new TQProcess(this);
InterfaceIpProc->addArgument( GlobalConfig->pathToIp );
InterfaceIpProc->addArgument("addr");
InterfaceIpProc->addArgument("show");
InterfaceIpProc->addArgument(Interface);
retrieveInterfaceIP=true;
readOutput=true;
connect( InterfaceIpProc, TQT_SIGNAL( readyReadStdout() ), this, TQT_SLOT( readFromStdout_interfaceip() ) );
connect( InterfaceIpProc, TQT_SIGNAL( readyReadStderr() ), this, TQT_SLOT( readFromStderr_interfaceip() ) );
connect( InterfaceIpProc, TQT_SIGNAL( processExited () ), this, TQT_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, TQT_SIGNAL( readyReadStdout() ), this, TQT_SLOT( readFromStdout_interfaceip() ) );
disconnect( InterfaceIpProc, TQT_SIGNAL( readyReadStderr() ), this, TQT_SLOT( readFromStderr_interfaceip() ) );
disconnect( InterfaceIpProc, TQT_SIGNAL( processExited () ), this, TQT_SLOT( processHasFinished() ) );
delete InterfaceIpProc;
InterfaceIpProc=0L;
}
return InterfaceIP;
}
TQString NetworkInterface::getInterfaceAddress( TQString IPforInterface )
{
/*
// TODO fixme
if ( !IPforInterface.isEmpty() )
{
this->IPforInterface = IPforInterface;
TQStringList devlist = getAllNetworkInterfaces();
tmpfile = new KTempFile();
TQString tmpPath = locateLocal ( "data", "kvpnc/" );
TQString GetIpForInterfaceScript = tmpPath + "get_interface_for_ip_"+IPforInterface+".sh";
TQFile file ( GetIpForInterfaceScript );
TQTextStream 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 TQProcess(this);
InterfaceAddressProc->addArgument( GlobalConfig->InterpreterShell );
InterfaceAddressProc->addArgument(GetIpForInterfaceScript);
retrieveInterfaceAddress=true;
readOutput=true;
//connect( InterfaceAddressProc, TQT_SIGNAL( readyReadStdout() ), this, TQT_SLOT( readFromStdout_interfaceaddress() ) );
// connect( InterfaceAddressProc, TQT_SIGNAL( readyReadStderr() ), this, TQT_SLOT( readFromStderr_interfaceaddress() ) );
connect( InterfaceAddressProc, TQT_SIGNAL( processExited () ), this, TQT_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, TQT_SIGNAL( readyReadStdout() ), this, TQT_SLOT( readFromStdout_interfaceaddress() ) );
// disconnect( InterfaceAddressProc, TQT_SIGNAL( readyReadStderr() ), this, TQT_SLOT( readFromStderr_interfaceaddress() ) );
disconnect( InterfaceAddressProc, TQT_SIGNAL( processExited () ), this, TQT_SLOT( processHasFinished() ) );
//delete InterfaceAddressProc;
}
}
}
*/
if ( !IPforInterface.isEmpty() )
{
this->IPforInterface = IPforInterface;
TQStringList devlist = getAllNetworkInterfaces();
if (!devlist.isEmpty())
{
for ( TQStringList::Iterator it = devlist.begin(); it != devlist.end(); ++it ) {
if (getInterfaceIP(*it) == IPforInterface)
return TQString(*it);
}
}
else
return "";
}
return InterfaceAddress;
}
TQString NetworkInterface::getNetmaskOfInterface(TQString interface)
{
TQFile NetRouteFile ( "/proc/net/route" );
TQTextStream stream ( &NetRouteFile );
TQString tmpmask;
if ( NetRouteFile .open ( IO_ReadOnly ) )
{
TQString 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";
}
TQString NetworkInterface::getDefaultInterface()
{
TQFile NetRouteFile ( "/proc/net/route" );
TQTextStream stream ( &NetRouteFile );
TQString tmpdev;
if ( NetRouteFile .open ( IO_ReadOnly ) )
{
TQString line = "";
while ( !stream.atEnd() )
{
line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
TQString 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()
{
TQFile NetRouteFile ( "/proc/net/route" );
TQTextStream stream ( &NetRouteFile );
int defaultroutecount=0;
if ( NetRouteFile .open ( IO_ReadOnly ) )
{
TQString line = "";
while ( !stream.atEnd() )
{
line = stream.readLine(); // line of text excluding '\n' and replace all white chars with one blank
TQString 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;
}
TQString NetworkInterface::getGatewayOfInterface(TQString interface)
{
TQFile NetRouteFile ( "/proc/net/route" );
TQTextStream stream ( &NetRouteFile );
TQString tmpgw;
if ( NetRouteFile .open ( IO_ReadOnly ) )
{
TQString 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";
}
TQString NetworkInterface::getGatewayOfDefaultInterface()
{
TQFile NetRouteFile ( "/proc/net/route" );
TQTextStream stream ( &NetRouteFile );
TQString tmpgw;
if ( NetRouteFile .open ( IO_ReadOnly ) )
{
TQString 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: " << TQString().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 "";
}
TQString NetworkInterface::getExternalIpAddress()
{
tqInitNetworkProtocols();
ExternalIpAddress="";
getExternalIpAddressRunning=true;
http = new TQHttp();
connect (http,TQT_SIGNAL(readyRead(const TQHttpResponseHeader &)), this, TQT_SLOT(externalIpDataRecieved(const TQHttpResponseHeader &)));
// 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(TQString ip1,TQString Netmask1,TQString ip2,TQString 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() )
{
TQString line = proc->readLineStdout() ;
// TQString line = TQString(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() ) {
// TQString line = proc->readLineStderr() ;
TQString line = TQString( 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 = TQString(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 TQHttpResponseHeader &)
{
ExternalIpAddress=TQString(http->readAll()).stripWhiteSpace().remove ("Current IP Address: ").stripWhiteSpace();
getExternalIpAddressRunning=false;
}
void NetworkInterface::readFromStdout_interfaceip()
{
while ( InterfaceIpProc && InterfaceIpProc->canReadLineStdout() )
{
TQString line = InterfaceIpProc->readLineStdout() ;
// TQString line = TQString(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() )
{
TQString line = InterfaceIpProc->readLineStderr() ;
// TQString line = TQString( InterfaceIpProc->readStderr() );
if ( interfaceTest )
{
interfaceExists = false;
interfaceTest = false;
}
//std::cerr << "dbg err: " << line << std::endl;
}
}