summaryrefslogtreecommitdiff
authormickeyl <mickeyl>2003-10-09 16:01:08 (UTC)
committer mickeyl <mickeyl>2003-10-09 16:01:08 (UTC)
commit802c9ab6b89fd10f709aa012e8ff075e9b4a5d7f (patch) (side-by-side diff)
treec6a33ab027752ca04d0d98a2e71a238aa954978d
parentc5c5c9f9fc6cab574f35f8be21076ac81f8c0369 (diff)
downloadopie-802c9ab6b89fd10f709aa012e8ff075e9b4a5d7f.zip
opie-802c9ab6b89fd10f709aa012e8ff075e9b4a5d7f.tar.gz
opie-802c9ab6b89fd10f709aa012e8ff075e9b4a5d7f.tar.bz2
- fix monitor mode on orinoco. Although WE > 14 define the standard mode
"MONITOR", the orinoco monitor patch for 0.13e still does not use that... - add documentation, a warning, and a runtime check for setChannel(0)
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--libopie2/opienet/onetwork.cpp12
-rw-r--r--libopie2/opienet/onetwork.h2
2 files changed, 12 insertions, 2 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp
index 45ee4c0..767651e 100644
--- a/libopie2/opienet/onetwork.cpp
+++ b/libopie2/opienet/onetwork.cpp
@@ -500,192 +500,198 @@ void OWirelessNetworkInterface::buildChannelList()
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 ) );
_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
}
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 ) );
}
// </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 );
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." );
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." );
}
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!" );
+ return;
+ }
+
if ( !_mon )
{
memset( &_iwr, 0, sizeof( struct iwreq ) );
_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.0, _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?
//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
}
}
@@ -846,195 +852,197 @@ bool OMonitoringInterface::enabled() const
void OMonitoringInterface::setEnabled( bool b )
{
}
/*======================================================================================
* OCiscoMonitoringInterface
*======================================================================================*/
OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface, bool prismHeader )
:OMonitoringInterface( iface, prismHeader )
{
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";
}
// 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, bool prismHeader )
:OMonitoringInterface( iface, prismHeader )
{
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 prism = _prismHeader ? "true" : "false";
QString cmd;
cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s prismheader=%s",
(const char*) _if->name(), 1, (const char*) enable, (const char*) prism );
system( cmd );
}
QString OWlanNGMonitoringInterface::name() const
{
return "wlan-ng";
}
void OWlanNGMonitoringInterface::setChannel( int c )
{
//NOTE: Older wlan-ng drivers automatically hopped channels while lnxreq_wlansniff=true. Newer ones don't.
QString enable = "true"; //_if->monitorMode() ? "true" : "false";
QString prism = _prismHeader ? "true" : "false";
QString cmd;
cmd.sprintf( "$(which wlanctl-ng) %s lnxreq_wlansniff channel=%d enable=%s prismheader=%s",
- (const char*) _if->name(), c+1, (const char*) enable, (const char*) prism );
+ (const char*) _if->name(), c, (const char*) enable, (const char*) prism );
system( cmd );
}
/*======================================================================================
* OHostAPMonitoringInterface
*======================================================================================*/
OHostAPMonitoringInterface::OHostAPMonitoringInterface( ONetworkInterface* iface, bool prismHeader )
:OMonitoringInterface( iface, prismHeader )
{
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 ( b )
_if->setMode( "monitor" ); // IW_MODE_MONITOR doesn't support prism header
else
_if->setMode( "managed" );
#else
int monitorCode = _prismHeader ? 1 : 2;
if ( b )
{
_if->setPrivate( "monitor", 1, monitorCode );
}
else
{
_if->setPrivate( "monitor", 1, 0 );
}
#endif
}
QString OHostAPMonitoringInterface::name() const
{
return "hostap";
}
/*======================================================================================
* OOrinocoNetworkInterface
*======================================================================================*/
OOrinocoMonitoringInterface::OOrinocoMonitoringInterface( ONetworkInterface* iface, bool prismHeader )
:OMonitoringInterface( iface, prismHeader )
{
iface->setMonitoring( this );
}
OOrinocoMonitoringInterface::~OOrinocoMonitoringInterface()
{
}
void OOrinocoMonitoringInterface::setChannel( int c )
{
int monitorCode = _prismHeader ? 1 : 2;
_if->setPrivate( "monitor", 2, monitorCode, c );
}
void OOrinocoMonitoringInterface::setEnabled( bool b )
{
// IW_MODE_MONITOR was introduced in Wireless Extensions Version 15
// Wireless Extensions < Version 15 need iwpriv commandos for monitoring
+ // However, as of recent orinoco drivers, IW_MODE_MONITOR is still not supported
- #if WIRELESS_EXT > 14
+ #if 0
+ //#if WIRELESS_EXT > 14
if ( b )
_if->setMode( "monitor" ); // IW_MODE_MONITOR doesn't support prism header
else
_if->setMode( "managed" );
#else
if ( b )
{
setChannel( 1 );
}
else
{
_if->setPrivate( "monitor", 2, 0, 0 );
}
#endif
}
QString OOrinocoMonitoringInterface::name() const
{
return "orinoco";
}
diff --git a/libopie2/opienet/onetwork.h b/libopie2/opienet/onetwork.h
index 2553a61..00d1ebb 100644
--- a/libopie2/opienet/onetwork.h
+++ b/libopie2/opienet/onetwork.h
@@ -243,192 +243,194 @@ class ONetworkInterface : public QObject
/*======================================================================================
* OChannelHopper
*======================================================================================*/
/**
* @brief A radio frequency channel hopper.
*
* This class provides a channel hopper for radio frequencies. A channel hopper frequently
* changes the radio frequency channel of its associated @ref OWirelessNetworkInterface.
* This is necessary when in monitoring mode and scanning for other devices, because
* the radio frequency hardware can only detect packets sent on the same frequency.
*
* @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
*/
class OChannelHopper : public QObject
{
Q_OBJECT
public:
/**
* Constructor.
*/
OChannelHopper( OWirelessNetworkInterface* );
/**
* Destructor.
*/
virtual ~OChannelHopper();
/**
* @returns true, if the channel hopper is hopping channels
*/
bool isActive() const;
/**
* @returns the last hopped channel
*/
int channel() const;
/**
* Set the channel hopping @a interval.
* An interval of 0 deactivates the channel hopper.
*/
void setInterval( int interval );
/**
* @returns the channel hopping interval
*/
int interval() const;
signals:
/**
* This signal is emitted right after the channel hopper performed a hop
*/
void hopped( int );
protected:
virtual void timerEvent( QTimerEvent* );
private:
OWirelessNetworkInterface* _iface;
int _interval;
int _tid;
QValueList<int> _channels;
QValueList<int>::Iterator _channel;
};
/*======================================================================================
* OWirelessNetworkInterface
*======================================================================================*/
/**
* @brief A network interface wrapper for interfaces supporting the wireless extensions protocol.
*
* This class provides a high-level encapsulation of the Linux wireless extension API.
*
* @author Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de>
*/
class OWirelessNetworkInterface : public ONetworkInterface
{
friend class OMonitoringInterface;
friend class OCiscoMonitoringInterface;
friend class OWlanNGMonitoringInterface;
friend class OHostAPMonitoringInterface;
friend class OOrinocoMonitoringInterface;
friend class OPrivateIOCTL;
public:
/**
* Constructor.
*/
OWirelessNetworkInterface( QObject* parent, const char* name );
/**
* Destructor.
*/
virtual ~OWirelessNetworkInterface();
/**
* Setting the @a channel of the interface changes the radio frequency (RF)
* of the corresponding wireless network device.
+ * @note Common channel range is within [1-14]. A value of 0 is not allowed.
+ * @see channels()
*/
virtual void setChannel( int channel ) const;
/**
* @returns the channel index of the current radio frequency.
*/
virtual int channel() const;
/**
* @returns the current radio frequency (in MHz).
*/
virtual double frequency() const;
/**
* @returns the number of radio frequency channels for the
* corresponding wireless network device.
* @note European devices usually have 14 channels, while American typically feature 11 channels.
*/
virtual int channels() const;
/**
* Set the IEEE 802.11 operation @a mode.
* Valid values are <ul><li>adhoc<li>managed<li>monitor<li>master
* @warning Not all drivers support the all modes.
* @note You might have to change the SSID to get the operation mode change into effect.
*/
virtual void setMode( const QString& mode );
/**
* @returns the current IEEE 802.11 operation mode.
* Possible values are <ul><li>adhoc<li>managed<li>monitor<li>master or <li>unknown
*/
virtual QString mode() const;
/**
* Setting the monitor mode on a wireless network interface enables
* listening to IEEE 802.11 data and management frames which normally
* are handled by the device firmware. This can be used to detect
* other wireless network devices, e.g. Access Points or Ad-hoc stations.
* @warning Standard wireless network drives don't support the monitor mode.
* @warning You need a patched driver for this to work.
* @note Enabling the monitor mode is highly driver dependent and requires
* the proper @ref OMonitoringInterface to be associated with the interface.
* @see OMonitoringInterface
*/
virtual void setMonitorMode( bool ); //FIXME: ==> setMode( "monitor" );
/**
* @returns true if the device is listening in IEEE 802.11 monitor mode
*/
virtual bool monitorMode() const; //FIXME: ==> mode()
/**
* Set the channel hopping @a interval. An @a interval of 0 disables channel hopping.
* @see OChannelHopper
*/
virtual void setChannelHopping( int interval = 0 );
/**
* @returns the channel hopping interval or 0, if channel hopping is disabled.
*/
virtual int channelHopping() const;
/**
* @returns the @ref OChannelHopper of this interface or 0, if channel hopping has not been activated before
*/
virtual OChannelHopper* channelHopper() const;
/**
* Set the station @a nickname.
*/
virtual void setNickName( const QString& nickname );
/**
* @returns the current station nickname.
*/
virtual QString nickName() const;
/**
* Invoke the private IOCTL @a command with a @number of parameters on the network interface.
* @see OPrivateIOCTL
*/
virtual void setPrivate( const QString& command, int number, ... );
/**
* @returns true if the interface is featuring the private IOCTL @command.
*/
virtual bool hasPrivate( const QString& command );
virtual void getPrivate( const QString& command ); //FIXME: Implement and document this
virtual bool isAssociated() const {}; //FIXME: Implement and document this
/**
* @returns the MAC address of the Access Point if the
* device is in infrastructure mode. @returns a (more or less random) CELL
* address if the device is in adhoc mode.
*/
virtual QString associatedAP() const;
/**
* Set the @a ssid (Service Set ID) string. This is used to decide
* which network to associate with (use "any" to let the driver decide).
*/
virtual void setSSID( const QString& ssid );
/**
* @returns the current SSID (Service Set ID).
*/
virtual QString SSID() const;
protected:
void buildChannelList();
void buildPrivateList();