From f2ae3fd3ff29c238fb6d0228bf6c60ecfb93ddcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Yao=20=E5=A7=9A=E8=92=99?= Date: Fri, 26 Jul 2024 23:01:38 +0800 Subject: [PATCH 1/3] Feat: Support Linux Cooked Capture v2 (SLL2) PDU Ref: https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html --- include/tins/pdu.h | 1 + include/tins/rtp.h | 613 +++++++++++++++++++------------------ include/tins/sll2.h | 167 ++++++++++ include/tins/tins.h | 1 + src/CMakeLists.txt | 2 + src/detail/pdu_helpers.cpp | 3 + src/sll2.cpp | 59 ++++ src/sniffer.cpp | 4 + tests/src/CMakeLists.txt | 1 + tests/src/sll2_test.cpp | 97 ++++++ 10 files changed, 646 insertions(+), 302 deletions(-) create mode 100644 include/tins/sll2.h create mode 100644 src/sll2.cpp create mode 100644 tests/src/sll2_test.cpp diff --git a/include/tins/pdu.h b/include/tins/pdu.h index 6402a129..7fbbe67a 100644 --- a/include/tins/pdu.h +++ b/include/tins/pdu.h @@ -169,6 +169,7 @@ class TINS_API PDU { IPv6, ICMPv6, SLL, + SLL2, DHCPv6, DOT1AD, DOT1Q, diff --git a/include/tins/rtp.h b/include/tins/rtp.h index 0040387a..68023f21 100644 --- a/include/tins/rtp.h +++ b/include/tins/rtp.h @@ -18,311 +18,320 @@ namespace Tins { */ class TINS_API RTP : public PDU { public: - /** - * \brief This PDU's flag. - */ - static const PDU::PDUType pdu_flag = PDU::RTP; - - /** - * The type used to store CSRC identifiers. - */ - typedef std::vector csrc_ids_type; - - /** - * The type used to store extension header data. - */ - typedef std::vector extension_header_data_type; - - /** - * Default constructor. - */ - RTP(); - - /** - * \brief Constructs a RTP object from a buffer. - * - * \param data The buffer from which this PDU will be constructed. - * \param size The size of the data buffer. - */ - RTP(const uint8_t* data, uint32_t size); - - /** - * \brief Getter for the version. - */ - small_uint<2> version() const { return header_.version; } - - /** - * \brief Getter for the padding bit. - */ - small_uint<1> padding_bit() const { return header_.padding; } - - /** - * \brief Getter for the extension bit. - */ - small_uint<1> extension_bit() const { return header_.extension; } - - /** - * \brief Getter for the CSRC count. - */ - small_uint<4> csrc_count() const { return header_.csrc_count; } - - /** - * \brief Getter for the marker bit. - */ - small_uint<1> marker_bit() const { return header_.marker; } - - /** - * \brief Getter for the payload type. - */ - small_uint<7> payload_type() const { return header_.payload_type; } - - /** - * \brief Getter for the sequence number. - */ - uint16_t sequence_number() const { return Endian::be_to_host(header_.seq_num); } - - /** - * \brief Getter for the timestamp. - */ - uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); } - - /** - * \brief Getter for the SSRC identifier. - */ - uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); } - - /** - * \brief Getter for the CSRC identifiers. - */ - const csrc_ids_type& csrc_ids() const { - return csrc_ids_; - } - - /** - * \brief Getter for the padding size. - */ - uint8_t padding_size() const { return padding_size_; } - - /** - * \brief Getter for the extension header profile. - */ - uint16_t extension_profile() const { return Endian::be_to_host(ext_header_.profile); } - - /** - * \brief Getter for the extension header length. - */ - uint16_t extension_length() const { return Endian::be_to_host(ext_header_.length); } - - /** - * \brief Getter for the extension header data. - */ - const extension_header_data_type& extension_data() const { - return ext_data_; - } - - /** - * \brief Setter for the version. - * \param version The new version. - */ - void version(small_uint<2> version) { header_.version = version; } - - /** - * \brief Setter for the extension bit. - * \param extension The new extension bit. - */ - void extension_bit(small_uint<1> extension) { header_.extension = extension; } - - /** - * \brief Setter for the marker bit. - * \param marker The new marker bit. - */ - void marker_bit(small_uint<1> marker) { header_.marker = marker; } - - /** - * \brief Setter for the payload type. - * \param payload_type The new payload type. - */ - void payload_type(small_uint<7> payload_type) { header_.payload_type = payload_type; } - - /** - * \brief Setter for the sequence number. - * \param seq_num The new sequence number. - */ - void sequence_number(uint16_t seq_num) { header_.seq_num = Endian::host_to_be(seq_num); } - - /** - * \brief Setter for the timestamp. - * \param timestamp The new timestamp. - */ - void timestamp(uint32_t timestamp) { header_.timestamp = Endian::host_to_be(timestamp); } - - /** - * \brief Setter for the SSRC identifier. - * \param ssrc_id The new SSRC identifier. - */ - void ssrc_id(uint32_t ssrc_id) { header_.ssrc_id = Endian::host_to_be(ssrc_id); } - - /** - * \brief Setter for the padding size. - * \param size The new padding size. - */ - void padding_size(uint8_t size) { - padding_bit(size > 0); - padding_size_ = size; - } - - /** - * \brief Setter for the extension header profile. - * \param profile The new extension header profile. - */ - void extension_profile(uint16_t profile) { ext_header_.profile = Endian::host_to_be(profile); } - - /** - * \brief Adds a word of extension header data. - * - * The word is added after the last word of extension header data. - * - * \param value The value of the extension header data to be added. - */ - void add_extension_data(const uint32_t value); - - /** - * \brief Removes a word of extension header data. - * - * If there are multiple words of extension header data of the given value, - * only the first one will be removed. - * - * \param value The value of the extension header data to be removed. - * \return true if the extension header data was removed, false otherwise. - */ - bool remove_extension_data(const uint32_t value); - - /** - * \brief Searches for extension header data that matches the given value. - * \param value The extension header data to be searched. - * \return true if the extension header data was found, false otherwise. - */ - bool search_extension_data(const uint32_t value); - - /** - * \brief Adds a CSRC identifier. - * - * The CSRC identifier is added after the last CSRC identifier in the extension - * header. - * - * \param csrc_id The CSRC identifier to be added - */ - void add_csrc_id(const uint32_t csrc_id); - - /** - * \brief Removes a CSRC identifier. - * - * If there are multiple CSRC identifiers of the given value, only the first one - * will be removed. - * - * \param value The value of the CSRC identifier to be removed. - * \return true if the CSRC identifier was removed, false otherwise. - */ - bool remove_csrc_id(const uint32_t value); - - /** - * \brief Searches for a CSRC identifier that matches the given value. - * \param value The CSRC identifier to be searched. - * \return true if the CSRC identifier was found, false otherwise. - */ - bool search_csrc_id(const uint32_t value); - - /** - * \brief Returns the RTP packet's header length. - * - * This method overrides PDU::header_size. - * - * \return An uint32_t with the header's size. - * \sa PDU::header_size - */ - uint32_t header_size() const; - - /** - * \brief Returns the RTP packet's trailer length. - * - * This method overrides PDU::trailer_size. - * - * \return An uint32_t with the trailer's size. - * \sa PDU::trailer_size - */ - uint32_t trailer_size() const { return static_cast(padding_size_); } - - /** - * \brief Getter for the PDU's type. - * \sa PDU::pdu_type - */ - PDUType pdu_type() const { return pdu_flag; } - - /** - * \sa PDU::clone - */ - RTP *clone() const { return new RTP(*this); } + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::RTP; + + /** + * The type used to store CSRC identifiers. + */ + typedef std::vector csrc_ids_type; + + /** + * The type used to store extension header data. + */ + typedef std::vector extension_header_data_type; + + /** + * Default constructor. + */ + RTP(); + + /** + * \brief Constructs a RTP object from a buffer. + * + * \param data The buffer from which this PDU will be constructed. + * \param size The size of the data buffer. + */ + RTP(const uint8_t *data, uint32_t size); + + /** + * \brief Getter for the version. + */ + small_uint<2> version() const { return header_.version; } + + /** + * \brief Getter for the padding bit. + */ + small_uint<1> padding_bit() const { return header_.padding; } + + /** + * \brief Getter for the extension bit. + */ + small_uint<1> extension_bit() const { return header_.extension; } + + /** + * \brief Getter for the CSRC count. + */ + small_uint<4> csrc_count() const { return header_.csrc_count; } + + /** + * \brief Getter for the marker bit. + */ + small_uint<1> marker_bit() const { return header_.marker; } + + /** + * \brief Getter for the payload type. + */ + small_uint<7> payload_type() const { return header_.payload_type; } + + /** + * \brief Getter for the sequence number. + */ + uint16_t sequence_number() const { + return Endian::be_to_host(header_.seq_num); + } + + /** + * \brief Getter for the timestamp. + */ + uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); } + + /** + * \brief Getter for the SSRC identifier. + */ + uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); } + + /** + * \brief Getter for the CSRC identifiers. + */ + const csrc_ids_type &csrc_ids() const { return csrc_ids_; } + + /** + * \brief Getter for the padding size. + */ + uint8_t padding_size() const { return padding_size_; } + + /** + * \brief Getter for the extension header profile. + */ + uint16_t extension_profile() const { + return Endian::be_to_host(ext_header_.profile); + } + + /** + * \brief Getter for the extension header length. + */ + uint16_t extension_length() const { + return Endian::be_to_host(ext_header_.length); + } + + /** + * \brief Getter for the extension header data. + */ + const extension_header_data_type &extension_data() const { return ext_data_; } + + /** + * \brief Setter for the version. + * \param version The new version. + */ + void version(small_uint<2> version) { header_.version = version; } + + /** + * \brief Setter for the extension bit. + * \param extension The new extension bit. + */ + void extension_bit(small_uint<1> extension) { header_.extension = extension; } + + /** + * \brief Setter for the marker bit. + * \param marker The new marker bit. + */ + void marker_bit(small_uint<1> marker) { header_.marker = marker; } + + /** + * \brief Setter for the payload type. + * \param payload_type The new payload type. + */ + void payload_type(small_uint<7> payload_type) { + header_.payload_type = payload_type; + } + + /** + * \brief Setter for the sequence number. + * \param seq_num The new sequence number. + */ + void sequence_number(uint16_t seq_num) { + header_.seq_num = Endian::host_to_be(seq_num); + } + + /** + * \brief Setter for the timestamp. + * \param timestamp The new timestamp. + */ + void timestamp(uint32_t timestamp) { + header_.timestamp = Endian::host_to_be(timestamp); + } + + /** + * \brief Setter for the SSRC identifier. + * \param ssrc_id The new SSRC identifier. + */ + void ssrc_id(uint32_t ssrc_id) { + header_.ssrc_id = Endian::host_to_be(ssrc_id); + } + + /** + * \brief Setter for the padding size. + * \param size The new padding size. + */ + void padding_size(uint8_t size) { + padding_bit(size > 0); + padding_size_ = size; + } + + /** + * \brief Setter for the extension header profile. + * \param profile The new extension header profile. + */ + void extension_profile(uint16_t profile) { + ext_header_.profile = Endian::host_to_be(profile); + } + + /** + * \brief Adds a word of extension header data. + * + * The word is added after the last word of extension header data. + * + * \param value The value of the extension header data to be added. + */ + void add_extension_data(const uint32_t value); + + /** + * \brief Removes a word of extension header data. + * + * If there are multiple words of extension header data of the given value, + * only the first one will be removed. + * + * \param value The value of the extension header data to be removed. + * \return true if the extension header data was removed, false otherwise. + */ + bool remove_extension_data(const uint32_t value); + + /** + * \brief Searches for extension header data that matches the given value. + * \param value The extension header data to be searched. + * \return true if the extension header data was found, false otherwise. + */ + bool search_extension_data(const uint32_t value); + + /** + * \brief Adds a CSRC identifier. + * + * The CSRC identifier is added after the last CSRC identifier in the + * extension header. + * + * \param csrc_id The CSRC identifier to be added + */ + void add_csrc_id(const uint32_t csrc_id); + + /** + * \brief Removes a CSRC identifier. + * + * If there are multiple CSRC identifiers of the given value, only the first + * one will be removed. + * + * \param value The value of the CSRC identifier to be removed. + * \return true if the CSRC identifier was removed, false otherwise. + */ + bool remove_csrc_id(const uint32_t value); + + /** + * \brief Searches for a CSRC identifier that matches the given value. + * \param value The CSRC identifier to be searched. + * \return true if the CSRC identifier was found, false otherwise. + */ + bool search_csrc_id(const uint32_t value); + + /** + * \brief Returns the RTP packet's header length. + * + * This method overrides PDU::header_size. + * + * \return An uint32_t with the header's size. + * \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \brief Returns the RTP packet's trailer length. + * + * This method overrides PDU::trailer_size. + * + * \return An uint32_t with the trailer's size. + * \sa PDU::trailer_size + */ + uint32_t trailer_size() const { return static_cast(padding_size_); } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \sa PDU::clone + */ + RTP *clone() const { return new RTP(*this); } private: - TINS_BEGIN_PACK - struct rtp_header { - #if TINS_IS_BIG_ENDIAN - uint16_t version:2, - padding:1, - extension:1, - csrc_count:4, - marker:1, - payload_type:7; - #elif TINS_IS_LITTLE_ENDIAN - uint16_t csrc_count:4, - extension:1, - padding:1, - version:2, - payload_type:7, - marker:1; - #endif - uint16_t seq_num; - uint32_t timestamp; - uint32_t ssrc_id; - } TINS_END_PACK; - - TINS_BEGIN_PACK - struct rtp_extension_header { - uint16_t profile; - uint16_t length; - } TINS_END_PACK; - - void write_serialization(uint8_t* buffer, uint32_t size); - csrc_ids_type::const_iterator search_csrc_id_iterator(const uint32_t csrc_id) const; - csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id); - extension_header_data_type::const_iterator search_extension_data_iterator(const uint32_t data) const; - extension_header_data_type::iterator search_extension_data_iterator(const uint32_t data); - - /** - * \brief Setter for the padding bit. - * \param padding The new padding bit. - */ - void padding_bit(small_uint<1> padding) { header_.padding = padding; } - - /** - * \brief Setter for the CSRC count. Hidden from the public interface. - * \param csrc_count The new CSRC count. - */ - void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; } - - /** - * \brief Setter for the extension header length. Hidden from the public interface. - * \param length The new extension header length. - */ - void extension_length(uint16_t length) { ext_header_.length = Endian::host_to_be(length); } - - rtp_header header_; - csrc_ids_type csrc_ids_; - rtp_extension_header ext_header_; - extension_header_data_type ext_data_; - uint8_t padding_size_; + TINS_BEGIN_PACK + struct rtp_header { +#if TINS_IS_BIG_ENDIAN + uint16_t version : 2, padding : 1, extension : 1, csrc_count : 4, + marker : 1, payload_type : 7; +#elif TINS_IS_LITTLE_ENDIAN + uint16_t csrc_count : 4, extension : 1, padding : 1, version : 2, + payload_type : 7, marker : 1; +#endif + uint16_t seq_num; + uint32_t timestamp; + uint32_t ssrc_id; + } TINS_END_PACK; + + TINS_BEGIN_PACK + struct rtp_extension_header { + uint16_t profile; + uint16_t length; + } TINS_END_PACK; + + void write_serialization(uint8_t *buffer, uint32_t size); + csrc_ids_type::const_iterator + search_csrc_id_iterator(const uint32_t csrc_id) const; + csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id); + extension_header_data_type::const_iterator + search_extension_data_iterator(const uint32_t data) const; + extension_header_data_type::iterator + search_extension_data_iterator(const uint32_t data); + + /** + * \brief Setter for the padding bit. + * \param padding The new padding bit. + */ + void padding_bit(small_uint<1> padding) { header_.padding = padding; } + + /** + * \brief Setter for the CSRC count. Hidden from the public interface. + * \param csrc_count The new CSRC count. + */ + void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; } + + /** + * \brief Setter for the extension header length. Hidden from the public + * interface. \param length The new extension header length. + */ + void extension_length(uint16_t length) { + ext_header_.length = Endian::host_to_be(length); + } + + rtp_header header_; + csrc_ids_type csrc_ids_; + rtp_extension_header ext_header_; + extension_header_data_type ext_data_; + uint8_t padding_size_; }; -} // Tins +} // namespace Tins #endif // TINS_RTP_H diff --git a/include/tins/sll2.h b/include/tins/sll2.h new file mode 100644 index 00000000..40015e93 --- /dev/null +++ b/include/tins/sll2.h @@ -0,0 +1,167 @@ +#ifndef TINS_SLL2_H +#define TINS_SLL2_H + +#include +#include +#include +#include +#include +#include + +namespace Tins { + +/** + * \class SLL2 + * \brief Represents a Linux Cooked Capture v2 (SLL2) PDU. + * + * https://www.tcpdump.org/linktypes/LINKTYPE_LINUX_SLL2.html + * + */ +class TINS_API SLL2 : public PDU { +public: + /** + * This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::SLL2; + + /** + * The type of the address type + */ + typedef HWAddress<8> address_type; + + /** + * Default constructor + */ + SLL2(); + + /** + * \brief Constructs a SLL2 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 a SLL 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. + */ + SLL2(const uint8_t *buffer, uint32_t total_sz); + + // Getters + + /** + * \brief Getter for the Protocol field. + * \return The stored Protocol field value. + */ + uint16_t protocol() const { return Endian::be_to_host(header_.protocol); } + + /** + * \brief Getter for the Interface Index field. + * \return The stored Interface Index field value. + */ + uint32_t interface_index() const { + return Endian::be_to_host(header_.interface_index); + } + + /** + * \brief Getter for the LLADDR Type field. + * \return The stored LLADDR Type field value. + */ + uint16_t lladdr_type() const { + return Endian::be_to_host(header_.lladdr_type); + } + + /** + * \brief Getter for the Packet Type field. + * \return The stored Packet Type field value. + */ + uint8_t packet_type() const { + return Endian::be_to_host(header_.packet_type); + } + + /** + * \brief Getter for the LLADDR Length field. + * \return The stored LLADDR Length field value. + */ + uint8_t lladdr_len() const { return Endian::be_to_host(header_.lladdr_len); } + + /** + * \brief Getter for the Address field. + * \return The stored Address field value. + */ + address_type address() const { return header_.address; } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + // Setters + + /** + * \brief Setter for the Protocol field. + * \param new_protocol The new Protocol field value. + */ + void protocol(uint16_t new_protocol); + + /** + * \brief Setter for the Interface Index field. + * \param new_interface_index The new Interface Index field value. + */ + void interface_index(uint32_t new_interface_index); + + /** + * \brief Setter for the LLADDR Type field. + * \param new_lladdr_type The new LLADDR Type field value. + */ + void lladdr_type(uint16_t new_lladdr_type); + + /** + * \brief Setter for the Packet Type field. + * \param new_packet_type The new Packet Type field value. + */ + void packet_type(uint8_t new_packet_type); + + /** + * \brief Setter for the LLADDR Length field. + * \param new_lladdr_len The new LLADDR Length field value. + */ + void lladdr_len(uint8_t new_lladdr_len); + + /** + * \brief Setter for the Address field. + * \param new_address The new Address field value. + */ + void address(const address_type &new_address); + + /** + * \brief Returns the header size. + * + * This method overrides PDU::header_size. \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \sa PDU::clone + */ + SLL2 *clone() const { return new SLL2(*this); } + +private: + TINS_BEGIN_PACK + struct sll2_header { + uint16_t protocol, reserved_mbz; + uint32_t interface_index; + uint16_t lladdr_type; + uint8_t packet_type, lladdr_len; + uint8_t address[8]; + } TINS_END_PACK; + + void write_serialization(uint8_t *buffer, uint32_t total_sz); + + sll2_header header_; +}; +} // namespace Tins + +#endif // TINS_SLL2_H diff --git a/include/tins/tins.h b/include/tins/tins.h index 6526c50e..7feed86d 100644 --- a/include/tins/tins.h +++ b/include/tins/tins.h @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8dc4fc82..eca99b8b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -56,6 +56,7 @@ set(SOURCES rsn_information.cpp rtp.cpp sll.cpp + sll2.cpp snap.cpp stp.cpp tcp.cpp @@ -134,6 +135,7 @@ set(HEADERS ${LIBTINS_INCLUDE_DIR}/tins/rsn_information.h ${LIBTINS_INCLUDE_DIR}/tins/rtp.h ${LIBTINS_INCLUDE_DIR}/tins/sll.h + ${LIBTINS_INCLUDE_DIR}/tins/sll2.h ${LIBTINS_INCLUDE_DIR}/tins/small_uint.h ${LIBTINS_INCLUDE_DIR}/tins/snap.h ${LIBTINS_INCLUDE_DIR}/tins/tcp.h diff --git a/src/detail/pdu_helpers.cpp b/src/detail/pdu_helpers.cpp index bdda65a4..88d32e54 100644 --- a/src/detail/pdu_helpers.cpp +++ b/src/detail/pdu_helpers.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -147,6 +148,8 @@ PDU* pdu_from_dlt_flag(int flag, return new Loopback(buffer, size); case DLT_LINUX_SLL: return new SLL(buffer, size); + case DLT_LINUX_SLL2: + return new SLL2(buffer, size); case DLT_PPI: return new PPI(buffer, size); default: diff --git a/src/sll2.cpp b/src/sll2.cpp new file mode 100644 index 00000000..410e2c75 --- /dev/null +++ b/src/sll2.cpp @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include + +using Tins::Memory::InputMemoryStream; +using Tins::Memory::OutputMemoryStream; + +namespace Tins { + +SLL2::SLL2() : header_() {} + +SLL2::SLL2(const uint8_t *buffer, uint32_t total_sz) { + InputMemoryStream stream(buffer, total_sz); + stream.read(header_); + if (stream) { + inner_pdu(Internals::pdu_from_flag((Constants::Ethernet::e)protocol(), + stream.pointer(), stream.size())); + } +} + +void SLL2::protocol(uint16_t new_protocol) { + header_.protocol = Endian::host_to_be(new_protocol); +} + +void SLL2::interface_index(uint32_t new_interface_index) { + header_.interface_index = Endian::host_to_be(new_interface_index); +} + +void SLL2::lladdr_type(uint16_t new_lladdr_type) { + header_.lladdr_type = Endian::host_to_be(new_lladdr_type); +} + +void SLL2::packet_type(uint8_t new_packet_type) { + header_.packet_type = Endian::host_to_be(new_packet_type); +} + +void SLL2::lladdr_len(uint8_t new_lladdr_len) { + header_.lladdr_len = Endian::host_to_be(new_lladdr_len); +} + +void SLL2::address(const address_type &new_address) { + new_address.copy(header_.address); +} + +uint32_t SLL2::header_size() const { return sizeof(header_); } + +void SLL2::write_serialization(uint8_t *buffer, uint32_t total_sz) { + OutputMemoryStream stream(buffer, total_sz); + if (inner_pdu()) { + Constants::Ethernet::e flag = + Internals::pdu_flag_to_ether_type(inner_pdu()->pdu_type()); + protocol(static_cast(flag)); + } + stream.write(header_); +} + +} // namespace Tins diff --git a/src/sniffer.cpp b/src/sniffer.cpp index 094f9ba8..12ba08f4 100644 --- a/src/sniffer.cpp +++ b/src/sniffer.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -178,6 +179,9 @@ PtrPacket BaseSniffer::next_packet() { case DLT_LINUX_SLL: handler = &sniff_loop_handler; break; + case DLT_LINUX_SLL2: + handler = &sniff_loop_handler; + break; case DLT_PPI: handler = &sniff_loop_handler; break; diff --git a/tests/src/CMakeLists.txt b/tests/src/CMakeLists.txt index aa0c3777..ea9222ee 100644 --- a/tests/src/CMakeLists.txt +++ b/tests/src/CMakeLists.txt @@ -65,6 +65,7 @@ CREATE_TEST(rc4_eapol) CREATE_TEST(rsn_eapol) CREATE_TEST(rtp) CREATE_TEST(sll) +CREATE_TEST(sll2) CREATE_TEST(snap) CREATE_TEST(stp) CREATE_TEST(tcp) diff --git a/tests/src/sll2_test.cpp b/tests/src/sll2_test.cpp new file mode 100644 index 00000000..34606218 --- /dev/null +++ b/tests/src/sll2_test.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace Tins; + +class SLL2Test : public testing::Test { +public: + static const uint8_t expected_packet[]; + + void test_equals(const SLL2 &, const SLL2 &); +}; + +const uint8_t SLL2Test::expected_packet[] = { + 8, 0, 0, 0, 0, 0, 1, 27, 0, 1,0, 6, 0, 27, 17, 210, 27, + 235, 0, 0, 69, 0, 0, 116, 65, 18, 0, 0, 44, 6, 156, 54, + 173, 194, 66, 109, 192, 168, 0, 100, 3, 225, 141, 4, 55, 61, 150, + 161, 85, 106, 73, 189, 128, 24, 1, 0, 202, 119, 0, 0, 1, 1, + 8, 10, 71, 45, 40, 171, 0, 19, 78, 86, 23, 3, 1, 0, 59, + 168, 147, 182, 150, 159, 178, 204, 116, 62, 85, 80, 167, 23, 24, 173, + 236, 55, 46, 190, 205, 255, 19, 248, 129, 198, 140, 208, 60, 79, 59, + 38, 165, 131, 33, 105, 212, 112, 174, 80, 211, 48, 37, 116, 108, 109, + 33, 36, 231, 154, 131, 112, 246, 3, 180, 199, 158, 205, 123, 238}; + +TEST_F(SLL2Test, DefaultConstructor) { + SLL2 sll2; + EXPECT_EQ(0, sll2.protocol()); + EXPECT_EQ(0, sll2.interface_index()); + EXPECT_EQ(0, sll2.lladdr_type()); + EXPECT_EQ(0, sll2.packet_type()); + EXPECT_EQ(0, sll2.lladdr_len()); + EXPECT_EQ(SLL2::address_type("00:00:00:00:00:00:00:00"), sll2.address()); +} + +TEST_F(SLL2Test, ConstructorFromBuffer) { + typedef HWAddress<6> address_type; + address_type addr("00:1b:11:d2:1b:eb"); + SLL2 sll2(expected_packet, sizeof(expected_packet)); + EXPECT_EQ(Constants::Ethernet::IP, sll2.protocol()); + EXPECT_EQ(283, sll2.interface_index()); + EXPECT_EQ(1, sll2.lladdr_type()); + EXPECT_EQ(0, sll2.packet_type()); + EXPECT_EQ(6, sll2.lladdr_len()); + EXPECT_EQ(addr, sll2.address()); + + ASSERT_TRUE(sll2.inner_pdu() != NULL); + EXPECT_EQ(sll2.find_pdu(), sll2.inner_pdu()); +} + +TEST_F(SLL2Test, Serialize) { + SLL2 sll2(expected_packet, sizeof(expected_packet)); + SLL2::serialization_type buffer = sll2.serialize(); + ASSERT_EQ(sizeof(expected_packet), buffer.size()); + EXPECT_TRUE(std::equal(buffer.begin(), buffer.end(), expected_packet)); +} + +TEST_F(SLL2Test, Protocol) { + SLL2 sll2; + sll2.protocol(0x923f); + EXPECT_EQ(0x923f, sll2.protocol()); +} + +TEST_F(SLL2Test, InterfaceIndex) { + SLL2 sll2; + sll2.interface_index(0x1234923f); + EXPECT_EQ(0x1234923f, sll2.interface_index()); +} + +TEST_F(SLL2Test, LLADDRType) { + SLL2 sll; + sll.lladdr_type(0x923f); + EXPECT_EQ(0x923f, sll.lladdr_type()); +} + +TEST_F(SLL2Test, PacketType) { + SLL2 sll; + sll.packet_type(0x3f); + EXPECT_EQ(0x3f, sll.packet_type()); +} + +TEST_F(SLL2Test, LLADDRLen) { + SLL2 sll2; + sll2.lladdr_len(0x92); + EXPECT_EQ(0x92, sll2.lladdr_len()); +} + +TEST_F(SLL2Test, Address) { + HWAddress<6> addr = "00:01:02:03:04:05"; + SLL2 sll2; + sll2.address(addr); + EXPECT_EQ(addr, sll2.address()); +} From 3dec8ef7de1574389d3350bbf78bb1ff5986009a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Yao=20=E5=A7=9A=E8=92=99?= Date: Fri, 26 Jul 2024 23:04:59 +0800 Subject: [PATCH 2/3] Restore form auto formatter --- include/tins/rtp.h | 615 ++++++++++++++++++++++----------------------- 1 file changed, 303 insertions(+), 312 deletions(-) diff --git a/include/tins/rtp.h b/include/tins/rtp.h index 68023f21..13ca9fb3 100644 --- a/include/tins/rtp.h +++ b/include/tins/rtp.h @@ -18,320 +18,311 @@ namespace Tins { */ class TINS_API RTP : public PDU { public: - /** - * \brief This PDU's flag. - */ - static const PDU::PDUType pdu_flag = PDU::RTP; - - /** - * The type used to store CSRC identifiers. - */ - typedef std::vector csrc_ids_type; - - /** - * The type used to store extension header data. - */ - typedef std::vector extension_header_data_type; - - /** - * Default constructor. - */ - RTP(); - - /** - * \brief Constructs a RTP object from a buffer. - * - * \param data The buffer from which this PDU will be constructed. - * \param size The size of the data buffer. - */ - RTP(const uint8_t *data, uint32_t size); - - /** - * \brief Getter for the version. - */ - small_uint<2> version() const { return header_.version; } - - /** - * \brief Getter for the padding bit. - */ - small_uint<1> padding_bit() const { return header_.padding; } - - /** - * \brief Getter for the extension bit. - */ - small_uint<1> extension_bit() const { return header_.extension; } - - /** - * \brief Getter for the CSRC count. - */ - small_uint<4> csrc_count() const { return header_.csrc_count; } - - /** - * \brief Getter for the marker bit. - */ - small_uint<1> marker_bit() const { return header_.marker; } - - /** - * \brief Getter for the payload type. - */ - small_uint<7> payload_type() const { return header_.payload_type; } - - /** - * \brief Getter for the sequence number. - */ - uint16_t sequence_number() const { - return Endian::be_to_host(header_.seq_num); - } - - /** - * \brief Getter for the timestamp. - */ - uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); } - - /** - * \brief Getter for the SSRC identifier. - */ - uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); } - - /** - * \brief Getter for the CSRC identifiers. - */ - const csrc_ids_type &csrc_ids() const { return csrc_ids_; } - - /** - * \brief Getter for the padding size. - */ - uint8_t padding_size() const { return padding_size_; } - - /** - * \brief Getter for the extension header profile. - */ - uint16_t extension_profile() const { - return Endian::be_to_host(ext_header_.profile); - } - - /** - * \brief Getter for the extension header length. - */ - uint16_t extension_length() const { - return Endian::be_to_host(ext_header_.length); - } - - /** - * \brief Getter for the extension header data. - */ - const extension_header_data_type &extension_data() const { return ext_data_; } - - /** - * \brief Setter for the version. - * \param version The new version. - */ - void version(small_uint<2> version) { header_.version = version; } - - /** - * \brief Setter for the extension bit. - * \param extension The new extension bit. - */ - void extension_bit(small_uint<1> extension) { header_.extension = extension; } - - /** - * \brief Setter for the marker bit. - * \param marker The new marker bit. - */ - void marker_bit(small_uint<1> marker) { header_.marker = marker; } - - /** - * \brief Setter for the payload type. - * \param payload_type The new payload type. - */ - void payload_type(small_uint<7> payload_type) { - header_.payload_type = payload_type; - } - - /** - * \brief Setter for the sequence number. - * \param seq_num The new sequence number. - */ - void sequence_number(uint16_t seq_num) { - header_.seq_num = Endian::host_to_be(seq_num); - } - - /** - * \brief Setter for the timestamp. - * \param timestamp The new timestamp. - */ - void timestamp(uint32_t timestamp) { - header_.timestamp = Endian::host_to_be(timestamp); - } - - /** - * \brief Setter for the SSRC identifier. - * \param ssrc_id The new SSRC identifier. - */ - void ssrc_id(uint32_t ssrc_id) { - header_.ssrc_id = Endian::host_to_be(ssrc_id); - } - - /** - * \brief Setter for the padding size. - * \param size The new padding size. - */ - void padding_size(uint8_t size) { - padding_bit(size > 0); - padding_size_ = size; - } - - /** - * \brief Setter for the extension header profile. - * \param profile The new extension header profile. - */ - void extension_profile(uint16_t profile) { - ext_header_.profile = Endian::host_to_be(profile); - } - - /** - * \brief Adds a word of extension header data. - * - * The word is added after the last word of extension header data. - * - * \param value The value of the extension header data to be added. - */ - void add_extension_data(const uint32_t value); - - /** - * \brief Removes a word of extension header data. - * - * If there are multiple words of extension header data of the given value, - * only the first one will be removed. - * - * \param value The value of the extension header data to be removed. - * \return true if the extension header data was removed, false otherwise. - */ - bool remove_extension_data(const uint32_t value); - - /** - * \brief Searches for extension header data that matches the given value. - * \param value The extension header data to be searched. - * \return true if the extension header data was found, false otherwise. - */ - bool search_extension_data(const uint32_t value); - - /** - * \brief Adds a CSRC identifier. - * - * The CSRC identifier is added after the last CSRC identifier in the - * extension header. - * - * \param csrc_id The CSRC identifier to be added - */ - void add_csrc_id(const uint32_t csrc_id); - - /** - * \brief Removes a CSRC identifier. - * - * If there are multiple CSRC identifiers of the given value, only the first - * one will be removed. - * - * \param value The value of the CSRC identifier to be removed. - * \return true if the CSRC identifier was removed, false otherwise. - */ - bool remove_csrc_id(const uint32_t value); - - /** - * \brief Searches for a CSRC identifier that matches the given value. - * \param value The CSRC identifier to be searched. - * \return true if the CSRC identifier was found, false otherwise. - */ - bool search_csrc_id(const uint32_t value); - - /** - * \brief Returns the RTP packet's header length. - * - * This method overrides PDU::header_size. - * - * \return An uint32_t with the header's size. - * \sa PDU::header_size - */ - uint32_t header_size() const; - - /** - * \brief Returns the RTP packet's trailer length. - * - * This method overrides PDU::trailer_size. - * - * \return An uint32_t with the trailer's size. - * \sa PDU::trailer_size - */ - uint32_t trailer_size() const { return static_cast(padding_size_); } - - /** - * \brief Getter for the PDU's type. - * \sa PDU::pdu_type - */ - PDUType pdu_type() const { return pdu_flag; } - - /** - * \sa PDU::clone - */ - RTP *clone() const { return new RTP(*this); } + /** + * \brief This PDU's flag. + */ + static const PDU::PDUType pdu_flag = PDU::RTP; + + /** + * The type used to store CSRC identifiers. + */ + typedef std::vector csrc_ids_type; + + /** + * The type used to store extension header data. + */ + typedef std::vector extension_header_data_type; + + /** + * Default constructor. + */ + RTP(); + + /** + * \brief Constructs a RTP object from a buffer. + * + * \param data The buffer from which this PDU will be constructed. + * \param size The size of the data buffer. + */ + RTP(const uint8_t* data, uint32_t size); + + /** + * \brief Getter for the version. + */ + small_uint<2> version() const { return header_.version; } + + /** + * \brief Getter for the padding bit. + */ + small_uint<1> padding_bit() const { return header_.padding; } + + /** + * \brief Getter for the extension bit. + */ + small_uint<1> extension_bit() const { return header_.extension; } + + /** + * \brief Getter for the CSRC count. + */ + small_uint<4> csrc_count() const { return header_.csrc_count; } + + /** + * \brief Getter for the marker bit. + */ + small_uint<1> marker_bit() const { return header_.marker; } + + /** + * \brief Getter for the payload type. + */ + small_uint<7> payload_type() const { return header_.payload_type; } + + /** + * \brief Getter for the sequence number. + */ + uint16_t sequence_number() const { return Endian::be_to_host(header_.seq_num); } + + /** + * \brief Getter for the timestamp. + */ + uint32_t timestamp() const { return Endian::be_to_host(header_.timestamp); } + + /** + * \brief Getter for the SSRC identifier. + */ + uint32_t ssrc_id() const { return Endian::be_to_host(header_.ssrc_id); } + + /** + * \brief Getter for the CSRC identifiers. + */ + const csrc_ids_type& csrc_ids() const { + return csrc_ids_; + } + + /** + * \brief Getter for the padding size. + */ + uint8_t padding_size() const { return padding_size_; } + + /** + * \brief Getter for the extension header profile. + */ + uint16_t extension_profile() const { return Endian::be_to_host(ext_header_.profile); } + + /** + * \brief Getter for the extension header length. + */ + uint16_t extension_length() const { return Endian::be_to_host(ext_header_.length); } + + /** + * \brief Getter for the extension header data. + */ + const extension_header_data_type& extension_data() const { + return ext_data_; + } + + /** + * \brief Setter for the version. + * \param version The new version. + */ + void version(small_uint<2> version) { header_.version = version; } + + /** + * \brief Setter for the extension bit. + * \param extension The new extension bit. + */ + void extension_bit(small_uint<1> extension) { header_.extension = extension; } + + /** + * \brief Setter for the marker bit. + * \param marker The new marker bit. + */ + void marker_bit(small_uint<1> marker) { header_.marker = marker; } + + /** + * \brief Setter for the payload type. + * \param payload_type The new payload type. + */ + void payload_type(small_uint<7> payload_type) { header_.payload_type = payload_type; } + + /** + * \brief Setter for the sequence number. + * \param seq_num The new sequence number. + */ + void sequence_number(uint16_t seq_num) { header_.seq_num = Endian::host_to_be(seq_num); } + + /** + * \brief Setter for the timestamp. + * \param timestamp The new timestamp. + */ + void timestamp(uint32_t timestamp) { header_.timestamp = Endian::host_to_be(timestamp); } + + /** + * \brief Setter for the SSRC identifier. + * \param ssrc_id The new SSRC identifier. + */ + void ssrc_id(uint32_t ssrc_id) { header_.ssrc_id = Endian::host_to_be(ssrc_id); } + + /** + * \brief Setter for the padding size. + * \param size The new padding size. + */ + void padding_size(uint8_t size) { + padding_bit(size > 0); + padding_size_ = size; + } + + /** + * \brief Setter for the extension header profile. + * \param profile The new extension header profile. + */ + void extension_profile(uint16_t profile) { ext_header_.profile = Endian::host_to_be(profile); } + + /** + * \brief Adds a word of extension header data. + * + * The word is added after the last word of extension header data. + * + * \param value The value of the extension header data to be added. + */ + void add_extension_data(const uint32_t value); + + /** + * \brief Removes a word of extension header data. + * + * If there are multiple words of extension header data of the given value, + * only the first one will be removed. + * + * \param value The value of the extension header data to be removed. + * \return true if the extension header data was removed, false otherwise. + */ + bool remove_extension_data(const uint32_t value); + + /** + * \brief Searches for extension header data that matches the given value. + * \param value The extension header data to be searched. + * \return true if the extension header data was found, false otherwise. + */ + bool search_extension_data(const uint32_t value); + + /** + * \brief Adds a CSRC identifier. + * + * The CSRC identifier is added after the last CSRC identifier in the extension + * header. + * + * \param csrc_id The CSRC identifier to be added + */ + void add_csrc_id(const uint32_t csrc_id); + + /** + * \brief Removes a CSRC identifier. + * + * If there are multiple CSRC identifiers of the given value, only the first one + * will be removed. + * + * \param value The value of the CSRC identifier to be removed. + * \return true if the CSRC identifier was removed, false otherwise. + */ + bool remove_csrc_id(const uint32_t value); + + /** + * \brief Searches for a CSRC identifier that matches the given value. + * \param value The CSRC identifier to be searched. + * \return true if the CSRC identifier was found, false otherwise. + */ + bool search_csrc_id(const uint32_t value); + + /** + * \brief Returns the RTP packet's header length. + * + * This method overrides PDU::header_size. + * + * \return An uint32_t with the header's size. + * \sa PDU::header_size + */ + uint32_t header_size() const; + + /** + * \brief Returns the RTP packet's trailer length. + * + * This method overrides PDU::trailer_size. + * + * \return An uint32_t with the trailer's size. + * \sa PDU::trailer_size + */ + uint32_t trailer_size() const { return static_cast(padding_size_); } + + /** + * \brief Getter for the PDU's type. + * \sa PDU::pdu_type + */ + PDUType pdu_type() const { return pdu_flag; } + + /** + * \sa PDU::clone + */ + RTP *clone() const { return new RTP(*this); } private: - TINS_BEGIN_PACK - struct rtp_header { -#if TINS_IS_BIG_ENDIAN - uint16_t version : 2, padding : 1, extension : 1, csrc_count : 4, - marker : 1, payload_type : 7; -#elif TINS_IS_LITTLE_ENDIAN - uint16_t csrc_count : 4, extension : 1, padding : 1, version : 2, - payload_type : 7, marker : 1; -#endif - uint16_t seq_num; - uint32_t timestamp; - uint32_t ssrc_id; - } TINS_END_PACK; - - TINS_BEGIN_PACK - struct rtp_extension_header { - uint16_t profile; - uint16_t length; - } TINS_END_PACK; - - void write_serialization(uint8_t *buffer, uint32_t size); - csrc_ids_type::const_iterator - search_csrc_id_iterator(const uint32_t csrc_id) const; - csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id); - extension_header_data_type::const_iterator - search_extension_data_iterator(const uint32_t data) const; - extension_header_data_type::iterator - search_extension_data_iterator(const uint32_t data); - - /** - * \brief Setter for the padding bit. - * \param padding The new padding bit. - */ - void padding_bit(small_uint<1> padding) { header_.padding = padding; } - - /** - * \brief Setter for the CSRC count. Hidden from the public interface. - * \param csrc_count The new CSRC count. - */ - void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; } - - /** - * \brief Setter for the extension header length. Hidden from the public - * interface. \param length The new extension header length. - */ - void extension_length(uint16_t length) { - ext_header_.length = Endian::host_to_be(length); - } - - rtp_header header_; - csrc_ids_type csrc_ids_; - rtp_extension_header ext_header_; - extension_header_data_type ext_data_; - uint8_t padding_size_; + TINS_BEGIN_PACK + struct rtp_header { + #if TINS_IS_BIG_ENDIAN + uint16_t version:2, + padding:1, + extension:1, + csrc_count:4, + marker:1, + payload_type:7; + #elif TINS_IS_LITTLE_ENDIAN + uint16_t csrc_count:4, + extension:1, + padding:1, + version:2, + payload_type:7, + marker:1; + #endif + uint16_t seq_num; + uint32_t timestamp; + uint32_t ssrc_id; + } TINS_END_PACK; + + TINS_BEGIN_PACK + struct rtp_extension_header { + uint16_t profile; + uint16_t length; + } TINS_END_PACK; + + void write_serialization(uint8_t* buffer, uint32_t size); + csrc_ids_type::const_iterator search_csrc_id_iterator(const uint32_t csrc_id) const; + csrc_ids_type::iterator search_csrc_id_iterator(const uint32_t csrc_id); + extension_header_data_type::const_iterator search_extension_data_iterator(const uint32_t data) const; + extension_header_data_type::iterator search_extension_data_iterator(const uint32_t data); + + /** + * \brief Setter for the padding bit. + * \param padding The new padding bit. + */ + void padding_bit(small_uint<1> padding) { header_.padding = padding; } + + /** + * \brief Setter for the CSRC count. Hidden from the public interface. + * \param csrc_count The new CSRC count. + */ + void csrc_count(small_uint<4> csrc_count) { header_.csrc_count = csrc_count; } + + /** + * \brief Setter for the extension header length. Hidden from the public interface. + * \param length The new extension header length. + */ + void extension_length(uint16_t length) { ext_header_.length = Endian::host_to_be(length); } + + rtp_header header_; + csrc_ids_type csrc_ids_; + rtp_extension_header ext_header_; + extension_header_data_type ext_data_; + uint8_t padding_size_; }; -} // namespace Tins +} // Tins -#endif // TINS_RTP_H +#endif // TINS_RTP_H \ No newline at end of file From 5ae19872a32d0a071b1fc4041c089f7be6691cad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Yao=20=E5=A7=9A=E8=92=99?= Date: Fri, 26 Jul 2024 23:07:38 +0800 Subject: [PATCH 3/3] Restore from auto formatter --- include/tins/rtp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/tins/rtp.h b/include/tins/rtp.h index 13ca9fb3..0040387a 100644 --- a/include/tins/rtp.h +++ b/include/tins/rtp.h @@ -325,4 +325,4 @@ class TINS_API RTP : public PDU { } // Tins -#endif // TINS_RTP_H \ No newline at end of file +#endif // TINS_RTP_H