#ifndef PCAPPP_FILE_DEVICE #define PCAPPP_FILE_DEVICE #include "PcapDevice.h" #include "RawPacket.h" #include // forward declaration for structs and typedefs defined in pcap.h struct pcap_dumper; typedef struct pcap_dumper pcap_dumper_t; /// @file /** * \namespace pcpp * \brief The main namespace for the PcapPlusPlus lib */ namespace pcpp { /** * @class IFileDevice * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices */ class IFileDevice : public IPcapDevice { protected: std::string m_FileName; explicit IFileDevice(const std::string& fileName); virtual ~IFileDevice(); public: /** * @return The name of the file */ std::string getFileName() const; //override methods /** * Close the file */ virtual void close(); }; /** * @class IFileReaderDevice * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader devices */ class IFileReaderDevice : public IFileDevice { protected: uint32_t m_NumOfPacketsRead; uint32_t m_NumOfPacketsNotParsed; /** * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file * isn't opened yet, so reading packets will fail. For opening the file call open() * @param[in] fileName The full path of the file to read */ IFileReaderDevice(const std::string& fileName); public: /** * A destructor for this class */ virtual ~IFileReaderDevice() {} /** * @return The file size in bytes */ uint64_t getFileSize() const; virtual bool getNextPacket(RawPacket& rawPacket) = 0; /** * Read the next N packets into a raw packet vector * @param[out] packetVec The raw packet vector to read packets into * @param[in] numOfPacketsToRead Number of packets to read. If value <0 all remaining packets in the file will be read into the * raw packet vector (this is the default value) * @return The number of packets actually read */ int getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead = -1); /** * A static method that creates an instance of the reader best fit to read the file. It decides by the file extension: for .pcapng * files it returns an instance of PcapNgFileReaderDevice and for all other extensions it returns an instance of PcapFileReaderDevice * @param[in] fileName The file name to open * @return An instance of the reader to read the file. Notice you should free this instance when done using it */ static IFileReaderDevice* getReader(const std::string& fileName); }; /** * @class PcapFileReaderDevice * A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets, packet-by-packet */ class PcapFileReaderDevice : public IFileReaderDevice { private: LinkLayerType m_PcapLinkLayerType; // private copy c'tor PcapFileReaderDevice(const PcapFileReaderDevice& other); PcapFileReaderDevice& operator=(const PcapFileReaderDevice& other); public: /** * A constructor for this class that gets the pcap full path file name to open. Notice that after calling this constructor the file * isn't opened yet, so reading packets will fail. For opening the file call open() * @param[in] fileName The full path of the file to read */ PcapFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {} /** * A destructor for this class */ virtual ~PcapFileReaderDevice() {} /** * @return The link layer type of this file */ LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; } //overridden methods /** * Read the next packet from the file. Before using this method please verify the file is opened using open() * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed) * or if reached end-of-file */ bool getNextPacket(RawPacket& rawPacket); /** * Open the file name which path was specified in the constructor in a read-only mode * @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example: * file path does not exist) */ bool open(); /** * Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The rest of the members will contain 0 * @param[out] stats The stats struct where stats are returned */ void getStatistics(PcapStats& stats) const; }; /** * @class SnoopFileReaderDevice * A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets, packet-by-packet */ class SnoopFileReaderDevice : public IFileReaderDevice { private: #pragma pack(1) /* * File format header. */ typedef struct { uint64_t identification_pattern; uint32_t version_number; uint32_t datalink_type; } snoop_file_header_t; /* * Packet record header. */ typedef struct { uint32_t original_length; /* original packet length */ uint32_t included_length; /* saved packet length */ uint32_t packet_record_length;/* total record length */ uint32_t ndrops_cumulative; /* cumulative drops */ uint32_t time_sec; /* timestamp */ uint32_t time_usec; /* microsecond timestamp */ } snoop_packet_header_t; #pragma pack() LinkLayerType m_PcapLinkLayerType; std::ifstream m_snoopFile; // private copy c'tor SnoopFileReaderDevice(const PcapFileReaderDevice& other); SnoopFileReaderDevice& operator=(const PcapFileReaderDevice& other); public: /** * A constructor for this class that gets the snoop full path file name to open. Notice that after calling this constructor the file * isn't opened yet, so reading packets will fail. For opening the file call open() * @param[in] fileName The full path of the file to read */ SnoopFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET) {} /** * A destructor for this class */ virtual ~SnoopFileReaderDevice(); /** * @return The link layer type of this file */ LinkLayerType getLinkLayerType() const { return m_PcapLinkLayerType; } //overridden methods /** * Read the next packet from the file. Before using this method please verify the file is opened using open() * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed) * or if reached end-of-file */ bool getNextPacket(RawPacket& rawPacket); /** * Open the file name which path was specified in the constructor in a read-only mode * @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example: * file path does not exist) */ bool open(); /** * Get statistics of packets read so far. In the PcapStats struct, only the packetsRecv member is relevant. The rest of the members will contain 0 * @param[out] stats The stats struct where stats are returned */ void getStatistics(PcapStats& stats) const; /** * Close the snoop file */ void close(); }; /** * @class PcapNgFileReaderDevice * A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets, packet-by-packet */ class PcapNgFileReaderDevice : public IFileReaderDevice { private: void* m_LightPcapNg; BpfFilterWrapper m_BpfWrapper; // private copy c'tor PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other); PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other); public: /** * A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling this constructor the file * isn't opened yet, so reading packets will fail. For opening the file call open() * @param[in] fileName The full path of the file to read */ PcapNgFileReaderDevice(const std::string& fileName); /** * A destructor for this class */ virtual ~PcapNgFileReaderDevice() { close(); } /** * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the * operating system that was used for capturing the packets. This method reads this string from the metadata (if exists) and * returns it * @return The operating system string if exists, or an empty string otherwise */ std::string getOS() const; /** * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the * hardware that was used for capturing the packets. This method reads this string from the metadata (if exists) and * returns it * @return The hardware string if exists, or an empty string otherwise */ std::string getHardware() const; /** * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string specifying the * capture application that was used for capturing the packets. This method reads this string from the metadata (if exists) and * returns it * @return The capture application string if exists, or an empty string otherwise */ std::string getCaptureApplication() const; /** * The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string containing a user-defined * comment (can be any string). This method reads this string from the metadata (if exists) and * returns it * @return The comment written inside the file if exists, or an empty string otherwise */ std::string getCaptureFileComment() const; /** * The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file). This method reads * the next packet and the comment attached to it (if such comment exists), and returns them both * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written * @param[out] packetComment The comment attached to the packet or an empty string if no comment exists * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed) * or if reached end-of-file */ bool getNextPacket(RawPacket& rawPacket, std::string& packetComment); //overridden methods /** * Read the next packet from the file. Before using this method please verify the file is opened using open() * @param[out] rawPacket A reference for an empty RawPacket where the packet will be written * @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an error log will be printed) * or if reached end-of-file */ bool getNextPacket(RawPacket& rawPacket); /** * Open the file name which path was specified in the constructor in a read-only mode * @return True if file was opened successfully or if file is already opened. False if opening the file failed for some reason (for example: * file path does not exist) */ bool open(); /** * Get statistics of packets read so far. * @param[out] stats The stats struct where stats are returned */ void getStatistics(PcapStats& stats) const; /** * Set a filter for PcapNG reader device. Only packets that match the filter will be received * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html) * @return True if filter set successfully, false otherwise */ bool setFilter(std::string filterAsString); /** * Close the pacp-ng file */ void close(); }; /** * @class IFileWriterDevice * An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer devices */ class IFileWriterDevice : public IFileDevice { protected: uint32_t m_NumOfPacketsWritten; uint32_t m_NumOfPacketsNotWritten; IFileWriterDevice(const std::string& fileName); public: /** * A destructor for this class */ virtual ~IFileWriterDevice() {} virtual bool writePacket(RawPacket const& packet) = 0; virtual bool writePackets(const RawPacketVector& packets) = 0; using IFileDevice::open; virtual bool open(bool appendMode) = 0; }; /** * @class PcapFileWriterDevice * A class for opening a pcap file for writing or create a new pcap file and write packets to it. This class adds * a unique capability that isn't supported in WinPcap and in older libpcap versions which is to open a pcap file * in append mode where packets are written at the end of the pcap file instead of running it over */ class PcapFileWriterDevice : public IFileWriterDevice { private: pcap_dumper_t* m_PcapDumpHandler; LinkLayerType m_PcapLinkLayerType; bool m_AppendMode; FILE* m_File; // private copy c'tor PcapFileWriterDevice(const PcapFileWriterDevice& other); PcapFileWriterDevice& operator=(const PcapFileWriterDevice& other); void closeFile(); public: /** * A constructor for this class that gets the pcap full path file name to open for writing or create. Notice that after calling this * constructor the file isn't opened yet, so writing packets will fail. For opening the file call open() * @param[in] fileName The full path of the file * @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is Ethernet */ PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET); /** * A destructor for this class */ ~PcapFileWriterDevice() {} /** * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the * written packet * @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 * 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); /** * 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 * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file * @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error * log will be printed) or if at least one of the packets wasn't written successfully to the file */ bool writePackets(const RawPacketVector& packets); //override methods /** * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be * overwritten, meaning all its current content will be deleted * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason * (an error will be printed to log) */ virtual bool open(); /** * Same as open(), but enables to open the file in append mode in which packets will be appended to the file * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false * this method will act exactly like open(). If set to true, file will be opened in append mode * @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned * if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in c'tor is * different from current file link type. In case appendMode is set to false, please refer to open() for return * values */ bool open(bool appendMode); /** * Flush and close the pacp file */ virtual void close(); /** * Flush packets to disk. */ void flush(); /** * Get statistics of packets written so far. * @param[out] stats The stats struct where stats are returned */ virtual void getStatistics(PcapStats& stats) const; }; /** * @class PcapNgFileWriterDevice * A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This class adds * unique capabilities such as writing metadata attributes into the file header, adding comments per packet and opening * the file in append mode where packets are added to a file instead of overriding it. This capabilities are part of the * pcap-ng standard but aren't supported in most tools and libraries */ class PcapNgFileWriterDevice : public IFileWriterDevice { private: void* m_LightPcapNg; int m_CompressionLevel; BpfFilterWrapper m_BpfWrapper; // private copy c'tor PcapNgFileWriterDevice(const PcapFileWriterDevice& other); PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other); public: /** * A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice that after calling this * constructor the file isn't opened yet, so writing packets will fail. For opening the file call open() * @param[in] fileName The full path of the file * @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression or 10 for max compression. Default is 0 */ PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel = 0); /** * A destructor for this class */ virtual ~PcapNgFileWriterDevice() { close(); } /** * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be * overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows writing several * metadata attributes that will be stored in the header of the file * @param[in] os A string describing the operating system that was used to capture the packets. If this string is empty or null it * will be ignored * @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is empty or null it * will be ignored * @param[in] captureApp A string describing the application that was used to capture the packets. If this string is empty or null it * will be ignored * @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the file. * If this string is empty or null it will be ignored * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason * (an error will be printed to log) */ bool open(const std::string& os, const std::string& hardware, const std::string& captureApp, const std::string& fileComment); /** * The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a RawPacket to the file and * adds a comment to it. Before using this method please verify the file is opened using open(). This method won't change the * written packet or the input comment * @param[in] packet A reference for an existing RawPcket to write to the file * @param[in] comment The comment to be written for the packet. If this string is empty or null it will be 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); //overridden methods /** * Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This method won't change the * written packet * @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); /** * 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 * @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the file * @return True if all packets were written successfully to the file. False will be returned if the file isn't opened (also, an error * log will be printed) or if at least one of the packets wasn't written successfully to the file */ bool writePackets(const RawPacketVector& packets); /** * Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be * overwritten, meaning all its current content will be deleted * @return True if file was opened/created successfully or if file is already opened. False if opening the file failed for some reason * (an error will be printed to log) */ bool open(); /** * Same as open(), but enables to open the file in append mode in which packets will be appended to the file * instead of overwrite its current content. In append mode file must exist, otherwise opening will fail * @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false * this method will act exactly like open(). If set to true, file will be opened in append mode * @return True of managed to open the file successfully. In case appendMode is set to true, false will be returned * if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to false, please refer to open() * for return values */ bool open(bool appendMode); /** * Flush packets to the pcap-ng file */ void flush(); /** * Flush and close the pcap-ng file */ void close(); /** * Get statistics of packets written so far. * @param[out] stats The stats struct where stats are returned */ void getStatistics(PcapStats& stats) const; /** * Set a filter for PcapNG writer device. Only packets that match the filter will be persisted * @param[in] filterAsString The filter to be set in Berkeley Packet Filter (BPF) syntax (http://biot.com/capstats/bpf.html) * @return True if filter set successfully, false otherwise */ bool setFilter(std::string filterAsString); }; }// namespace pcpp #endif