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 
280  std::string error;
281  uint32_t errorCode = 0;
282  };
283 
286  struct SendResult
287  {
290  enum class Status
291  {
292  Completed,
293  Failed
294  };
295 
297  size_t packetsSent;
298  std::string error;
299  uint32_t errorCode = 0;
300  };
301 
305  {
306  uint64_t major;
307  uint64_t minor;
308 
310  std::string toString() const
311  {
312  return std::to_string(major) + "." + std::to_string(minor);
313  }
314  };
315 
319  {
320  uint32_t index;
321  std::wstring name;
322  std::wstring description;
323  bool isLoopback;
324  bool isUp;
325  };
326 
334  enum class QueueParam
335  {
336  QueueLength,
337  QueueTime,
338  QueueSize
339  };
340 
344 
348  {
349  WinDivertDevice* device = nullptr;
350  };
351 
357  using ReceivePacketCallback = std::function<void(const WinDivertRawPacketVector& packetVec,
358  const WinDivertReceiveCallbackContext& context)>;
361  using QueueParams = std::unordered_map<QueueParam, uint64_t>;
362 
368  WinDivertDevice(std::unique_ptr<internal::IWinDivertDriver> driver = nullptr);
369 
373  bool open() override;
374 
379  bool open(const std::string& filter);
380 
382  void close() override;
383 
384  bool isOpened() const override
385  {
386  return m_DeviceOpened;
387  }
388 
401  ReceiveResult receivePackets(WinDivertRawPacketVector& packetVec, uint32_t timeout = 5000,
402  uint32_t maxPackets = 0, uint8_t batchSize = 64);
403 
414  ReceiveResult receivePackets(const ReceivePacketCallback& callback, uint32_t timeout = 5000,
415  uint8_t batchSize = 64);
416 
419  void stopReceive();
420 
428  SendResult sendPackets(const RawPacketVector& packetVec, uint8_t batchSize = 64) const;
429 
433 
437  void setPacketQueueParams(const QueueParams& params) const;
438 
442 
447  const NetworkInterface* getNetworkInterface(uint32_t interfaceIndex) const;
448 
451  std::vector<NetworkInterface> getNetworkInterfaces() const;
452 
453  private:
454  std::unique_ptr<internal::IWinDivertDriver> m_Driver;
455  std::unique_ptr<internal::IWinDivertHandle> m_Handle;
456  std::atomic<bool> m_IsReceiving{ false };
457  mutable std::unordered_map<uint32_t, NetworkInterface> m_NetworkInterfaces;
458  mutable bool m_NetworkInterfacesInitialized = false;
459  bool m_DeviceOpened = false;
460 
461  struct ReceiveResultInternal : ReceiveResult
462  {
463  uint32_t capturedDataLength = 0;
464  std::vector<internal::WinDivertAddress> addresses;
465 
466  ReceiveResultInternal(Status status, const std::string& error = "", uint32_t errorCode = 0)
467  : ReceiveResult{ status, error, errorCode }
468  {}
469 
470  ReceiveResultInternal(uint32_t capturedDataLength, const std::vector<internal::WinDivertAddress>& addresses)
471  : ReceiveResult{ Status::Completed, "", 0 }, capturedDataLength(capturedDataLength),
472  addresses(addresses)
473  {}
474  };
475 
476  ReceiveResultInternal receivePacketsInternal(uint32_t timeout, uint8_t batchSize, std::vector<uint8_t>& buffer,
477  internal::IOverlappedWrapper* overlapped);
478  static std::tuple<LinkLayerType, uint16_t, timespec> getPacketInfo(uint8_t* buffer, uint32_t bufferLen,
479  const internal::WinDivertAddress& address);
480  void setNetworkInterfaces() const;
481  static std::string getErrorString(uint32_t errorCode);
482  };
483 } // 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:335
@ 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:384
std::unordered_map< QueueParam, uint64_t > QueueParams
A map of QueueParam keys to their values. Units are per QueueParam description above.
Definition: WinDivertDevice.h:361
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:358
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:319
uint32_t index
Interface index as provided by Windows.
Definition: WinDivertDevice.h:320
std::wstring description
Human-readable description from the OS.
Definition: WinDivertDevice.h:322
bool isUp
True when the interface operational status is up.
Definition: WinDivertDevice.h:324
std::wstring name
Interface name (GUID or friendly/system name)
Definition: WinDivertDevice.h:321
bool isLoopback
True if the interface type is software loopback.
Definition: WinDivertDevice.h:323
Result object returned by receive operations.
Definition: WinDivertDevice.h:269
Status status
Operation status (Completed/Timeout/Failed)
Definition: WinDivertDevice.h:279
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:281
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:280
Result object returned by send operations.
Definition: WinDivertDevice.h:287
Status
Status codes for send operations.
Definition: WinDivertDevice.h:291
@ 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:299
std::string error
Error message when status is Failed; empty otherwise.
Definition: WinDivertDevice.h:298
size_t packetsSent
Number of packets successfully sent when status is Completed.
Definition: WinDivertDevice.h:297
Status status
Operation status (Completed/Failed)
Definition: WinDivertDevice.h:296
Context object passed to ReceivePacketCallback.
Definition: WinDivertDevice.h:348
WinDivertDevice * device
The device that owns the receive loop (may be null)
Definition: WinDivertDevice.h:349
The WinDivert runtime version as reported by the driver.
Definition: WinDivertDevice.h:305
std::string toString() const
Convert to "major.minor" string representation.
Definition: WinDivertDevice.h:310
uint64_t major
Major version number reported by WinDivert.
Definition: WinDivertDevice.h:306
uint64_t minor
Minor version number reported by WinDivert.
Definition: WinDivertDevice.h:307
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