diff --git a/include/dot11.h b/include/dot11.h index 9e730de..36da870 100644 --- a/include/dot11.h +++ b/include/dot11.h @@ -464,7 +464,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11; + return flag == PDU::DOT11; } /** @@ -998,21 +998,21 @@ 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_MANAGEMENT; } - + /** * \brief Check wether this PDU matches the specified flag. * \param flag The flag to match * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_MANAGEMENT || Dot11::matches_flag(flag); + return flag == PDU::DOT11_MANAGEMENT || Dot11::matches_flag(flag); } protected: struct ExtendedHeader { @@ -1238,8 +1238,7 @@ namespace Tins { * \brief partial_virtual_bitmap uint8_t array with the value fo the Partial Virtual Bitmap field. * \brief partial_virtual_bitmap_sz uint8_t with the size of the partial_virtual_bitmap array. */ - void tim(uint8_t dtim_count, uint8_t dtim_period, uint8_t bitmap_control, uint8_t* partial_virtual_bitmap, uint8_t partial_virtual_bitmap_sz); - + void tim(uint8_t dtim_count, uint8_t dtim_period, uint8_t bitmap_control, uint8_t* partial_virtual_bitmap, uint8_t partial_virtual_bitmap_sz); uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); void copy_ext_header(const Dot11ManagementFrame *other); @@ -1497,6 +1496,13 @@ namespace Tins { */ void edca_parameter_set(uint32_t ac_be, uint32_t ac_bk, uint32_t ac_vi, uint32_t ac_vo); + /** + * \brief Helper method to set the QoS capability tagged option. + * + * \brief qos_info uint8_t with the QoS info byte. + */ + void qos_capabilities(uint8_t qos_info); + /** * \brief Helper method to search for the ESSID of this beacon. * @@ -1521,14 +1527,14 @@ namespace Tins { * \sa PDU::header_size() */ uint32_t header_size() const; - + /** * \brief Check wether this PDU matches the specified flag. * \param flag The flag to match * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_BEACON || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_BEACON || Dot11ManagementFrame::matches_flag(flag); } /** @@ -1626,7 +1632,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_DIASSOC || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_DIASSOC || Dot11ManagementFrame::matches_flag(flag); } /** @@ -1780,7 +1786,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_ASSOC_REQ || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_ASSOC_REQ || Dot11ManagementFrame::matches_flag(flag); } /** @@ -1923,7 +1929,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_ASSOC_RESP || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_ASSOC_RESP || Dot11ManagementFrame::matches_flag(flag); } /** @@ -1944,6 +1950,177 @@ namespace Tins { AssocRespBody _body; }; + /** + * \brief Class representing an ReAssociation Request frame in the IEEE 802.11 Protocol. + * + */ + class Dot11ReAssocRequest : public Dot11ManagementFrame { + + public: + + /** + * \brief Default constructor for the ReAssociation Request frame. + * + * \param dst_hw_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional). + */ + Dot11ReAssocRequest(const uint8_t* dst_hw_addr = 0, const uint8_t* src_hw_addr = 0); + + /** + * \brief Constructor for creating a 802.11 ReAssociation Request. + * + * Constructor that builds a 802.11 Association Request 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_hw_addr uint8_t array of 6 bytes containing the destination's MAC(optional). + * \param src_hw_addr uint8_t array of 6 bytes containing the source's MAC(optional). + */ + Dot11ReAssocRequest(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 Dot11AssocRequest 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. + */ + Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz); + + /** + * \brief Getter for the Capabilities Information. + * + * \return CapabilityInformation Structure in a CapabilityInformation&. + */ + inline const CapabilityInformation& capabilities() const { return this->_body.capability;} + + /** + * \brief Getter for the Capabilities Information. + * + * \return CapabilityInformation Structure in a CapabilityInformation&. + */ + inline CapabilityInformation& capabilities() { return this->_body.capability;} + + /** + * \brief Getter for the listen interval. + * + * \return The listen interval in an uint16_t. + */ + inline uint16_t listen_interval() const { return this->_body.listen_interval; } + + /** + * \brief Getter for the current ap field. + * + * \return The current ap in an array of 6 uint8_t. + */ + inline const uint8_t* current_ap() const { return this->_body.current_ap; } + + /** + * \brief Setter for the listen interval. + * + * \param new_listen_interval uint16_t with the new listen interval. + */ + void listen_interval(uint16_t new_listen_interval); + + /** + * \brief Setter for the current ap. + * + * \param new_current_ap uint8_t array of 6 bytes with the new current ap. + */ + void current_ap(uint8_t* new_current_ap); + + /** + * \brief Helper method to set the essid. + * + * \param new_ssid The ssid to be set. + */ + void ssid(const std::string &new_ssid); + + /** + * \brief Helper method to set the supported rates. + * + * \param new_rates A list of rates to be set. + */ + void supported_rates(const std::list &new_rates); + + /** + * \brief Helper method to set the extended supported rates. + * + * \param new_rates A list of rates to be set. + */ + void extended_supported_rates(const std::list &new_rates); + + /** + * \brief Helper method to set the power capabilities. + * + * \param min_power uint8_t indicating the minimum transmiting power capability. + * \param max_power uint8_t indicating the maximum transmiting power capability. + */ + void power_capabilities(uint8_t min_power, uint8_t max_power); + + /** + * \brief Helper method to set the supported channels. + * + * \param new_channels A list of channels to be set. + */ + void supported_channels(const std::list > &new_channels); + + /** + * \brief Helper method to set the RSN information option. + * + * \param info The RSNInformation structure to be set. + */ + void rsn_information(const RSNInformation& info); + + /** + * \brief Helper method to set the QoS capabilities. + * + * \param new_qos_capabilities uint8_t with the capabilities. + */ + void qos_capabilities(uint8_t new_qos_capabilities); + + /** + * \brief Returns the 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_REASSOC_REQ; } + + /** + * \brief Check wether this PDU matches the specified flag. + * \param flag The flag to match + * \sa PDU::matches_flag + */ + bool matches_flag(PDUType flag) { + return flag == PDU::DOT11_REASSOC_REQ || Dot11ManagementFrame::matches_flag(flag); + } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone_pdu + */ + PDU *clone_pdu() const; + private: + struct ReAssocReqBody { + CapabilityInformation capability; + uint16_t listen_interval; + uint8_t current_ap[6]; + }; + + uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz); + + ReAssocReqBody _body; + }; + + /** * \brief Class representing an Probe Request frame in the IEEE 802.11 Protocol. * @@ -2021,7 +2198,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_PROBE_REQ || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_PROBE_REQ || Dot11ManagementFrame::matches_flag(flag); } /** @@ -2299,7 +2476,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_PROBE_RESP || Dot11ManagementFrame::matches_flag(flag); + return flag == PDU::DOT11_PROBE_RESP || Dot11ManagementFrame::matches_flag(flag); } protected: @@ -2416,7 +2593,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_DATA || Dot11::matches_flag(flag); + return flag == PDU::DOT11_DATA || Dot11::matches_flag(flag); } /** @@ -2548,7 +2725,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag); + return flag == PDU::DOT11_QOS_DATA || Dot11Data::matches_flag(flag); } private: void copy_fields(const Dot11QoSData *other); @@ -2617,7 +2794,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag); + return flag == PDU::DOT11_CONTROL || Dot11::matches_flag(flag); } }; @@ -2768,7 +2945,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_RTS || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_RTS || Dot11Control::matches_flag(flag); } }; @@ -2825,7 +3002,7 @@ namespace Tins { * \sa PDU::clone_pdu */ PDU *clone_pdu() const; - + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type @@ -2838,7 +3015,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_PS_POLL || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_PS_POLL || Dot11Control::matches_flag(flag); } }; @@ -2895,7 +3072,7 @@ namespace Tins { * \sa PDU::clone_pdu */ PDU *clone_pdu() const; - + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type @@ -2908,7 +3085,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_CF_END || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_CF_END || Dot11Control::matches_flag(flag); } }; @@ -2962,7 +3139,7 @@ namespace Tins { * \sa PDU::clone_pdu */ PDU *clone_pdu() const; - + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type @@ -2975,7 +3152,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_END_CF_ACK || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_END_CF_ACK || Dot11Control::matches_flag(flag); } }; @@ -3023,7 +3200,7 @@ namespace Tins { * \param total_sz The total size of the buffer. */ Dot11Ack(const uint8_t *buffer, uint32_t total_sz); - + /** * \brief Clones this PDU. * @@ -3043,7 +3220,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_ACK || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_ACK || Dot11Control::matches_flag(flag); } }; @@ -3135,7 +3312,7 @@ namespace Tins { * \sa PDU::clone_pdu */ PDU *clone_pdu() const; - + /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type @@ -3148,7 +3325,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_BLOCK_ACK_REQ || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_BLOCK_ACK_REQ || Dot11Control::matches_flag(flag); } protected: uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); @@ -3275,7 +3452,7 @@ namespace Tins { * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) { - return flag == PDU::DOT11_BLOCK_ACK || Dot11Control::matches_flag(flag); + return flag == PDU::DOT11_BLOCK_ACK || Dot11Control::matches_flag(flag); } /** @@ -3297,7 +3474,7 @@ namespace Tins { void init_block_ack(); uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz); - + BarControl _bar_control; StartSequence _start_sequence; diff --git a/include/pdu.h b/include/pdu.h index ba716d0..b0cb98e 100644 --- a/include/pdu.h +++ b/include/pdu.h @@ -35,10 +35,10 @@ namespace Tins { /** \brief Base class for protocol data units. * * Every PDU implementation must inherit this one. PDUs can be serialized, - * therefore allowing a PacketSender to send them through the corresponding - * sockets. PDUs are created upwards: upper layers will be children of the - * lower ones. Each PDU must provide its flag identifier. This will be most - * likely added to its parent's data, hence it should be a valid identifier. + * therefore allowing a PacketSender to send them through the corresponding + * sockets. PDUs are created upwards: upper layers will be children of the + * lower ones. Each PDU must provide its flag identifier. This will be most + * likely added to its parent's data, hence it should be a valid identifier. * For example, IP should provide IPPROTO_IP. */ class PDU { @@ -71,6 +71,7 @@ namespace Tins { DOT11_PROBE_RESP, DOT11_PS_POLL, DOT11_RTS, + DOT11_REASSOC_REQ, DOT11_QOS_DATA, SNAP, IP, @@ -114,13 +115,13 @@ namespace Tins { */ uint32_t size() const; - /** + /** * \brief Getter for this PDU's type flag identifier. * \return The type flag identifier. */ inline uint32_t flag() const { return _flag; } - /** + /** * \brief Getter for the inner PDU. * \return The current inner PDU. Might be 0. */ @@ -130,7 +131,7 @@ namespace Tins { */ void flag(uint32_t new_flag); - /** + /** * \brief Sets the child PDU. * * \param next_pdu The new child PDU. @@ -147,12 +148,12 @@ namespace Tins { * operator delete[]. */ uint8_t *serialize(uint32_t &sz); - + /** * \brief Find and returns the first PDU that matches the given flag. - * - * This method searches for the first PDU which has the same type flag as - * the given one. If the first PDU matches that flag, it is returned. + * + * This method searches for the first PDU which has the same type flag as + * the given one. If the first PDU matches that flag, it is returned. * If no PDU matches, 0 is returned. * \param flag The flag which being searched. */ @@ -165,29 +166,29 @@ namespace Tins { } return 0; } - + /** * \brief Clones this packet. - * - * This method clones this PDU and clones every inner PDU, - * therefore obtaining a clone of the whole inner PDU chain. + * + * This method clones this PDU and clones every inner PDU, + * therefore obtaining a clone of the whole inner PDU chain. * The pointer returned must be deleted by the user. * \return A pointer to a clone of this packet. */ PDU *clone_packet() const; - + /** * \brief Clones this PDU. - * + * * This method does not clone the inner PDUs. \sa PDU::clone_packet * \return A pointer to a copy of this PDU. */ - virtual PDU *clone_pdu() const { + virtual PDU *clone_pdu() const { /* Should be pure virtual. It's this way to avoid compiling issues. * Once every pdu has implemented it, make it pure virtual. */ - return 0; + return 0; } - + /** \brief Send the stack of PDUs through a PacketSender. * * This method will be called only for the PDU on the bottom of the stack, @@ -216,17 +217,17 @@ namespace Tins { * \param total_sz The size of the buffer. */ virtual bool matches_response(uint8_t *ptr, uint32_t total_sz) { return false; } - - /** + + /** * \brief Check wether this PDU matches the specified flag. - * + * * This method should be reimplemented in PDU classes which have * subclasses, and try to match the given PDU to each of its parent * classes' flag. * \param flag The flag to match. */ virtual bool matches_flag(PDUType flag) { - return flag == pdu_type(); + return flag == pdu_type(); } /** @@ -249,19 +250,19 @@ namespace Tins { * \brief Copy constructor. */ PDU(const PDU &other); - + /** * \brief Copy assignment operator. */ PDU &operator=(const PDU &other); - + /** * \brief Copy other PDU's inner PDU(if any). * \param pdu The PDU from which to copy the inner PDU. */ void copy_inner_pdu(const PDU &pdu); - - + + /** \brief Serializes this PDU and propagates this action to child PDUs. * * \param buffer The buffer in which to store this PDU's serialization. diff --git a/src/dot11.cpp b/src/dot11.cpp index 77bdfae..59de76a 100644 --- a/src/dot11.cpp +++ b/src/dot11.cpp @@ -744,6 +744,9 @@ void Tins::Dot11Beacon::edca_parameter_set(uint32_t ac_be, Dot11ManagementFrame::edca_parameter_set(ac_be, ac_bk, ac_vi, ac_vo); } +void Tins::Dot11Beacon::qos_capabilities(uint8_t qos_info) { + Dot11ManagementFrame::qos_capabilities(qos_info); +} string Tins::Dot11Beacon::essid() const { const Dot11::Dot11_Option *option = lookup_option(SSID); @@ -1001,6 +1004,87 @@ Tins::PDU *Tins::Dot11AssocResponse::clone_pdu() const { return new_pdu; } +/* ReAssoc request. */ + +Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : Dot11ManagementFrame(dst_hw_addr, src_hw_addr) { + this->subtype(Dot11::REASSOC_REQ); + memset(&_body, 0, sizeof(_body)); +} + +Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const std::string& iface, + const uint8_t* dst_hw_addr, + const uint8_t* src_hw_addr) throw (std::runtime_error) : Dot11ManagementFrame(iface, dst_hw_addr, src_hw_addr){ + this->subtype(Dot11::REASSOC_REQ); + memset(&_body, 0, sizeof(_body)); +} + +Tins::Dot11ReAssocRequest::Dot11ReAssocRequest(const uint8_t *buffer, uint32_t total_sz) : Dot11ManagementFrame(buffer, total_sz) { + 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 reassociation request header in the buffer."); + memcpy(&_body, buffer, sizeof(_body)); + buffer += sizeof(_body); + total_sz -= sizeof(_body); + parse_tagged_parameters(buffer, total_sz); +} + +void Tins::Dot11ReAssocRequest::listen_interval(uint16_t new_listen_interval) { + this->_body.listen_interval = new_listen_interval; +} + +void Tins::Dot11ReAssocRequest::current_ap(uint8_t* new_current_ap) { + memcpy(this->_body.current_ap, new_current_ap, 6); +} + +void Tins::Dot11ReAssocRequest::ssid(const std::string &new_ssid) { + Dot11ManagementFrame::ssid(new_ssid); +} + +void Tins::Dot11ReAssocRequest::supported_rates(const std::list &new_rates) { + Dot11ManagementFrame::supported_rates(new_rates); +} + +void Tins::Dot11ReAssocRequest::extended_supported_rates(const std::list &new_rates) { + Dot11ManagementFrame::extended_supported_rates(new_rates); +} + +void Tins::Dot11ReAssocRequest::power_capabilities(uint8_t min_power, uint8_t max_power) { + Dot11ManagementFrame::power_capabilities(min_power, max_power); +} + +void Tins::Dot11ReAssocRequest::supported_channels(const std::list > &new_channels) { + Dot11ManagementFrame::supported_channels(new_channels); +} + +void Tins::Dot11ReAssocRequest::rsn_information(const RSNInformation& info) { + Dot11ManagementFrame::rsn_information(info); +} + +void Tins::Dot11ReAssocRequest::qos_capabilities(uint8_t new_qos_capabilities) { + Dot11ManagementFrame::qos_capabilities(new_qos_capabilities); +} + +uint32_t Tins::Dot11ReAssocRequest::header_size() const { + return Dot11ManagementFrame::header_size() + sizeof(this->_body); +} + +uint32_t Tins::Dot11ReAssocRequest::write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { + uint32_t sz = sizeof(this->_body); + assert(sz <= total_sz); + memcpy(buffer, &this->_body, sz); + return sz; +} + +Tins::PDU *Tins::Dot11ReAssocRequest::clone_pdu() const { + Dot11ReAssocRequest *new_pdu = new Dot11ReAssocRequest(); + new_pdu->copy_80211_fields(this); + new_pdu->copy_ext_header(this); + std::memcpy(&new_pdu->_body, &_body, sizeof(_body)); + return new_pdu; +} + /* Probe Request */ Tins::Dot11ProbeRequest::Dot11ProbeRequest(const uint8_t* dst_hw_addr, const uint8_t* src_hw_addr) : Dot11ManagementFrame(dst_hw_addr, src_hw_addr) {