author | mickeyl <mickeyl> | 2003-04-08 14:15:35 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-04-08 14:15:35 (UTC) |
commit | 1af4ae3d621d63c82f7d78efda05218a3457981f (patch) (side-by-side diff) | |
tree | 99423ee25f8bf9d008d8e990725c4ecefc864ecd | |
parent | 77b1330ad7380ac87db4ab532acec7ae11c3bd3a (diff) | |
download | opie-1af4ae3d621d63c82f7d78efda05218a3457981f.zip opie-1af4ae3d621d63c82f7d78efda05218a3457981f.tar.gz opie-1af4ae3d621d63c82f7d78efda05218a3457981f.tar.bz2 |
- add skeleton for the last missing parts in the 802.11 decoding framework
- fix huge memory leak in packet capturer
- add more fine granular 802.11 subtype handling
-rw-r--r-- | libopie2/opienet/802_11_user.h | 16 | ||||
-rw-r--r-- | libopie2/opienet/opcap.cpp | 95 | ||||
-rw-r--r-- | libopie2/opienet/opcap.h | 22 |
3 files changed, 104 insertions, 29 deletions
diff --git a/libopie2/opienet/802_11_user.h b/libopie2/opienet/802_11_user.h index ffdcb93..f596bd8 100644 --- a/libopie2/opienet/802_11_user.h +++ b/libopie2/opienet/802_11_user.h @@ -130,298 +130,314 @@ struct ieee_802_11_802_2_header { { ieee_802_11_frame_subtype_Probe_Req , 0xF,"4 Probe Request"},\ { ieee_802_11_frame_subtype_Probe_Resp , 0xF,"5 Probe Response"},\ { ieee_802_11_frame_subtype_Beacon , 0xF,"8 Beacon"},\ { ieee_802_11_frame_subtype_ATIM , 0xF,"9 ATIM"},\ { ieee_802_11_frame_subtype_Disassociation, 0xF,"A Disassociation"},\ { ieee_802_11_frame_subtype_Authentication, 0xF,"B Authentication"},\ { ieee_802_11_frame_subtype_Deauthentication, 0xF,"C Deauthentication"},\ { ieee_802_11_frame_subtype_PS_Poll , 0xF,"A PS-Poll"},\ { ieee_802_11_frame_subtype_RTS , 0xF,"B RTS"},\ { ieee_802_11_frame_subtype_CTS , 0xF,"C CTS"},\ { ieee_802_11_frame_subtype_ACK , 0xF,"D ACK"},\ { ieee_802_11_frame_subtype_CFEnd , 0xF,"E CF-End"},\ { ieee_802_11_frame_subtype_CFEnd_CFAck , 0xF,"F CF-End + CF-Ack"},\ { ieee_802_11_frame_subtype_Data , 0xF,"0 Data"},\ { ieee_802_11_frame_subtype_Data_CFAck , 0xF,"1 Data + CF-Ack"},\ { ieee_802_11_frame_subtype_Data_CFPoll , 0xF,"2 Data + CF-Poll"},\ { ieee_802_11_frame_subtype_Data_CFAck_CFPoll, 0xF,"3 Data + CF-Ack + CF-Poll"},\ { ieee_802_11_frame_subtype_Null_Function , 0xF,"4 Null Function (no data)"},\ { ieee_802_11_frame_subtype_CFAck , 0xF,"5 CF-Ack (no data)"},\ { ieee_802_11_frame_subtype_CFPoll , 0xF,"6 CF-Poll (no data)"},\ { ieee_802_11_frame_subtype_CFAck_CFPoll, 0xF,"y7 CF-Ack + CF-Poll (no data)"},\ { 0,0,NULL}\ } struct ieee_802_11_frame_subtype_class { u_int8_t subtype; u_int8_t mask; u_int8_t klass; u_int8_t type; }; #define ieee_802_11_frame_subtype_classes {\ { ieee_802_11_frame_subtype_Association_Req, 0xF,2,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Association_Resp, 0xF,2,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Reassociation_Req, 0xF,2,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Reassociation_Resp, 0xF,2,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Probe_Req , 0xF,1,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Probe_Resp , 0xF,1,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Beacon , 0xF,1,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_ATIM , 0xF,1,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Disassociation, 0xF,2,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Authentication, 0xF,1,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_Deauthentication, 0xF,3,ieee_802_11_frame_type_Management},\ { ieee_802_11_frame_subtype_PS-Poll , 0xF,3,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_RTS , 0xF,1,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_CTS , 0xF,1,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_ACK , 0xF,1,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_CFEnd , 0xF,1,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_CFEnd_CFAck , 0xF,1,ieee_802_11_frame_type_Control},\ { ieee_802_11_frame_subtype_Data , 0xF,3,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_Data_CFAck , 0xF,3,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_Data_CF_Poll 0xF,3,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_Data_CF_AckCF_Poll, 0xF,3,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_NullFunction 0xF,1,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_CF_Ack , 0xF,1,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_CF_Poll , 0xF,1,ieee_802_11_frame_type_Data},\ { ieee_802_11_frame_subtype_CF_AckCF_Poll, 0xF,1,ieee_802_11_frame_type_Data},\ { 0,0,NULL}\ } #define IEEE802_11_FC_LEN 2 #define T_MGMT 0x0 /* management */ #define T_CTRL 0x1 /* control */ #define T_DATA 0x2 /* data */ #define T_RESV 0x3 /* reserved */ #define ST_ASSOC_REQUEST 0x0 #define ST_ASSOC_RESPONSE 0x1 #define ST_REASSOC_REQUEST 0x2 #define ST_REASSOC_RESPONSE 0x3 #define ST_PROBE_REQUEST 0x4 #define ST_PROBE_RESPONSE 0x5 /* RESERVED 0x6 */ /* RESERVED 0x7 */ #define ST_BEACON 0x8 #define ST_ATIM 0x9 #define ST_DISASSOC 0xA #define ST_AUTH 0xB #define ST_DEAUTH 0xC /* RESERVED 0xD */ /* RESERVED 0xE */ /* RESERVED 0xF */ #define CTRL_PS_POLL 0xA #define CTRL_RTS 0xB #define CTRL_CTS 0xC #define CTRL_ACK 0xD #define CTRL_CF_END 0xE #define CTRL_END_ACK 0xF /* * Bits in the frame control field. */ #define FC_VERSION(fc) ((fc) & 0x3) #define FC_TYPE(fc) (((fc) >> 2) & 0x3) #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) #define FC_TO_DS(fc) ((fc) & 0x0100) #define FC_FROM_DS(fc) ((fc) & 0x0200) #define FC_MORE_FLAG(fc) ((fc) & 0x0400) #define FC_RETRY(fc) ((fc) & 0x0800) #define FC_POWER_MGMT(fc) ((fc) & 0x1000) #define FC_MORE_DATA(fc) ((fc) & 0x2000) #define FC_WEP(fc) ((fc) & 0x4000) #define FC_ORDER(fc) ((fc) & 0x8000) struct ieee_802_11_mgmt_header { u_int16_t fc; u_int16_t duration; u_int8_t da[6]; u_int8_t sa[6]; u_int8_t bssid[6]; u_int16_t seq_ctrl; }; struct ieee_802_11_data_header { u_int16_t frame_control; u_int16_t duration; u_int8_t mac1[6]; u_int8_t mac2[6]; u_int8_t mac3[6]; u_int16_t SeqCtl; u_int8_t mac4[6]; // u_int16_t gapLen; // u_int8_t gap[8]; }; +struct ieee_802_11_control_header { + u_int16_t frame_control; + u_int16_t duration; + u_int8_t mac1[6]; + u_int8_t mac2[6]; + u_int8_t mac3[6]; + u_int16_t SeqCtl; + u_int8_t mac4[6]; +// u_int16_t gapLen; +// u_int8_t gap[8]; +}; + #define CAPABILITY_ESS(cap) ((cap) & 0x0001) #define CAPABILITY_IBSS(cap) ((cap) & 0x0002) #define CAPABILITY_CFP(cap) ((cap) & 0x0004) #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) struct ssid_t { u_int8_t element_id; u_int8_t length; u_char ssid[33]; /* 32 + 1 for null */ }; struct rates_t { u_int8_t element_id; u_int8_t length; u_int8_t rate[8]; }; struct challenge_t { u_int8_t element_id; u_int8_t length; u_int8_t text[254]; /* 1-253 + 1 for null */ }; struct fh_t { u_int8_t element_id; u_int8_t length; u_int16_t dwell_time; u_int8_t hop_set; u_int8_t hop_pattern; u_int8_t hop_index; }; struct ds_t { u_int8_t element_id; u_int8_t length; u_int8_t channel; }; struct cf_t { u_int8_t element_id; u_int8_t length; u_int8_t count; u_int8_t period; u_int16_t max_duration; u_int16_t dur_remaing; }; struct tim_t { u_int8_t element_id; u_int8_t length; u_int8_t count; u_int8_t period; u_int8_t bitmap_control; u_int8_t bitmap[251]; }; struct ibss_t { u_int8_t element_id; u_int8_t length; u_int16_t atim_window; }; #define E_SSID 0 #define E_RATES 1 #define E_FH 2 #define E_DS 3 #define E_CF 4 #define E_TIM 5 #define E_IBSS 6 #define E_CHALLENGE 16 #define E_CISCO 133 struct ieee_802_11_mgmt_body { u_int8_t timestamp[8]; u_int16_t beacon_interval; // u_int16_t listen_interval; // u_int16_t status_code; // u_int16_t aid; // u_char ap[6]; // u_int16_t reason_code; // u_int16_t auth_alg; // u_int16_t auth_trans_seq_num; // struct challenge_t challenge; u_int16_t capability_info; // struct ssid_t ssid; // struct rates_t rates; // struct ds_t ds; // struct cf_t cf; // struct fh_t fh; // struct tim_t tim; }; struct ieee_802_11_data_body { //FIXME }; +struct ieee_802_11_control_body { +//FIXME +}; + struct ctrl_rts_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t ta[6]; u_int8_t fcs[4]; }; #define CTRL_RTS_LEN (2+2+6+6+4) struct ctrl_cts_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t fcs[4]; }; #define CTRL_CTS_LEN (2+2+6+4) struct ctrl_ack_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t fcs[4]; }; #define CTRL_ACK_LEN (2+2+6+4) struct ctrl_ps_poll_t { u_int16_t fc; u_int16_t aid; u_int8_t bssid[6]; u_int8_t ta[6]; u_int8_t fcs[4]; }; #define CTRL_PS_POLL_LEN (2+2+6+6+4) struct ctrl_end_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t bssid[6]; u_int8_t fcs[4]; }; #define CTRL_END_LEN (2+2+6+6+4) struct ctrl_end_ack_t { u_int16_t fc; u_int16_t duration; u_int8_t ra[6]; u_int8_t bssid[6]; u_int8_t fcs[4]; }; #define CTRL_END_ACK_LEN (2+2+6+6+4) #define IV_IV(iv) ((iv) & 0xFFFFFF) #define IV_PAD(iv) (((iv) >> 24) & 0x3F) #define IV_KEYID(iv) (((iv) >> 30) & 0x03) #endif diff --git a/libopie2/opienet/opcap.cpp b/libopie2/opienet/opcap.cpp index 40aac2c..5c464cf 100644 --- a/libopie2/opienet/opcap.cpp +++ b/libopie2/opienet/opcap.cpp @@ -1,832 +1,875 @@ /* This file is part of the Opie Project Copyright (C) 2003 by the Wellenreiter team: Martin J. Muench <mjm@remote-exploit.org> Max Moser <mmo@remote-exploit.org Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* OPIE */ #include <opie2/opcap.h> /* QT */ #include <qapplication.h> // don't use oapplication here (will decrease reusability in other projects) #include <qsocketnotifier.h> /*====================================================================================== * OPacket *======================================================================================*/ -OPacket::OPacket( packetheaderstruct header, const unsigned char* data, QObject* parent ) +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 ); + //qDebug( "OPacket::data @ %0x, end @ %0x", data, _end ); - if ( packetCapturer()->dataLink() == DLT_EN10MB ) + switch ( datalink ) { + case DLT_EN10MB: qDebug( "OPacket::OPacket(): Received Packet. Datalink = ETHERNET" ); new OEthernetPacket( _end, (const struct ether_header*) data, this ); - } - else - { + break; + + case DLT_IEEE802_11: qDebug( "OPacket::OPacket(): Received Packet. Datalink = IEEE802.11" ); new OWaveLanPacket( _end, (const struct ieee_802_11_header*) data, this ); + break; + + default: + qWarning( "OPacket::OPacket(): Received Packet over unsupported datalink '%s'!", datalink ); } } OPacket::~OPacket() { } -OPacketCapturer* OPacket::packetCapturer() const -{ - return parent()->inherits( "OPacketCapturer" ) ? static_cast<OPacketCapturer*>( parent() ) : 0; -} - - timevalstruct OPacket::timeval() const { return _hdr.ts; } int OPacket::caplen() const { return _hdr.caplen; } QString OPacket::dump( int bpl ) const { static int index = 0; index++; int len = _hdr.caplen; QString str; str.sprintf( "\n<----- Packet #%04d Len = 0x%X (%d) ----->\n\n", index, len, len ); str.append( "0000: " ); QString tmp; QString bytes; QString chars; for ( int i = 0; i < len; ++i ) { tmp.sprintf( "%02X ", _data[i] ); bytes.append( tmp ); if ( (_data[i] > 31) && (_data[i]<128) ) chars.append( _data[i] ); else chars.append( '.' ); if ( !((i+1) % bpl) ) { str.append( bytes ); str.append( ' ' ); str.append( chars ); str.append( '\n' ); tmp.sprintf( "%04X: ", i+1 ); str.append( tmp ); bytes = ""; chars = ""; } } if ( (len % bpl) ) { str.append( bytes.leftJustify( 1 + 3*bpl ) ); str.append( chars ); } str.append( '\n' ); return str; } int OPacket::len() const { return _hdr.len; } /*====================================================================================== * OEthernetPacket *======================================================================================*/ OEthernetPacket::OEthernetPacket( const unsigned char* end, const struct ether_header* data, QObject* parent ) :QObject( parent, "Ethernet" ), _ether( data ) { qDebug( "Source = %s", (const char*) sourceAddress().toString() ); qDebug( "Destination = %s", (const char*) destinationAddress().toString() ); if ( sourceAddress() == OMacAddress::broadcast ) qDebug( "Source is broadcast address" ); if ( destinationAddress() == OMacAddress::broadcast ) qDebug( "Destination is broadcast address" ); switch ( type() ) { case ETHERTYPE_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; case ETHERTYPE_ARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = ARP" ); break; } case ETHERTYPE_REVARP: { qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = RARP" ); break; } default: qDebug( "OPacket::OPacket(): Received Ethernet Packet : Type = UNKNOWN" ); } } OEthernetPacket::~OEthernetPacket() { } OMacAddress OEthernetPacket::sourceAddress() const { return OMacAddress( _ether->ether_shost ); } OMacAddress OEthernetPacket::destinationAddress() const { return OMacAddress( _ether->ether_dhost ); } int OEthernetPacket::type() const { return ntohs( _ether->ether_type ); } /*====================================================================================== * OIPPacket *======================================================================================*/ OIPPacket::OIPPacket( const unsigned char* end, const struct iphdr* data, QObject* parent ) :QObject( parent, "IP" ), _iphdr( data ) { qDebug( "OIPPacket::OIPPacket(): decoding IP header..." ); //qDebug( "FromAddress: %s", (const char*) inet_ntoa( *src ) ); //qDebug( " ToAddress: %s", (const char*) inet_ntoa( *dst ) ); qDebug( "FromAddress: %s", (const char*) fromIPAddress().toString() ); qDebug( " toAddress: %s", (const char*) toIPAddress().toString() ); switch ( protocol() ) { case IPPROTO_UDP: new OUDPPacket( end, (const struct udphdr*) (data+1), this ); break; case IPPROTO_TCP: new OTCPPacket( end, (const struct tcphdr*) (data+1), this ); break; default: qDebug( "OIPPacket::OIPPacket(): unknown IP protocol type = %d", protocol() ); } } OIPPacket::~OIPPacket() { } QHostAddress OIPPacket::fromIPAddress() const { return EXTRACT_32BITS( &_iphdr->saddr ); } QHostAddress OIPPacket::toIPAddress() const { return EXTRACT_32BITS( &_iphdr->saddr ); } int OIPPacket::tos() const { return _iphdr->tos; } int OIPPacket::len() const { return EXTRACT_16BITS( &_iphdr->tot_len ); } int OIPPacket::id() const { return EXTRACT_16BITS( &_iphdr->id ); } int OIPPacket::offset() const { return EXTRACT_16BITS( &_iphdr->frag_off ); } int OIPPacket::ttl() const { return _iphdr->ttl; } int OIPPacket::protocol() const { return _iphdr->protocol; } int OIPPacket::checksum() const { return EXTRACT_16BITS( &_iphdr->check ); } /*====================================================================================== * OUDPPacket *======================================================================================*/ OUDPPacket::OUDPPacket( const unsigned char* end, const struct udphdr* data, QObject* parent ) :QObject( parent, "UDP" ), _udphdr( data ) { qDebug( "OUDPPacket::OUDPPacket(): decoding UDP header..." ); } OUDPPacket::~OUDPPacket() { } /*====================================================================================== * OTCPPacket *======================================================================================*/ OTCPPacket::OTCPPacket( const unsigned char* end, const struct tcphdr* data, QObject* parent ) :QObject( parent, "TCP" ), _tcphdr( data ) { qDebug( "OTCPPacket::OTCPPacket(): decoding TCP header..." ); } OTCPPacket::~OTCPPacket() { } /*====================================================================================== * OWaveLanPacket *======================================================================================*/ OWaveLanPacket::OWaveLanPacket( const unsigned char* end, const struct ieee_802_11_header* data, QObject* parent ) :QObject( parent, "802.11" ), _wlanhdr( data ) { qDebug( "OWaveLanPacket::OWaveLanPacket(): decoding IEEE 802.11 header..." ); qDebug( "type: %0X", type() ); qDebug( "subType: %0X", subType() ); qDebug( "duration: %d", duration() ); qDebug( "powermanagement: %d", usesPowerManagement() ); - qDebug( "wep: %d", usesWep() ); + qDebug( "payload is encrypted: %s", usesWep() ? "yes" : "no" ); qDebug( "MAC1: %s", (const char*) macAddress1().toString() ); qDebug( "MAC2: %s", (const char*) macAddress2().toString() ); qDebug( "MAC3: %s", (const char*) macAddress3().toString() ); qDebug( "MAC4: %s", (const char*) macAddress4().toString() ); switch ( type() ) { case T_MGMT: new OWaveLanManagementPacket( end, (const struct ieee_802_11_mgmt_header*) data, this ); break; case T_DATA: new OWaveLanDataPacket( end, (const struct ieee_802_11_data_header*) data, this ); break; - //case T_CTRL: new OWaveLanControlPacket( end, (const struct ieee_802_11_ctrl_header*) data, this ); break; - default: qDebug( "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown type!" ); + case T_CTRL: new OWaveLanControlPacket( end, (const struct ieee_802_11_control_header*) data, this ); break; + default: qDebug( "OWaveLanPacket::OWaveLanPacket(): Warning: Unknown major type '%d'!", type() ); } } OWaveLanPacket::~OWaveLanPacket() { } int OWaveLanPacket::duration() const { return _wlanhdr->duration; } OMacAddress OWaveLanPacket::macAddress1() const { return OMacAddress( _wlanhdr->mac1 ); } OMacAddress OWaveLanPacket::macAddress2() const { return OMacAddress( _wlanhdr->mac2 ); } OMacAddress OWaveLanPacket::macAddress3() const { return OMacAddress( _wlanhdr->mac3 ); } OMacAddress OWaveLanPacket::macAddress4() const { return OMacAddress( _wlanhdr->mac4 ); } int OWaveLanPacket::subType() const { return FC_SUBTYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } int OWaveLanPacket::type() const { return FC_TYPE( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } int OWaveLanPacket::version() const { return FC_VERSION( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } bool OWaveLanPacket::fromDS() const { return FC_FROM_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } bool OWaveLanPacket::toDS() const { return FC_TO_DS( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } bool OWaveLanPacket::usesPowerManagement() const { return FC_POWER_MGMT( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } bool OWaveLanPacket::usesWep() const { return FC_WEP( EXTRACT_LE_16BITS( &_wlanhdr->frame_control ) ); } /*====================================================================================== * OWaveLanManagementPacket *======================================================================================*/ OWaveLanManagementPacket::OWaveLanManagementPacket( const unsigned char* end, const struct ieee_802_11_mgmt_header* data, OWaveLanPacket* parent ) :QObject( parent, "802.11 Management" ), _header( data ), _body( (const struct ieee_802_11_mgmt_body*) (data+1) ) { qDebug( "OWaveLanManagementPacket::OWaveLanManagementPacket(): decoding frame..." ); - - switch ( ((OWaveLanPacket*) this->parent() )->subType() ) - { - case ST_BEACON: - { - // nice, received a beacon... - } - } + qDebug( "Detected subtype is '%s'", (const char*) managementType() ); // grab tagged values const unsigned char* ptr = (const unsigned char*) (_body+1); while (ptr < end) { switch ( *ptr ) { case E_SSID: new OWaveLanManagementSSID( end, (struct ssid_t*) ptr, this ); break; case E_FH: new OWaveLanManagementFH( end, (struct fh_t*) ptr, this ); break; case E_DS: new OWaveLanManagementDS( end, (struct ds_t*) ptr, this ); break; case E_RATES: new OWaveLanManagementRates( end, (struct rates_t*) ptr, this ); break; case E_CF: new OWaveLanManagementCF( end, (struct cf_t*) ptr, this ); break; case E_TIM: new OWaveLanManagementTim( end, (struct tim_t*) ptr, this ); break; case E_IBSS: new OWaveLanManagementIBSS( end, (struct ibss_t*) ptr, this ); break; case E_CHALLENGE: new OWaveLanManagementChallenge( end, (struct challenge_t*) ptr, this ); break; } ptr+= ( ( struct ssid_t* ) ptr )->length; // skip length of tagged value ptr+= 2; // skip tag ID and length } } OWaveLanManagementPacket::~OWaveLanManagementPacket() { } +QString OWaveLanManagementPacket::managementType() const +{ + switch ( FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ) + { + case ST_ASSOC_REQUEST: return "AssociationRequest"; break; + case ST_ASSOC_RESPONSE: return "AssociationResponse"; break; + case ST_REASSOC_REQUEST: return "ReassociationRequest"; break; + case ST_REASSOC_RESPONSE: return "ReassociationResponse"; break; + case ST_PROBE_REQUEST: return "ProbeRequest"; break; + case ST_PROBE_RESPONSE: return "ProbeResponse"; break; + case ST_BEACON: return "Beacon"; break; + case ST_ATIM: return "Atim"; break; + case ST_DISASSOC: return "Disassociation"; break; + case ST_AUTH: return "Authentication"; break; + case ST_DEAUTH: return "Deathentication"; break; + default: + qWarning( "OWaveLanManagementPacket::managementType(): unhandled subtype %d", FC_SUBTYPE( EXTRACT_LE_16BITS( &_header->fc ) ) ); + return "Unknown"; + } +} + + int OWaveLanManagementPacket::beaconInterval() const { return EXTRACT_LE_16BITS( &_body->beacon_interval ); } int OWaveLanManagementPacket::capabilities() const { return EXTRACT_LE_16BITS( &_body->capability_info ); } bool OWaveLanManagementPacket::canESS() const { return CAPABILITY_ESS( EXTRACT_LE_16BITS( &_body->capability_info ) ); } bool OWaveLanManagementPacket::canIBSS() const { return CAPABILITY_IBSS( EXTRACT_LE_16BITS( &_body->capability_info ) ); } bool OWaveLanManagementPacket::canCFP() const { return CAPABILITY_CFP( EXTRACT_LE_16BITS( &_body->capability_info ) ); } bool OWaveLanManagementPacket::canCFP_REQ() const { return CAPABILITY_CFP_REQ( EXTRACT_LE_16BITS( &_body->capability_info ) ); } bool OWaveLanManagementPacket::canPrivacy() const { return CAPABILITY_PRIVACY( EXTRACT_LE_16BITS( &_body->capability_info ) ); } /*====================================================================================== * OWaveLanManagementSSID *======================================================================================*/ OWaveLanManagementSSID::OWaveLanManagementSSID( const unsigned char* end, const struct ssid_t* data, QObject* parent ) :QObject( parent, "802.11 SSID" ), _data( data ) { qDebug( "OWaveLanManagementSSID()" ); } OWaveLanManagementSSID::~OWaveLanManagementSSID() { } QString OWaveLanManagementSSID::ID() const { int length = _data->length; if ( length > 32 ) length = 32; char essid[length+1]; memcpy( &essid, &_data->ssid, length ); essid[length] = 0x0; return essid; } /*====================================================================================== * OWaveLanManagementRates *======================================================================================*/ OWaveLanManagementRates::OWaveLanManagementRates( const unsigned char* end, const struct rates_t* data, QObject* parent ) :QObject( parent, "802.11 Rates" ), _data( data ) { qDebug( "OWaveLanManagementRates()" ); } OWaveLanManagementRates::~OWaveLanManagementRates() { } /*====================================================================================== * OWaveLanManagementCF *======================================================================================*/ OWaveLanManagementCF::OWaveLanManagementCF( const unsigned char* end, const struct cf_t* data, QObject* parent ) :QObject( parent, "802.11 CF" ), _data( data ) { qDebug( "OWaveLanManagementCF()" ); } OWaveLanManagementCF::~OWaveLanManagementCF() { } /*====================================================================================== * OWaveLanManagementFH *======================================================================================*/ OWaveLanManagementFH::OWaveLanManagementFH( const unsigned char* end, const struct fh_t* data, QObject* parent ) :QObject( parent, "802.11 FH" ), _data( data ) { qDebug( "OWaveLanManagementFH()" ); } OWaveLanManagementFH::~OWaveLanManagementFH() { } /*====================================================================================== * OWaveLanManagementDS *======================================================================================*/ OWaveLanManagementDS::OWaveLanManagementDS( const unsigned char* end, const struct ds_t* data, QObject* parent ) :QObject( parent, "802.11 DS" ), _data( data ) { qDebug( "OWaveLanManagementDS()" ); } OWaveLanManagementDS::~OWaveLanManagementDS() { } int OWaveLanManagementDS::channel() const { return _data->channel; } /*====================================================================================== * OWaveLanManagementTim *======================================================================================*/ OWaveLanManagementTim::OWaveLanManagementTim( const unsigned char* end, const struct tim_t* data, QObject* parent ) :QObject( parent, "802.11 Tim" ), _data( data ) { qDebug( "OWaveLanManagementTim()" ); } OWaveLanManagementTim::~OWaveLanManagementTim() { } /*====================================================================================== * OWaveLanManagementIBSS *======================================================================================*/ OWaveLanManagementIBSS::OWaveLanManagementIBSS( const unsigned char* end, const struct ibss_t* data, QObject* parent ) :QObject( parent, "802.11 IBSS" ), _data( data ) { qDebug( "OWaveLanManagementIBSS()" ); } OWaveLanManagementIBSS::~OWaveLanManagementIBSS() { } /*====================================================================================== * OWaveLanManagementChallenge *======================================================================================*/ OWaveLanManagementChallenge::OWaveLanManagementChallenge( const unsigned char* end, const struct challenge_t* data, QObject* parent ) :QObject( parent, "802.11 Challenge" ), _data( data ) { qDebug( "OWaveLanManagementChallenge()" ); } OWaveLanManagementChallenge::~OWaveLanManagementChallenge() { } /*====================================================================================== * OWaveLanDataPacket *======================================================================================*/ OWaveLanDataPacket::OWaveLanDataPacket( const unsigned char* end, const struct ieee_802_11_data_header* data, OWaveLanPacket* parent ) :QObject( parent, "802.11 Data" ), _header( data ) { qDebug( "OWaveLanDataPacket::OWaveLanDataPacket(): decoding frame..." ); const unsigned char* payload = (const unsigned char*) data + sizeof( struct ieee_802_11_data_header ); #warning The next line works for most cases, but can not be correct generally! if (!( ( (OWaveLanPacket*) this->parent())->duration() )) payload -= 6; // compensation for missing last address new OLLCPacket( end, (const struct ieee_802_11_802_2_header*) payload, this ); } OWaveLanDataPacket::~OWaveLanDataPacket() { } /*====================================================================================== * OLLCPacket *======================================================================================*/ OLLCPacket::OLLCPacket( const unsigned char* end, const struct ieee_802_11_802_2_header* data, QObject* parent ) :QObject( parent, "802.11 LLC" ), _header( data ) { qDebug( "OLLCPacket::OLLCPacket(): decoding frame..." ); if ( !(_header->oui[0] || _header->oui[1] || _header->oui[2]) ) { qDebug( "OLLCPacket::OLLCPacket(): contains an encapsulated Ethernet frame (type=%04X)", EXTRACT_16BITS( &_header->type ) ); switch ( EXTRACT_16BITS( &_header->type ) ) // defined in linux/if_ether.h { case ETH_P_IP: new OIPPacket( end, (const struct iphdr*) (data+1), this ); break; default: qDebug( "OLLCPacket::OLLCPacket(): Unknown Encapsulation Type" ); } } } OLLCPacket::~OLLCPacket() { } + +/*====================================================================================== + * OWaveLanControlPacket + *======================================================================================*/ + +OWaveLanControlPacket::OWaveLanControlPacket( const unsigned char* end, const struct ieee_802_11_control_header* data, OWaveLanPacket* parent ) + :QObject( parent, "802.11 Data" ), _header( data ) +{ + qDebug( "OWaveLanControlPacket::OWaveLanDataControl(): decoding frame..." ); + //TODO: Implement this +} + + +OWaveLanControlPacket::~OWaveLanControlPacket() +{ +} + + /*====================================================================================== * OPacketCapturer *======================================================================================*/ OPacketCapturer::OPacketCapturer( QObject* parent, const char* name ) :QObject( parent, name ), _name( QString::null ), _open( false ), _pch( 0 ), _sn( 0 ) { } OPacketCapturer::~OPacketCapturer() { if ( _open ) { qDebug( "OPacketCapturer::~OPacketCapturer(): pcap still open, autoclosing." ); close(); } } void OPacketCapturer::setBlocking( bool b ) { if ( pcap_setnonblock( _pch, 1-b, _errbuf ) != -1 ) { qDebug( "OPacketCapturer::setBlocking(): blocking mode changed successfully." ); } else { qDebug( "OPacketCapturer::setBlocking(): can't change blocking mode: %s", _errbuf ); } } bool OPacketCapturer::blocking() const { int b = pcap_getnonblock( _pch, _errbuf ); if ( b == -1 ) { qDebug( "OPacketCapturer::blocking(): can't get blocking mode: %s", _errbuf ); return -1; } return !b; } void OPacketCapturer::close() { if ( _open ) { if ( _sn ) { _sn->disconnect( SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); delete _sn; } pcap_close( _pch ); _open = false; } } int OPacketCapturer::dataLink() const { return pcap_datalink( _pch ); } int OPacketCapturer::fileno() const { if ( _open ) { return pcap_fileno( _pch ); } else { return -1; } } OPacket* OPacketCapturer::next() { packetheaderstruct header; qDebug( "==> OPacketCapturer::next()" ); const unsigned char* pdata = pcap_next( _pch, &header ); qDebug( "<== OPacketCapturer::next()" ); if ( header.len ) - return new OPacket( header, pdata, this ); + { + return 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 ] + } else + { 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; pcap_t* handle = pcap_open_live( const_cast<char*>( (const char*) name ), 1024, 0, 0, &_errbuf[0] ); if ( handle ) { qDebug( "OPacketCapturer::open(): libpcap opened successfully." ); _pch = handle; _open = true; // in case we have an application object, create a socket notifier if ( qApp ) { _sn = new QSocketNotifier( fileno(), QSocketNotifier::Read ); connect( _sn, SIGNAL( activated(int) ), this, SLOT( readyToReceive() ) ); } return true; } else { qDebug( "OPacketCapturer::open(): can't open libpcap: %s", _errbuf ); return false; } } bool OPacketCapturer::isOpen() const { return _open; } void OPacketCapturer::readyToReceive() { qDebug( "OPacketCapturer::readyToReceive(): about to emit 'receivePacket(...)'" ); - emit receivedPacket( next() ); + OPacket* p = next(); + emit receivedPacket( p ); + // emit is synchronous - packet has been dealt with, now it's safe to delete + delete p; } diff --git a/libopie2/opienet/opcap.h b/libopie2/opienet/opcap.h index 04d22ff..ddef278 100644 --- a/libopie2/opienet/opcap.h +++ b/libopie2/opienet/opcap.h @@ -1,436 +1,452 @@ /* This file is part of the Opie Project Copyright (C) 2003 by the Wellenreiter team: Martin J. Muench <mjm@remote-exploit.org> Max Moser <mmo@remote-exploit.org Michael 'Mickey' Lauer <mickey@tm.informatik.uni-frankfurt.de> =. .=l. .>+-= _;:, .> :=|. This program is free software; you can .> <`_, > . <= redistribute it and/or modify it under :`=1 )Y*s>-.-- : the terms of the GNU Library General Public .="- .-=="i, .._ License as published by the Free Software - . .-<_> .<> Foundation; either version 2 of the License, ._= =} : or (at your option) any later version. .%`+i> _;_. .i_,=:_. -<s. This program is distributed in the hope that + . -:. = it will be useful, but WITHOUT ANY WARRANTY; : .. .:, . . . without even the implied warranty of =_ + =;=|` MERCHANTABILITY or FITNESS FOR A _.=:. : :=>`: PARTICULAR PURPOSE. See the GNU ..}^=.= = ; Library General Public License for more ++= -. .` .: details. : = ...= . :.=- -. .:....=;==+<; You should have received a copy of the GNU -_. . . )=. = Library General Public License along with -- :-=` this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef OPCAP_H #define OPCAP_H /* LINUX */ extern "C" // work around a bpf/pcap conflict in recent headers { #include <pcap.h> } #include <netinet/ether.h> #include <netinet/ip.h> #include <netinet/udp.h> #include <netinet/tcp.h> #include <time.h> /* QT */ #include <qhostaddress.h> #include <qobject.h> #include <qstring.h> /* OPIE */ #include <opie2/onetutils.h> #include "802_11_user.h" /* TYPEDEFS */ typedef struct timeval timevalstruct; typedef struct pcap_pkthdr packetheaderstruct; /* FORWARDS */ class OPacketCapturer; class QSocketNotifier; /*====================================================================================== * OPacket - A frame on the wire *======================================================================================*/ class OPacket : public QObject { Q_OBJECT public: - OPacket( packetheaderstruct, const unsigned char*, QObject* parent ); + OPacket( int datalink, packetheaderstruct, const unsigned char*, QObject* parent ); virtual ~OPacket(); timevalstruct timeval() const; - OPacketCapturer* packetCapturer() const; - int caplen() const; int len() const; QString dump( int = 32 ) const; private: const packetheaderstruct _hdr; // pcap packet header const unsigned char* _data; // pcap packet data const unsigned char* _end; // end of pcap packet data }; /*====================================================================================== * OEthernetPacket - DLT_EN10MB frame *======================================================================================*/ class OEthernetPacket : public QObject { Q_OBJECT public: OEthernetPacket( const unsigned char*, const struct ether_header*, QObject* parent = 0 ); virtual ~OEthernetPacket(); OMacAddress sourceAddress() const; OMacAddress destinationAddress() const; int type() const; private: const struct ether_header* _ether; }; /*====================================================================================== * OWaveLanPacket - DLT_IEEE802_11 frame *======================================================================================*/ class OWaveLanPacket : public QObject { Q_OBJECT public: OWaveLanPacket( const unsigned char*, const struct ieee_802_11_header*, QObject* parent = 0 ); virtual ~OWaveLanPacket(); int duration() const; bool fromDS() const; bool toDS() const; virtual OMacAddress macAddress1() const; virtual OMacAddress macAddress2() const; virtual OMacAddress macAddress3() const; virtual OMacAddress macAddress4() const; bool usesPowerManagement() const; int type() const; int subType() const; int version() const; bool usesWep() const; private: const struct ieee_802_11_header* _wlanhdr; }; /*====================================================================================== * OWaveLanManagementPacket - type: management (T_MGMT) *======================================================================================*/ class OWaveLanManagementPacket : public QObject { Q_OBJECT public: OWaveLanManagementPacket( const unsigned char*, const struct ieee_802_11_mgmt_header*, OWaveLanPacket* parent = 0 ); virtual ~OWaveLanManagementPacket(); + QString managementType() const; + int beaconInterval() const; int capabilities() const; // generic bool canESS() const; bool canIBSS() const; bool canCFP() const; bool canCFP_REQ() const; bool canPrivacy() const; private: const struct ieee_802_11_mgmt_header* _header; const struct ieee_802_11_mgmt_body* _body; }; /*====================================================================================== * OWaveLanManagementSSID *======================================================================================*/ class OWaveLanManagementSSID : public QObject { Q_OBJECT public: OWaveLanManagementSSID( const unsigned char*, const struct ssid_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementSSID(); QString ID() const; private: const struct ssid_t* _data; }; /*====================================================================================== * OWaveLanManagementRates *======================================================================================*/ class OWaveLanManagementRates : public QObject { Q_OBJECT public: OWaveLanManagementRates( const unsigned char*, const struct rates_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementRates(); private: const struct rates_t* _data; }; /*====================================================================================== * OWaveLanManagementCF *======================================================================================*/ class OWaveLanManagementCF : public QObject { Q_OBJECT public: OWaveLanManagementCF( const unsigned char*, const struct cf_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementCF(); private: const struct cf_t* _data; }; /*====================================================================================== * OWaveLanManagementFH *======================================================================================*/ class OWaveLanManagementFH : public QObject { Q_OBJECT public: OWaveLanManagementFH( const unsigned char*, const struct fh_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementFH(); private: const struct fh_t* _data; }; /*====================================================================================== * OWaveLanManagementDS *======================================================================================*/ class OWaveLanManagementDS : public QObject { Q_OBJECT public: OWaveLanManagementDS( const unsigned char*, const struct ds_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementDS(); int channel() const; private: const struct ds_t* _data; }; /*====================================================================================== * OWaveLanManagementTim *======================================================================================*/ class OWaveLanManagementTim : public QObject { Q_OBJECT public: OWaveLanManagementTim( const unsigned char*, const struct tim_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementTim(); private: const struct tim_t* _data; }; /*====================================================================================== * OWaveLanManagementIBSS *======================================================================================*/ class OWaveLanManagementIBSS : public QObject { Q_OBJECT public: OWaveLanManagementIBSS( const unsigned char*, const struct ibss_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementIBSS(); private: const struct ibss_t* _data; }; /*====================================================================================== * OWaveLanManagementChallenge *======================================================================================*/ class OWaveLanManagementChallenge : public QObject { Q_OBJECT public: OWaveLanManagementChallenge( const unsigned char*, const struct challenge_t*, QObject* parent = 0 ); virtual ~OWaveLanManagementChallenge(); private: const struct challenge_t* _data; }; /*====================================================================================== * OWaveLanDataPacket - type: data (T_DATA) *======================================================================================*/ class OWaveLanDataPacket : public QObject { Q_OBJECT public: OWaveLanDataPacket( const unsigned char*, const struct ieee_802_11_data_header*, OWaveLanPacket* parent = 0 ); virtual ~OWaveLanDataPacket(); private: const struct ieee_802_11_data_header* _header; }; /*====================================================================================== + * OWaveLanControlPacket - type: control (T_CTRL) + *======================================================================================*/ + +class OWaveLanControlPacket : public QObject +{ + Q_OBJECT + + public: + OWaveLanControlPacket( const unsigned char*, const struct ieee_802_11_control_header*, OWaveLanPacket* parent = 0 ); + virtual ~OWaveLanControlPacket(); + + private: + const struct ieee_802_11_control_header* _header; +}; + +/*====================================================================================== * OLLCPacket - IEEE 802.2 Link Level Control *======================================================================================*/ class OLLCPacket : public QObject { Q_OBJECT public: OLLCPacket( const unsigned char*, const struct ieee_802_11_802_2_header* data, QObject* parent = 0 ); virtual ~OLLCPacket(); private: const struct ieee_802_11_802_2_header* _header; }; /*====================================================================================== * OIPPacket *======================================================================================*/ class OIPPacket : public QObject { Q_OBJECT public: OIPPacket( const unsigned char*, const struct iphdr*, QObject* parent = 0 ); virtual ~OIPPacket(); QHostAddress fromIPAddress() const; QHostAddress toIPAddress() const; int tos() const; int len() const; int id() const; int offset() const; int ttl() const; int protocol() const; int checksum() const; private: const struct iphdr* _iphdr; }; /*====================================================================================== * 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; private: const struct udphdr* _udphdr; }; /*====================================================================================== * 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; private: const struct tcphdr* _tcphdr; }; /*====================================================================================== * OPacketCapturer *======================================================================================*/ class OPacketCapturer : public QObject { Q_OBJECT public: OPacketCapturer( QObject* parent = 0, const char* name = 0 ); ~OPacketCapturer(); void setBlocking( bool ); bool blocking() const; void close(); int dataLink() const; int fileno() const; OPacket* next(); bool open( const QString& name ); bool isOpen() const; signals: void receivedPacket( OPacket* ); protected slots: void readyToReceive(); protected: QString _name; // devicename bool _open; // check this before doing pcap calls pcap_t* _pch; // pcap library handle QSocketNotifier* _sn; // socket notifier for main loop mutable char _errbuf[PCAP_ERRBUF_SIZE]; }; #endif // OPCAP_H |