Coverage Report

Created: 2024-02-25 06:29

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