diff --git a/include/dot11.h b/include/dot11.h index b6e18cd..b1eeef8 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, @@ -988,7 +989,6 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; - protected: struct ExtendedHeader { uint8_t addr2[6]; @@ -1028,7 +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]; @@ -1036,8 +1035,18 @@ namespace Tins { }; class Dot11DataFrame : public Dot11 { - public: + /** + * \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); /** * \brief Getter for the second address. * @@ -1116,6 +1125,11 @@ namespace Tins { */ uint32_t header_size() const; + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return PDU::DOT11_DATA; } protected: struct ExtendedHeader { uint8_t addr2[6]; @@ -1131,18 +1145,6 @@ namespace Tins { } __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); @@ -1298,7 +1300,6 @@ namespace Tins { void copy_fields(const Dot11Beacon *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); - BeaconBody _body; }; @@ -1724,6 +1725,12 @@ namespace Tins { * \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_QOS_DATA; } private: void copy_fields(const Dot11QoSData *other); uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); @@ -1778,6 +1785,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 +1866,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 +1920,12 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11RTS(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_RTS; } }; class Dot11PSPoll : public Dot11ControlTA { @@ -2094,6 +2113,12 @@ 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; } }; /** @@ -2268,10 +2293,16 @@ 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; } private: uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); - uint8_t _bitmap[128]; + uint8_t _bitmap[8]; }; }; diff --git a/include/pdu.h b/include/pdu.h index c6cc06a..7f5ca29 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -53,6 +53,12 @@ namespace Tins { RAW, ETHERNET_II, DOT11, + DOT11_DATA, + DOT11_QOS_DATA, + DOT11_CONTROL, + DOT11_ACK, + DOT11_BLOCK_ACK, + DOT11_RTS, SNAP, RADIOTAP, IP, diff --git a/src/dot11.cpp b/src/dot11.cpp index 71176e8..ff57668 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -208,17 +208,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 +233,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 Dot11DataFrame(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; @@ -261,24 +283,30 @@ Tins::Dot11ManagementFrame::Dot11ManagementFrame(const uint8_t *buffer, uint32_t 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) { 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 { @@ -309,15 +337,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) { @@ -481,9 +508,7 @@ uint32_t Tins::Dot11DataFrame::write_ext_header(uint8_t *buffer, uint32_t total_ } -/* - * Beacon - */ +/* Dot11Beacon */ Tins::Dot11Beacon::Dot11Beacon(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : Dot11ManagementFrame() { this->subtype(Dot11::BEACON); @@ -509,7 +534,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,11 +619,11 @@ 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; @@ -876,8 +901,9 @@ Tins::Dot11QoSData::Dot11QoSData(uint32_t iface_index, const uint8_t* dst_hw_add } Tins::Dot11QoSData::Dot11QoSData(const uint8_t *buffer, uint32_t total_sz) : Dot11DataFrame(buffer, total_sz) { - buffer += sizeof(ieee80211_header); - total_sz -= sizeof(ieee80211_header); + uint32_t sz = Dot11DataFrame::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); @@ -1092,7 +1118,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)); } @@ -1120,14 +1146,17 @@ uint32_t Tins::Dot11BlockAckRequest::header_size() const { /* 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)); }