-rw-r--r-- | libopie2/opienet/opcap.cpp | 6 |
1 files changed, 2 insertions, 4 deletions
diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 8ec4f47..8184f21 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -1,554 +1,552 @@ /* This file is part of the Opie Project Copyright (C) 2003-2004 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. */ #include "udp_ports.h" #include "opcap.h" /* OPIE */ #include <opie2/odebug.h> using namespace Opie::Core; /* QT */ #include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects) #include <qsocketnotifier.h> #include <qobjectlist.h> /* STD */ #include <sys/time.h> #include <sys/types.h> #include <assert.h> #include <unistd.h> #include <string.h> namespace Opie { namespace Net { /*====================================================================================== * OPacket *======================================================================================*/ OPacket::OPacket( int datalink, packetheaderstruct header, const unsigned char* data, QObject* parent ) :QObject( parent, "Generic" ), _hdr( header ), _data( 0 ) { _data = new unsigned char[ header.len ]; assert( _data ); memcpy( const_cast<unsigned char*>(_data), data, header.len ); // We have to copy the data structure here, because the 'data' pointer handed by libpcap // points to an internal region which is reused by lipcap. odebug << "OPacket: Length = " << header.len << ", Caplen = " << header.caplen << oendl; _end = (unsigned char*) _data + header.len; 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() { odebug << "~OPacket( " << name() << " )" << oendl; delete _data; } 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 str( "000:" ); 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 ); + tmp.sprintf( "%03X:", 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; } QTextStream& operator<<( QTextStream& s, const OPacket& p ) { s << p.dumpStructure(); } /*====================================================================================== * OEthernetPacket *======================================================================================*/ OEthernetPacket::OEthernetPacket( const unsigned char* end, const struct ether_header* data, QObject* parent ) :QObject( parent, "Ethernet" ), _ether( data ) { odebug << "Source = " << sourceAddress().toString() << oendl; odebug << "Destination = " << destinationAddress().toString() << oendl; if ( sourceAddress() == OMacAddress::broadcast ) odebug << "Source is broadcast address" << oendl; if ( destinationAddress() == OMacAddress::broadcast ) odebug << "Destination is broadcast address" << oendl; switch ( type() ) { case ETHERTYPE_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; case ETHERTYPE_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break; case ETHERTYPE_REVARP: { odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" << oendl; break; } default: odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" << oendl; } } OEthernetPacket::~OEthernetPacket() { } OMacAddress OEthernetPacket::sourceAddress() const { return OMacAddress( _ether->ether_shost ); } OMacAddress OEthernetPacket::destinationAddress() const { return OMacAddress( _ether->ether_dhost ); } int OEthernetPacket::type() const { return ntohs( _ether->ether_type ); } /*====================================================================================== * OIPPacket *======================================================================================*/ OIPPacket::OIPPacket( const unsigned char* end, const struct iphdr* data, QObject* parent ) :QObject( parent, "IP" ), _iphdr( data ) { odebug << "OIPPacket::OIPPacket(): decoding IP header..." << oendl; odebug << "FromAddress = " << fromIPAddress().toString() << oendl; odebug << " toAddress = " << toIPAddress().toString() << oendl; switch ( protocol() ) { case IPPROTO_UDP: new OUDPPacket( end, (const struct udphdr*) (data+1), this ); break; case IPPROTO_TCP: new OTCPPacket( end, (const struct tcphdr*) (data+1), this ); break; default: odebug << "OIPPacket::OIPPacket(): unknown IP protocol, type = " << protocol() << oendl; } } OIPPacket::~OIPPacket() { } QHostAddress OIPPacket::fromIPAddress() const { return EXTRACT_32BITS( &_iphdr->saddr ); } QHostAddress OIPPacket::toIPAddress() const { return EXTRACT_32BITS( &_iphdr->saddr ); } int OIPPacket::tos() const { return _iphdr->tos; } int OIPPacket::len() const { return EXTRACT_16BITS( &_iphdr->tot_len ); } int OIPPacket::id() const { return EXTRACT_16BITS( &_iphdr->id ); } int OIPPacket::offset() const { return EXTRACT_16BITS( &_iphdr->frag_off ); } int OIPPacket::ttl() const { return _iphdr->ttl; } int OIPPacket::protocol() const { return _iphdr->protocol; } int OIPPacket::checksum() const { return EXTRACT_16BITS( &_iphdr->check ); } /*====================================================================================== * OARPPacket *======================================================================================*/ OARPPacket::OARPPacket( const unsigned char* end, const struct myarphdr* data, QObject* parent ) :QObject( parent, "ARP" ), _arphdr( data ) { odebug << "OARPPacket::OARPPacket(): decoding ARP header..." << oendl; odebug << "ARP type seems to be " << EXTRACT_16BITS( &_arphdr->ar_op ) << " = " << type() << oendl; odebug << "Sender: MAC " << senderMacAddress().toString() << " = IP " << senderIPV4Address().toString() << oendl; odebug << "Target: MAC " << targetMacAddress().toString() << " = IP " << targetIPV4Address().toString() << oendl; } OARPPacket::~OARPPacket() { } QString OARPPacket::type() const { switch ( EXTRACT_16BITS( &_arphdr->ar_op ) ) { case 1: return "REQUEST"; case 2: return "REPLY"; case 3: return "RREQUEST"; case 4: return "RREPLY"; case 8: return "InREQUEST"; case 9: return "InREPLY"; case 10: return "NAK"; default: owarn << "OARPPacket::type(): invalid ARP type!" << oendl; return "<unknown>"; } } QHostAddress OARPPacket::senderIPV4Address() const { return EXTRACT_32BITS( &_arphdr->ar_sip ); } QHostAddress OARPPacket::targetIPV4Address() const { return EXTRACT_32BITS( &_arphdr->ar_tip ); } OMacAddress OARPPacket::senderMacAddress() const { return OMacAddress( _arphdr->ar_sha ); } OMacAddress OARPPacket::targetMacAddress() const { return OMacAddress( _arphdr->ar_tha ); } /*====================================================================================== * OUDPPacket *======================================================================================*/ OUDPPacket::OUDPPacket( const unsigned char* end, const struct udphdr* data, QObject* parent ) :QObject( parent, "UDP" ), _udphdr( data ) { odebug << "OUDPPacket::OUDPPacket(): decoding UDP header..." << oendl; odebug << "fromPort = " << fromPort() << oendl; odebug << " toPort = " << toPort() << oendl; // TODO: Make this a case or a hash if we know more udp protocols if ( fromPort() == UDP_PORT_BOOTPS || fromPort() == UDP_PORT_BOOTPC || toPort() == UDP_PORT_BOOTPS || toPort() == UDP_PORT_BOOTPC ) { odebug << "seems to be part of a DHCP conversation => creating DHCP packet." << oendl; new ODHCPPacket( end, (const struct dhcp_packet*) (data+1), this ); } } OUDPPacket::~OUDPPacket() { } int OUDPPacket::fromPort() const { return EXTRACT_16BITS( &_udphdr->source ); } int OUDPPacket::toPort() const { return EXTRACT_16BITS( &_udphdr->dest ); } int OUDPPacket::length() const { return EXTRACT_16BITS( &_udphdr->len ); } int OUDPPacket::checksum() const { return EXTRACT_16BITS( &_udphdr->check ); } /*====================================================================================== * ODHCPPacket *======================================================================================*/ ODHCPPacket::ODHCPPacket( const unsigned char* end, const struct dhcp_packet* data, QObject* parent ) :QObject( parent, "DHCP" ), _dhcphdr( data ) { odebug << "ODHCPPacket::ODHCPPacket(): decoding DHCP information..." << oendl; odebug << "DHCP opcode seems to be " << _dhcphdr->op << ": " << ( isRequest() ? "REQUEST" : "REPLY" ) << oendl; odebug << "clientAddress = " << clientAddress().toString() << oendl; odebug << " yourAddress = " << yourAddress().toString() << oendl; odebug << "serverAddress = " << serverAddress().toString() << oendl; odebug << " relayAddress = " << relayAddress().toString() << oendl; odebug << "parsing DHCP options..." << oendl; _type = 0; const unsigned char* option = &_dhcphdr->options[4]; char tag = -1; char len = -1; while ( ( tag = *option++ ) != -1 /* end of option field */ ) { len = *option++; odebug << "recognized DHCP option #" << tag << ", length " << len << oendl; if ( tag == DHO_DHCP_MESSAGE_TYPE ) _type = *option; option += len; if ( option >= end ) { owarn << "DHCP parsing ERROR: sanity check says the packet is at its end!" << oendl; break; } } odebug << "DHCP type seems to be << " << type() << oendl; } ODHCPPacket::~ODHCPPacket() { } bool ODHCPPacket::isRequest() const { return ( _dhcphdr->op == 01 ); } bool ODHCPPacket::isReply() const { return ( _dhcphdr->op == 02 ); } QString ODHCPPacket::type() const { switch ( _type ) { case 1: return "DISCOVER"; case 2: return "OFFER"; case 3: return "REQUEST"; case 4: return "DECLINE"; case 5: return "ACK"; case 6: return "NAK"; case 7: return "RELEASE"; case 8: return "INFORM"; default: owarn << "ODHCPPacket::type(): invalid DHCP type " << _dhcphdr->op << oendl; 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 ) |