author | mickeyl <mickeyl> | 2005-04-18 21:40:04 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2005-04-18 21:40:04 (UTC) |
commit | 9e685cedc4425dd5ae60170e3f59a899c9e2bf36 (patch) (side-by-side diff) | |
tree | 72e1eca8468cfde65f2cfa9446be4f08a1a9e19a | |
parent | 3d5e5c098ccb686588380bc1f220beafbc5a6d76 (diff) | |
download | opie-9e685cedc4425dd5ae60170e3f59a899c9e2bf36.zip opie-9e685cedc4425dd5ae60170e3f59a899c9e2bf36.tar.gz opie-9e685cedc4425dd5ae60170e3f59a899c9e2bf36.tar.bz2 |
- improve scan function using the wireless extensions.
- fix bug in setSSID().
Major parts of this patch are courtesy Skyhusker - thanks!
-rw-r--r-- | libopie2/opienet/onetutils.h | 25 | ||||
-rw-r--r-- | libopie2/opienet/onetwork.cpp | 203 | ||||
-rw-r--r-- | libopie2/opienet/onetwork.h | 8 | ||||
-rw-r--r-- | libopie2/opienet/opienet.pro | 2 | ||||
-rw-r--r-- | libopie2/opienet/ostation.h | 5 |
5 files changed, 212 insertions, 31 deletions
diff --git a/libopie2/opienet/onetutils.h b/libopie2/opienet/onetutils.h index f1d34a0..32f5355 100644 --- a/libopie2/opienet/onetutils.h +++ b/libopie2/opienet/onetutils.h @@ -1,196 +1,215 @@ /* This file is part of the Opie Project - - (C) 2003 Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de> + (C) 2003-2005 Michael 'Mickey' Lauer <mickey@Vanille.de> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; version 2 of the License. - ._= =} : + ._= =} : .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ONETUTILS_H #define ONETUTILS_H #include <qdict.h> #include <qmap.h> #include <qstring.h> #include <qhostaddress.h> #include <qobject.h> #include <sys/types.h> struct ifreq; namespace Opie { namespace Net { class OWirelessNetworkInterface; /*====================================================================================== * OMacAddress *======================================================================================*/ class OMacAddress { public: // QString c'tor? -zecke OMacAddress(); OMacAddress( unsigned char* ); OMacAddress( const unsigned char* ); OMacAddress( struct ifreq& ); ~OMacAddress(); QString manufacturer() const; QString toString( bool substitute = false ) const; const unsigned char* native() const; // no c'tor but this one why not make it a c'tor. it could also replace the others or is this the problem? static OMacAddress fromString( const QString& ); public: static const OMacAddress& broadcast; // ff:ff:ff:ff:ff:ff static const OMacAddress& unknown; // 44:44:44:44:44:44 private: unsigned char _bytes[6]; friend bool operator==( const OMacAddress &m1, const OMacAddress &m2 ); class Private; Private *d; }; bool operator==( const OMacAddress &m1, const OMacAddress &m2 ); /*====================================================================================== * OHostAddress *======================================================================================*/ class OHostAddress : public QHostAddress { /*public: OHostAddress(); ~OHostAddress(); */ private: class Private; Private *d; }; /*====================================================================================== * OPrivateIOCTL *======================================================================================*/ class OPrivateIOCTL : public QObject { public: OPrivateIOCTL( QObject* parent, const char* name, int cmd, int getargs, int setargs ); ~OPrivateIOCTL(); int numberGetArgs() const; int typeGetArgs() const; int numberSetArgs() const; int typeSetArgs() const; // FIXME return int? as ::ioctl does? -zecke void invoke() const; void setParameter( int, u_int32_t ); private: u_int32_t _ioctl; u_int16_t _getargs; u_int16_t _setargs; class Private; Private *d; }; /*====================================================================================== * Miscellaneous *======================================================================================*/ namespace Internal { void dumpBytes( const unsigned char* data, int num ); QString modeToString( int ); int stringToMode( const QString& ); } } } #define IW_PRIV_TYPE_MASK 0x7000 #define IW_PRIV_TYPE_NONE 0x0000 #define IW_PRIV_TYPE_BYTE 0x1000 #define IW_PRIV_TYPE_CHAR 0x2000 #define IW_PRIV_TYPE_INT 0x4000 #define IW_PRIV_TYPE_FLOAT 0x5000 #define IW_PRIV_TYPE_ADDR 0x6000 #define IW_PRIV_SIZE_FIXED 0x0800 #define IW_PRIV_SIZE_MASK 0x07FF +#define IW_HEADER_TYPE_NULL 0 /* Not available */ +#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */ +#define IW_HEADER_TYPE_UINT 4 /* __u32 */ +#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */ +#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */ +#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */ +#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */ +#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */ + +#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ + (char *) NULL) + #ifndef ARPHRD_IEEE80211 #define ARPHRD_IEEE80211 801 #endif #ifndef ARPHRD_IEEE80211_PRISM #define ARPHRD_IEEE80211_PRISM 802 #endif +/* Wireless Extension Scanning Stuff */ +struct iw_stream_descr +{ + char * end; /* End of the stream */ + char * current; /* Current event in stream of events */ + char * value; /* Current value in event */ +}; + /* Network to host order macros */ #ifdef LBL_ALIGN #define EXTRACT_16BITS(p) \ ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 0) << 8 | \ (u_int16_t)*((const u_int8_t *)(p) + 1))) #define EXTRACT_32BITS(p) \ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 24 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 2) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 3))) #else #define EXTRACT_16BITS(p) \ ((u_int16_t)ntohs(*(const u_int16_t *)(p))) #define EXTRACT_32BITS(p) \ ((u_int32_t)ntohl(*(const u_int32_t *)(p))) #endif #define EXTRACT_24BITS(p) \ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 0) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 2))) /* Little endian protocol host order macros */ #define EXTRACT_LE_8BITS(p) (*(p)) #define EXTRACT_LE_16BITS(p) \ ((u_int16_t)((u_int16_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int16_t)*((const u_int8_t *)(p) + 0))) #define EXTRACT_LE_32BITS(p) \ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 3) << 24 | \ (u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \ (u_int32_t)*((const u_int8_t *)(p) + 0))) #endif // ONETUTILS_H diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index ae1865d..546be9e 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -1,157 +1,156 @@ /* This file is part of the Opie Project - Copyright (C) 2003-2004 by Michael 'Mickey' Lauer - =. <mickey@Vanille.de> + Copyright (C) 2003-2005 by Michael 'Mickey' Lauer <mickey@Vanille.de> + =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; version 2 of the License. - ._= =} : + ._= =} : .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* OPIE */ #include <opie2/onetwork.h> #include <opie2/ostation.h> #include <opie2/odebug.h> /* QT */ #include <qfile.h> #include <qtextstream.h> /* UNIX */ #include <assert.h> #include <arpa/inet.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <sys/types.h> #include <unistd.h> #include <linux/sockios.h> #include <net/if_arp.h> #include <stdarg.h> #ifndef NODEBUG #include <opie2/odebugmapper.h> - using namespace Opie::Core; using namespace Opie::Net::Internal; DebugMapper* debugmapper = new DebugMapper(); #endif /*====================================================================================== * ONetwork *======================================================================================*/ namespace Opie { namespace Net { ONetwork* ONetwork::_instance = 0; ONetwork::ONetwork() { odebug << "ONetwork::ONetwork()" << oendl; odebug << "ONetwork: This code has been compiled against Wireless Extensions V" << WIRELESS_EXT << oendl; 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 ) { odebug << "ONetwork: /proc/net/dev not existing. No network devices available" << oendl; return; } QTextStream s( &f ); s.readLine(); s.readLine(); while ( !s.atEnd() ) { s >> str; str.truncate( str.find( ':' ) ); odebug << "ONetwork: found interface '" << str << "'" << oendl; ONetworkInterface* iface = 0; if ( isWirelessInterface( str ) ) { iface = new OWirelessNetworkInterface( this, (const char*) str ); odebug << "ONetwork: interface '" << str << "' has Wireless Extensions" << oendl; } else { iface = new ONetworkInterface( this, (const char*) str ); } _interfaces.insert( str, iface ); s.readLine(); } } short ONetwork::wirelessExtensionCompileVersion() { return WIRELESS_EXT; } int ONetwork::count() const { return _interfaces.count(); } ONetworkInterface* ONetwork::interface( const QString& iface ) const { return _interfaces[iface]; } ONetwork* ONetwork::instance() { if ( !_instance ) _instance = new ONetwork(); return _instance; } ONetwork::InterfaceIterator ONetwork::iterator() const { return ONetwork::InterfaceIterator( _interfaces ); } bool ONetwork::isPresent( const char* name ) const { int sfd = socket( AF_INET, SOCK_STREAM, 0 ); struct ifreq ifr; memset( &ifr, 0, sizeof( struct ifreq ) ); @@ -772,321 +771,483 @@ QString OWirelessNetworkInterface::mode() const if ( dataLinkType() == ARPHRD_IEEE80211 || dataLinkType() == 802 ) { return "monitor"; } else { return modeToString( _iwr.u.mode ); } } 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; } } void OWirelessNetworkInterface::setPrivate( const QString& call, int numargs, ... ) { OPrivateIOCTL* priv = static_cast<OPrivateIOCTL*>( child( (const char*) call ) ); if ( !priv ) { owarn << "OWirelessNetworkInterface::setPrivate(): interface '" << name() << "' does not support private ioctl '" << call << "'" << oendl; return; } if ( priv->numberSetArgs() != numargs ) { owarn << "OWirelessNetworkInterface::setPrivate(): parameter count not matching. '" << call << "' expects " << priv->numberSetArgs() << ", but got " << numargs << oendl; return; } odebug << "OWirelessNetworkInterface::setPrivate(): about to call '" << call << "' on interface '" << name() << "'" << oendl; memset( &_iwr, 0, sizeof _iwr ); va_list argp; va_start( argp, numargs ); for ( int i = 0; i < numargs; ++i ) { priv->setParameter( i, va_arg( argp, int ) ); } va_end( argp ); priv->invoke(); } void OWirelessNetworkInterface::getPrivate( const QString& ) { oerr << "OWirelessNetworkInterface::getPrivate() is not implemented yet." << oendl; } bool OWirelessNetworkInterface::hasPrivate( const QString& call ) { return child( call.local8Bit() ); } 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(); + _iwr.u.essid.length = ssid.length()+1; // zero byte wioctl( SIOCSIWESSID ); } OStationList* OWirelessNetworkInterface::scanNetwork() { _iwr.u.param.flags = IW_SCAN_DEFAULT; _iwr.u.param.value = 0; if ( !wioctl( SIOCSIWSCAN ) ) { return 0; } OStationList* stations = new OStationList(); - int timeout = 1000000; + int timeout = 10000000; odebug << "ONetworkInterface::scanNetwork() - scan started." << oendl; 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) { odebug << "ONetworkInterface::scanNetwork() - scan in progress..." << oendl; #if 0 if ( qApp ) { qApp->processEvents( 100 ); continue; } #endif tv.tv_sec = 0; tv.tv_usec = 100000; continue; } } odebug << "ONetworkInterface::scanNetwork() - scan finished." << oendl; if ( results ) { odebug << " - result length = " << _iwr.u.data.length << oendl; if ( !_iwr.u.data.length ) { odebug << " - no results (empty neighbourhood)" << oendl; return stations; } odebug << " - results are in!" << oendl; dumpBytes( (const unsigned char*) &buffer[0], _iwr.u.data.length ); // parse results + struct iw_event iwe; + struct iw_stream_descr stream; + unsigned int cmd_index, event_type, event_len; + char *pointer; + + const char standard_ioctl_hdr[] = { + IW_HEADER_TYPE_NULL, /* SIOCSIWCOMMIT */ + IW_HEADER_TYPE_CHAR, /* SIOCGIWNAME */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWNWID */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWNWID */ + IW_HEADER_TYPE_FREQ, /* SIOCSIWFREQ */ + IW_HEADER_TYPE_FREQ, /* SIOCGIWFREQ */ + IW_HEADER_TYPE_UINT, /* SIOCSIWMODE */ + IW_HEADER_TYPE_UINT, /* SIOCGIWMODE */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWSENS */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWSENS */ + IW_HEADER_TYPE_NULL, /* SIOCSIWRANGE */ + IW_HEADER_TYPE_POINT, /* SIOCGIWRANGE */ + IW_HEADER_TYPE_NULL, /* SIOCSIWPRIV */ + IW_HEADER_TYPE_POINT, /* SIOCGIWPRIV */ + IW_HEADER_TYPE_NULL, /* SIOCSIWSTATS */ + IW_HEADER_TYPE_POINT, /* SIOCGIWSTATS */ + IW_HEADER_TYPE_POINT, /* SIOCSIWSPY */ + IW_HEADER_TYPE_POINT, /* SIOCGIWSPY */ + IW_HEADER_TYPE_POINT, /* SIOCSIWTHRSPY */ + IW_HEADER_TYPE_POINT, /* SIOCGIWTHRSPY */ + IW_HEADER_TYPE_ADDR, /* SIOCSIWAP */ + IW_HEADER_TYPE_ADDR, /* SIOCGIWAP */ + IW_HEADER_TYPE_NULL, /* -- hole -- */ + IW_HEADER_TYPE_POINT, /* SIOCGIWAPLIST */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWSCAN */ + IW_HEADER_TYPE_POINT, /* SIOCGIWSCAN */ + IW_HEADER_TYPE_POINT, /* SIOCSIWESSID */ + IW_HEADER_TYPE_POINT, /* SIOCGIWESSID */ + IW_HEADER_TYPE_POINT, /* SIOCSIWNICKN */ + IW_HEADER_TYPE_POINT, /* SIOCGIWNICKN */ + IW_HEADER_TYPE_NULL, /* -- hole -- */ + IW_HEADER_TYPE_NULL, /* -- hole -- */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWRATE */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWRATE */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWRTS */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWRTS */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWFRAG */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWFRAG */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWTXPOW */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWTXPOW */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWRETRY */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWRETRY */ + IW_HEADER_TYPE_POINT, /* SIOCSIWENCODE */ + IW_HEADER_TYPE_POINT, /* SIOCGIWENCODE */ + IW_HEADER_TYPE_PARAM, /* SIOCSIWPOWER */ + IW_HEADER_TYPE_PARAM, /* SIOCGIWPOWER */ + }; + + const char standard_event_hdr[] = { + IW_HEADER_TYPE_ADDR, /* IWEVTXDROP */ + IW_HEADER_TYPE_QUAL, /* IWEVQUAL */ + IW_HEADER_TYPE_POINT, /* IWEVCUSTOM */ + IW_HEADER_TYPE_ADDR, /* IWEVREGISTERED */ + IW_HEADER_TYPE_ADDR, /* IWEVEXPIRED */ + IW_HEADER_TYPE_POINT, /* IWEVGENIE */ + IW_HEADER_TYPE_POINT, /* IWEVMICHAELMICFAILURE */ + IW_HEADER_TYPE_POINT, /* IWEVASSOCREQIE */ + IW_HEADER_TYPE_POINT, /* IWEVASSOCRESPIE */ + IW_HEADER_TYPE_POINT, /* IWEVPMKIDCAND */ + }; + + + const int event_type_size[] = { + IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */ + 0, + IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */ + 0, + IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */ + IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */ + IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */ + 0, + IW_EV_POINT_LEN, /* Without variable payload */ + IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */ + IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ + }; + + + //Initialize the stream + memset( &stream, 0, sizeof(struct iw_stream_descr) ); + stream.current = buffer; + stream.end = buffer + _iwr.u.data.length; + + do + { + if ((stream.current + IW_EV_LCP_LEN) > stream.end) + break; + memcpy((char *) &iwe, stream.current, IW_EV_LCP_LEN); - int offset = 0; - struct iw_event* we = (struct iw_event*) &buffer[0]; + if (iwe.len <= IW_EV_LCP_LEN) //If yes, it is an invalid event + break; + if (iwe.cmd <= SIOCIWLAST) { + cmd_index = iwe.cmd - SIOCIWFIRST; - while ( offset < _iwr.u.data.length ) - { - //const char* cmd = *(*_ioctlmap)[we->cmd]; - //if ( !cmd ) cmd = "<unknown>"; + if(cmd_index < sizeof(standard_ioctl_hdr)) + event_type = standard_ioctl_hdr[cmd_index]; + } + else { + cmd_index = iwe.cmd - IWEVFIRST; + + if(cmd_index < sizeof(standard_event_hdr)) + event_type = standard_event_hdr[cmd_index]; + } + + /* Unknown events -> event_type=0 => IW_EV_LCP_LEN */ + event_len = event_type_size[event_type]; + + /* Fixup for later version of WE */ + if((_range.we_version_compiled > 18) && (event_type == IW_HEADER_TYPE_POINT)) + event_len -= IW_EV_POINT_OFF; + + /* Check if we know about this event */ + if(event_len <= IW_EV_LCP_LEN) { + /* Skip to next event */ + stream.current += iwe.len; + continue; + } + + event_len -= IW_EV_LCP_LEN; + + /* Set pointer on data */ + if(stream.value != NULL) + pointer = stream.value; /* Next value in event */ + else + pointer = stream.current + IW_EV_LCP_LEN; /* First value in event */ + + if((pointer + event_len) > stream.end) { + /* Go to next event */ + stream.current += iwe.len; + break; + } + + /* Fixup for later version of WE */ + if((_range.we_version_compiled > 18) && (event_type == IW_HEADER_TYPE_POINT)) + memcpy((char *) &iwe + IW_EV_LCP_LEN + IW_EV_POINT_OFF, pointer, event_len); + else + memcpy((char *) &iwe + IW_EV_LCP_LEN, pointer, event_len); + + /* Skip event in the stream */ + pointer += event_len; + + /* Special processing for iw_point events */ + if(event_type == IW_HEADER_TYPE_POINT) { + /* Check the length of the payload */ + + if((iwe.len - (event_len + IW_EV_LCP_LEN)) > 0) + /* Set pointer on variable part (warning : non aligned) */ + iwe.u.data.pointer = pointer; + else + /* No data */ + iwe.u.data.pointer = NULL; + /* Go to next event */ + stream.current += iwe.len; + } + + else { + /* Is there more value in the event ? */ + if((pointer + event_len) <= (stream.current + iwe.len)) + /* Go to next value */ + stream.value = pointer; + else { + /* Go to next event */ + stream.value = NULL; + stream.current += iwe.len; + } + } + + struct iw_event *we = &iwe; + //------ odebug << " - reading next event... cmd=" << we->cmd << ", len=" << we->len << oendl; switch (we->cmd) { case SIOCGIWAP: { odebug << "SIOCGIWAP" << oendl; stations->append( new OStation() ); stations->last()->macAddress = (const unsigned char*) &we->u.ap_addr.sa_data[0]; break; } case SIOCGIWMODE: { odebug << "SIOCGIWMODE" << oendl; stations->last()->type = modeToString( we->u.mode ); break; } case SIOCGIWFREQ: { odebug << "SIOCGIWFREQ" << oendl; stations->last()->channel = _channels[ static_cast<int>(double( we->u.freq.m ) * pow( 10.0, we->u.freq.e ) / 1000000) ]; break; } case SIOCGIWESSID: { odebug << "SIOCGIWESSID" << oendl; - stations->last()->ssid = static_cast<const char*>( we->u.essid.pointer ); + we->u.essid.length = '\0'; // make sure it is zero terminated + stations->last()->ssid = static_cast<const char*> (we->u.essid.pointer); + odebug << "ESSID: " << stations->last()->ssid << oendl; break; } case SIOCGIWSENS: odebug << "SIOCGIWSENS" << oendl; break; case SIOCGIWENCODE: odebug << "SIOCGIWENCODE" << oendl; break; case IWEVTXDROP: odebug << "IWEVTXDROP" << oendl; break; /* Packet dropped to excessive retry */ case IWEVQUAL: odebug << "IWEVQUAL" << oendl; break; /* Quality part of statistics (scan) */ case IWEVCUSTOM: odebug << "IWEVCUSTOM" << oendl; break; /* Driver specific ascii string */ case IWEVREGISTERED: odebug << "IWEVREGISTERED" << oendl; break; /* Discovered a new node (AP mode) */ case IWEVEXPIRED: odebug << "IWEVEXPIRED" << oendl; break; /* Expired a node (AP mode) */ default: odebug << "unhandled event" << oendl; } - offset += we->len; - we = (struct iw_event*) &buffer[offset]; - } - return stations; - - return stations; - + } while (true); } else { odebug << " - no results (timeout) :(" << oendl; - return stations; } + return stations; } int OWirelessNetworkInterface::signalStrength() const { iw_statistics stat; ::memset( &stat, 0, sizeof stat ); _iwr.u.data.pointer = (char*) &stat; _iwr.u.data.flags = 0; _iwr.u.data.length = sizeof stat; if ( !wioctl( SIOCGIWSTATS ) ) { return -1; } int max = _range.max_qual.qual; int cur = stat.qual.qual; // int lev = stat.qual.level; //FIXME: Do something with them? // int noi = stat.qual.noise; //FIXME: Do something with them? return max != 0 ? cur*100/max: -1; } bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const { #ifndef NODEBUG int result = ::ioctl( _sfd, call, &iwreq ); if ( result == -1 ) odebug << "ONetworkInterface::wioctl (" << name() << ") call '" << debugmapper->map( call ) << "' FAILED! " << result << " (" << strerror( errno ) << ")" << oendl; else odebug << "ONetworkInterface::wioctl (" << name() << ") call '" << debugmapper->map( call ) << "' - Status: Ok." << oendl; return ( result != -1 ); #else return ::ioctl( _sfd, call, &iwreq ) != -1; #endif } 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() { } void OMonitoringInterface::setChannel( int c ) { // use standard WE channel switching protocol memset( &_if->_iwr, 0, sizeof( struct iwreq ) ); _if->_iwr.u.freq.m = c; _if->_iwr.u.freq.e = 0; _if->wioctl( SIOCSIWFREQ ); } void OMonitoringInterface::setEnabled( bool ) { } /*====================================================================================== * OCiscoMonitoringInterface *======================================================================================*/ OCiscoMonitoringInterface::OCiscoMonitoringInterface( ONetworkInterface* iface, bool prismHeader ) :OMonitoringInterface( iface, prismHeader ) { iface->setMonitoring( this ); } OCiscoMonitoringInterface::~OCiscoMonitoringInterface() { } diff --git a/libopie2/opienet/onetwork.h b/libopie2/opienet/onetwork.h index be4bb46..4d9912d 100644 --- a/libopie2/opienet/onetwork.h +++ b/libopie2/opienet/onetwork.h @@ -1,142 +1,142 @@ /* This file is part of the Opie Project - Copyright (C) 2003-2004 by Michael 'Mickey' Lauer - =. <mickey@Vanille.de> + Copyright (C) 2003-2005 by Michael 'Mickey' Lauer <mickey@Vanille.de> + =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; version 2 of the License. - ._= =} : + ._= =} : .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef ONETWORK_H #define ONETWORK_H /* OPIE */ #include <opie2/onetutils.h> #include <opie2/ostation.h> /* QT */ #include <qvaluelist.h> #include <qdict.h> #include <qmap.h> #include <qobject.h> #include <qhostaddress.h> /* STD */ -// hacky workaround until we have a user space wireless.h +// hacky workarounds until we have a true user space wireless.h #include <net/if.h> #define _LINUX_IF_H #include <linux/wireless.h> #ifndef IW_MAX_PRIV_DEF #define IW_MAX_PRIV_DEF 128 #endif namespace Opie { namespace Net { class ONetworkInterface; class OWirelessNetworkInterface; class OChannelHopper; class OMonitoringInterface; /*====================================================================================== * ONetwork *======================================================================================*/ /** * @brief A container class for all network interfaces * * This class provides access to all available network interfaces of your computer. * * @author Michael 'Mickey' Lauer <mickey@vanille.de> */ class ONetwork : public QObject { Q_OBJECT public: typedef QDict<ONetworkInterface> InterfaceMap; typedef QDictIterator<ONetworkInterface> InterfaceIterator; public: /** * @returns the number of available interfaces */ int count() const; /** * @returns a pointer to the (one and only) @ref ONetwork instance. */ static ONetwork* instance(); /** * @returns an iterator usable for iterating through all network interfaces. */ InterfaceIterator iterator() const; /** * @returns true, if the @a interface is present. */ bool isPresent( const char* interface ) const; /** * @returns true, if the @a interface supports the wireless extension protocol. */ bool isWirelessInterface( const char* interface ) const; /** * @returns a pointer to the @ref ONetworkInterface object for the specified @a interface or 0, if not found. * @see ONetworkInterface */ ONetworkInterface* interface( const QString& interface ) const; /** * @internal Rebuild the internal interface database * @note Sometimes it might be useful to call this from client code, * e.g. after issuing a cardctl insert */ void synchronize(); /** * @returns the wireless extension version used at compile time. **/ static short wirelessExtensionCompileVersion(); protected: ONetwork(); private: static ONetwork* _instance; InterfaceMap _interfaces; class Private; Private *d; }; /*====================================================================================== * ONetworkInterface *======================================================================================*/ /** * @brief A network interface wrapper. * * This class provides a wrapper for a network interface. All the cumbersume details of * Linux ioctls are hidden under a convenient high-level interface. * @warning Most of the setting methods contained in this class require the appropriate * process permissions to work. * * @author Michael 'Mickey' Lauer <mickey@vanille.de> */ class ONetworkInterface : public QObject diff --git a/libopie2/opienet/opienet.pro b/libopie2/opienet/opienet.pro index 98fa175..a10a949 100644 --- a/libopie2/opienet/opienet.pro +++ b/libopie2/opienet/opienet.pro @@ -1,40 +1,40 @@ TEMPLATE = lib CONFIG += qt warn_on DESTDIR = $(OPIEDIR)/lib HEADERS = 802_11_user.h \ dhcp.h \ udp_ports.h \ odebugmapper.h \ omanufacturerdb.h \ onetutils.h \ onetwork.h \ opcap.h \ ostation.h SOURCES = odebugmapper.cpp \ omanufacturerdb.cpp \ onetutils.cpp \ onetwork.cpp \ opcap.cpp \ ostation.cpp INTERFACES = TARGET = opienet2 -VERSION = 1.8.4 +VERSION = 1.8.5 INCLUDEPATH += $(OPIEDIR)/include DEPENDPATH += $(OPIEDIR)/include LIBS += -lpcap !contains( platform, x11 ) { include( $(OPIEDIR)/include.pro ) } contains( platform, x11 ) { LIBS += -L$(OPIEDIR)/lib -Wl,-rpath,$(OPIEDIR)/lib } !isEmpty( LIBPCAP_INC_DIR ) { INCLUDEPATH = $$LIBPCAP_INC_DIR $$INCLUDEPATH } !isEmpty( LIBPCAP_LIB_DIR ) { LIBS = -L$$LIBPCAP_LIB_DIR $$LIBS } diff --git a/libopie2/opienet/ostation.h b/libopie2/opienet/ostation.h index bdc653f..5219d92 100644 --- a/libopie2/opienet/ostation.h +++ b/libopie2/opienet/ostation.h @@ -1,82 +1,83 @@ /* This file is part of the Opie Project - Copyright (C) 2003 by Michael 'Mickey' Lauer <mickey@Vanille.de> + Copyright (C) 2003-2005 by Michael 'Mickey' Lauer <mickey@Vanille.de> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; version 2 of the License. - ._= =} : + ._= =} : .%`+i> _;_. .i_,=:_. -<s. 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 ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OSTATION_H #define OSTATION_H #include <opie2/onetutils.h> #include <qlist.h> #include <qstring.h> #include <qhostaddress.h> #include <qobject.h> #include <sys/types.h> namespace Opie { namespace Net { class OStation; typedef QList<OStation> OStationList; /*====================================================================================== * OStation *======================================================================================*/ class OStation { public: OStation(); ~OStation(); void dump(); /* Ethernet */ QString type; OMacAddress macAddress; QHostAddress ipAddress; /* WaveLan */ QString ssid; OMacAddress apAddress; int channel; + int level; bool encrypted; private: class Private; Private *d; }; } } #endif // OSTATION_H |