Skip to content

Commit

Permalink
Add linux cooked capture v2 (seladb#1138)
Browse files Browse the repository at this point in the history
  • Loading branch information
jiangjiongyu authored Aug 7, 2023
1 parent 0725fa1 commit 5666e28
Show file tree
Hide file tree
Showing 23 changed files with 598 additions and 48 deletions.
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
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:
/**
* 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

0 comments on commit 5666e28

Please sign in to comment.