PcapPlusPlus  Next
WinDivertDevice.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <functional>
4 #include <tuple>
5 #include <unordered_map>
6 #include <atomic>
7 #include "Device.h"
8 
23 namespace pcpp
24 {
25  namespace internal
26  {
32  {
33  public:
38  struct WaitResult
39  {
42  enum class Status
43  {
44  Completed,
45  Timeout,
46  Failed
47  };
48 
50  uint32_t errorCode = 0;
51  };
52 
58  {
61  enum class Status
62  {
63  Success,
64  Failed
65  };
66 
68  uint32_t packetLen = 0;
69  uint32_t errorCode = 0;
70  };
71 
72  virtual WaitResult wait(uint32_t timeout) = 0;
73  virtual void reset() = 0;
74  virtual OverlappedResult getOverlappedResult() = 0;
75  virtual ~IOverlappedWrapper() = default;
76  };
77 
84  {
85  bool isIPv6;
86  uint32_t interfaceIndex;
87  uint64_t timestamp;
88  };
89 
98  {
99  public:
101  enum class WinDivertParam
102  {
103  QueueLength = 0,
104  QueueTime = 1,
105  QueueSize = 2,
106  VersionMajor = 3,
107  VersionMinor = 4
108  };
109 
111  static constexpr uint32_t SuccessResult = 0;
113  static constexpr uint32_t ErrorIoPending = 997;
114 
115  virtual ~IWinDivertHandle() = default;
116 
119  virtual uint32_t close() = 0;
120 
133  virtual uint32_t recvEx(uint8_t* buffer, uint32_t bufferLen, size_t addressesSize,
134  IOverlappedWrapper* overlapped) = 0;
135 
138  virtual std::vector<WinDivertAddress> recvExComplete() = 0;
139 
145  virtual uint32_t sendEx(uint8_t* buffer, uint32_t bufferLen, size_t addressesSize) = 0;
146 
149  virtual std::unique_ptr<IOverlappedWrapper> createOverlapped() = 0;
150 
155  virtual bool getParam(WinDivertParam param, uint64_t& value) = 0;
156 
161  virtual bool setParam(WinDivertParam param, uint64_t value) = 0;
162  };
163 
173  {
174  public:
177  {
178  uint32_t index;
179  std::wstring name;
180  std::wstring description;
181  bool isLoopback;
182  bool isUp;
183  };
184 
191  virtual std::unique_ptr<IWinDivertHandle> open(const std::string& filter, int layer, int16_t priority,
192  uint64_t flags) = 0;
193 
196  virtual std::vector<NetworkInterface> getNetworkInterfaces() const = 0;
197 
198  virtual ~IWinDivertDriver() = default;
199  };
200  } // namespace internal
201 
210  {
211  public:
212  WinDivertRawPacket(const uint8_t* pRawData, int rawDataLen, timespec timestamp, bool deleteRawDataAtDestructor,
213  LinkLayerType layerType, uint32_t interfaceIndex, uint64_t winDivertTimestamp)
214  : RawPacket(pRawData, rawDataLen, timestamp, deleteRawDataAtDestructor, layerType),
215  m_InterfaceIndex(interfaceIndex), m_WinDivertTimestamp(winDivertTimestamp)
216  {}
217 
218  ~WinDivertRawPacket() override = default;
219 
222  uint32_t getInterfaceIndex() const
223  {
224  return m_InterfaceIndex;
225  }
226 
229  uint64_t getWinDivertTimestamp() const
230  {
231  return m_WinDivertTimestamp;
232  }
233 
234  protected:
236  {
237  return internal::RawPacketImplType::WinDivert;
238  }
239 
240  private:
241  uint32_t m_InterfaceIndex;
242  uint64_t m_WinDivertTimestamp;
243  };
244 
263  class WinDivertDevice : public IDevice
264  {
265  public:
269  {
272  enum class Status
273  {
274  Completed,
275  Timeout,
276  Failed
277  };
278 
279  // cppcheck-suppress noExplicitConstructor
280  ReceiveResult(Status status, std::string const& error = "", uint32_t errorCode = 0)
282  {}
283 
285  std::string error;
286  uint32_t errorCode = 0;
287  };
288 
291  struct SendResult
292  {
295  enum class Status
296  {
297  Completed,
298  Failed
299  };
300 
302  size_t packetsSent;
303  std::string error;
304  uint32_t errorCode = 0;
305  };
306 
310  {
311  uint64_t major;
312  uint64_t minor;
313 
315  std::string toString() const
316  {
317  return std::to_string(major) + "." + std::to_string(minor);
318  }
319  };
320 
324  {
325  uint32_t index;
326  std::wstring name;
327  std::wstring description;
328  bool isLoopback;
329  bool isUp;
330  };
331 
339  enum class QueueParam
340  {
341  QueueLength,
342  QueueTime,
343  QueueSize
344  };
345 
349 
353  {
354  WinDivertDevice* device = nullptr;
355  };
356 
362  using ReceivePacketCallback = std::function<void(const WinDivertRawPacketVector& packetVec,
363  const WinDivertReceiveCallbackContext& context)>;
366  using QueueParams = std::unordered_map<QueueParam, uint64_t>;
367 
373  explicit WinDivertDevice(std::unique_ptr<internal::IWinDivertDriver> driver = nullptr);
374 
378  bool open() override;
379 
384  bool open(const std::string& filter);
385 
387  void close() override;
388 
389  bool isOpened() const override
390  {
391  return m_DeviceOpened;
392  }
393 
406  ReceiveResult receivePackets(WinDivertRawPacketVector& packetVec, uint32_t timeout = 5000,
407  uint32_t maxPackets = 0, uint8_t batchSize = 64);
408 
419  ReceiveResult receivePackets(const ReceivePacketCallback& callback, uint32_t timeout = 5000,
420  uint8_t batchSize = 64);
421 
424  void stopReceive();
425 
433  SendResult sendPackets(const RawPacketVector& packetVec, uint8_t batchSize = 64) const;
434 
438 
442  void setPacketQueueParams(const QueueParams& params) const;
443 
447 
452  const NetworkInterface* getNetworkInterface(uint32_t interfaceIndex) const;
453 
456  std::vector<NetworkInterface> getNetworkInterfaces() const;
457 
458  private:
459  std::unique_ptr<internal::IWinDivertDriver> m_Driver;
460  std::unique_ptr<internal::IWinDivertHandle> m_Handle;
461  std::atomic<bool> m_IsReceiving{ false };
462  mutable std::unordered_map<uint32_t, NetworkInterface> m_NetworkInterfaces;
463  mutable bool m_NetworkInterfacesInitialized = false;
464  bool m_DeviceOpened = false;
465 
466  struct ReceiveResultInternal : ReceiveResult
467  {
468  uint32_t capturedDataLength = 0;
469  std::vector<internal::WinDivertAddress> addresses;
470 
471  // cppcheck-suppress noExplicitConstructor
472  ReceiveResultInternal(Status status, const std::string& error = "", uint32_t errorCode = 0)
473  : ReceiveResult(status, error, errorCode)
474  {}
475 
476  ReceiveResultInternal(uint32_t capturedDataLength, const std::vector<internal::WinDivertAddress>& addresses)
477  : ReceiveResult(Status::Completed, "", 0), capturedDataLength(capturedDataLength), addresses(addresses)
478  {}
479  };
480 
481  ReceiveResultInternal receivePacketsInternal(uint32_t timeout, uint8_t batchSize, std::vector<uint8_t>& buffer,
482  internal::IOverlappedWrapper* overlapped);
483  static std::tuple<LinkLayerType, uint16_t, timespec> getPacketInfo(uint8_t* buffer, uint32_t bufferLen,
484  const internal::WinDivertAddress& address);
485  void setNetworkInterfaces() const;
486  static std::string getErrorString(uint32_t errorCode);
487  };
488 } // namespace pcpp
RawPacketImplType
Type of RawPacket implementation.
Definition: RawPacket.h:267
Definition: Device.h:20
Definition: PointerVector.h:50
Definition: RawPacket.h:290
RawPacket()=default
A device wrapper around the WinDivert driver for Windows.
Definition: WinDivertDevice.h:264
void stopReceive()
Request to stop an ongoing receivePackets(callback, ...) loop.
const NetworkInterface * getNetworkInterface(uint32_t interfaceIndex) const
Get a pointer to a specific Windows network interface by index.
std::vector< NetworkInterface > getNetworkInterfaces() const
Enumerate Windows network interfaces.
void close() override
Close the device and release the underlying WinDivert handle.
void setPacketQueueParams(const QueueParams &params) const
Set WinDivert queue parameters.
bool open(const std::string &filter)
Open the device with a custom WinDivert filter.
QueueParams getPacketQueueParams() const
Get the current WinDivert queue parameters.
WinDivertVersion getVersion() const
Get the WinDivert runtime version loaded on the system.
QueueParam
Queue tuning parameters supported by WinDivert.
Definition: WinDivertDevice.h:340
@ QueueLength
Maximum number of packets in the packet queue (packets)
@ QueueSize
Maximum memory allocated for the queue (bytes)
@ QueueTime
Maximum residence time of packets in the queue (milliseconds)
ReceiveResult receivePackets(WinDivertRawPacketVector &packetVec, uint32_t timeout=5000, uint32_t maxPackets=0, uint8_t batchSize=64)
Receive packets into a vector owned by the caller.
bool open() override
Open the device with a default filter capturing both directions.
bool isOpened() const override
Definition: WinDivertDevice.h:389
std::unordered_map< QueueParam, uint64_t > QueueParams
A map of QueueParam keys to their values. Units are per QueueParam description above.
Definition: WinDivertDevice.h:366
ReceiveResult receivePackets(const ReceivePacketCallback &callback, uint32_t timeout=5000, uint8_t batchSize=64)
Receive packets using a callback invoked for each received batch.
WinDivertDevice(std::unique_ptr< internal::IWinDivertDriver > driver=nullptr)
Construct a WinDivertDevice.
SendResult sendPackets(const RawPacketVector &packetVec, uint8_t batchSize=64) const
Send a vector of raw packets in batches.
std::function< void(const WinDivertRawPacketVector &packetVec, const WinDivertReceiveCallbackContext &context)> ReceivePacketCallback
Callback invoked with a batch of received packets when using the callback receive API....
Definition: WinDivertDevice.h:363
A RawPacket specialization used by WinDivertDevice.
Definition: WinDivertDevice.h:210
uint32_t getInterfaceIndex() const
Get the Windows interface index the packet was captured on.
Definition: WinDivertDevice.h:222
uint64_t getWinDivertTimestamp() const
Get the original WinDivert timestamp captured for this packet.
Definition: WinDivertDevice.h:229
internal::RawPacketImplType getImplType() const override
Get the type of RawPacket implementation.
Definition: WinDivertDevice.h:235
Abstract helper that wraps Windows OVERLAPPED I/O used by WinDivert operations.
Definition: WinDivertDevice.h:32
Factory and system-query abstraction used by WinDivertDevice.
Definition: WinDivertDevice.h:173
virtual std::vector< NetworkInterface > getNetworkInterfaces() const =0
Enumerate Windows network interfaces relevant to WinDivert.
virtual std::unique_ptr< IWinDivertHandle > open(const std::string &filter, int layer, int16_t priority, uint64_t flags)=0
Open a WinDivert handle with the given filter and settings.
An abstract handle for interacting with the WinDivert device.
Definition: WinDivertDevice.h:98
virtual uint32_t close()=0
Close the underlying WinDivert handle.
static constexpr uint32_t ErrorIoPending
Windows ERROR_IO_PENDING (997) reported when an async operation is in flight.
Definition: WinDivertDevice.h:113
virtual uint32_t recvEx(uint8_t *buffer, uint32_t bufferLen, size_t addressesSize, IOverlappedWrapper *overlapped)=0
Begin or perform an overlapped receive of raw packet data.
virtual std::unique_ptr< IOverlappedWrapper > createOverlapped()=0
Create a new overlapped wrapper bound to this handle.
static constexpr uint32_t SuccessResult
Generic success code returned by most operations.
Definition: WinDivertDevice.h:111
virtual std::vector< WinDivertAddress > recvExComplete()=0
Finalize a previous overlapped receive and fetch per-packet address metadata.
virtual bool getParam(WinDivertParam param, uint64_t &value)=0
Query a WinDivert runtime/queue parameter.
virtual bool setParam(WinDivertParam param, uint64_t value)=0
Set a WinDivert runtime/queue parameter.
virtual uint32_t sendEx(uint8_t *buffer, uint32_t bufferLen, size_t addressesSize)=0
Send a batch of raw packets.
WinDivertParam
WinDivert runtime parameters that can be queried or configured.
Definition: WinDivertDevice.h:102
@ QueueLength
Maximum number of packets in the queue.
@ QueueSize
Maximum total queue size (bytes)
@ QueueTime
Maximum time (ms) a packet may stay in the queue.
The main namespace for the PcapPlusPlus lib.
Definition: AssertionUtils.h:19
LinkLayerType
An enum describing all known link layer type. Taken from: http://www.tcpdump.org/linktypes....
Definition: RawPacket.h:22
A Windows network interface entry returned by getNetworkInterfaces().
Definition: WinDivertDevice.h:324
uint32_t index
Interface index as provided by Windows.
Definition: WinDivertDevice.h:325
std::wstring description
Human-readable description from the OS.
Definition: WinDivertDevice.h:327
bool isUp
True when the interface operational status is up.
Definition: WinDivertDevice.h:329
std::wstring name
Interface name (GUID or friendly/system name)
Definition: WinDivertDevice.h:326
bool isLoopback
True if the interface type is software loopback.
Definition: WinDivertDevice.h:328
Result object returned by receive operations.
Definition: WinDivertDevice.h:269
Status status
Operation status (Completed/Timeout/Failed)
Definition: WinDivertDevice.h:284
Status
Status codes for receive operations.
Definition: WinDivertDevice.h:273
@ Completed
Receive completed successfully.
@ Timeout
Receive timed out before completing the requested operation.
@ Failed
Receive failed due to an error (see error and errorCode)
uint32_t errorCode
Platform-specific error code associated with the failure (0 if none)
Definition: WinDivertDevice.h:286
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:285
Result object returned by send operations.
Definition: WinDivertDevice.h:292
Status
Status codes for send operations.
Definition: WinDivertDevice.h:296
@ Completed
Send operation completed successfully.
@ Failed
Send operation failed (see error and errorCode)
uint32_t errorCode
Platform-specific error code associated with the failure (0 if none)
Definition: WinDivertDevice.h:304
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:303
size_t packetsSent
Number of packets successfully sent when status is Completed.
Definition: WinDivertDevice.h:302
Status status
Operation status (Completed/Failed)
Definition: WinDivertDevice.h:301
Context object passed to ReceivePacketCallback.
Definition: WinDivertDevice.h:353
WinDivertDevice * device
The device that owns the receive loop (may be null)
Definition: WinDivertDevice.h:354
The WinDivert runtime version as reported by the driver.
Definition: WinDivertDevice.h:310
std::string toString() const
Convert to "major.minor" string representation.
Definition: WinDivertDevice.h:315
uint64_t major
Major version number reported by WinDivert.
Definition: WinDivertDevice.h:311
uint64_t minor
Minor version number reported by WinDivert.
Definition: WinDivertDevice.h:312
Result of completing an OVERLAPPED I/O operation.
Definition: WinDivertDevice.h:58
Status
Status codes for overlapped result.
Definition: WinDivertDevice.h:62
Status status
Completion status.
Definition: WinDivertDevice.h:67
uint32_t errorCode
Windows error code (when relevant)
Definition: WinDivertDevice.h:69
uint32_t packetLen
Number of bytes read/written (when applicable)
Definition: WinDivertDevice.h:68
Result of waiting on an OVERLAPPED I/O operation.
Definition: WinDivertDevice.h:39
uint32_t errorCode
Windows error code (when relevant)
Definition: WinDivertDevice.h:50
Status
Status codes for wait result.
Definition: WinDivertDevice.h:43
@ Timeout
The wait timed out before completion.
Status status
Final wait status.
Definition: WinDivertDevice.h:49
Information about a Windows network interface as reported by WinDivert/Windows APIs.
Definition: WinDivertDevice.h:177
bool isUp
True when the interface operational status is up.
Definition: WinDivertDevice.h:182
std::wstring description
Human-readable description from the OS.
Definition: WinDivertDevice.h:180
std::wstring name
Interface name (GUID or friendly/system name)
Definition: WinDivertDevice.h:179
bool isLoopback
True if the interface type is software loopback.
Definition: WinDivertDevice.h:181
uint32_t index
Interface index as provided by Windows.
Definition: WinDivertDevice.h:178
Minimal address/metadata returned by WinDivert for a captured packet.
Definition: WinDivertDevice.h:84
bool isIPv6
True if the packet is IPv6, false for IPv4.
Definition: WinDivertDevice.h:85
uint32_t interfaceIndex
Windows network interface index.
Definition: WinDivertDevice.h:86
uint64_t timestamp
WinDivert timestamp associated with the packet.
Definition: WinDivertDevice.h:87