Coverage Report

Created: 2023-01-17 06:15

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