Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Support Linux Cooked Capture v2 (SLL2) PDU #536

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/tins/pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ class TINS_API PDU {
IPv6,
ICMPv6,
SLL,
SLL2,
DHCPv6,
DOT1AD,
DOT1Q,
Expand Down
167 changes: 167 additions & 0 deletions include/tins/sll2.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
#ifndef TINS_SLL2_H
#define TINS_SLL2_H

#include <cstdint>
#include <tins/endianness.h>
#include <tins/hw_address.h>
#include <tins/macros.h>
#include <tins/pdu.h>
#include <vector>

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
1 change: 1 addition & 0 deletions include/tins/tins.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
#include <tins/packet.h>
#include <tins/timestamp.h>
#include <tins/sll.h>
#include <tins/sll2.h>
#include <tins/dhcpv6.h>
#include <tins/pppoe.h>
#include <tins/stp.h>
Expand Down
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ set(SOURCES
rsn_information.cpp
rtp.cpp
sll.cpp
sll2.cpp
snap.cpp
stp.cpp
tcp.cpp
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions src/detail/pdu_helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <tins/icmp.h>
#include <tins/loopback.h>
#include <tins/sll.h>
#include <tins/sll2.h>
#include <tins/ppi.h>
#include <tins/icmpv6.h>
#include <tins/mpls.h>
Expand Down Expand Up @@ -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:
Expand Down
59 changes: 59 additions & 0 deletions src/sll2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include <cstring>
#include <tins/detail/pdu_helpers.h>
#include <tins/exceptions.h>
#include <tins/memory_helpers.h>
#include <tins/sll2.h>

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<uint16_t>(flag));
}
stream.write(header_);
}

} // namespace Tins
4 changes: 4 additions & 0 deletions src/sniffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <tins/dot3.h>
#include <tins/pktap.h>
#include <tins/sll.h>
#include <tins/sll2.h>
#include <tins/ppi.h>
#include <tins/ip.h>
#include <tins/ipv6.h>
Expand Down Expand Up @@ -178,6 +179,9 @@ PtrPacket BaseSniffer::next_packet() {
case DLT_LINUX_SLL:
handler = &sniff_loop_handler<SLL>;
break;
case DLT_LINUX_SLL2:
handler = &sniff_loop_handler<SLL2>;
break;
case DLT_PPI:
handler = &sniff_loop_handler<PPI>;
break;
Expand Down
1 change: 1 addition & 0 deletions tests/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading