From d4fce241e98aeed9aa33ab0582571ceac71a1433 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 13:31:39 +0300 Subject: [PATCH 1/6] Added RawPacketBase as initial framework for base class between RawPacket and MBufRawPacket. --- Packet++/header/RawPacket.h | 91 ++++++++++++++++++++++++++----------- Packet++/src/RawPacket.cpp | 47 +++++++++++-------- 2 files changed, 94 insertions(+), 44 deletions(-) diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 41cb56a2a0..33268779c7 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -251,20 +251,82 @@ namespace pcpp /// Max packet size supported #define PCPP_MAX_PACKET_SIZE 65536 + namespace internal + { + // TODO: Class is experimental and should not be used in user code yet. Eventually promote it to public API + /// @brief A base class for raw packet classes, containing common attributes and methods. + class RawPacketBase + { + protected: + /// @brief A default constructor that zero initializes the timestamp and sets the link layer type to + /// Ethernet. + RawPacketBase() = default; + /// @brief A constructor that initializes the timestamp and link layer type. + /// @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision) + /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. + RawPacketBase(timespec timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + /// @brief A constructor that initializes the timestamp and link layer type. + /// @param[in] timestamp The timestamp packet was received by the NIC (in usec precision) + /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. + RawPacketBase(timeval timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + + // Copy and move constructors and assignment operators are protected to prevent slicing + RawPacketBase(const RawPacketBase&) = default; + RawPacketBase(RawPacketBase&&) = default; + RawPacketBase& operator=(const RawPacketBase&) = default; + RawPacketBase& operator=(RawPacketBase&&) = default; + + public: + virtual ~RawPacketBase() = default; + + /// @brief Get the link layer type of the packet. + /// @return A LinkLayerType enum value representing the link layer type of the packet. + LinkLayerType getLinkLayerType() const + { + return m_LinkLayerType; + } + + /// @brief Return the timestamp of the packet. + /// @return The timestamp of the packet with nanosecond precision. + timespec getPacketTimeStamp() const + { + return m_TimeStamp; + } + + /// Set raw packet timestamp with usec precision + /// @param[in] timestamp The timestamp to set (with usec precision) + /// @return True if timestamp was set successfully, false otherwise + bool setPacketTimeStamp(timeval timestamp); + + /// Set raw packet timestamp with nsec precision + /// @param[in] timestamp The timestamp to set (with nsec precision) + /// @return True if timestamp was set successfully, false otherwise + bool setPacketTimeStamp(timespec timestamp); + + protected: + void setLinkLayerType(LinkLayerType linkLayerType) + { + m_LinkLayerType = linkLayerType; + } + + private: + timespec m_TimeStamp{}; // Zero initialized + LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET; + }; + } // namespace internal + /// @class RawPacket /// This class holds the packet as raw (not parsed) data. The data is held as byte array. In addition to the data /// itself every instance also holds a timestamp representing the time the packet was received by the NIC. RawPacket /// instance isn't read only. The user can change the packet data, add or remove data, etc. - class RawPacket + class RawPacket : public internal::RawPacketBase { protected: uint8_t* m_RawData = nullptr; int m_RawDataLen = 0; int m_FrameLength = 0; - timespec m_TimeStamp{}; // Zero initialized bool m_DeleteRawDataAtDestructor = true; bool m_RawPacketSet = false; - LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET; void copyDataFrom(const RawPacket& other, bool allocateData = true); @@ -372,13 +434,6 @@ namespace pcpp return m_RawData; } - /// Get the link layer type - /// @return the type of the link layer - LinkLayerType getLinkLayerType() const - { - return m_LinkLayerType; - } - /// This static method validates whether a link type integer value is valid /// @param[in] linkTypeValue Link type integer value /// @return True if the link type value is valid and can be casted into LinkLayerType enum, false otherwise @@ -397,22 +452,6 @@ namespace pcpp { return m_FrameLength; } - /// Get raw data timestamp - /// @return Raw data timestamp - timespec getPacketTimeStamp() const - { - return m_TimeStamp; - } - - /// Set raw packet timestamp with usec precision - /// @param[in] timestamp The timestamp to set (with usec precision) - /// @return True if timestamp was set successfully, false otherwise - virtual bool setPacketTimeStamp(timeval timestamp); - - /// Set raw packet timestamp with nsec precision - /// @param[in] timestamp The timestamp to set (with nsec precision) - /// @return True if timestamp was set successfully, false otherwise - virtual bool setPacketTimeStamp(timespec timestamp); /// Get an indication whether raw data was already set for this instance. /// @return True if raw data was set for this instance. Raw data can be set using the non-default constructor, diff --git a/Packet++/src/RawPacket.cpp b/Packet++/src/RawPacket.cpp index 08022885c0..520396c4db 100644 --- a/Packet++/src/RawPacket.cpp +++ b/Packet++/src/RawPacket.cpp @@ -7,6 +7,28 @@ namespace pcpp { + namespace internal + { + RawPacketBase::RawPacketBase(timespec timestamp, LinkLayerType linkLayerType) + : m_TimeStamp(timestamp), m_LinkLayerType(linkLayerType) + {} + + RawPacketBase::RawPacketBase(timeval timestamp, LinkLayerType linkLayerType) + : m_TimeStamp(internal::toTimespec(timestamp)), m_LinkLayerType(linkLayerType) + {} + + bool RawPacketBase::setPacketTimeStamp(timeval timestamp) + { + return setPacketTimeStamp(internal::toTimespec(timestamp)); + } + + bool RawPacketBase::setPacketTimeStamp(timespec timestamp) + { + m_TimeStamp = timestamp; + return true; + } + } // namespace internal + RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) : RawPacket(pRawData, rawDataLen, internal::toTimespec(timestamp), deleteRawDataAtDestructor, layerType) @@ -14,9 +36,9 @@ namespace pcpp RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) - : m_RawData(const_cast(pRawData)), m_RawDataLen(rawDataLen), m_FrameLength(rawDataLen), - m_TimeStamp(timestamp), m_DeleteRawDataAtDestructor(deleteRawDataAtDestructor), m_RawPacketSet(true), - m_LinkLayerType(layerType) + : internal::RawPacketBase(timestamp, layerType), m_RawData(const_cast(pRawData)), + m_RawDataLen(rawDataLen), m_FrameLength(rawDataLen), m_DeleteRawDataAtDestructor(deleteRawDataAtDestructor), + m_RawPacketSet(true) {} RawPacket::~RawPacket() @@ -52,7 +74,8 @@ namespace pcpp if (!other.m_RawPacketSet) return; - m_TimeStamp = other.m_TimeStamp; + // Call base class copy assignment operator to copy timestamp and link layer type + RawPacketBase::operator=(other); if (allocateData) { @@ -62,7 +85,6 @@ namespace pcpp } memcpy(m_RawData, other.m_RawData, other.m_RawDataLen); - m_LinkLayerType = other.m_LinkLayerType; m_FrameLength = other.m_FrameLength; m_RawPacketSet = true; } @@ -81,9 +103,9 @@ namespace pcpp m_FrameLength = (frameLength == -1) ? rawDataLen : frameLength; m_RawData = (uint8_t*)pRawData; m_RawDataLen = rawDataLen; - m_TimeStamp = timestamp; + setPacketTimeStamp(timestamp); // Always returns true + setLinkLayerType(layerType); m_RawPacketSet = true; - m_LinkLayerType = layerType; return true; } @@ -175,17 +197,6 @@ namespace pcpp return true; } - bool RawPacket::setPacketTimeStamp(timeval timestamp) - { - return setPacketTimeStamp(internal::toTimespec(timestamp)); - } - - bool RawPacket::setPacketTimeStamp(timespec timestamp) - { - m_TimeStamp = timestamp; - return true; - } - bool RawPacket::isLinkTypeValid(int linkTypeValue) { if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276) From 2642400ff3adf77488c16d9af3b2ba32f50127b8 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 17:27:05 +0300 Subject: [PATCH 2/6] Fixed timestamp access. --- Pcap++/src/MBufRawPacket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pcap++/src/MBufRawPacket.cpp b/Pcap++/src/MBufRawPacket.cpp index 9922205785..beee2f8639 100644 --- a/Pcap++/src/MBufRawPacket.cpp +++ b/Pcap++/src/MBufRawPacket.cpp @@ -131,7 +131,7 @@ namespace pcpp return; } - setMBuf(newMbuf, other.m_TimeStamp); + setMBuf(newMbuf, other.getPacketTimeStamp()); m_RawPacketSet = false; From 3b2b57cc9187b3ad101cf8622f7807b548c5e125 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 17:27:57 +0300 Subject: [PATCH 3/6] Fixed explicit ctors --- Packet++/header/RawPacket.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 33268779c7..52a330b61b 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -264,11 +264,11 @@ namespace pcpp /// @brief A constructor that initializes the timestamp and link layer type. /// @param[in] timestamp The timestamp packet was received by the NIC (in nsec precision) /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. - RawPacketBase(timespec timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + explicit RawPacketBase(timespec timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); /// @brief A constructor that initializes the timestamp and link layer type. /// @param[in] timestamp The timestamp packet was received by the NIC (in usec precision) /// @param[in] linkLayerType The link layer type of the packet, defaulting to Ethernet. - RawPacketBase(timeval timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); + explicit RawPacketBase(timeval timestamp, LinkLayerType linkLayerType = LinkLayerType::LINKTYPE_ETHERNET); // Copy and move constructors and assignment operators are protected to prevent slicing RawPacketBase(const RawPacketBase&) = default; From 3489b6e4cb119307569e16d594a94b5ca83a918e Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Sat, 26 Jul 2025 19:25:27 +0300 Subject: [PATCH 4/6] Fixed usages of now private variables. --- Pcap++/src/MBufRawPacket.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pcap++/src/MBufRawPacket.cpp b/Pcap++/src/MBufRawPacket.cpp index beee2f8639..a6469f16f3 100644 --- a/Pcap++/src/MBufRawPacket.cpp +++ b/Pcap++/src/MBufRawPacket.cpp @@ -217,10 +217,10 @@ namespace pcpp m_RawDataLen = rte_pktmbuf_pkt_len(m_MBuf); memcpy(m_RawData, pRawData, m_RawDataLen); delete[] pRawData; - m_TimeStamp = timestamp; + setPacketTimeStamp(timestamp); m_RawPacketSet = true; m_FrameLength = frameLength; - m_LinkLayerType = layerType; + setLinkLayerType(layerType); return true; } From d7eba533219cdb55f3c0e607d708fb8e038056a8 Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 1 Aug 2025 15:15:26 +0300 Subject: [PATCH 5/6] Added comments about future API on base class. --- Packet++/header/RawPacket.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 52a330b61b..750e30c11d 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -303,6 +303,22 @@ namespace pcpp /// @return True if timestamp was set successfully, false otherwise bool setPacketTimeStamp(timespec timestamp); + // To be implemented in derived classes: + + // bool isContiguous() const = 0; <- eventually needed for MBufRawPacket to indicate if the mbuf is a single + // segment or not. + + // uint8_t* getRawData() = 0; <- maybe protected, so direct modification is not allowed? Expose maybe a span + // proxy instead for public? uint8_t const* getRawData() const = 0; int getRawDataLen() const = 0; <- should + // probably return size_t for consistency with modern C++ practices, but the current API uses int + + // Mutators: + // void setRawData(...) = 0; + // bool appendData(...) = 0; + // bool insertData(...) = 0; + // void removeData(...) = 0; + // void clear(...) = 0; + protected: void setLinkLayerType(LinkLayerType linkLayerType) { From 00b4db929b1e461d52dff7876eb2e2725096a31a Mon Sep 17 00:00:00 2001 From: Dimitar Krastev Date: Fri, 1 Aug 2025 15:17:19 +0300 Subject: [PATCH 6/6] Lint --- Packet++/header/RawPacket.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 750e30c11d..51c346f2a7 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -309,8 +309,12 @@ namespace pcpp // segment or not. // uint8_t* getRawData() = 0; <- maybe protected, so direct modification is not allowed? Expose maybe a span - // proxy instead for public? uint8_t const* getRawData() const = 0; int getRawDataLen() const = 0; <- should - // probably return size_t for consistency with modern C++ practices, but the current API uses int + // proxy instead for public? + + // uint8_t const* getRawData() const = 0; + + // int getRawDataLen() const = 0; <- should probably return size_t for consistency with modern C++ + // practices, but the current API uses int // Mutators: // void setRawData(...) = 0;