From 11c6b3b8ba56b28b160965387b4ffeffe2a2f143 Mon Sep 17 00:00:00 2001 From: mickeyl Date: Sat, 20 Dec 2003 00:43:12 +0000 Subject: libopienet2 now uses the fancy odebug classes, no longer qdebug --- (limited to 'libopie2/opienet') diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index 6a9280f..d918193 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -1,1188 +1,1196 @@ -/* -                 This file is part of the Opie Project -              Copyright (C) 2003 by Michael 'Mickey' Lauer - =. - .=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; either version 2 of the License, -     ._= =}       : or (at your option) any later version. -    .%`+i>       _;_. -    .i_,=:_.      -`: 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 -#include - -/* QT */ - -#include -#include - -/* UNIX */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NODEBUG -#include -DebugMapper* debugmapper = new DebugMapper(); -#endif - -/*====================================================================================== - * ONetwork - *======================================================================================*/ - -ONetwork* ONetwork::_instance = 0; - -ONetwork::ONetwork() -{ - qDebug( "ONetwork::ONetwork()" ); - qDebug( "ONetwork: This code has been compiled against Wireless Extensions V%d", WIRELESS_EXT ); - 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 ) - { - qDebug( "ONetwork: /proc/net/dev not existing. No network devices available" ); - return; - } - QTextStream s( &f ); - s.readLine(); - s.readLine(); - while ( !s.atEnd() ) - { - s >> str; - str.truncate( str.find( ':' ) ); - qDebug( "ONetwork: found interface '%s'", (const char*) str ); - ONetworkInterface* iface; - if ( isWirelessInterface( str ) ) - { - iface = new OWirelessNetworkInterface( this, (const char*) str ); - qDebug( "ONetwork: interface '%s' has Wireless Extensions", (const char*) str ); - } - else - { - iface = new ONetworkInterface( this, (const char*) str ); - } - _interfaces.insert( str, iface ); - s.readLine(); - } -} - - -short ONetwork::wirelessExtensionVersion() -{ - 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::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 ) -{ - qDebug( "ONetworkInterface::ONetworkInterface()" ); - init(); -} - - -struct ifreq& ONetworkInterface::ifr() const -{ - return _ifr; -} - - -void ONetworkInterface::init() -{ - qDebug( "ONetworkInterface::init()" ); - - memset( &_ifr, 0, sizeof( struct ifreq ) ); - - if ( _sfd == -1 ) - { - qDebug( "ONetworkInterface::init(): Warning - can't get socket for device '%s'", name() ); - return; - } -} - - -bool ONetworkInterface::ioctl( int call, struct ifreq& ifreq ) const -{ - #ifndef NODEBUG - int result = ::ioctl( _sfd, call, &ifreq ); - if ( result == -1 ) - qDebug( "ONetworkInterface::ioctl (%s) call %s (0x%04X) - Status: Failed: %d (%s)", name(), (const char*) debugmapper->map( call ), call, result, strerror( errno ) ); - else - qDebug( "ONetworkInterface::ioctl (%s) call %s (0x%04X) - Status: Ok.", name(), (const char*) debugmapper->map( call ), call ); - 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 ""; - -} - - -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 ""; -} - - -int ONetworkInterface::dataLinkType() const -{ - if ( ioctl( SIOCGIFHWADDR ) ) - { - return _ifr.ifr_hwaddr.sa_family; - } - else - { - return -1; - } -} - - -void ONetworkInterface::setMonitoring( OMonitoringInterface* m ) -{ - _mon = m; - qDebug( "ONetwork::setMonitoring(): Installed monitoring driver '%s' on interface '%s'", (const char*) m->name(), name() ); -} - - -OMonitoringInterface* ONetworkInterface::monitoring() const -{ - return _mon; -} - - -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 ), _tid( 0 ) -{ - int _maxChannel = iface->channels()+1; - // generate fancy hopping sequence honoring the device capabilities - if ( _maxChannel >= 1 ) _channels.append( 1 ); - if ( _maxChannel >= 7 ) _channels.append( 7 ); - if ( _maxChannel >= 13 ) _channels.append( 13 ); - if ( _maxChannel >= 2 ) _channels.append( 2 ); - if ( _maxChannel >= 8 ) _channels.append( 8 ); - if ( _maxChannel >= 3 ) _channels.append( 3 ); - if ( _maxChannel >= 14 ) _channels.append( 14 ); - if ( _maxChannel >= 9 ) _channels.append( 9 ); - if ( _maxChannel >= 4 ) _channels.append( 4 ); - if ( _maxChannel >= 10 ) _channels.append( 10 ); - if ( _maxChannel >= 5 ) _channels.append( 5 ); - if ( _maxChannel >= 11 ) _channels.append( 11 ); - if ( _maxChannel >= 6 ) _channels.append( 6 ); - if ( _maxChannel >= 12 ) _channels.append( 12 ); - _channel = _channels.begin(); - -} - - -OChannelHopper::~OChannelHopper() -{ -} - - -bool OChannelHopper::isActive() const -{ - return _tid; -} - - -int OChannelHopper::channel() const -{ - return *_channel; -} - - -void OChannelHopper::timerEvent( QTimerEvent* ) -{ - _iface->setChannel( *_channel ); - emit( hopped( *_channel ) ); - qDebug( "OChannelHopper::timerEvent(): set channel %d on interface '%s'", - *_channel, (const char*) _iface->name() ); - if ( ++_channel == _channels.end() ) _channel = _channels.begin(); -} - - -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( QObject* parent, const char* name ) - :ONetworkInterface( parent, name ), _hopper( 0 ) -{ - qDebug( "OWirelessNetworkInterface::OWirelessNetworkInterface()" ); - init(); -} - - -OWirelessNetworkInterface::~OWirelessNetworkInterface() -{ -} - - -struct iwreq& OWirelessNetworkInterface::iwr() const -{ - return _iwr; -} - - -void OWirelessNetworkInterface::init() -{ - qDebug( "OWirelessNetworkInterface::init()" ); - memset( &_iwr, 0, sizeof( struct iwreq ) ); - buildInformation(); - buildPrivateList(); - dumpInformation(); -} - - -bool OWirelessNetworkInterface::isAssociated() const -{ - //FIXME: handle different modes - return !(associatedAP() == OMacAddress::unknown); -} - - -OMacAddress OWirelessNetworkInterface::associatedAP() const -{ - if ( ioctl( SIOCGIWAP ) ) - return (const unsigned char*) &_ifr.ifr_hwaddr.sa_data[0]; - else - return OMacAddress::unknown; -} - - -void OWirelessNetworkInterface::buildInformation() -{ - //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* - //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::buildInformation(): SIOCGIWRANGE failed (%s) - using default values.", 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 - - memset( &_range, 0, sizeof( struct iw_range ) ); - } - else - { - // - int max = 0; - for ( int r = sizeof( struct iw_range ); r < len; r++ ) - if (buffer[r] != 0) - max = r; - if (max > 0) - { - qWarning( "OWirelessNetworkInterface::buildInformation(): Driver for wireless interface '%s' sucks!\n" - "It overwrote the buffer end with at least %i bytes!\n", name(), max - sizeof( struct iw_range ) ); - } - // - - struct iw_range range; - memcpy( &range, buffer, sizeof range ); - - qDebug( "OWirelessNetworkInterface::buildInformation(): 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 ); - } - } - - memcpy( &_range, buffer, sizeof( struct iw_range ) ); - qDebug( "OWirelessNetworkInterface::buildInformation(): Information block 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." ); -} - - -void OWirelessNetworkInterface::dumpInformation() const -{ - qDebug( "OWirelessNetworkInterface::() -------------- dumping information block ----------------" ); - - qDebug( " - driver's idea of maximum throughput is %d bps = %d byte/s = %d Kb/s = %f.2 Mb/s", _range.throughput, _range.throughput / 8, _range.throughput / 8 / 1024, float( _range.throughput ) / 8.0 / 1024.0 / 1024.0 ); - qDebug( " - driver for '%s' has been compiled against WE V%d (source=V%d)", name(), _range.we_version_compiled, _range.we_version_source ); - - qDebug( "OWirelessNetworkInterface::() ---------------------------------------------------------" ); -} - - -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(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::commit() const -{ - wioctl( SIOCSIWCOMMIT ); -} - - -void OWirelessNetworkInterface::setMode( const QString& newMode ) -{ - #ifdef FINALIZE - QString currentMode = mode(); - if ( currentMode == newMode ) return; - #endif - - qDebug( "OWirelessNetworkInterface::setMode(): trying to set mode '%s' (%d)", (const char*) newMode, stringToMode( newMode ) ); - - _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" ) - { - qDebug( "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not sufficient - trying fallback to iwpriv..." ); - if ( _mon ) - _mon->setEnabled( false ); - else - qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" ); - } - - } - else // special iwpriv fallback for monitor mode - { - if ( wioctl( SIOCSIWMODE ) ) - { - qDebug( "OWirelessNetworkInterface::setMode(): IW_MODE_MONITOR ok" ); - } - else - { - qDebug( "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not working - trying fallback to iwpriv..." ); - - if ( _mon ) - _mon->setEnabled( true ); - else - qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" ); - } - } -} - - -QString OWirelessNetworkInterface::mode() const -{ - memset( &_iwr, 0, sizeof( struct iwreq ) ); - - if ( !wioctl( SIOCGIWMODE ) ) - { - return ""; - } - - qDebug( "DEBUG: WE's idea of current mode seems to be '%s'", (const char*) modeToString( _iwr.u.mode ) ); - - // 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( (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 ""; - } - 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( child( (const char*) call ) ); - if ( !priv ) - { - qDebug( "OWirelessNetworkInterface::setPrivate(): interface '%s' does not support private ioctl '%s'", name(), (const char*) call ); - return; - } - if ( priv->numberSetArgs() != numargs ) - { - qDebug( "OWirelessNetworkInterface::setPrivate(): parameter count not matching. '%s' expects %d arguments, but got %d", (const char*) call, priv->numberSetArgs(), numargs ); - return; - } - - qDebug( "OWirelessNetworkInterface::setPrivate(): about to call '%s' on interface '%s'", (const char*) call, name() ); - 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& call ) -{ - qWarning( "OWirelessNetworkInterface::getPrivate() is not implemented yet." ); -} - - -bool OWirelessNetworkInterface::hasPrivate( const QString& call ) -{ - return child( (const char*) call ); -} - - -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 ""; - } - else - { - return str; - } -} - - -void OWirelessNetworkInterface::setSSID( const QString& ssid ) -{ - _iwr.u.essid.pointer = const_cast( (const char*) ssid ); - _iwr.u.essid.length = ssid.length(); - 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; - - qDebug( "ONetworkInterface::scanNetwork() - scan started." ); - - 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) - { - qDebug( "ONetworkInterface::scanNetwork() - scan in progress..." ); - #if 0 - if ( qApp ) - { - qApp->processEvents( 100 ); - continue; - } - #endif - tv.tv_sec = 0; - tv.tv_usec = 100000; - continue; - } - } - - qDebug( "ONetworkInterface::scanNetwork() - scan finished." ); - - if ( results ) - { - qDebug( " - result length = %d", _iwr.u.data.length ); - if ( !_iwr.u.data.length ) - { - qDebug( " - no results (empty neighbourhood)" ); - return stations; - } - - qDebug( " - results are in!" ); - dumpBytes( (const unsigned char*) &buffer[0], _iwr.u.data.length ); - - // parse results - - int offset = 0; - struct iw_event* we = (struct iw_event*) &buffer[0]; - - while ( offset < _iwr.u.data.length ) - { - //const char* cmd = *(*_ioctlmap)[we->cmd]; - //if ( !cmd ) cmd = ""; - qDebug( "reading next event... cmd=%d, len=%d", we->cmd, we->len ); - switch (we->cmd) - { - case SIOCGIWAP: - { - qDebug( "SIOCGIWAP" ); - stations->append( new OStation() ); - stations->last()->macAddress = (const unsigned char*) &we->u.ap_addr.sa_data[0]; - break; - } - case SIOCGIWMODE: - { - qDebug( "SIOCGIWMODE" ); - stations->last()->type = modeToString( we->u.mode ); - break; - } - case SIOCGIWFREQ: - { - qDebug( "SIOCGIWFREQ" ); - stations->last()->channel = _channels[ static_cast(double( we->u.freq.m ) * pow( 10.0, we->u.freq.e ) / 1000000) ]; - break; - } - case SIOCGIWESSID: - { - qDebug( "SIOCGIWESSID" ); - stations->last()->ssid = we->u.essid.pointer; - break; - } - case SIOCGIWSENS: qDebug( "SIOCGIWSENS" ); break; - case SIOCGIWENCODE: qDebug( "SIOCGIWENCODE" ); break; - case IWEVTXDROP: qDebug( "IWEVTXDROP" ); break; /* Packet dropped to excessive retry */ - case IWEVQUAL: qDebug( "IWEVQUAL" ); break; /* Quality part of statistics (scan) */ - case IWEVCUSTOM: qDebug( "IWEVCUSTOM" ); break; /* Driver specific ascii string */ - case IWEVREGISTERED: qDebug( "IWEVREGISTERED" ); break; /* Discovered a new node (AP mode) */ - case IWEVEXPIRED: qDebug( "IWEVEXPIRED" ); break; /* Expired a node (AP mode) */ - default: qDebug( "unhandled event" ); - } - - offset += we->len; - we = (struct iw_event*) &buffer[offset]; - } - return stations; - - return stations; - - } - else - { - qDebug( " - no results (timeout) :(" ); - return stations; - } -} - - -bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const -{ - #ifndef NODEBUG - int result = ::ioctl( _sfd, call, &iwreq ); - if ( result == -1 ) - qDebug( "ONetworkInterface::wioctl (%s) call %s (0x%04X) - Status: Failed: %d (%s)", name(), (const char*) debugmapper->map( call ), call, result, strerror( errno ) ); - else - qDebug( "ONetworkInterface::wioctl (%s) call %s (0x%04X) - Status: Ok.", name(), (const char*) debugmapper->map( call ), call ); - 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( 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 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, (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 ) -{ - int monitorCode = _prismHeader ? 1 : 2; - if ( b ) - { - _if->setPrivate( "monitor", 1, monitorCode ); - } - else - { - _if->setPrivate( "monitor", 1, 0 ); - } -} - - -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 ( b ) - { - setChannel( 1 ); - } - else - { - _if->setPrivate( "monitor", 2, 0, 0 ); - } -} - - -QString OOrinocoMonitoringInterface::name() const -{ - return "orinoco"; -} +/* +                 This file is part of the Opie Project +              Copyright (C) 2003 by Michael 'Mickey' Lauer + =. + .=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; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: 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 +#include +#include + +/* QT */ + +#include +#include + +/* UNIX */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NODEBUG +#include +DebugMapper* debugmapper = new DebugMapper(); +#endif + +/*====================================================================================== + * ONetwork + *======================================================================================*/ + +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; + 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::wirelessExtensionVersion() +{ + 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::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 ""; + +} + + +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 ""; +} + + +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 ); +} + + +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 ), _tid( 0 ) +{ + int _maxChannel = iface->channels()+1; + // generate fancy hopping sequence honoring the device capabilities + if ( _maxChannel >= 1 ) _channels.append( 1 ); + if ( _maxChannel >= 7 ) _channels.append( 7 ); + if ( _maxChannel >= 13 ) _channels.append( 13 ); + if ( _maxChannel >= 2 ) _channels.append( 2 ); + if ( _maxChannel >= 8 ) _channels.append( 8 ); + if ( _maxChannel >= 3 ) _channels.append( 3 ); + if ( _maxChannel >= 14 ) _channels.append( 14 ); + if ( _maxChannel >= 9 ) _channels.append( 9 ); + if ( _maxChannel >= 4 ) _channels.append( 4 ); + if ( _maxChannel >= 10 ) _channels.append( 10 ); + if ( _maxChannel >= 5 ) _channels.append( 5 ); + if ( _maxChannel >= 11 ) _channels.append( 11 ); + if ( _maxChannel >= 6 ) _channels.append( 6 ); + if ( _maxChannel >= 12 ) _channels.append( 12 ); + _channel = _channels.begin(); + +} + + +OChannelHopper::~OChannelHopper() +{ +} + + +bool OChannelHopper::isActive() const +{ + return _tid; +} + + +int OChannelHopper::channel() const +{ + return *_channel; +} + + +void OChannelHopper::timerEvent( QTimerEvent* ) +{ + _iface->setChannel( *_channel ); + emit( hopped( *_channel ) ); + odebug << "OChannelHopper::timerEvent(): set channel " << *_channel << " on interface '" << _iface->name() << "'" << oendl; + if ( ++_channel == _channels.end() ) _channel = _channels.begin(); +} + + +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( QObject* parent, const char* name ) + :ONetworkInterface( parent, name ), _hopper( 0 ) +{ + odebug << "OWirelessNetworkInterface::OWirelessNetworkInterface()" << oendl; + init(); +} + + +OWirelessNetworkInterface::~OWirelessNetworkInterface() +{ +} + + +struct iwreq& OWirelessNetworkInterface::iwr() const +{ + return _iwr; +} + + +void OWirelessNetworkInterface::init() +{ + odebug << "OWirelessNetworkInterface::init()" << oendl; + memset( &_iwr, 0, sizeof( struct iwreq ) ); + buildInformation(); + buildPrivateList(); + dumpInformation(); +} + + +bool OWirelessNetworkInterface::isAssociated() const +{ + //FIXME: handle different modes + return !(associatedAP() == OMacAddress::unknown); +} + + +OMacAddress OWirelessNetworkInterface::associatedAP() const +{ + if ( ioctl( SIOCGIWAP ) ) + return (const unsigned char*) &_ifr.ifr_hwaddr.sa_data[0]; + else + return OMacAddress::unknown; +} + + +void OWirelessNetworkInterface::buildInformation() +{ + //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* + //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 ) + { + owarn << "OWirelessNetworkInterface::buildInformation(): Can't get channel information - using default values." << oendl; + _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 + + memset( &_range, 0, sizeof( struct iw_range ) ); + } + else + { + // + int max = 0; + 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; + } + // + + 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 ); + _channels.insert( freq, i+1 ); + } + } + + memcpy( &_range, buffer, sizeof( struct iw_range ) ); + odebug << "OWirelessNetworkInterface::buildInformation(): Information block constructed." << oendl; + free(buffer); +} + + +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; + + qDebug( " - driver's idea of maximum throughput is %d bps = %d byte/s = %d Kb/s = %f.2 Mb/s", _range.throughput, _range.throughput / 8, _range.throughput / 8 / 1024, float( _range.throughput ) / 8.0 / 1024.0 / 1024.0 ); + qDebug( " - driver for '%s' has been compiled against WE V%d (source=V%d)", name(), _range.we_version_compiled, _range.we_version_source ); + + 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(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 ""; + } + + 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( (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 ""; + } + 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( 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& call ) +{ + oerr << "OWirelessNetworkInterface::getPrivate() is not implemented yet." << oendl; +} + + +bool OWirelessNetworkInterface::hasPrivate( const QString& call ) +{ + return child( (const char*) call ); +} + + +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 ""; + } + else + { + return str; + } +} + + +void OWirelessNetworkInterface::setSSID( const QString& ssid ) +{ + _iwr.u.essid.pointer = const_cast( (const char*) ssid ); + _iwr.u.essid.length = ssid.length(); + 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; + + 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 + + int offset = 0; + struct iw_event* we = (struct iw_event*) &buffer[0]; + + while ( offset < _iwr.u.data.length ) + { + //const char* cmd = *(*_ioctlmap)[we->cmd]; + //if ( !cmd ) cmd = ""; + 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(double( we->u.freq.m ) * pow( 10.0, we->u.freq.e ) / 1000000) ]; + break; + } + case SIOCGIWESSID: + { + odebug << "SIOCGIWESSID" << oendl; + stations->last()->ssid = we->u.essid.pointer; + 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; + + } + else + { + odebug << " - no results (timeout) :(" << oendl; + return stations; + } +} + + +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( 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 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, (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 ) +{ + int monitorCode = _prismHeader ? 1 : 2; + if ( b ) + { + _if->setPrivate( "monitor", 1, monitorCode ); + } + else + { + _if->setPrivate( "monitor", 1, 0 ); + } +} + + +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 ( b ) + { + setChannel( 1 ); + } + else + { + _if->setPrivate( "monitor", 2, 0, 0 ); + } +} + + +QString OOrinocoMonitoringInterface::name() const +{ + return "orinoco"; +} diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 635224c..e9b3b2c 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -1,1320 +1,1317 @@ -/* -                 This file is part of the Opie Project -              Copyright (C) 2003 by Michael 'Mickey' Lauer - =. - .=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; either version 2 of the License, -     ._= =}       : or (at your option) any later version. -    .%`+i>       _;_. -    .i_,=:_.      -`: 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 - -/* QT */ -#include // don't use oapplication here (will decrease reusability in other projects) -#include -#include - -/* SYSTEM */ -#include -#include -#include - -/* LOCAL */ -#include "udp_ports.h" - -/*====================================================================================== - * OPacket - *======================================================================================*/ - -OPacket::OPacket( int datalink, packetheaderstruct header, const unsigned char* data, QObject* parent ) - :QObject( parent, "Generic" ), _hdr( header ), _data( data ) -{ - //qDebug( "OPacket::OPacket(): (Len %d, CapLen %d)" /*, ctime((const time_t*) header.ts.tv_sec)*/, header.len, header.caplen ); - - _end = (unsigned char*) data + header.len; - //qDebug( "OPacket::data @ %0x, end @ %0x", data, _end ); - - switch ( datalink ) - { - case DLT_EN10MB: - qDebug( "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" ); - new OEthernetPacket( _end, (const struct ether_header*) data, this ); - break; - - case DLT_IEEE802_11: - qDebug( "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" ); - new OWaveLanPacket( _end, (const struct ieee_802_11_header*) data, this ); - break; - - case DLT_PRISM_HEADER: - qDebug( "OPacket::OPacket(): Received Packet. Datalink = PRISM_HEADER" ); - new OPrismHeaderPacket( _end, (const struct prism_hdr*) (unsigned char*) data, this ); - break; - - default: - qWarning( "OPacket::OPacket(): Received Packet over unsupported datalink (type %d)!", datalink ); - } -} - - -OPacket::~OPacket() -{ -} - - -timevalstruct OPacket::timeval() const -{ - return _hdr.ts; -} - - -int OPacket::caplen() const -{ - return _hdr.caplen; -} - - -void OPacket::updateStats( QMap& stats, QObjectList* l ) -{ - if (!l) return; - QObject* o = l->first(); - while ( o ) - { - stats[o->name()]++; - updateStats( stats, const_cast( o->children() ) ); - o = l->next(); - } -} - - -void OPacket::dumpStructure( QObjectList* l ) -{ - QString packetString( "[ |" + _dumpStructure( l ) + " ]" ); - qDebug( "OPacket::dumpStructure: %s", (const char*) packetString ); -} - - -QString OPacket::_dumpStructure( QObjectList* l ) -{ - if (!l) return QString::null; - QObject* o = l->first(); - QString str(" "); - - while ( o ) - { - str.append( o->name() ); - str.append( " |" ); - str += _dumpStructure( const_cast( o->children() ) ); - o = l->next(); - } - return str; -} - -QString OPacket::dump( int bpl ) const -{ - static int index = 0; - index++; - int len = _hdr.caplen; - QString str; - str.sprintf( "\n<----- Packet #%04d Len = 0x%X (%d) ----->\n\n", index, len, len ); - str.append( "0000: " ); - QString tmp; - QString bytes; - QString chars; - - for ( int i = 0; i < len; ++i ) - { - tmp.sprintf( "%02X ", _data[i] ); bytes.append( tmp ); - if ( (_data[i] > 31) && (_data[i]<128) ) chars.append( _data[i] ); - else chars.append( '.' ); - - if ( !((i+1) % bpl) ) - { - str.append( bytes ); - str.append( ' ' ); - str.append( chars ); - str.append( '\n' ); - tmp.sprintf( "%04X: ", i+1 ); str.append( tmp ); - bytes = ""; - chars = ""; - } - - } - if ( (len % bpl) ) - { - str.append( bytes.leftJustify( 1 + 3*bpl ) ); - str.append( chars ); - } - str.append( '\n' ); - return str; -} - - -int OPacket::len() const -{ - return _hdr.len; -} - - -/*====================================================================================== - * OEthernetPacket - *======================================================================================*/ - -OEthernetPacket::OEthernetPacket( const unsigned char* end, const struct ether_header* data, QObject* parent ) - :QObject( parent, "Ethernet" ), _ether( data ) -{ - - qDebug( "Source = %s", (const char*) sourceAddress().toString() ); - qDebug( "Destination = %s", (const char*) destinationAddress().toString() ); - - if ( sourceAddress() == OMacAddress::broadcast ) - qDebug( "Source is broadcast address" ); - if ( destinationAddress() == OMacAddress::broadcast ) - qDebug( "Destination is broadcast address" ); - - switch ( type() ) - { - case ETHERTYPE_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; - case ETHERTYPE_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break; - case ETHERTYPE_REVARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" ); break; } - default: qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" ); - } - -} - - -OEthernetPacket::~OEthernetPacket() -{ -} - - -OMacAddress OEthernetPacket::sourceAddress() const -{ - return OMacAddress( _ether->ether_shost ); -} - - -OMacAddress OEthernetPacket::destinationAddress() const -{ - return OMacAddress( _ether->ether_dhost ); -} - -int OEthernetPacket::type() const -{ - return ntohs( _ether->ether_type ); -} - - -/*====================================================================================== - * OIPPacket - *======================================================================================*/ - - -OIPPacket::OIPPacket( const unsigned char* end, const struct iphdr* data, QObject* parent ) - :QObject( parent, "IP" ), _iphdr( data ) -{ - qDebug( "OIPPacket::OIPPacket(): decoding IP header..." ); - - //qDebug( "FromAddress: %s", (const char*) inet_ntoa( *src ) ); - //qDebug( " ToAddress: %s", (const char*) inet_ntoa( *dst ) ); - - qDebug( "FromAddress: %s", (const char*) fromIPAddress().toString() ); - qDebug( " toAddress: %s", (const char*) toIPAddress().toString() ); - - switch ( protocol() ) - { - case IPPROTO_UDP: new OUDPPacket( end, (const struct udphdr*) (data+1), this ); break; - case IPPROTO_TCP: new OTCPPacket( end, (const struct tcphdr*) (data+1), this ); break; - default: qDebug( "OIPPacket::OIPPacket(): unknown IP protocol type = %d", protocol() ); - } - -} - -OIPPacket::~OIPPacket() -{ -} - - -QHostAddress OIPPacket::fromIPAddress() const -{ - return EXTRACT_32BITS( &_iphdr->saddr ); -} - - -QHostAddress OIPPacket::toIPAddress() const -{ - return EXTRACT_32BITS( &_iphdr->saddr ); -} - - -int OIPPacket::tos() const -{ - return _iphdr->tos; -} - - -int OIPPacket::len() const -{ - return EXTRACT_16BITS( &_iphdr->tot_len ); -} - - -int OIPPacket::id() const -{ - return EXTRACT_16BITS( &_iphdr->id ); -} - - -int OIPPacket::offset() const -{ - return EXTRACT_16BITS( &_iphdr->frag_off ); -} - - -int OIPPacket::ttl() const -{ - return _iphdr->ttl; -} - - -int OIPPacket::protocol() const -{ - return _iphdr->protocol; -} - - -int OIPPacket::checksum() const -{ - return EXTRACT_16BITS( &_iphdr->check ); -} - -/*====================================================================================== - * OARPPacket - *======================================================================================*/ - - -OARPPacket::OARPPacket( const unsigned char* end, const struct myarphdr* data, QObject* parent ) - :QObject( parent, "ARP" ), _arphdr( data ) -{ - qDebug( "OARPPacket::OARPPacket(): decoding ARP header..." ); - qDebug( "ARP type seems to be %02d - '%s'", EXTRACT_16BITS( &_arphdr->ar_op ), (const char*) type() ); - qDebug( "Sender: MAC %s = IP %s", (const char*) senderMacAddress().toString(), (const char*) senderIPV4Address().toString() ); - qDebug( "Target: MAC %s = IP %s", (const char*) targetMacAddress().toString(), (const char*) targetIPV4Address().toString() ); -} - - -OARPPacket::~OARPPacket() -{ -} - - -QString OARPPacket::type() const -{ - switch ( EXTRACT_16BITS( &_arphdr->ar_op ) ) - { - case 1: return "REQUEST"; - case 2: return "REPLY"; - case 3: return "RREQUEST"; - case 4: return "RREPLY"; - case 8: return "InREQUEST"; - case 9: return "InREPLY"; - case 10: return "NAK"; - default: qWarning( "OARPPacket::type(): invalid ARP type!" ); return ""; - } -} - - -QHostAddress OARPPacket::senderIPV4Address() const -{ - return EXTRACT_32BITS( &_arphdr->ar_sip ); -} - - -QHostAddress OARPPacket::targetIPV4Address() const -{ - return EXTRACT_32BITS( &_arphdr->ar_tip ); -} - - -OMacAddress OARPPacket::senderMacAddress() const -{ - return OMacAddress( _arphdr->ar_sha ); -} - - -OMacAddress OARPPacket::targetMacAddress() const -{ - return OMacAddress( _arphdr->ar_tha ); -} - - -/*====================================================================================== - * OUDPPacket - *======================================================================================*/ - - -OUDPPacket::OUDPPacket( const unsigned char* end, const struct udphdr* data, QObject* parent ) - :QObject( parent, "UDP" ), _udphdr( data ) - -{ - qDebug( "OUDPPacket::OUDPPacket(): decoding UDP header..." ); - qDebug( "fromPort = %d", fromPort() ); - qDebug( " toPort = %d", toPort() ); - - // TODO: Make this a case or a hash if we know more udp protocols - - if ( fromPort() == UDP_PORT_BOOTPS || fromPort() == UDP_PORT_BOOTPC || - toPort() == UDP_PORT_BOOTPS || toPort() == UDP_PORT_BOOTPC ) - { - qDebug( "seems to be part of a DHCP conversation => creating DHCP packet." ); - new ODHCPPacket( end, (const struct dhcp_packet*) (data+1), this ); - } -} - - -OUDPPacket::~OUDPPacket() -{ -} - - -int OUDPPacket::fromPort() const -{ - return EXTRACT_16BITS( &_udphdr->source ); -} - - -int OUDPPacket::toPort() const -{ - return EXTRACT_16BITS( &_udphdr->dest ); -} - - -int OUDPPacket::length() const -{ - return EXTRACT_16BITS( &_udphdr->len ); -} - - -int OUDPPacket::checksum() const -{ - return EXTRACT_16BITS( &_udphdr->check ); -} - - -/*====================================================================================== - * ODHCPPacket - *======================================================================================*/ - - -ODHCPPacket::ODHCPPacket( const unsigned char* end, const struct dhcp_packet* data, QObject* parent ) - :QObject( parent, "DHCP" ), _dhcphdr( data ) - -{ - qDebug( "ODHCPPacket::ODHCPPacket(): decoding DHCP information..." ); - qDebug( "DHCP opcode seems to be %02d - '%s'", _dhcphdr->op, isRequest() ? "REQUEST" : "REPLY" ); - qDebug( "clientAddress: %s", (const char*) clientAddress().toString() ); - qDebug( " yourAddress: %s", (const char*) yourAddress().toString() ); - qDebug( "serverAddress: %s", (const char*) serverAddress().toString() ); - qDebug( " relayAddress: %s", (const char*) relayAddress().toString() ); - qDebug( "parsing DHCP options..." ); - - _type = 0; - - const unsigned char* option = &_dhcphdr->options[4]; - char tag = -1; - char len = -1; - - while ( ( tag = *option++ ) != -1 /* end of option field */ ) - { - len = *option++; - qDebug( "recognized DHCP option #%d, length %d", tag, len ); - - if ( tag == DHO_DHCP_MESSAGE_TYPE ) - _type = *option; - - option += len; - if ( option >= end ) - { - qWarning( "DHCP parsing ERROR: sanity check says the packet is at its end!" ); - break; - } - } - - qDebug( "DHCP type seems to be '%s'", (const char*) type() ); -} - - -ODHCPPacket::~ODHCPPacket() -{ -} - - -bool ODHCPPacket::isRequest() const -{ - return ( _dhcphdr->op == 01 ); -} - - -bool ODHCPPacket::isReply() const -{ - return ( _dhcphdr->op == 02 ); -} - - -QString ODHCPPacket::type() const -{ - switch ( _type ) - { - case 1: return "DISCOVER"; - case 2: return "OFFER"; - case 3: return "REQUEST"; - case 4: return "DECLINE"; - case 5: return "ACK"; - case 6: return "NAK"; - case 7: return "RELEASE"; - case 8: return "INFORM"; - default: qWarning( "ODHCPPacket::type(): invalid DHCP type (%d) !", _dhcphdr->op ); return ""; - } -} - - -QHostAddress ODHCPPacket::clientAddress() const -{ - return EXTRACT_32BITS( &_dhcphdr->ciaddr ); -} - - -QHostAddress ODHCPPacket::yourAddress() const -{ - return EXTRACT_32BITS( &_dhcphdr->yiaddr ); -} - - -QHostAddress ODHCPPacket::serverAddress() const -{ - return EXTRACT_32BITS( &_dhcphdr->siaddr ); -} - - -QHostAddress ODHCPPacket::relayAddress() const -{ - return EXTRACT_32BITS( &_dhcphdr->giaddr ); -} - - -OMacAddress ODHCPPacket::clientMacAddress() const -{ - return OMacAddress( _dhcphdr->chaddr ); -} - - -/*====================================================================================== - * OTCPPacket - *======================================================================================*/ - - -OTCPPacket::OTCPPacket( const unsigned char* end, const struct tcphdr* data, QObject* parent ) - :QObject( parent, "TCP" ), _tcphdr( data ) - -{ - qDebug( "OTCPPacket::OTCPPacket(): decoding TCP header..." ); -} - - -OTCPPacket::~OTCPPacket() -{ -} - - -int OTCPPacket::fromPort() const -{ - return EXTRACT_16BITS( &_tcphdr->source ); -} - - -int OTCPPacket::toPort() const -{ - return EXTRACT_16BITS( &_tcphdr->dest ); -} - - -int OTCPPacket::seq() const -{ - return EXTRACT_16BITS( &_tcphdr->seq ); -} - - -int OTCPPacket::ack() const -{ - return EXTRACT_16BITS( &_tcphdr->ack_seq ); -} - - -int OTCPPacket::window() const -{ - return EXTRACT_16BITS( &_tcphdr->window ); -} - - -int OTCPPacket::checksum() const -{ - return EXTRACT_16BITS( &_tcphdr->check ); -} - -/*====================================================================================== - * OPrismHeaderPacket - *======================================================================================*/ - - -OPrismHeaderPacket::OPrismHeaderPacket( const unsigned char* end, const struct prism_hdr* data, QObject* parent ) - :QObject( parent, "Prism" ), _header( data ) - -{ - qDebug( "OPrismHeaderPacket::OPrismHeaderPacket(): decoding PRISM header..." ); - - qDebug( "Signal Strength = %d", data->signal.data ); - - new OWaveLanPacket( end, (const struct ieee_802_11_header*) (data+1), this ); -} - -OPrismHeaderPacket::~OPrismHeaderPacket() -{ -} - - -unsigned int OPrismHeaderPacket::signalStrength() const -{ - return _header->signal.data; -} - -/*====================================================================================== - * OWaveLanPacket - *======================================================================================*/ - - -OWaveLanPacket::OWaveLanPacket( const unsigned char* end, const struct ieee_802_11_header* data, QObject* parent ) - :QObject( parent, "802.11" ), _wlanhdr( data ) - -{ - qDebug( "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." ); - qDebug( "type: %0X", type() ); - qDebug( "subType: %0X", subType() ); - qDebug( "duration: %d", duration() ); - qDebug( "powermanagement: %d", usesPowerManagement() ); - qDebug( "payload is encrypted: %s", usesWep() ? "yes" : "no" ); - qDebug( "MAC1: %s", (const char*) macAddress1().toString() ); - qDebug( "MAC2: %s", (const char*) macAddress2().toString() ); - qDebug( "MAC3: %s", (const char*) macAddress3().toString() ); - qDebug( "MAC4: %s", (const char*) macAddress4().toString() ); - - switch ( type() ) - { - case T_MGMT: new OWaveLanManagementPacket( end, (const struct ieee_802_11_mgmt_header*) data, this ); break; - case T_DATA: new OWaveLanDataPacket( end, (const struct ieee_802_11_data_header*) data, this ); break; - case T_CTRL: new OWaveLanControlPacket( end, (const struct ieee_802_11_control_header*) data, this ); break; - default: qDebug( "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown major type '%d'!", type() ); - } -} - -OWaveLanPacket::~OWaveLanPacket() -{ -} - - -int OWaveLanPacket::duration() const -{ - return _wlanhdr->duration; -} - - -OMacAddress OWaveLanPacket::macAddress1() const -{ - return OMacAddress( _wlanhdr->mac1 ); -} - - -OMacAddress OWaveLanPacket::macAddress2() const -{ - return OMacAddress( _wlanhdr->mac2 ); -} - - -OMacAddress OWaveLanPacket::macAddress3() const -{ - return OMacAddress( _wlanhdr->mac3 ); -} - - -OMacAddress OWaveLanPacket::macAddress4() const -{ - return OMacAddress( _wlanhdr->mac4 ); -} - - -int OWaveLanPacket::subType() const -{ - return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -int OWaveLanPacket::type() const -{ - return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -int OWaveLanPacket::version() const -{ - return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -bool OWaveLanPacket::fromDS() const -{ - return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -bool OWaveLanPacket::toDS() const -{ - return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -bool OWaveLanPacket::usesPowerManagement() const -{ - return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -bool OWaveLanPacket::usesWep() const -{ - return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); -} - - -/*====================================================================================== - * OWaveLanManagementPacket - *======================================================================================*/ - -OWaveLanManagementPacket::OWaveLanManagementPacket( const unsigned char* end, const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent ) - :QObject( parent, "802.11 Management" ), _header( data ), - _body( (const struct ieee_802_11_mgmt_body*) (data+1) ) -{ - qDebug( "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." ); - qDebug( "Detected subtype is '%s'", (const char*) managementType() ); - - // grab tagged values - const unsigned char* ptr = (const unsigned char*) (_body+1); - while (ptr < end) - { - switch ( *ptr ) - { - case E_SSID: new OWaveLanManagementSSID( end, (struct ssid_t*) ptr, this ); break; - case E_FH: new OWaveLanManagementFH( end, (struct fh_t*) ptr, this ); break; - case E_DS: new OWaveLanManagementDS( end, (struct ds_t*) ptr, this ); break; - case E_RATES: new OWaveLanManagementRates( end, (struct rates_t*) ptr, this ); break; - case E_CF: new OWaveLanManagementCF( end, (struct cf_t*) ptr, this ); break; - case E_TIM: new OWaveLanManagementTim( end, (struct tim_t*) ptr, this ); break; - case E_IBSS: new OWaveLanManagementIBSS( end, (struct ibss_t*) ptr, this ); break; - case E_CHALLENGE: new OWaveLanManagementChallenge( end, (struct challenge_t*) ptr, this ); break; - } - ptr+= ( ( struct ssid_t* ) ptr )->length; // skip length of tagged value - ptr+= 2; // skip tag ID and length - } -} - - -OWaveLanManagementPacket::~OWaveLanManagementPacket() -{ -} - - -QString OWaveLanManagementPacket::managementType() const -{ - switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ) - { - case ST_ASSOC_REQUEST: return "AssociationRequest"; break; - case ST_ASSOC_RESPONSE: return "AssociationResponse"; break; - case ST_REASSOC_REQUEST: return "ReassociationRequest"; break; - case ST_REASSOC_RESPONSE: return "ReassociationResponse"; break; - case ST_PROBE_REQUEST: return "ProbeRequest"; break; - case ST_PROBE_RESPONSE: return "ProbeResponse"; break; - case ST_BEACON: return "Beacon"; break; - case ST_ATIM: return "Atim"; break; - case ST_DISASSOC: return "Disassociation"; break; - case ST_AUTH: return "Authentication"; break; - case ST_DEAUTH: return "Deathentication"; break; - default: - qWarning( "OWaveLanManagementPacket::managementType(): unhandled subtype %d", FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ); - return "Unknown"; - } -} - - -int OWaveLanManagementPacket::beaconInterval() const -{ - return EXTRACT_LE_16BITS( &_body->beacon_interval ); -} - - -int OWaveLanManagementPacket::capabilities() const -{ - return EXTRACT_LE_16BITS( &_body->capability_info ); -} - - -bool OWaveLanManagementPacket::canESS() const -{ - return CAPABILITY_ESS( EXTRACT_LE_16BITS( &_body->capability_info ) ); -} - - -bool OWaveLanManagementPacket::canIBSS() const -{ - return CAPABILITY_IBSS( EXTRACT_LE_16BITS( &_body->capability_info ) ); -} - - -bool OWaveLanManagementPacket::canCFP() const -{ - return CAPABILITY_CFP( EXTRACT_LE_16BITS( &_body->capability_info ) ); -} - - -bool OWaveLanManagementPacket::canCFP_REQ() const -{ - return CAPABILITY_CFP_REQ( EXTRACT_LE_16BITS( &_body->capability_info ) ); -} - - -bool OWaveLanManagementPacket::canPrivacy() const -{ - return CAPABILITY_PRIVACY( EXTRACT_LE_16BITS( &_body->capability_info ) ); -} - - -/*====================================================================================== - * OWaveLanManagementSSID - *======================================================================================*/ - -OWaveLanManagementSSID::OWaveLanManagementSSID( const unsigned char* end, const struct ssid_t* data, QObject* parent ) - :QObject( parent, "802.11 SSID" ), _data( data ) -{ - qDebug( "OWaveLanManagementSSID()" ); -} - - -OWaveLanManagementSSID::~OWaveLanManagementSSID() -{ -} - - -QString OWaveLanManagementSSID::ID() const -{ - int length = _data->length; - if ( length > 32 ) length = 32; - char essid[length+1]; - memcpy( &essid, &_data->ssid, length ); - essid[length] = 0x0; - return essid; -} - - -/*====================================================================================== - * OWaveLanManagementRates - *======================================================================================*/ - -OWaveLanManagementRates::OWaveLanManagementRates( const unsigned char* end, const struct rates_t* data, QObject* parent ) - :QObject( parent, "802.11 Rates" ), _data( data ) -{ - qDebug( "OWaveLanManagementRates()" ); -} - - -OWaveLanManagementRates::~OWaveLanManagementRates() -{ -} - -/*====================================================================================== - * OWaveLanManagementCF - *======================================================================================*/ - -OWaveLanManagementCF::OWaveLanManagementCF( const unsigned char* end, const struct cf_t* data, QObject* parent ) - :QObject( parent, "802.11 CF" ), _data( data ) -{ - qDebug( "OWaveLanManagementCF()" ); -} - - -OWaveLanManagementCF::~OWaveLanManagementCF() -{ -} - -/*====================================================================================== - * OWaveLanManagementFH - *======================================================================================*/ - -OWaveLanManagementFH::OWaveLanManagementFH( const unsigned char* end, const struct fh_t* data, QObject* parent ) - :QObject( parent, "802.11 FH" ), _data( data ) -{ - qDebug( "OWaveLanManagementFH()" ); -} - - -OWaveLanManagementFH::~OWaveLanManagementFH() -{ -} - -/*====================================================================================== - * OWaveLanManagementDS - *======================================================================================*/ - -OWaveLanManagementDS::OWaveLanManagementDS( const unsigned char* end, const struct ds_t* data, QObject* parent ) - :QObject( parent, "802.11 DS" ), _data( data ) -{ - qDebug( "OWaveLanManagementDS()" ); -} - - -OWaveLanManagementDS::~OWaveLanManagementDS() -{ -} - - -int OWaveLanManagementDS::channel() const -{ - return _data->channel; -} - -/*====================================================================================== - * OWaveLanManagementTim - *======================================================================================*/ - -OWaveLanManagementTim::OWaveLanManagementTim( const unsigned char* end, const struct tim_t* data, QObject* parent ) - :QObject( parent, "802.11 Tim" ), _data( data ) -{ - qDebug( "OWaveLanManagementTim()" ); -} - - -OWaveLanManagementTim::~OWaveLanManagementTim() -{ -} - -/*====================================================================================== - * OWaveLanManagementIBSS - *======================================================================================*/ - -OWaveLanManagementIBSS::OWaveLanManagementIBSS( const unsigned char* end, const struct ibss_t* data, QObject* parent ) - :QObject( parent, "802.11 IBSS" ), _data( data ) -{ - qDebug( "OWaveLanManagementIBSS()" ); -} - - -OWaveLanManagementIBSS::~OWaveLanManagementIBSS() -{ -} - -/*====================================================================================== - * OWaveLanManagementChallenge - *======================================================================================*/ - -OWaveLanManagementChallenge::OWaveLanManagementChallenge( const unsigned char* end, const struct challenge_t* data, QObject* parent ) - :QObject( parent, "802.11 Challenge" ), _data( data ) -{ - qDebug( "OWaveLanManagementChallenge()" ); -} - - -OWaveLanManagementChallenge::~OWaveLanManagementChallenge() -{ -} - -/*====================================================================================== - * OWaveLanDataPacket - *======================================================================================*/ - -OWaveLanDataPacket::OWaveLanDataPacket( const unsigned char* end, const struct ieee_802_11_data_header* data, OWaveLanPacket* parent ) - :QObject( parent, "802.11 Data" ), _header( data ) -{ - qDebug( "OWaveLanDataPacket::OWaveLanDataPacket(): decoding frame..." ); - - const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header ); - - #warning The next line works for most cases, but can not be correct generally! - if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address - - new OLLCPacket( end, (const struct ieee_802_11_802_2_header*) payload, this ); -} - - -OWaveLanDataPacket::~OWaveLanDataPacket() -{ -} - - -/*====================================================================================== - * OLLCPacket - *======================================================================================*/ - -OLLCPacket::OLLCPacket( const unsigned char* end, const struct ieee_802_11_802_2_header* data, QObject* parent ) - :QObject( parent, "802.11 LLC" ), _header( data ) -{ - qDebug( "OLLCPacket::OLLCPacket(): decoding frame..." ); - - if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) ) - { - qDebug( "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type=%04X)", EXTRACT_16BITS( &_header->type ) ); - - switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h - { - case ETH_P_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; - case ETH_P_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break; - default: qWarning( "OLLCPacket::OLLCPacket(): Unknown Encapsulation (type=%04X)", EXTRACT_16BITS( &_header->type ) ); - } - - } -} - - -OLLCPacket::~OLLCPacket() -{ -} - - -/*====================================================================================== - * OWaveLanControlPacket - *======================================================================================*/ - -OWaveLanControlPacket::OWaveLanControlPacket( const unsigned char* end, const struct ieee_802_11_control_header* data, OWaveLanPacket* parent ) - :QObject( parent, "802.11 Control" ), _header( data ) -{ - qDebug( "OWaveLanControlPacket::OWaveLanDataControl(): decoding frame..." ); - //TODO: Implement this -} - - -OWaveLanControlPacket::~OWaveLanControlPacket() -{ -} - - -/*====================================================================================== - * OPacketCapturer - *======================================================================================*/ - -OPacketCapturer::OPacketCapturer( QObject* parent, const char* name ) - :QObject( parent, name ), _name( QString::null ), _open( false ), - _pch( 0 ), _pcd( 0 ), _sn( 0 ) -{ -} - - -OPacketCapturer::~OPacketCapturer() -{ - if ( _open ) - { - qDebug( "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." ); - close(); - } -} - - -void OPacketCapturer::setBlocking( bool b ) -{ - if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 ) - { - qDebug( "OPacketCapturer::setBlocking(): blocking mode changed successfully." ); - } - else - { - qDebug( "OPacketCapturer::setBlocking(): can't change blocking mode: %s", _errbuf ); - } -} - - -bool OPacketCapturer::blocking() const -{ - int b = pcap_getnonblock( _pch, _errbuf ); - if ( b == -1 ) - { - qDebug( "OPacketCapturer::blocking(): can't get blocking mode: %s", _errbuf ); - return -1; - } - return !b; -} - - -void OPacketCapturer::closeDumpFile() -{ - if ( _pcd ) - { - pcap_dump_close( _pcd ); - _pcd = 0; - } - pcap_close( _pch ); -} - - -void OPacketCapturer::close() -{ - if ( _open ) - { - if ( _sn ) - { - _sn->disconnect( SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); - delete _sn; - } - closeDumpFile(); - _open = false; - } - - qDebug( "OPacketCapturer::close() --- dumping capturing statistics..." ); - qDebug( "--------------------------------------------------" ); - for( QMap::Iterator it = _stats.begin(); it != _stats.end(); ++it ) - qDebug( "%s : %d", (const char*) it.key(), it.data() ); - qDebug( "--------------------------------------------------" ); - -} - - -int OPacketCapturer::dataLink() const -{ - return pcap_datalink( _pch ); -} - - -void OPacketCapturer::dump( OPacket* p ) -{ - if ( !_pcd ) - { - qWarning( "OPacketCapturer::dump() - cannot dump without open capture file!" ); - return; - } - pcap_dump( (u_char*) _pcd, &p->_hdr, p->_data ); -} - - -int OPacketCapturer::fileno() const -{ - if ( _open ) - { - return pcap_fileno( _pch ); - } - else - { - return -1; - } -} - - -OPacket* OPacketCapturer::next( int time ) -{ - fd_set fds; - struct timeval tv; - FD_ZERO( &fds ); - FD_SET( pcap_fileno( _pch ), &fds ); - tv.tv_sec = time / 1000; - tv.tv_usec = time % 1000; - int retval = select( pcap_fileno( _pch )+1, &fds, NULL, NULL, &tv); - if ( retval > 0 ) // clear to read! - return next(); - else - return 0; -} - - -OPacket* OPacketCapturer::next() -{ - packetheaderstruct header; - qDebug( "==> OPacketCapturer::next()" ); - const unsigned char* pdata = pcap_next( _pch, &header ); - qDebug( "<== OPacketCapturer::next()" ); - - if ( pdata && header.len ) - { - OPacket* p = new OPacket( dataLink(), header, pdata, 0 ); - // packets shouldn't be inserted in the QObject child-parent hierarchy, - // because due to memory constraints they will be deleted as soon - // as possible - that is right after they have been processed - // by emit() [ see below ] - //TODO: make gathering statistics optional, because it takes time - p->updateStats( _stats, const_cast( p->children() ) ); - #ifndef NODEBUG - p->dumpStructure( const_cast( p->children() ) ); - #endif - return p; - } - else - { - qWarning( "OPacketCapturer::next() - no packet received!" ); - return 0; - } -} - - -bool OPacketCapturer::open( const QString& name ) -{ - if ( _open ) - { - if ( name == _name ) // ignore opening an already openend device - { - return true; - } - else // close the last opened device - { - close(); - } - } - - _name = name; - - // open libpcap - pcap_t* handle = pcap_open_live( const_cast( (const char*) name ), 1024, 0, 0, &_errbuf[0] ); - - if ( !handle ) - { - qWarning( "OPacketCapturer::open(): can't open libpcap with '%s': %s", (const char*) name, _errbuf ); - return false; - } - - qDebug( "OPacketCapturer::open(): libpcap [%s] opened successfully.", (const char*) name ); - _pch = handle; - _open = true; - _stats.clear(); - - // in case we have an application object, create a socket notifier - if ( qApp ) //TODO: I don't like this here... - { - _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read ); - connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); - } - - return true; -} - - -bool OPacketCapturer::openDumpFile( const QString& filename ) -{ - pcap_dumper_t* dump = pcap_dump_open( _pch, const_cast( (const char*) filename ) ); - if ( !dump ) - { - qWarning( "OPacketCapturer::open(): can't open dump with '%s': %s", (const char*) filename, _errbuf ); - return false; - } - qDebug( "OPacketCapturer::open(): dump [%s] opened successfully.", (const char*) filename ); - _pcd = dump; - - return true; -} - - -bool OPacketCapturer::open( const QFile& file ) -{ - QString name = file.name(); - - if ( _open ) - { - close(); - if ( name == _name ) // ignore opening an already openend device - { - return true; - } - else // close the last opened device - { - close(); - } - } - - _name = name; - - pcap_t* handle = pcap_open_offline( const_cast( (const char*) name ), &_errbuf[0] ); - - if ( handle ) - { - qDebug( "OPacketCapturer::open(): libpcap opened successfully." ); - _pch = handle; - _open = true; - - // in case we have an application object, create a socket notifier - if ( qApp ) - { - _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read ); - connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); - } - - return true; - } - else - { - qDebug( "OPacketCapturer::open(): can't open libpcap with '%s': %s", (const char*) name, _errbuf ); - return false; - } - -} - - -bool OPacketCapturer::isOpen() const -{ - return _open; -} - - -void OPacketCapturer::readyToReceive() -{ - qDebug( "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(p)'" ); - OPacket* p = next(); - emit receivedPacket( p ); - // emit is synchronous - packet has been dealt with, now it's safe to delete - delete p; -} - - -const QMap& OPacketCapturer::statistics() const -{ - return _stats; -} - - -int OPacketCapturer::snapShot() const -{ - return pcap_snapshot( _pch ); -} - - -bool OPacketCapturer::swapped() const -{ - return pcap_is_swapped( _pch ); -} - - -QString OPacketCapturer::version() const -{ - return QString().sprintf( "%s.%s", pcap_major_version( _pch ), pcap_minor_version( _pch ) ); -} - - +/* +                 This file is part of the Opie Project +              Copyright (C) 2003 by Michael 'Mickey' Lauer + =. + .=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; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: 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 +#include + +/* QT */ +#include // don't use oapplication here (will decrease reusability in other projects) +#include +#include + +/* SYSTEM */ +#include +#include +#include + +/* LOCAL */ +#include "udp_ports.h" + +/*====================================================================================== + * OPacket + *======================================================================================*/ + +OPacket::OPacket( int datalink, packetheaderstruct header, const unsigned char* data, QObject* parent ) + :QObject( parent, "Generic" ), _hdr( header ), _data( data ) +{ + //qDebug( "OPacket::OPacket(): (Len %d, CapLen %d)" /*, ctime((const time_t*) header.ts.tv_sec)*/, header.len, header.caplen ); + + _end = (unsigned char*) data + header.len; + //qDebug( "OPacket::data @ %0x, end @ %0x", data, _end ); + + switch ( datalink ) + { + case DLT_EN10MB: + odebug << "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" << oendl; + new OEthernetPacket( _end, (const struct ether_header*) data, this ); + break; + + case DLT_IEEE802_11: + odebug << "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" << oendl; + new OWaveLanPacket( _end, (const struct ieee_802_11_header*) data, this ); + break; + + case DLT_PRISM_HEADER: + odebug << "OPacket::OPacket(): Received Packet. Datalink = PRISM_HEADER" << oendl; + new OPrismHeaderPacket( _end, (const struct prism_hdr*) (unsigned char*) data, this ); + break; + + default: + owarn << "OPacket::OPacket(): Received Packet over unsupported datalink, type " << datalink << "!" << oendl; + } +} + + +OPacket::~OPacket() +{ +} + + +timevalstruct OPacket::timeval() const +{ + return _hdr.ts; +} + + +int OPacket::caplen() const +{ + return _hdr.caplen; +} + + +void OPacket::updateStats( QMap& stats, QObjectList* l ) +{ + if (!l) return; + QObject* o = l->first(); + while ( o ) + { + stats[o->name()]++; + updateStats( stats, const_cast( o->children() ) ); + o = l->next(); + } +} + + +void OPacket::dumpStructure( QObjectList* l ) +{ + QString packetString( "[ |" + _dumpStructure( l ) + " ]" ); + odebug << "OPacket::dumpStructure: " << packetString << oendl; +} + + +QString OPacket::_dumpStructure( QObjectList* l ) +{ + if (!l) return QString::null; + QObject* o = l->first(); + QString str(" "); + + while ( o ) + { + str.append( o->name() ); + str.append( " |" ); + str += _dumpStructure( const_cast( o->children() ) ); + o = l->next(); + } + return str; +} + +QString OPacket::dump( int bpl ) const +{ + static int index = 0; + index++; + int len = _hdr.caplen; + QString str; + str.sprintf( "\n<----- Packet #%04d Len = 0x%X (%d) ----->\n\n", index, len, len ); + str.append( "0000: " ); + QString tmp; + QString bytes; + QString chars; + + for ( int i = 0; i < len; ++i ) + { + tmp.sprintf( "%02X ", _data[i] ); bytes.append( tmp ); + if ( (_data[i] > 31) && (_data[i]<128) ) chars.append( _data[i] ); + else chars.append( '.' ); + + if ( !((i+1) % bpl) ) + { + str.append( bytes ); + str.append( ' ' ); + str.append( chars ); + str.append( '\n' ); + tmp.sprintf( "%04X: ", i+1 ); str.append( tmp ); + bytes = ""; + chars = ""; + } + + } + if ( (len % bpl) ) + { + str.append( bytes.leftJustify( 1 + 3*bpl ) ); + str.append( chars ); + } + str.append( '\n' ); + return str; +} + + +int OPacket::len() const +{ + return _hdr.len; +} + + +/*====================================================================================== + * OEthernetPacket + *======================================================================================*/ + +OEthernetPacket::OEthernetPacket( const unsigned char* end, const struct ether_header* data, QObject* parent ) + :QObject( parent, "Ethernet" ), _ether( data ) +{ + + odebug << "Source = " << sourceAddress().toString(); + odebug << "Destination = " << destinationAddress().toString(); + + if ( sourceAddress() == OMacAddress::broadcast ) + odebug << "Source is broadcast address" << oendl; + if ( destinationAddress() == OMacAddress::broadcast ) + odebug << "Destination is broadcast address" << oendl; + + switch ( type() ) + { + case ETHERTYPE_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; + case ETHERTYPE_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break; + case ETHERTYPE_REVARP: { odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" << oendl; break; } + default: odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" << oendl; + } + +} + + +OEthernetPacket::~OEthernetPacket() +{ +} + + +OMacAddress OEthernetPacket::sourceAddress() const +{ + return OMacAddress( _ether->ether_shost ); +} + + +OMacAddress OEthernetPacket::destinationAddress() const +{ + return OMacAddress( _ether->ether_dhost ); +} + +int OEthernetPacket::type() const +{ + return ntohs( _ether->ether_type ); +} + + +/*====================================================================================== + * OIPPacket + *======================================================================================*/ + + +OIPPacket::OIPPacket( const unsigned char* end, const struct iphdr* data, QObject* parent ) + :QObject( parent, "IP" ), _iphdr( data ) +{ + odebug << "OIPPacket::OIPPacket(): decoding IP header..." << oendl; + + odebug << "FromAddress = " << fromIPAddress().toString(); + odebug << " toAddress = " << toIPAddress().toString(); + + switch ( protocol() ) + { + case IPPROTO_UDP: new OUDPPacket( end, (const struct udphdr*) (data+1), this ); break; + case IPPROTO_TCP: new OTCPPacket( end, (const struct tcphdr*) (data+1), this ); break; + default: odebug << "OIPPacket::OIPPacket(): unknown IP protocol, type = " << protocol() << oendl; + } + +} + +OIPPacket::~OIPPacket() +{ +} + + +QHostAddress OIPPacket::fromIPAddress() const +{ + return EXTRACT_32BITS( &_iphdr->saddr ); +} + + +QHostAddress OIPPacket::toIPAddress() const +{ + return EXTRACT_32BITS( &_iphdr->saddr ); +} + + +int OIPPacket::tos() const +{ + return _iphdr->tos; +} + + +int OIPPacket::len() const +{ + return EXTRACT_16BITS( &_iphdr->tot_len ); +} + + +int OIPPacket::id() const +{ + return EXTRACT_16BITS( &_iphdr->id ); +} + + +int OIPPacket::offset() const +{ + return EXTRACT_16BITS( &_iphdr->frag_off ); +} + + +int OIPPacket::ttl() const +{ + return _iphdr->ttl; +} + + +int OIPPacket::protocol() const +{ + return _iphdr->protocol; +} + + +int OIPPacket::checksum() const +{ + return EXTRACT_16BITS( &_iphdr->check ); +} + +/*====================================================================================== + * OARPPacket + *======================================================================================*/ + + +OARPPacket::OARPPacket( const unsigned char* end, const struct myarphdr* data, QObject* parent ) + :QObject( parent, "ARP" ), _arphdr( data ) +{ + odebug << "OARPPacket::OARPPacket(): decoding ARP header..." << oendl; + odebug << "ARP type seems to be " << EXTRACT_16BITS( &_arphdr->ar_op ) << " = " << type() << oendl; + odebug << "Sender: MAC " << senderMacAddress().toString() << " = IP " << senderIPV4Address().toString() << oendl; + odebug << "Target: MAC " << targetMacAddress().toString() << " = IP " << targetIPV4Address().toString() << oendl; +} + + +OARPPacket::~OARPPacket() +{ +} + + +QString OARPPacket::type() const +{ + switch ( EXTRACT_16BITS( &_arphdr->ar_op ) ) + { + case 1: return "REQUEST"; + case 2: return "REPLY"; + case 3: return "RREQUEST"; + case 4: return "RREPLY"; + case 8: return "InREQUEST"; + case 9: return "InREPLY"; + case 10: return "NAK"; + default: qWarning( "OARPPacket::type(): invalid ARP type!" ); return ""; + } +} + + +QHostAddress OARPPacket::senderIPV4Address() const +{ + return EXTRACT_32BITS( &_arphdr->ar_sip ); +} + + +QHostAddress OARPPacket::targetIPV4Address() const +{ + return EXTRACT_32BITS( &_arphdr->ar_tip ); +} + + +OMacAddress OARPPacket::senderMacAddress() const +{ + return OMacAddress( _arphdr->ar_sha ); +} + + +OMacAddress OARPPacket::targetMacAddress() const +{ + return OMacAddress( _arphdr->ar_tha ); +} + + +/*====================================================================================== + * OUDPPacket + *======================================================================================*/ + + +OUDPPacket::OUDPPacket( const unsigned char* end, const struct udphdr* data, QObject* parent ) + :QObject( parent, "UDP" ), _udphdr( data ) + +{ + odebug << "OUDPPacket::OUDPPacket(): decoding UDP header..." << oendl; + odebug << "fromPort = " << fromPort() << oendl; + odebug << " toPort = " << toPort() << oendl; + + // TODO: Make this a case or a hash if we know more udp protocols + + if ( fromPort() == UDP_PORT_BOOTPS || fromPort() == UDP_PORT_BOOTPC || + toPort() == UDP_PORT_BOOTPS || toPort() == UDP_PORT_BOOTPC ) + { + odebug << "seems to be part of a DHCP conversation => creating DHCP packet." << oendl; + new ODHCPPacket( end, (const struct dhcp_packet*) (data+1), this ); + } +} + + +OUDPPacket::~OUDPPacket() +{ +} + + +int OUDPPacket::fromPort() const +{ + return EXTRACT_16BITS( &_udphdr->source ); +} + + +int OUDPPacket::toPort() const +{ + return EXTRACT_16BITS( &_udphdr->dest ); +} + + +int OUDPPacket::length() const +{ + return EXTRACT_16BITS( &_udphdr->len ); +} + + +int OUDPPacket::checksum() const +{ + return EXTRACT_16BITS( &_udphdr->check ); +} + + +/*====================================================================================== + * ODHCPPacket + *======================================================================================*/ + + +ODHCPPacket::ODHCPPacket( const unsigned char* end, const struct dhcp_packet* data, QObject* parent ) + :QObject( parent, "DHCP" ), _dhcphdr( data ) + +{ + odebug << "ODHCPPacket::ODHCPPacket(): decoding DHCP information..." << oendl; + odebug << "DHCP opcode seems to be " << _dhcphdr->op << ": " << ( isRequest() ? "REQUEST" : "REPLY" ) << oendl; + odebug << "clientAddress = " << clientAddress().toString() << oendl; + odebug << " yourAddress = " << yourAddress().toString() << oendl; + odebug << "serverAddress = " << serverAddress().toString() << oendl; + odebug << " relayAddress = " << relayAddress().toString() << oendl; + odebug << "parsing DHCP options..." << oendl; + + _type = 0; + + const unsigned char* option = &_dhcphdr->options[4]; + char tag = -1; + char len = -1; + + while ( ( tag = *option++ ) != -1 /* end of option field */ ) + { + len = *option++; + odebug << "recognized DHCP option #" << tag << ", length " << len << oendl; + + if ( tag == DHO_DHCP_MESSAGE_TYPE ) + _type = *option; + + option += len; + if ( option >= end ) + { + owarn << "DHCP parsing ERROR: sanity check says the packet is at its end!" << oendl; + break; + } + } + + odebug << "DHCP type seems to be << " << type() << oendl; +} + + +ODHCPPacket::~ODHCPPacket() +{ +} + + +bool ODHCPPacket::isRequest() const +{ + return ( _dhcphdr->op == 01 ); +} + + +bool ODHCPPacket::isReply() const +{ + return ( _dhcphdr->op == 02 ); +} + + +QString ODHCPPacket::type() const +{ + switch ( _type ) + { + case 1: return "DISCOVER"; + case 2: return "OFFER"; + case 3: return "REQUEST"; + case 4: return "DECLINE"; + case 5: return "ACK"; + case 6: return "NAK"; + case 7: return "RELEASE"; + case 8: return "INFORM"; + default: qWarning( "ODHCPPacket::type(): invalid DHCP type (%d) !", _dhcphdr->op ); return ""; + } +} + + +QHostAddress ODHCPPacket::clientAddress() const +{ + return EXTRACT_32BITS( &_dhcphdr->ciaddr ); +} + + +QHostAddress ODHCPPacket::yourAddress() const +{ + return EXTRACT_32BITS( &_dhcphdr->yiaddr ); +} + + +QHostAddress ODHCPPacket::serverAddress() const +{ + return EXTRACT_32BITS( &_dhcphdr->siaddr ); +} + + +QHostAddress ODHCPPacket::relayAddress() const +{ + return EXTRACT_32BITS( &_dhcphdr->giaddr ); +} + + +OMacAddress ODHCPPacket::clientMacAddress() const +{ + return OMacAddress( _dhcphdr->chaddr ); +} + + +/*====================================================================================== + * OTCPPacket + *======================================================================================*/ + + +OTCPPacket::OTCPPacket( const unsigned char* end, const struct tcphdr* data, QObject* parent ) + :QObject( parent, "TCP" ), _tcphdr( data ) + +{ + odebug << "OTCPPacket::OTCPPacket(): decoding TCP header..." << oendl; +} + + +OTCPPacket::~OTCPPacket() +{ +} + + +int OTCPPacket::fromPort() const +{ + return EXTRACT_16BITS( &_tcphdr->source ); +} + + +int OTCPPacket::toPort() const +{ + return EXTRACT_16BITS( &_tcphdr->dest ); +} + + +int OTCPPacket::seq() const +{ + return EXTRACT_16BITS( &_tcphdr->seq ); +} + + +int OTCPPacket::ack() const +{ + return EXTRACT_16BITS( &_tcphdr->ack_seq ); +} + + +int OTCPPacket::window() const +{ + return EXTRACT_16BITS( &_tcphdr->window ); +} + + +int OTCPPacket::checksum() const +{ + return EXTRACT_16BITS( &_tcphdr->check ); +} + +/*====================================================================================== + * OPrismHeaderPacket + *======================================================================================*/ + + +OPrismHeaderPacket::OPrismHeaderPacket( const unsigned char* end, const struct prism_hdr* data, QObject* parent ) + :QObject( parent, "Prism" ), _header( data ) + +{ + odebug << "OPrismHeaderPacket::OPrismHeaderPacket(): decoding PRISM header..." << oendl; + + odebug << "Signal Strength = " << data->signal.data << oendl; + + new OWaveLanPacket( end, (const struct ieee_802_11_header*) (data+1), this ); +} + +OPrismHeaderPacket::~OPrismHeaderPacket() +{ +} + + +unsigned int OPrismHeaderPacket::signalStrength() const +{ + return _header->signal.data; +} + +/*====================================================================================== + * OWaveLanPacket + *======================================================================================*/ + + +OWaveLanPacket::OWaveLanPacket( const unsigned char* end, const struct ieee_802_11_header* data, QObject* parent ) + :QObject( parent, "802.11" ), _wlanhdr( data ) + +{ + odebug << "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." << oendl; + odebug << "type = " << type() << oendl; + odebug << "subType = " << subType() << oendl; + odebug << "duration = " << duration() << oendl; + odebug << "powermanagement = " << usesPowerManagement() << oendl; + odebug << "payload is encrypted = " << ( usesWep() ? "yes" : "no" ) << oendl; + odebug << "MAC1 = " << macAddress1().toString() << oendl; + odebug << "MAC2 = " << macAddress2().toString() << oendl; + odebug << "MAC3 = " << macAddress3().toString() << oendl; + odebug << "MAC4 = " << macAddress4().toString() << oendl; + + switch ( type() ) + { + case T_MGMT: new OWaveLanManagementPacket( end, (const struct ieee_802_11_mgmt_header*) data, this ); break; + case T_DATA: new OWaveLanDataPacket( end, (const struct ieee_802_11_data_header*) data, this ); break; + case T_CTRL: new OWaveLanControlPacket( end, (const struct ieee_802_11_control_header*) data, this ); break; + default: odebug << "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown major type = " << type() << oendl; + } +} + +OWaveLanPacket::~OWaveLanPacket() +{ +} + + +int OWaveLanPacket::duration() const +{ + return _wlanhdr->duration; +} + + +OMacAddress OWaveLanPacket::macAddress1() const +{ + return OMacAddress( _wlanhdr->mac1 ); +} + + +OMacAddress OWaveLanPacket::macAddress2() const +{ + return OMacAddress( _wlanhdr->mac2 ); +} + + +OMacAddress OWaveLanPacket::macAddress3() const +{ + return OMacAddress( _wlanhdr->mac3 ); +} + + +OMacAddress OWaveLanPacket::macAddress4() const +{ + return OMacAddress( _wlanhdr->mac4 ); +} + + +int OWaveLanPacket::subType() const +{ + return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +int OWaveLanPacket::type() const +{ + return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +int OWaveLanPacket::version() const +{ + return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +bool OWaveLanPacket::fromDS() const +{ + return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +bool OWaveLanPacket::toDS() const +{ + return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +bool OWaveLanPacket::usesPowerManagement() const +{ + return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +bool OWaveLanPacket::usesWep() const +{ + return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); +} + + +/*====================================================================================== + * OWaveLanManagementPacket + *======================================================================================*/ + +OWaveLanManagementPacket::OWaveLanManagementPacket( const unsigned char* end, const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent ) + :QObject( parent, "802.11 Management" ), _header( data ), + _body( (const struct ieee_802_11_mgmt_body*) (data+1) ) +{ + odebug << "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." << oendl; + odebug << "Detected subtype is " << managementType() << oendl; + + // grab tagged values + const unsigned char* ptr = (const unsigned char*) (_body+1); + while (ptr < end) + { + switch ( *ptr ) + { + case E_SSID: new OWaveLanManagementSSID( end, (struct ssid_t*) ptr, this ); break; + case E_FH: new OWaveLanManagementFH( end, (struct fh_t*) ptr, this ); break; + case E_DS: new OWaveLanManagementDS( end, (struct ds_t*) ptr, this ); break; + case E_RATES: new OWaveLanManagementRates( end, (struct rates_t*) ptr, this ); break; + case E_CF: new OWaveLanManagementCF( end, (struct cf_t*) ptr, this ); break; + case E_TIM: new OWaveLanManagementTim( end, (struct tim_t*) ptr, this ); break; + case E_IBSS: new OWaveLanManagementIBSS( end, (struct ibss_t*) ptr, this ); break; + case E_CHALLENGE: new OWaveLanManagementChallenge( end, (struct challenge_t*) ptr, this ); break; + } + ptr+= ( ( struct ssid_t* ) ptr )->length; // skip length of tagged value + ptr+= 2; // skip tag ID and length + } +} + + +OWaveLanManagementPacket::~OWaveLanManagementPacket() +{ +} + + +QString OWaveLanManagementPacket::managementType() const +{ + switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ) + { + case ST_ASSOC_REQUEST: return "AssociationRequest"; break; + case ST_ASSOC_RESPONSE: return "AssociationResponse"; break; + case ST_REASSOC_REQUEST: return "ReassociationRequest"; break; + case ST_REASSOC_RESPONSE: return "ReassociationResponse"; break; + case ST_PROBE_REQUEST: return "ProbeRequest"; break; + case ST_PROBE_RESPONSE: return "ProbeResponse"; break; + case ST_BEACON: return "Beacon"; break; + case ST_ATIM: return "Atim"; break; + case ST_DISASSOC: return "Disassociation"; break; + case ST_AUTH: return "Authentication"; break; + case ST_DEAUTH: return "Deathentication"; break; + default: + qWarning( "OWaveLanManagementPacket::managementType(): unhandled subtype %d", FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ); + return "Unknown"; + } +} + + +int OWaveLanManagementPacket::beaconInterval() const +{ + return EXTRACT_LE_16BITS( &_body->beacon_interval ); +} + + +int OWaveLanManagementPacket::capabilities() const +{ + return EXTRACT_LE_16BITS( &_body->capability_info ); +} + + +bool OWaveLanManagementPacket::canESS() const +{ + return CAPABILITY_ESS( EXTRACT_LE_16BITS( &_body->capability_info ) ); +} + + +bool OWaveLanManagementPacket::canIBSS() const +{ + return CAPABILITY_IBSS( EXTRACT_LE_16BITS( &_body->capability_info ) ); +} + + +bool OWaveLanManagementPacket::canCFP() const +{ + return CAPABILITY_CFP( EXTRACT_LE_16BITS( &_body->capability_info ) ); +} + + +bool OWaveLanManagementPacket::canCFP_REQ() const +{ + return CAPABILITY_CFP_REQ( EXTRACT_LE_16BITS( &_body->capability_info ) ); +} + + +bool OWaveLanManagementPacket::canPrivacy() const +{ + return CAPABILITY_PRIVACY( EXTRACT_LE_16BITS( &_body->capability_info ) ); +} + + +/*====================================================================================== + * OWaveLanManagementSSID + *======================================================================================*/ + +OWaveLanManagementSSID::OWaveLanManagementSSID( const unsigned char* end, const struct ssid_t* data, QObject* parent ) + :QObject( parent, "802.11 SSID" ), _data( data ) +{ + odebug << "OWaveLanManagementSSID()" << oendl; +} + + +OWaveLanManagementSSID::~OWaveLanManagementSSID() +{ +} + + +QString OWaveLanManagementSSID::ID() const +{ + int length = _data->length; + if ( length > 32 ) length = 32; + char essid[length+1]; + memcpy( &essid, &_data->ssid, length ); + essid[length] = 0x0; + return essid; +} + + +/*====================================================================================== + * OWaveLanManagementRates + *======================================================================================*/ + +OWaveLanManagementRates::OWaveLanManagementRates( const unsigned char* end, const struct rates_t* data, QObject* parent ) + :QObject( parent, "802.11 Rates" ), _data( data ) +{ + odebug << "OWaveLanManagementRates()" << oendl; +} + + +OWaveLanManagementRates::~OWaveLanManagementRates() +{ +} + +/*====================================================================================== + * OWaveLanManagementCF + *======================================================================================*/ + +OWaveLanManagementCF::OWaveLanManagementCF( const unsigned char* end, const struct cf_t* data, QObject* parent ) + :QObject( parent, "802.11 CF" ), _data( data ) +{ + odebug << "OWaveLanManagementCF()" << oendl; +} + + +OWaveLanManagementCF::~OWaveLanManagementCF() +{ +} + +/*====================================================================================== + * OWaveLanManagementFH + *======================================================================================*/ + +OWaveLanManagementFH::OWaveLanManagementFH( const unsigned char* end, const struct fh_t* data, QObject* parent ) + :QObject( parent, "802.11 FH" ), _data( data ) +{ + odebug << "OWaveLanManagementFH()" << oendl; +} + + +OWaveLanManagementFH::~OWaveLanManagementFH() +{ +} + +/*====================================================================================== + * OWaveLanManagementDS + *======================================================================================*/ + +OWaveLanManagementDS::OWaveLanManagementDS( const unsigned char* end, const struct ds_t* data, QObject* parent ) + :QObject( parent, "802.11 DS" ), _data( data ) +{ + odebug << "OWaveLanManagementDS()" << oendl; +} + + +OWaveLanManagementDS::~OWaveLanManagementDS() +{ +} + + +int OWaveLanManagementDS::channel() const +{ + return _data->channel; +} + +/*====================================================================================== + * OWaveLanManagementTim + *======================================================================================*/ + +OWaveLanManagementTim::OWaveLanManagementTim( const unsigned char* end, const struct tim_t* data, QObject* parent ) + :QObject( parent, "802.11 Tim" ), _data( data ) +{ + odebug << "OWaveLanManagementTim()" << oendl; +} + + +OWaveLanManagementTim::~OWaveLanManagementTim() +{ +} + +/*====================================================================================== + * OWaveLanManagementIBSS + *======================================================================================*/ + +OWaveLanManagementIBSS::OWaveLanManagementIBSS( const unsigned char* end, const struct ibss_t* data, QObject* parent ) + :QObject( parent, "802.11 IBSS" ), _data( data ) +{ + odebug << "OWaveLanManagementIBSS()" << oendl; +} + + +OWaveLanManagementIBSS::~OWaveLanManagementIBSS() +{ +} + +/*====================================================================================== + * OWaveLanManagementChallenge + *======================================================================================*/ + +OWaveLanManagementChallenge::OWaveLanManagementChallenge( const unsigned char* end, const struct challenge_t* data, QObject* parent ) + :QObject( parent, "802.11 Challenge" ), _data( data ) +{ + odebug << "OWaveLanManagementChallenge()" << oendl; +} + + +OWaveLanManagementChallenge::~OWaveLanManagementChallenge() +{ +} + +/*====================================================================================== + * OWaveLanDataPacket + *======================================================================================*/ + +OWaveLanDataPacket::OWaveLanDataPacket( const unsigned char* end, const struct ieee_802_11_data_header* data, OWaveLanPacket* parent ) + :QObject( parent, "802.11 Data" ), _header( data ) +{ + odebug << "OWaveLanDataPacket::OWaveLanDataPacket(): decoding frame..." << oendl; + + const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header ); + + #warning The next line works for most cases, but can not be correct generally! + if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address + + new OLLCPacket( end, (const struct ieee_802_11_802_2_header*) payload, this ); +} + + +OWaveLanDataPacket::~OWaveLanDataPacket() +{ +} + + +/*====================================================================================== + * OLLCPacket + *======================================================================================*/ + +OLLCPacket::OLLCPacket( const unsigned char* end, const struct ieee_802_11_802_2_header* data, QObject* parent ) + :QObject( parent, "802.11 LLC" ), _header( data ) +{ + odebug << "OLLCPacket::OLLCPacket(): decoding frame..." << oendl; + + if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) ) + { + owarn << "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type = " << EXTRACT_16BITS( &_header->type ) << ")" << oendl; + + switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h + { + case ETH_P_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; + case ETH_P_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break; + default: owarn << "OLLCPacket::OLLCPacket(): Unknown Encapsulation type = " << EXTRACT_16BITS( &_header->type ) << oendl; + } + } +} + + +OLLCPacket::~OLLCPacket() +{ +} + + +/*====================================================================================== + * OWaveLanControlPacket + *======================================================================================*/ + +OWaveLanControlPacket::OWaveLanControlPacket( const unsigned char* end, const struct ieee_802_11_control_header* data, OWaveLanPacket* parent ) + :QObject( parent, "802.11 Control" ), _header( data ) +{ + odebug << "OWaveLanControlPacket::OWaveLanDataControl(): decoding frame..." << oendl; + //TODO: Implement this +} + + +OWaveLanControlPacket::~OWaveLanControlPacket() +{ +} + + +/*====================================================================================== + * OPacketCapturer + *======================================================================================*/ + +OPacketCapturer::OPacketCapturer( QObject* parent, const char* name ) + :QObject( parent, name ), _name( QString::null ), _open( false ), + _pch( 0 ), _pcd( 0 ), _sn( 0 ) +{ +} + + +OPacketCapturer::~OPacketCapturer() +{ + if ( _open ) + { + odebug << "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." << oendl; + close(); + } +} + + +void OPacketCapturer::setBlocking( bool b ) +{ + if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 ) + { + odebug << "OPacketCapturer::setBlocking(): blocking mode changed successfully." << oendl; + } + else + { + odebug << "OPacketCapturer::setBlocking(): can't change blocking mode: " << _errbuf << oendl; + } +} + + +bool OPacketCapturer::blocking() const +{ + int b = pcap_getnonblock( _pch, _errbuf ); + if ( b == -1 ) + { + odebug << "OPacketCapturer::blocking(): can't get blocking mode: " << _errbuf << oendl; + return -1; + } + return !b; +} + + +void OPacketCapturer::closeDumpFile() +{ + if ( _pcd ) + { + pcap_dump_close( _pcd ); + _pcd = 0; + } + pcap_close( _pch ); +} + + +void OPacketCapturer::close() +{ + if ( _open ) + { + if ( _sn ) + { + _sn->disconnect( SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); + delete _sn; + } + closeDumpFile(); + _open = false; + } + + odebug << "OPacketCapturer::close() --- dumping capturing statistics..." << oendl; + odebug << "--------------------------------------------------" << oendl; + for( QMap::Iterator it = _stats.begin(); it != _stats.end(); ++it ) + odebug << it.key() << " = " << it.data() << oendl; + odebug << "--------------------------------------------------" << oendl; + +} + + +int OPacketCapturer::dataLink() const +{ + return pcap_datalink( _pch ); +} + + +void OPacketCapturer::dump( OPacket* p ) +{ + if ( !_pcd ) + { + qWarning( "OPacketCapturer::dump() - cannot dump without open capture file!" ); + return; + } + pcap_dump( (u_char*) _pcd, &p->_hdr, p->_data ); +} + + +int OPacketCapturer::fileno() const +{ + if ( _open ) + { + return pcap_fileno( _pch ); + } + else + { + return -1; + } +} + + +OPacket* OPacketCapturer::next( int time ) +{ + fd_set fds; + struct timeval tv; + FD_ZERO( &fds ); + FD_SET( pcap_fileno( _pch ), &fds ); + tv.tv_sec = time / 1000; + tv.tv_usec = time % 1000; + int retval = select( pcap_fileno( _pch )+1, &fds, NULL, NULL, &tv); + if ( retval > 0 ) // clear to read! + return next(); + else + return 0; +} + + +OPacket* OPacketCapturer::next() +{ + packetheaderstruct header; + odebug << "==> OPacketCapturer::next()" << oendl; + const unsigned char* pdata = pcap_next( _pch, &header ); + odebug << "<== OPacketCapturer::next()" << oendl; + + if ( pdata && header.len ) + { + OPacket* p = new OPacket( dataLink(), header, pdata, 0 ); + // packets shouldn't be inserted in the QObject child-parent hierarchy, + // because due to memory constraints they will be deleted as soon + // as possible - that is right after they have been processed + // by emit() [ see below ] + //TODO: make gathering statistics optional, because it takes time + p->updateStats( _stats, const_cast( p->children() ) ); + #ifndef NODEBUG + p->dumpStructure( const_cast( p->children() ) ); + #endif + return p; + } + else + { + qWarning( "OPacketCapturer::next() - no packet received!" ); + return 0; + } +} + + +bool OPacketCapturer::open( const QString& name ) +{ + if ( _open ) + { + if ( name == _name ) // ignore opening an already openend device + { + return true; + } + else // close the last opened device + { + close(); + } + } + + _name = name; + + // open libpcap + pcap_t* handle = pcap_open_live( const_cast( (const char*) name ), 1024, 0, 0, &_errbuf[0] ); + + if ( !handle ) + { + owarn << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl; + return false; + } + + odebug << "OPacketCapturer::open(): libpcap [" << name << "] opened successfully." << oendl; + _pch = handle; + _open = true; + _stats.clear(); + + // in case we have an application object, create a socket notifier + if ( qApp ) //TODO: I don't like this here... + { + _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read ); + connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); + } + + return true; +} + + +bool OPacketCapturer::openDumpFile( const QString& filename ) +{ + pcap_dumper_t* dump = pcap_dump_open( _pch, const_cast( (const char*) filename ) ); + if ( !dump ) + { + owarn << "OPacketCapturer::open(): can't open dump with '" << filename << "': " << _errbuf << oendl; + return false; + } + odebug << "OPacketCapturer::open(): dump [" << filename << "] opened successfully." << oendl; + _pcd = dump; + + return true; +} + + +bool OPacketCapturer::open( const QFile& file ) +{ + QString name = file.name(); + + if ( _open ) + { + close(); + if ( name == _name ) // ignore opening an already openend device + { + return true; + } + else // close the last opened device + { + close(); + } + } + + _name = name; + + pcap_t* handle = pcap_open_offline( const_cast( (const char*) name ), &_errbuf[0] ); + + if ( handle ) + { + odebug << "OPacketCapturer::open(): libpcap opened successfully." << oendl; + _pch = handle; + _open = true; + + // in case we have an application object, create a socket notifier + if ( qApp ) + { + _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read ); + connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); + } + + return true; + } + else + { + odebug << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl; + return false; + } + +} + + +bool OPacketCapturer::isOpen() const +{ + return _open; +} + + +void OPacketCapturer::readyToReceive() +{ + odebug << "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(p)'" << oendl; + OPacket* p = next(); + emit receivedPacket( p ); + // emit is synchronous - packet has been dealt with, now it's safe to delete + delete p; +} + + +const QMap& OPacketCapturer::statistics() const +{ + return _stats; +} + + +int OPacketCapturer::snapShot() const +{ + return pcap_snapshot( _pch ); +} + + +bool OPacketCapturer::swapped() const +{ + return pcap_is_swapped( _pch ); +} + + +QString OPacketCapturer::version() const +{ + return QString().sprintf( "%s.%s", pcap_major_version( _pch ), pcap_minor_version( _pch ) ); +} + + diff --git a/libopie2/opienet/ostation.cpp b/libopie2/opienet/ostation.cpp index c363f0c..8c989d8 100644 --- a/libopie2/opienet/ostation.cpp +++ b/libopie2/opienet/ostation.cpp @@ -29,6 +29,7 @@ */ #include +#include /*====================================================================================== * OStation @@ -36,7 +37,7 @@ OStation::OStation() { - qDebug( "OStation::OStation()" ); + odebug << "OStation::OStation()" << oendl; type = ""; macAddress = OMacAddress::unknown; @@ -49,13 +50,13 @@ OStation::OStation() OStation::~OStation() { - qDebug( "OStation::~OStation()" ); + odebug << "OStation::~OStation()" << oendl; } void OStation::dump() { - qDebug( "------- OStation::dump() ------------" ); + odebug << "------- OStation::dump() ------------" << oendl; qDebug( "type: %s", (const char*) type ); qDebug( "mac: %s", (const char*) macAddress.toString() ); qDebug( "ap: %s", (const char*) apAddress.toString() ); -- cgit v0.9.0.2