-rw-r--r-- | libopie2/opienet/onetwork.cpp | 41 |
1 files changed, 29 insertions, 12 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index 21fa390..cd36f16 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -252,262 +252,264 @@ OMonitoringInterface* ONetworkInterface::monitoring() const const QString& ONetworkInterface::name() const { return _name; } ONetworkInterface::~ONetworkInterface() { qDebug( "ONetworkInterface::~ONetworkInterface()" ); if ( _sfd != -1 ) ::close( _sfd ); } bool ONetworkInterface::setPromiscuousMode( bool b ) { ioctl( SIOCGIFFLAGS ); if ( b ) _ifr.ifr_flags |= IFF_PROMISC; else _ifr.ifr_flags &= (~IFF_PROMISC); return ioctl( SIOCSIFFLAGS ); } bool ONetworkInterface::promiscuousMode() const { ioctl( SIOCGIFFLAGS ); return _ifr.ifr_flags & IFF_PROMISC; } bool ONetworkInterface::isWireless() const { return ioctl( SIOCGIWNAME ); } /*====================================================================================== * OChannelHopper *======================================================================================*/ OChannelHopper::OChannelHopper( OWirelessNetworkInterface* iface ) :QObject( 0, "Mickey's funky hopper" ), _iface( iface ), _interval( 0 ), _channel( 1 ), _tid( 0 ), _maxChannel( iface->channels()+1 ) { } OChannelHopper::~OChannelHopper() { } bool OChannelHopper::isActive() const { return _tid; } int OChannelHopper::channel() const { return _channel; } void OChannelHopper::timerEvent( QTimerEvent* ) { if ( !--_channel ) _channel = _maxChannel; _iface->setChannel( _channel ); qDebug( "OChannelHopper::timerEvent(): set channel %d on interface '%s'", _channel, (const char*) _iface->name() ); } void OChannelHopper::setInterval( int interval ) { if ( interval == _interval ) return; if ( _interval ) killTimer( _tid ); _tid = 0; _interval = interval; if ( _interval ) { _tid = startTimer( interval ); } } int OChannelHopper::interval() const { return _interval; } /*====================================================================================== * OWirelessNetworkInterface *======================================================================================*/ OWirelessNetworkInterface::OWirelessNetworkInterface( const QString& name ) :ONetworkInterface( name ), _hopper( 0 ) { qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" ); init(); } OWirelessNetworkInterface::~OWirelessNetworkInterface() { } iwreqstruct& OWirelessNetworkInterface::iwr() const { return _iwr; } void OWirelessNetworkInterface::init() { qDebug( "OWirelessNetworkInterface::init()" ); memset( &_iwr, 0, sizeof( struct iwreq ) ); // IEEE802.11(b) radio frequency channels - //FIXME: get these directly from the interface - //FIXME: check if these channels are off-by-one iwrangestruct range; + //ML: work around an ugly HostAP bug, which needs + //ML: extra space or will complain with "invalid argument length"... :-( + char __extraBufferForBuggyDrivers[sizeof range]; _iwr.u.data.pointer = (char*) ⦥ - _iwr.u.data.length = sizeof( iwrangestruct ); + _iwr.u.data.length = (sizeof range) * 2; + _iwr.u.data.flags = 0; if ( !wioctl( SIOCGIWRANGE ) ) { qDebug( "OWirelessNetworkInterface::init(): SIOCGIWRANGE failed (%s)", strerror( errno ) ); return; } for ( int i = 0; i < range.num_frequency; ++i ) { int freq = (int) ( double( range.freq[i].m ) * pow( 10, range.freq[i].e ) / 1000000.0 ); _channels.insert( freq, i+1 ); } } 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; } 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, _iwr.u.freq.e ) / 1000000) ]; } } void OWirelessNetworkInterface::setChannel( int c ) const { if ( !_mon ) { memset( &_iwr, 0, sizeof( iwreqstruct ) ); _iwr.u.freq.m = c; _iwr.u.freq.e = 0; wioctl( SIOCSIWFREQ ); } else { _mon->setChannel( c ); } } double OWirelessNetworkInterface::frequency() const { if ( !wioctl( SIOCGIWFREQ ) ) { return -1.0; } else { return double( _iwr.u.freq.m ) * pow( 10, _iwr.u.freq.e ) / 1000000000.0; } } int OWirelessNetworkInterface::channels() const { return _channels.count(); } void OWirelessNetworkInterface::setChannelHopping( int interval ) { if ( !_hopper ) _hopper = new OChannelHopper( this ); _hopper->setInterval( interval ); //FIXME: When and by whom will the channel hopper be deleted? } int OWirelessNetworkInterface::channelHopping() const { return _hopper->interval(); } 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 { return _mon ? _mon->enabled() : false; } 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>"; @@ -596,197 +598,212 @@ void OMonitoringInterface::setEnabled( bool b ) { // open a packet capturer here or leave this to // the client code? /* if ( b ) { OPacketCapturer* opcap = new OPacketCapturer(); opcap->open( _if->name() ); } */ _enabled = b; } /*====================================================================================== * OCiscoMonitoringInterface *======================================================================================*/ OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface ) :OMonitoringInterface( iface ) { iface->setMonitoring( this ); } OCiscoMonitoringInterface::~OCiscoMonitoringInterface() { } void OCiscoMonitoringInterface::setEnabled( bool b ) { QString fname; fname.sprintf( "/proc/driver/aironet/%s", (const char*) _if->name() ); QFile f( fname ); if ( !f.exists() ) return; if ( f.open( IO_WriteOnly ) ) { QTextStream s( &f ); s << "Mode: r"; s << "Mode: y"; s << "XmitPower: 1"; OMonitoringInterface::setEnabled( b ); } // flushing and closing will be done automatically when f goes out of scope } QString OCiscoMonitoringInterface::name() const { return "cisco"; } void OCiscoMonitoringInterface::setChannel( int ) { // cisco devices automatically switch channels when in monitor mode } /*====================================================================================== * OWlanNGMonitoringInterface *======================================================================================*/ OWlanNGMonitoringInterface::OWlanNGMonitoringInterface( ONetworkInterface* iface ) :OMonitoringInterface( iface ) { iface->setMonitoring( this ); } OWlanNGMonitoringInterface::~OWlanNGMonitoringInterface() { } void OWlanNGMonitoringInterface::setEnabled( bool b ) { //FIXME: do nothing if its already in the same mode QString enable = b ? "true" : "false"; QString cmd; cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s", (const char*) _if->name(), 1, (const char*) enable ); system( cmd ); OMonitoringInterface::setEnabled( b ); } QString OWlanNGMonitoringInterface::name() const { return "wlan-ng"; } void OWlanNGMonitoringInterface::setChannel( int ) { // wlan-ng devices automatically switch channels when in monitor mode } /*====================================================================================== * OHostAPMonitoringInterface *======================================================================================*/ OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface ) :OMonitoringInterface( iface ) { iface->setMonitoring( this ); } OHostAPMonitoringInterface::~OHostAPMonitoringInterface() { } void OHostAPMonitoringInterface::setEnabled( bool b ) { // IW_MODE_MONITOR was introduced in Wireless Extensions Version 15 // Wireless Extensions < Version 15 need iwpriv commandos for monitoring - #if WIRELESS_EXT > 14 - _if->_iwr.u.mode = IW_MODE_MONITOR; - _if->wioctl( SIOCSIWMODE ); - #else - int* args = (int*) &_if->_iwr.u.name; - args[0] = 2; - args[1] = 0; - _if->wioctl( SIOCDEVPRIVATE ); - #endif + if ( b ) + { + #if WIRELESS_EXT > 14 + _if->_iwr.u.mode = IW_MODE_MONITOR; + _if->wioctl( SIOCSIWMODE ); + #else + int* args = (int*) &_if->_iwr.u.name; + args[0] = 2; + args[1] = 0; + _if->wioctl( SIOCDEVPRIVATE ); + #endif + } + else + { + #if WIRELESS_EXT > 14 + _if->_iwr.u.mode = IW_MODE_INFRA; + _if->wioctl( SIOCSIWMODE ); + #else + int* args = (int*) &_if->_iwr.u.name; + args[0] = 0; + args[1] = 0; + _if->wioctl( SIOCDEVPRIVATE ); + #endif + } OMonitoringInterface::setEnabled( b ); } QString OHostAPMonitoringInterface::name() const { return "hostap"; } /*====================================================================================== * OOrinocoNetworkInterface *======================================================================================*/ OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface ) :OMonitoringInterface( iface ) { iface->setMonitoring( this ); } OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface() { } void OOrinocoMonitoringInterface::setChannel( int c ) { // call iwpriv <device> monitor 2 <channel> int* args = (int*) &_if->_iwr.u.name; args[0] = 2; args[1] = c; _if->wioctl( SIOCIWFIRSTPRIV + 0x8 ); } void OOrinocoMonitoringInterface::setEnabled( bool b ) { if ( b ) { setChannel( 1 ); } else { // call iwpriv <device> monitor 0 0 int* args = (int*) &_if->_iwr.u.name; args[0] = 0; args[1] = 0; _if->wioctl( SIOCIWFIRSTPRIV + 0x8 ); } OMonitoringInterface::setEnabled( b ); } QString OOrinocoMonitoringInterface::name() const { return "orinoco"; } |