From 65f689027da621b9328dc489239d0840114b187a Mon Sep 17 00:00:00 2001 From: Matias Fontanini Date: Mon, 5 Sep 2011 12:03:44 -0300 Subject: [PATCH] Started refactoring 802.11 control frames. --- include/dot11.h | 549 +++++++++++++++++++++++++++++++++++++++++++++++- src/dot11.cpp | 238 +++++++++++++++++++++ 2 files changed, 783 insertions(+), 4 deletions(-) diff --git a/include/dot11.h b/include/dot11.h index 0cd404c..f95c4f7 100644 --- a/include/dot11.h +++ b/include/dot11.h @@ -114,12 +114,13 @@ namespace Tins { * */ enum ControlSubtypes { + BLOCK_ACK = 9, PS = 10, RTS = 11, CTS = 12, ACK = 13, - CF = 14, - CFE_CFA = 15 + CF_END = 14, + CF_END_ACK = 15 }; /** @@ -1161,7 +1162,6 @@ namespace Tins { */ uint32_t header_size() const; private: - struct BeaconBody { uint64_t timestamp; uint16_t interval; @@ -1605,6 +1605,547 @@ namespace Tins { uint16_t _qos_control; }; -} + /** + * \brief Class that represents an 802.11 control frame. + */ + class Dot11Control : public Dot11 { + public: + /** + * \brief Constructor for creating a 802.11 control frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Control(const uint8_t* dst_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 control frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Control(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0) throw (std::runtime_error); + + /** + * \brief Constructor for creating an 802.11 control frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Control(uint32_t iface_index, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor which creates an 802.11 control frame 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. + */ + Dot11Control(const uint8_t *buffer, uint32_t total_sz); + }; + + /** + * \brief Class that represents an abstraction of the 802.11 control frames + * that contain a target address. + */ + class Dot11ControlTA : public Dot11Control { + protected: + /** + * \brief Constructor for creating a 802.11 control frame TA PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11ControlTA(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 control frame TA PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11ControlTA(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0) throw (std::runtime_error); + + /** + * \brief Constructor for creating an 802.11 control frame TA PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11ControlTA(uint32_t iface_index, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor which creates an 802.11 control frame 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. + */ + Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Getter for the target address field. + */ + inline const uint8_t* target_addr() const { return _taddr; } + + /** + * \brief Setter for the target address field. + * \param addr The new target address. + */ + void target_addr(const uint8_t *addr); + + /** + * \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: + /** + * \brief Getter for the control ta additional fields size. + */ + uint32_t controlta_size() const { return sizeof(_taddr); } + private: + uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); + + uint8_t _taddr[6]; + }; + + class Dot11RTS : public Dot11ControlTA { + public: + /** + * \brief Constructor for creating a 802.11 RTS frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11RTS(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 RTS frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11RTS(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0) throw (std::runtime_error); + + /** + * \brief Constructor for creating an 802.11 RTS frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11RTS(uint32_t iface_index, const uint8_t* dst_hw_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor which creates an 802.11 RTS frame 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. + */ + Dot11RTS(const uint8_t *buffer, uint32_t total_sz); + }; + + class Dot11PSPoll : public Dot11ControlTA { + public: + /** + * \brief Constructor for creating a 802.11 PS-Poll frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11PSPoll(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 PS-Poll frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11PSPoll(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 PS-Poll frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11PSPoll(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 PS-Poll frame 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. + */ + Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz); + }; + + class Dot11CFEnd : public Dot11ControlTA { + public: + /** + * \brief Constructor for creating a 802.11 CF-End frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11CFEnd(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 CF-End frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11CFEnd(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 CF-End frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11CFEnd(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 CF-End frame 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. + */ + Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz); + }; + + class Dot11EndCFAck : public Dot11ControlTA { + public: + /** + * \brief Constructor for creating a 802.11 End-CF-Ack frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11EndCFAck(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 End-CF-Ack frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11EndCFAck(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 End-CF-Ack frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11EndCFAck(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 End-CF-Ack frame 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. + */ + Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz); + }; + + class Dot11Ack : public Dot11Control { + public: + /** + * \brief Constructor for creating a 802.11 Ack frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Ack(const uint8_t* dst_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 Ack frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Ack(const std::string& iface, const uint8_t* dst_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 Ack frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11Ack(uint32_t iface_index, const uint8_t* dst_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 Ack frame 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. + */ + Dot11Ack(const uint8_t *buffer, uint32_t total_sz); + }; + + /** + * \brief Class that represents an 802.11 Block Ack Request PDU. + */ + class Dot11BlockAckRequest : public Dot11ControlTA { + public: + /** + * \brief Constructor for creating a 802.11 Block Ack request frame PDU + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAckRequest(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 Block Ack request frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAckRequest(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 Block Ack request frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAckRequest(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 Block Ack request frame 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. + */ + Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz); + + /* Getter */ + + /** + * \brief Getter for the bar control field. + * \return The bar control field. + */ + uint16_t bar_control() const { return _bar_control; } + + /** + * \brief Getter for the start sequence field. + * \return The bar start sequence. + */ + uint16_t start_sequence() const { return _start_sequence; } + + /** + * \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; + + /* Setter */ + + /** + * \brief Setter for the bar control field. + * \param bar The new bar control field. + */ + void bar_control(uint16_t bar); + + /** + * \brief Setter for the start sequence field. + * \param bar The new start sequence field. + */ + void start_sequence(uint16_t seq); + protected: + /** + * \brief Getter for the control ta additional fields size. + */ + uint32_t blockack_request_size() const { return controlta_size() + sizeof(_bar_control) + sizeof(_start_sequence); } + private: + struct BarControl { + uint16_t reserved:12, + tid:4; + } __attribute__((__packed__)); + + struct StartSequence { + uint16_t frag:4, + seq:12; + } __attribute__((__packed__)); + + void init_block_ack(); + uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); + + BarControl _bar_control; + StartSequence _start_sequence; + }; + + /** + * \brief Class that represents an 802.11 block ack frame. + */ + class Dot11BlockAck : public Dot11BlockAckRequest { + public: + /** + * \brief Constructor for creating a 802.11 Block Ack frame PDU. + * + * Constructor that builds a 802.11 PDU taking the destination's and source's MAC. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAck(const uint8_t* dst_addr = 0, const uint8_t* target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating a 802.11 Block Ack frame PDU + * + * Constructor that builds a 802.11 PDU taking the interface name, + * destination's and source's MAC. + * \param iface string containing the interface's name from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAck(const std::string& iface, const uint8_t* dst_addr = 0, const uint8_t *target_addr = 0, PDU* child = 0); + + /** + * \brief Constructor for creating an 802.11 Block Ack frame PDU + * + * Constructor that builds an 802.11 PDU taking the interface index, + * destination's and source's MAC. + * \param iface_index const uint32_t with the interface's index from where to send the packet. + * \param dst_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param target_addr uint8_t array of 6 bytes containing the source's MAC(optional). + * \param child PDU* with the PDU contained by the 802.11 PDU (optional). + */ + Dot11BlockAck(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child); + + /** + * \brief Constructor which creates an 802.11 Block Ack request frame 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. + */ + Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz); + + /** + * \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 bitmap field. + * \return The bitmap field. + */ + const uint8_t *bitmap() const { return _bitmap; } + + /** + * \brief Setter for the bitmap field. + * \param bit The new bitmap field to be set. + */ + void bitmap(const uint8_t bit); + private: + uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); + + uint8_t _bitmap[128]; + }; +}; + + #endif diff --git a/src/dot11.cpp b/src/dot11.cpp index 45e17a5..3193d74 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -829,3 +829,241 @@ uint32_t Tins::Dot11QoSData::write_fixed_parameters(uint8_t *buffer, uint32_t to *(uint16_t*)buffer = this->_qos_control; return sz; } + +/* Dot11Control */ +Tins::Dot11Control::Dot11Control(const uint8_t* dst_addr, PDU* child) : Dot11(dst_addr, child) { + type(CONTROL); +} + +Tins::Dot11ControlTA::Dot11ControlTA(const std::string& iface, const uint8_t* dst_addr, PDU* child) throw (std::runtime_error) : Dot11(iface, dst_addr, child) { + type(CONTROL); +} + +Tins::Dot11ControlTA::Dot11ControlTA(uint32_t iface_index, const uint8_t* dst_addr, PDU* child) : Dot11(iface_index, dst_addr, child) { + type(CONTROL); +} + +Tins::Dot11ControlTA::Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { + +} + +/* Dot11ControlTA */ +Tins::Dot11ControlTA::Dot11ControlTA(const uint8_t* dst_addr, const uint8_t *target_addres, PDU* child) : Dot11Control(dst_addr, child) { + if(target_addr) + target_addr(target_address); + else + std::memset(_taddr, 0, sizeof(_taddr)); +} + +Tins::Dot11ControlTA::Dot11ControlTA(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11Control(iface, dst_addr, child){ + if(target_addr) + target_addr(target_address); + else + std::memset(_taddr, 0, sizeof(_taddr)); +} + +Tins::Dot11ControlTA::Dot11ControlTA(uint32_t iface_index, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) : Dot11Control(iface_index, dst_addr, child) { + if(target_addr) + target_addr(target_address); + else + std::memset(_taddr, 0, sizeof(_taddr)); +} + +Tins::Dot11ControlTA::Dot11ControlTA(const uint8_t *buffer, uint32_t total_sz) : Dot11Control(buffer, total_sz) { + buffer += sizeof(ieee80211_header); + total_sz -= sizeof(ieee80211_header); + if(total_sz < sizeof(_taddr)) + throw std::runtime_error("Not enough size for an IEEE 802.11 RTS frame in the buffer."); + std::memcpy(_taddr, buffer, sizeof(_taddr)); +} + +uint32_t Tins::Dot11ControlTA::header_size() const { + return Dot11::header_size() + sizeof(_taddr); +} + +uint32_t Tins::Dot11ControlTA::write_ext_header(uint8_t *buffer, uint32_t total_sz) { + assert(total_sz >= sizeof(_taddr)); + std::memcpy(buffer, _taddr, sizeof(_taddr)); + return sizeof(_taddr); +} + +void Tins::Dot11ControlTA::target_addr(const uint8_t *addr) { + std::memcpy(_taddr, addr, sizeof(_taddr)); +} + +/* Dot11RTS */ +Tins::Dot11RTS::Dot11RTS(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { + subtype(RTS); +} + +Tins::Dot11RTS::Dot11RTS(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11ControlTA(iface, dst_addr, target_addr, child) { + subtype(RTS); +} + +Tins::Dot11RTS::Dot11RTS(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11ControlTA(iface_index, dst_addr, target_addr, child) { + subtype(RTS); +} + +Tins::Dot11RTS::Dot11RTS(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { + +} + +/* Dot11PSPoll */ +Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { + subtype(PS); +} + +Tins::Dot11PSPoll::Dot11PSPoll(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11ControlTA(iface, dst_addr, target_addr, child) { + subtype(PS); +} + +Tins::Dot11PSPoll::Dot11PSPoll(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11ControlTA(iface_index, dst_addr, target_addr, child) { + subtype(PS); +} + +Tins::Dot11PSPoll::Dot11PSPoll(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { + +} + +/* Dot11CFEnd */ + +Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { + subtype(CF_END); +} + +Tins::Dot11CFEnd::Dot11CFEnd(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11ControlTA(iface, dst_addr, target_addr, child) { + subtype(CF_END); +} + +Tins::Dot11CFEnd::Dot11CFEnd(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11ControlTA(iface_index, dst_addr, target_addr, child) { + subtype(CF_END); +} + +Tins::Dot11CFEnd::Dot11CFEnd(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { + +} + +/* Dot11EndCFAck */ + +Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { + subtype(CF_END_ACK); +} + +Tins::Dot11EndCFAck::Dot11EndCFAck(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11ControlTA(iface, dst_addr, target_addr, child) { + subtype(CF_END_ACK); +} + +Tins::Dot11EndCFAck::Dot11EndCFAck(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11ControlTA(iface_index, dst_addr, target_addr, child) { + subtype(CF_END_ACK); +} + +Tins::Dot11EndCFAck::Dot11EndCFAck(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { + +} + +/* Dot11Ack */ + +Tins::Dot11Ack::Dot11Ack(const uint8_t* dst_addr , PDU* child) : Dot11(dst_addr, target_addr, child) { + subtype(ACK); +} + +Tins::Dot11Ack::Dot11Ack(const std::string& iface, onst uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11(iface, dst_addr, child) { + subtype(ACK); +} + +Tins::Dot11Ack::Dot11Ack(uint32_t iface_index, const uint8_t* dst_hw_addr, PDU* child) : Dot11(iface_index, dst_addr, child) { + subtype(ACK); +} + +Tins::Dot11Ack::Dot11Ack(const uint8_t *buffer, uint32_t total_sz) : Dot11(buffer, total_sz) { + +} + +/* Dot11BlockAck */ + +Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11ControlTA(dst_addr, target_addr, child) { + init_block_ack(); +} + +Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const std::string& iface, const uint8_t* dst_addr, const uint8_t *target_addr, PDU* child) throw (std::runtime_error) : Dot11ControlTA(iface, dst_addr, target_addr, child) { + init_block_ack(); +} + +Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11ControlTA(iface_index, dst_addr, target_addr, child) { + init_block_ack(); +} + +Tins::Dot11BlockAckRequest::Dot11BlockAckRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ControlTA(buffer, total_sz) { + uint32_t padding = controlta_size(); + buffer += padding; + total_sz -= padding; + if(total_sz < sizeof(_bar_control) + sizeof(_start_sequence)) + throw std::runtime_error("Not enough size for an IEEE 802.11 Block Ack frame in the buffer."); + std::memcpy(&_bar_control, buffer, sizeof(_bar_control)); + buffer += sizeof(_bar_control); + std::memcpy(&_start_sequence, buffer, sizeof(_start_sequence)); +} + +void Tins::Dot11BlockAckRequest::init_block_ack() { + subtype(BLOCK_ACK); + std::memset(&_bar_control, 0, sizeof(_bar_control)); + std::memset(&_start_sequence, 0, sizeof(_start_sequence)); +} + +uint32_t Tins::Dot11BlockAckRequest::write_ext_header(uint8_t *buffer, uint32_t total_sz) { + uint32_t parent_size = Dot11ControlTA::write_ext_header(buffer, total_sz); + buffer += parent_size; + std::memcpy(buffer, _bar_control, sizeof(_bar_control)); + buffer += sizeof(_bar_control); + std::memcpy(buffer, _start_sequence, sizeof(_start_sequence)); + return parent_size + sizeof(_start_sequence); +} + +void Tins::Dot11BlockAckRequest::bar_control(uint16_t bar) { + std::memcpy(&_bar_control, &bar, sizeof(bar)); +} + +void Tins::Dot11BlockAckRequest::start_sequence(uint16_t seq) { + std::memcpy(&_start_sequence, &seq, sizeof(seq)); +} + +uint32_t Tins::Dot11BlockAckRequest::header_size() const { + return Dot11ControlTA::header_size() + sizeof(_start_sequence) + sizeof(_start_sequence); +} + +/* Dot11BlockAck */ +Tins::Dot11BlockAck::Dot11BlockAck(const uint8_t* dst_addr , const uint8_t* target_addr, PDU* child) : Dot11BlockAckRequest(dst_addr, target_addr, child) { + 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) { + std::memset(_bitmap, 0, sizeof(_bitmap)); +} + +Tins::Dot11BlockAck::Dot11BlockAck(uint32_t iface_index, const uint8_t* dst_hw_addr, const uint8_t *target_addr, PDU* child) : Dot11BlockAckRequest(iface_index, dst_addr, target_addr, child) { + std::memset(_bitmap, 0, sizeof(_bitmap)); +} + +Tins::Dot11BlockAck::Dot11BlockAck(const uint8_t *buffer, uint32_t total_sz) : Dot11BlockAckRequest(buffer, total_sz) { + uint32_t padding = blockack_request_size(); + buffer += padding; + total_sz -= padding; + if(total_sz < sizeof(_bitmap)) + throw std::runtime_error("Not enough size for an IEEE 802.11 Block Ack frame in the buffer."); + std::memcpy(&_bitmap, buffer, sizeof(_bitmap)); +} + +void Tins::Dot11BlockAck::bitmap(const uint8_t bit) { + std::memcpy(_bitmap, bit, sizeof(_bitmap)); +} + +uint32_t Tins::Dot11BlockAck::write_ext_header(uint8_t *buffer, uint32_t total_sz) { + uint32_t parent_size = Dot11BlockAckRequest::write_ext_header(buffer, total_sz); + buffer += parent_size; + std::memcpy(buffer, _bitmap, sizeof(_bitmap)); + return parent_size + sizeof(_bitmap); +} + +uint32_t Tins::Dot11BlockAck::header_size() const { + return Dot11BlockAckRequest::header_size() + sizeof(_bitmap)); +}