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  private:
235  uint32_t m_InterfaceIndex;
236  uint64_t m_WinDivertTimestamp;
237  };
238 
257  class WinDivertDevice : public IDevice
258  {
259  public:
263  {
266  enum class Status
267  {
268  Completed,
269  Timeout,
270  Failed
271  };
272 
274  std::string error;
275  uint32_t errorCode = 0;
276  };
277 
280  struct SendResult
281  {
284  enum class Status
285  {
286  Completed,
287  Failed
288  };
289 
291  size_t packetsSent;
292  std::string error;
293  uint32_t errorCode = 0;
294  };
295 
299  {
300  uint64_t major;
301  uint64_t minor;
302 
304  std::string toString() const
305  {
306  return std::to_string(major) + "." + std::to_string(minor);
307  }
308  };
309 
313  {
314  uint32_t index;
315  std::wstring name;
316  std::wstring description;
317  bool isLoopback;
318  bool isUp;
319  };
320 
328  enum class QueueParam
329  {
330  QueueLength,
331  QueueTime,
332  QueueSize
333  };
334 
338 
342  {
343  WinDivertDevice* device = nullptr;
344  };
345 
351  using ReceivePacketCallback = std::function<void(const WinDivertRawPacketVector& packetVec,
352  const WinDivertReceiveCallbackContext& context)>;
355  using QueueParams = std::unordered_map<QueueParam, uint64_t>;
356 
362  WinDivertDevice(std::unique_ptr<internal::IWinDivertDriver> driver = nullptr);
363 
367  bool open() override;
368 
373  bool open(const std::string& filter);
374 
376  void close() override;
377 
378  bool isOpened() const override
379  {
380  return m_DeviceOpened;
381  }
382 
395  ReceiveResult receivePackets(WinDivertRawPacketVector& packetVec, uint32_t timeout = 5000,
396  uint32_t maxPackets = 0, uint8_t batchSize = 64);
397 
408  ReceiveResult receivePackets(const ReceivePacketCallback& callback, uint32_t timeout = 5000,
409  uint8_t batchSize = 64);
410 
413  void stopReceive();
414 
422  SendResult sendPackets(const RawPacketVector& packetVec, uint8_t batchSize = 64) const;
423 
427 
431  void setPacketQueueParams(const QueueParams& params) const;
432 
436 
441  const NetworkInterface* getNetworkInterface(uint32_t interfaceIndex) const;
442 
445  std::vector<NetworkInterface> getNetworkInterfaces() const;
446 
447  private:
448  std::unique_ptr<internal::IWinDivertDriver> m_Driver;
449  std::unique_ptr<internal::IWinDivertHandle> m_Handle;
450  std::atomic<bool> m_IsReceiving{ false };
451  mutable std::unordered_map<uint32_t, NetworkInterface> m_NetworkInterfaces;
452  mutable bool m_NetworkInterfacesInitialized = false;
453  bool m_DeviceOpened = false;
454 
455  struct ReceiveResultInternal : ReceiveResult
456  {
457  uint32_t capturedDataLength = 0;
458  std::vector<internal::WinDivertAddress> addresses;
459 
460  ReceiveResultInternal(Status status, const std::string& error = "", uint32_t errorCode = 0)
461  : ReceiveResult{ status, error, errorCode }
462  {}
463 
464  ReceiveResultInternal(uint32_t capturedDataLength, const std::vector<internal::WinDivertAddress>& addresses)
465  : ReceiveResult{ Status::Completed, "", 0 }, capturedDataLength(capturedDataLength),
466  addresses(addresses)
467  {}
468  };
469 
470  ReceiveResultInternal receivePacketsInternal(uint32_t timeout, uint8_t batchSize, std::vector<uint8_t>& buffer,
471  internal::IOverlappedWrapper* overlapped);
472  static std::tuple<LinkLayerType, uint16_t, timespec> getPacketInfo(uint8_t* buffer, uint32_t bufferLen,
473  const internal::WinDivertAddress& address);
474  void setNetworkInterfaces() const;
475  static std::string getErrorString(uint32_t errorCode);
476  };
477 } // namespace pcpp
Definition: Device.h:20
Definition: PointerVector.h:50
Definition: RawPacket.h:261
RawPacket()=default
A device wrapper around the WinDivert driver for Windows.
Definition: WinDivertDevice.h:258
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:329
@ 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:378
std::unordered_map< QueueParam, uint64_t > QueueParams
A map of QueueParam keys to their values. Units are per QueueParam description above.
Definition: WinDivertDevice.h:355
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:352
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
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:313
uint32_t index
Interface index as provided by Windows.
Definition: WinDivertDevice.h:314
std::wstring description
Human-readable description from the OS.
Definition: WinDivertDevice.h:316
bool isUp
True when the interface operational status is up.
Definition: WinDivertDevice.h:318
std::wstring name
Interface name (GUID or friendly/system name)
Definition: WinDivertDevice.h:315
bool isLoopback
True if the interface type is software loopback.
Definition: WinDivertDevice.h:317
Result object returned by receive operations.
Definition: WinDivertDevice.h:263
Status status
Operation status (Completed/Timeout/Failed)
Definition: WinDivertDevice.h:273
Status
Status codes for receive operations.
Definition: WinDivertDevice.h:267
@ 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:275
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:274
Result object returned by send operations.
Definition: WinDivertDevice.h:281
Status
Status codes for send operations.
Definition: WinDivertDevice.h:285
@ 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:293
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:292
size_t packetsSent
Number of packets successfully sent when status is Completed.
Definition: WinDivertDevice.h:291
Status status
Operation status (Completed/Failed)
Definition: WinDivertDevice.h:290
Context object passed to ReceivePacketCallback.
Definition: WinDivertDevice.h:342
WinDivertDevice * device
The device that owns the receive loop (may be null)
Definition: WinDivertDevice.h:343
The WinDivert runtime version as reported by the driver.
Definition: WinDivertDevice.h:299
std::string toString() const
Convert to "major.minor" string representation.
Definition: WinDivertDevice.h:304
uint64_t major
Major version number reported by WinDivert.
Definition: WinDivertDevice.h:300
uint64_t minor
Minor version number reported by WinDivert.
Definition: WinDivertDevice.h:301
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