Coverage Report

Created: 2026-03-31 07:53

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
209k
    {
67
209k
      m_NumOfPacketsProcessed += numPackets;
68
209k
    }
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
4.80k
    {
74
4.80k
      m_NumOfPacketsDropped += numPackets;
75
4.80k
    }
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
935
    explicit PcapFileReaderDevice(const std::string& fileName) : IFileReaderDevice(fileName)
150
935
    {}
151
152
    /// A destructor for this class
153
935
    ~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
    std::vector<uint8_t> m_ReadBuffer;
214
215
    bool readNextPacket(timespec& packetTimestamp, uint8_t* packetData, uint32_t packetDataLen,
216
                        uint32_t& capturedLength, uint32_t& frameLength);
217
  };
218
219
  /// @class PcapFileWriterDevice
220
  /// A class for opening a pcap file for writing or creating a new pcap file and writing packets to it.
221
  /// It supports opening a pcap file in append mode where packets are written at the end of the file
222
  /// instead of overwriting it. This implementation writes the pcap stream directly using C++ I/O
223
  /// facilities (std::fstream) and does not require libpcap/WinPcap at runtime.
224
  class PcapFileWriterDevice : public IFileWriterDevice
225
  {
226
  public:
227
    /// A constructor for this class that gets the pcap full path file name to open for writing or create. Notice
228
    /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the
229
    /// file call open()
230
    /// @param[in] fileName The full path of the file
231
    /// @param[in] linkLayerType The link layer type all packet in this file will be based on. The default is
232
    /// Ethernet
233
    /// @param[in] nanosecondsPrecision A boolean indicating whether to write timestamps in nano-precision. If set
234
    /// to false, timestamps will be written in micro-precision
235
    /// @throws std::runtime_error if nanosecondsPrecision is set to `true` but the current platform and environment
236
    /// doesn't support it.
237
    PcapFileWriterDevice(const std::string& fileName, LinkLayerType linkLayerType = LINKTYPE_ETHERNET,
238
                         bool nanosecondsPrecision = false);
239
240
    PcapFileWriterDevice(const PcapFileWriterDevice& other) = delete;
241
    PcapFileWriterDevice& operator=(const PcapFileWriterDevice& other) = delete;
242
243
    /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This
244
    /// method won't change the written packet
245
    /// @param[in] packet A reference for an existing RawPcket to write to the file
246
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened
247
    /// or if the packet link layer type is different than the one defined for the file
248
    /// (in all cases, an error will be printed to log)
249
    bool writePacket(RawPacket const& packet) override;
250
251
    /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using
252
    /// open(). This method won't change the written packets or the RawPacketVector instance
253
    /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the
254
    /// file
255
    /// @return True if all packets were written successfully to the file. False will be returned if the file isn't
256
    /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to
257
    /// the file
258
    bool writePackets(const RawPacketVector& packets) override;
259
260
    /// @return The precision of the timestamps in the file.
261
    FileTimestampPrecision getTimestampPrecision() const
262
0
    {
263
0
      return m_Precision;
264
0
    }
265
266
    /// A static method that checks if nano-second precision is supported in the current platform and environment
267
    /// @return True if nano-second precision is supported, false otherwise
268
    /// @deprecated Nanosecond precision is now natively supported by the internal parser and always returns true
269
    PCPP_DEPRECATED("Nanosecond precision is now natively supported by the internal parser and always returns true")
270
    static bool isNanoSecondPrecisionSupported()
271
0
    {
272
0
      return true;
273
0
    }
274
275
    LinkLayerType getLinkLayerType() const
276
0
    {
277
0
      return m_PcapLinkLayerType;
278
0
    }
279
280
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
281
    /// overwritten, meaning all its current content will be deleted
282
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
283
    /// failed for some reason (an error will be printed to log)
284
    bool open() override;
285
286
    /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file
287
    /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
288
    /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
289
    /// this method will act exactly like open(). If set to true, file will be opened in append mode
290
    /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be
291
    /// returned if file wasn't found or couldn't be read, if file type is not pcap, or if link type specified in
292
    /// c'tor is different from current file link type. In case appendMode is set to false, please refer to open()
293
    /// for return values
294
    bool open(bool appendMode) override;
295
296
    /// @return True if the file is opened, false otherwise
297
    bool isOpened() const override
298
0
    {
299
0
      return m_PcapFile.is_open();
300
0
    }
301
302
    /// Flush and close the pacp file
303
    void close() override;
304
305
    /// Flush packets to disk.
306
    void flush();
307
308
  private:
309
    LinkLayerType m_PcapLinkLayerType = LINKTYPE_ETHERNET;
310
    bool m_NeedsSwap = false;
311
    FileTimestampPrecision m_Precision = FileTimestampPrecision::Unknown;
312
    std::fstream m_PcapFile;
313
314
    struct CheckHeaderResult
315
    {
316
      enum class Result
317
      {
318
        HeaderOk,
319
        HeaderError,
320
        HeaderNeeded
321
      };
322
323
      Result result;
324
      std::string error;
325
      bool needsSwap = false;
326
327
      static CheckHeaderResult fromOk(bool needsSwap)
328
956
      {
329
956
        return { Result::HeaderOk, "", needsSwap };
330
956
      }
331
332
      static CheckHeaderResult fromError(const std::string& error)
333
0
      {
334
0
        return { Result::HeaderError, error };
335
0
      }
336
337
      static CheckHeaderResult fromHeaderNeeded()
338
0
      {
339
0
        return { Result::HeaderNeeded };
340
0
      }
341
    };
342
343
    static bool writeHeader(std::fstream& pcapFile, FileTimestampPrecision precision, uint32_t snaplen,
344
                            LinkLayerType linkType);
345
    static CheckHeaderResult checkHeader(std::fstream& pcapFile, FileTimestampPrecision requestedPrecision,
346
                                         LinkLayerType requestedLinkType);
347
  };
348
349
  /// @class PcapNgFileReaderDevice
350
  /// A class for opening a pcap-ng file in read-only mode. This class enable to open the file and read all packets,
351
  /// packet-by-packet
352
  class PcapNgFileReaderDevice : public IFileReaderDevice
353
  {
354
  private:
355
    internal::LightPcapNgHandle* m_LightPcapNg;
356
357
  public:
358
    /// A constructor for this class that gets the pcap-ng full path file name to open. Notice that after calling
359
    /// this constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
360
    /// @param[in] fileName The full path of the file to read
361
    PcapNgFileReaderDevice(const std::string& fileName);
362
363
    /// A destructor for this class
364
    ~PcapNgFileReaderDevice() override
365
11.7k
    {
366
11.7k
      PcapNgFileReaderDevice::close();
367
11.7k
    }
368
369
    PcapNgFileReaderDevice(const PcapNgFileReaderDevice& other) = delete;
370
    PcapNgFileReaderDevice& operator=(const PcapNgFileReaderDevice& other) = delete;
371
372
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
373
    /// specifying the operating system that was used for capturing the packets. This method reads this string from
374
    /// the metadata (if exists) and returns it
375
    /// @return The operating system string if exists, or an empty string otherwise
376
    std::string getOS() const;
377
378
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
379
    /// specifying the hardware that was used for capturing the packets. This method reads this string from the
380
    /// metadata (if exists) and returns it
381
    /// @return The hardware string if exists, or an empty string otherwise
382
    std::string getHardware() const;
383
384
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
385
    /// specifying the capture application that was used for capturing the packets. This method reads this string
386
    /// from the metadata (if exists) and returns it
387
    /// @return The capture application string if exists, or an empty string otherwise
388
    std::string getCaptureApplication() const;
389
390
    /// The pcap-ng format allows storing metadata at the header of the file. Part of this metadata is a string
391
    /// containing a user-defined comment (can be any string). This method reads this string from the metadata (if
392
    /// exists) and returns it
393
    /// @return The comment written inside the file if exists, or an empty string otherwise
394
    std::string getCaptureFileComment() const;
395
396
    /// The pcap-ng format allows storing a user-defined comment for every packet (besides the comment per-file).
397
    /// This method reads the next packet and the comment attached to it (if such comment exists), and returns them
398
    /// both
399
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
400
    /// @param[out] packetComment The comment attached to the packet or an empty string if no comment exists
401
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
402
    /// error log will be printed) or if reached end-of-file
403
    bool getNextPacket(RawPacket& rawPacket, std::string& packetComment);
404
405
    // overridden methods
406
407
    /// Read the next packet from the file. Before using this method please verify the file is opened using open()
408
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
409
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
410
    /// error log will be printed) or if reached end-of-file
411
    bool getNextPacket(RawPacket& rawPacket) override;
412
413
    /// Open the file name which path was specified in the constructor in a read-only mode
414
    /// @return True if file was opened successfully or if file is already opened. False if opening the file failed
415
    /// for some reason (for example: file path does not exist)
416
    bool open() override;
417
418
    /// @return True if the file is opened, false otherwise
419
    bool isOpened() const override
420
0
    {
421
0
      return m_LightPcapNg != nullptr;
422
0
    }
423
424
    /// Close the pacp-ng file
425
    void close() override;
426
427
  private:
428
    bool getNextPacketInternal(RawPacket& rawPacket, std::string* packetComment);
429
  };
430
431
  /// @class PcapNgFileWriterDevice
432
  /// A class for opening a pcap-ng file for writing or creating a new pcap-ng file and write packets to it. This
433
  /// class adds unique capabilities such as writing metadata attributes into the file header, adding comments per
434
  /// packet and opening the file in append mode where packets are added to a file instead of overriding it. This
435
  /// capabilities are part of the pcap-ng standard but aren't supported in most tools and libraries
436
  class PcapNgFileWriterDevice : public IFileWriterDevice
437
  {
438
  private:
439
    internal::LightPcapNgHandle* m_LightPcapNg;
440
    int m_CompressionLevel;
441
442
  public:
443
    /// A constructor for this class that gets the pcap-ng full path file name to open for writing or create. Notice
444
    /// that after calling this constructor the file isn't opened yet, so writing packets will fail. For opening the
445
    /// file call open()
446
    /// @param[in] fileName The full path of the file
447
    /// @param[in] compressionLevel The compression level to use when writing the file, use 0 to disable compression
448
    /// or 10 for max compression. Default is 0
449
    PcapNgFileWriterDevice(const std::string& fileName, int compressionLevel = 0);
450
451
    /// A destructor for this class
452
    ~PcapNgFileWriterDevice() override
453
614
    {
454
614
      PcapNgFileWriterDevice::close();
455
614
    }
456
457
    PcapNgFileWriterDevice(const PcapFileWriterDevice& other) = delete;
458
    PcapNgFileWriterDevice& operator=(const PcapNgFileWriterDevice& other) = delete;
459
460
    /// The pcap-ng format allows adding a user-defined comment for each stored packet. This method writes a
461
    /// RawPacket to the file and adds a comment to it. Before using this method please verify the file is opened
462
    /// using open(). This method won't change the written packet or the input comment
463
    /// @param[in] packet A reference for an existing RawPcket to write to the file
464
    /// @param[in] comment The comment to be written for the packet. If this string is empty or null it will be
465
    /// ignored
466
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error
467
    /// will be printed to log)
468
    bool writePacket(RawPacket const& packet, const std::string& comment);
469
470
    // overridden methods
471
472
    /// Write a RawPacket to the file. Before using this method please verify the file is opened using open(). This
473
    /// method won't change the written packet
474
    /// @param[in] packet A reference for an existing RawPcket to write to the file
475
    /// @return True if a packet was written successfully. False will be returned if the file isn't opened (an error
476
    /// will be printed to log)
477
    bool writePacket(RawPacket const& packet) override;
478
479
    /// Write multiple RawPacket to the file. Before using this method please verify the file is opened using
480
    /// open(). This method won't change the written packets or the RawPacketVector instance
481
    /// @param[in] packets A reference for an existing RawPcketVector, all of its packets will be written to the
482
    /// file
483
    /// @return True if all packets were written successfully to the file. False will be returned if the file isn't
484
    /// opened (also, an error log will be printed) or if at least one of the packets wasn't written successfully to
485
    /// the file
486
    bool writePackets(const RawPacketVector& packets) override;
487
488
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
489
    /// overwritten, meaning all its current content will be deleted
490
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
491
    /// failed for some reason (an error will be printed to log)
492
    bool open() override;
493
494
    /// Same as open(), but enables to open the file in append mode in which packets will be appended to the file
495
    /// instead of overwrite its current content. In append mode file must exist, otherwise opening will fail
496
    /// @param[in] appendMode A boolean indicating whether to open the file in append mode or not. If set to false
497
    /// this method will act exactly like open(). If set to true, file will be opened in append mode
498
    /// @return True of managed to open the file successfully. In case appendMode is set to true, false will be
499
    /// returned if file wasn't found or couldn't be read, if file type is not pcap-ng. In case appendMode is set to
500
    /// false, please refer to open() for return values
501
    bool open(bool appendMode) override;
502
503
    /// Open the file in a write mode. If file doesn't exist, it will be created. If it does exist it will be
504
    /// overwritten, meaning all its current content will be deleted. As opposed to open(), this method also allows
505
    /// writing several metadata attributes that will be stored in the header of the file
506
    /// @param[in] os A string describing the operating system that was used to capture the packets. If this string
507
    /// is empty or null it will be ignored
508
    /// @param[in] hardware A string describing the hardware that was used to capture the packets. If this string is
509
    /// empty or null it will be ignored
510
    /// @param[in] captureApp A string describing the application that was used to capture the packets. If this
511
    /// string is empty or null it will be ignored
512
    /// @param[in] fileComment A string containing a user-defined comment that will be part of the metadata of the
513
    /// file. If this string is empty or null it will be ignored
514
    /// @return True if file was opened/created successfully or if file is already opened. False if opening the file
515
    /// failed for some reason (an error will be printed to log)
516
    bool open(const std::string& os, const std::string& hardware, const std::string& captureApp,
517
              const std::string& fileComment);
518
519
    /// @return True if the file is opened, false otherwise
520
    bool isOpened() const override
521
0
    {
522
0
      return m_LightPcapNg != nullptr;
523
0
    }
524
525
    /// Flush packets to the pcap-ng file
526
    void flush();
527
528
    /// Flush and close the pcap-ng file
529
    void close() override;
530
531
  private:
532
    /// @struct PcapNgMetadata
533
    /// @brief A struct for holding the metadata of a pcap-ng file. The metadata includes the operating system,
534
    /// hardware, capture application and file comment.
535
    struct PcapNgMetadata
536
    {
537
      /// The operating system that was used for capturing the packets
538
      std::string os;
539
      /// The hardware that was used for capturing the packets
540
      std::string hardware;
541
      /// The capture application that was used for capturing the packets
542
      std::string captureApplication;
543
      /// The comment that was written inside the file
544
      std::string comment;
545
    };
546
547
    bool openWrite(PcapNgMetadata const* metadata = nullptr);
548
    bool openAppend();
549
  };
550
551
  /// @class SnoopFileReaderDevice
552
  /// A class for opening a snoop file in read-only mode. This class enable to open the file and read all packets,
553
  /// packet-by-packet
554
  class SnoopFileReaderDevice : public IFileReaderDevice
555
  {
556
  private:
557
#pragma pack(1)
558
    /// File format header.
559
    typedef struct
560
    {
561
      uint64_t identification_pattern;
562
      uint32_t version_number;
563
      uint32_t datalink_type;
564
    } snoop_file_header_t;
565
566
    /// Packet record header.
567
    typedef struct
568
    {
569
      uint32_t original_length;       ///< original packet length
570
      uint32_t included_length;       ///< saved packet length
571
      uint32_t packet_record_length;  ///< total record length
572
      uint32_t ndrops_cumulative;     ///< cumulative drops
573
      uint32_t time_sec;              ///< timestamp
574
      uint32_t time_usec;             ///< microsecond timestamp
575
    } snoop_packet_header_t;
576
#pragma pack()
577
578
    LinkLayerType m_PcapLinkLayerType;
579
    std::ifstream m_SnoopFile;
580
581
    bool readNextPacket(timespec& packetTimestamp, uint8_t* packetData, uint32_t packetDataLen,
582
                        uint32_t& capturedLength, uint32_t& frameLength);
583
584
  public:
585
    /// A constructor for this class that gets the snoop full path file name to open. Notice that after calling this
586
    /// constructor the file isn't opened yet, so reading packets will fail. For opening the file call open()
587
    /// @param[in] fileName The full path of the file to read
588
    SnoopFileReaderDevice(const std::string& fileName)
589
363
        : IFileReaderDevice(fileName), m_PcapLinkLayerType(LINKTYPE_ETHERNET)
590
363
    {}
591
592
    /// A destructor for this class
593
    ~SnoopFileReaderDevice() override;
594
595
    SnoopFileReaderDevice(const PcapFileReaderDevice& other) = delete;
596
    SnoopFileReaderDevice& operator=(const PcapFileReaderDevice& other) = delete;
597
598
    /// @return The link layer type of this file
599
    LinkLayerType getLinkLayerType() const
600
0
    {
601
0
      return m_PcapLinkLayerType;
602
0
    }
603
604
    // overridden methods
605
606
    /// Read the next packet from the file. Before using this method please verify the file is opened using open()
607
    /// @param[out] rawPacket A reference for an empty RawPacket where the packet will be written
608
    /// @return True if a packet was read successfully. False will be returned if the file isn't opened (also, an
609
    /// error log will be printed) or if reached end-of-file
610
    bool getNextPacket(RawPacket& rawPacket) override;
611
612
    /// Open the file name which path was specified in the constructor in a read-only mode
613
    /// @return True if file was opened successfully or if file is already opened. False if opening the file failed
614
    /// for some reason (for example: file path does not exist)
615
    bool open() override;
616
617
    /// @return True if the file is opened, false otherwise
618
    bool isOpened() const override
619
1.43k
    {
620
1.43k
      return m_SnoopFile.is_open();
621
1.43k
    }
622
623
    /// Close the snoop file
624
    void close() override;
625
  };
626
}  // namespace pcpp