From b4f1571ea38f87aa5c90d9a303e938a58fb9591f Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 25 Aug 2011 19:36:57 -0300 Subject: [PATCH 1/4] Fixed IEEE802_11 constructor from buffer to allow initialization from shorter 802.11 types. --- src/ieee802-11.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index e4c5ba2..2a8a018 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -22,7 +22,7 @@ #include #include #include -#include //borrame +#include #ifndef WIN32 #include #include @@ -70,11 +70,12 @@ Tins::IEEE802_11::IEEE802_11(const ieee80211_header *header_ptr) : PDU(ETHERTYPE } Tins::IEEE802_11::IEEE802_11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP), _options_size(0) { - if(total_sz < sizeof(_header)) + if(total_sz < sizeof(_header.control)) throw std::runtime_error("Not enough size for an IEEE 802.11 header in the buffer."); - std::memcpy(&_header, buffer, sizeof(_header)); - buffer += sizeof(_header); - total_sz -= sizeof(_header); + uint32_t sz = std::min(sizeof(_header), total_sz); + std::memcpy(&_header, buffer, sz); + buffer += sz; + total_sz -= sz; // subclass specific parsing missing too. } @@ -241,12 +242,16 @@ void Tins::IEEE802_11::write_serialization(uint8_t *buffer, uint32_t total_sz, c } Tins::PDU *Tins::IEEE802_11::from_bytes(const uint8_t *buffer, uint32_t total_sz) { - if(total_sz < sizeof(ieee80211_header)) + // We only need the control field, the length of the PDU will depend on the flags set. + if(total_sz < sizeof(ieee80211_header::control)) throw std::runtime_error("Not enough size for a IEEE 802.11 header in the buffer."); const ieee80211_header *hdr = (const ieee80211_header*)buffer; PDU *ret = 0; - if(hdr->control.type == 0 && hdr->control.subtype == 8) + if(hdr->control.type == 0 && hdr->control.subtype == 8) { + if(total_sz < sizeof(_header)) + throw std::runtime_error("Not enough size for an IEEE 802.11 header in the buffer."); ret = new IEEE802_11_Beacon(buffer, total_sz); + } else ret = new IEEE802_11(buffer, total_sz); return ret; From 9e56c3681e639c5d3cb5ee0bbfe8d0bd32e13396 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 25 Aug 2011 21:39:32 -0300 Subject: [PATCH 2/4] Changed IEEE802_11::dst_addr, src_addr and filter_addr to addr1, addr2 and addr3. --- include/ieee802-11.h | 56 ++++++++++++++++++++++---------------------- src/ieee802-11.cpp | 33 +++++++++++++------------- src/radiotap.cpp | 2 +- 3 files changed, 45 insertions(+), 46 deletions(-) diff --git a/include/ieee802-11.h b/include/ieee802-11.h index 163fc45..09a22ad 100644 --- a/include/ieee802-11.h +++ b/include/ieee802-11.h @@ -297,25 +297,25 @@ namespace Tins { inline uint16_t duration_id() const { return Utils::net_to_host_s(this->_header.duration_id); } /** - * \brief Getter for the destination's address. + * \brief Getter for the first address. * - * \return The destination's address as a constant uint8_t pointer. + * \return The first address as a constant uint8_t pointer. */ - inline const uint8_t* dst_addr() const { return this->_header.dst_addr; } + inline const uint8_t* addr1() const { return this->_header.addr1; } /** - * \brief Getter for the source's address. + * \brief Getter for the second address. * - * \return The source's address as a constant uint8_t pointer. + * \return The second address as a constant uint8_t pointer. */ - inline const uint8_t* src_addr() const { return this->_header.src_addr; } + inline const uint8_t* addr2() const { return this->_header.addr2; } /** - * \brief Getter for the filtering's address. + * \brief Getter for the third address. * - * \return The filtering's address as a constant uint8_t pointer. + * \return The third address as a constant uint8_t pointer. */ - inline const uint8_t* filter_addr() const { return this->_header.filter_addr; } + inline const uint8_t* addr3() const { return this->_header.addr3; } /** * \brief Getter for the fragment number. @@ -332,11 +332,11 @@ namespace Tins { inline uint16_t seq_num() const { return Utils::net_to_host_s(this->_header.seq_control.seq_number); } /** - * \brief Getter for the optional address. + * \brief Getter for the fourth address. * - * \return The optional address as a constant uint8_t pointer. + * \return The fourth address as a constant uint8_t pointer. */ - inline const uint8_t* opt_addr() const { return this->_opt_addr; } + inline const uint8_t* addr4() const { return this->_addr4; } /** * \brief Getter for the interface. @@ -423,25 +423,25 @@ namespace Tins { void duration_id(uint16_t new_duration_id); /** - * \brief Setter for the destination's address. + * \brief Setter for the first address. * - * \param new_dst_addr const uint8_t array of 6 bytes containing the new destination's address. + * \param new_addr1 const uint8_t array of 6 bytes containing the new first's address. */ - void dst_addr(const uint8_t* new_dst_addr); + void addr1(const uint8_t* new_addr1); /** - * \brief Setter for the source's address. + * \brief Setter for the second address. * - * \param new_src_addr const uint8_t array of 6 bytes containing the new source's address. + * \param new_addr2 const uint8_t array of 6 bytes containing the new second's address. */ - void src_addr(const uint8_t* new_src_addr); + void addr2(const uint8_t* new_addr2); /** - * \brief Setter for the filtering's address. + * \brief Setter for the third address. * - * \param new_filter_addr const uint8_t array of 6 bytes containing the new filtering's address. + * \param new_addr3 const uint8_t array of 6 bytes containing the new third address. */ - void filter_addr(const uint8_t* new_filter_addr); + void addr3(const uint8_t* new_addr3); /** * \brief Setter for the fragment number. @@ -458,11 +458,11 @@ namespace Tins { void seq_num(uint16_t new_seq_num); /** - * \brief Setter for the optional address. + * \brief Setter for the fourth address. * - * \param new_opt_addr const uint8_t array of 6 bytes containing the new optional address. + * \param new_addr4 const uint8_t array of 6 bytes containing the new fourth address. */ - void opt_addr(const uint8_t* new_opt_addr); + void addr4(const uint8_t* new_addr4); /** * \brief Setter for the interface. @@ -558,9 +558,9 @@ namespace Tins { #endif } __attribute__((__packed__)) control; uint16_t duration_id; - uint8_t dst_addr[6]; - uint8_t src_addr[6]; - uint8_t filter_addr[6]; + uint8_t addr1[6]; + uint8_t addr2[6]; + uint8_t addr3[6]; struct { #if __BYTE_ORDER == __LITTLE_ENDIAN unsigned int seq_number:12; @@ -580,7 +580,7 @@ namespace Tins { ieee80211_header _header; - uint8_t _opt_addr[6]; + uint8_t _addr4[6]; uint32_t _iface_index, _options_size; std::list _options; }; diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index e4c5ba2..97bb740 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -22,7 +22,6 @@ #include #include #include -#include //borrame #ifndef WIN32 #include #include @@ -41,17 +40,17 @@ const uint8_t *Tins::IEEE802_11::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\x Tins::IEEE802_11::IEEE802_11(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child), _options_size(0) { memset(&this->_header, 0, sizeof(ieee80211_header)); if(dst_hw_addr) - this->dst_addr(dst_hw_addr); + this->addr1(dst_hw_addr); if(src_hw_addr) - this->src_addr(src_hw_addr); + this->addr2(src_hw_addr); } Tins::IEEE802_11::IEEE802_11(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : PDU(ETHERTYPE_IP, child), _options_size(0) { memset(&this->_header, 0, sizeof(ieee80211_header)); if(dst_hw_addr) - this->dst_addr(dst_hw_addr); + this->addr1(dst_hw_addr); if(src_hw_addr) - this->src_addr(src_hw_addr); + this->addr2(src_hw_addr); this->iface(iface); } @@ -59,9 +58,9 @@ Tins::IEEE802_11::IEEE802_11(const std::string& iface, const uint8_t* dst_hw_add Tins::IEEE802_11::IEEE802_11(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child), _options_size(0) { memset(&this->_header, 0, sizeof(ieee80211_header)); if(dst_hw_addr) - this->dst_addr(dst_hw_addr); + this->addr1(dst_hw_addr); if(src_hw_addr) - this->src_addr(src_hw_addr); + this->addr2(src_hw_addr); this->iface(iface_index); } @@ -163,16 +162,16 @@ void Tins::IEEE802_11::duration_id(uint16_t new_duration_id) { this->_header.duration_id = Utils::net_to_host_s(new_duration_id); } -void Tins::IEEE802_11::dst_addr(const uint8_t* new_dst_addr) { - memcpy(this->_header.dst_addr, new_dst_addr, 6); +void Tins::IEEE802_11::addr1(const uint8_t* new_addr1) { + memcpy(this->_header.addr1, new_addr1, 6); } -void Tins::IEEE802_11::src_addr(const uint8_t* new_src_addr) { - memcpy(this->_header.src_addr, new_src_addr, 6); +void Tins::IEEE802_11::addr2(const uint8_t* new_addr2) { + memcpy(this->_header.addr2, new_addr2, 6); } -void Tins::IEEE802_11::filter_addr(const uint8_t* new_filter_addr) { - memcpy(this->_header.filter_addr, new_filter_addr, 6); +void Tins::IEEE802_11::addr3(const uint8_t* new_addr3) { + memcpy(this->_header.addr3, new_addr3, 6); } void Tins::IEEE802_11::frag_num(uint8_t new_frag_num) { @@ -183,8 +182,8 @@ void Tins::IEEE802_11::seq_num(uint16_t new_seq_num) { this->_header.seq_control.seq_number = Utils::net_to_host_s(new_seq_num); } -void Tins::IEEE802_11::opt_addr(const uint8_t* new_opt_addr) { - memcpy(this->_opt_addr, new_opt_addr, 6); +void Tins::IEEE802_11::addr4(const uint8_t* new_addr4) { + memcpy(this->_addr4, new_addr4, 6); } void Tins::IEEE802_11::iface(uint32_t new_iface_index) { @@ -213,7 +212,7 @@ bool Tins::IEEE802_11::send(PacketSender* sender) { addr.sll_protocol = Utils::net_to_host_s(ETH_P_ALL); addr.sll_halen = 6; addr.sll_ifindex = this->_iface_index; - memcpy(&(addr.sll_addr), this->_header.dst_addr, 6); + memcpy(&(addr.sll_addr), this->_header.addr1, 6); return sender->send_l2(this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr)); } @@ -224,7 +223,7 @@ void Tins::IEEE802_11::write_serialization(uint8_t *buffer, uint32_t total_sz, c memcpy(buffer, &this->_header, sizeof(ieee80211_header)); buffer += sizeof(ieee80211_header); if (this->to_ds() && this->from_ds()) { - memcpy(buffer, this->_opt_addr, 6); + memcpy(buffer, this->_addr4, 6); buffer += 6; total_sz -= 6; } diff --git a/src/radiotap.cpp b/src/radiotap.cpp index 4b9d70d..0a47e36 100644 --- a/src/radiotap.cpp +++ b/src/radiotap.cpp @@ -197,7 +197,7 @@ bool Tins::RadioTap::send(PacketSender* sender) { Tins::IEEE802_11 *wlan = dynamic_cast(inner_pdu()); if(wlan) - memcpy(&(addr.sll_addr), wlan->dst_addr(), 6); + memcpy(&(addr.sll_addr), wlan->addr1(), 6); return sender->send_l2(this, (struct sockaddr*)&addr, (uint32_t)sizeof(addr)); } From 479d6c4acd1bc083a4fac1f3d4b9363096b19aa1 Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 25 Aug 2011 22:22:57 -0300 Subject: [PATCH 3/4] IEEE802_11 data packets now can be created from raw buffers. Not tested yet. --- include/snap.h | 8 ++++++++ src/ieee802-11.cpp | 6 +++++- src/snap.cpp | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/snap.h b/include/snap.h index 09f2f8e..7c394be 100644 --- a/include/snap.h +++ b/include/snap.h @@ -41,6 +41,14 @@ namespace Tins { */ SNAP(PDU *child = 0); + /** + * \brief Constructor which creates a SNAP object from a buffer and adds all identifiable + * PDUs found in the buffer as children of this one. + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + SNAP(const uint8_t *buffer, uint32_t total_sz); + /** * \brief Returns the SNAP frame's header length. * diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index 97bb740..951ab4e 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -32,6 +32,7 @@ #include "radiotap.h" #include "sniffer.h" #include "utils.h" +#include "snap.h" using namespace std; @@ -74,7 +75,10 @@ Tins::IEEE802_11::IEEE802_11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETH std::memcpy(&_header, buffer, sizeof(_header)); buffer += sizeof(_header); total_sz -= sizeof(_header); - + if(type() == 0 && subtype() < 4) { + // It's a data packet + inner_pdu(new Tins::SNAP(buffer, total_sz)); + } // subclass specific parsing missing too. } diff --git a/src/snap.cpp b/src/snap.cpp index 0b0621c..56fcd20 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -21,11 +21,14 @@ #include #include +#include #ifndef WIN32 #include #endif #include "snap.h" #include "utils.h" +#include "arp.h" +#include "ip.h" Tins::SNAP::SNAP(PDU *child) : PDU(0xff, child) { @@ -34,6 +37,22 @@ Tins::SNAP::SNAP(PDU *child) : PDU(0xff, child) { _snap.id = 3; } +Tins::SNAP::SNAP(const uint8_t *buffer, uint32_t total_sz) : PDU(0xff) { + if(total_sz < sizeof(_snap)) + throw std::runtime_error("Not enough size for a SNAP header in the buffer."); + std::memcpy(&_snap, buffer, sizeof(_snap)); + buffer += sizeof(_snap); + total_sz -= sizeof(_snap); + switch(Utils::net_to_host_s(_snap.eth_type)) { + case ETHERTYPE_IP: + inner_pdu(new Tins::IP(buffer, total_sz)); + break; + case ETHERTYPE_ARP: + inner_pdu(new Tins::ARP(buffer, total_sz)); + break; + }; +} + uint32_t Tins::SNAP::header_size() const { return sizeof(_snap); } From 079672f2daa3e1906246d83c245ac235f713d57c Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Thu, 25 Aug 2011 23:11:16 -0300 Subject: [PATCH 4/4] Added IEEE802_11_Assoc_Request constructor from raw buffer. --- include/ieee802-11.h | 9 +++++++++ src/ieee802-11.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/ieee802-11.h b/include/ieee802-11.h index fbef570..d9f4201 100644 --- a/include/ieee802-11.h +++ b/include/ieee802-11.h @@ -1221,6 +1221,15 @@ namespace Tins { */ IEEE802_11_Assoc_Request(const std::string& iface, const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0) throw (std::runtime_error); + /** + * \brief Constructor which creates a IEEE802_11_Assoc_Request object from a + * buffer and adds all identifiable PDUs found in the buffer as children of this one. + * + * \param buffer The buffer from which this PDU will be constructed. + * \param total_sz The total size of the buffer. + */ + IEEE802_11_Assoc_Request(const uint8_t *buffer, uint32_t total_sz); + /** * \brief Getter for the Capabilities Information. * diff --git a/src/ieee802-11.cpp b/src/ieee802-11.cpp index 01e4cc6..ed8bd4a 100644 --- a/src/ieee802-11.cpp +++ b/src/ieee802-11.cpp @@ -500,6 +500,17 @@ Tins::IEEE802_11_Assoc_Request::IEEE802_11_Assoc_Request(const std::string& ifac memset(&_body, 0, sizeof(_body)); } +Tins::IEEE802_11_Assoc_Request::IEEE802_11_Assoc_Request(const uint8_t *buffer, uint32_t total_sz) : ManagementFrame(buffer, total_sz) { + buffer += sizeof(ieee80211_header); + total_sz -= sizeof(ieee80211_header); + if(total_sz < sizeof(_body)) + throw std::runtime_error("Not enough size for an IEEE 802.11 association header in the buffer."); + memcpy(&_body, buffer, sizeof(_body)); + buffer += sizeof(_body); + total_sz -= sizeof(_body); + parse_tagged_parameters(buffer, total_sz); +} + void Tins::IEEE802_11_Assoc_Request::listen_interval(uint16_t new_listen_interval) { this->_body.listen_interval = new_listen_interval; }