author | mickeyl <mickeyl> | 2003-04-04 10:31:26 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-04-04 10:31:26 (UTC) |
commit | 089385bb8ab768fbf6f394f326e565e3589163fc (patch) (side-by-side diff) | |
tree | 23891b81b11310186c43179612531bc92e52ae65 /libopie2/opienet | |
parent | 7da7e9cbfb52988ce801310f66b1336e0809db28 (diff) | |
download | opie-089385bb8ab768fbf6f394f326e565e3589163fc.zip opie-089385bb8ab768fbf6f394f326e565e3589163fc.tar.gz opie-089385bb8ab768fbf6f394f326e565e3589163fc.tar.bz2 |
low-level network programming is sick. some wlan-drivers don't honor struct sizes
and simply write bytes _after_ the struct... this patch makes calling
SIOCGIWRANGE more failure-proof.
-rw-r--r-- | libopie2/opienet/onetutils.cpp | 1 | ||||
-rw-r--r-- | libopie2/opienet/onetwork.cpp | 57 | ||||
-rw-r--r-- | libopie2/opienet/onetwork.h | 19 |
3 files changed, 47 insertions, 30 deletions
diff --git a/libopie2/opienet/onetutils.cpp b/libopie2/opienet/onetutils.cpp index fd8f9e9..b317810 100644 --- a/libopie2/opienet/onetutils.cpp +++ b/libopie2/opienet/onetutils.cpp @@ -178,8 +178,9 @@ void dumpBytes( const unsigned char* data, int num ) for ( int i = 0; i < num; ++i ) { printf( "%02x ", data[i] ); if ( !((i+1) % 32) ) printf( "\n" ); } printf( "\n\n" ); } + diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index 66fa215..789e8ca 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -123,18 +123,18 @@ ONetwork::InterfaceIterator ONetwork::iterator() const { return ONetwork::InterfaceIterator( _interfaces ); } bool ONetwork::isWirelessInterface( const char* name ) const { int sfd = socket( AF_INET, SOCK_STREAM, 0 ); - iwreqstruct iwr; - memset( &iwr, 0, sizeof( iwreqstruct ) ); + struct iwreq iwr; + memset( &iwr, 0, sizeof( struct iwreq ) ); strcpy( (char*) &iwr.ifr_name, name ); int result = ::ioctl( sfd, SIOCGIWNAME, &iwr ); if ( result == -1 ) qDebug( "ONetwork::ioctl(): SIOCGIWNAME failed: %d (%s)", result, strerror( errno ) ); else qDebug( "ONetwork::ioctl(): SIOCGIWNAME ok." ); return ( result != -1 ); } @@ -147,17 +147,17 @@ ONetworkInterface::ONetworkInterface( QObject* parent, const char* name ) :QObject( parent, name ), _sfd( socket( AF_INET, SOCK_DGRAM, 0 ) ), _mon( 0 ) { qDebug( "ONetworkInterface::ONetworkInterface()" ); init(); } -ifreqstruct& ONetworkInterface::ifr() const +struct ifreq& ONetworkInterface::ifr() const { return _ifr; } void ONetworkInterface::init() { qDebug( "ONetworkInterface::init()" ); @@ -167,17 +167,17 @@ void ONetworkInterface::init() if ( _sfd == -1 ) { qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", name() ); return; } } -bool ONetworkInterface::ioctl( int call, ifreqstruct& ifreq ) const +bool ONetworkInterface::ioctl( int call, struct ifreq& ifreq ) const { int result = ::ioctl( _sfd, call, &ifreq ); if ( result == -1 ) qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) ); else qDebug( "ONetworkInterface::ioctl(): Call %d - Status: Ok.", call ); return ( result != -1 ); } @@ -372,17 +372,17 @@ OWirelessNetworkInterface::OWirelessNetworkInterface( QObject* parent, const cha } OWirelessNetworkInterface::~OWirelessNetworkInterface() { } -iwreqstruct& OWirelessNetworkInterface::iwr() const +struct iwreq& OWirelessNetworkInterface::iwr() const { return _iwr; } void OWirelessNetworkInterface::init() { qDebug( "OWirelessNetworkInterface::init()" ); @@ -412,54 +412,77 @@ QString OWirelessNetworkInterface::associatedAP() const mac = "<Unknown>"; } return mac; } void OWirelessNetworkInterface::buildChannelList() { - // IEEE802.11(b) radio frequency channels - struct iw_range range; - //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* - - _iwr.u.data.pointer = (char*) ⦥ - _iwr.u.data.length = IW_MAX_FREQUENCIES; //sizeof range; - _iwr.u.data.flags = 0; - - if ( !wioctl( SIOCGIWRANGE ) ) + //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 ) ); _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]; @@ -500,17 +523,17 @@ int OWirelessNetworkInterface::channel() const } } void OWirelessNetworkInterface::setChannel( int c ) const { if ( !_mon ) { - memset( &_iwr, 0, sizeof( iwreqstruct ) ); + memset( &_iwr, 0, sizeof( struct iwreq ) ); _iwr.u.freq.m = c; _iwr.u.freq.e = 0; wioctl( SIOCSIWFREQ ); } else { _mon->setChannel( c ); } @@ -634,17 +657,17 @@ QString OWirelessNetworkInterface::SSID() const void OWirelessNetworkInterface::setSSID( const QString& ssid ) { _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid ); _iwr.u.essid.length = ssid.length(); wioctl( SIOCSIWESSID ); } -bool OWirelessNetworkInterface::wioctl( int call, iwreqstruct& iwreq ) const +bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const { int result = ::ioctl( _sfd, call, &iwreq ); if ( result == -1 ) qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Failed: %d (%s)", call, result, strerror( errno ) ); else qDebug( "ONetworkInterface::wioctl(): Call %d - Status: Ok.", call ); return ( result != -1 ); } @@ -670,17 +693,17 @@ OMonitoringInterface::OMonitoringInterface( ONetworkInterface* iface ) OMonitoringInterface::~OMonitoringInterface() { } void OMonitoringInterface::setChannel( int c ) { // use standard WE channel switching protocol - memset( &_if->_iwr, 0, sizeof( iwreqstruct ) ); + memset( &_if->_iwr, 0, sizeof( struct iwreq ) ); _if->_iwr.u.freq.m = c; _if->_iwr.u.freq.e = 0; _if->wioctl( SIOCSIWFREQ ); } bool OMonitoringInterface::enabled() const { diff --git a/libopie2/opienet/onetwork.h b/libopie2/opienet/onetwork.h index 7c70873..509c3db 100644 --- a/libopie2/opienet/onetwork.h +++ b/libopie2/opienet/onetwork.h @@ -67,23 +67,16 @@ #define SIOCIWFIRSTPRIV SIOCDEVPRIVATE #endif class ONetworkInterface; class OWirelessNetworkInterface; class OChannelHopper; class OMonitoringInterface; -typedef struct ifreq ifreqstruct; -typedef struct iwreq iwreqstruct; -typedef struct iw_event iweventstruct; -typedef struct iw_freq iwfreqstruct; -typedef struct iw_priv_args iwprivargsstruct; -typedef struct iw_range iwrangestruct; - /*====================================================================================== * ONetwork *======================================================================================*/ class ONetwork : public QObject { Q_OBJECT @@ -131,24 +124,24 @@ class ONetworkInterface : public QObject bool isUp() const; bool isLoopback() const; bool isWireless() const; QString ipV4Address() const; OMacAddress macAddress() const; protected: const int _sfd; - mutable ifreqstruct _ifr; + mutable ifreq _ifr; OMonitoringInterface* _mon; protected: - ifreqstruct& ifr() const; + struct ifreq& ifr() const; virtual void init(); bool ioctl( int call ) const; - bool ioctl( int call, ifreqstruct& ) const; + bool ioctl( int call, struct ifreq& ) const; }; /*====================================================================================== * OChannelHopper *======================================================================================*/ class OChannelHopper : public QObject { @@ -217,22 +210,22 @@ class OWirelessNetworkInterface : public ONetworkInterface virtual void setSSID( const QString& ); virtual QString SSID() const; protected: void buildChannelList(); void buildPrivateList(); virtual void init(); - iwreqstruct& iwr() const; + struct iwreq& iwr() const; bool wioctl( int call ) const; - bool wioctl( int call, iwreqstruct& ) const; + bool wioctl( int call, struct iwreq& ) const; protected: - mutable iwreqstruct _iwr; + mutable struct iwreq _iwr; QMap<int,int> _channels; private: OChannelHopper* _hopper; }; /*====================================================================================== |