Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

opcap.cpp

Go to the documentation of this file.
00001 /*
00002                              This file is part of the Opie Project
00003                              Copyright (C) 2003-2004 by Michael 'Mickey' Lauer <mickey@Vanille.de>
00004               =.
00005             .=l.
00006            .>+-=
00007  _;:,     .>    :=|.         This program is free software; you can
00008 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00009 :`=1 )Y*s>-.--   :           the terms of the GNU Library General Public
00010 .="- .-=="i,     .._         License as published by the Free Software
00011  - .   .-<_>     .<>         Foundation; version 2 of the License.
00012      ._= =}       :
00013     .%`+i>       _;_.
00014     .i_,=:_.      -<s.       This program is distributed in the hope that
00015      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00016     : ..    .:,     . . .    without even the implied warranty of
00017     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00018   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00019 ..}^=.=       =       ;      Library General Public License for more
00020 ++=   -.     .`     .:       details.
00021  :     =  ...= . :.=-
00022  -.   .:....=;==+<;          You should have received a copy of the GNU
00023   -_. . .   )=.  =           Library General Public License along with
00024     --        :-=`           this library; see the file COPYING.LIB.
00025                              If not, write to the Free Software Foundation,
00026                              Inc., 59 Temple Place - Suite 330,
00027                              Boston, MA 02111-1307, USA.
00028 
00029 */
00030 
00031 #include "udp_ports.h"
00032 #include "opcap.h"
00033 
00034 /* OPIE */
00035 #include <opie2/odebug.h>
00036 using namespace Opie::Core;
00037 
00038 /* QT */
00039 #include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects)
00040 #include <qsocketnotifier.h>
00041 #include <qobjectlist.h>
00042 
00043 /* STD */
00044 #include <sys/time.h>
00045 #include <sys/types.h>
00046 #include <assert.h>
00047 #include <unistd.h>
00048 #include <string.h>
00049 
00050 namespace Opie {
00051 namespace Net  {
00052 
00053 /*======================================================================================
00054  * OPacket
00055  *======================================================================================*/
00056 
00057 OPacket::OPacket( int datalink, packetheaderstruct header, const unsigned char* data, QObject* parent )
00058         :QObject( parent, "Generic" ), _hdr( header ), _data( 0 )
00059 {
00060 
00061     _data = new unsigned char[ header.len ];
00062     assert( _data );
00063     memcpy( const_cast<unsigned char*>(_data), data, header.len );
00064     // We have to copy the data structure here, because the 'data' pointer handed by libpcap
00065     // points to an internal region which is reused by lipcap.
00066     odebug << "OPacket: Length = " << header.len << ", Caplen = " << header.caplen << oendl;
00067     _end = (unsigned char*) _data + header.len;
00068 
00069     switch ( datalink )
00070     {
00071         case DLT_EN10MB:
00072             odebug << "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" << oendl;
00073             new OEthernetPacket( _end, (const struct ether_header*) _data, this );
00074             break;
00075 
00076         case DLT_IEEE802_11:
00077             odebug << "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" << oendl;
00078             new OWaveLanPacket( _end, (const struct ieee_802_11_header*) _data, this );
00079             break;
00080 
00081         case DLT_PRISM_HEADER:
00082             odebug << "OPacket::OPacket(): Received Packet. Datalink = PRISM_HEADER" << oendl;
00083             new OPrismHeaderPacket( _end, (const struct prism_hdr*) (unsigned char*) _data, this );
00084             break;
00085 
00086         default:
00087             owarn << "OPacket::OPacket(): Received Packet over unsupported datalink, type " << datalink << "!" << oendl;
00088     }
00089 }
00090 
00091 
00092 OPacket::~OPacket()
00093 {
00094     odebug << "~OPacket( " << name() << " )" << oendl;
00095     delete [] _data;
00096 }
00097 
00098 
00099 timevalstruct OPacket::timeval() const
00100 {
00101     return _hdr.ts;
00102 }
00103 
00104 
00105 int OPacket::caplen() const
00106 {
00107     return _hdr.caplen;
00108 }
00109 
00110 
00111 void OPacket::updateStats( QMap<QString,int>& stats, QObjectList* l )
00112 {
00113     if (!l) return;
00114     QObject* o = l->first();
00115     while ( o )
00116     {
00117         stats[o->name()]++;
00118         updateStats( stats, const_cast<QObjectList*>( o->children() ) );
00119         o = l->next();
00120     }
00121 }
00122 
00123 
00124 QString OPacket::dumpStructure() const
00125 {
00126     return "[ |" + _dumpStructure(  const_cast<QObjectList*>( this->children() ) ) + " ]";
00127 }
00128 
00129 
00130 QString OPacket::_dumpStructure( QObjectList* l ) const
00131 {
00132     if (!l) return QString::null;
00133     QObject* o = l->first();
00134     QString str(" ");
00135 
00136     while ( o )
00137     {
00138         str.append( o->name() );
00139         str.append( " |" );
00140         str += _dumpStructure( const_cast<QObjectList*>( o->children() ) );
00141         o = l->next();
00142     }
00143     return str;
00144 }
00145 
00146 QString OPacket::dump( int bpl ) const
00147 {
00148     static int index = 0;
00149     index++;
00150     int len = _hdr.caplen;
00151     QString str( "000:" );
00152     QString tmp;
00153     QString bytes;
00154     QString chars;
00155 
00156     for ( int i = 0; i < len; ++i )
00157     {
00158         tmp.sprintf( "%02X ", _data[i] ); bytes.append( tmp );
00159         if ( (_data[i] > 31) && (_data[i]<128) ) chars.append( _data[i] );
00160         else chars.append( '.' );
00161 
00162         if ( !((i+1) % bpl) )
00163         {
00164             str.append( bytes );
00165             str.append( ' ' );
00166             str.append( chars );
00167             str.append( '\n' );
00168             tmp.sprintf( "%03X:", i+1 ); str.append( tmp );
00169             bytes = "";
00170             chars = "";
00171         }
00172 
00173     }
00174     if ( (len % bpl) )
00175     {
00176         str.append( bytes.leftJustify( 1 + 3*bpl ) );
00177         str.append( chars );
00178     }
00179     str.append( '\n' );
00180     return str;
00181 }
00182 
00183 
00184 int OPacket::len() const
00185 {
00186     return _hdr.len;
00187 }
00188 
00189 
00190 QTextStream& operator<<( QTextStream& s, const OPacket& p )
00191 {
00192     s << p.dumpStructure();
00193     return s;
00194 }
00195 
00196 
00197 /*======================================================================================
00198  * OEthernetPacket
00199  *======================================================================================*/
00200 
00201 OEthernetPacket::OEthernetPacket( const unsigned char* end, const struct ether_header* data, QObject* parent )
00202                 :QObject( parent, "Ethernet" ), _ether( data )
00203 {
00204 
00205     odebug << "Source = " << sourceAddress().toString() << oendl;
00206     odebug << "Destination = " << destinationAddress().toString() << oendl;
00207 
00208     if ( sourceAddress() == OMacAddress::broadcast )
00209         odebug << "Source is broadcast address" << oendl;
00210     if ( destinationAddress() == OMacAddress::broadcast )
00211         odebug << "Destination is broadcast address" << oendl;
00212 
00213     switch ( type() )
00214     {
00215         case ETHERTYPE_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break;
00216         case ETHERTYPE_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break;
00217         case ETHERTYPE_REVARP: { odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" << oendl; break; }
00218         default: odebug << "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" << oendl;
00219     }
00220 
00221 }
00222 
00223 
00224 OEthernetPacket::~OEthernetPacket()
00225 {
00226 }
00227 
00228 
00229 OMacAddress OEthernetPacket::sourceAddress() const
00230 {
00231     return OMacAddress( _ether->ether_shost );
00232 }
00233 
00234 
00235 OMacAddress OEthernetPacket::destinationAddress() const
00236 {
00237     return OMacAddress( _ether->ether_dhost );
00238 }
00239 
00240 int OEthernetPacket::type() const
00241 {
00242     return ntohs( _ether->ether_type );
00243 }
00244 
00245 
00246 /*======================================================================================
00247  * OIPPacket
00248  *======================================================================================*/
00249 
00250 
00251 OIPPacket::OIPPacket( const unsigned char* end, const struct iphdr* data, QObject* parent )
00252           :QObject( parent, "IP" ), _iphdr( data )
00253 {
00254     odebug << "OIPPacket::OIPPacket(): decoding IP header..." << oendl;
00255 
00256     odebug << "FromAddress = " << fromIPAddress().toString() << oendl;
00257     odebug << "  toAddress = " << toIPAddress().toString() << oendl;
00258 
00259     switch ( protocol() )
00260     {
00261         case IPPROTO_UDP: new OUDPPacket( end, (const struct udphdr*) (data+1), this ); break;
00262         case IPPROTO_TCP: new OTCPPacket( end, (const struct tcphdr*) (data+1), this ); break;
00263         default: odebug << "OIPPacket::OIPPacket(): unknown IP protocol, type = " << protocol() << oendl;
00264     }
00265 
00266 }
00267 
00268 OIPPacket::~OIPPacket()
00269 {
00270 }
00271 
00272 
00273 QHostAddress OIPPacket::fromIPAddress() const
00274 {
00275     return EXTRACT_32BITS( &_iphdr->saddr );
00276 }
00277 
00278 
00279 QHostAddress OIPPacket::toIPAddress() const
00280 {
00281     return EXTRACT_32BITS( &_iphdr->saddr );
00282 }
00283 
00284 
00285 int OIPPacket::tos() const
00286 {
00287     return _iphdr->tos;
00288 }
00289 
00290 
00291 int OIPPacket::len() const
00292 {
00293     return EXTRACT_16BITS( &_iphdr->tot_len );
00294 }
00295 
00296 
00297 int OIPPacket::id() const
00298 {
00299     return EXTRACT_16BITS( &_iphdr->id );
00300 }
00301 
00302 
00303 int OIPPacket::offset() const
00304 {
00305     return EXTRACT_16BITS( &_iphdr->frag_off );
00306 }
00307 
00308 
00309 int OIPPacket::ttl() const
00310 {
00311     return _iphdr->ttl;
00312 }
00313 
00314 
00315 int OIPPacket::protocol() const
00316 {
00317     return _iphdr->protocol;
00318 }
00319 
00320 
00321 int OIPPacket::checksum() const
00322 {
00323     return EXTRACT_16BITS( &_iphdr->check );
00324 }
00325 
00326 /*======================================================================================
00327  * OARPPacket
00328  *======================================================================================*/
00329 
00330 
00331 OARPPacket::OARPPacket( const unsigned char* /*end*/, const struct myarphdr* data, QObject* parent )
00332            :QObject( parent, "ARP" ), _arphdr( data )
00333 {
00334     odebug << "OARPPacket::OARPPacket(): decoding ARP header..." << oendl;
00335     odebug << "ARP type seems to be " << EXTRACT_16BITS( &_arphdr->ar_op ) << " = " << type() << oendl;
00336     odebug << "Sender: MAC " << senderMacAddress().toString() << " = IP " << senderIPV4Address().toString() << oendl;
00337     odebug << "Target: MAC " << targetMacAddress().toString() << " = IP " << targetIPV4Address().toString() << oendl;
00338 }
00339 
00340 
00341 OARPPacket::~OARPPacket()
00342 {
00343 }
00344 
00345 
00346 QString OARPPacket::type() const
00347 {
00348     switch ( EXTRACT_16BITS( &_arphdr->ar_op ) )
00349     {
00350         case 1: return "REQUEST";
00351         case 2: return "REPLY";
00352         case 3: return "RREQUEST";
00353         case 4: return "RREPLY";
00354         case 8: return "InREQUEST";
00355         case 9: return "InREPLY";
00356         case 10: return "NAK";
00357         default: owarn << "OARPPacket::type(): invalid ARP type!" << oendl; return "<unknown>";
00358     }
00359 }
00360 
00361 
00362 QHostAddress OARPPacket::senderIPV4Address() const
00363 {
00364     return EXTRACT_32BITS( &_arphdr->ar_sip );
00365 }
00366 
00367 
00368 QHostAddress OARPPacket::targetIPV4Address() const
00369 {
00370     return EXTRACT_32BITS( &_arphdr->ar_tip );
00371 }
00372 
00373 
00374 OMacAddress OARPPacket::senderMacAddress() const
00375 {
00376     return OMacAddress( _arphdr->ar_sha );
00377 }
00378 
00379 
00380 OMacAddress OARPPacket::targetMacAddress() const
00381 {
00382     return OMacAddress( _arphdr->ar_tha );
00383 }
00384 
00385 
00386 /*======================================================================================
00387  * OUDPPacket
00388  *======================================================================================*/
00389 
00390 
00391 OUDPPacket::OUDPPacket( const unsigned char* end, const struct udphdr* data, QObject* parent )
00392            :QObject( parent, "UDP" ), _udphdr( data )
00393 
00394 {
00395     odebug << "OUDPPacket::OUDPPacket(): decoding UDP header..." << oendl;
00396     odebug << "fromPort = " << fromPort() << oendl;
00397     odebug << "  toPort = " << toPort() << oendl;
00398 
00399     // TODO: Make this a case or a hash if we know more udp protocols
00400 
00401     if ( fromPort() == UDP_PORT_BOOTPS || fromPort() == UDP_PORT_BOOTPC ||
00402          toPort() == UDP_PORT_BOOTPS || toPort() == UDP_PORT_BOOTPC )
00403     {
00404         odebug << "seems to be part of a DHCP conversation => creating DHCP packet." << oendl;
00405         new ODHCPPacket( end, (const struct dhcp_packet*) (data+1), this );
00406     }
00407 }
00408 
00409 
00410 OUDPPacket::~OUDPPacket()
00411 {
00412 }
00413 
00414 
00415 int OUDPPacket::fromPort() const
00416 {
00417     return EXTRACT_16BITS( &_udphdr->source );
00418 }
00419 
00420 
00421 int OUDPPacket::toPort() const
00422 {
00423     return EXTRACT_16BITS( &_udphdr->dest );
00424 }
00425 
00426 
00427 int OUDPPacket::length() const
00428 {
00429     return EXTRACT_16BITS( &_udphdr->len );
00430 }
00431 
00432 
00433 int OUDPPacket::checksum() const
00434 {
00435     return EXTRACT_16BITS( &_udphdr->check );
00436 }
00437 
00438 
00439 /*======================================================================================
00440  * ODHCPPacket
00441  *======================================================================================*/
00442 
00443 
00444 ODHCPPacket::ODHCPPacket( const unsigned char* end, const struct dhcp_packet* data, QObject* parent )
00445            :QObject( parent, "DHCP" ), _dhcphdr( data )
00446 
00447 {
00448     odebug << "ODHCPPacket::ODHCPPacket(): decoding DHCP information..." << oendl;
00449     odebug << "DHCP opcode seems to be " << _dhcphdr->op << ": " << ( isRequest() ? "REQUEST" : "REPLY" ) << oendl;
00450     odebug << "clientAddress = " << clientAddress().toString() << oendl;
00451     odebug << "  yourAddress = " << yourAddress().toString() << oendl;
00452     odebug << "serverAddress = " << serverAddress().toString() << oendl;
00453     odebug << " relayAddress = " << relayAddress().toString() << oendl;
00454     odebug << "parsing DHCP options..." << oendl;
00455 
00456     _type = 0;
00457 
00458     const unsigned char* option = &_dhcphdr->options[4];
00459     char tag = -1;
00460     char len = -1;
00461 
00462     while ( ( tag = *option++ ) != -1 /* end of option field */ )
00463     {
00464         len = *option++;
00465         odebug << "recognized DHCP option #" << tag << ", length " << len << oendl;
00466 
00467         if ( tag == DHO_DHCP_MESSAGE_TYPE )
00468             _type = *option;
00469 
00470         option += len;
00471         if ( option >= end )
00472         {
00473             owarn << "DHCP parsing ERROR: sanity check says the packet is at its end!" << oendl;
00474             break;
00475         }
00476     }
00477 
00478     odebug << "DHCP type seems to be << " << type() << oendl;
00479 }
00480 
00481 
00482 ODHCPPacket::~ODHCPPacket()
00483 {
00484 }
00485 
00486 
00487 bool ODHCPPacket::isRequest() const
00488 {
00489     return ( _dhcphdr->op == 01 );
00490 }
00491 
00492 
00493 bool ODHCPPacket::isReply() const
00494 {
00495     return ( _dhcphdr->op == 02 );
00496 }
00497 
00498 
00499 QString ODHCPPacket::type() const
00500 {
00501     switch ( _type )
00502     {
00503         case 1: return "DISCOVER";
00504         case 2: return "OFFER";
00505         case 3: return "REQUEST";
00506         case 4: return "DECLINE";
00507         case 5: return "ACK";
00508         case 6: return "NAK";
00509         case 7: return "RELEASE";
00510         case 8: return "INFORM";
00511         default: owarn << "ODHCPPacket::type(): invalid DHCP type " << _dhcphdr->op << oendl; return "<unknown>";
00512     }
00513 }
00514 
00515 
00516 QHostAddress ODHCPPacket::clientAddress() const
00517 {
00518     return EXTRACT_32BITS( &_dhcphdr->ciaddr );
00519 }
00520 
00521 
00522 QHostAddress ODHCPPacket::yourAddress() const
00523 {
00524     return EXTRACT_32BITS( &_dhcphdr->yiaddr );
00525 }
00526 
00527 
00528 QHostAddress ODHCPPacket::serverAddress() const
00529 {
00530     return EXTRACT_32BITS( &_dhcphdr->siaddr );
00531 }
00532 
00533 
00534 QHostAddress ODHCPPacket::relayAddress() const
00535 {
00536     return EXTRACT_32BITS( &_dhcphdr->giaddr );
00537 }
00538 
00539 
00540 OMacAddress ODHCPPacket::clientMacAddress() const
00541 {
00542     return OMacAddress( _dhcphdr->chaddr );
00543 }
00544 
00545 
00546 /*======================================================================================
00547  * OTCPPacket
00548  *======================================================================================*/
00549 
00550 
00551 OTCPPacket::OTCPPacket( const unsigned char* /*end*/, const struct tcphdr* data, QObject* parent )
00552            :QObject( parent, "TCP" ), _tcphdr( data )
00553 
00554 {
00555     odebug << "OTCPPacket::OTCPPacket(): decoding TCP header..." << oendl;
00556 }
00557 
00558 
00559 OTCPPacket::~OTCPPacket()
00560 {
00561 }
00562 
00563 
00564 int OTCPPacket::fromPort() const
00565 {
00566     return EXTRACT_16BITS( &_tcphdr->source );
00567 }
00568 
00569 
00570 int OTCPPacket::toPort() const
00571 {
00572     return EXTRACT_16BITS( &_tcphdr->dest );
00573 }
00574 
00575 
00576 int OTCPPacket::seq() const
00577 {
00578     return EXTRACT_16BITS( &_tcphdr->seq );
00579 }
00580 
00581 
00582 int OTCPPacket::ack() const
00583 {
00584     return EXTRACT_16BITS( &_tcphdr->ack_seq );
00585 }
00586 
00587 
00588 int OTCPPacket::window() const
00589 {
00590     return EXTRACT_16BITS( &_tcphdr->window );
00591 }
00592 
00593 
00594 int OTCPPacket::checksum() const
00595 {
00596     return EXTRACT_16BITS( &_tcphdr->check );
00597 }
00598 
00599 /*======================================================================================
00600  * OPrismHeaderPacket
00601  *======================================================================================*/
00602 
00603 
00604 OPrismHeaderPacket::OPrismHeaderPacket( const unsigned char* end, const struct prism_hdr* data, QObject* parent )
00605                 :QObject( parent, "Prism" ), _header( data )
00606 
00607 {
00608     odebug << "OPrismHeaderPacket::OPrismHeaderPacket(): decoding PRISM header..." << oendl;
00609 
00610     odebug << "Signal Strength = " << data->signal.data << oendl;
00611 
00612     new OWaveLanPacket( end, (const struct ieee_802_11_header*) (data+1), this );
00613 }
00614 
00615 OPrismHeaderPacket::~OPrismHeaderPacket()
00616 {
00617 }
00618 
00619 
00620 unsigned int OPrismHeaderPacket::signalStrength() const
00621 {
00622     return _header->signal.data;
00623 }
00624 
00625 /*======================================================================================
00626  * OWaveLanPacket
00627  *======================================================================================*/
00628 
00629 
00630 OWaveLanPacket::OWaveLanPacket( const unsigned char* end, const struct ieee_802_11_header* data, QObject* parent )
00631                 :QObject( parent, "802.11" ), _wlanhdr( data )
00632 
00633 {
00634     odebug << "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." << oendl;
00635     odebug << "type = " << type() << oendl;
00636     odebug << "subType = " << subType() << oendl;
00637     odebug << "duration = " << duration() << oendl;
00638     odebug << "powermanagement = " << usesPowerManagement() << oendl;
00639     odebug << "payload is encrypted = " << ( usesWep() ? "yes" : "no" ) << oendl;
00640     odebug << "MAC1 = " << macAddress1().toString() << oendl;
00641     odebug << "MAC2 = " << macAddress2().toString() << oendl;
00642     odebug << "MAC3 = " << macAddress3().toString() << oendl;
00643     odebug << "MAC4 = " << macAddress4().toString() << oendl;
00644 
00645     switch ( type() )
00646     {
00647         case T_MGMT: new OWaveLanManagementPacket( end, (const struct ieee_802_11_mgmt_header*) data, this ); break;
00648         case T_DATA: new OWaveLanDataPacket( end, (const struct ieee_802_11_data_header*) data, this ); break;
00649         case T_CTRL: new OWaveLanControlPacket( end, (const struct ieee_802_11_control_header*) data, this ); break;
00650         default: odebug << "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown major type = " << type() << oendl;
00651     }
00652 }
00653 
00654 OWaveLanPacket::~OWaveLanPacket()
00655 {
00656 }
00657 
00658 
00659 int OWaveLanPacket::duration() const
00660 {
00661     return _wlanhdr->duration;
00662 }
00663 
00664 
00665 OMacAddress OWaveLanPacket::macAddress1() const
00666 {
00667     return OMacAddress( _wlanhdr->mac1 );
00668 }
00669 
00670 
00671 OMacAddress OWaveLanPacket::macAddress2() const
00672 {
00673     return OMacAddress( _wlanhdr->mac2 );
00674 }
00675 
00676 
00677 OMacAddress OWaveLanPacket::macAddress3() const
00678 {
00679     return OMacAddress( _wlanhdr->mac3 );
00680 }
00681 
00682 
00683 OMacAddress OWaveLanPacket::macAddress4() const
00684 {
00685     return OMacAddress( _wlanhdr->mac4 );
00686 }
00687 
00688 
00689 int OWaveLanPacket::subType() const
00690 {
00691     return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00692 }
00693 
00694 
00695 int OWaveLanPacket::type() const
00696 {
00697     return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00698 }
00699 
00700 
00701 int OWaveLanPacket::version() const
00702 {
00703     return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00704 }
00705 
00706 
00707 bool OWaveLanPacket::fromDS() const
00708 {
00709     return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00710 }
00711 
00712 
00713 bool OWaveLanPacket::toDS() const
00714 {
00715     return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00716 }
00717 
00718 
00719 bool OWaveLanPacket::usesPowerManagement() const
00720 {
00721     return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00722 }
00723 
00724 
00725 bool OWaveLanPacket::usesWep() const
00726 {
00727     return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) );
00728 }
00729 
00730 
00731 /*======================================================================================
00732  * OWaveLanManagementPacket
00733  *======================================================================================*/
00734 
00735 OWaveLanManagementPacket::OWaveLanManagementPacket( const unsigned char* end, const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent )
00736                 :QObject( parent, "802.11 Management" ), _header( data ),
00737                 _body( (const struct ieee_802_11_mgmt_body*) (data+1) )
00738 {
00739     odebug << "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." << oendl;
00740     odebug << "Detected subtype is " << managementType() << oendl;
00741 
00742     // Grab tagged values.
00743     // Beacons contain a 12 byte long fixed parameters set before the tagged parameters come,
00744     // Other management frames don't - which is why we have to inspect the subtype here.
00745 
00746     const unsigned char* ptr = managementType() == "Beacon" ?  (const unsigned char*) (_body+1) : (const unsigned char*) (_header+1);
00747 
00748     while (ptr < end)
00749     {
00750         switch ( *ptr )
00751         {
00752             case E_SSID: new OWaveLanManagementSSID( end, (struct ssid_t*) ptr, this ); break;
00753             case E_FH: new OWaveLanManagementFH( end, (struct fh_t*) ptr, this ); break;
00754             case E_DS: new OWaveLanManagementDS( end, (struct ds_t*) ptr, this ); break;
00755             case E_RATES: new OWaveLanManagementRates( end, (struct rates_t*) ptr, this ); break;
00756             case E_CF: new OWaveLanManagementCF( end, (struct cf_t*) ptr, this ); break;
00757             case E_TIM: new OWaveLanManagementTim( end, (struct tim_t*) ptr, this ); break;
00758             case E_IBSS: new OWaveLanManagementIBSS( end, (struct ibss_t*) ptr, this ); break;
00759             case E_CHALLENGE: new OWaveLanManagementChallenge( end, (struct challenge_t*) ptr, this ); break;
00760         }
00761         ptr+= ( ( struct ssid_t* ) ptr )->length; // skip length of tagged value
00762         ptr+= 2; // skip tag ID and length
00763     }
00764 }
00765 
00766 
00767 OWaveLanManagementPacket::~OWaveLanManagementPacket()
00768 {
00769 }
00770 
00771 
00772 QString OWaveLanManagementPacket::managementType() const
00773 {
00774     switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) )
00775     {
00776         case ST_ASSOC_REQUEST: return "AssociationRequest"; break;
00777         case ST_ASSOC_RESPONSE: return "AssociationResponse"; break;
00778         case ST_REASSOC_REQUEST: return "ReassociationRequest"; break;
00779         case ST_REASSOC_RESPONSE: return "ReassociationResponse"; break;
00780         case ST_PROBE_REQUEST: return "ProbeRequest"; break;
00781         case ST_PROBE_RESPONSE: return "ProbeResponse"; break;
00782         case ST_BEACON: return "Beacon"; break;
00783         case ST_ATIM: return "Atim"; break;
00784         case ST_DISASSOC: return "Disassociation"; break;
00785         case ST_AUTH: return "Authentication"; break;
00786         case ST_DEAUTH: return "Deathentication"; break;
00787         default: owarn << "OWaveLanManagementPacket::managementType(): unhandled subtype " << FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) << oendl; return "Unknown";
00788     }
00789 }
00790 
00791 
00792 int OWaveLanManagementPacket::beaconInterval() const
00793 {
00794     return EXTRACT_LE_16BITS( &_body->beacon_interval );
00795 }
00796 
00797 
00798 int OWaveLanManagementPacket::capabilities() const
00799 {
00800     return EXTRACT_LE_16BITS( &_body->capability_info );
00801 }
00802 
00803 
00804 bool OWaveLanManagementPacket::canESS() const
00805 {
00806     return CAPABILITY_ESS( EXTRACT_LE_16BITS( &_body->capability_info ) );
00807 }
00808 
00809 
00810 bool OWaveLanManagementPacket::canIBSS() const
00811 {
00812     return CAPABILITY_IBSS( EXTRACT_LE_16BITS( &_body->capability_info ) );
00813 }
00814 
00815 
00816 bool OWaveLanManagementPacket::canCFP() const
00817 {
00818     return CAPABILITY_CFP( EXTRACT_LE_16BITS( &_body->capability_info ) );
00819 }
00820 
00821 
00822 bool OWaveLanManagementPacket::canCFP_REQ() const
00823 {
00824     return CAPABILITY_CFP_REQ( EXTRACT_LE_16BITS( &_body->capability_info ) );
00825 }
00826 
00827 
00828 bool OWaveLanManagementPacket::canPrivacy() const
00829 {
00830     return CAPABILITY_PRIVACY( EXTRACT_LE_16BITS( &_body->capability_info ) );
00831 }
00832 
00833 
00834 /*======================================================================================
00835  * OWaveLanManagementSSID
00836  *======================================================================================*/
00837 
00838 OWaveLanManagementSSID::OWaveLanManagementSSID( const unsigned char* /*end*/, const struct ssid_t* data, QObject* parent )
00839                 :QObject( parent, "802.11 SSID" ), _data( data )
00840 {
00841     odebug << "OWaveLanManagementSSID()" << oendl;
00842 }
00843 
00844 
00845 OWaveLanManagementSSID::~OWaveLanManagementSSID()
00846 {
00847 }
00848 
00849 
00850 QString OWaveLanManagementSSID::ID( bool decloak ) const
00851 {
00852     int length = _data->length;
00853     if ( length > 32 ) length = 32;
00854     char essid[length+1];
00855     memcpy( &essid, &_data->ssid, length );
00856     essid[length] = 0x0;
00857     if ( !decloak || length < 2 || essid[0] != '\0' ) return essid;
00858     odebug << "OWaveLanManagementSSID:ID(): SSID is cloaked - decloaking..." << oendl;
00859 
00860     QString decloakedID;
00861     for ( int i = 1; i < length; ++i )
00862     {
00863         if ( essid[i] >= 32 && essid[i] <= 126 ) decloakedID.append( essid[i] );
00864         else decloakedID.append( '.' );
00865     }
00866     return decloakedID;
00867 }
00868 
00869 
00870 /*======================================================================================
00871  * OWaveLanManagementRates
00872  *======================================================================================*/
00873 
00874 OWaveLanManagementRates::OWaveLanManagementRates( const unsigned char* /*end*/, const struct rates_t* data, QObject* parent )
00875                 :QObject( parent, "802.11 Rates" ), _data( data )
00876 {
00877     odebug << "OWaveLanManagementRates()" << oendl;
00878 }
00879 
00880 
00881 OWaveLanManagementRates::~OWaveLanManagementRates()
00882 {
00883 }
00884 
00885 /*======================================================================================
00886  * OWaveLanManagementCF
00887  *======================================================================================*/
00888 
00889 OWaveLanManagementCF::OWaveLanManagementCF( const unsigned char* /*end*/, const struct cf_t* data, QObject* parent )
00890                 :QObject( parent, "802.11 CF" ), _data( data )
00891 {
00892     odebug << "OWaveLanManagementCF()" << oendl;
00893 }
00894 
00895 
00896 OWaveLanManagementCF::~OWaveLanManagementCF()
00897 {
00898 }
00899 
00900 /*======================================================================================
00901  * OWaveLanManagementFH
00902  *======================================================================================*/
00903 
00904 OWaveLanManagementFH::OWaveLanManagementFH( const unsigned char* /*end*/, const struct fh_t* data, QObject* parent )
00905                 :QObject( parent, "802.11 FH" ), _data( data )
00906 {
00907     odebug << "OWaveLanManagementFH()" << oendl;
00908 }
00909 
00910 
00911 OWaveLanManagementFH::~OWaveLanManagementFH()
00912 {
00913 }
00914 
00915 /*======================================================================================
00916  * OWaveLanManagementDS
00917  *======================================================================================*/
00918 
00919 OWaveLanManagementDS::OWaveLanManagementDS( const unsigned char* /*end*/, const struct ds_t* data, QObject* parent )
00920                 :QObject( parent, "802.11 DS" ), _data( data )
00921 {
00922     odebug << "OWaveLanManagementDS()" << oendl;
00923 }
00924 
00925 
00926 OWaveLanManagementDS::~OWaveLanManagementDS()
00927 {
00928 }
00929 
00930 
00931 int OWaveLanManagementDS::channel() const
00932 {
00933     return _data->channel;
00934 }
00935 
00936 /*======================================================================================
00937  * OWaveLanManagementTim
00938  *======================================================================================*/
00939 
00940 OWaveLanManagementTim::OWaveLanManagementTim( const unsigned char* /*end*/, const struct tim_t* data, QObject* parent )
00941                 :QObject( parent, "802.11 Tim" ), _data( data )
00942 {
00943     odebug << "OWaveLanManagementTim()" << oendl;
00944 }
00945 
00946 
00947 OWaveLanManagementTim::~OWaveLanManagementTim()
00948 {
00949 }
00950 
00951 /*======================================================================================
00952  * OWaveLanManagementIBSS
00953  *======================================================================================*/
00954 
00955 OWaveLanManagementIBSS::OWaveLanManagementIBSS( const unsigned char* /*end*/, const struct ibss_t* data, QObject* parent )
00956                 :QObject( parent, "802.11 IBSS" ), _data( data )
00957 {
00958     odebug << "OWaveLanManagementIBSS()" << oendl;
00959 }
00960 
00961 
00962 OWaveLanManagementIBSS::~OWaveLanManagementIBSS()
00963 {
00964 }
00965 
00966 /*======================================================================================
00967  * OWaveLanManagementChallenge
00968  *======================================================================================*/
00969 
00970 OWaveLanManagementChallenge::OWaveLanManagementChallenge( const unsigned char* /*end*/, const struct challenge_t* data, QObject* parent )
00971                 :QObject( parent, "802.11 Challenge" ), _data( data )
00972 {
00973     odebug << "OWaveLanManagementChallenge()" << oendl;
00974 }
00975 
00976 
00977 OWaveLanManagementChallenge::~OWaveLanManagementChallenge()
00978 {
00979 }
00980 
00981 /*======================================================================================
00982  * OWaveLanDataPacket
00983  *======================================================================================*/
00984 
00985 OWaveLanDataPacket::OWaveLanDataPacket( const unsigned char* end, const struct ieee_802_11_data_header* data, OWaveLanPacket* parent )
00986                 :QObject( parent, "802.11 Data" ), _header( data )
00987 {
00988     odebug << "OWaveLanDataPacket::OWaveLanDataPacket(): decoding frame..." << oendl;
00989 
00990     const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header );
00991 
00992     #warning The next line works for most cases, but can not be correct generally!
00993     if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address
00994 
00995     new OLLCPacket( end, (const struct ieee_802_11_802_2_header*) payload, this );
00996 }
00997 
00998 
00999 OWaveLanDataPacket::~OWaveLanDataPacket()
01000 {
01001 }
01002 
01003 
01004 /*======================================================================================
01005  * OLLCPacket
01006  *======================================================================================*/
01007 
01008 OLLCPacket::OLLCPacket( const unsigned char* end, const struct ieee_802_11_802_2_header* data, QObject* parent )
01009            :QObject( parent, "802.11 LLC" ), _header( data )
01010 {
01011     odebug << "OLLCPacket::OLLCPacket(): decoding frame..." << oendl;
01012 
01013     if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) )
01014     {
01015         owarn << "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type = " << EXTRACT_16BITS( &_header->type ) << ")" << oendl;
01016 
01017         switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h
01018         {
01019             case ETH_P_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break;
01020             case ETH_P_ARP: new OARPPacket( end, (const struct myarphdr*) (data+1), this ); break;
01021             default: owarn << "OLLCPacket::OLLCPacket(): Unknown Encapsulation type = " << EXTRACT_16BITS( &_header->type ) << oendl;
01022         }
01023     }
01024 }
01025 
01026 
01027 OLLCPacket::~OLLCPacket()
01028 {
01029 }
01030 
01031 
01032 /*======================================================================================
01033  * OWaveLanControlPacket
01034  *======================================================================================*/
01035 
01036 OWaveLanControlPacket::OWaveLanControlPacket( const unsigned char* /*end*/, const struct ieee_802_11_control_header* data, OWaveLanPacket* parent )
01037                       :QObject( parent, "802.11 Control" ), _header( data )
01038 {
01039     odebug << "OWaveLanControlPacket::OWaveLanDataControl(): decoding frame..." << oendl;
01040     odebug << "Detected subtype is " << controlType() << oendl;
01041 }
01042 
01043 
01044 OWaveLanControlPacket::~OWaveLanControlPacket()
01045 {
01046 }
01047 
01048 
01049 QString OWaveLanControlPacket::controlType() const
01050 {
01051     switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) )
01052     {
01053         case CTRL_PS_POLL: return "PowerSavePoll"; break;
01054         case CTRL_RTS: return "RequestToSend"; break;
01055         case CTRL_CTS: return "ClearToSend"; break;
01056         case CTRL_ACK: return "Acknowledge"; break;
01057         case CTRL_CF_END: return "ContentionFreeEnd"; break;
01058         case CTRL_END_ACK: return "AcknowledgeEnd"; break;
01059         default:
01060             owarn << "OWaveLanControlPacket::managementType(): unhandled subtype " << FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) << oendl;
01061             return "Unknown";
01062     }
01063 }
01064 
01065 
01066 /*======================================================================================
01067  * OPacketCapturer
01068  *======================================================================================*/
01069 
01070 OPacketCapturer::OPacketCapturer( QObject* parent, const char* name )
01071                 :QObject( parent, name ), _name( QString::null ), _open( false ), _pch( 0 ), _pcd( 0 ), _sn( 0 ), _autodelete( true )
01072 {
01073 }
01074 
01075 
01076 OPacketCapturer::~OPacketCapturer()
01077 {
01078     if ( _open )
01079     {
01080         odebug << "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." << oendl;
01081         close();
01082     }
01083 }
01084 
01085 
01086 void OPacketCapturer::setAutoDelete( bool b )
01087 {
01088     _autodelete = b;
01089 }
01090 
01091 
01092 bool OPacketCapturer::autoDelete() const
01093 {
01094     return _autodelete;
01095 }
01096 
01097 
01098 void OPacketCapturer::setBlocking( bool b )
01099 {
01100     if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 )
01101     {
01102         odebug << "OPacketCapturer::setBlocking(): blocking mode changed successfully." << oendl;
01103     }
01104     else
01105     {
01106         odebug << "OPacketCapturer::setBlocking(): can't change blocking mode: " << _errbuf << oendl;
01107     }
01108 }
01109 
01110 
01111 bool OPacketCapturer::blocking() const
01112 {
01113     int b = pcap_getnonblock( _pch, _errbuf );
01114     if ( b == -1 )
01115     {
01116         odebug << "OPacketCapturer::blocking(): can't get blocking mode: " << _errbuf << oendl;
01117         return -1;
01118     }
01119     return !b;
01120 }
01121 
01122 
01123 void OPacketCapturer::closeDumpFile()
01124 {
01125     if ( _pcd )
01126     {
01127         pcap_dump_close( _pcd );
01128         _pcd = 0;
01129     }
01130     pcap_close( _pch );
01131 }
01132 
01133 
01134 void OPacketCapturer::close()
01135 {
01136     if ( _open )
01137     {
01138         if ( _sn )
01139         {
01140             _sn->disconnect( SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
01141             delete _sn;
01142         }
01143         closeDumpFile();
01144     _open = false;
01145     }
01146 
01147     odebug << "OPacketCapturer::close() --- dumping capturing statistics..." << oendl;
01148     odebug << "--------------------------------------------------" << oendl;
01149     for( QMap<QString,int>::Iterator it = _stats.begin(); it != _stats.end(); ++it )
01150         odebug << it.key() << " = " << it.data() << oendl;
01151     odebug << "--------------------------------------------------" << oendl;
01152 
01153 }
01154 
01155 
01156 int OPacketCapturer::dataLink() const
01157 {
01158     return pcap_datalink( _pch );
01159 }
01160 
01161 
01162 void OPacketCapturer::dump( OPacket* p )
01163 {
01164     if ( !_pcd )
01165     {
01166         owarn << "OPacketCapturer::dump() - cannot dump without open capture file!" << oendl;
01167         return;
01168     }
01169     pcap_dump( (u_char*) _pcd, &p->_hdr, p->_data );
01170 }
01171 
01172 
01173 int OPacketCapturer::fileno() const
01174 {
01175     if ( _open )
01176     {
01177         return pcap_fileno( _pch );
01178     }
01179     else
01180     {
01181         return -1;
01182     }
01183 }
01184 
01185 
01186 OPacket* OPacketCapturer::next( int time )
01187 {
01188     fd_set fds;
01189     struct timeval tv;
01190     FD_ZERO( &fds );
01191     FD_SET( pcap_fileno( _pch ), &fds );
01192     tv.tv_sec = time / 1000;
01193     tv.tv_usec = time % 1000;
01194     int retval = select( pcap_fileno( _pch )+1, &fds, NULL, NULL, &tv);
01195     if ( retval > 0 ) // clear to read!
01196         return next();
01197     else
01198         return 0;
01199 }
01200 
01201 
01202 OPacket* OPacketCapturer::next()
01203 {
01204     packetheaderstruct header;
01205     odebug << "==> OPacketCapturer::next()" << oendl;
01206     const unsigned char* pdata = pcap_next( _pch, &header );
01207     odebug << "<== OPacketCapturer::next()" << oendl;
01208 
01209     if ( pdata && header.len )
01210     {
01211         OPacket* p = new OPacket( dataLink(), header, pdata, 0 );
01212         // packets shouldn't be inserted in the QObject child-parent hierarchy,
01213         // because due to memory constraints they will be deleted as soon
01214         // as possible - that is right after they have been processed
01215         // by emit() [ see below ]
01216         //TODO: make gathering statistics optional, because it takes time
01217         p->updateStats( _stats, const_cast<QObjectList*>( p->children() ) );
01218         odebug << "OPacket::dumpStructure: " << p->dumpStructure() << oendl;
01219         return p;
01220     }
01221     else
01222     {
01223         owarn << "OPacketCapturer::next() - no packet received!" << oendl;
01224         return 0;
01225     }
01226 }
01227 
01228 
01229 bool OPacketCapturer::open( const QString& name )
01230 {
01231     if ( _open )
01232     {
01233         if ( name == _name )    // ignore opening an already openend device
01234         {
01235             return true;
01236         }
01237         else                    // close the last opened device
01238         {
01239             close();
01240         }
01241     }
01242 
01243     _name = name;
01244 
01245     // open libpcap
01246     pcap_t* handle = pcap_open_live( const_cast<char*>( (const char*) name ), 1024, 0, 0, &_errbuf[0] );
01247 
01248     if ( !handle )
01249     {
01250         owarn << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl;
01251         return false;
01252     }
01253 
01254     odebug << "OPacketCapturer::open(): libpcap [" << name << "] opened successfully." << oendl;
01255     _pch = handle;
01256     _open = true;
01257     _stats.clear();
01258 
01259     // in case we have an application object, create a socket notifier
01260     if ( qApp ) //TODO: I don't like this here...
01261     {
01262         _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read );
01263         connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
01264     }
01265 
01266     return true;
01267 }
01268 
01269 
01270 bool OPacketCapturer::openDumpFile( const QString& filename )
01271 {
01272     pcap_dumper_t* dump = pcap_dump_open( _pch, const_cast<char*>( (const char*) filename ) );
01273     if ( !dump )
01274     {
01275         owarn << "OPacketCapturer::open(): can't open dump with '" << filename << "': " << _errbuf << oendl;
01276         return false;
01277     }
01278     odebug << "OPacketCapturer::open(): dump [" << filename << "] opened successfully." << oendl;
01279     _pcd = dump;
01280 
01281     return true;
01282 }
01283 
01284 
01285 bool OPacketCapturer::openCaptureFile( const QString& name )
01286 {
01287     if ( _open )
01288     {
01289         close();
01290         if ( name == _name )    // ignore opening an already openend device
01291         {
01292             return true;
01293         }
01294         else                    // close the last opened device
01295         {
01296             close();
01297         }
01298     }
01299 
01300     _name = name;
01301 
01302     pcap_t* handle = pcap_open_offline( const_cast<char*>( (const char*) name ), &_errbuf[0] );
01303 
01304     if ( handle )
01305     {
01306         odebug << "OPacketCapturer::open(): libpcap opened successfully." << oendl;
01307         _pch = handle;
01308         _open = true;
01309 
01310         // in case we have an application object, create a socket notifier
01311         if ( qApp )
01312         {
01313             _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read );
01314             connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) );
01315         }
01316 
01317         return true;
01318     }
01319     else
01320     {
01321         odebug << "OPacketCapturer::open(): can't open libpcap with '" << name << "': " << _errbuf << oendl;
01322         return false;
01323     }
01324 
01325 }
01326 
01327 
01328 bool OPacketCapturer::isOpen() const
01329 {
01330     return _open;
01331 }
01332 
01333 
01334 void OPacketCapturer::readyToReceive()
01335 {
01336     odebug << "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(p)'" << oendl;
01337     OPacket* p = next();
01338     emit receivedPacket( p );
01339     // emit is synchronous - packet has been dealt with, now it's safe to delete (if enabled)
01340     if ( _autodelete ) delete p;
01341 }
01342 
01343 
01344 const QMap<QString,int>& OPacketCapturer::statistics() const
01345 {
01346     return _stats;
01347 }
01348 
01349 
01350 int OPacketCapturer::snapShot() const
01351 {
01352     return pcap_snapshot( _pch );
01353 }
01354 
01355 
01356 bool OPacketCapturer::swapped() const
01357 {
01358     return pcap_is_swapped( _pch );
01359 }
01360 
01361 
01362 QString OPacketCapturer::version() const
01363 {
01364     return QString().sprintf( "%d.%d", pcap_major_version( _pch ), pcap_minor_version( _pch ) );
01365 }
01366 
01367 }
01368 }

Generated on Sat Nov 5 16:16:13 2005 for OPIE by  doxygen 1.4.2