From d22f5ef05eded4c98da3c07d5b1b22c2e4268f91 Mon Sep 17 00:00:00 2001 From: Mario Silvestre Delgado Date: Fri, 23 Aug 2024 22:19:37 +0000 Subject: [PATCH] Added minimal support for dot11 action and action-no-ack management frame subtypes --- .gitignore | 2 + include/tins/dot11.h | 1 + include/tins/dot11/dot11_action.h | 154 ++++++++++++++++++++++++++++++ include/tins/dot11/dot11_base.h | 4 +- include/tins/pdu.h | 1 + src/CMakeLists.txt | 2 + src/detail/pdu_helpers.cpp | 1 + src/dot11/dot11_action.cpp | 76 +++++++++++++++ src/dot11/dot11_base.cpp | 3 + tests/CMakeLists.txt | 2 + 10 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 include/tins/dot11/dot11_action.h create mode 100644 src/dot11/dot11_action.cpp diff --git a/.gitignore b/.gitignore index 6109d958..ef713c5c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ +.devcontainer/ +.vscode/ build/** include/tins/config.h diff --git a/include/tins/dot11.h b/include/tins/dot11.h index 89f2a6a2..c23dc1cf 100644 --- a/include/tins/dot11.h +++ b/include/tins/dot11.h @@ -40,5 +40,6 @@ #include #include #include +#include #endif // TINS_DOT_11 diff --git a/include/tins/dot11/dot11_action.h b/include/tins/dot11/dot11_action.h new file mode 100644 index 00000000..2a9f09e9 --- /dev/null +++ b/include/tins/dot11/dot11_action.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +#include + +#if !defined(TINS_DOT11_DOT11_ACTION_H) && defined(TINS_HAVE_DOT11) +#define TINS_DOT11_DOT11_ACTION_H + +#include +#include + +namespace Tins { + +/** + * \brief Represents an IEEE 802.11 Action. + * + */ +class TINS_API Dot11Action : public Dot11ManagementFrame { +public: + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::DOT11_ACTION; + + /** + * \brief Enum for the different action categories. + * + */ + enum ActionCategories { + SPECTRUMMANAGEMENT = 0, + QOS, + DLS, + BLOCKACK, + PUBLIC, + RADIOMEASUREMENT, + FASTBSS, + HT, + SAQUERY, + PROTECTEDPUBLIC, + VENDORSPECIFIC=127 + }; + + /** + * \brief Constructor for creating a 802.11 Action. + * + * Constructs a 802.11 Action taking destination, source and a category + * + * \param dst_hw_addr The destination hardware address. + * \param src_hw_addr The source hardware address. + * \param category the action category + */ + Dot11Action(const address_type& dst_hw_addr = address_type(), + const address_type& src_hw_addr = address_type(), + ActionCategories category = ActionCategories::PUBLIC); + + /** + * \brief Constructs a Dot11Action object 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 the header in the buffer + * or the input data is malformed, 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. + */ + Dot11Action(const uint8_t* buffer, uint32_t total_sz); + + /** + * \brief Getter for the category field. + * + * \return The stored category value. + */ + ActionCategories category() const { + return static_cast(body_.category); + } + + /** + * \brief Setter for the category field. + * + * \param new_category The category to be set. + */ + void category(ActionCategories new_category); + + uint32_t header_size() const; + + /** + * \brief Check whether 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 || Dot11ManagementFrame::matches_flag(flag); + } + + /** + * \brief Clones this PDU. + * + * \sa PDU::clone + */ + Dot11Action* clone() const { + return new Dot11Action(*this); + } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { + return pdu_flag; + } +private: + TINS_BEGIN_PACK + struct dot11_action_body { + uint8_t category; + } TINS_END_PACK; + + void write_fixed_parameters(Memory::OutputMemoryStream& stream); + + dot11_action_body body_; +}; + +} // namespace Tins + +#endif // TINS_DOT11_DOT11_ACTION_H \ No newline at end of file diff --git a/include/tins/dot11/dot11_base.h b/include/tins/dot11/dot11_base.h index ed2c2277..4f1ccb24 100644 --- a/include/tins/dot11/dot11_base.h +++ b/include/tins/dot11/dot11_base.h @@ -287,7 +287,9 @@ class TINS_API Dot11 : public PDU { ATIM = 9, DISASSOC = 10, AUTH = 11, - DEAUTH = 12 + DEAUTH = 12, + ACTION = 13, + ACTION_NO_ACK = 14 }; /** diff --git a/include/tins/pdu.h b/include/tins/pdu.h index 6402a129..cd110e0a 100644 --- a/include/tins/pdu.h +++ b/include/tins/pdu.h @@ -152,6 +152,7 @@ class TINS_API PDU { DOT11_REASSOC_RESP, DOT11_RTS, DOT11_QOS_DATA, + DOT11_ACTION, LLC, SNAP, IP, diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8dc4fc82..023ed7ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,6 +166,7 @@ SET(DOT11_DEPENDENT_SOURCES dot11/dot11_auth.cpp dot11/dot11_probe.cpp dot11/dot11_control.cpp + dot11/dot11_action.cpp ) SET(DOT11_DEPENDENT_HEADERS @@ -178,6 +179,7 @@ SET(DOT11_DEPENDENT_HEADERS ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_auth.h ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_probe.h ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_control.h + ${LIBTINS_INCLUDE_DIR}/tins/dot11/dot11_action.h ) IF(LIBTINS_ENABLE_DOT11) diff --git a/src/detail/pdu_helpers.cpp b/src/detail/pdu_helpers.cpp index bdda65a4..9799446a 100644 --- a/src/detail/pdu_helpers.cpp +++ b/src/detail/pdu_helpers.cpp @@ -196,6 +196,7 @@ Tins::PDU* pdu_from_flag(PDU::PDUType type, const uint8_t* buffer, uint32_t size case Tins::PDU::DOT11_REASSOC_RESP: case Tins::PDU::DOT11_RTS: case Tins::PDU::DOT11_QOS_DATA: + case Tins::PDU::DOT11_ACTION: return Tins::Dot11::from_bytes(buffer, size); #endif // TINS_HAVE_DOT11 default: diff --git a/src/dot11/dot11_action.cpp b/src/dot11/dot11_action.cpp new file mode 100644 index 00000000..86d3714c --- /dev/null +++ b/src/dot11/dot11_action.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017, 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. + * + */ + +#include +#ifdef TINS_HAVE_DOT11 + +#include +#include +#include + +using Tins::Memory::InputMemoryStream; +using Tins::Memory::OutputMemoryStream; +using Tins::RawPDU; + +namespace Tins { + +// Dot11Action + +Dot11Action::Dot11Action(const address_type& dst_hw_addr, +const address_type& src_hw_addr, ActionCategories category) +: Dot11ManagementFrame(dst_hw_addr, src_hw_addr), body_() { + body_.category = category; + subtype(Dot11::ACTION); +} + +Dot11Action::Dot11Action(const uint8_t* buffer, uint32_t total_sz) +: Dot11ManagementFrame(buffer, total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.skip(management_frame_size()); + stream.read(body_); + if (stream) { + inner_pdu(RawPDU(stream.pointer(), stream.size())); + } +} + +void Dot11Action::category(ActionCategories new_category) { + body_.category = static_cast(new_category); +} + +uint32_t Dot11Action::header_size() const { + return Dot11ManagementFrame::header_size() + sizeof(body_); +} + +void Dot11Action::write_fixed_parameters(OutputMemoryStream& stream) { + stream.write(body_); +} + +} // Tins + +#endif // TINS_HAVE_DOT11 \ No newline at end of file diff --git a/src/dot11/dot11_base.cpp b/src/dot11/dot11_base.cpp index cc324442..9d2b7a67 100644 --- a/src/dot11/dot11_base.cpp +++ b/src/dot11/dot11_base.cpp @@ -253,6 +253,9 @@ Dot11* Dot11::from_bytes(const uint8_t* buffer, uint32_t total_sz) { return new Dot11ProbeRequest(buffer, total_sz); case PROBE_RESP: return new Dot11ProbeResponse(buffer, total_sz); + case ACTION: + case ACTION_NO_ACK: + return new Dot11Action(buffer, total_sz); default: break; }; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a6e8a06f..e7d50afb 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,6 +2,8 @@ SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/tests) INCLUDE_DIRECTORIES(${gtest_INCLUDE_DIRS}) ADD_SUBDIRECTORY(src) +set_property(TARGET tests PROPERTY CXX_STANDARD 14) + IF (ENABLE_ACTIVE_TESTS AND LIBTINS_ENABLE_PCAP) ADD_SUBDIRECTORY(active_tests) ENDIF() \ No newline at end of file