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

Add linux cooked capture v2 #1138

Merged
merged 21 commits into from
Aug 7, 2023
Merged
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
2 changes: 2 additions & 0 deletions Examples/PcapPrinter/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ std::string linkLayerToString(pcpp::LinkLayerType linkLayer)
return "IEEE 802.5 Token Ring";
else if (linkLayer == pcpp::LINKTYPE_LINUX_SLL)
return "Linux cooked capture";
else if (linkLayer == pcpp::LINKTYPE_LINUX_SLL2)
return "Linux cooked capture v2";
else if (linkLayer == pcpp::LINKTYPE_NULL)
return "Null/Loopback";
else if (linkLayer == pcpp::LINKTYPE_RAW || linkLayer == pcpp::LINKTYPE_DLT_RAW1 || linkLayer == pcpp::LINKTYPE_DLT_RAW2)
Expand Down
2 changes: 2 additions & 0 deletions Packet++/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ add_library(
src/SdpLayer.cpp
src/SingleCommandTextProtocol.cpp
src/SipLayer.cpp
src/Sll2Layer.cpp
seladb marked this conversation as resolved.
Show resolved Hide resolved
src/SllLayer.cpp
src/SomeIpLayer.cpp
src/SomeIpSdLayer.cpp
Expand Down Expand Up @@ -106,6 +107,7 @@ set(public_headers
header/SingleCommandTextProtocol.h
header/SipLayer.h
header/SllLayer.h
header/Sll2Layer.h
header/SomeIpLayer.h
header/SomeIpSdLayer.h
header/SSHLayer.h
Expand Down
7 changes: 6 additions & 1 deletion Packet++/header/ProtocolType.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,12 @@ namespace pcpp
/**
* COTP protocol
*/
const ProtocolType COTP = 0x900000000000;
const ProtocolType COTP = 0x4000000000000;

/**
* SLL2 protocol
*/
const ProtocolType SLL2 = 0x8000000000000;

/**
* An enum representing OSI model layers
Expand Down
4 changes: 3 additions & 1 deletion Packet++/header/RawPacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ namespace pcpp
/** Formats for WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol common packet structure captures */
LINKTYPE_WATTSTOPPER_DLM = 263,
/** Messages between ISO 14443 contactless smartcards (Proximity Integrated Circuit Card, PICC) and card readers (Proximity Coupling Device, PCD), with the message format specified by the PCAP format for ISO14443 specification */
LINKTYPE_ISO_14443 = 264
LINKTYPE_ISO_14443 = 264,
/** Linux "cooked" capture encapsulation v2 */
LINKTYPE_LINUX_SLL2 = 276
};

/**
Expand Down
192 changes: 192 additions & 0 deletions Packet++/header/Sll2Layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#ifndef PACKETPP_SLL2_LAYER
#define PACKETPP_SLL2_LAYER

#include "MacAddress.h"
#include "Layer.h"

/// @file

/**
* \namespace pcpp
* \brief The main namespace for the PcapPlusPlus lib
*/
namespace pcpp
{
/**
* @struct sll2_header
* Represents SLL2 header
*/
#pragma pack(push, 1)
struct sll2_header
{
/** Contains an Ethernet protocol type of the next layer */
uint16_t protocol_type;
/** The "Reserved (MBZ)" field is reserved, and must be set to zero */
uint16_t reserved;
/** The interface index field is a signed integer in network byte
* order and contains the 1-based index of the interface on which the packet was observed
**/
uint32_t interface_index;
/** Contains a Linux ARPHRD_ value for the link-layer device type */
uint16_t ARPHRD_type;
/** Specifies whether packet was: specifically sent to us by somebody else (value=0);
* broadcast by somebody else (value=1); multicast, but not broadcast, by somebody else (value=2);
* sent to somebody else by somebody else (value=3); sent by us (value=4)
**/
uint8_t packet_type;
/** Contains the length of the link-layer address of the sender of the packet. That length could be zero */
uint8_t link_layer_addr_len;
/** Contains the link-layer address of the sender of the packet; the number of bytes of that field that are
* meaningful is specified by the link-layer address length field
**/
uint8_t link_layer_addr[8];
};
#pragma pack(pop)

/**
* @class Sll2Layer
* Represents an SLL2 (Linux cooked capture) protocol layer
*/
class Sll2Layer : public Layer
{
public:
seladb marked this conversation as resolved.
Show resolved Hide resolved
/**
* A constructor that creates the layer from an existing packet raw data
* @param[in] data A pointer to the raw data (will be casted to ether_header)
* @param[in] dataLen Size of the data in bytes
* @param[in] packet A pointer to the Packet instance where layer will be stored in
*/
Sll2Layer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) { m_Protocol = SLL2; }

/**
* A constructor that creates a new SLL2 header and allocates the data
* @param[in] interfaceIndex The interface index
* @param[in] ARPHRDType The ARPHRD type
* @param[in] packetType The packet type
*/
Sll2Layer(uint32_t interfaceIndex, uint16_t ARPHRDType, uint8_t packetType);

~Sll2Layer() {}

/**
* Get a pointer to the Sll header. Notice this points directly to the data, so every change will change the actual packet data
* @return A pointer to the sll2_header
*/
sll2_header* getSll2Header() const { return (sll2_header*)m_Data; }

/**
* A static method that validates the input data
* @param[in] data The pointer to the beginning of a byte stream of an IEEE 802.3 Eth packet
* @param[in] dataLen The length of the byte stream
* @return True if the data is valid and can represent an IEEE 802.3 Eth packet
*/
static bool isDataValid(const uint8_t* data, size_t dataLen);

/**
* Get a protocol type of this layer
* @return protocol type
*/
uint16_t getProtocolType() const;

/**
* Set protocol type of this layer
* @param[in] protocolType type to set
*/
void setProtocolType(uint16_t protocolType);

/**
* Get interface index of this layer
* @return interface index
*/
uint32_t getInterfaceIndex() const;

/**
* Set interface index of this layer
* @param[in] interfaceIndex interface index to set
*/
void setInterfaceIndex(uint32_t interfaceIndex);

/**
* Get arphrd type of this layer
* @return arphrd type
*/
uint16_t getArphrdType() const;

/**
* Set arphrd type of this layer
* @param[in] arphrdType arphrd type to set
*/
void setArphrdType(uint16_t arphrdType);

/**
* Get packet type of this layer
* @return packet type
*/
uint8_t getPacketType() const;

/**
* Set packet type of this layer
* @param[in] packetType packet type to set
*/
void setPacketType(uint8_t packetType);

/**
* Get link layer address length
* @return link layer address length
*/
uint8_t getLinkLayerAddrLen() const;

/**
* Get link layer address data pointer
* @return link layer address data pointer
*/
const uint8_t* getLinkLayerAddr() const;

/**
* A setter for the link layer address field
* @param[in] addr The address to set. Memory will be copied to packet
* @param[in] addrLength Address length, must be lower or equal to 8 (which is max length for SLL2 address)
* @return True if address was set successfully, or false of addrLength is out of bounds (0 or larger than 8)
*/
bool setLinkLayerAddr(const uint8_t* addr, size_t addrLength);

/**
* Get a MAC address in the link layer address field
* @return return macAddress pointer was set successfully, null pointer if d MAC address isn't valid or if set failed
*/
MacAddress getLinkLayerAsMacAddress();

/**
* Set a MAC address in the link layer address field
* @param[in] macAddr MAC address to set
* @return True if address was set successfully, false if MAC address isn't valid or if set failed
*/
bool setMacAddressAsLinkLayer(const MacAddress& macAddr);

// implement abstract methods

/**
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer,
* MplsLayer.
* Otherwise sets PayloadLayer
*/
void parseNextLayer();

/**
* Calculate the next protocol type for known protocols: IPv4, IPv6, ARP, VLAN
*/
void computeCalculateFields();

/**
* @return Size of sll2_header
*/
size_t getHeaderLen() const { return sizeof(sll2_header); }

std::string toString() const;

OsiModelLayer getOsiModelLayer() const { return OsiModelDataLinkLayer; }
};

} // namespace pcpp

#endif /* PACKETPP_SLL2_LAYER */
4 changes: 2 additions & 2 deletions Packet++/header/SllLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ namespace pcpp
* @param[in] dataLen Size of the data in bytes
* @param[in] packet A pointer to the Packet instance where layer will be stored in
*/
SllLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, NULL, packet) { m_Protocol = SLL; }
SllLayer(uint8_t* data, size_t dataLen, Packet* packet) : Layer(data, dataLen, nullptr, packet) { m_Protocol = SLL; }

/**
* A constructor that creates a new SLL header and allocates the data
Expand Down Expand Up @@ -81,7 +81,7 @@ namespace pcpp
* @param[in] macAddr MAC address to set
* @return True if address was set successfully, false if MAC address isn't valid or if set failed
*/
bool setMacAddressAsLinkLayer(MacAddress macAddr);
bool setMacAddressAsLinkLayer(const MacAddress& macAddr);

/**
* Currently identifies the following next layers: IPv4Layer, IPv6Layer, ArpLayer, VlanLayer, PPPoESessionLayer, PPPoEDiscoveryLayer,
Expand Down
5 changes: 5 additions & 0 deletions Packet++/src/Packet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "EthLayer.h"
#include "EthDot3Layer.h"
#include "SllLayer.h"
#include "Sll2Layer.h"
#include "NflogLayer.h"
#include "NullLoopbackLayer.h"
#include "IPv4Layer.h"
Expand Down Expand Up @@ -733,6 +734,10 @@ Layer* Packet::createFirstLayer(LinkLayerType linkType)
{
return new SllLayer((uint8_t*)rawData, rawDataLen, this);
}
else if (linkType == LINKTYPE_LINUX_SLL2 && Sll2Layer::isDataValid(rawData, rawDataLen))
{
return new Sll2Layer((uint8_t*)rawData, rawDataLen, this);
}
else if (linkType == LINKTYPE_NULL)
{
if (rawDataLen >= sizeof(uint32_t))
Expand Down
3 changes: 2 additions & 1 deletion Packet++/src/RawPacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ bool RawPacket::setPacketTimeStamp(timespec timestamp)

bool RawPacket::isLinkTypeValid(int linkTypeValue)
{
if (linkTypeValue < 0 || linkTypeValue > 264)
if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276)
return false;

switch (static_cast<LinkLayerType>(linkTypeValue))
Expand Down Expand Up @@ -298,6 +298,7 @@ bool RawPacket::isLinkTypeValid(int linkTypeValue)
case LINKTYPE_ZWAVE_R3:
case LINKTYPE_WATTSTOPPER_DLM:
case LINKTYPE_ISO_14443:
case LINKTYPE_LINUX_SLL2:
return true;
default:
return false;
Expand Down
Loading