summaryrefslogtreecommitdiff
path: root/libopie2/opienet/opcap.cpp
authormickeyl <mickeyl>2004-03-28 16:52:43 (UTC)
committer mickeyl <mickeyl>2004-03-28 16:52:43 (UTC)
commite2368b92a101437f7ed289d5ae62f7e7e2466344 (patch) (side-by-side diff)
tree1e7775ee681d970c9cd785b9afb6946143c212e1 /libopie2/opienet/opcap.cpp
parent6c102bd456d760fbe237fd49ce46f212614f228a (diff)
downloadopie-e2368b92a101437f7ed289d5ae62f7e7e2466344.zip
opie-e2368b92a101437f7ed289d5ae62f7e7e2466344.tar.gz
opie-e2368b92a101437f7ed289d5ae62f7e7e2466344.tar.bz2
OPacketCapturer API addition: setAutoDelete() and autoDelete()
Diffstat (limited to 'libopie2/opienet/opcap.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opienet/opcap.cpp21
1 files changed, 17 insertions, 4 deletions
diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp
index 4081d4f..c5df041 100644
--- a/libopie2/opienet/opcap.cpp
+++ b/libopie2/opienet/opcap.cpp
@@ -1,185 +1,186 @@
/*
                This file is part of the Opie Project
              Copyright (C) 2003 by Michael 'Mickey' Lauer <mickey@Vanille.de>
=.
.=l.
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU Library General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. This program is distributed in the hope that
     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
    : ..    .:,     . . . without even the implied warranty of
    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = Library General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* OPIE */
#include <opie2/opcap.h>
#include <opie2/odebug.h>
/* QT */
#include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
#include <qsocketnotifier.h>
#include <qobjectlist.h>
/* SYSTEM */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/* LOCAL */
#include "udp_ports.h"
using namespace Opie::Core;
namespace Opie {
namespace Net {
/*======================================================================================
* 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 );
+ qDebug( "OPacket::OPacket(): (Len %d, CapLen %d)" /*, ctime((const time_t*) header.ts.tv_sec)*/, header.len, header.caplen );
_end = (unsigned char*) data + header.len;
//qDebug( "OPacket::data @ %0x, end @ %0x", data, _end );
switch ( datalink )
{
case DLT_EN10MB:
odebug << "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" << oendl;
new OEthernetPacket( _end, (const struct ether_header*) data, this );
break;
case DLT_IEEE802_11:
odebug << "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" << oendl;
new OWaveLanPacket( _end, (const struct ieee_802_11_header*) data, this );
break;
case DLT_PRISM_HEADER:
odebug << "OPacket::OPacket(): Received Packet. Datalink = PRISM_HEADER" << oendl;
new OPrismHeaderPacket( _end, (const struct prism_hdr*) (unsigned char*) data, this );
break;
default:
owarn << "OPacket::OPacket(): Received Packet over unsupported datalink, type " << datalink << "!" << oendl;
}
}
OPacket::~OPacket()
{
+ qDebug( "OPacket::~OPacket( %s )", name() );
}
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();
}
}
QString OPacket::dumpStructure() const
{
return "[ |" + _dumpStructure( const_cast<QObjectList*>( this->children() ) ) + " ]";
}
QString OPacket::_dumpStructure( QObjectList* l ) const
{
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;
}
@@ -970,207 +971,219 @@ OWaveLanManagementChallenge::OWaveLanManagementChallenge( const unsigned char* e
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 )
+ :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;
@@ -1228,126 +1241,126 @@ bool OPacketCapturer::open( const QString& name )
// open libpcap
pcap_t* handle = pcap_open_live( const_cast<char*>( (const char*) name ), 1024, 0, 0, &_errbuf[0] );
if ( !handle )
{
owarn << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl;
return false;
}
odebug << "OPacketCapturer::open(): libpcap [" << name << "] opened successfully." << oendl;
_pch = handle;
_open = true;
_stats.clear();
// in case we have an application object, create a socket notifier
if ( qApp ) //TODO: I don't like this here...
{
_sn = new QSocketNotifier( fileno(), QSocketNotifier::Read );
connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
}
return true;
}
bool OPacketCapturer::openDumpFile( const QString& filename )
{
pcap_dumper_t* dump = pcap_dump_open( _pch, const_cast<char*>( (const char*) filename ) );
if ( !dump )
{
owarn << "OPacketCapturer::open(): can't open dump with '" << filename << "': " << _errbuf << oendl;
return false;
}
odebug << "OPacketCapturer::open(): dump [" << filename << "] opened successfully." << oendl;
_pcd = dump;
return true;
}
bool OPacketCapturer::open( const QFile& file )
{
QString name = file.name();
if ( _open )
{
close();
if ( name == _name ) // ignore opening an already openend device
{
return true;
}
else // close the last opened device
{
close();
}
}
_name = name;
pcap_t* handle = pcap_open_offline( const_cast<char*>( (const char*) name ), &_errbuf[0] );
if ( handle )
{
odebug << "OPacketCapturer::open(): libpcap opened successfully." << oendl;
_pch = handle;
_open = true;
// in case we have an application object, create a socket notifier
if ( qApp )
{
_sn = new QSocketNotifier( fileno(), QSocketNotifier::Read );
connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
}
return true;
}
else
{
odebug << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl;
return false;
}
}
bool OPacketCapturer::isOpen() const
{
return _open;
}
void OPacketCapturer::readyToReceive()
{
odebug << "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(p)'" << oendl;
OPacket* p = next();
emit receivedPacket( p );
- // emit is synchronous - packet has been dealt with, now it's safe to delete
- delete p;
+ // 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 ) );
}
}
}