author | mickeyl <mickeyl> | 2003-10-09 00:03:06 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-10-09 00:03:06 (UTC) |
commit | f8d08db59ac05f5bf2f56e6ebf69c28dfbe8b13e (patch) (side-by-side diff) | |
tree | 36059d71abfcdb73748c1941fb9458dc75e0d4a8 | |
parent | 5517443d9ebe96ff9c30d91b2254418964d5c410 (diff) | |
download | opie-f8d08db59ac05f5bf2f56e6ebf69c28dfbe8b13e.zip opie-f8d08db59ac05f5bf2f56e6ebf69c28dfbe8b13e.tar.gz opie-f8d08db59ac05f5bf2f56e6ebf69c28dfbe8b13e.tar.bz2 |
- catch up with changed sniffing behaviour in newer wlan-ng *puke* drivers
- new API: OPacketCapturer::next( int time )
-rw-r--r-- | libopie2/opienet/onetwork.cpp | 12 | ||||
-rw-r--r-- | libopie2/opienet/opcap.cpp | 27 | ||||
-rw-r--r-- | libopie2/opienet/opcap.h | 5 |
3 files changed, 38 insertions, 6 deletions
diff --git a/libopie2/opienet/onetwork.cpp b/libopie2/opienet/onetwork.cpp index 1f529d2..45ee4c0 100644 --- a/libopie2/opienet/onetwork.cpp +++ b/libopie2/opienet/onetwork.cpp @@ -1,1034 +1,1040 @@ /* This file is part of the Opie Project Copyright (C) 2003 by the Wellenreiter team: Martin J. Muench <mjm@remote-exploit.org> Max Moser <mmo@remote-exploit.org Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.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> /* QT */ #include <qfile.h> #include <qtextstream.h> /* UNIX */ #include <assert.h> #include <arpa/inet.h> #include <cerrno> #include <cstring> #include <cstdlib> #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> using namespace std; /*====================================================================================== * 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 _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 { int result = ::ioctl( _sfd, call, &ifreq ); if ( result == -1 ) qDebug( "ONetworkInterface::ioctl (%s) call %d - Status: Failed: %d (%s)", name(), call, result, strerror( errno ) ); else qDebug( "ONetworkInterface::ioctl (%s) call %d - Status: Ok.", name(), call ); return ( result != -1 ); } 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 ) ); buildChannelList(); buildPrivateList(); } QString OWirelessNetworkInterface::associatedAP() const { //FIXME: use OMacAddress QString mac; if ( ioctl( SIOCGIWAP ) ) { mac.sprintf( "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", _ifr.ifr_hwaddr.sa_data[0]&0xff, _ifr.ifr_hwaddr.sa_data[1]&0xff, _ifr.ifr_hwaddr.sa_data[2]&0xff, _ifr.ifr_hwaddr.sa_data[3]&0xff, _ifr.ifr_hwaddr.sa_data[4]&0xff, _ifr.ifr_hwaddr.sa_data[5]&0xff ); } else { mac = "<Unknown>"; } return mac; } void OWirelessNetworkInterface::buildChannelList() { //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::buildChannelList(): SIOCGIWRANGE failed (%s) - defaulting to 11 channels", strerror( errno ) ); _channels.insert( 2412, 1 ); // 2.412 GHz _channels.insert( 2417, 2 ); // 2.417 GHz _channels.insert( 2422, 3 ); // 2.422 GHz _channels.insert( 2427, 4 ); // 2.427 GHz _channels.insert( 2432, 5 ); // 2.432 GHz _channels.insert( 2437, 6 ); // 2.437 GHz _channels.insert( 2442, 7 ); // 2.442 GHz _channels.insert( 2447, 8 ); // 2.447 GHz _channels.insert( 2452, 9 ); // 2.452 GHz _channels.insert( 2457, 10 ); // 2.457 GHz _channels.insert( 2462, 11 ); // 2.462 GHz } else { // <check if the driver overwrites stuff> int max = 0; for ( int r = sizeof( struct iw_range ); r < len; r++ ) if (buffer[r] != 0) max = r; if (max > 0) { qWarning( "OWirelessNetworkInterface::buildChannelList(): Driver for wireless interface '%s'" "overwrote buffer end with at least %i bytes!\n", name(), max - sizeof( struct iw_range ) ); } // </check if the driver overwrites stuff> struct iw_range range; memcpy( &range, buffer, sizeof range ); qDebug( "OWirelessNetworkInterface::buildChannelList(): Interface %s reported to have %d channels.", name(), range.num_frequency ); for ( int i = 0; i < range.num_frequency; ++i ) { int freq = (int) ( double( range.freq[i].m ) * pow( 10.0, range.freq[i].e ) / 1000000.0 ); _channels.insert( freq, i+1 ); } } qDebug( "OWirelessNetworkInterface::buildChannelList(): Channel list constructed." ); free(buffer); } void OWirelessNetworkInterface::buildPrivateList() { qDebug( "OWirelessNetworkInterface::buildPrivateList()" ); struct iw_priv_args priv[IW_MAX_PRIV_DEF]; _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." ); } 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 ( !_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::setMode( const QString& mode ) { if ( mode == "auto" ) _iwr.u.mode = IW_MODE_AUTO; else if ( mode == "adhoc" ) _iwr.u.mode = IW_MODE_ADHOC; else if ( mode == "managed" ) _iwr.u.mode = IW_MODE_INFRA; else if ( mode == "master" ) _iwr.u.mode = IW_MODE_MASTER; else if ( mode == "repeater" ) _iwr.u.mode = IW_MODE_REPEAT; else if ( mode == "secondary" ) _iwr.u.mode = IW_MODE_SECOND; #if WIRELESS_EXT > 14 else if ( mode == "monitor" ) _iwr.u.mode = IW_MODE_MONITOR; #endif else { qDebug( "ONetwork: Warning! Invalid IEEE 802.11 mode '%s' specified.", (const char*) mode ); return; } wioctl( SIOCSIWMODE ); } QString OWirelessNetworkInterface::mode() const { if ( !wioctl( SIOCGIWMODE ) ) { return "<unknown>"; } switch ( _iwr.u.mode ) { case IW_MODE_AUTO: return "auto"; case IW_MODE_ADHOC: return "adhoc"; case IW_MODE_INFRA: return "managed"; case IW_MODE_MASTER: return "master"; case IW_MODE_REPEAT: return "repeater"; case IW_MODE_SECOND: return "secondary"; #if WIRELESS_EXT > 14 case IW_MODE_MONITOR: return "monitor"; #endif default: assert( 0 ); // shouldn't happen } } void OWirelessNetworkInterface::setMonitorMode( bool b ) { if ( _mon ) _mon->setEnabled( b ); else qDebug( "ONetwork(): can't switch monitor mode without installed monitoring interface" ); } bool OWirelessNetworkInterface::monitorMode() const { qDebug( "dataLinkType = %d", dataLinkType() ); return ( dataLinkType() == ARPHRD_IEEE80211 || dataLinkType() == 802 ); // 802 is the header type for PRISM - Linux support for this is pending... } 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 ); } bool OWirelessNetworkInterface::wioctl( int call, struct iwreq& iwreq ) const { int result = ::ioctl( _sfd, call, &iwreq ); if ( result == -1 ) qDebug( "ONetworkInterface::wioctl (%s) call %d - Status: Failed: %d (%s)", name(), call, result, strerror( errno ) ); else qDebug( "ONetworkInterface::wioctl (%s) call %d - Status: Ok.", name(), call ); return ( result != -1 ); } 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 ); } bool OMonitoringInterface::enabled() const { return _if->monitorMode(); } 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 ) +void OWlanNGMonitoringInterface::setChannel( int c ) { - // wlan-ng devices automatically switch channels when in monitor mode - // NOTE: The above note no longer seems to be true for recent driver versions! + //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+1, (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 ) { // IW_MODE_MONITOR was introduced in Wireless Extensions Version 15 // Wireless Extensions < Version 15 need iwpriv commandos for monitoring #if WIRELESS_EXT > 14 if ( b ) _if->setMode( "monitor" ); // IW_MODE_MONITOR doesn't support prism header else _if->setMode( "managed" ); #else int monitorCode = _prismHeader ? 1 : 2; if ( b ) { _if->setPrivate( "monitor", 1, monitorCode ); } else { _if->setPrivate( "monitor", 1, 0 ); } #endif } 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 #if WIRELESS_EXT > 14 if ( b ) _if->setMode( "monitor" ); // IW_MODE_MONITOR doesn't support prism header else _if->setMode( "managed" ); #else if ( b ) { setChannel( 1 ); } else { _if->setPrivate( "monitor", 2, 0, 0 ); } #endif } QString OOrinocoMonitoringInterface::name() const { return "orinoco"; } diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 9ed2b83..38ca1a1 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -1,1302 +1,1323 @@ /* This file is part of the Opie Project Copyright (C) 2003 by the Wellenreiter team: Martin J. Muench <mjm@remote-exploit.org> Max Moser <mmo@remote-exploit.org Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.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: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = ARP" ); 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( 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 ) ); } diff --git a/libopie2/opienet/opcap.h b/libopie2/opienet/opcap.h index 51f067a..54b256b 100644 --- a/libopie2/opienet/opcap.h +++ b/libopie2/opienet/opcap.h @@ -1,662 +1,667 @@ /* This file is part of the Opie Project Copyright (C) 2003 by the Wellenreiter team: Martin J. Muench <mjm@remote-exploit.org> Max Moser <mmo@remote-exploit.org Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.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. */ #ifndef OPCAP_H #define OPCAP_H /* LINUX */ extern "C" // work around a bpf/pcap conflict in recent headers { #include <pcap.h> } #include <netinet/ether.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <time.h> /* QT */ #include <qevent.h> #include <qfile.h> #include <qhostaddress.h> #include <qobject.h> #include <qstring.h> #include <qmap.h> /* OPIE */ #include <opie2/onetutils.h> /* Custom Network Includes */ #include "802_11_user.h" #include "dhcp.h" /* TYPEDEFS */ typedef struct timeval timevalstruct; typedef struct pcap_pkthdr packetheaderstruct; /* FORWARDS */ class OPacketCapturer; class QSocketNotifier; /*====================================================================================== * OPacket - A frame on the wire *======================================================================================*/ /** @brief A class representing a data frame on the wire. * * The whole family of the packet classes are used when capturing frames from a network. * Most standard network protocols in use share a common architecture, which mostly is * a packet header and then the packet payload. In layered architectures, each lower layer * encapsulates data from its upper layer - that is it * treats the data from its upper layer as payload and prepends an own header to the packet, * which - again - is treated as the payload for the layer below. The figure below is an * example for how such a data frame is composed out of packets, e.g. when sending a mail. * * <pre> * | User Data | == Mail Data * | SMTP Header | User Data | == SMTP * | TCP Header | SMTP Header | User Data | == TCP * | IP Header | TCP Header | SMTP Header | User Data | == IP * | MAC Header | IP Header | TCP Header | SMTP Header | User Data | == MAC * * </pre> * * The example is trimmed for simplicity, because the MAC (Medium Access Control) layer * also contains a few more levels of encapsulation. * Since the type of the payload is more or less independent from the encapsulating protocol, * the header must be inspected before attempting to decode the payload. Hence, the * encapsulation level varies and can't be deduced without actually looking into the packets. * * For actually working with captured frames, it's useful to identify the packets via names and * insert them into a parent/child - relationship based on the encapsulation. This is why * all packet classes derive from QObject. The amount of overhead caused by the QObject is * not a problem in this case, because we're talking about a theoratical maximum of about * 10 packets per captured frame. We need to stuff them into a searchable list anyway and the * QObject also cares about destroying the sub-, (child-) packets. * * This enables us to perform a simple look for packets of a certain type: * @code * OPacketCapturer* pcap = new OPacketCapturer(); * pcap->open( "eth0" ); * OPacket* p = pcap->next(); * OIPPacket* ip = (OIPPacket*) p->child( "IP" ); // returns 0, if no such child exists * odebug << "got ip packet from " << ip->fromIPAddress().toString() << " to " << ip->toIPAddress().toString() << oendl; * */ class OPacket : public QObject { Q_OBJECT friend class OPacketCapturer; public: OPacket( int datalink, packetheaderstruct, const unsigned char*, QObject* parent ); virtual ~OPacket(); timevalstruct timeval() const; int caplen() const; int len() const; QString dump( int = 32 ) const; void updateStats( QMap<QString,int>&, QObjectList* ); private: void dumpStructure( QObjectList* ); QString _dumpStructure( QObjectList* ); private: const packetheaderstruct _hdr; // pcap packet header const unsigned char* _data; // pcap packet data const unsigned char* _end; // end of pcap packet data }; /*====================================================================================== * OEthernetPacket - DLT_EN10MB frame *======================================================================================*/ class OEthernetPacket : public QObject { Q_OBJECT public: OEthernetPacket( const unsigned char*, const struct ether_header*, QObject* parent = 0 ); virtual ~OEthernetPacket(); OMacAddress sourceAddress() const; OMacAddress destinationAddress() const; int type() const; private: const struct ether_header* _ether; }; /*====================================================================================== * OPrismHeaderPacket - DLT_PRISM_HEADER frame *======================================================================================*/ class OPrismHeaderPacket : public QObject { Q_OBJECT public: OPrismHeaderPacket( const unsigned char*, const struct prism_hdr*, QObject* parent = 0 ); virtual ~OPrismHeaderPacket(); unsigned int signalStrength() const; private: const struct prism_hdr* _header; }; /*====================================================================================== * OWaveLanPacket - DLT_IEEE802_11 frame *======================================================================================*/ class OWaveLanPacket : public QObject { Q_OBJECT public: OWaveLanPacket( const unsigned char*, const struct ieee_802_11_header*, QObject* parent = 0 ); virtual ~OWaveLanPacket(); int duration() const; bool fromDS() const; bool toDS() const; virtual OMacAddress macAddress1() const; virtual OMacAddress macAddress2() const; virtual OMacAddress macAddress3() const; virtual OMacAddress macAddress4() const; bool usesPowerManagement() const; int type() const; int subType() const; int version() const; bool usesWep() const; private: const struct ieee_802_11_header* _wlanhdr; }; /*====================================================================================== * OWaveLanManagementPacket - type: management (T_MGMT) *======================================================================================*/ class OWaveLanManagementPacket : public QObject { Q_OBJECT public: OWaveLanManagementPacket( const unsigned char*, const struct ieee_802_11_mgmt_header*, OWaveLanPacket* parent = 0 ); virtual ~OWaveLanManagementPacket(); QString managementType() const; int beaconInterval() const; int capabilities() const; // generic bool canESS() const; bool canIBSS() const; bool canCFP() const; bool canCFP_REQ() const; bool canPrivacy() const; private: const struct ieee_802_11_mgmt_header* _header; const struct ieee_802_11_mgmt_body* _body; }; /*====================================================================================== * OWaveLanManagementSSID *======================================================================================*/ class OWaveLanManagementSSID : public QObject { Q_OBJECT public: OWaveLanManagementSSID( const unsigned char*, const struct ssid_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementSSID(); QString ID() const; private: const struct ssid_t* _data; }; /*====================================================================================== * OWaveLanManagementRates *======================================================================================*/ class OWaveLanManagementRates : public QObject { Q_OBJECT public: OWaveLanManagementRates( const unsigned char*, const struct rates_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementRates(); private: const struct rates_t* _data; }; /*====================================================================================== * OWaveLanManagementCF *======================================================================================*/ class OWaveLanManagementCF : public QObject { Q_OBJECT public: OWaveLanManagementCF( const unsigned char*, const struct cf_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementCF(); private: const struct cf_t* _data; }; /*====================================================================================== * OWaveLanManagementFH *======================================================================================*/ class OWaveLanManagementFH : public QObject { Q_OBJECT public: OWaveLanManagementFH( const unsigned char*, const struct fh_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementFH(); private: const struct fh_t* _data; }; /*====================================================================================== * OWaveLanManagementDS *======================================================================================*/ class OWaveLanManagementDS : public QObject { Q_OBJECT public: OWaveLanManagementDS( const unsigned char*, const struct ds_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementDS(); int channel() const; private: const struct ds_t* _data; }; /*====================================================================================== * OWaveLanManagementTim *======================================================================================*/ class OWaveLanManagementTim : public QObject { Q_OBJECT public: OWaveLanManagementTim( const unsigned char*, const struct tim_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementTim(); private: const struct tim_t* _data; }; /*====================================================================================== * OWaveLanManagementIBSS *======================================================================================*/ class OWaveLanManagementIBSS : public QObject { Q_OBJECT public: OWaveLanManagementIBSS( const unsigned char*, const struct ibss_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementIBSS(); private: const struct ibss_t* _data; }; /*====================================================================================== * OWaveLanManagementChallenge *======================================================================================*/ class OWaveLanManagementChallenge : public QObject { Q_OBJECT public: OWaveLanManagementChallenge( const unsigned char*, const struct challenge_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementChallenge(); private: const struct challenge_t* _data; }; /*====================================================================================== * OWaveLanDataPacket - type: data (T_DATA) *======================================================================================*/ class OWaveLanDataPacket : public QObject { Q_OBJECT public: OWaveLanDataPacket( const unsigned char*, const struct ieee_802_11_data_header*, OWaveLanPacket* parent = 0 ); virtual ~OWaveLanDataPacket(); private: const struct ieee_802_11_data_header* _header; }; /*====================================================================================== * OWaveLanControlPacket - type: control (T_CTRL) *======================================================================================*/ class OWaveLanControlPacket : public QObject { Q_OBJECT public: OWaveLanControlPacket( const unsigned char*, const struct ieee_802_11_control_header*, OWaveLanPacket* parent = 0 ); virtual ~OWaveLanControlPacket(); private: const struct ieee_802_11_control_header* _header; }; /*====================================================================================== * OLLCPacket - IEEE 802.2 Link Level Control *======================================================================================*/ class OLLCPacket : public QObject { Q_OBJECT public: OLLCPacket( const unsigned char*, const struct ieee_802_11_802_2_header* data, QObject* parent = 0 ); virtual ~OLLCPacket(); private: const struct ieee_802_11_802_2_header* _header; }; /*====================================================================================== * OIPPacket *======================================================================================*/ class OIPPacket : public QObject { Q_OBJECT public: OIPPacket( const unsigned char*, const struct iphdr*, QObject* parent = 0 ); virtual ~OIPPacket(); QHostAddress fromIPAddress() const; QHostAddress toIPAddress() const; int tos() const; int len() const; int id() const; int offset() const; int ttl() const; int protocol() const; int checksum() const; private: const struct iphdr* _iphdr; }; /*====================================================================================== * OARPPacket *======================================================================================*/ class OARPPacket : public QObject { Q_OBJECT public: OARPPacket( const unsigned char*, const struct myarphdr*, QObject* parent = 0 ); virtual ~OARPPacket(); QHostAddress senderIPV4Address() const; OMacAddress senderMacAddress() const; QHostAddress targetIPV4Address() const; OMacAddress targetMacAddress() const; //int type() const; QString type() const; private: const struct myarphdr* _arphdr; }; /*====================================================================================== * OUDPPacket *======================================================================================*/ class OUDPPacket : public QObject { Q_OBJECT public: OUDPPacket( const unsigned char*, const struct udphdr*, QObject* parent = 0 ); virtual ~OUDPPacket(); int fromPort() const; int toPort() const; int length() const; int checksum() const; private: const struct udphdr* _udphdr; }; /*====================================================================================== * ODHCPPacket *======================================================================================*/ class ODHCPPacket : public QObject { Q_OBJECT public: ODHCPPacket( const unsigned char*, const struct dhcp_packet*, QObject* parent = 0 ); virtual ~ODHCPPacket(); QHostAddress clientAddress() const; QHostAddress yourAddress() const; QHostAddress serverAddress() const; QHostAddress relayAddress() const; OMacAddress clientMacAddress() const; bool isRequest() const; bool isReply() const; QString type() const; private: const struct dhcp_packet* _dhcphdr; unsigned char _type; }; /*====================================================================================== * OTCPPacket *======================================================================================*/ class OTCPPacket : public QObject { Q_OBJECT public: OTCPPacket( const unsigned char*, const struct tcphdr*, QObject* parent = 0 ); virtual ~OTCPPacket(); int fromPort() const; int toPort() const; int seq() const; int ack() const; int window() const; int checksum() const; private: const struct tcphdr* _tcphdr; }; /*====================================================================================== * OPacketCapturer *======================================================================================*/ /** * @brief A class based wrapper for network packet capturing. * * This class is the base of a high-level interface to the well known packet capturing * library libpcap. * @see http://tcpdump.org */ class OPacketCapturer : public QObject { Q_OBJECT public: /** * Constructor. */ OPacketCapturer( QObject* parent = 0, const char* name = 0 ); /** * Destructor. */ ~OPacketCapturer(); /** * Set the packet capturer to use blocking or non-blocking IO. This can be useful when * not using the socket notifier, e.g. without an application object. */ void setBlocking( bool ); /** * @returns true if the packet capturer uses blocking IO calls. */ bool blocking() const; /** * Close the packet capturer. This is automatically done in the destructor. */ void close(); /** * Close the output capture file. */ void closeDumpFile(); /** * @returns the data link type. * @see <pcap.h> for possible values. */ int dataLink() const; /** * Dump a packet to the output capture file. */ void dump( OPacket* ); /** * @returns the file descriptor of the packet capturer. This is only useful, if * not using the socket notifier, e.g. without an application object. */ int fileno() const; /** * @returns the next @ref OPacket from the packet capturer. * @note If blocking mode is true then this call might block. */ OPacket* next(); /** + * @returns the next @ref OPacket from the packet capturer, if + * one arrives within @a time milliseconds. + */ + OPacket* next( int time ); + /** * Open the packet capturer to capture packets in live-mode from @a interface. */ bool open( const QString& interface ); /** * Open the packet capturer to capture packets in offline-mode from @a file. */ bool open( const QFile& file ); /** * Open a prerecorded tcpdump compatible capture file for use with @ref dump() */ bool openDumpFile( const QString& filename ); /** * @returns true if the packet capturer is open */ bool isOpen() const; /** * @returns the snapshot length of this packet capturer */ int snapShot() const; /** * @returns true if the input capture file has a different byte-order * than the byte-order of the running system. */ bool swapped() const; /** * @returns the libpcap version string used to write the input capture file. */ QString version() const; /** * @returns the packet statistic database. * @see QMap */ const QMap<QString,int>& statistics() const; signals: /** * This signal is emitted, when a packet has been received. */ void receivedPacket( OPacket* ); protected slots: void readyToReceive(); protected: QString _name; // devicename bool _open; // check this before doing pcap calls pcap_t* _pch; // pcap library handle pcap_dumper_t* _pcd; // pcap dumper handle QSocketNotifier* _sn; // socket notifier for main loop mutable char _errbuf[PCAP_ERRBUF_SIZE]; // holds error strings from libpcap QMap<QString, int> _stats; // statistics; }; #endif // OPCAP_H |