summaryrefslogtreecommitdiff
path: root/libopie2/opienet/onetwork.cpp
Side-by-side diff
Diffstat (limited to 'libopie2/opienet/onetwork.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opienet/onetwork.cpp113
1 files changed, 97 insertions, 16 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp
index dc2e388..be45924 100644
--- a/libopie2/opienet/onetwork.cpp
+++ b/libopie2/opienet/onetwork.cpp
@@ -55,48 +55,49 @@
#include <linux/sockios.h>
#include <net/if_arp.h>
#include <stdarg.h>
using namespace std;
/*======================================================================================
* ONetwork
*======================================================================================*/
ONetwork* ONetwork::_instance = 0;
ONetwork::ONetwork()
{
qDebug( "ONetwork::ONetwork()" );
qDebug( "ONetwork: This code has been compiled against Wireless Extensions V%d", WIRELESS_EXT );
synchronize();
}
void ONetwork::synchronize()
{
// gather available interfaces by inspecting /proc/net/dev
//FIXME: we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices
//FIXME: Use SIOCGIFCONF anway, because we can disable listing of aliased devices
+ //FIXME: Best is use SIOCGIFCONF and if this doesn't work (result=-1), then fallback to parsing /proc/net/dev
_interfaces.clear();
QString str;
QFile f( "/proc/net/dev" );
bool hasFile = f.open( IO_ReadOnly );
if ( !hasFile )
{
qDebug( "ONetwork: /proc/net/dev not existing. No network devices available" );
return;
}
QTextStream s( &f );
s.readLine();
s.readLine();
while ( !s.atEnd() )
{
s >> str;
str.truncate( str.find( ':' ) );
qDebug( "ONetwork: found interface '%s'", (const char*) str );
ONetworkInterface* iface;
if ( isWirelessInterface( str ) )
{
iface = new OWirelessNetworkInterface( this, (const char*) str );
qDebug( "ONetwork: interface '%s' has Wireless Extensions", (const char*) str );
}
@@ -167,51 +168,51 @@ ONetworkInterface::ONetworkInterface( QObject* parent, const char* name )
struct ifreq& ONetworkInterface::ifr() const
{
return _ifr;
}
void ONetworkInterface::init()
{
qDebug( "ONetworkInterface::init()" );
memset( &_ifr, 0, sizeof( struct ifreq ) );
if ( _sfd == -1 )
{
qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", name() );
return;
}
}
bool ONetworkInterface::ioctl( int call, struct ifreq& ifreq ) const
{
int result = ::ioctl( _sfd, call, &ifreq );
if ( result == -1 )
- qDebug( "ONetworkInterface::ioctl (%s) call %d - Status: Failed: %d (%s)", name(), call, result, strerror( errno ) );
+ qDebug( "ONetworkInterface::ioctl (%s) call %d (0x%04X) - Status: Failed: %d (%s)", name(), call, call, result, strerror( errno ) );
else
- qDebug( "ONetworkInterface::ioctl (%s) call %d - Status: Ok.", name(), call );
+ qDebug( "ONetworkInterface::ioctl (%s) call %d (0x%04X) - Status: Ok.", name(), call, call );
return ( result != -1 );
}
bool ONetworkInterface::ioctl( int call ) const
{
strcpy( _ifr.ifr_name, name() );
return ioctl( call, _ifr );
}
bool ONetworkInterface::isLoopback() const
{
ioctl( SIOCGIFFLAGS );
return _ifr.ifr_flags & IFF_LOOPBACK;
}
bool ONetworkInterface::setUp( bool b )
{
ioctl( SIOCGIFFLAGS );
if ( b ) _ifr.ifr_flags |= IFF_UP;
else _ifr.ifr_flags &= (~IFF_UP);
return ioctl( SIOCSIFFLAGS );
@@ -433,166 +434,188 @@ int OChannelHopper::interval() const
OWirelessNetworkInterface::OWirelessNetworkInterface( QObject* parent, const char* name )
:ONetworkInterface( parent, name ), _hopper( 0 )
{
qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" );
init();
}
OWirelessNetworkInterface::~OWirelessNetworkInterface()
{
}
struct iwreq& OWirelessNetworkInterface::iwr() const
{
return _iwr;
}
void OWirelessNetworkInterface::init()
{
qDebug( "OWirelessNetworkInterface::init()" );
memset( &_iwr, 0, sizeof( struct iwreq ) );
- buildChannelList();
+ buildInformation();
buildPrivateList();
+ dumpInformation();
+}
+
+
+bool OWirelessNetworkInterface::isAssociated() const
+{
+ //FIXME: handle different modes
+ return associatedAP() != "44:44:44:44:44:44";
}
QString OWirelessNetworkInterface::associatedAP() const
{
//FIXME: use OMacAddress
QString mac;
if ( ioctl( SIOCGIWAP ) )
{
mac.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
_ifr.ifr_hwaddr.sa_data[0]&0xff,
_ifr.ifr_hwaddr.sa_data[1]&0xff,
_ifr.ifr_hwaddr.sa_data[2]&0xff,
_ifr.ifr_hwaddr.sa_data[3]&0xff,
_ifr.ifr_hwaddr.sa_data[4]&0xff,
_ifr.ifr_hwaddr.sa_data[5]&0xff );
}
else
{
mac = "<Unknown>";
}
return mac;
}
-void OWirelessNetworkInterface::buildChannelList()
+void OWirelessNetworkInterface::buildInformation()
{
//ML: If you listen carefully enough, you can hear lots of WLAN drivers suck
//ML: The HostAP drivers need more than sizeof struct_iw range to complete
//ML: SIOCGIWRANGE otherwise they fail with "Invalid Argument Length".
//ML: The Wlan-NG drivers on the otherside fail (segfault!) if you allocate
//ML: _too much_ space. This is damn shitty crap *sigh*
//ML: We allocate a large memory region in RAM and check whether the
//ML: driver pollutes this extra space. The complaint will be made on stdout,
//ML: so please forward this...
struct iwreq wrq;
int len = sizeof( struct iw_range )*2;
char *buffer = (char*) malloc( len );
//FIXME: Validate if we actually got the memory block
memset( buffer, 0, len );
memcpy( wrq.ifr_name, name(), IFNAMSIZ);
wrq.u.data.pointer = (caddr_t) buffer;
wrq.u.data.length = sizeof( struct iw_range );
wrq.u.data.flags = 0;
if ( ::ioctl( _sfd, SIOCGIWRANGE, &wrq ) == -1 )
{
- qDebug( "OWirelessNetworkInterface::buildChannelList(): SIOCGIWRANGE failed (%s) - defaulting to 11 channels", strerror( errno ) );
+ qDebug( "OWirelessNetworkInterface::buildInformation(): SIOCGIWRANGE failed (%s) - using default values.", strerror( errno ) );
_channels.insert( 2412, 1 ); // 2.412 GHz
_channels.insert( 2417, 2 ); // 2.417 GHz
_channels.insert( 2422, 3 ); // 2.422 GHz
_channels.insert( 2427, 4 ); // 2.427 GHz
_channels.insert( 2432, 5 ); // 2.432 GHz
_channels.insert( 2437, 6 ); // 2.437 GHz
_channels.insert( 2442, 7 ); // 2.442 GHz
_channels.insert( 2447, 8 ); // 2.447 GHz
_channels.insert( 2452, 9 ); // 2.452 GHz
_channels.insert( 2457, 10 ); // 2.457 GHz
_channels.insert( 2462, 11 ); // 2.462 GHz
+
+ memset( &_range, 0, sizeof( struct iw_range ) );
}
else
{
// <check if the driver overwrites stuff>
int max = 0;
for ( int r = sizeof( struct iw_range ); r < len; r++ )
if (buffer[r] != 0)
max = r;
if (max > 0)
{
- qWarning( "OWirelessNetworkInterface::buildChannelList(): Driver for wireless interface '%s'"
- "overwrote buffer end with at least %i bytes!\n", name(), max - sizeof( struct iw_range ) );
+ qWarning( "OWirelessNetworkInterface::buildInformation(): Driver for wireless interface '%s' sucks!\n"
+ "It overwrote the buffer end with at least %i bytes!\n", name(), max - sizeof( struct iw_range ) );
}
// </check if the driver overwrites stuff>
struct iw_range range;
memcpy( &range, buffer, sizeof range );
- qDebug( "OWirelessNetworkInterface::buildChannelList(): Interface %s reported to have %d channels.", name(), range.num_frequency );
+ qDebug( "OWirelessNetworkInterface::buildInformation(): Interface %s reported to have %d channels.", name(), range.num_frequency );
for ( int i = 0; i < range.num_frequency; ++i )
{
int freq = (int) ( double( range.freq[i].m ) * pow( 10.0, range.freq[i].e ) / 1000000.0 );
_channels.insert( freq, i+1 );
}
}
- qDebug( "OWirelessNetworkInterface::buildChannelList(): Channel list constructed." );
+ memcpy( &_range, buffer, sizeof( struct iw_range ) );
+ qDebug( "OWirelessNetworkInterface::buildInformation(): Information block constructed." );
free(buffer);
}
void OWirelessNetworkInterface::buildPrivateList()
{
qDebug( "OWirelessNetworkInterface::buildPrivateList()" );
struct iw_priv_args priv[IW_MAX_PRIV_DEF];
_iwr.u.data.pointer = (char*) &priv;
_iwr.u.data.length = IW_MAX_PRIV_DEF; // length in terms of number of (sizeof iw_priv_args), not (sizeof iw_priv_args) itself
_iwr.u.data.flags = 0;
if ( !wioctl( SIOCGIWPRIV ) )
{
qDebug( "OWirelessNetworkInterface::buildPrivateList(): SIOCGIWPRIV failed (%s) - can't get private ioctl information.", strerror( errno ) );
return;
}
for ( int i = 0; i < _iwr.u.data.length; ++i )
{
new OPrivateIOCTL( this, priv[i].name, priv[i].cmd, priv[i].get_args, priv[i].set_args );
}
qDebug( "OWirelessNetworkInterface::buildPrivateList(): Private IOCTL list constructed." );
}
+void OWirelessNetworkInterface::dumpInformation() const
+{
+ qDebug( "OWirelessNetworkInterface::() -------------- dumping information block ----------------" );
+
+ qDebug( " - driver's idea of maximum throughput is %d bps = %d byte/s = %d Kb/s = %f.2 Mb/s", _range.throughput, _range.throughput / 8, _range.throughput / 8 / 1024, float( _range.throughput ) / 8.0 / 1024.0 / 1024.0 );
+ qDebug( " - driver for '%s' has been compiled against WE V%d (source=V%d)", name(), _range.we_version_compiled, _range.we_version_source );
+
+ qDebug( "OWirelessNetworkInterface::() ---------------------------------------------------------" );
+}
+
+
int OWirelessNetworkInterface::channel() const
{
//FIXME: When monitoring enabled, then use it
//FIXME: to gather the current RF channel
//FIXME: Until then, get active channel from hopper.
if ( _hopper && _hopper->isActive() )
return _hopper->channel();
if ( !wioctl( SIOCGIWFREQ ) )
{
return -1;
}
else
{
return _channels[ static_cast<int>(double( _iwr.u.freq.m ) * pow( 10.0, _iwr.u.freq.e ) / 1000000) ];
}
}
void OWirelessNetworkInterface::setChannel( int c ) const
{
if ( !c )
{
qWarning( "OWirelessNetworkInterface::setChannel( 0 ) called - fix your application!" );
@@ -640,96 +663,93 @@ void OWirelessNetworkInterface::setChannelHopping( int interval )
//TODO: rely on QObject hierarchy
}
int OWirelessNetworkInterface::channelHopping() const
{
return _hopper->interval();
}
OChannelHopper* OWirelessNetworkInterface::channelHopper() const
{
return _hopper;
}
void OWirelessNetworkInterface::setMode( const QString& mode )
{
if ( mode == "auto" ) _iwr.u.mode = IW_MODE_AUTO;
else if ( mode == "adhoc" ) _iwr.u.mode = IW_MODE_ADHOC;
else if ( mode == "managed" ) _iwr.u.mode = IW_MODE_INFRA;
else if ( mode == "master" ) _iwr.u.mode = IW_MODE_MASTER;
else if ( mode == "repeater" ) _iwr.u.mode = IW_MODE_REPEAT;
else if ( mode == "secondary" ) _iwr.u.mode = IW_MODE_SECOND;
- #if WIRELESS_EXT > 14
else if ( mode == "monitor" ) _iwr.u.mode = IW_MODE_MONITOR;
- #endif
else
{
qDebug( "ONetwork: Warning! Invalid IEEE 802.11 mode '%s' specified.", (const char*) mode );
return;
}
wioctl( SIOCSIWMODE );
}
QString OWirelessNetworkInterface::mode() const
{
if ( !wioctl( SIOCGIWMODE ) )
{
return "<unknown>";
}
switch ( _iwr.u.mode )
{
case IW_MODE_AUTO: return "auto";
case IW_MODE_ADHOC: return "adhoc";
case IW_MODE_INFRA: return "managed";
case IW_MODE_MASTER: return "master";
case IW_MODE_REPEAT: return "repeater";
case IW_MODE_SECOND: return "secondary";
- #if WIRELESS_EXT > 14
case IW_MODE_MONITOR: return "monitor";
- #endif
default: assert( 0 ); // shouldn't happen
}
}
void OWirelessNetworkInterface::setMonitorMode( bool b )
{
if ( _mon )
_mon->setEnabled( b );
else
qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" );
}
bool OWirelessNetworkInterface::monitorMode() const
{
qDebug( "dataLinkType = %d", dataLinkType() );
return ( dataLinkType() == ARPHRD_IEEE80211 || dataLinkType() == 802 );
- // 802 is the header type for PRISM - Linux support for this is pending...
+ //FIXME: 802 is the header type for PRISM - Linux support for this is pending...
+ //FIXME: What is 119, by the way?
}
void OWirelessNetworkInterface::setNickName( const QString& nickname )
{
_iwr.u.essid.pointer = const_cast<char*>( (const char*) nickname );
_iwr.u.essid.length = nickname.length();
wioctl( SIOCSIWNICKN );
}
QString OWirelessNetworkInterface::nickName() const
{
char str[IW_ESSID_MAX_SIZE];
_iwr.u.data.pointer = &str[0];
_iwr.u.data.length = IW_ESSID_MAX_SIZE;
if ( !wioctl( SIOCGIWNICKN ) )
{
return "<unknown>";
}
else
{
str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
return str;
@@ -779,55 +799,116 @@ bool OWirelessNetworkInterface::hasPrivate( const QString& call )
QString OWirelessNetworkInterface::SSID() const
{
char str[IW_ESSID_MAX_SIZE];
_iwr.u.essid.pointer = &str[0];
_iwr.u.essid.length = IW_ESSID_MAX_SIZE;
if ( !wioctl( SIOCGIWESSID ) )
{
return "<unknown>";
}
else
{
return str;
}
}
void OWirelessNetworkInterface::setSSID( const QString& ssid )
{
_iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
_iwr.u.essid.length = ssid.length();
wioctl( SIOCSIWESSID );
}
+int OWirelessNetworkInterface::scanNetwork()
+{
+ _iwr.u.param.flags = IW_SCAN_DEFAULT;
+ _iwr.u.param.value = 0;
+ if ( !wioctl( SIOCSIWSCAN ) )
+ {
+ return -1;
+ }
+
+ int timeout = 1000000;
+
+ qDebug( "ONetworkInterface::scanNetwork() - scan started." );
+
+ bool results = false;
+ struct timeval tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 250000; // initial timeout ~ 250ms
+ char buffer[IW_SCAN_MAX_DATA];
+
+ while ( !results && timeout > 0 )
+ {
+ timeout -= tv.tv_usec;
+ select( 0, 0, 0, 0, &tv );
+
+ _iwr.u.data.pointer = &buffer[0];
+ _iwr.u.data.flags = 0;
+ _iwr.u.data.length = sizeof buffer;
+ if ( wioctl( SIOCGIWSCAN ) )
+ {
+ results = true;
+ continue;
+ }
+ else if ( errno == EAGAIN)
+ {
+ qDebug( "ONetworkInterface::scanNetwork() - scan in progress..." );
+ #if 0
+ if ( qApp )
+ {
+ qApp->processEvents( 100 );
+ continue;
+ }
+ #endif
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ continue;
+ }
+ }
+
+ qDebug( "ONetworkInterface::scanNetwork() - scan finished." );
+
+ if ( results )
+ {
+ qDebug( " - results are in!" );
+ }
+ else
+ {
+ qDebug( " - no results :(" );
+ }
+}
+
+
bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const
{
int result = ::ioctl( _sfd, call, &iwreq );
if ( result == -1 )
- qDebug( "ONetworkInterface::wioctl (%s) call %d - Status: Failed: %d (%s)", name(), call, result, strerror( errno ) );
+ qDebug( "ONetworkInterface::wioctl (%s) call %d (0x%04X) - Status: Failed: %d (%s)", name(), call, call, result, strerror( errno ) );
else
- qDebug( "ONetworkInterface::wioctl (%s) call %d - Status: Ok.", name(), call );
+ qDebug( "ONetworkInterface::wioctl (%s) call %d (0x%04X) - Status: Ok.", name(), call, call );
return ( result != -1 );
}
bool OWirelessNetworkInterface::wioctl( int call ) const
{
strcpy( _iwr.ifr_name, name() );
return wioctl( call, _iwr );
}
/*======================================================================================
* OMonitoringInterface
*======================================================================================*/
OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface, bool prismHeader )
:_if( static_cast<OWirelessNetworkInterface*>( iface ) ), _prismHeader( prismHeader )
{
}
OMonitoringInterface::~OMonitoringInterface()
{
}