summaryrefslogtreecommitdiff
path: root/libopie2/opienet
authormickeyl <mickeyl>2003-12-20 00:43:12 (UTC)
committer mickeyl <mickeyl>2003-12-20 00:43:12 (UTC)
commit11c6b3b8ba56b28b160965387b4ffeffe2a2f143 (patch) (side-by-side diff)
tree4da82e0b0f7120ec493644af44ac84e801cc4b9b /libopie2/opienet
parent56762e511d9709c7141a504e609f7b850a5304f7 (diff)
downloadopie-11c6b3b8ba56b28b160965387b4ffeffe2a2f143.zip
opie-11c6b3b8ba56b28b160965387b4ffeffe2a2f143.tar.gz
opie-11c6b3b8ba56b28b160965387b4ffeffe2a2f143.tar.bz2
libopienet2 now uses the fancy odebug classes, no longer qdebug
Diffstat (limited to 'libopie2/opienet') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opienet/onetwork.cpp2384
-rw-r--r--libopie2/opienet/opcap.cpp2637
-rw-r--r--libopie2/opienet/ostation.cpp7
3 files changed, 2517 insertions, 2511 deletions
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 <mickey@Vanille.de>
- =.
- .=l.
-           .>+-=
- _;:,     .>    :=|. This program is free software; you can
-.> <`_,   >  .   <= redistribute it and/or modify it under
-:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
-.="- .-=="i,     .._ License as published by the Free Software
- - .   .-<_>     .<> Foundation; either version 2 of the License,
-     ._= =}       : or (at your option) any later version.
-    .%`+i>       _;_.
-    .i_,=:_.      -<s. This program is distributed in the hope that
-     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
-    : ..    .:,     . . . without even the implied warranty of
-    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
-  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
-..}^=.=       =       ; Library General Public License for more
-++=   -.     .`     .: details.
- :     =  ...= . :.=-
- -.   .:....=;==+<; You should have received a copy of the GNU
-  -_. . .   )=.  = Library General Public License along with
-    --        :-=` this library; see the file COPYING.LIB.
- If not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
-*/
-
-/* OPIE */
-
-#include <opie2/onetwork.h>
-#include <opie2/ostation.h>
-
-/* QT */
-
-#include <qfile.h>
-#include <qtextstream.h>
-
-/* UNIX */
-
-#include <assert.h>
-#include <arpa/inet.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <linux/sockios.h>
-#include <net/if_arp.h>
-#include <stdarg.h>
-
-#ifndef NODEBUG
-#include <opie2/odebugmapper.h>
-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 "<unknown>";
-
-}
-
-
-void ONetworkInterface::setMacAddress( const OMacAddress& addr )
-{
- _ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
- memcpy( &_ifr.ifr_hwaddr.sa_data, addr.native(), 6 );
- ioctl( SIOCSIFHWADDR );
-}
-
-
-OMacAddress ONetworkInterface::macAddress() const
-{
- if ( ioctl( SIOCGIFHWADDR ) )
- {
- return OMacAddress( _ifr );
- }
- else
- {
- return OMacAddress::unknown;
- }
-}
-
-
-void ONetworkInterface::setIPV4Netmask( const QHostAddress& addr )
-{
- struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr;
- sa->sin_family = AF_INET;
- sa->sin_port = 0;
- sa->sin_addr.s_addr = htonl( addr.ip4Addr() );
- ioctl( SIOCSIFNETMASK );
-}
-
-
-QString ONetworkInterface::ipV4Netmask() const
-{
- if ( ioctl( SIOCGIFNETMASK ) )
- {
- struct sockaddr_in* sa = (struct sockaddr_in *) &_ifr.ifr_addr;
- //FIXME: Use QHostAddress here
- return QString( inet_ntoa( sa->sin_addr ) );
- }
- else
- return "<unknown>";
-}
-
-
-int ONetworkInterface::dataLinkType() const
-{
- if ( ioctl( SIOCGIFHWADDR ) )
- {
- return _ifr.ifr_hwaddr.sa_family;
- }
- else
- {
- return -1;
- }
-}
-
-
-void ONetworkInterface::setMonitoring( OMonitoringInterface* m )
-{
- _mon = m;
- 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
- {
- // <check if the driver overwrites stuff>
- int max = 0;
- for ( int r = sizeof( struct iw_range ); r < len; r++ )
- if (buffer[r] != 0)
- max = r;
- if (max > 0)
- {
- qWarning( "OWirelessNetworkInterface::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 ) );
- }
- // </check if the driver overwrites stuff>
-
- 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<int>(double( _iwr.u.freq.m ) * pow( 10.0, _iwr.u.freq.e ) / 1000000) ];
- }
-}
-
-
-void OWirelessNetworkInterface::setChannel( int c ) const
-{
- if ( !c )
- {
- qWarning( "OWirelessNetworkInterface::setChannel( 0 ) called - fix your application!" );
- return;
- }
-
- if ( !_mon )
- {
- memset( &_iwr, 0, sizeof( struct iwreq ) );
- _iwr.u.freq.m = c;
- _iwr.u.freq.e = 0;
- wioctl( SIOCSIWFREQ );
- }
- else
- {
- _mon->setChannel( c );
- }
-}
-
-
-double OWirelessNetworkInterface::frequency() const
-{
- if ( !wioctl( SIOCGIWFREQ ) )
- {
- return -1.0;
- }
- else
- {
- return double( _iwr.u.freq.m ) * pow( 10.0, _iwr.u.freq.e ) / 1000000000.0;
- }
-}
-
-
-int OWirelessNetworkInterface::channels() const
-{
- return _channels.count();
-}
-
-
-void OWirelessNetworkInterface::setChannelHopping( int interval )
-{
- if ( !_hopper ) _hopper = new OChannelHopper( this );
- _hopper->setInterval( interval );
- //FIXME: When and by whom will the channel hopper be deleted?
- //TODO: rely on QObject hierarchy
-}
-
-
-int OWirelessNetworkInterface::channelHopping() const
-{
- return _hopper->interval();
-}
-
-
-OChannelHopper* OWirelessNetworkInterface::channelHopper() const
-{
- return _hopper;
-}
-
-
-void OWirelessNetworkInterface::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 "<unknown>";
- }
-
- 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<char*>( (const char*) nickname );
- _iwr.u.essid.length = nickname.length();
- wioctl( SIOCSIWNICKN );
-}
-
-
-QString OWirelessNetworkInterface::nickName() const
-{
- char str[IW_ESSID_MAX_SIZE];
- _iwr.u.data.pointer = &str[0];
- _iwr.u.data.length = IW_ESSID_MAX_SIZE;
- if ( !wioctl( SIOCGIWNICKN ) )
- {
- return "<unknown>";
- }
- else
- {
- str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
- return str;
- }
-}
-
-
-void OWirelessNetworkInterface::setPrivate( const QString& call, int numargs, ... )
-{
- OPrivateIOCTL* priv = static_cast<OPrivateIOCTL*>( child( (const char*) call ) );
- if ( !priv )
- {
- 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 "<unknown>";
- }
- else
- {
- return str;
- }
-}
-
-
-void OWirelessNetworkInterface::setSSID( const QString& ssid )
-{
- _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
- _iwr.u.essid.length = ssid.length();
- 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 = "<unknown>";
- 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<int>(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<OWirelessNetworkInterface*>( iface ) ), _prismHeader( prismHeader )
-{
-}
-
-
-OMonitoringInterface::~OMonitoringInterface()
-{
-}
-
-
-void OMonitoringInterface::setChannel( int c )
-{
- // use standard WE channel switching protocol
- memset( &_if->_iwr, 0, sizeof( struct iwreq ) );
- _if->_iwr.u.freq.m = c;
- _if->_iwr.u.freq.e = 0;
- _if->wioctl( SIOCSIWFREQ );
-}
-
-
-void OMonitoringInterface::setEnabled( bool 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 <mickey@Vanille.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* OPIE */
+
+#include <opie2/onetwork.h>
+#include <opie2/ostation.h>
+#include <opie2/odebug.h>
+
+/* QT */
+
+#include <qfile.h>
+#include <qtextstream.h>
+
+/* UNIX */
+
+#include <assert.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/sockios.h>
+#include <net/if_arp.h>
+#include <stdarg.h>
+
+#ifndef NODEBUG
+#include <opie2/odebugmapper.h>
+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 "<unknown>";
+
+}
+
+
+void ONetworkInterface::setMacAddress( const OMacAddress& addr )
+{
+ _ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
+ memcpy( &_ifr.ifr_hwaddr.sa_data, addr.native(), 6 );
+ ioctl( SIOCSIFHWADDR );
+}
+
+
+OMacAddress ONetworkInterface::macAddress() const
+{
+ if ( ioctl( SIOCGIFHWADDR ) )
+ {
+ return OMacAddress( _ifr );
+ }
+ else
+ {
+ return OMacAddress::unknown;
+ }
+}
+
+
+void ONetworkInterface::setIPV4Netmask( const QHostAddress& addr )
+{
+ struct sockaddr_in *sa = (struct sockaddr_in *) &_ifr.ifr_addr;
+ sa->sin_family = AF_INET;
+ sa->sin_port = 0;
+ sa->sin_addr.s_addr = htonl( addr.ip4Addr() );
+ ioctl( SIOCSIFNETMASK );
+}
+
+
+QString ONetworkInterface::ipV4Netmask() const
+{
+ if ( ioctl( SIOCGIFNETMASK ) )
+ {
+ struct sockaddr_in* sa = (struct sockaddr_in *) &_ifr.ifr_addr;
+ //FIXME: Use QHostAddress here
+ return QString( inet_ntoa( sa->sin_addr ) );
+ }
+ else
+ return "<unknown>";
+}
+
+
+int ONetworkInterface::dataLinkType() const
+{
+ if ( ioctl( SIOCGIFHWADDR ) )
+ {
+ return _ifr.ifr_hwaddr.sa_family;
+ }
+ else
+ {
+ return -1;
+ }
+}
+
+
+void ONetworkInterface::setMonitoring( OMonitoringInterface* m )
+{
+ _mon = m;
+ odebug << "ONetwork::setMonitoring(): Installed monitoring driver '" << m->name() << "' on interface '" << name() << "'" << oendl;
+}
+
+
+OMonitoringInterface* ONetworkInterface::monitoring() const
+{
+ return _mon;
+}
+
+
+ONetworkInterface::~ONetworkInterface()
+{
+ odebug << "ONetworkInterface::~ONetworkInterface()" << oendl;
+ if ( _sfd != -1 ) ::close( _sfd );
+}
+
+
+bool ONetworkInterface::setPromiscuousMode( bool b )
+{
+ ioctl( SIOCGIFFLAGS );
+ if ( b ) _ifr.ifr_flags |= IFF_PROMISC;
+ else _ifr.ifr_flags &= (~IFF_PROMISC);
+ return ioctl( SIOCSIFFLAGS );
+}
+
+
+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
+ {
+ // <check if the driver overwrites stuff>
+ int max = 0;
+ for ( int r = sizeof( struct iw_range ); r < len; r++ )
+ if (buffer[r] != 0)
+ max = r;
+ if (max > 0)
+ {
+ owarn << "OWirelessNetworkInterface::buildInformation(): Driver for wireless interface '" << name()
+ << "' sucks! It overwrote the buffer end with at least " << max - sizeof( struct iw_range ) << " bytes!" << oendl;
+ }
+ // </check if the driver overwrites stuff>
+
+ struct iw_range range;
+ memcpy( &range, buffer, sizeof range );
+
+ odebug << "OWirelessNetworkInterface::buildInformation(): Interface reported to have " << (int) range.num_frequency << " channels." << oendl;
+ for ( int i = 0; i < range.num_frequency; ++i )
+ {
+ int freq = (int) ( double( range.freq[i].m ) * pow( 10.0, range.freq[i].e ) / 1000000.0 );
+ _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<int>(double( _iwr.u.freq.m ) * pow( 10.0, _iwr.u.freq.e ) / 1000000) ];
+ }
+}
+
+
+void OWirelessNetworkInterface::setChannel( int c ) const
+{
+ if ( !c )
+ {
+ oerr << "OWirelessNetworkInterface::setChannel( 0 ) called - fix your application!" << oendl;
+ return;
+ }
+
+ if ( !_mon )
+ {
+ memset( &_iwr, 0, sizeof( struct iwreq ) );
+ _iwr.u.freq.m = c;
+ _iwr.u.freq.e = 0;
+ wioctl( SIOCSIWFREQ );
+ }
+ else
+ {
+ _mon->setChannel( c );
+ }
+}
+
+
+double OWirelessNetworkInterface::frequency() const
+{
+ if ( !wioctl( SIOCGIWFREQ ) )
+ {
+ return -1.0;
+ }
+ else
+ {
+ return double( _iwr.u.freq.m ) * pow( 10.0, _iwr.u.freq.e ) / 1000000000.0;
+ }
+}
+
+
+int OWirelessNetworkInterface::channels() const
+{
+ return _channels.count();
+}
+
+
+void OWirelessNetworkInterface::setChannelHopping( int interval )
+{
+ if ( !_hopper ) _hopper = new OChannelHopper( this );
+ _hopper->setInterval( interval );
+ //FIXME: When and by whom will the channel hopper be deleted?
+ //TODO: rely on QObject hierarchy
+}
+
+
+int OWirelessNetworkInterface::channelHopping() const
+{
+ return _hopper->interval();
+}
+
+
+OChannelHopper* OWirelessNetworkInterface::channelHopper() const
+{
+ return _hopper;
+}
+
+
+void OWirelessNetworkInterface::commit() const
+{
+ wioctl( SIOCSIWCOMMIT );
+}
+
+
+void OWirelessNetworkInterface::setMode( const QString& newMode )
+{
+ #ifdef FINALIZE
+ QString currentMode = mode();
+ if ( currentMode == newMode ) return;
+ #endif
+
+ odebug << "OWirelessNetworkInterface::setMode(): trying to set mode " << newMode << oendl;
+
+ _iwr.u.mode = stringToMode( newMode );
+
+ if ( _iwr.u.mode != IW_MODE_MONITOR )
+ {
+ // IWR.U.MODE WIRD DURCH ABFRAGE DES MODE HIER PLATTGEMACHT!!!!!!!!!!!!!!!!!!!!! DEPP!
+ _iwr.u.mode = stringToMode( newMode );
+ wioctl( SIOCSIWMODE );
+
+ // special iwpriv fallback for monitor mode (check if we're really out of monitor mode now)
+
+ if ( mode() == "monitor" )
+ {
+ odebug << "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not sufficient - trying fallback to iwpriv..." << oendl;
+ if ( _mon )
+ _mon->setEnabled( false );
+ else
+ odebug << "ONetwork(): can't switch monitor mode without installed monitoring interface" << oendl;
+ }
+
+ }
+ else // special iwpriv fallback for monitor mode
+ {
+ if ( wioctl( SIOCSIWMODE ) )
+ {
+ odebug << "OWirelessNetworkInterface::setMode(): IW_MODE_MONITOR ok" << oendl;
+ }
+ else
+ {
+ odebug << "OWirelessNetworkInterface::setMode(): SIOCSIWMODE not working - trying fallback to iwpriv..." << oendl;
+
+ if ( _mon )
+ _mon->setEnabled( true );
+ else
+ odebug << "ONetwork(): can't switch monitor mode without installed monitoring interface" << oendl;
+ }
+ }
+}
+
+
+QString OWirelessNetworkInterface::mode() const
+{
+ memset( &_iwr, 0, sizeof( struct iwreq ) );
+
+ if ( !wioctl( SIOCGIWMODE ) )
+ {
+ return "<unknown>";
+ }
+
+ odebug << "OWirelessNetworkInterface::setMode(): WE's idea of current mode seems to be " << modeToString( _iwr.u.mode ) << oendl;
+
+ // legacy compatible monitor mode check
+
+ if ( dataLinkType() == ARPHRD_IEEE80211 || dataLinkType() == 802 )
+ {
+ return "monitor";
+ }
+ else
+ {
+ return modeToString( _iwr.u.mode );
+ }
+}
+
+void OWirelessNetworkInterface::setNickName( const QString& nickname )
+{
+ _iwr.u.essid.pointer = const_cast<char*>( (const char*) nickname );
+ _iwr.u.essid.length = nickname.length();
+ wioctl( SIOCSIWNICKN );
+}
+
+
+QString OWirelessNetworkInterface::nickName() const
+{
+ char str[IW_ESSID_MAX_SIZE];
+ _iwr.u.data.pointer = &str[0];
+ _iwr.u.data.length = IW_ESSID_MAX_SIZE;
+ if ( !wioctl( SIOCGIWNICKN ) )
+ {
+ return "<unknown>";
+ }
+ else
+ {
+ str[_iwr.u.data.length] = 0x0; // some drivers (e.g. wlan-ng) don't zero-terminate the string
+ return str;
+ }
+}
+
+
+void OWirelessNetworkInterface::setPrivate( const QString& call, int numargs, ... )
+{
+ OPrivateIOCTL* priv = static_cast<OPrivateIOCTL*>( child( (const char*) call ) );
+ if ( !priv )
+ {
+ owarn << "OWirelessNetworkInterface::setPrivate(): interface '" << name()
+ << "' does not support private ioctl '" << call << "'" << oendl;
+ return;
+ }
+ if ( priv->numberSetArgs() != numargs )
+ {
+ owarn << "OWirelessNetworkInterface::setPrivate(): parameter count not matching. '"
+ << call << "' expects " << priv->numberSetArgs() << ", but got " << numargs << oendl;
+ return;
+ }
+
+ odebug << "OWirelessNetworkInterface::setPrivate(): about to call '" << call << "' on interface '" << name() << "'" << oendl;
+ memset( &_iwr, 0, sizeof _iwr );
+ va_list argp;
+ va_start( argp, numargs );
+ for ( int i = 0; i < numargs; ++i )
+ {
+ priv->setParameter( i, va_arg( argp, int ) );
+ }
+ va_end( argp );
+ priv->invoke();
+}
+
+
+void OWirelessNetworkInterface::getPrivate( const QString& 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 "<unknown>";
+ }
+ else
+ {
+ return str;
+ }
+}
+
+
+void OWirelessNetworkInterface::setSSID( const QString& ssid )
+{
+ _iwr.u.essid.pointer = const_cast<char*>( (const char*) ssid );
+ _iwr.u.essid.length = ssid.length();
+ 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 = "<unknown>";
+ odebug << " - reading next event... cmd=" << we->cmd << ", len=" << we->len << oendl;
+ switch (we->cmd)
+ {
+ case SIOCGIWAP:
+ {
+ odebug << "SIOCGIWAP" << oendl;
+ stations->append( new OStation() );
+ stations->last()->macAddress = (const unsigned char*) &we->u.ap_addr.sa_data[0];
+ break;
+ }
+ case SIOCGIWMODE:
+ {
+ odebug << "SIOCGIWMODE" << oendl;
+ stations->last()->type = modeToString( we->u.mode );
+ break;
+ }
+ case SIOCGIWFREQ:
+ {
+ odebug << "SIOCGIWFREQ" << oendl;
+ stations->last()->channel = _channels[ static_cast<int>(double( we->u.freq.m ) * pow( 10.0, we->u.freq.e ) / 1000000) ];
+ break;
+ }
+ case SIOCGIWESSID:
+ {
+ odebug << "SIOCGIWESSID" << oendl;
+ stations->last()->ssid = 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<OWirelessNetworkInterface*>( iface ) ), _prismHeader( prismHeader )
+{
+}
+
+
+OMonitoringInterface::~OMonitoringInterface()
+{
+}
+
+
+void OMonitoringInterface::setChannel( int c )
+{
+ // use standard WE channel switching protocol
+ memset( &_if->_iwr, 0, sizeof( struct iwreq ) );
+ _if->_iwr.u.freq.m = c;
+ _if->_iwr.u.freq.e = 0;
+ _if->wioctl( SIOCSIWFREQ );
+}
+
+
+void OMonitoringInterface::setEnabled( bool 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 <mickey@Vanille.de>
- =.
- .=l.
-           .>+-=
- _;:,     .>    :=|. This program is free software; you can
-.> <`_,   >  .   <= redistribute it and/or modify it under
-:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
-.="- .-=="i,     .._ License as published by the Free Software
- - .   .-<_>     .<> Foundation; either version 2 of the License,
-     ._= =}       : or (at your option) any later version.
-    .%`+i>       _;_.
-    .i_,=:_.      -<s. This program is distributed in the hope that
-     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
-    : ..    .:,     . . . without even the implied warranty of
-    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
-  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
-..}^=.=       =       ; Library General Public License for more
-++=   -.     .`     .: details.
- :     =  ...= . :.=-
- -.   .:....=;==+<; You should have received a copy of the GNU
-  -_. . .   )=.  = Library General Public License along with
-    --        :-=` this library; see the file COPYING.LIB.
- If not, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
-*/
-
-/* OPIE */
-#include <opie2/opcap.h>
-
-/* QT */
-#include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
-#include <qsocketnotifier.h>
-#include <qobjectlist.h>
-
-/* SYSTEM */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-/* 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<QString,int>& stats, QObjectList* l )
-{
- if (!l) return;
- QObject* o = l->first();
- while ( o )
- {
- stats[o->name()]++;
- updateStats( stats, const_cast<QObjectList*>( 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<QObjectList*>( 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 "<unknown>";
- }
-}
-
-
-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 "<unknown>";
- }
-}
-
-
-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<QString,int>::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<QObjectList*>( p->children() ) );
- #ifndef NODEBUG
- p->dumpStructure( const_cast<QObjectList*>( 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<char*>( (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<char*>( (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<char*>( (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<QString,int>& 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 <mickey@Vanille.de>
+ =.
+ .=l.
+           .>+-=
+ _;:,     .>    :=|. This program is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This program is distributed in the hope that
+     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
+    : ..    .:,     . . . without even the implied warranty of
+    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
+  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
+..}^=.=       =       ; Library General Public License for more
+++=   -.     .`     .: details.
+ :     =  ...= . :.=-
+ -.   .:....=;==+<; You should have received a copy of the GNU
+  -_. . .   )=.  = Library General Public License along with
+    --        :-=` this library; see the file COPYING.LIB.
+ If not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+/* OPIE */
+#include <opie2/opcap.h>
+#include <opie2/odebug.h>
+
+/* QT */
+#include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
+#include <qsocketnotifier.h>
+#include <qobjectlist.h>
+
+/* SYSTEM */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* 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<QString,int>& stats, QObjectList* l )
+{
+ if (!l) return;
+ QObject* o = l->first();
+ while ( o )
+ {
+ stats[o->name()]++;
+ updateStats( stats, const_cast<QObjectList*>( 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<QObjectList*>( 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 "<unknown>";
+ }
+}
+
+
+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 "<unknown>";
+ }
+}
+
+
+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<QString,int>::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<QObjectList*>( p->children() ) );
+ #ifndef NODEBUG
+ p->dumpStructure( const_cast<QObjectList*>( 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<char*>( (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<char*>( (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<char*>( (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<QString,int>& 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 <opie2/ostation.h>
+#include <opie2/odebug.h>
/*======================================================================================
* OStation
@@ -36,7 +37,7 @@
OStation::OStation()
{
- qDebug( "OStation::OStation()" );
+ odebug << "OStation::OStation()" << oendl;
type = "<unknown>";
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() );