Diffstat (limited to 'libopie2/opienet/onetwork.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opienet/onetwork.cpp | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index 0a74019..f4bdbe0 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -1,362 +1,368 @@ /* This file is part of the Opie Project 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> #include <qapplication.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 <net/ethernet.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; + if ( str.startsWith( "wifi" ) ) + { + odebug << "ONetwork: ignoring hostap control interface" << oendl; + s.readLine(); + continue; + } 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 ) ); strcpy( (char*) &ifr.ifr_name, name ); int result = ::ioctl( sfd, SIOCGIFFLAGS, &ifr ); return result != -1; } bool ONetwork::isWirelessInterface( const char* name ) const { int sfd = socket( AF_INET, SOCK_STREAM, 0 ); struct iwreq iwr; memset( &iwr, 0, sizeof( struct iwreq ) ); strcpy( (char*) &iwr.ifr_name, name ); int result = ::ioctl( sfd, SIOCGIWNAME, &iwr ); return result != -1; } /*====================================================================================== * ONetworkInterface *======================================================================================*/ ONetworkInterface::ONetworkInterface( QObject* parent, const char* name ) :QObject( parent, name ), _sfd( socket( AF_INET, SOCK_DGRAM, 0 ) ), _mon( 0 ) { odebug << "ONetworkInterface::ONetworkInterface()" << oendl; init(); } struct ifreq& ONetworkInterface::ifr() const { return _ifr; } void ONetworkInterface::init() { odebug << "ONetworkInterface::init()" << oendl; memset( &_ifr, 0, sizeof( struct ifreq ) ); if ( _sfd == -1 ) { odebug << "ONetworkInterface::init(): Warning - can't get socket for device '" << name() << "'" << oendl; return; } } bool ONetworkInterface::ioctl( int call, struct ifreq& ifreq ) const { #ifndef NODEBUG int result = ::ioctl( _sfd, call, &ifreq ); if ( result == -1 ) odebug << "ONetworkInterface::ioctl (" << name() << ") call '" << debugmapper->map( call ) << "' FAILED! " << result << " (" << strerror( errno ) << ")" << oendl; else odebug << "ONetworkInterface::ioctl (" << name() << ") call '" << debugmapper->map( call ) << "' - Status: Ok." << oendl; return ( result != -1 ); #else return ::ioctl( _sfd, call, &ifreq ) != -1; #endif } 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 ); } bool ONetworkInterface::isUp() const { ioctl( SIOCGIFFLAGS ); return _ifr.ifr_flags & IFF_UP; } void ONetworkInterface::setIPV4Address( const QHostAddress& addr ) { struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr; sa->sin_family = AF_INET; sa->sin_port = 0; sa->sin_addr.s_addr = htonl( addr.ip4Addr() ); ioctl( SIOCSIFADDR ); } QString ONetworkInterface::ipV4Address() const { if ( ioctl( SIOCGIFADDR ) ) { struct sockaddr_in* sa = (struct sockaddr_in *) &_ifr.ifr_addr; //FIXME: Use QHostAddress here return QString( inet_ntoa( sa->sin_addr ) ); } else return "<unknown>"; } void ONetworkInterface::setMacAddress( const OMacAddress& addr ) { _ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; memcpy( &_ifr.ifr_hwaddr.sa_data, addr.native(), 6 ); ioctl( SIOCSIFHWADDR ); } OMacAddress ONetworkInterface::macAddress() const { if ( ioctl( SIOCGIFHWADDR ) ) { return OMacAddress( _ifr ); } else { return OMacAddress::unknown; } } void ONetworkInterface::setIPV4Netmask( const QHostAddress& addr ) { struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr; sa->sin_family = AF_INET; sa->sin_port = 0; sa->sin_addr.s_addr = htonl( addr.ip4Addr() ); ioctl( SIOCSIFNETMASK ); } QString ONetworkInterface::ipV4Netmask() const { if ( ioctl( SIOCGIFNETMASK ) ) { struct sockaddr_in* sa = (struct sockaddr_in *) &_ifr.ifr_addr; //FIXME: Use QHostAddress here return QString( inet_ntoa( sa->sin_addr ) ); } else return "<unknown>"; } int ONetworkInterface::dataLinkType() const { if ( ioctl( SIOCGIFHWADDR ) ) { return _ifr.ifr_hwaddr.sa_family; } else { return -1; } } void ONetworkInterface::setMonitoring( OMonitoringInterface* m ) { _mon = m; odebug << "ONetwork::setMonitoring(): Installed monitoring driver '" << m->name() << "' on interface '" << name() << "'" << oendl; } OMonitoringInterface* ONetworkInterface::monitoring() const { return _mon; } ONetworkInterface::~ONetworkInterface() { odebug << "ONetworkInterface::~ONetworkInterface()" << oendl; 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 ); } @@ -555,570 +561,571 @@ void OWirelessNetworkInterface::buildInformation() for ( int r = sizeof( struct iw_range ); r < len; r++ ) if (buffer[r] != 0) max = r; if (max > 0) { owarn << "OWirelessNetworkInterface::buildInformation(): Driver for wireless interface '" << name() << "' sucks! It overwrote the buffer end with at least " << max - sizeof( struct iw_range ) << " bytes!" << oendl; } // </check if the driver overwrites stuff> struct iw_range range; memcpy( &range, buffer, sizeof range ); odebug << "OWirelessNetworkInterface::buildInformation(): Interface reported to have " << (int) range.num_frequency << " channels." << oendl; 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 ); odebug << "OWirelessNetworkInterface::buildInformation: Adding frequency " << freq << " as channel " << i+1 << oendl; _channels.insert( freq, i+1 ); } } memcpy( &_range, buffer, sizeof( struct iw_range ) ); odebug << "OWirelessNetworkInterface::buildInformation(): Information block constructed." << oendl; free(buffer); } short OWirelessNetworkInterface::wirelessExtensionDriverVersion() const { return _range.we_version_compiled; } void OWirelessNetworkInterface::buildPrivateList() { odebug << "OWirelessNetworkInterface::buildPrivateList()" << oendl; 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 ) ) { owarn << "OWirelessNetworkInterface::buildPrivateList(): Can't get private ioctl information." << oendl; 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 ); } odebug << "OWirelessNetworkInterface::buildPrivateList(): Private ioctl list constructed." << oendl; } void OWirelessNetworkInterface::dumpInformation() const { odebug << "OWirelessNetworkInterface::() -------------- dumping information block ----------------" << oendl; odebug << " - driver's idea of maximum throughput is " << _range.throughput << " bps = " << ( _range.throughput / 8 ) << " byte/s = " << ( _range.throughput / 8 / 1024 ) << " Kb/s = " << QString().sprintf("%f.2", float( _range.throughput ) / 8.0 / 1024.0 / 1024.0 ) << " Mb/s" << oendl; odebug << " - driver for '" << name() << "' (V" << _range.we_version_source << ") has been compiled against WE V" << _range.we_version_compiled << oendl; if ( _range.we_version_compiled != WIRELESS_EXT ) { owarn << "Version mismatch! WE_DRIVER = " << _range.we_version_compiled << " and WE_OPIENET = " << WIRELESS_EXT << oendl; } odebug << "OWirelessNetworkInterface::() ---------------------------------------------------------" << oendl; } 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 ) { oerr << "OWirelessNetworkInterface::setChannel( 0 ) called - fix your application!" << oendl; 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::commit() const { wioctl( SIOCSIWCOMMIT ); } void OWirelessNetworkInterface::setMode( const QString& newMode ) { #ifdef FINALIZE QString currentMode = mode(); if ( currentMode == newMode ) return; #endif odebug << "OWirelessNetworkInterface::setMode(): trying to set mode " << newMode << oendl; _iwr.u.mode = stringToMode( newMode ); if ( _iwr.u.mode != IW_MODE_MONITOR ) { // IWR.U.MODE WIRD DURCH ABFRAGE DES MODE HIER PLATTGEMACHT!!!!!!!!!!!!!!!!!!!!! DEPP! _iwr.u.mode = stringToMode( newMode ); wioctl( SIOCSIWMODE ); // special iwpriv fallback for monitor mode (check if we're really out of monitor mode now) if ( mode() == "monitor" ) { odebug << "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not sufficient - trying fallback to iwpriv..." << oendl; if ( _mon ) _mon->setEnabled( false ); else odebug << "ONetwork(): can't switch monitor mode without installed monitoring interface" << oendl; } } else // special iwpriv fallback for monitor mode { if ( wioctl( SIOCSIWMODE ) ) { odebug << "OWirelessNetworkInterface::setMode(): IW_MODE_MONITOR ok" << oendl; } else { odebug << "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not working - trying fallback to iwpriv..." << oendl; if ( _mon ) _mon->setEnabled( true ); else odebug << "ONetwork(): can't switch monitor mode without installed monitoring interface" << oendl; } } } QString OWirelessNetworkInterface::mode() const { memset( &_iwr, 0, sizeof( struct iwreq ) ); if ( !wioctl( SIOCGIWMODE ) ) { return "<unknown>"; } odebug << "OWirelessNetworkInterface::setMode(): WE's idea of current mode seems to be " << modeToString( _iwr.u.mode ) << oendl; // legacy compatible monitor mode check 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 + str[_iwr.u.data.length] = '\0'; // some drivers 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 { + str[_iwr.u.essid.length] = '\0'; // some drivers don't zero-terminate the string return str; } } void OWirelessNetworkInterface::setSSID( const QString& ssid ) { _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid ); _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 = 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 ( qApp ) { qApp->processEvents( 100 ); continue; } 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); if (iwe.len <= IW_EV_LCP_LEN) //If yes, it is an invalid event break; if (iwe.cmd <= SIOCIWLAST) { cmd_index = iwe.cmd - SIOCIWFIRST; 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; |