Coverage Report

Created: 2026-02-14 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Pcap++/header/PcapFileDevice.h
Line
Count
Source
1
#pragma once
2
3
#include "Device.h"
4
#include "PcapDevice.h"
5
#include "RawPacket.h"
6
#include <fstream>
7
8
/// @file
9
10
/// @namespace pcpp
11
/// @brief The main namespace for the PcapPlusPlus lib
12
namespace pcpp
13
{
14
  namespace internal
15
  {
16
    /// @struct LightPcapNgHandle
17
    /// An opaque struct representing a handle for pcapng files.
18
    struct LightPcapNgHandle;
19
  }  // namespace internal
20
21
  /// @enum FileTimestampPrecision
22
  /// An enumeration representing the precision of timestamps in a pcap file.
23
  /// The precision can be Unknown, Micro, or Nano.
24
  enum class FileTimestampPrecision : int8_t
25
  {
26
    /// Precision is unknown or not set/determined
27
    Unknown = -1,
28
    /// Precision is in microseconds.
29
    Microseconds = 0,
30
    /// Precision is in nanoseconds.
31
    Nanoseconds = 1
32
  };
33
34
  /// @class IFileDevice
35
  /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for all file devices
36
  class IFileDevice : public IFilterableDevice, public IPcapStatisticsProvider
37
  {
38
  protected:
39
    std::string m_FileName;
40
    BpfFilterWrapper m_BpfWrapper;
41
42
    explicit IFileDevice(const std::string& fileName);
43
44
    bool doUpdateFilter(std::string const* filterAsString) override;
45
46
  public:
47
    /// @return The name of the file
48
    std::string getFileName() const;
49
50
    // override methods
51
52
    /// @brief Get the statistics for this device.
53
    ///
54
    /// The PcapStats structure will hold the following:
55
    /// - packetsRecv: Number of packets processed (read or written, depending on the device type)
56
    /// - packetsDrop: Number of packets dropped (not read or not written, depending on the device type)
57
    /// - packetsDropByInterface: Not supported for file devices, will always be 0
58
    ///
59
    /// @param[out] stats The stats object to fill in.
60
    void getStatistics(PcapStats& stats) const override;
61
62
  protected:
63
    /// @brief Report that packets were processed (read or written, depending on the device type).
64
    /// @param numPackets The number of packets processed. Default is 1.
65
    void reportPacketProcessed(uint64_t numPackets = 1)
66
7.43k
    {
67
7.43k
      m_NumOfPacketsProcessed += numPackets;
68
7.43k
    }
69
70
    /// @brief Report that packets were dropped (not read or not written, depending on the device type).
71
    /// @param numPackets The number of packets dropped. Default is 1.
72
    void reportPacketDropped(uint64_t numPackets = 1)
73
0
    {
74
0
      m_NumOfPacketsDropped += numPackets;
75
0
    }
76
77
    /// @brief Reset the internal statistic counters to zero.
78
    void resetStatisticCounters();
79
80
  private:
81
    uint64_t m_NumOfPacketsProcessed = 0;
82
    uint64_t m_NumOfPacketsDropped = 0;
83
  };
84
85
  /// @class IFileReaderDevice
86
  /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file reader
87
  /// devices
88
  class IFileReaderDevice : public IFileDevice
89
  {
90
  protected:
91
    /// A constructor for this class that gets the pcap full path file name to open. Notice that after calling this
92
    /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
93
    /// @param[in] fileName The full path of the file to read
94
    IFileReaderDevice(const std::string& fileName);
95
96
  public:
97
    /// A destructor for this class
98
    ~IFileReaderDevice() override = default;
99
100
    /// @return The file size in bytes
101
    uint64_t getFileSize() const;
102
103
    virtual bool getNextPacket(RawPacket& rawPacket) = 0;
104
105
    /// Read the next N packets into a raw packet vector
106
    /// @param[out] packetVec The raw packet vector to read packets into
107
    /// @param[in] numOfPacketsToRead Number of packets to read. If value <0 all remaining packets in the file will
108
    /// be read into the raw packet vector (this is the default value)
109
    /// @return The number of packets actually read
110
    int getNextPackets(RawPacketVector& packetVec, int numOfPacketsToRead = -1);
111
112
    /// A static method that creates an instance of the reader best fit to read the file. It decides by the file
113
    /// extension: for .pcapng files it returns an instance of PcapNgFileReaderDevice and for all other extensions
114
    /// it returns an instance of PcapFileReaderDevice
115
    /// @param[in] fileName The file name to open
116
    /// @return An instance of the reader to read the file. Notice you should free this instance when done using it
117
    static IFileReaderDevice* getReader(const std::string& fileName);
118
  };
119
120
  /// @class IFileWriterDevice
121
  /// An abstract class (cannot be instantiated, has a private c'tor) which is the parent class for file writer
122
  /// devices
123
  class IFileWriterDevice : public IFileDevice
124
  {
125
  protected:
126
    IFileWriterDevice(const std::string& fileName);
127
128
  public:
129
    /// A destructor for this class
130
    ~IFileWriterDevice() override = default;
131
132
    virtual bool writePacket(RawPacket const& packet) = 0;
133
134
    virtual bool writePackets(const RawPacketVector& packets) = 0;
135
136
    using IFileDevice::open;
137
    virtual bool open(bool appendMode) = 0;
138
  };
139
140
  /// @class PcapFileReaderDevice
141
  /// A class for opening a pcap file in read-only mode. This class enable to open the file and read all packets,
142
  /// packet-by-packet
143
  class PcapFileReaderDevice : public IFileReaderDevice
144
  {
145
  public:
146
    /// A constructor for this class that gets the pcap full path file name to open. Notice that after calling this
147
    /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
148
    /// @param[in] fileName The full path of the file to read
149
926
    explicit PcapFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName)
150
926
    {}
151
152
    /// A destructor for this class
153
926
    ~PcapFileReaderDevice() override = default;
154
155
    PcapFileReaderDevice(const PcapFileReaderDevice& other) = delete;
156
    PcapFileReaderDevice& operator=(const PcapFileReaderDevice& other) = delete;
157
158
    /// @return The link layer type of this file
159
    LinkLayerType getLinkLayerType() const
160
0
    {
161
0
      return m_PcapLinkLayerType;
162
0
    }
163
164
    /// @return The precision of the timestamps in the file
165
    FileTimestampPrecision getTimestampPrecision() const
166
0
    {
167
0
      return m_Precision;
168
0
    }
169
170
    /// @return The file's snapshot length (snaplen)
171
    uint32_t getSnapshotLength() const
172
0
    {
173
0
      return m_SnapshotLength;
174
0
    }
175
176
    /// A static method that checks if nano-second precision is supported in the current platform and environment
177
    /// @return True if nano-second precision is supported, false otherwise
178
    /// @deprecated Nanosecond precision is now natively supported by the internal parser and always returns true
179
    PCPP_DEPRECATED("Nanosecond precision is now natively supported by the internal parser and always returns true")
180
    static bool isNanoSecondPrecisionSupported()
181
0
    {
182
0
      return true;
183
0
    }
184
185
    // overridden methods
186
187
    /// @return True if the file is opened, false otherwise
188
    bool isOpened() const override
189
0
    {
190
0
      return m_PcapFile.is_open();
191
0
    }
192
193
    /// Read the next packet from the file. Before using this method please verify the file is opened using open()
194
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
195
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
196
    /// error log will be printed) or if reached end-of-file
197
    bool getNextPacket(RawPacket& rawPacket) override;
198
199
    /// Open the file name which path was specified in the constructor in a read-only mode
200
    /// @return True if file was opened successfully or if file is already opened. False if opening the file failed
201
    /// for some reason (for example: file path does not exist)
202
    bool open() override;
203
204
    /// Close the pacp file
205
    void close() override;
206
207
  private:
208
    FileTimestampPrecision m_Precision = FileTimestampPrecision::Unknown;
209
    LinkLayerType m_PcapLinkLayerType = LINKTYPE_ETHERNET;
210
    std::ifstream m_PcapFile;
211
    bool m_NeedsSwap = false;
212
    uint32_t m_SnapshotLength = 0;
213
214
    bool readNextPacket(timespec& packetTimestamp, uint8_t* packetData, uint32_t packetDataLen,
215
                        uint32_t& capturedLength, uint32_t& frameLength);
216
  };
217
218
  /// @class PcapFileWriterDevice
219
  /// A class for opening a pcap file for writing or creating a new pcap file and writing packets to it.
220
  /// It supports opening a pcap file in append mode where packets are written at the end of the file
221
  /// instead of overwriting it. This implementation writes the pcap stream directly using C++ I/O
222
  /// facilities (std::fstream) and does not require libpcap/WinPcap at runtime.
223
  class PcapFileWriterDevice : public IFileWriterDevice
224
  {
225
  public:
226
    /// A constructor for this class that gets the pcap full path file name to open for writing or create. Notice
227
    /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the
228
    /// file call open()
229
    /// @param[in] fileName The full path of the file
230
    /// @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is
231
    /// Ethernet
232
    /// @param[in] nanosecondsPrecision A boolean indicating whether to write timestamps in nano-precision. If set
233
    /// to false, timestamps will be written in micro-precision
234
    /// @throws std::runtime_error if nanosecondsPrecision is set to `true` but the current platform and environment
235
    /// doesn't support it.
236
    PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET,
237
                         bool nanosecondsPrecision = false);
238
239
    PcapFileWriterDevice(const PcapFileWriterDevice& other) = delete;
240
    PcapFileWriterDevice& operator=(const PcapFileWriterDevice& other) = delete;
241
242
    /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This
243
    /// method won't change the written packet
244
    /// @param[in] packet A reference for an existing RawPcket to write to the file
245
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened
246
    /// or if the packet link layer type is different than the one defined for the file
247
    /// (in all cases, an error will be printed to log)
248
    bool writePacket(RawPacket const& packet) override;
249
250
    /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using
251
    /// open(). This method won't change the written packets or the RawPacketVector instance
252
    /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the
253
    /// file
254
    /// @return True if all packets were written successfully to the file. False will be returned if the file isn't
255
    /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to
256
    /// the file
257
    bool writePackets(const RawPacketVector& packets) override;
258
259
    /// @return The precision of the timestamps in the file.
260
    FileTimestampPrecision getTimestampPrecision() const
261
0
    {
262
0
      return m_Precision;
263
0
    }
264
265
    /// A static method that checks if nano-second precision is supported in the current platform and environment
266
    /// @return True if nano-second precision is supported, false otherwise
267
    /// @deprecated Nanosecond precision is now natively supported by the internal parser and always returns true
268
    PCPP_DEPRECATED("Nanosecond precision is now natively supported by the internal parser and always returns true")
269
    static bool isNanoSecondPrecisionSupported()
270
0
    {
271
0
      return true;
272
0
    }
273
274
    LinkLayerType getLinkLayerType() const
275
0
    {
276
0
      return m_PcapLinkLayerType;
277
0
    }
278
279
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
280
    /// overwritten, meaning all its current content will be deleted
281
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
282
    /// failed for some reason (an error will be printed to log)
283
    bool open() override;
284
285
    /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file
286
    /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
287
    /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
288
    /// this method will act exactly like open(). If set to true, file will be opened in append mode
289
    /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be
290
    /// returned if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in
291
    /// c'tor is different from current file link type. In case appendMode is set to false, please refer to open()
292
    /// for return values
293
    bool open(bool appendMode) override;
294
295
    /// @return True if the file is opened, false otherwise
296
    bool isOpened() const override
297
0
    {
298
0
      return m_PcapFile.is_open();
299
0
    }
300
301
    /// Flush and close the pacp file
302
    void close() override;
303
304
    /// Flush packets to disk.
305
    void flush();
306
307
  private:
308
    LinkLayerType m_PcapLinkLayerType = LINKTYPE_ETHERNET;
309
    bool m_NeedsSwap = false;
310
    FileTimestampPrecision m_Precision = FileTimestampPrecision::Unknown;
311
    std::fstream m_PcapFile;
312
313
    struct CheckHeaderResult
314
    {
315
      enum class Result
316
      {
317
        HeaderOk,
318
        HeaderError,
319
        HeaderNeeded
320
      };
321
322
      Result result;
323
      std::string error;
324
      bool needsSwap = false;
325
326
      static CheckHeaderResult fromOk(bool needsSwap)
327
0
      {
328
0
        return { Result::HeaderOk, "", needsSwap };
329
0
      }
330
331
      static CheckHeaderResult fromError(const std::string& error)
332
0
      {
333
0
        return { Result::HeaderError, error };
334
0
      }
335
336
      static CheckHeaderResult fromHeaderNeeded()
337
0
      {
338
0
        return { Result::HeaderNeeded };
339
0
      }
340
    };
341
342
    static bool writeHeader(std::fstream& pcapFile, FileTimestampPrecision precision, uint32_t snaplen,
343
                            LinkLayerType linkType);
344
    static CheckHeaderResult checkHeader(std::fstream& pcapFile, FileTimestampPrecision requestedPrecision,
345
                                         LinkLayerType requestedLinkType);
346
  };
347
348
  /// @class PcapNgFileReaderDevice
349
  /// A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets,
350
  /// packet-by-packet
351
  class PcapNgFileReaderDevice : public IFileReaderDevice
352
  {
353
  private:
354
    internal::LightPcapNgHandle* m_LightPcapNg;
355
356
  public:
357
    /// A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling
358
    /// this constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
359
    /// @param[in] fileName The full path of the file to read
360
    PcapNgFileReaderDevice(const std::string& fileName);
361
362
    /// A destructor for this class
363
    ~PcapNgFileReaderDevice() override
364
0
    {
365
0
      PcapNgFileReaderDevice::close();
366
0
    }
367
368
    PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other) = delete;
369
    PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other) = delete;
370
371
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
372
    /// specifying the operating system that was used for capturing the packets. This method reads this string from
373
    /// the metadata (if exists) and returns it
374
    /// @return The operating system string if exists, or an empty string otherwise
375
    std::string getOS() const;
376
377
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
378
    /// specifying the hardware that was used for capturing the packets. This method reads this string from the
379
    /// metadata (if exists) and returns it
380
    /// @return The hardware string if exists, or an empty string otherwise
381
    std::string getHardware() const;
382
383
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
384
    /// specifying the capture application that was used for capturing the packets. This method reads this string
385
    /// from the metadata (if exists) and returns it
386
    /// @return The capture application string if exists, or an empty string otherwise
387
    std::string getCaptureApplication() const;
388
389
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
390
    /// containing a user-defined comment (can be any string). This method reads this string from the metadata (if
391
    /// exists) and returns it
392
    /// @return The comment written inside the file if exists, or an empty string otherwise
393
    std::string getCaptureFileComment() const;
394
395
    /// The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file).
396
    /// This method reads the next packet and the comment attached to it (if such comment exists), and returns them
397
    /// both
398
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
399
    /// @param[out] packetComment The comment attached to the packet or an empty string if no comment exists
400
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
401
    /// error log will be printed) or if reached end-of-file
402
    bool getNextPacket(RawPacket& rawPacket, std::string& packetComment);
403
404
    // overridden methods
405
406
    /// Read the next packet from the file. Before using this method please verify the file is opened using open()
407
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
408
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
409
    /// error log will be printed) or if reached end-of-file
410
    bool getNextPacket(RawPacket& rawPacket) override;
411
412
    /// Open the file name which path was specified in the constructor in a read-only mode
413
    /// @return True if file was opened successfully or if file is already opened. False if opening the file failed
414
    /// for some reason (for example: file path does not exist)
415
    bool open() override;
416
417
    /// @return True if the file is opened, false otherwise
418
    bool isOpened() const override
419
0
    {
420
0
      return m_LightPcapNg != nullptr;
421
0
    }
422
423
    /// Close the pacp-ng file
424
    void close() override;
425
426
  private:
427
    bool getNextPacketInternal(RawPacket& rawPacket, std::string* packetComment);
428
  };
429
430
  /// @class PcapNgFileWriterDevice
431
  /// A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This
432
  /// class adds unique capabilities such as writing metadata attributes into the file header, adding comments per
433
  /// packet and opening the file in append mode where packets are added to a file instead of overriding it. This
434
  /// capabilities are part of the pcap-ng standard but aren't supported in most tools and libraries
435
  class PcapNgFileWriterDevice : public IFileWriterDevice
436
  {
437
  private:
438
    internal::LightPcapNgHandle* m_LightPcapNg;
439
    int m_CompressionLevel;
440
441
  public:
442
    /// A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice
443
    /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the
444
    /// file call open()
445
    /// @param[in] fileName The full path of the file
446
    /// @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression
447
    /// or 10 for max compression. Default is 0
448
    PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel = 0);
449
450
    /// A destructor for this class
451
    ~PcapNgFileWriterDevice() override
452
619
    {
453
619
      PcapNgFileWriterDevice::close();
454
619
    }
455
456
    PcapNgFileWriterDevice(const PcapFileWriterDevice& other) = delete;
457
    PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other) = delete;
458
459
    /// The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a
460
    /// RawPacket to the file and adds a comment to it. Before using this method please verify the file is opened
461
    /// using open(). This method won't change the written packet or the input comment
462
    /// @param[in] packet A reference for an existing RawPcket to write to the file
463
    /// @param[in] comment The comment to be written for the packet. If this string is empty or null it will be
464
    /// ignored
465
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error
466
    /// will be printed to log)
467
    bool writePacket(RawPacket const& packet, const std::string& comment);
468
469
    // overridden methods
470
471
    /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This
472
    /// method won't change the written packet
473
    /// @param[in] packet A reference for an existing RawPcket to write to the file
474
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error
475
    /// will be printed to log)
476
    bool writePacket(RawPacket const& packet) override;
477
478
    /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using
479
    /// open(). This method won't change the written packets or the RawPacketVector instance
480
    /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the
481
    /// file
482
    /// @return True if all packets were written successfully to the file. False will be returned if the file isn't
483
    /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to
484
    /// the file
485
    bool writePackets(const RawPacketVector& packets) override;
486
487
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
488
    /// overwritten, meaning all its current content will be deleted
489
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
490
    /// failed for some reason (an error will be printed to log)
491
    bool open() override;
492
493
    /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file
494
    /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
495
    /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
496
    /// this method will act exactly like open(). If set to true, file will be opened in append mode
497
    /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be
498
    /// returned if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to
499
    /// false, please refer to open() for return values
500
    bool open(bool appendMode) override;
501
502
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
503
    /// overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows
504
    /// writing several metadata attributes that will be stored in the header of the file
505
    /// @param[in] os A string describing the operating system that was used to capture the packets. If this string
506
    /// is empty or null it will be ignored
507
    /// @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is
508
    /// empty or null it will be ignored
509
    /// @param[in] captureApp A string describing the application that was used to capture the packets. If this
510
    /// string is empty or null it will be ignored
511
    /// @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the
512
    /// file. If this string is empty or null it will be ignored
513
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
514
    /// failed for some reason (an error will be printed to log)
515
    bool open(const std::string& os, const std::string& hardware, const std::string& captureApp,
516
              const std::string& fileComment);
517
518
    /// @return True if the file is opened, false otherwise
519
    bool isOpened() const override
520
0
    {
521
0
      return m_LightPcapNg != nullptr;
522
0
    }
523
524
    /// Flush packets to the pcap-ng file
525
    void flush();
526
527
    /// Flush and close the pcap-ng file
528
    void close() override;
529
530
  private:
531
    /// @struct PcapNgMetadata
532
    /// @brief A struct for holding the metadata of a pcap-ng file. The metadata includes the operating system,
533
    /// hardware, capture application and file comment.
534
    struct PcapNgMetadata
535
    {
536
      /// The operating system that was used for capturing the packets
537
      std::string os;
538
      /// The hardware that was used for capturing the packets
539
      std::string hardware;
540
      /// The capture application that was used for capturing the packets
541
      std::string captureApplication;
542
      /// The comment that was written inside the file
543
      std::string comment;
544
    };
545
546
    bool openWrite(PcapNgMetadata const* metadata = nullptr);
547
    bool openAppend();
548
  };
549
550
  /// @class SnoopFileReaderDevice
551
  /// A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets,
552
  /// packet-by-packet
553
  class SnoopFileReaderDevice : public IFileReaderDevice
554
  {
555
  private:
556
#pragma pack(1)
557
    /// File format header.
558
    typedef struct
559
    {
560
      uint64_t identification_pattern;
561
      uint32_t version_number;
562
      uint32_t datalink_type;
563
    } snoop_file_header_t;
564
565
    /// Packet record header.
566
    typedef struct
567
    {
568
      uint32_t original_length;       ///< original packet length
569
      uint32_t included_length;       ///< saved packet length
570
      uint32_t packet_record_length;  ///< total record length
571
      uint32_t ndrops_cumulative;     ///< cumulative drops
572
      uint32_t time_sec;              ///< timestamp
573
      uint32_t time_usec;             ///< microsecond timestamp
574
    } snoop_packet_header_t;
575
#pragma pack()
576
577
    LinkLayerType m_PcapLinkLayerType;
578
    std::ifstream m_SnoopFile;
579
580
    bool readNextPacket(timespec& packetTimestamp, uint8_t* packetData, uint32_t packetDataLen,
581
                        uint32_t& capturedLength, uint32_t& frameLength);
582
583
  public:
584
    /// A constructor for this class that gets the snoop full path file name to open. Notice that after calling this
585
    /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
586
    /// @param[in] fileName The full path of the file to read
587
    SnoopFileReaderDevice(const std::string& fileName)
588
0
        : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET)
589
0
    {}
590
591
    /// A destructor for this class
592
    ~SnoopFileReaderDevice() override;
593
594
    SnoopFileReaderDevice(const PcapFileReaderDevice& other) = delete;
595
    SnoopFileReaderDevice& operator=(const PcapFileReaderDevice& other) = delete;
596
597
    /// @return The link layer type of this file
598
    LinkLayerType getLinkLayerType() const
599
0
    {
600
0
      return m_PcapLinkLayerType;
601
0
    }
602
603
    // overridden methods
604
605
    /// Read the next packet from the file. Before using this method please verify the file is opened using open()
606
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
607
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
608
    /// error log will be printed) or if reached end-of-file
609
    bool getNextPacket(RawPacket& rawPacket) override;
610
611
    /// Open the file name which path was specified in the constructor in a read-only mode
612
    /// @return True if file was opened successfully or if file is already opened. False if opening the file failed
613
    /// for some reason (for example: file path does not exist)
614
    bool open() override;
615
616
    /// @return True if the file is opened, false otherwise
617
    bool isOpened() const override
618
0
    {
619
0
      return m_SnoopFile.is_open();
620
0
    }
621
622
    /// Close the snoop file
623
    void close() override;
624
  };
625
}  // namespace pcpp