/* * Copyright (c) 2012, Matias Fontanini * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef TINS_DOT_11 #define TINS_DOT_11 #include #include #include #include #include "macros.h" #include "pdu.h" #include "endianness.h" #include "hw_address.h" #include "small_uint.h" #include "pdu_option.h" #include "network_interface.h" #include "cxxstd.h" namespace Tins { class RSNInformation; /** * \brief Class representing an 802.11 frame. */ class Dot11 : public PDU { public: typedef HWAddress<6> address_type; /** * \brief This PDU's flag. */ static const PDU::PDUType pdu_flag = PDU::DOT11; /** * \brief Broadcast hardware address. */ static const address_type BROADCAST; /** * \brief Enum for the different types of 802.11 frames. * */ enum Types { MANAGEMENT = 0, CONTROL = 1, DATA = 2 }; /** * \brief Enum for the different types of tagged options. */ enum OptionTypes { SSID, SUPPORTED_RATES, FH_SET, DS_SET, CF_SET, TIM, IBSS_SET, COUNTRY, HOPPING_PATTERN_PARAMS, HOPPING_PATTERN_TABLE, REQUEST_INFORMATION, BSS_LOAD, EDCA, TSPEC, TCLAS, SCHEDULE, CHALLENGE_TEXT, POWER_CONSTRAINT = 32, POWER_CAPABILITY, TPC_REQUEST, TPC_REPORT, SUPPORTED_CHANNELS, CHANNEL_SWITCH, MEASUREMENT_REQUEST, MEASUREMENT_REPORT, QUIET, IBSS_DFS, ERP_INFORMATION, TS_DELAY, TCLAS_PROCESSING, QOS_CAPABILITY = 46, RSN = 48, EXT_SUPPORTED_RATES = 50 }; /** * \brief Enum for the different subtypes of 802.11 management frames. * */ enum ManagementSubtypes { ASSOC_REQ = 0, ASSOC_RESP = 1, REASSOC_REQ = 2, REASSOC_RESP = 3, PROBE_REQ = 4, PROBE_RESP = 5, BEACON = 8, ATIM = 9, DISASSOC = 10, AUTH = 11, DEAUTH = 12 }; /** * \brief Enum for the different subtypes of 802.11 control frames. * */ enum ControlSubtypes { BLOCK_ACK_REQ = 8, BLOCK_ACK = 9, PS = 10, RTS = 11, CTS = 12, ACK = 13, CF_END = 14, CF_END_ACK = 15 }; /** * \brief Enum fro the different subtypes of 802.11 data frames. * */ enum DataSubtypes { DATA_DATA = 0, DATA_CF_ACK = 1, DATA_CF_POLL = 2, DATA_CF_ACK_POLL = 3, DATA_NULL = 4, CF_ACK = 5, CF_POLL = 6, CF_ACK_POLL = 7, QOS_DATA_DATA = 8, QOS_DATA_CF_ACK = 9, QOS_DATA_CF_POLL = 10, QOS_DATA_CF_ACK_POLL = 11, QOS_DATA_NULL = 12 }; /** * \brief IEEE 802.11 options struct. */ typedef PDUOption option; /** * \brief Constructor for creating an 802.11 PDU * * Constructor that builds an 802.11 PDU taking the interface index, * destination's and source's MAC. * * \param dst_hw_addr The destination hardware address. */ Dot11(const address_type &dst_hw_addr = address_type()); /** * \brief Constructs 802.11 PDU from a buffer and adds all * identifiable PDUs found in the buffer as children of this one. * * If the next PDU is not recognized, then a RawPDU is used. * * If there is not enough size for a 802.11 header in the * buffer, a malformed_packet exception is thrown. * * \param buffer The buffer from which this PDU will be constructed. * \param total_sz The total size of the buffer. */ Dot11(const uint8_t *buffer, uint32_t total_sz); /** * \brief Getter for the protocol version. * * \return uint8_t containing the protocol version. */ small_uint<2> protocol() const { return _header.control.protocol; } /** * \brief Getter for the 802.11 frame's type. * * \return uint8_t containing the type of this 802.11 frame. */ small_uint<2> type() const { return _header.control.type; } /** * \brief Getter for the 802.11 frame's subtype. * * \return uint8_t cotaining the subtype of this 802.11 frame. */ small_uint<4> subtype() const { return _header.control.subtype; } /** * \brief Getter for the 802.11 frame's To-DS field. * * \return small_uint<1> containing the To-DS field. */ small_uint<1> to_ds() const { return _header.control.to_ds; } /** * \brief Getter for the 802.11 frame's From-DS field. * * \return small_uint<1> containing the From-DS field. */ small_uint<1> from_ds() const { return _header.control.from_ds; } /** * \brief Getter for the 802.11 frame's More-Frag field. * * \return small_uint<1> containing the More-Frag field. */ small_uint<1> more_frag() const { return _header.control.more_frag; } /** * \brief Getter for the 802.11 frame's Retry field. * * \return small_uint<1> containing the Retry field. */ small_uint<1> retry() const { return _header.control.retry; } /** * \brief Getter for the 802.11 frame's Power-Management field. * * \return small_uint<1> containing the Power-Management field. */ small_uint<1> power_mgmt() const { return _header.control.power_mgmt; } /** * \brief Getter for the 802.11 frame's WEP field. * * \return small_uint<1> containing the WEP field. */ small_uint<1> wep() const { return _header.control.wep; } /** * \brief Getter for the 802.11 frame's Order field. * * \return small_uint<1> containing the Order field. */ small_uint<1> order() const { return _header.control.order; } /** * \brief Getter for the Duration-ID field. * * \return uint16_t containing the Duration-ID field. */ uint16_t duration_id() const { return Endian::le_to_host(_header.duration_id); } /** * \brief Getter for the first address. * * \return address_type containing the first address. */ address_type addr1() const { return _header.addr1; } /** * \brief Setter for the protocol version. * * \param new_proto The new protocol version. */ void protocol(small_uint<2> new_proto); /** * \brief Setter for the 802.11 frame's type. * * \param new_type The new type of this 802.11 frame. */ void type(small_uint<2> new_type); /** * \brief Setter for the 802.11 frame's subtype. * * \param new_subtype The new subtype of this 802.11 frame. */ void subtype(small_uint<4> new_subtype); /** * \brief Setter for the 802.11 frame's To-DS field. * * \param new_value The new value of the To-DS field. */ void to_ds(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's From-DS field. * * \param new_value The new value of the From-DS field. */ void from_ds(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's More-Frag field. * * \param new_value The new value of the More-Frag field. */ void more_frag(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's Retry field. * * \param new_value sThe new value of the Retry field. */ void retry(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's Power-Management field. * * \param new_value The new value of the Power-Management field. */ void power_mgmt(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's WEP field. * * \param new_value The new value of the WEP field. */ void wep(small_uint<1> new_value); /** * \brief Setter for the 802.11 frame's Order field. * * \param new_value The new value of the Order field. */ void order(small_uint<1> new_value); /** * \brief Setter for the Duration-ID field. * * \param new_duration_id The new value of the Duration-ID field. */ void duration_id(uint16_t new_duration_id); /** * \brief Setter for the first address. * * \param new_addr1 The new first address. */ void addr1(const address_type &new_addr1); /* Virtual methods */ /** * \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; #ifndef WIN32 /** * \sa PDU::send() */ void send(PacketSender &sender, const NetworkInterface &iface); #endif // WIN32 /** * \brief Adds a new option to this Dot11 PDU. * \param opt The option to be added. */ void add_option(const option &opt); #if TINS_IS_CXX11 /** * \brief Adds a new option to this Dot11 PDU. * * The option is move-constructed * * \param opt The option to be added. */ void add_option(option &&opt) { internal_add_option(opt); _options.push_back(std::move(opt)); } #endif /** * \brief Looks up a tagged option in the option list. * * The returned pointer must not be free'd. * * \param opt The option identifier. * \return The option found, or 0 if no such option has been set. */ const option *search_option(OptionTypes opt) const; /** * \brief Getter for the PDU's type. * \sa PDU::pdu_type */ PDUType pdu_type() const { return pdu_flag; } /** * \sa PDU::clone */ Dot11 *clone() const { return new Dot11(*this); } /** * \brief Check wether this PDU matches the specified flag. * \param flag The flag to match * \sa PDU::matches_flag */ bool matches_flag(PDUType flag) const { return flag == pdu_flag; } /** * \brief Allocates an Dot11 PDU from a buffer. * * This can be used somehow as a "virtual constructor". This * method instantiates a subclass of Dot11 from the given buffer. * The allocated class' type will be figured out from the * information provided in the buffer. * * \param buffer The buffer from which to take the PDU data. * \param total_sz The total size of the buffer. * \return The allocated Dot11 PDU. */ static Dot11 *from_bytes(const uint8_t *buffer, uint32_t total_sz); protected: virtual uint32_t write_ext_header(uint8_t *buffer, uint32_t total_sz) { return 0; } virtual uint32_t write_fixed_parameters(uint8_t *buffer, uint32_t total_sz) { return 0; } void parse_tagged_parameters(const uint8_t *buffer, uint32_t total_sz); void add_tagged_option(OptionTypes opt, uint8_t len, const uint8_t *val); protected: /** * Struct that represents the 802.11 header */ TINS_BEGIN_PACK struct ieee80211_header { TINS_BEGIN_PACK struct { #if TINS_IS_LITTLE_ENDIAN uint16_t protocol:2, type:2, subtype:4, to_ds:1, from_ds:1, more_frag:1, retry:1, power_mgmt:1, more_data:1, wep:1, order:1; #elif TINS_IS_BIG_ENDIAN uint16_t subtype:4, type:2, protocol:2, order:1, wep:1, more_data:1, power_mgmt:1, retry:1, more_frag:1, from_ds:1, to_ds:1; #endif } TINS_END_PACK control; uint16_t duration_id; uint8_t addr1[address_type::address_size]; } TINS_END_PACK; private: Dot11(const ieee80211_header *header_ptr); void internal_add_option(const option &opt); void write_serialization(uint8_t *buffer, uint32_t total_sz, const PDU *parent); ieee80211_header _header; uint32_t _options_size; std::list