diff --git a/include/dot11.h b/include/dot11.h index b6e18cd..0b62850 100644 --- a/include/dot11.h +++ b/include/dot11.h @@ -114,6 +114,7 @@ namespace Tins { * */ enum ControlSubtypes { + BLOCK_ACK_REQ = 8, BLOCK_ACK = 9, PS = 10, RTS = 11, @@ -306,7 +307,7 @@ namespace Tins { * * \return The value of the duration/id field in an uint16_t. */ - inline uint16_t duration_id() const { return Utils::net_to_host_s(this->_header.duration_id); } + inline uint16_t duration_id() const { return this->_header.duration_id; } /** * \brief Getter for the first address. @@ -937,7 +938,7 @@ namespace Tins { * * \return The sequence number as an uint16_t. */ - inline uint16_t seq_num() const { return Utils::net_to_host_s(this->_ext_header.seq_control.seq_number); } + inline uint16_t seq_num() const { return this->_ext_header.seq_control.seq_number; } /** * \brief Getter for the fourth address. @@ -988,18 +989,17 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; - protected: struct ExtendedHeader { uint8_t addr2[6]; uint8_t addr3[6]; struct { #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int seq_number:12; unsigned int frag_number:4; + unsigned int seq_number:12; #elif __BYTE_ORDER == __BIG_ENDIAN - unsigned int frag_number:4; unsigned int seq_number:12; + unsigned int frag_number:4; #endif } __attribute__((__packed__)) seq_control; } __attribute__((__packed__)); @@ -1028,124 +1028,6 @@ namespace Tins { uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); void copy_ext_header(const Dot11ManagementFrame *other); - - private: - ExtendedHeader _ext_header; - uint8_t _addr4[6]; - - }; - - class Dot11DataFrame : public Dot11 { - - public: - /** - * \brief Getter for the second address. - * - * \return The second address as a constant uint8_t pointer. - */ - inline const uint8_t* addr2() const { return this->_ext_header.addr2; } - - /** - * \brief Getter for the third address. - * - * \return The third address as a constant uint8_t pointer. - */ - inline const uint8_t* addr3() const { return this->_ext_header.addr3; } - - /** - * \brief Getter for the fragment number. - * - * \return The fragment number as an uint8_t. - */ - inline uint8_t frag_num() const { return this->_ext_header.seq_control.frag_number; } - - /** - * \brief Getter for the sequence number. - * - * \return The sequence number as an uint16_t. - */ - inline uint16_t seq_num() const { return Utils::net_to_host_s(this->_ext_header.seq_control.seq_number); } - - /** - * \brief Getter for the fourth address. - * - * \return The fourth address as a constant uint8_t pointer. - */ - inline const uint8_t* addr4() const { return this->_addr4; } - - /** - * \brief Setter for the second address. - * - * \param new_addr2 const uint8_t array of 6 bytes containing the new second's address. - */ - void addr2(const uint8_t* new_addr2); - - /** - * \brief Setter for the third address. - * - * \param new_addr3 const uint8_t array of 6 bytes containing the new third address. - */ - void addr3(const uint8_t* new_addr3); - - /** - * \brief Setter for the fragment number. - * - * \param new_frag_num uint8_t with the new fragment number. - */ - void frag_num(uint8_t new_frag_num); - - /** - * \brief Setter for the sequence number. - * - * \param new_seq_num uint16_t with the new sequence number. - */ - void seq_num(uint16_t new_seq_num); - - /** - * \brief Setter for the fourth address. - * - * \param new_addr4 const uint8_t array of 6 bytes containing the new fourth address. - */ - void addr4(const uint8_t* new_addr4); - - /** - * \brief Returns the 802.11 frame's header length. - * - * \return An uint32_t with the header's size. - * \sa PDU::header_size() - */ - uint32_t header_size() const; - - protected: - struct ExtendedHeader { - uint8_t addr2[6]; - uint8_t addr3[6]; - struct { - #if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned int seq_number:12; - unsigned int frag_number:4; - #elif __BYTE_ORDER == __BIG_ENDIAN - unsigned int frag_number:4; - unsigned int seq_number:12; - #endif - } __attribute__((__packed__)) seq_control; - } __attribute__((__packed__)); - - /** - * \brief Constructor which creates a Dot11DataFrame 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. - */ - Dot11DataFrame(uint32_t iface_index, const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0); - Dot11DataFrame(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0); - Dot11DataFrame(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child = 0) throw (std::runtime_error); - Dot11DataFrame(const uint8_t *buffer, uint32_t total_sz); - Dot11DataFrame(const Dot11DataFrame &other); - - uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); - void copy_ext_header(const Dot11DataFrame *other); - private: ExtendedHeader _ext_header; uint8_t _addr4[6]; @@ -1208,7 +1090,7 @@ namespace Tins { /** * \brief Getter for the interval field. * - * \return Timestamp value in an uint64_t. + * \return Timestamp value in an uint16_t. */ inline uint16_t interval() const { return Utils::net_to_host_s(this->_body.interval); } @@ -1288,6 +1170,19 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_BEACON; } private: struct BeaconBody { uint64_t timestamp; @@ -1298,7 +1193,6 @@ namespace Tins { void copy_fields(const Dot11Beacon *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); - BeaconBody _body; }; @@ -1359,6 +1253,13 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct DisassocBody { uint16_t reason_code; @@ -1501,6 +1402,13 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct AssocReqBody { CapabilityInformation capability; @@ -1631,6 +1539,13 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: struct AssocRespBody { CapabilityInformation capability; @@ -1644,7 +1559,132 @@ namespace Tins { AssocRespBody _body; }; - class Dot11QoSData : public Dot11DataFrame { + class Dot11Data : public Dot11 { + public: + /** + * \brief Constructor which creates a Dot11Data 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. + */ + Dot11Data(uint32_t iface_index, const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0); + Dot11Data(const uint8_t *dst_hw_addr = 0, const uint8_t *src_hw_addr = 0, PDU* child = 0); + Dot11Data(const std::string &iface, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child = 0) throw (std::runtime_error); + Dot11Data(const uint8_t *buffer, uint32_t total_sz); + /** + * \brief Getter for the second address. + * + * \return The second address as a constant uint8_t pointer. + */ + inline const uint8_t* addr2() const { return this->_ext_header.addr2; } + + /** + * \brief Getter for the third address. + * + * \return The third address as a constant uint8_t pointer. + */ + inline const uint8_t* addr3() const { return this->_ext_header.addr3; } + + /** + * \brief Getter for the fragment number. + * + * \return The fragment number as an uint8_t. + */ + inline uint8_t frag_num() const { return this->_ext_header.seq_control.frag_number; } + + /** + * \brief Getter for the sequence number. + * + * \return The sequence number as an uint16_t. + */ + inline uint16_t seq_num() const { return this->_ext_header.seq_control.seq_number; } + + /** + * \brief Getter for the fourth address. + * + * \return The fourth address as a constant uint8_t pointer. + */ + inline const uint8_t* addr4() const { return this->_addr4; } + + /** + * \brief Setter for the second address. + * + * \param new_addr2 const uint8_t array of 6 bytes containing the new second's address. + */ + void addr2(const uint8_t* new_addr2); + + /** + * \brief Setter for the third address. + * + * \param new_addr3 const uint8_t array of 6 bytes containing the new third address. + */ + void addr3(const uint8_t* new_addr3); + + /** + * \brief Setter for the fragment number. + * + * \param new_frag_num uint8_t with the new fragment number. + */ + void frag_num(uint8_t new_frag_num); + + /** + * \brief Setter for the sequence number. + * + * \param new_seq_num uint16_t with the new sequence number. + */ + void seq_num(uint16_t new_seq_num); + + /** + * \brief Setter for the fourth address. + * + * \param new_addr4 const uint8_t array of 6 bytes containing the new fourth address. + */ + void addr4(const uint8_t* new_addr4); + + /** + * \brief Returns the 802.11 frame's header length. + * + * \return An uint32_t with the header's size. + * \sa PDU::header_size() + */ + uint32_t header_size() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_DATA; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; + protected: + struct ExtendedHeader { + uint8_t addr2[6]; + uint8_t addr3[6]; + struct { + #if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int seq_number:12; + unsigned int frag_number:4; + #elif __BYTE_ORDER == __BIG_ENDIAN + unsigned int frag_number:4; + unsigned int seq_number:12; + #endif + } __attribute__((__packed__)) seq_control; + } __attribute__((__packed__)); + + uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); + void copy_ext_header(const Dot11Data *other); + + private: + ExtendedHeader _ext_header; + uint8_t _addr4[6]; + }; + + class Dot11QoSData : public Dot11Data { public: @@ -1724,6 +1764,19 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_QOS_DATA; } private: void copy_fields(const Dot11QoSData *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); @@ -1778,6 +1831,12 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11Control(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_CONTROL; } }; /** @@ -1853,7 +1912,7 @@ namespace Tins { /** * \brief Getter for the control ta additional fields size. */ - uint32_t controlta_size() const { return sizeof(_taddr); } + uint32_t controlta_size() const { return sizeof(_taddr) + sizeof(ieee80211_header); } uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); private: @@ -1907,6 +1966,19 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11RTS(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_RTS; } }; class Dot11PSPoll : public Dot11ControlTA { @@ -1955,6 +2027,13 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; }; class Dot11CFEnd : public Dot11ControlTA { @@ -2003,6 +2082,13 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; }; class Dot11EndCFAck : public Dot11ControlTA { @@ -2048,6 +2134,13 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; }; class Dot11Ack : public Dot11Control { @@ -2094,6 +2187,19 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11Ack(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_ACK; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; }; /** @@ -2178,6 +2284,13 @@ namespace Tins { * \param bar The new start sequence field. */ void start_sequence(uint16_t seq); + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; protected: /** * \brief Getter for the control ta additional fields size. @@ -2268,10 +2381,23 @@ namespace Tins { * \param bit The new bitmap field to be set. */ void bitmap(const uint8_t *bit); + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_BLOCK_ACK; } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; private: uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); - uint8_t _bitmap[128]; + uint8_t _bitmap[8]; }; }; diff --git a/src/dot11.cpp b/src/dot11.cpp index 71176e8..e11f523 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #ifndef WIN32 #include #include @@ -42,8 +43,10 @@ const uint8_t *Tins::Dot11::BROADCAST = (const uint8_t*)"\xff\xff\xff\xff\xff\xf Tins::Dot11::Dot11(const uint8_t* dst_hw_addr, PDU* child) : PDU(ETHERTYPE_IP, child), _options_size(0) { memset(&this->_header, 0, sizeof(ieee80211_header)); - if(dst_hw_addr) + if(dst_hw_addr) { + this->addr1(dst_hw_addr); + } } Tins::Dot11::Dot11(const std::string& iface, const uint8_t* dst_hw_addr, PDU* child) throw (std::runtime_error) : PDU(ETHERTYPE_IP, child), _options_size(0) { @@ -72,10 +75,6 @@ Tins::Dot11::Dot11(const uint8_t *buffer, uint32_t total_sz) : PDU(ETHERTYPE_IP) std::memcpy(&_header, buffer, sz); buffer += sz; total_sz -= sz; - if(type() == 2 && subtype() < 4) { - // It's a data packet - inner_pdu(new Tins::SNAP(buffer, total_sz)); - } } Tins::Dot11::Dot11(const Dot11 &other) : PDU(other) { @@ -169,7 +168,7 @@ void Tins::Dot11::order(bool new_value) { } void Tins::Dot11::duration_id(uint16_t new_duration_id) { - this->_header.duration_id = Utils::net_to_host_s(new_duration_id); + this->_header.duration_id = new_duration_id; } void Tins::Dot11::addr1(const uint8_t* new_addr1) { @@ -208,17 +207,17 @@ bool Tins::Dot11::send(PacketSender* sender) { void Tins::Dot11::write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent) { uint32_t my_sz = header_size(); assert(total_sz >= my_sz); - memcpy(buffer, &this->_header, sizeof(ieee80211_header)); - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); + memcpy(buffer, &_header, sizeof(_header)); + buffer += sizeof(_header); + total_sz -= sizeof(_header); uint32_t written = this->write_ext_header(buffer, total_sz); buffer += written; total_sz -= written; - uint32_t child_len = write_fixed_parameters(buffer, total_sz - sizeof(ieee80211_header) - _options_size); + uint32_t child_len = write_fixed_parameters(buffer, total_sz - _options_size); buffer += child_len; - assert(total_sz > child_len + _options_size); + assert(total_sz >= child_len + _options_size); for(std::list::const_iterator it = _options.begin(); it != _options.end(); ++it) { *(buffer++) = it->option; *(buffer++) = it->length; @@ -233,11 +232,33 @@ Tins::PDU *Tins::Dot11::from_bytes(const uint8_t *buffer, uint32_t total_sz) { 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 == MANAGEMENT && 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 Dot11Beacon(buffer, total_sz); } + else if(hdr->control.type == DATA){ + if(hdr->control.subtype <= 4) + ret = new Dot11Data(buffer, total_sz); + else + ret = new Dot11QoSData(buffer, total_sz); + } + else if(hdr->control.type == CONTROL){ + if(hdr->control.subtype == ACK) + ret = new Dot11Ack(buffer, total_sz); + else if(hdr->control.subtype == CF_END) + ret = new Dot11CFEnd(buffer, total_sz); + else if(hdr->control.subtype == CF_END_ACK) + ret = new Dot11EndCFAck(buffer, total_sz); + else if(hdr->control.subtype == PS) + ret = new Dot11PSPoll(buffer, total_sz); + else if(hdr->control.subtype == RTS) + ret = new Dot11RTS(buffer, total_sz); + else if(hdr->control.subtype == BLOCK_ACK) + ret = new Dot11BlockAck(buffer, total_sz); + else if(hdr->control.subtype == BLOCK_ACK_REQ) + ret = new Dot11BlockAckRequest(buffer, total_sz); + } else ret = new Dot11(buffer, total_sz); return ret; @@ -251,34 +272,44 @@ void Tins::Dot11::copy_80211_fields(const Dot11 *other) { _options.push_back(Dot11_Option(it->option, it->length, it->value)); } -/* - * Dot11ManagementFrame - */ +/* Dot11ManagementFrame */ Tins::Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { - + buffer += sizeof(ieee80211_header); + total_sz -= sizeof(ieee80211_header); + if(total_sz < sizeof(_ext_header)) + throw std::runtime_error("Not enough size for an IEEE 802.11 header in the buffer."); + std::memcpy(&_ext_header, buffer, sizeof(_ext_header)); + if(from_ds() && to_ds()) + std::memcpy(_addr4, buffer + sizeof(_ext_header), sizeof(_addr4)); } Tins::Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr) : Dot11(dst_hw_addr) { this->type(Dot11::MANAGEMENT); - this->addr2(src_hw_addr); + if(src_hw_addr) + addr2(src_hw_addr); + else + std::memset(_ext_header.addr2, 0, sizeof(_ext_header.addr2)); } Tins::Dot11ManagementFrame::Dot11ManagementFrame(const std::string &iface, - const uint8_t *dst_hw_addr, - const uint8_t *src_hw_addr) throw (std::runtime_error) : Dot11(iface, dst_hw_addr) { + const uint8_t *dst_hw_addr, + const uint8_t *src_hw_addr) throw (std::runtime_error) : Dot11(iface, dst_hw_addr) { this->type(Dot11::MANAGEMENT); - this->addr2(src_hw_addr); + if(src_hw_addr) + addr2(src_hw_addr); + else + std::memset(_ext_header.addr2, 0, sizeof(_ext_header.addr2)); } Tins::Dot11ManagementFrame::Dot11ManagementFrame(const Dot11ManagementFrame &other) : Dot11(other) { - + copy_ext_header(&other); } void Tins::Dot11ManagementFrame::copy_ext_header(const Dot11ManagementFrame* other) { Dot11::copy_80211_fields(other); - std::memcpy(&this->_ext_header, &other->_ext_header, sizeof(this->_ext_header)); - std::memcpy(this->_addr4, other->_addr4, 6); + std::memcpy(&_ext_header, &other->_ext_header, sizeof(_ext_header)); + std::memcpy(_addr4, other->_addr4, 6); } uint32_t Tins::Dot11ManagementFrame::header_size() const { @@ -301,7 +332,7 @@ void Tins::Dot11ManagementFrame::frag_num(uint8_t new_frag_num) { } void Tins::Dot11ManagementFrame::seq_num(uint16_t new_seq_num) { - this->_ext_header.seq_control.seq_number = Utils::net_to_host_s(new_seq_num); + this->_ext_header.seq_control.seq_number = new_seq_num; } void Tins::Dot11ManagementFrame::addr4(const uint8_t* new_addr4) { @@ -309,15 +340,14 @@ void Tins::Dot11ManagementFrame::addr4(const uint8_t* new_addr4) { } uint32_t Tins::Dot11ManagementFrame::write_ext_header(uint8_t *buffer, uint32_t total_sz) { - uint32_t written = sizeof(this->_ext_header); - memcpy(buffer, &this->_ext_header, sizeof(this->_ext_header)); - buffer += sizeof(this->_ext_header); - if (this->from_ds() && this->to_ds()) { + uint32_t written = sizeof(_ext_header); + memcpy(buffer, &_ext_header, sizeof(this->_ext_header)); + buffer += sizeof(_ext_header); + if (from_ds() && to_ds()) { written += 6; - memcpy(buffer, this->_addr4, 6); + memcpy(buffer, _addr4, 6); } return written; - } void Tins::Dot11ManagementFrame::ssid(const std::string &new_ssid) { @@ -405,85 +435,7 @@ void Tins::Dot11ManagementFrame::edca_parameter_set(uint32_t ac_be, uint32_t ac_ delete[] buffer; } -/* - * Dot11DataFrame - */ - -Tins::Dot11DataFrame::Dot11DataFrame(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { - -} - -Tins::Dot11DataFrame::Dot11DataFrame(uint32_t iface_index, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(iface_index, dst_hw_addr, child) { - this->type(Dot11::DATA); - this->addr2(src_hw_addr); -} - -Tins::Dot11DataFrame::Dot11DataFrame(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(dst_hw_addr, child) { - this->type(Dot11::DATA); - this->addr2(src_hw_addr); -} - - -Tins::Dot11DataFrame::Dot11DataFrame(const std::string &iface, - const uint8_t *dst_hw_addr, - const uint8_t *src_hw_addr, - PDU* child) throw (std::runtime_error) : Dot11(iface, dst_hw_addr, child) { - this->type(Dot11::DATA); - this->addr2(src_hw_addr); -} - -Tins::Dot11DataFrame::Dot11DataFrame(const Dot11DataFrame &other) : Dot11(other) { - -} - -void Tins::Dot11DataFrame::copy_ext_header(const Dot11DataFrame* other) { - Dot11::copy_80211_fields(other); - std::memcpy(&this->_ext_header, &other->_ext_header, sizeof(this->_ext_header)); - std::memcpy(this->_addr4, other->_addr4, 6); -} - -uint32_t Tins::Dot11DataFrame::header_size() const { - uint32_t sz = Dot11::header_size() + sizeof(_ext_header); - if (this->from_ds() && this->to_ds()) - sz += 6; - return sz; -} - -void Tins::Dot11DataFrame::addr2(const uint8_t* new_addr2) { - memcpy(this->_ext_header.addr2, new_addr2, 6); -} - -void Tins::Dot11DataFrame::addr3(const uint8_t* new_addr3) { - memcpy(this->_ext_header.addr3, new_addr3, 6); -} - -void Tins::Dot11DataFrame::frag_num(uint8_t new_frag_num) { - this->_ext_header.seq_control.frag_number = new_frag_num; -} - -void Tins::Dot11DataFrame::seq_num(uint16_t new_seq_num) { - this->_ext_header.seq_control.seq_number = Utils::net_to_host_s(new_seq_num); -} - -void Tins::Dot11DataFrame::addr4(const uint8_t* new_addr4) { - memcpy(this->_addr4, new_addr4, 6); -} - -uint32_t Tins::Dot11DataFrame::write_ext_header(uint8_t *buffer, uint32_t total_sz) { - uint32_t written = sizeof(this->_ext_header); - memcpy(buffer, &this->_ext_header, sizeof(this->_ext_header)); - buffer += sizeof(this->_ext_header); - if (this->from_ds() && this->to_ds()) { - written += 6; - memcpy(buffer, this->_addr4, 6); - } - return written; - -} - -/* - * Beacon - */ +/* Dot11Beacon */ Tins::Dot11Beacon::Dot11Beacon(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : Dot11ManagementFrame() { this->subtype(Dot11::BEACON); @@ -498,8 +450,9 @@ Tins::Dot11Beacon::Dot11Beacon(const std::string& iface, } Tins::Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); + uint32_t sz = Dot11ManagementFrame::header_size(); + buffer += sz; + total_sz -= sz; if(total_sz < sizeof(_body)) throw std::runtime_error("Not enough size for a IEEE 802.11 beacon header in the buffer."); memcpy(&_body, buffer, sizeof(_body)); @@ -509,7 +462,7 @@ Tins::Dot11Beacon::Dot11Beacon(const uint8_t *buffer, uint32_t total_sz) : Dot11 } Tins::Dot11Beacon::Dot11Beacon(const Dot11Beacon &other) : Dot11ManagementFrame(other) { - + copy_fields(&other); } Tins::Dot11Beacon &Tins::Dot11Beacon::operator= (const Dot11Beacon &other) { @@ -594,16 +547,22 @@ bool Tins::Dot11Beacon::rsn_information(RSNInformation *rsn) { } uint32_t Tins::Dot11Beacon::header_size() const { - return Dot11ManagementFrame::header_size() + sizeof(BeaconBody); + return Dot11ManagementFrame::header_size() + sizeof(_body); } uint32_t Tins::Dot11Beacon::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { - uint32_t sz = sizeof(BeaconBody); + uint32_t sz = sizeof(_body); assert(sz <= total_sz); memcpy(buffer, &this->_body, sz); return sz; } +Tins::PDU *Tins::Dot11Beacon::clone_pdu() const { + Dot11Beacon *new_pdu = new Dot11Beacon(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* 802.11 diassoc */ Tins::Dot11Disassoc::Dot11Disassoc() : Dot11ManagementFrame() { @@ -648,9 +607,14 @@ uint32_t Tins::Dot11Disassoc::write_fixed_parameters(uint8_t *buffer, uint32_t t return sz; } -/* - * RSNInformation class - */ +Tins::PDU *Tins::Dot11Disassoc::clone_pdu() const { + Dot11Disassoc *new_pdu = new Dot11Disassoc(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + +/* RSNInformation */ + Tins::RSNInformation::RSNInformation() : _version(1), _capabilities(0) { } @@ -724,8 +688,9 @@ Tins::Dot11AssocRequest::Dot11AssocRequest(const std::string& iface, } Tins::Dot11AssocRequest::Dot11AssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); + uint32_t sz = Dot11ManagementFrame::header_size(); + buffer += sz; + total_sz -= sz; 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)); @@ -792,6 +757,12 @@ uint32_t Tins::Dot11AssocRequest::write_fixed_parameters(uint8_t *buffer, uint32 return sz; } +Tins::PDU *Tins::Dot11AssocRequest::clone_pdu() const { + Dot11AssocRequest *new_pdu = new Dot11AssocRequest(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Assoc response. */ Tins::Dot11AssocResponse::Dot11AssocResponse() : Dot11ManagementFrame() { @@ -863,21 +834,123 @@ uint32_t Tins::Dot11AssocResponse::write_fixed_parameters(uint8_t *buffer, uint3 return sz; } +Tins::PDU *Tins::Dot11AssocResponse::clone_pdu() const { + Dot11AssocResponse *new_pdu = new Dot11AssocResponse(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + +/* Dot11Data */ + +Tins::Dot11Data::Dot11Data(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { + uint32_t sz = Dot11::header_size(); + buffer += sz; + total_sz -= sz; + if(total_sz < sizeof(_ext_header)) + throw std::runtime_error("Not enough size for an IEEE 802.11 data header in the buffer."); + std::memcpy(&_ext_header, buffer, sizeof(_ext_header)); + buffer += sizeof(_ext_header); + total_sz -= sizeof(_ext_header); + if(from_ds() && to_ds()) { + if(total_sz < sizeof(_addr4)) + throw std::runtime_error("Not enough size for an IEEE 802.11 data header in the buffer."); + std::memcpy(&_addr4, buffer, sizeof(_addr4)); + buffer += sizeof(_addr4); + total_sz -= sizeof(_addr4); + } + inner_pdu(new Tins::SNAP(buffer, total_sz)); +} + +Tins::Dot11Data::Dot11Data(uint32_t iface_index, const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(iface_index, dst_hw_addr, child) { + this->type(Dot11::DATA); + this->addr2(src_hw_addr); +} + +Tins::Dot11Data::Dot11Data(const uint8_t *dst_hw_addr, const uint8_t *src_hw_addr, PDU* child) : Dot11(dst_hw_addr, child) { + this->type(Dot11::DATA); + this->addr2(src_hw_addr); +} + + +Tins::Dot11Data::Dot11Data(const std::string &iface, + const uint8_t *dst_hw_addr, + const uint8_t *src_hw_addr, + PDU* child) throw (std::runtime_error) : Dot11(iface, dst_hw_addr, child) { + this->type(Dot11::DATA); + this->addr2(src_hw_addr); +} + +void Tins::Dot11Data::copy_ext_header(const Dot11Data* other) { + Dot11::copy_80211_fields(other); + std::memcpy(&this->_ext_header, &other->_ext_header, sizeof(this->_ext_header)); + std::memcpy(this->_addr4, other->_addr4, 6); +} + +uint32_t Tins::Dot11Data::header_size() const { + uint32_t sz = Dot11::header_size() + sizeof(_ext_header); + if (this->from_ds() && this->to_ds()) + sz += 6; + return sz; +} + +void Tins::Dot11Data::addr2(const uint8_t* new_addr2) { + memcpy(this->_ext_header.addr2, new_addr2, 6); +} + +void Tins::Dot11Data::addr3(const uint8_t* new_addr3) { + memcpy(this->_ext_header.addr3, new_addr3, 6); +} + +void Tins::Dot11Data::frag_num(uint8_t new_frag_num) { + this->_ext_header.seq_control.frag_number = new_frag_num; +} + +void Tins::Dot11Data::seq_num(uint16_t new_seq_num) { + this->_ext_header.seq_control.seq_number = new_seq_num; +} + +void Tins::Dot11Data::addr4(const uint8_t* new_addr4) { + memcpy(this->_addr4, new_addr4, 6); +} + +uint32_t Tins::Dot11Data::write_ext_header(uint8_t *buffer, uint32_t total_sz) { + uint32_t written = sizeof(this->_ext_header); + memcpy(buffer, &this->_ext_header, sizeof(this->_ext_header)); + buffer += sizeof(this->_ext_header); + if (this->from_ds() && this->to_ds()) { + written += 6; + memcpy(buffer, this->_addr4, 6); + } + return written; + +} + +Tins::PDU *Tins::Dot11Data::clone_pdu() const { + Dot11Data *new_pdu = new Dot11Data(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* QoS data. */ -Tins::Dot11QoSData::Dot11QoSData(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : Dot11DataFrame(iface, dst_hw_addr, src_hw_addr, child) { +Tins::Dot11QoSData::Dot11QoSData(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11Data(dst_hw_addr, src_hw_addr, child) { + +} + +Tins::Dot11QoSData::Dot11QoSData(const std::string& iface, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) throw (std::runtime_error) : Dot11Data(iface, dst_hw_addr, src_hw_addr, child) { this->subtype(Dot11::QOS_DATA_DATA); this->_qos_control = 0; } -Tins::Dot11QoSData::Dot11QoSData(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11DataFrame(iface_index, dst_hw_addr, src_hw_addr, child) { +Tins::Dot11QoSData::Dot11QoSData(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr, PDU* child) : Dot11Data(iface_index, dst_hw_addr, src_hw_addr, child) { this->subtype(Dot11::QOS_DATA_DATA); this->_qos_control = 0; } -Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot11DataFrame(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); +Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot11Data(buffer, total_sz) { + uint32_t sz = Dot11Data::header_size(); + buffer += sz; + total_sz -= sz; assert(total_sz >= sizeof(this->_qos_control)); this->_qos_control = *(uint16_t*)buffer; total_sz -= sizeof(uint16_t); @@ -886,7 +959,7 @@ Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot inner_pdu(new Tins::SNAP(buffer, total_sz)); } -Tins::Dot11QoSData::Dot11QoSData(const Dot11QoSData &other) : Dot11DataFrame(other) { +Tins::Dot11QoSData::Dot11QoSData(const Dot11QoSData &other) : Dot11Data(other) { copy_fields(&other); } @@ -897,7 +970,7 @@ Tins::Dot11QoSData &Tins::Dot11QoSData::operator= (const Dot11QoSData &other) { } void Tins::Dot11QoSData::copy_fields(const Dot11QoSData *other) { - Dot11DataFrame::copy_ext_header(other); + Dot11Data::copy_ext_header(other); _qos_control = other->_qos_control; } @@ -916,7 +989,14 @@ uint32_t Tins::Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t to return sz; } +Tins::PDU *Tins::Dot11QoSData::clone_pdu() const { + Dot11QoSData *new_pdu = new Dot11QoSData(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11Control */ + Tins::Dot11Control::Dot11Control(const uint8_t* dst_addr, PDU* child) : Dot11(dst_addr, child) { type(CONTROL); } @@ -994,6 +1074,12 @@ Tins::Dot11RTS::Dot11RTS(const uint8_t *buffer, uint32_t total_sz) : Dot11Contro } +Tins::PDU *Tins::Dot11RTS::clone_pdu() const { + Dot11RTS *new_pdu = new Dot11RTS(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11PSPoll */ Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { @@ -1012,6 +1098,12 @@ Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz) : Dot11 } +Tins::PDU *Tins::Dot11PSPoll::clone_pdu() const { + Dot11PSPoll *new_pdu = new Dot11PSPoll(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11CFEnd */ Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { @@ -1030,6 +1122,12 @@ Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz) : Dot11Co } +Tins::PDU *Tins::Dot11CFEnd::clone_pdu() const { + Dot11CFEnd *new_pdu = new Dot11CFEnd(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11EndCFAck */ Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { @@ -1048,6 +1146,12 @@ Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz) : D } +Tins::PDU *Tins::Dot11EndCFAck::clone_pdu() const { + Dot11EndCFAck *new_pdu = new Dot11EndCFAck(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11Ack */ Tins::Dot11Ack::Dot11Ack(const uint8_t* dst_addr, PDU* child) : Dot11Control(dst_addr, child) { @@ -1066,6 +1170,12 @@ Tins::Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz) : Dot11Contro } +Tins::PDU *Tins::Dot11Ack::clone_pdu() const { + Dot11Ack *ack = new Dot11Ack(); + ack->copy_80211_fields(this); + return ack; +} + /* Dot11BlockAck */ Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { @@ -1092,7 +1202,7 @@ Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t } void Tins::Dot11BlockAckRequest::init_block_ack() { - subtype(BLOCK_ACK); + subtype(BLOCK_ACK_REQ); std::memset(&_bar_control, 0, sizeof(_bar_control)); std::memset(&_start_sequence, 0, sizeof(_start_sequence)); } @@ -1118,16 +1228,25 @@ uint32_t Tins::Dot11BlockAckRequest::header_size() const { return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence); } +Tins::PDU *Tins::Dot11BlockAckRequest::clone_pdu() const { + Dot11BlockAckRequest *new_pdu = new Dot11BlockAckRequest(); + new_pdu->copy_80211_fields(this); + return new_pdu; +} + /* Dot11BlockAck */ Tins::Dot11BlockAck::Dot11BlockAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11BlockAckRequest(dst_addr, target_addr, child) { + subtype(BLOCK_ACK); std::memset(_bitmap, 0, sizeof(_bitmap)); } Tins::Dot11BlockAck::Dot11BlockAck(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11BlockAckRequest(iface, dst_addr, target_addr, child) { + subtype(BLOCK_ACK); std::memset(_bitmap, 0, sizeof(_bitmap)); } Tins::Dot11BlockAck::Dot11BlockAck(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) : Dot11BlockAckRequest(iface_index, dst_addr, target_addr, child) { + subtype(BLOCK_ACK); std::memset(_bitmap, 0, sizeof(_bitmap)); } @@ -1154,3 +1273,9 @@ uint32_t Tins::Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_s uint32_t Tins::Dot11BlockAck::header_size() const { return Dot11BlockAckRequest::header_size() + sizeof(_bitmap); } + +Tins::PDU *Tins::Dot11BlockAck::clone_pdu() const { + Dot11BlockAck *new_pdu = new Dot11BlockAck(); + new_pdu->copy_80211_fields(this); + return new_pdu; +}