libraries/pcappp/include/pcapplusplus/PcapFileDevice.h

596 lines
23 KiB
C++

#ifndef PCAPPP_FILE_DEVICE
#define PCAPPP_FILE_DEVICE
#include "PcapDevice.h"
#include "RawPacket.h"
#include <fstream>
// 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;
IFileDevice(const std::string& fileName);
virtual ~IFileDevice();
public:
/**
* @return The name of the file
*/
std::string getFileName() const;
//override methods
/**
* Close the file
* @return No return value
*/
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(0)
/*
* 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