-rw-r--r-- | libopie2/opienet/opcap.cpp | 4 | ||||
-rw-r--r-- | libopie2/opienet/opcap.h | 4 |
2 files changed, 3 insertions, 5 deletions
diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 067d6b7..f8ebe6b 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -518,854 +518,852 @@ 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. // Beacons contain a 12 byte long fixed parameters set before the tagged parameters come, // Other management frames don't - which is why we have to inspect the subtype here. const unsigned char* ptr = managementType() == "Beacon" ? (const unsigned char*) (_body+1) : (const unsigned char*) (_header+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: owarn << "OWaveLanManagementPacket::managementType(): unhandled subtype " << FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) << oendl; 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( bool decloak ) const { int length = _data->length; if ( length > 32 ) length = 32; char essid[length+1]; memcpy( &essid, &_data->ssid, length ); essid[length] = 0x0; if ( !decloak || length < 2 || essid[0] != '\0' ) return essid; odebug << "OWaveLanManagementSSID:ID(): SSID is cloaked - decloaking..." << oendl; QString decloakedID; for ( int i = 1; i < length; ++i ) { if ( essid[i] >= 32 && essid[i] <= 126 ) decloakedID.append( essid[i] ); else decloakedID.append( '.' ); } return decloakedID; } /*====================================================================================== * 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; odebug << "Detected subtype is " << controlType() << oendl; } OWaveLanControlPacket::~OWaveLanControlPacket() { } QString OWaveLanControlPacket::controlType() const { switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ) { case CTRL_PS_POLL: return "PowerSavePoll"; break; case CTRL_RTS: return "RequestToSend"; break; case CTRL_CTS: return "ClearToSend"; break; case CTRL_ACK: return "Acknowledge"; break; case CTRL_CF_END: return "ContentionFreeEnd"; break; case CTRL_END_ACK: return "AcknowledgeEnd"; break; default: owarn << "OWaveLanControlPacket::managementType(): unhandled subtype " << FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) << oendl; return "Unknown"; } } /*====================================================================================== * OPacketCapturer *======================================================================================*/ OPacketCapturer::OPacketCapturer( QObject* parent, const char* name ) :QObject( parent, name ), _name( QString::null ), _open( false ), _pch( 0 ), _pcd( 0 ), _sn( 0 ), _autodelete( true ) { } OPacketCapturer::~OPacketCapturer() { if ( _open ) { odebug << "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." << oendl; close(); } } void OPacketCapturer::setAutoDelete( bool b ) { _autodelete = b; } bool OPacketCapturer::autoDelete() const { return _autodelete; } 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 ) { owarn << "OPacketCapturer::dump() - cannot dump without open capture file!" << oendl; 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() ) ); odebug << "OPacket::dumpStructure: " << p->dumpStructure() << oendl; return p; } else { owarn << "OPacketCapturer::next() - no packet received!" << oendl; 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 ) +bool OPacketCapturer::openCaptureFile( const QString& name ) { - 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 (if enabled) if ( _autodelete ) 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( "%d.%d", pcap_major_version( _pch ), pcap_minor_version( _pch ) ); } } } diff --git a/libopie2/opienet/opcap.h b/libopie2/opienet/opcap.h index 2dbe030..9e718d5 100644 --- a/libopie2/opienet/opcap.h +++ b/libopie2/opienet/opcap.h @@ -1,733 +1,733 @@ /* 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. */ #ifndef OPCAP_H #define OPCAP_H /* OPIE */ #include <opie2/onetutils.h> /* QT */ #include <qevent.h> #include <qfile.h> #include <qhostaddress.h> #include <qobject.h> #include <qstring.h> #include <qtextstream.h> #include <qmap.h> /* STD */ 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> /* Custom Network Includes (must go here, don't reorder!) */ #include "802_11_user.h" #include "dhcp.h" /* TYPEDEFS */ typedef struct timeval timevalstruct; typedef struct pcap_pkthdr packetheaderstruct; /* FORWARDS */ class QSocketNotifier; namespace Opie { namespace Net { class OPacketCapturer; /*====================================================================================== * 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; friend QTextStream& operator<<( QTextStream& s, const OPacket& p ); 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; //FIXME: remove that void updateStats( QMap<QString,int>&, QObjectList* ); //FIXME: Revise QString dumpStructure() const; //FIXME: Revise private: QString _dumpStructure( QObjectList* ) const; //FIXME: Revise private: const packetheaderstruct _hdr; // pcap packet header const unsigned char* _data; // pcap packet data const unsigned char* _end; // end of pcap packet data private: class Private; Private *d; }; QTextStream& operator<<( QTextStream& s, const OPacket& p ); //FIXME: Revise /*====================================================================================== * 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; private: class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * OWaveLanManagementSSID *======================================================================================*/ class OWaveLanManagementSSID : public QObject { Q_OBJECT public: OWaveLanManagementSSID( const unsigned char*, const struct ssid_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementSSID(); QString ID( bool decloak = false ) const; private: const struct ssid_t* _data; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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(); QString controlType() const; private: const struct ieee_802_11_control_header* _header; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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; class Private; Private *d; }; /*====================================================================================== * 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. + * Open the packet capturer to capture packets in offline-mode from @a filename. */ - bool open( const QFile& file ); + bool openCaptureFile( const QString& filename ); /** * 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; /** * Enable or disable the auto-delete option. * If auto-delete is enabled, then the packet capturer will delete a packet right * after it has been emit'ted. This is the default, which is useful if the packet * capturer has the only reference to the packets. If you pass the packet for adding * into a collection or do processing after the SLOT, the auto delete must be disabled. */ void setAutoDelete( bool enable ); /** * @returns the auto-delete value. */ bool autoDelete() const; signals: /** * This signal is emitted, when a packet has been received. */ void receivedPacket( Opie::Net::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; bool _autodelete; // if we auto delete packets after emit class Private; // Private Forward declaration Private *d; // if we need to add data }; } } #endif // OPCAP_H |