diff --git a/Common++/header/Logger.h b/Common++/header/Logger.h index fc36013cb..eb13e4f6a 100644 --- a/Common++/header/Logger.h +++ b/Common++/header/Logger.h @@ -27,8 +27,9 @@ // Allows for conditional removal of unwanted log calls at compile time. #define PCPP_LOG_LEVEL_OFF 0 #define PCPP_LOG_LEVEL_ERROR 1 -#define PCPP_LOG_LEVEL_INFO 2 -#define PCPP_LOG_LEVEL_DEBUG 3 +#define PCPP_LOG_LEVEL_WARN 2 +#define PCPP_LOG_LEVEL_INFO 3 +#define PCPP_LOG_LEVEL_DEBUG 4 // All log messages built via a PCPP_LOG_* macro below the PCPP_ACTIVE_LOG_LEVEL will be removed at compile time. // Uses the PCPP_ACTIVE_LOG_LEVEL if it is defined, otherwise defaults to PCAP_LOG_LEVEL_DEBUG @@ -146,6 +147,7 @@ namespace pcpp { Off = PCPP_LOG_LEVEL_OFF, ///< No log messages are emitted. Error = PCPP_LOG_LEVEL_ERROR, ///< Error level logs are emitted. + Warn = PCPP_LOG_LEVEL_WARN, ///< Warning level logs and above are emitted. Info = PCPP_LOG_LEVEL_INFO, ///< Info level logs and above are emitted. Debug = PCPP_LOG_LEVEL_DEBUG ///< Debug level logs and above are emitted. }; @@ -436,6 +438,12 @@ namespace pcpp # define PCPP_LOG_INFO(message) (void)0 #endif +#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_WARN +# define PCPP_LOG_WARN(message) PCPP_LOG(pcpp::LogLevel::Warn, message) +#else +# define PCPP_LOG_WARN(message) (void)0 +#endif + #if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_ERROR # define PCPP_LOG_ERROR(message) PCPP_LOG(pcpp::LogLevel::Error, message) #else diff --git a/Packet++/header/IPReassembly.h b/Packet++/header/IPReassembly.h index 7edca7600..75cf3f3f9 100644 --- a/Packet++/header/IPReassembly.h +++ b/Packet++/header/IPReassembly.h @@ -399,7 +399,7 @@ namespace pcpp /// - If the input fragment is the last one and the reassembled packet is ready - a pointer to the reassembled /// packet is returned. Notice it's the user's responsibility to free this pointer when done using it /// - If the reassembled packet isn't ready then nullptr is returned - Packet* processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, + Packet* processPacket(IRawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /// Get a partially reassembled packet. This method returns all the reassembled data that was gathered so far diff --git a/Packet++/header/Packet.h b/Packet++/header/Packet.h index d8f66d18b..954c7bb1d 100644 --- a/Packet++/header/Packet.h +++ b/Packet++/header/Packet.h @@ -23,7 +23,7 @@ namespace pcpp friend class Layer; private: - RawPacket* m_RawPacket; + IRawPacket* m_RawPacket; Layer* m_FirstLayer; Layer* m_LastLayer; size_t m_MaxPacketLen; @@ -65,7 +65,7 @@ namespace pcpp /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the /// whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter into account - explicit Packet(RawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, + explicit Packet(IRawPacket* rawPacket, bool freeRawPacket = false, ProtocolType parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets @@ -77,7 +77,7 @@ namespace pcpp /// @param[in] parseUntil Parse the packet until you reach a certain protocol (inclusive). Can be useful for /// cases when you need to parse only up to a certain layer and want to avoid the performance impact and memory /// consumption of parsing the whole packet - explicit Packet(RawPacket* rawPacket, ProtocolType parseUntil); + explicit Packet(IRawPacket* rawPacket, ProtocolType parseUntil); /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't @@ -88,7 +88,7 @@ namespace pcpp /// @param[in] parseUntilFamily Parse the packet until you reach a certain protocol family (inclusive). Can be /// useful for cases when you need to parse only up to a certain layer and want to avoid the performance impact /// and memory consumption of parsing the whole packet - explicit Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily); + explicit Packet(IRawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily); /// A constructor for creating a packet out of already allocated RawPacket. Very useful when parsing packets /// that came from the network. When using this constructor a pointer to the RawPacket is saved (data isn't @@ -101,7 +101,7 @@ namespace pcpp /// model (inclusive). Can be useful for cases when you need to parse only up to a certain OSI layer (for /// example transport layer) and want to avoid the performance impact and memory consumption of parsing the /// whole packet - explicit Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer); + explicit Packet(IRawPacket* rawPacket, OsiModelLayer parseUntilLayer); /// A destructor for this class. Frees all layers allocated by this instance (Notice: it doesn't free layers /// that weren't allocated by this class, for example layers that were added by addLayer() or insertLayer() ). @@ -130,7 +130,7 @@ namespace pcpp /// Get a pointer to the Packet's RawPacket /// @return A pointer to the Packet's RawPacket - RawPacket* getRawPacket() const + IRawPacket* getRawPacket() const { return m_RawPacket; } @@ -147,12 +147,12 @@ namespace pcpp /// you need to parse only up to a certain layer and want to avoid the performance impact and memory consumption /// of parsing the whole packet. Default value is ::OsiModelLayerUnknown which means don't take this parameter /// into account - void setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol, + void setRawPacket(IRawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil = UnknownProtocol, OsiModelLayer parseUntilLayer = OsiModelLayerUnknown); /// Get a pointer to the Packet's RawPacket in a read-only manner /// @return A pointer to the Packet's RawPacket - const RawPacket* getRawPacketReadOnly() const + const IRawPacket* getRawPacketReadOnly() const { return m_RawPacket; } diff --git a/Packet++/header/RawPacket.h b/Packet++/header/RawPacket.h index 41cb56a2a..9929d05ed 100644 --- a/Packet++/header/RawPacket.h +++ b/Packet++/header/RawPacket.h @@ -9,6 +9,8 @@ #endif #include +#include "DeprecationUtils.h" + /// @file /// @namespace pcpp @@ -251,24 +253,188 @@ namespace pcpp /// Max packet size supported #define PCPP_MAX_PACKET_SIZE 65536 + namespace internal + { + enum class RawPacketType + { + Unknown = 0, ///< Unknown raw packet type, used as a sentinel value + Standard = 1, ///< Standard raw packet, usually used in libpcap, WinPcap, Npcap, etc. + MBufPacket = 2, ///< Raw packet that is based on mbuf structure (used in DPDK) + }; + } // namespace internal + + enum class RawPacketBufferPolicy + { + /// @brief Allocate new buffer and copy the raw data to it. + Copy, + + /// @brief Move the ownership of the raw data buffer to the RawPacket. + /// The original data must not be used after this call, and the RawPacket will take care of freeing the buffer. + Move, + + /// @brief Reference the raw data, the original data must remain valid for the lifetime of the RawPacket. + /// The packet will not reallocate the data, and operations that exceed the original buffer size will fail. + StrictReference, + + /// @brief Reference the raw data, the original data must remain valid for the lifetime of the RawPacket. + /// The packet may reallocate the data to an internal buffer if needed, and the original data will not be freed. + SoftReference, + }; + + struct BufferInfo + { + /// @brief Pointer to the raw data buffer. This pointer may be null if the buffer is empty or not allocated. + uint8_t* ptr = nullptr; + /// @brief The size of the buffer, i.e. the number of bytes currently in use. + size_t size = 0; + /// @brief The capacity of the buffer, i.e. the maximum size it can grow to without reallocation. + size_t capacity = 0; + + BufferInfo() = default; + BufferInfo(uint8_t* p, size_t s) : ptr(p), size(s), capacity(s) + {} + BufferInfo(uint8_t* p, size_t s, size_t c) : ptr(p), size(s), capacity(c) + {} + }; + + class IRawPacket + { + protected: + IRawPacket() = default; + + public: + /// A virtual destructor for this class + virtual ~IRawPacket() = default; + + /// @brief Get the type of this raw packet + /// @return The type of this raw packet, see internal::RawPacketType for more details + virtual internal::RawPacketType getRawPacketType() const = 0; + + PCPP_DEPRECATED("Use getRawPacketType()") + uint8_t getObjectType() const + { + return static_cast(getRawPacketType()); + } + + /// @return The link layer type of this raw packet + virtual LinkLayerType getLinkLayerType() const = 0; + + /// 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 + static bool isLinkTypeValid(int linkTypeValue); + + /// @return The raw data of this packet + virtual uint8_t const* getRawData() const = 0; + virtual uint8_t* getRawData() = 0; + uint8_t const* getRawDataReadOnly() const + { + return getRawData(); + } + + /// @return The length of the raw data buffer in bytes + virtual int getRawDataLen() const = 0; + /// @return The frame length of this packet (the length of the entire packet including all layers) + virtual int getFrameLength() const = 0; + /// @return The true capacity of the raw data buffer, i.e. the maximum size it can grow to without reallocation + virtual size_t getRawDataCapacity() const = 0; + + /// @return The timestamp when this packet was received by the NIC + virtual timespec getPacketTimeStamp() const = 0; + + /// 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 + virtual bool setPacketTimeStamp(timespec timestamp) = 0; + + virtual bool supportsBufferPolicy(RawPacketBufferPolicy policy) const = 0; + + bool setRawData(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timeval timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); + + virtual bool setRawData(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1) = 0; + + virtual void clear() = 0; + virtual size_t appendData(uint8_t const* dataToAppend, size_t dataToAppendLen) = 0; + virtual size_t insertData(int atIndex, uint8_t const* dataToInsert, size_t dataToInsertLen) = 0; + virtual size_t insertUninitializedData(int atIndex, size_t dataToInsertLen) = 0; + virtual bool removeData(int atIndex, size_t numOfBytesToRemove) = 0; + + virtual bool supportsReallocation() const = 0; + virtual bool reallocateData(size_t newBufferLength) = 0; + virtual bool reserve(size_t newCapacity) = 0; + + virtual IRawPacket* clone() const = 0; + }; + + class RawPacketBase : public IRawPacket + { + protected: + RawPacketBase() = default; + RawPacketBase(timespec timestamp, LinkLayerType layerType = LinkLayerType::LINKTYPE_ETHERNET); + RawPacketBase(timeval timestamp, LinkLayerType layerType = LinkLayerType::LINKTYPE_ETHERNET); + + RawPacketBase(const RawPacketBase& other) = default; + + RawPacketBase& operator=(const RawPacketBase& other) = default; + + ~RawPacketBase() override = default; + + public: + LinkLayerType getLinkLayerType() const override final + { + return m_LinkLayerType; + } + + timespec getPacketTimeStamp() const override final + { + return m_TimeStamp; + } + + using IRawPacket::setPacketTimeStamp; + bool setPacketTimeStamp(timespec timestamp) override final; + + protected: + void setLinkLayerType(LinkLayerType layerType) + { + m_LinkLayerType = layerType; + } + + private: + timespec m_TimeStamp{}; // Zero initialized + LinkLayerType m_LinkLayerType = LinkLayerType::LINKTYPE_ETHERNET; + }; + /// @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 final : public 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); - + // The true capacity of the raw data buffer, i.e. the maximum size it can grow to without reallocation + size_t m_RawDataCapacity = 0; + bool m_DeleteRawDataAtDestructor = true; // m_OwnsRawData indicates whether the raw data pointer + // Controls whether the raw data can be reallocated or not to allow for appending data exceeding the current + // capacity + bool m_ReallocationsAllowed = true; + public: + static bool isBufferPolicySupported(RawPacketBufferPolicy policy) + { + return (policy == RawPacketBufferPolicy::Copy || policy == RawPacketBufferPolicy::Move || + policy == RawPacketBufferPolicy::SoftReference || policy == RawPacketBufferPolicy::StrictReference); + } + /// A default constructor that initializes class'es attributes to default value: /// - data pointer is set to nullptr /// - data length is set to 0 @@ -288,6 +454,7 @@ namespace pcpp /// @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance /// is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed /// @param[in] layerType The link layer type of this raw packet. The default is Ethernet + PCPP_DEPRECATED("Use constructors with RawPacketBufferPolicy parameter instead") RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET); @@ -301,11 +468,21 @@ namespace pcpp /// @param[in] deleteRawDataAtDestructor An indicator whether raw data pointer should be freed when the instance /// is freed or not. If set to 'true' than pRawData will be freed when instanced is being freed /// @param[in] layerType The link layer type of this raw packet. The default is Ethernet + PCPP_DEPRECATED("Use constructors with RawPacketBufferPolicy parameter instead") RawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType = LINKTYPE_ETHERNET); + RawPacket(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timeval timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET); + RawPacket(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET); + + /// @brief A conversion constructor that creates a RawPacket from an IRawPacket instance. + /// @param source The IRawPacket instance to convert to a RawPacket. + explicit RawPacket(IRawPacket const& source); + /// A destructor for this class. Frees the raw data if deleteRawDataAtDestructor was set to 'true' - virtual ~RawPacket(); + ~RawPacket() override; /// A copy constructor that copies all data from another instance. Notice all raw data is copied (using memcpy), /// so when the original or the other instance are freed, the other won't be affected @@ -322,12 +499,18 @@ namespace pcpp /// @return A pointer to the new RawPacket object which is a clone of this object virtual RawPacket* clone() const; - /// @return RawPacket object type. Each derived class should return a different value - virtual uint8_t getObjectType() const + internal::RawPacketType getRawPacketType() const override { - return 0; + return internal::RawPacketType::Standard; } + bool supportsBufferPolicy(RawPacketBufferPolicy policy) const override + { + return isBufferPolicySupported(policy); + } + + using RawPacketBase::setRawData; + /// Set a raw data. If data was already set and deleteRawDataAtDestructor was set to 'true' the old data will be /// freed first /// @param[in] pRawData A pointer to the new raw data @@ -338,6 +521,8 @@ namespace pcpp /// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or /// set to -1 it is assumed both lengths are equal /// @return True if raw data was set successfully, false otherwise + /// @deprecated Use setRawData() overload with RawPacketBufferPolicy + PCPP_DEPRECATED("Use setRawData() overload with RawPacketBufferPolicy") virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); @@ -351,9 +536,14 @@ namespace pcpp /// actual packet length. This parameter represents the packet length. This parameter is optional, if not set or /// set to -1 it is assumed both lengths are equal /// @return True if raw data was set successfully, false otherwise + /// @deprecated Use setRawData() overload with RawPacketBufferPolicy + PCPP_DEPRECATED("Use setRawData() overload with RawPacketBufferPolicy") virtual bool setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1); + bool setRawData(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timespec timestamp, + LinkLayerType layerType = LINKTYPE_ETHERNET, int frameLength = -1) override final; + /// Initialize a raw packet with data. The main difference between this method and setRawData() is that /// setRawData() is meant for replacing the data in an existing raw packet, whereas this method is meant to be /// used right after constructing a raw packet using the default c'tor, before setting any data @@ -362,79 +552,67 @@ namespace pcpp /// @param timestamp The timestamp packet was received by the NIC (in nsec precision) /// @param layerType The link layer type for this raw data /// @return True if raw data was set successfully, false otherwise + /// @deprecated Use setRawData() overload with RawPacketBufferPolicy + PCPP_DEPRECATED("Use setRawData() overload with RawPacketBufferPolicy") bool initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType = LINKTYPE_ETHERNET); /// Get raw data pointer /// @return A read-only pointer to the raw data - const uint8_t* getRawData() const + uint8_t const* getRawData() const override final { return m_RawData; } - /// Get the link layer type - /// @return the type of the link layer - LinkLayerType getLinkLayerType() const + /// Get raw data pointer + /// @return A pointer to the raw data. + uint8_t* getRawData() override final { - return m_LinkLayerType; + return m_RawData; } - /// 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 - static bool isLinkTypeValid(int linkTypeValue); - /// Get raw data length in bytes /// @return Raw data length in bytes - int getRawDataLen() const + int getRawDataLen() const override final { return m_RawDataLen; } /// Get frame length in bytes /// @return frame length in bytes - int getFrameLength() const + int getFrameLength() const override final { return m_FrameLength; } - /// Get raw data timestamp - /// @return Raw data timestamp - timespec getPacketTimeStamp() const + + size_t getRawDataCapacity() const override final { - return m_TimeStamp; + return m_RawDataCapacity; } - /// 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, /// using setRawData(), using the copy constructor or using the assignment operator. Returns false otherwise, /// for example: if the instance was created using the default constructor or clear() was called bool isPacketSet() const { - return m_RawPacketSet; + return m_RawData != nullptr; } /// Clears all members of this instance, meaning setting raw data to nullptr, raw data length to 0, etc. /// Frees the raw data if deleteRawDataAtDestructor was set to 'true' /// @todo set timestamp to a default value as well - virtual void clear(); + void clear() override; + // TODO: Redo documentation /// Append data to the end of current data. This method works without allocating more memory, it just uses /// memcpy() to copy dataToAppend at the end of the current data. This means that the method assumes this memory /// was already allocated by the user. If it isn't the case then this method will cause memory corruption /// @param[in] dataToAppend A pointer to the data to append to current raw data /// @param[in] dataToAppendLen Length in bytes of dataToAppend - virtual void appendData(const uint8_t* dataToAppend, size_t dataToAppendLen); + size_t appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) override; + // TODO: Redo documentation /// Insert new data at some index of the current data and shift the remaining old data to the end. This method /// works without allocating more memory, it just copies dataToAppend at the relevant index and shifts the /// remaining data to the end. This means that the method assumes this memory was already allocated by the user. @@ -442,7 +620,9 @@ namespace pcpp /// @param[in] atIndex The index to insert the new data to /// @param[in] dataToInsert A pointer to the new data to insert /// @param[in] dataToInsertLen Length in bytes of dataToInsert - virtual void insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen); + size_t insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) override; + + size_t insertUninitializedData(int atIndex, size_t length) override; /// Remove certain number of bytes from current raw data buffer. All data after the removed bytes will be /// shifted back @@ -450,7 +630,12 @@ namespace pcpp /// @param[in] numOfBytesToRemove Number of bytes to remove /// @return True if all bytes were removed successfully, or false if atIndex+numOfBytesToRemove is out-of-bounds /// of the raw data buffer - virtual bool removeData(int atIndex, size_t numOfBytesToRemove); + bool removeData(int atIndex, size_t numOfBytesToRemove) override; + + bool supportsReallocation() const override + { + return m_ReallocationsAllowed; + } /// Re-allocate raw packet buffer meaning add size to it without losing the current packet data. This method /// allocates the required buffer size as instructed by the use and then copies the raw data from the current @@ -460,7 +645,9 @@ namespace pcpp /// @param[in] newBufferLength The new buffer length as required by the user. The method is responsible to /// allocate the memory /// @return True if data was reallocated successfully, false otherwise - virtual bool reallocateData(size_t newBufferLength); + bool reallocateData(size_t newBufferLength) override; + + bool reserve(size_t newCapacity) override; }; } // namespace pcpp diff --git a/Packet++/src/IPReassembly.cpp b/Packet++/src/IPReassembly.cpp index cf00c8121..6c085c44e 100644 --- a/Packet++/src/IPReassembly.cpp +++ b/Packet++/src/IPReassembly.cpp @@ -364,11 +364,10 @@ namespace pcpp auto fragmentRawPacket = fragment->getRawPacket(); auto rawDataLen = fragWrapper->getIPLayerPayload() - fragmentRawPacket->getRawData() + fragWrapper->getIPLayerPayloadSize(); - auto rawData = new uint8_t[rawDataLen]; - memcpy(rawData, fragmentRawPacket->getRawData(), rawDataLen); - fragData->data = new RawPacket(rawData, rawDataLen, fragmentRawPacket->getPacketTimeStamp(), true, - fragmentRawPacket->getLinkLayerType()); + fragData->data = + new RawPacket(RawPacketBufferPolicy::Copy, BufferInfo(fragmentRawPacket->getRawData(), rawDataLen), + fragmentRawPacket->getPacketTimeStamp(), fragmentRawPacket->getLinkLayerType()); fragData->currentOffset = fragWrapper->getIPLayerPayloadSize(); status = FIRST_FRAGMENT; @@ -514,7 +513,7 @@ namespace pcpp return nullptr; } - Packet* IPReassembly::processPacket(RawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil, + Packet* IPReassembly::processPacket(IRawPacket* fragment, ReassemblyStatus& status, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) { Packet* parsedFragment = new Packet(fragment, false, parseUntil, parseUntilLayer); diff --git a/Packet++/src/Packet.cpp b/Packet++/src/Packet.cpp index c0754a812..5f7483569 100644 --- a/Packet++/src/Packet.cpp +++ b/Packet++/src/Packet.cpp @@ -31,7 +31,7 @@ namespace pcpp gettimeofday(&time, nullptr); uint8_t* data = new uint8_t[maxPacketLen]; memset(data, 0, maxPacketLen); - m_RawPacket = new RawPacket(data, 0, time, true, linkType); + m_RawPacket = new RawPacket(RawPacketBufferPolicy::Move, BufferInfo(data, 0, maxPacketLen), time, linkType); } Packet::Packet(uint8_t* buffer, size_t bufferSize, LinkLayerType linkType) @@ -41,10 +41,11 @@ namespace pcpp timeval time; gettimeofday(&time, nullptr); memset(buffer, 0, bufferSize); - m_RawPacket = new RawPacket(buffer, 0, time, false, linkType); + // Using StrictReference to ensure backwards compatibility with existing code that expects it. + m_RawPacket = new RawPacket(RawPacketBufferPolicy::StrictReference, BufferInfo(buffer, 0, bufferSize), time, linkType); } - void Packet::setRawPacket(RawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, + void Packet::setRawPacket(IRawPacket* rawPacket, bool freeRawPacket, ProtocolTypeFamily parseUntil, OsiModelLayer parseUntilLayer) { destructPacketData(); @@ -113,7 +114,7 @@ namespace pcpp } } - Packet::Packet(RawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) + Packet::Packet(IRawPacket* rawPacket, bool freeRawPacket, ProtocolType parseUntil, OsiModelLayer parseUntilLayer) { m_FreeRawPacket = false; m_RawPacket = nullptr; @@ -121,7 +122,7 @@ namespace pcpp setRawPacket(rawPacket, freeRawPacket, parseUntil, parseUntilLayer); } - Packet::Packet(RawPacket* rawPacket, ProtocolType parseUntil) + Packet::Packet(IRawPacket* rawPacket, ProtocolType parseUntil) { m_FreeRawPacket = false; m_RawPacket = nullptr; @@ -130,7 +131,7 @@ namespace pcpp setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); } - Packet::Packet(RawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) + Packet::Packet(IRawPacket* rawPacket, ProtocolTypeFamily parseUntilFamily) { m_FreeRawPacket = false; m_RawPacket = nullptr; @@ -138,7 +139,7 @@ namespace pcpp setRawPacket(rawPacket, false, parseUntilFamily, OsiModelLayerUnknown); } - Packet::Packet(RawPacket* rawPacket, OsiModelLayer parseUntilLayer) + Packet::Packet(IRawPacket* rawPacket, OsiModelLayer parseUntilLayer) { m_FreeRawPacket = false; m_RawPacket = nullptr; @@ -174,7 +175,7 @@ namespace pcpp void Packet::copyDataFrom(const Packet& other) { - m_RawPacket = new RawPacket(*(other.m_RawPacket)); + m_RawPacket = other.m_RawPacket->clone(); m_FreeRawPacket = true; m_MaxPacketLen = other.m_MaxPacketLen; m_FirstLayer = createFirstLayer(m_RawPacket->getLinkLayerType()); @@ -595,7 +596,7 @@ namespace pcpp // this move operation occurs on already allocated memory, which is backed by the reallocation if's provided // above if offsetInLayer == layer->getHeaderLen() insertData will not move any data but only increase the // packet size by numOfBytesToExtend - m_RawPacket->insertData(indexToInsertData, nullptr, numOfBytesToExtend); + m_RawPacket->insertUninitializedData(indexToInsertData, numOfBytesToExtend); // re-calculate all layers data ptr and data length const uint8_t* dataPtr = m_RawPacket->getRawData(); diff --git a/Packet++/src/RawPacket.cpp b/Packet++/src/RawPacket.cpp index 75e6341ff..a15930d24 100644 --- a/Packet++/src/RawPacket.cpp +++ b/Packet++/src/RawPacket.cpp @@ -17,91 +17,241 @@ namespace pcpp } } // namespace + bool IRawPacket::setPacketTimeStamp(timeval timestamp) + { + return setPacketTimeStamp(toTimespec(timestamp)); + } + + bool IRawPacket::setRawData(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timeval timestamp, + LinkLayerType layerType, int frameLength) + { + return setRawData(bufPolicy, rawDataBuf, toTimespec(timestamp), layerType, frameLength); + } + + RawPacketBase::RawPacketBase(timespec timestamp, LinkLayerType layerType) + : m_TimeStamp(timestamp), m_LinkLayerType(layerType) + {} + + RawPacketBase::RawPacketBase(timeval timestamp, LinkLayerType layerType) + : m_TimeStamp(toTimespec(timestamp)), m_LinkLayerType(layerType) + {} + + bool RawPacketBase::setPacketTimeStamp(timespec timestamp) + { + m_TimeStamp = timestamp; + return true; + } + RawPacket::RawPacket(const uint8_t* pRawData, int rawDataLen, timeval timestamp, bool deleteRawDataAtDestructor, LinkLayerType layerType) - : RawPacket(pRawData, rawDataLen, toTimespec(timestamp), deleteRawDataAtDestructor, layerType) + : RawPacket(deleteRawDataAtDestructor ? RawPacketBufferPolicy::Move : RawPacketBufferPolicy::SoftReference, + BufferInfo(const_cast(pRawData), rawDataLen), timestamp, layerType) {} 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) + : RawPacket(deleteRawDataAtDestructor ? RawPacketBufferPolicy::Move : RawPacketBufferPolicy::SoftReference, + BufferInfo(const_cast(pRawData), rawDataLen), timestamp, layerType) {} - RawPacket::~RawPacket() + RawPacket::RawPacket(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timeval timestamp, + LinkLayerType layerType) + : RawPacket(bufPolicy, rawDataBuf, toTimespec(timestamp), layerType) + {} + + RawPacket::RawPacket(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timespec timestamp, + LinkLayerType layerType) + : RawPacketBase(timestamp, layerType) { - clear(); + switch (bufPolicy) + { + case RawPacketBufferPolicy::Copy: + { + m_RawData = new uint8_t[rawDataBuf.size]; + m_RawDataCapacity = rawDataBuf.size; + m_DeleteRawDataAtDestructor = true; + std::memcpy(m_RawData, rawDataBuf.ptr, rawDataBuf.size); + break; + } + case RawPacketBufferPolicy::Move: + { + m_RawData = rawDataBuf.ptr; + m_RawDataCapacity = rawDataBuf.capacity; + m_DeleteRawDataAtDestructor = true; + break; + } + case RawPacketBufferPolicy::StrictReference: + { + // StrictReference does not allow reallocation, so we set the flag to false + m_ReallocationsAllowed = false; + // fall through + } + case RawPacketBufferPolicy::SoftReference: + { + m_RawData = rawDataBuf.ptr; + m_RawDataCapacity = rawDataBuf.capacity; + m_DeleteRawDataAtDestructor = false; // no deletion of raw data at destructor + break; + } + default: + throw std::invalid_argument("Invalid RawPacketBufferPolicy. Use Copy, Move, or Reference."); + } + + m_RawDataLen = rawDataBuf.size; + m_FrameLength = rawDataBuf.size; } - RawPacket::RawPacket(const RawPacket& other) + RawPacket::RawPacket(IRawPacket const& source) + : RawPacket(RawPacketBufferPolicy::Copy, + BufferInfo(const_cast(source.getRawData()), source.getRawDataLen()), + source.getPacketTimeStamp(), source.getLinkLayerType()) + {} + + RawPacket::~RawPacket() { - m_RawData = nullptr; - copyDataFrom(other, true); + clear(); } - RawPacket& RawPacket::operator=(const RawPacket& other) + RawPacket::RawPacket(const RawPacket& other) : RawPacketBase(other) { - if (this != &other) - { - clear(); + // Reserves memory for the raw data buffer and copies the data from the other packet + // If the other packet has no raw data, it will reserve 0 bytes which is a noop. + if (!reserve(other.m_RawDataLen)) + throw std::runtime_error("Failed to reserve memory for RawPacket"); - copyDataFrom(other, true); + if (other.m_RawData != nullptr) + { + if (appendData(other.m_RawData, other.m_RawDataLen) != static_cast(other.m_RawDataLen)) + throw std::runtime_error("Failed to copy data to RawPacket"); } - return *this; + m_FrameLength = other.m_FrameLength; } - RawPacket* RawPacket::clone() const + RawPacket& RawPacket::operator=(const RawPacket& other) { - return new RawPacket(*this); - } + if (this == &other) + { + return *this; + } - void RawPacket::copyDataFrom(const RawPacket& other, bool allocateData) - { - if (!other.m_RawPacketSet) - return; + // TODO: Potential reuse of existing buffer if it matches the policy and capacity + clear(); - m_TimeStamp = other.m_TimeStamp; + RawPacketBase::operator=(other); - if (allocateData) + if (!reserve(other.m_RawDataLen)) + throw std::runtime_error("Failed to reserve memory for RawPacket"); + + if (other.m_RawData != nullptr) { - m_DeleteRawDataAtDestructor = true; - m_RawData = new uint8_t[other.m_RawDataLen]; - m_RawDataLen = other.m_RawDataLen; + if (appendData(other.m_RawData, other.m_RawDataLen) != static_cast(other.m_RawDataLen)) + throw std::runtime_error("Failed to copy data to RawPacket"); } - memcpy(m_RawData, other.m_RawData, other.m_RawDataLen); - m_LinkLayerType = other.m_LinkLayerType; m_FrameLength = other.m_FrameLength; - m_RawPacketSet = true; + return *this; + } + + RawPacket* RawPacket::clone() const + { + return new RawPacket(*this); } bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timeval timestamp, LinkLayerType layerType, int frameLength) { - return setRawData(pRawData, rawDataLen, toTimespec(timestamp), layerType, frameLength); + // Legacy method for compatibility with older code. The method was used when assigning a raw buffer that is + // externally managed. + // Deprecation due to ambiguity on buffer ownership as it assumes the buffer matches the previous buffer's + // policy. + RawPacketBufferPolicy policy = + m_DeleteRawDataAtDestructor ? RawPacketBufferPolicy::Move : RawPacketBufferPolicy::SoftReference; + return setRawData(policy, BufferInfo(const_cast(pRawData), rawDataLen), timestamp, layerType, + frameLength); } bool RawPacket::setRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType, int frameLength) { + // Legacy method for compatibility with older code. The method was used when assigning a raw buffer that is + // externally managed. + // Deprecation due to ambiguity on buffer ownership as it assumes the buffer matches the previous buffer's + // policy. + RawPacketBufferPolicy policy = + m_DeleteRawDataAtDestructor ? RawPacketBufferPolicy::Move : RawPacketBufferPolicy::SoftReference; + return setRawData(policy, BufferInfo(const_cast(pRawData), rawDataLen), timestamp, layerType, + frameLength); + } + + bool RawPacket::setRawData(RawPacketBufferPolicy bufPolicy, BufferInfo const& rawDataBuf, timespec timestamp, + LinkLayerType layerType, int frameLength) + { + // Early check to maintain previous data if policy is invalid. + switch (bufPolicy) + { + case RawPacketBufferPolicy::Copy: + case RawPacketBufferPolicy::Move: + case RawPacketBufferPolicy::SoftReference: + case RawPacketBufferPolicy::StrictReference: + break; + default: + PCPP_LOG_ERROR("Invalid RawPacketBufferPolicy. Use Copy, Move, or Reference."); + return false; + } + clear(); - m_FrameLength = (frameLength == -1) ? rawDataLen : frameLength; - m_RawData = (uint8_t*)pRawData; - m_RawDataLen = rawDataLen; - m_TimeStamp = timestamp; - m_RawPacketSet = true; - m_LinkLayerType = layerType; + // Set the flag to allow reallocations by default, as this is the most common use case + m_ReallocationsAllowed = true; + + switch (bufPolicy) + { + case RawPacketBufferPolicy::Copy: + { + // TODO: Consider reusing previous allocated buffer if the packet owns it and capacity is enough. + m_RawData = new uint8_t[rawDataBuf.size]; + m_RawDataCapacity = rawDataBuf.size; + m_DeleteRawDataAtDestructor = true; + std::memcpy(m_RawData, rawDataBuf.ptr, rawDataBuf.size); + break; + } + case RawPacketBufferPolicy::Move: + { + m_RawData = rawDataBuf.ptr; + m_RawDataCapacity = rawDataBuf.capacity; + m_DeleteRawDataAtDestructor = true; + break; + } + case RawPacketBufferPolicy::StrictReference: + { + // StrictReference does not allow reallocation, so we set the flag to false + m_ReallocationsAllowed = false; + // fall through + } + case RawPacketBufferPolicy::SoftReference: + { + m_RawData = rawDataBuf.ptr; + m_RawDataCapacity = rawDataBuf.capacity; + m_DeleteRawDataAtDestructor = false; + break; + } + } + + m_RawDataLen = rawDataBuf.size; + m_FrameLength = (frameLength == -1) ? rawDataBuf.size : frameLength; + setPacketTimeStamp(timestamp); + setLinkLayerType(layerType); return true; } bool RawPacket::initWithRawData(const uint8_t* pRawData, int rawDataLen, timespec timestamp, LinkLayerType layerType) { - m_DeleteRawDataAtDestructor = false; - return setRawData(pRawData, rawDataLen, timestamp, layerType); + // Legacy method for compatibility with older code. The method was used when assigning a raw buffer that is + // externally managed. + return setRawData(RawPacketBufferPolicy::SoftReference, BufferInfo(const_cast(pRawData), rawDataLen), + timestamp, layerType); } void RawPacket::clear() @@ -112,54 +262,142 @@ namespace pcpp m_RawData = nullptr; m_RawDataLen = 0; m_FrameLength = 0; - m_RawPacketSet = false; + m_RawDataCapacity = 0; + m_ReallocationsAllowed = true; } - void RawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) + size_t RawPacket::appendData(const uint8_t* dataToAppend, size_t dataToAppendLen) { - memcpy((uint8_t*)m_RawData + m_RawDataLen, dataToAppend, dataToAppendLen); + if (dataToAppend == nullptr || dataToAppendLen == 0) + return 0; + + if (dataToAppendLen + m_RawDataLen > m_RawDataCapacity) + { + if (!m_ReallocationsAllowed) + { + PCPP_LOG_ERROR("Cannot append data to raw packet because reallocation is not allowed"); + return 0; + } + if (!reallocateData(m_RawDataLen + dataToAppendLen)) + { + PCPP_LOG_ERROR("Failed to reallocate raw packet data buffer for appending new data"); + return 0; + } + } + + std::memcpy(m_RawData + m_RawDataLen, dataToAppend, dataToAppendLen); m_RawDataLen += dataToAppendLen; m_FrameLength = m_RawDataLen; + return dataToAppendLen; } - void RawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) + size_t RawPacket::insertData(int atIndex, const uint8_t* dataToInsert, size_t dataToInsertLen) { - // memmove copies data as if there was an intermediate buffer in between - so it allows for copying processes on - // overlapping src/dest ptrs if insertData is called with atIndex == m_RawDataLen, then no data is being moved. - // The data of the raw packet is still extended by dataToInsertLen - memmove((uint8_t*)m_RawData + atIndex + dataToInsertLen, (uint8_t*)m_RawData + atIndex, m_RawDataLen - atIndex); + if (dataToInsert == nullptr) + { + PCPP_LOG_WARN("Using RawPacket::insertData with nullptr data buffer to extend uninitialized buffer. " + "This behaviour has been deprecated and will result errors in the future. " + "Please use insertUninitializedData() instead to insert an uninitialized block of data."); + // Forward the call to insertUninitializedData for the duration of the deprecation period + return insertUninitializedData(atIndex, dataToInsertLen); + } + + if (dataToInsertLen == 0) + return 0; + + // Insert an empty data block at the specified index + if (insertUninitializedData(atIndex, dataToInsertLen) != dataToInsertLen) + { + PCPP_LOG_ERROR("Failed to insert uninitialized data into raw packet"); + return 0; + } + + // Insert the actual data into the raw packet at the specified index + std::memcpy(m_RawData + atIndex, dataToInsert, dataToInsertLen); + return dataToInsertLen; + } + + size_t RawPacket::insertUninitializedData(int atIndex, size_t length) + { + if (length == 0) + return 0; - if (dataToInsert != nullptr) + if (atIndex < 0 || atIndex > m_RawDataLen) { - // insert data - memcpy((uint8_t*)m_RawData + atIndex, dataToInsert, dataToInsertLen); + PCPP_LOG_ERROR("Index to insert uninitialized data is out of raw packet bound"); + return 0; } - m_RawDataLen += dataToInsertLen; + if (length + m_RawDataLen > m_RawDataCapacity) + { + if (!m_ReallocationsAllowed) + { + PCPP_LOG_ERROR("Cannot insert data to raw packet because reallocation is not allowed"); + return 0; + } + if (!reallocateData(length + m_RawDataLen)) + { + PCPP_LOG_ERROR("Failed to reallocate raw packet data buffer for inserting new data"); + return 0; + } + } + + // memmove copies data as if there was an intermediate buffer in between - so it allows for copying processes on + // overlapping src/dest ptrs if insertData is called with atIndex == m_RawDataLen, then no data is being moved. + // The data of the raw packet is still extended by dataToInsertLen + std::memmove(m_RawData + atIndex + length, m_RawData + atIndex, m_RawDataLen - atIndex); + + m_RawDataLen += length; m_FrameLength = m_RawDataLen; + return length; } bool RawPacket::reallocateData(size_t newBufferLength) { - if ((int)newBufferLength == m_RawDataLen) + if (newBufferLength == static_cast(m_RawDataLen)) return true; - if ((int)newBufferLength < m_RawDataLen) + if (newBufferLength < static_cast(m_RawDataLen)) { PCPP_LOG_ERROR("Cannot reallocate raw packet to a smaller size. Current data length: " << m_RawDataLen << "; requested length: " << newBufferLength); return false; } - uint8_t* newBuffer = new uint8_t[newBufferLength]; - memset(newBuffer, 0, newBufferLength); - memcpy(newBuffer, m_RawData, m_RawDataLen); - if (m_DeleteRawDataAtDestructor) + reserve(newBufferLength); + return true; + } + + bool RawPacket::reserve(size_t newCapacity) + { + if (newCapacity <= m_RawDataCapacity) + return true; + + if (!m_ReallocationsAllowed) + { + PCPP_LOG_ERROR("Cannot reserve more space in raw packet because reallocation is not allowed"); + return false; + } + + std::unique_ptr newBuffer = std::make_unique(newCapacity); + + // Copy the existing data to the new buffer if there is any + if (m_RawData != nullptr && m_RawDataLen > 0) + { + std::memcpy(newBuffer.get(), m_RawData, m_RawDataLen); + } + + // Zero out the rest of the new buffer. Is this necessary? + std::memset(newBuffer.get() + m_RawDataLen, 0, newCapacity - m_RawDataLen); + + // Deallocates the old buffer if it was allocated and we own it + if (m_RawData != nullptr && m_DeleteRawDataAtDestructor) delete[] m_RawData; + // Sets the new buffer as the raw data buffer + m_RawData = newBuffer.release(); m_DeleteRawDataAtDestructor = true; - m_RawData = newBuffer; - + m_RawDataCapacity = newCapacity; return true; } @@ -185,18 +423,7 @@ namespace pcpp return true; } - bool RawPacket::setPacketTimeStamp(timeval timestamp) - { - return setPacketTimeStamp(toTimespec(timestamp)); - } - - bool RawPacket::setPacketTimeStamp(timespec timestamp) - { - m_TimeStamp = timestamp; - return true; - } - - bool RawPacket::isLinkTypeValid(int linkTypeValue) + bool IRawPacket::isLinkTypeValid(int linkTypeValue) { if ((linkTypeValue < 0 || linkTypeValue > 264) && linkTypeValue != 276) return false; diff --git a/Pcap++/header/Device.h b/Pcap++/header/Device.h index ac493066e..8e23a1551 100644 --- a/Pcap++/header/Device.h +++ b/Pcap++/header/Device.h @@ -11,7 +11,7 @@ namespace pcpp { /// A vector of pointers to RawPacket - typedef PointerVector RawPacketVector; + typedef PointerVector RawPacketVector; /// @class IDevice /// An abstract interface representing all packet processing devices. It stands as the root class for all devices. diff --git a/Pcap++/header/MBufRawPacket.h b/Pcap++/header/MBufRawPacket.h index dd4a85189..74983e816 100644 --- a/Pcap++/header/MBufRawPacket.h +++ b/Pcap++/header/MBufRawPacket.h @@ -41,7 +41,7 @@ namespace pcpp /// create a linked list of mbufs. This is good for Jumbo packets or other uses. MBufRawPacket doesn't support /// this capability so there is no way to access the mbufs linked to the mbuf wrapped by MBufRawPacket /// instance. I hope I'll be able to add this support in the future - class MBufRawPacket : public RawPacket + class MBufRawPacket : public RawPacketBase { friend class DpdkDevice; #ifdef USE_DPDK_KNI @@ -63,7 +63,7 @@ namespace pcpp /// order to allocate an mbuf the user should call the init() method. Without calling init() the instance of /// this class is not usable. This c'tor can be used for initializing an array of MBufRawPacket (which requires /// an empty c'tor) - MBufRawPacket() : RawPacket(), m_MBuf(nullptr), m_Mempool(nullptr), m_MbufDataSize(0), m_FreeMbuf(true) + MBufRawPacket() : RawPacketBase(), m_MBuf(nullptr), m_Mempool(nullptr), m_MbufDataSize(0), m_FreeMbuf(true) { m_DeleteRawDataAtDestructor = false; } diff --git a/Pcap++/header/PcapDevice.h b/Pcap++/header/PcapDevice.h index b29445041..c5aa87ff6 100644 --- a/Pcap++/header/PcapDevice.h +++ b/Pcap++/header/PcapDevice.h @@ -159,7 +159,7 @@ namespace pcpp /// @param[in] filter A filter class to test against /// @param[in] rawPacket A pointer to the raw packet to match the filter with /// @return True if raw packet matches the filter or false otherwise - static bool matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket); + static bool matchPacketWithFilter(GeneralFilter& filter, IRawPacket* rawPacket); // implement abstract methods diff --git a/Pcap++/header/PcapFileDevice.h b/Pcap++/header/PcapFileDevice.h index 4c4367bcd..0a20e054d 100644 --- a/Pcap++/header/PcapFileDevice.h +++ b/Pcap++/header/PcapFileDevice.h @@ -328,7 +328,7 @@ namespace pcpp virtual ~IFileWriterDevice() {} - virtual bool writePacket(RawPacket const& packet) = 0; + virtual bool writePacket(IRawPacket const& packet) = 0; virtual bool writePackets(const RawPacketVector& packets) = 0; @@ -379,7 +379,7 @@ namespace pcpp /// @return True if a packet was written successfully. False will be returned if the file isn't opened /// or if the packet link layer type is different than the one defined for the file /// (in all cases, an error will be printed to log) - bool writePacket(RawPacket const& packet) override; + bool writePacket(IRawPacket const& packet) override; /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using /// open(). This method won't change the written packets or the RawPacketVector instance @@ -472,7 +472,7 @@ namespace pcpp /// ignored /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error /// will be printed to log) - bool writePacket(RawPacket const& packet, const std::string& comment); + bool writePacket(IRawPacket const& packet, const std::string& comment); // overridden methods @@ -481,7 +481,7 @@ namespace pcpp /// @param[in] packet A reference for an existing RawPcket to write to the file /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error /// will be printed to log) - bool writePacket(RawPacket const& packet) override; + bool writePacket(IRawPacket const& packet) override; /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using /// open(). This method won't change the written packets or the RawPacketVector instance diff --git a/Pcap++/header/PcapFilter.h b/Pcap++/header/PcapFilter.h index e11a54a33..6b70a3104 100644 --- a/Pcap++/header/PcapFilter.h +++ b/Pcap++/header/PcapFilter.h @@ -111,7 +111,7 @@ namespace pcpp /// @param[in] rawPacket A pointer to a raw packet which the filter will be matched against /// @return True if the filter matches (or if it's empty). False if the packet doesn't match or if the filter /// could not be compiled - bool matchPacketWithFilter(const RawPacket* rawPacket); + bool matchPacketWithFilter(const IRawPacket* rawPacket); /// Match a packet data with the filter stored in this object. If the filter is empty the method returns "true". /// If the link type provided is different than the one set in setFilter(), the filter will be re-compiled @@ -144,7 +144,7 @@ namespace pcpp /// Match a raw packet with a given BPF filter. /// @param[in] rawPacket A pointer to the raw packet to match the BPF filter with /// @return True if a raw packet matches the BPF filter or false otherwise - bool matchPacketWithFilter(RawPacket* rawPacket); + bool matchPacketWithFilter(IRawPacket* rawPacket); GeneralFilter() {} diff --git a/Pcap++/header/PcapLiveDevice.h b/Pcap++/header/PcapLiveDevice.h index 14eebb0ca..61c5c3f35 100644 --- a/Pcap++/header/PcapLiveDevice.h +++ b/Pcap++/header/PcapLiveDevice.h @@ -555,7 +555,7 @@ namespace pcpp /// - Packet length is 0 /// - Packet length is larger than device MTU /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - bool sendPacket(RawPacket const& rawPacket, bool checkMtu = false); + bool sendPacket(IRawPacket const& rawPacket, bool checkMtu = false); /// Send a buffer containing packet raw data (including all layers) to the network. /// This particular version of the sendPacket method should only be used if you already have access to the size @@ -604,7 +604,7 @@ namespace pcpp /// - Packet length is 0 /// - Packet length is larger than device MTU and checkMtu is true /// - Packet could not be sent due to some error in libpcap/WinPcap/Npcap - virtual int sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu = false); + virtual int sendPackets(IRawPacket* rawPacketsArr, int arrLength, bool checkMtu = false); /// Send an array of pointers to Packet objects to the network /// @param[in] packetsArr The array of pointers to Packet objects to send. This method treats all packets as diff --git a/Pcap++/header/RawSocketDevice.h b/Pcap++/header/RawSocketDevice.h index 8b69c84d8..fdc690701 100644 --- a/Pcap++/header/RawSocketDevice.h +++ b/Pcap++/header/RawSocketDevice.h @@ -104,7 +104,7 @@ namespace pcpp /// @param[in] rawPacket The packet to send /// @return True if packet was sent successfully or false if the socket is not open, if the packet is not /// Ethernet or if there was a failure sending the packet - bool sendPacket(const RawPacket* rawPacket); + bool sendPacket(const IRawPacket* rawPacket); /// Send a set of Ethernet packets to the network. L2 protocols other than Ethernet are not supported by raw /// sockets. The entire packet is sent as is, including the original Ethernet and IP data. This method is only diff --git a/Pcap++/src/PcapDevice.cpp b/Pcap++/src/PcapDevice.cpp index 91f0ea678..f16805b0f 100644 --- a/Pcap++/src/PcapDevice.cpp +++ b/Pcap++/src/PcapDevice.cpp @@ -150,7 +150,7 @@ namespace pcpp return m_PcapDescriptor.clearFilter(); } - bool IPcapDevice::matchPacketWithFilter(GeneralFilter& filter, RawPacket* rawPacket) + bool IPcapDevice::matchPacketWithFilter(GeneralFilter& filter, IRawPacket* rawPacket) { return filter.matchPacketWithFilter(rawPacket); } diff --git a/Pcap++/src/PcapFileDevice.cpp b/Pcap++/src/PcapFileDevice.cpp index 051d7e78e..43402edca 100644 --- a/Pcap++/src/PcapFileDevice.cpp +++ b/Pcap++/src/PcapFileDevice.cpp @@ -239,8 +239,8 @@ namespace pcpp #else struct timeval ts = pkthdr.ts; #endif - if (!rawPacket.setRawData(pMyPacketData, pkthdr.caplen, ts, static_cast(m_PcapLinkLayerType), - pkthdr.len)) + if (!rawPacket.setRawData(RawPacketBufferPolicy::Move, BufferInfo(pMyPacketData, pkthdr.caplen), ts, + static_cast(m_PcapLinkLayerType), pkthdr.len)) { PCPP_LOG_ERROR("Couldn't set data to raw packet"); return false; @@ -346,7 +346,8 @@ namespace pcpp } timespec ts = { static_cast(be32toh(snoop_packet_header.time_sec)), static_cast(be32toh(snoop_packet_header.time_usec)) * 1000 }; - if (!rawPacket.setRawData((const uint8_t*)packetData.release(), packetSize, ts, + if (!rawPacket.setRawData(RawPacketBufferPolicy::Move, + BufferInfo(reinterpret_cast(packetData.release()), packetSize), ts, static_cast(m_PcapLinkLayerType))) { PCPP_LOG_ERROR("Couldn't set data to raw packet"); @@ -442,8 +443,8 @@ namespace pcpp PCPP_LOG_ERROR("Link layer type of raw packet could not be determined"); } - if (!rawPacket.setRawData(myPacketData, pktHeader.captured_length, pktHeader.timestamp, linkType, - pktHeader.original_length)) + if (!rawPacket.setRawData(RawPacketBufferPolicy::Move, BufferInfo(myPacketData, pktHeader.captured_length), + pktHeader.timestamp, linkType, pktHeader.original_length)) { PCPP_LOG_ERROR("Couldn't set data to raw packet"); return false; @@ -591,7 +592,7 @@ namespace pcpp } } - bool PcapFileWriterDevice::writePacket(RawPacket const& packet) + bool PcapFileWriterDevice::writePacket(IRawPacket const& packet) { if ((!m_AppendMode && m_PcapDescriptor == nullptr) || (m_PcapDumpHandler == nullptr)) { @@ -608,9 +609,9 @@ namespace pcpp } pcap_pkthdr pktHdr; - pktHdr.caplen = ((RawPacket&)packet).getRawDataLen(); - pktHdr.len = ((RawPacket&)packet).getFrameLength(); - timespec packet_timestamp = ((RawPacket&)packet).getPacketTimeStamp(); + pktHdr.caplen = packet.getRawDataLen(); + pktHdr.len = packet.getFrameLength(); + timespec packet_timestamp = packet.getPacketTimeStamp(); #if defined(PCAP_TSTAMP_PRECISION_NANO) if (m_Precision != FileTimestampPrecision::Nanoseconds) { @@ -625,7 +626,7 @@ namespace pcpp TIMESPEC_TO_TIMEVAL(&pktHdr.ts, &packet_timestamp); #endif if (!m_AppendMode) - pcap_dump((uint8_t*)m_PcapDumpHandler, &pktHdr, ((RawPacket&)packet).getRawData()); + pcap_dump((uint8_t*)m_PcapDumpHandler, &pktHdr, packet.getRawData()); else { // Below are actually the lines run by pcap_dump. The reason I had to put them instead pcap_dump is that on @@ -643,7 +644,7 @@ namespace pcpp pktHdrTemp.caplen = pktHdr.caplen; pktHdrTemp.len = pktHdr.len; fwrite(&pktHdrTemp, sizeof(pktHdrTemp), 1, m_File); - fwrite(((RawPacket&)packet).getRawData(), pktHdrTemp.caplen, 1, m_File); + fwrite(packet.getRawData(), pktHdrTemp.caplen, 1, m_File); } PCPP_LOG_DEBUG("Packet written successfully to '" << m_FileName << "'"); m_NumOfPacketsWritten++; @@ -851,7 +852,7 @@ namespace pcpp m_CompressionLevel = compressionLevel; } - bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet, const std::string& comment) + bool PcapNgFileWriterDevice::writePacket(IRawPacket const& packet, const std::string& comment) { if (m_LightPcapNg == nullptr) { @@ -866,14 +867,14 @@ namespace pcpp } light_packet_header pktHeader; - pktHeader.captured_length = ((RawPacket&)packet).getRawDataLen(); - pktHeader.original_length = ((RawPacket&)packet).getFrameLength(); - pktHeader.timestamp = ((RawPacket&)packet).getPacketTimeStamp(); - pktHeader.data_link = (uint16_t)packet.getLinkLayerType(); + pktHeader.captured_length = packet.getRawDataLen(); + pktHeader.original_length = packet.getFrameLength(); + pktHeader.timestamp = packet.getPacketTimeStamp(); + pktHeader.data_link = static_cast(packet.getLinkLayerType()); pktHeader.interface_id = 0; if (!comment.empty()) { - pktHeader.comment = (char*)comment.c_str(); + pktHeader.comment = const_cast(comment.c_str()); pktHeader.comment_length = static_cast(comment.size()); } else @@ -882,14 +883,14 @@ namespace pcpp pktHeader.comment_length = 0; } - const uint8_t* pktData = ((RawPacket&)packet).getRawData(); + const uint8_t* pktData = packet.getRawData(); light_write_packet(toLightPcapNgT(m_LightPcapNg), &pktHeader, pktData); m_NumOfPacketsWritten++; return true; } - bool PcapNgFileWriterDevice::writePacket(RawPacket const& packet) + bool PcapNgFileWriterDevice::writePacket(IRawPacket const& packet) { return writePacket(packet, std::string()); } diff --git a/Pcap++/src/PcapFilter.cpp b/Pcap++/src/PcapFilter.cpp index 65d6973df..c67611c1a 100644 --- a/Pcap++/src/PcapFilter.cpp +++ b/Pcap++/src/PcapFilter.cpp @@ -18,7 +18,7 @@ namespace pcpp static const int DEFAULT_SNAPLEN = 9000; - bool GeneralFilter::matchPacketWithFilter(RawPacket* rawPacket) + bool GeneralFilter::matchPacketWithFilter(IRawPacket* rawPacket) { std::string filterStr; parseToString(filterStr); @@ -91,7 +91,7 @@ namespace pcpp m_FilterStr.clear(); } - bool BpfFilterWrapper::matchPacketWithFilter(const RawPacket* rawPacket) + bool BpfFilterWrapper::matchPacketWithFilter(const IRawPacket* rawPacket) { return matchPacketWithFilter(rawPacket->getRawData(), rawPacket->getRawDataLen(), rawPacket->getPacketTimeStamp(), rawPacket->getLinkLayerType()); diff --git a/Pcap++/src/PcapLiveDevice.cpp b/Pcap++/src/PcapLiveDevice.cpp index 9df29c2b9..fe165102a 100644 --- a/Pcap++/src/PcapLiveDevice.cpp +++ b/Pcap++/src/PcapLiveDevice.cpp @@ -349,7 +349,11 @@ namespace pcpp return; } - RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); + // Stripping const from packet pointer is necessary. It previously stripped it under the hood in constructor, + // but it is more explicit to strip it outside. This is a workaround for the fact that RawPacket constructor + // doesn't accept const uint8_t*. A copy would be safer but it would also be less efficient. + RawPacket rawPacket(RawPacketBufferPolicy::SoftReference, + BufferInfo(const_cast(packet), pkthdr->caplen), pkthdr->ts, pThis->getLinkType()); if (pThis->m_cbOnPacketArrives != nullptr) pThis->m_cbOnPacketArrives(&rawPacket, pThis, pThis->m_cbOnPacketArrivesUserCookie); @@ -367,7 +371,8 @@ namespace pcpp uint8_t* packetData = new uint8_t[pkthdr->caplen]; memcpy(packetData, packet, pkthdr->caplen); - RawPacket* rawPacketPtr = new RawPacket(packetData, pkthdr->caplen, pkthdr->ts, true, pThis->getLinkType()); + RawPacket* rawPacketPtr = new RawPacket(RawPacketBufferPolicy::Move, BufferInfo(packetData, pkthdr->caplen), + pkthdr->ts, pThis->getLinkType()); pThis->m_CapturedPackets->pushBack(rawPacketPtr); } @@ -381,7 +386,9 @@ namespace pcpp return; } - RawPacket rawPacket(packet, pkthdr->caplen, pkthdr->ts, false, pThis->getLinkType()); + // Stripping const from packet pointer. See comment in `onPacketArrives` for details. + RawPacket rawPacket(RawPacketBufferPolicy::SoftReference, + BufferInfo(const_cast(packet), pkthdr->caplen), pkthdr->ts, pThis->getLinkType()); if (pThis->m_cbOnPacketArrivesBlockingMode != nullptr) if (pThis->m_cbOnPacketArrivesBlockingMode(&rawPacket, pThis, @@ -921,7 +928,7 @@ namespace pcpp bool PcapLiveDevice::sendPacket(Packet const& packet, bool checkMtu) { - RawPacket const* rawPacket = packet.getRawPacketReadOnly(); + IRawPacket const* rawPacket = packet.getRawPacketReadOnly(); if (!checkMtu) { @@ -944,14 +951,14 @@ namespace pcpp return doMtuCheck(packetPayloadLength) && sendPacket(*rawPacket, false); } - bool PcapLiveDevice::sendPacket(RawPacket const& rawPacket, bool checkMtu) + bool PcapLiveDevice::sendPacket(IRawPacket const& rawPacket, bool checkMtu) { if (!checkMtu) { return sendPacketDirect(rawPacket.getRawData(), rawPacket.getRawDataLen()); } - RawPacket* rPacket = const_cast(&rawPacket); + IRawPacket* rPacket = const_cast(&rawPacket); Packet parsedPacket = Packet(rPacket, OsiModelDataLinkLayer); return sendPacket(parsedPacket, true); } @@ -971,7 +978,9 @@ namespace pcpp timeval time; gettimeofday(&time, nullptr); - pcpp::RawPacket rawPacket(packetData, packetDataLength, time, false, linkType); + // Stripping constness of packet data pointer. RawPacket should be used in read only. + pcpp::RawPacket rawPacket(RawPacketBufferPolicy::StrictReference, + BufferInfo(const_cast(packetData), packetDataLength), time, linkType); Packet parsedPacket = Packet(&rawPacket, pcpp::OsiModelDataLinkLayer); return sendPacket(parsedPacket, true); } @@ -1019,10 +1028,10 @@ namespace pcpp } } // namespace - int PcapLiveDevice::sendPackets(RawPacket* rawPacketsArr, int arrLength, bool checkMtu) + int PcapLiveDevice::sendPackets(IRawPacket* rawPacketsArr, int arrLength, bool checkMtu) { return sendPacketsLoop(rawPacketsArr, rawPacketsArr + arrLength, - [this, checkMtu](RawPacket const& packet) { return sendPacket(packet, checkMtu); }); + [this, checkMtu](IRawPacket const& packet) { return sendPacket(packet, checkMtu); }); } int PcapLiveDevice::sendPackets(Packet** packetsArr, int arrLength, bool checkMtu) @@ -1034,7 +1043,7 @@ namespace pcpp int PcapLiveDevice::sendPackets(const RawPacketVector& rawPackets, bool checkMtu) { return sendPacketsLoop(rawPackets.begin(), rawPackets.end(), - [this, checkMtu](RawPacket const* packet) { return sendPacket(*packet, checkMtu); }); + [this, checkMtu](IRawPacket const* packet) { return sendPacket(*packet, checkMtu); }); } void PcapLiveDevice::setDeviceMtu() diff --git a/Pcap++/src/PfRingDevice.cpp b/Pcap++/src/PfRingDevice.cpp index 540a2c0ae..1f7677031 100644 --- a/Pcap++/src/PfRingDevice.cpp +++ b/Pcap++/src/PfRingDevice.cpp @@ -667,7 +667,7 @@ namespace pcpp // continue; // } - RawPacket rawPacket(bufferPtr, pktHdr.caplen, pktHdr.ts, false); + RawPacket rawPacket(RawPacketBufferPolicy::StrictReference, BufferInfo(bufferPtr, pktHdr.caplen), pktHdr.ts); this->m_OnPacketsArriveCallback(&rawPacket, 1, coreId, this, this->m_OnPacketsArriveUserCookie); } else if (recvRes < 0) diff --git a/Pcap++/src/RawSocketDevice.cpp b/Pcap++/src/RawSocketDevice.cpp index 956d3460e..a41ccc8d9 100644 --- a/Pcap++/src/RawSocketDevice.cpp +++ b/Pcap++/src/RawSocketDevice.cpp @@ -136,7 +136,8 @@ namespace pcpp { timeval time; gettimeofday(&time, nullptr); - rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_DLT_RAW1); + rawPacket.setRawData(RawPacketBufferPolicy::Move, BufferInfo(reinterpret_cast(buffer), bufferLen), + time, LINKTYPE_DLT_RAW1); return RecvSuccess; } @@ -199,7 +200,8 @@ namespace pcpp { timeval time; gettimeofday(&time, nullptr); - rawPacket.setRawData((const uint8_t*)buffer, bufferLen, time, LINKTYPE_ETHERNET); + rawPacket.setRawData(RawPacketBufferPolicy::Move, BufferInfo(reinterpret_cast(buffer), bufferLen), time, + LINKTYPE_ETHERNET); return RecvSuccess; } @@ -257,7 +259,7 @@ namespace pcpp return packetCount; } - bool RawSocketDevice::sendPacket(const RawPacket* rawPacket) + bool RawSocketDevice::sendPacket(const IRawPacket* rawPacket) { #if defined(_WIN32) diff --git a/Tests/Packet++Test/Tests/BgpTests.cpp b/Tests/Packet++Test/Tests/BgpTests.cpp index ae047337a..de5629af8 100644 --- a/Tests/Packet++Test/Tests/BgpTests.cpp +++ b/Tests/Packet++Test/Tests/BgpTests.cpp @@ -454,7 +454,8 @@ PTF_TEST_CASE(BgpLayerEditTest) PTF_ASSERT_BUF_COMPARE(bgpNotificationMessage1->getData(), bgpNotificationMessage2->getData(), bgpNotificationMessage2->getDataLen()); - pcpp::RawPacket rawPacket1Tag(origBuffer, bufferLength1, time, false); + pcpp::RawPacket rawPacket1Tag(pcpp::RawPacketBufferPolicy::SoftReference, + pcpp::BufferInfo(origBuffer, bufferLength1), time); bgpNotificationPacket1.setRawPacket(&rawPacket1Tag, false); bgpNotificationMessage1 = bgpNotificationPacket1.getLayerOfType(); std::string notificationData = diff --git a/Tests/Packet++Test/Tests/CiscoHdlcTests.cpp b/Tests/Packet++Test/Tests/CiscoHdlcTests.cpp index 805061b76..84b4c56f5 100644 --- a/Tests/Packet++Test/Tests/CiscoHdlcTests.cpp +++ b/Tests/Packet++Test/Tests/CiscoHdlcTests.cpp @@ -57,7 +57,8 @@ PTF_TEST_CASE(CiscoHdlcParsingTest) // Malformed Cisco HDLC + IPv4 { auto data = std::vector{ 0x0f, 0x00, 0x08, 0x00, 0x45, 0xc0 }; - auto rawPacket = pcpp::RawPacket(data.data(), data.size(), time, false, pcpp::LINKTYPE_C_HDLC); + auto rawPacket = pcpp::RawPacket(pcpp::RawPacketBufferPolicy::StrictReference, + pcpp::BufferInfo(data.data(), data.size()), time, pcpp::LINKTYPE_C_HDLC); const pcpp::Packet ciscoHdlcPacket(&rawPacket); diff --git a/Tests/Packet++Test/Tests/EthAndArpTests.cpp b/Tests/Packet++Test/Tests/EthAndArpTests.cpp index 5628c6369..8df043300 100644 --- a/Tests/Packet++Test/Tests/EthAndArpTests.cpp +++ b/Tests/Packet++Test/Tests/EthAndArpTests.cpp @@ -47,7 +47,7 @@ PTF_TEST_CASE(EthPacketCreation) PTF_ASSERT_EQUAL(ethPacket.getLayerOfType()->getSourceMac(), srcMac); PTF_ASSERT_EQUAL(ethPacket.getLayerOfType()->getEthHeader()->etherType, be16toh(PCPP_ETHERTYPE_IP)); - pcpp::RawPacket* rawPacket = ethPacket.getRawPacket(); + pcpp::IRawPacket* rawPacket = ethPacket.getRawPacket(); PTF_ASSERT_NOT_NULL(rawPacket); PTF_ASSERT_EQUAL(rawPacket->getRawDataLen(), 18); @@ -77,7 +77,7 @@ PTF_TEST_CASE(EthPacketPointerCreation) PTF_ASSERT_EQUAL(ethPacket->getLayerOfType()->getEthHeader()->etherType, be16toh(PCPP_ETHERTYPE_IP)); - pcpp::RawPacket* rawPacket = ethPacket->getRawPacket(); + pcpp::IRawPacket* rawPacket = ethPacket->getRawPacket(); PTF_ASSERT_NOT_NULL(rawPacket); PTF_ASSERT_EQUAL(rawPacket->getRawDataLen(), 18); diff --git a/Tests/Packet++Test/Tests/IPv4Tests.cpp b/Tests/Packet++Test/Tests/IPv4Tests.cpp index 3dbe99c4a..7b3e31ab4 100644 --- a/Tests/Packet++Test/Tests/IPv4Tests.cpp +++ b/Tests/Packet++Test/Tests/IPv4Tests.cpp @@ -34,7 +34,7 @@ PTF_TEST_CASE(IPv4PacketCreation) PTF_ASSERT_FALSE(tmpPacket.addLayer(ðLayer)); pcpp::Logger::getInstance().enableLogs(); - pcpp::RawPacket* rawPacket = ip4Packet.getRawPacket(); + pcpp::IRawPacket* rawPacket = ip4Packet.getRawPacket(); PTF_ASSERT_NOT_NULL(rawPacket); PTF_ASSERT_EQUAL(rawPacket->getRawDataLen(), 14); diff --git a/Tests/Packet++Test/Utils/TestUtils.h b/Tests/Packet++Test/Utils/TestUtils.h index 89c269111..e14a30f8d 100644 --- a/Tests/Packet++Test/Utils/TestUtils.h +++ b/Tests/Packet++Test/Utils/TestUtils.h @@ -34,11 +34,14 @@ namespace pcpp_tests #define READ_FILE_AND_CREATE_PACKET(num, filename) \ READ_FILE_INTO_BUFFER(num, filename); \ - pcpp::RawPacket rawPacket##num(static_cast(buffer##num), bufferLength##num, time, true) + pcpp::RawPacket rawPacket##num(pcpp::RawPacketBufferPolicy::Move, \ + pcpp::BufferInfo(static_cast(buffer##num), bufferLength##num), time) #define READ_FILE_AND_CREATE_PACKET_LINKTYPE(num, filename, linktype) \ READ_FILE_INTO_BUFFER(num, filename); \ - pcpp::RawPacket rawPacket##num(static_cast(buffer##num), bufferLength##num, time, true, linktype) + pcpp::RawPacket rawPacket##num(pcpp::RawPacketBufferPolicy::Move, \ + pcpp::BufferInfo(static_cast(buffer##num), bufferLength##num), time, \ + linktype) #ifdef PCPP_TESTS_DEBUG void savePacketToPcap(pcpp::Packet& packet, const std::string& fileName); diff --git a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp index ee3b961f2..b7952c93e 100644 --- a/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp +++ b/Tests/Pcap++Test/Tests/LiveDeviceTests.cpp @@ -892,8 +892,8 @@ PTF_TEST_CASE(TestMtuSize) PTF_ASSERT_EQUAL(smallPacket.getLayerOfType()->getDataLen(), (size_t)liveDev->getMtu(), ptr); // Try sending the packet PTF_ASSERT_TRUE(liveDev->sendPacket(smallPacket)); - pcpp::RawPacket* rawSmallPacketPtr = smallPacket.getRawPacket(); - pcpp::RawPacket& rawSmallPacketRef = *rawSmallPacketPtr; + pcpp::IRawPacket* rawSmallPacketPtr = smallPacket.getRawPacket(); + pcpp::IRawPacket& rawSmallPacketRef = *rawSmallPacketPtr; PTF_ASSERT_TRUE(liveDev->sendPacket(rawSmallPacketRef, true)); PTF_ASSERT_TRUE(liveDev->sendPacket(rawSmallPacketPtr->getRawData(), rawSmallPacketPtr->getRawDataLen(), true, pcpp::LINKTYPE_ETHERNET)); @@ -926,8 +926,8 @@ PTF_TEST_CASE(TestMtuSize) pcpp::Logger::getInstance().suppressLogs(); PTF_ASSERT_FALSE(liveDev->sendPacket(largePacket)); - pcpp::RawPacket* rawLargePacketPtr = largePacket.getRawPacket(); - pcpp::RawPacket& rawLargePacketRef = *rawLargePacketPtr; + pcpp::IRawPacket* rawLargePacketPtr = largePacket.getRawPacket(); + pcpp::IRawPacket& rawLargePacketRef = *rawLargePacketPtr; PTF_ASSERT_FALSE(liveDev->sendPacket(rawLargePacketRef, true)); PTF_ASSERT_FALSE(liveDev->sendPacket(rawLargePacketPtr->getRawData(), rawLargePacketPtr->getRawDataLen(), true, pcpp::LINKTYPE_ETHERNET)); @@ -999,7 +999,7 @@ PTF_TEST_CASE(TestRemoteCapture) // send multiple packets pcpp::RawPacketVector packetsToSend; - std::vector::iterator iter = capturedPackets.begin(); + auto iter = capturedPackets.begin(); size_t capturedPacketsSize = capturedPackets.size(); while (iter != capturedPackets.end()) diff --git a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp index 9b65d9f6a..7860eeb54 100644 --- a/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp +++ b/Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "EndianPortable.h" #include "SystemUtils.h" #include "TcpReassembly.h" @@ -227,14 +228,14 @@ static void tcpReassemblyConnectionEndCallback(const pcpp::ConnectionData& conne static bool tcpReassemblyTest(const std::vector& packetStream, TcpReassemblyMultipleConnStats& results, bool monitorOpenCloseConns, bool closeConnsManually) { - pcpp::TcpReassembly* tcpReassembly = nullptr; + std::unique_ptr tcpReassembly = nullptr; if (monitorOpenCloseConns) tcpReassembly = - new pcpp::TcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, + std::make_unique(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback, tcpReassemblyConnectionEndCallback); else - tcpReassembly = new pcpp::TcpReassembly(tcpReassemblyMsgReadyCallback, &results); + tcpReassembly = std::make_unique(tcpReassemblyMsgReadyCallback, &results); for (auto iter : packetStream) { @@ -259,8 +260,6 @@ static bool tcpReassemblyTest(const std::vector& packetStream, if (closeConnsManually) tcpReassembly->closeAllConnections(); - delete tcpReassembly; - return true; } @@ -310,16 +309,17 @@ static pcpp::RawPacket tcpReassemblyAddRetransmissions(pcpp::RawPacket rawPacket if (numOfBytes <= 0) numOfBytes = tcpPayloadSize - beginning; - uint8_t* newPayload = new uint8_t[numOfBytes]; + + auto newPayload = std::make_unique(numOfBytes); if (beginning + numOfBytes <= tcpPayloadSize) { - memcpy(newPayload, tcpLayer->getLayerPayload() + beginning, numOfBytes); + memcpy(newPayload.get(), tcpLayer->getLayerPayload() + beginning, numOfBytes); } else { int bytesToCopy = tcpPayloadSize - beginning; - memcpy(newPayload, tcpLayer->getLayerPayload() + beginning, bytesToCopy); + memcpy(newPayload.get(), tcpLayer->getLayerPayload() + beginning, bytesToCopy); for (int i = bytesToCopy; i < numOfBytes; i++) { newPayload[i] = '*'; @@ -332,14 +332,13 @@ static pcpp::RawPacket tcpReassemblyAddRetransmissions(pcpp::RawPacket rawPacket tcpLayer->getTcpHeader()->sequenceNumber = htobe32(be32toh(tcpLayer->getTcpHeader()->sequenceNumber) + beginning); - pcpp::PayloadLayer newPayloadLayer(newPayload, numOfBytes); + pcpp::PayloadLayer newPayloadLayer(newPayload.get(), numOfBytes); packet.addLayer(&newPayloadLayer); packet.computeCalculateFields(); - delete[] newPayload; - - return *(packet.getRawPacket()); + // Static downcast to RawPacket because we know that the packet is a RawPacket + return *static_cast(packet.getRawPacket()); } // ~~~~~~~~~~~~~~~~~~~~~