/* * windivert.h * (C) 2019, all rights reserved, * * This file is part of WinDivert. * * WinDivert is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * WinDivert is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __WINDIVERT_H #define __WINDIVERT_H #ifndef WINDIVERT_KERNEL #include #endif /* WINDIVERT_KERNEL */ #ifndef WINDIVERTEXPORT #define WINDIVERTEXPORT extern __declspec(dllimport) #endif /* WINDIVERTEXPORT */ #ifdef __MINGW32__ #define __in #define __in_opt #define __out #define __out_opt #define __inout #define __inout_opt #include #define INT8 int8_t #define UINT8 uint8_t #define INT16 int16_t #define UINT16 uint16_t #define INT32 int32_t #define UINT32 uint32_t #define INT64 int64_t #define UINT64 uint64_t #endif /* __MINGW32__ */ #ifdef __cplusplus extern "C" { #endif /****************************************************************************/ /* WINDIVERT API */ /****************************************************************************/ /* * WinDivert layers. */ typedef enum { WINDIVERT_LAYER_NETWORK = 0, /* Network layer. */ WINDIVERT_LAYER_NETWORK_FORWARD = 1,/* Network layer (forwarded packets) */ WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */ WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */ WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */ } WINDIVERT_LAYER, *PWINDIVERT_LAYER; /* * WinDivert NETWORK and NETWORK_FORWARD layer data. */ typedef struct { UINT32 IfIdx; /* Packet's interface index. */ UINT32 SubIfIdx; /* Packet's sub-interface index. */ } WINDIVERT_DATA_NETWORK, *PWINDIVERT_DATA_NETWORK; /* * WinDivert FLOW layer data. */ typedef struct { UINT64 EndpointId; /* Endpoint ID. */ UINT64 ParentEndpointId; /* Parent endpoint ID. */ UINT32 ProcessId; /* Process ID. */ UINT32 LocalAddr[4]; /* Local address. */ UINT32 RemoteAddr[4]; /* Remote address. */ UINT16 LocalPort; /* Local port. */ UINT16 RemotePort; /* Remote port. */ UINT8 Protocol; /* Protocol. */ } WINDIVERT_DATA_FLOW, *PWINDIVERT_DATA_FLOW; /* * WinDivert SOCKET layer data. */ typedef struct { UINT64 EndpointId; /* Endpoint ID. */ UINT64 ParentEndpointId; /* Parent Endpoint ID. */ UINT32 ProcessId; /* Process ID. */ UINT32 LocalAddr[4]; /* Local address. */ UINT32 RemoteAddr[4]; /* Remote address. */ UINT16 LocalPort; /* Local port. */ UINT16 RemotePort; /* Remote port. */ UINT8 Protocol; /* Protocol. */ } WINDIVERT_DATA_SOCKET, *PWINDIVERT_DATA_SOCKET; /* * WinDivert REFLECTION layer data. */ typedef struct { INT64 Timestamp; /* Handle open time. */ UINT32 ProcessId; /* Handle process ID. */ WINDIVERT_LAYER Layer; /* Handle layer. */ UINT64 Flags; /* Handle flags. */ INT16 Priority; /* Handle priority. */ } WINDIVERT_DATA_REFLECT, *PWINDIVERT_DATA_REFLECT; /* * WinDivert address. */ #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4201) #endif typedef struct { INT64 Timestamp; /* Packet's timestamp. */ UINT32 Layer:8; /* Packet's layer. */ UINT32 Event:8; /* Packet event. */ UINT32 Sniffed:1; /* Packet was sniffed? */ UINT32 Outbound:1; /* Packet is outound? */ UINT32 Loopback:1; /* Packet is loopback? */ UINT32 Impostor:1; /* Packet is impostor? */ UINT32 IPv6:1; /* Packet is IPv6? */ UINT32 IPChecksum:1; /* Packet has valid IPv4 checksum? */ UINT32 TCPChecksum:1; /* Packet has valid TCP checksum? */ UINT32 UDPChecksum:1; /* Packet has valid UDP checksum? */ UINT32 Reserved1:8; UINT32 Reserved2; union { WINDIVERT_DATA_NETWORK Network; /* Network layer data. */ WINDIVERT_DATA_FLOW Flow; /* Flow layer data. */ WINDIVERT_DATA_SOCKET Socket; /* Socket layer data. */ WINDIVERT_DATA_REFLECT Reflect; /* Reflect layer data. */ UINT8 Reserved3[64]; }; } WINDIVERT_ADDRESS, *PWINDIVERT_ADDRESS; #ifdef _MSC_VER #pragma warning(pop) #endif /* * WinDivert events. */ typedef enum { WINDIVERT_EVENT_NETWORK_PACKET = 0, /* Network packet. */ WINDIVERT_EVENT_FLOW_ESTABLISHED = 1, /* Flow established. */ WINDIVERT_EVENT_FLOW_DELETED = 2, /* Flow deleted. */ WINDIVERT_EVENT_SOCKET_BIND = 3, /* Socket bind. */ WINDIVERT_EVENT_SOCKET_CONNECT = 4, /* Socket connect. */ WINDIVERT_EVENT_SOCKET_LISTEN = 5, /* Socket listen. */ WINDIVERT_EVENT_SOCKET_ACCEPT = 6, /* Socket accept. */ WINDIVERT_EVENT_SOCKET_CLOSE = 7, /* Socket close. */ WINDIVERT_EVENT_REFLECT_OPEN = 8, /* WinDivert handle opened. */ WINDIVERT_EVENT_REFLECT_CLOSE = 9, /* WinDivert handle closed. */ } WINDIVERT_EVENT, *PWINDIVERT_EVENT; /* * WinDivert flags. */ #define WINDIVERT_FLAG_SNIFF 0x0001 #define WINDIVERT_FLAG_DROP 0x0002 #define WINDIVERT_FLAG_RECV_ONLY 0x0004 #define WINDIVERT_FLAG_READ_ONLY WINDIVERT_FLAG_RECV_ONLY #define WINDIVERT_FLAG_SEND_ONLY 0x0008 #define WINDIVERT_FLAG_WRITE_ONLY WINDIVERT_FLAG_SEND_ONLY #define WINDIVERT_FLAG_NO_INSTALL 0x0010 #define WINDIVERT_FLAG_FRAGMENTS 0x0020 /* * WinDivert parameters. */ typedef enum { WINDIVERT_PARAM_QUEUE_LENGTH = 0, /* Packet queue length. */ WINDIVERT_PARAM_QUEUE_TIME = 1, /* Packet queue time. */ WINDIVERT_PARAM_QUEUE_SIZE = 2, /* Packet queue size. */ WINDIVERT_PARAM_VERSION_MAJOR = 3, /* Driver version (major). */ WINDIVERT_PARAM_VERSION_MINOR = 4, /* Driver version (minor). */ } WINDIVERT_PARAM, *PWINDIVERT_PARAM; #define WINDIVERT_PARAM_MAX WINDIVERT_PARAM_VERSION_MINOR /* * WinDivert shutdown parameter. */ typedef enum { WINDIVERT_SHUTDOWN_RECV = 0x1, /* Shutdown recv. */ WINDIVERT_SHUTDOWN_SEND = 0x2, /* Shutdown send. */ WINDIVERT_SHUTDOWN_BOTH = 0x3, /* Shutdown recv and send. */ } WINDIVERT_SHUTDOWN, *PWINDIVERT_SHUTDOWN; #define WINDIVERT_SHUTDOWN_MAX WINDIVERT_SHUTDOWN_BOTH #ifndef WINDIVERT_KERNEL /* * Open a WinDivert handle. */ WINDIVERTEXPORT HANDLE WinDivertOpen( __in const char *filter, __in WINDIVERT_LAYER layer, __in INT16 priority, __in UINT64 flags); /* * Receive (read) a packet from a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertRecv( __in HANDLE handle, __out_opt VOID *pPacket, __in UINT packetLen, __out_opt UINT *pRecvLen, __out_opt WINDIVERT_ADDRESS *pAddr); /* * Receive (read) a packet from a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertRecvEx( __in HANDLE handle, __out_opt VOID *pPacket, __in UINT packetLen, __out_opt UINT *pRecvLen, __in UINT64 flags, __out WINDIVERT_ADDRESS *pAddr, __inout_opt UINT *pAddrLen, __inout_opt LPOVERLAPPED lpOverlapped); /* * Send (write/inject) a packet to a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertSend( __in HANDLE handle, __in const VOID *pPacket, __in UINT packetLen, __out_opt UINT *pSendLen, __in const WINDIVERT_ADDRESS *pAddr); /* * Send (write/inject) a packet to a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertSendEx( __in HANDLE handle, __in const VOID *pPacket, __in UINT packetLen, __out_opt UINT *pSendLen, __in UINT64 flags, __in const WINDIVERT_ADDRESS *pAddr, __in UINT addrLen, __inout_opt LPOVERLAPPED lpOverlapped); /* * Shutdown a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertShutdown( __in HANDLE handle, __in WINDIVERT_SHUTDOWN how); /* * Close a WinDivert handle. */ WINDIVERTEXPORT BOOL WinDivertClose( __in HANDLE handle); /* * Set a WinDivert handle parameter. */ WINDIVERTEXPORT BOOL WinDivertSetParam( __in HANDLE handle, __in WINDIVERT_PARAM param, __in UINT64 value); /* * Get a WinDivert handle parameter. */ WINDIVERTEXPORT BOOL WinDivertGetParam( __in HANDLE handle, __in WINDIVERT_PARAM param, __out UINT64 *pValue); #endif /* WINDIVERT_KERNEL */ /* * WinDivert constants. */ #define WINDIVERT_PRIORITY_HIGHEST 30000 #define WINDIVERT_PRIORITY_LOWEST (-WINDIVERT_PRIORITY_HIGHEST) #define WINDIVERT_PARAM_QUEUE_LENGTH_DEFAULT 4096 #define WINDIVERT_PARAM_QUEUE_LENGTH_MIN 32 #define WINDIVERT_PARAM_QUEUE_LENGTH_MAX 16384 #define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 2000 /* 2s */ #define WINDIVERT_PARAM_QUEUE_TIME_MIN 100 /* 100ms */ #define WINDIVERT_PARAM_QUEUE_TIME_MAX 16000 /* 16s */ #define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */ #define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */ #define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */ #define WINDIVERT_BATCH_MAX 0xFF /* 255 */ #define WINDIVERT_MTU_MAX (40 + 0xFFFF) /****************************************************************************/ /* WINDIVERT HELPER API */ /****************************************************************************/ #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4214) #endif /* * IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions. */ typedef struct { UINT8 HdrLength:4; UINT8 Version:4; UINT8 TOS; UINT16 Length; UINT16 Id; UINT16 FragOff0; UINT8 TTL; UINT8 Protocol; UINT16 Checksum; UINT32 SrcAddr; UINT32 DstAddr; } WINDIVERT_IPHDR, *PWINDIVERT_IPHDR; #define WINDIVERT_IPHDR_GET_FRAGOFF(hdr) \ (((hdr)->FragOff0) & 0xFF1F) #define WINDIVERT_IPHDR_GET_MF(hdr) \ ((((hdr)->FragOff0) & 0x0020) != 0) #define WINDIVERT_IPHDR_GET_DF(hdr) \ ((((hdr)->FragOff0) & 0x0040) != 0) #define WINDIVERT_IPHDR_GET_RESERVED(hdr) \ ((((hdr)->FragOff0) & 0x0080) != 0) #define WINDIVERT_IPHDR_SET_FRAGOFF(hdr, val) \ do \ { \ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0x00E0) | \ ((val) & 0xFF1F); \ } \ while (FALSE) #define WINDIVERT_IPHDR_SET_MF(hdr, val) \ do \ { \ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFDF) | \ (((val) & 0x0001) << 5); \ } \ while (FALSE) #define WINDIVERT_IPHDR_SET_DF(hdr, val) \ do \ { \ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFFBF) | \ (((val) & 0x0001) << 6); \ } \ while (FALSE) #define WINDIVERT_IPHDR_SET_RESERVED(hdr, val) \ do \ { \ (hdr)->FragOff0 = (((hdr)->FragOff0) & 0xFF7F) | \ (((val) & 0x0001) << 7); \ } \ while (FALSE) typedef struct { UINT8 TrafficClass0:4; UINT8 Version:4; UINT8 FlowLabel0:4; UINT8 TrafficClass1:4; UINT16 FlowLabel1; UINT16 Length; UINT8 NextHdr; UINT8 HopLimit; UINT32 SrcAddr[4]; UINT32 DstAddr[4]; } WINDIVERT_IPV6HDR, *PWINDIVERT_IPV6HDR; #define WINDIVERT_IPV6HDR_GET_TRAFFICCLASS(hdr) \ ((((hdr)->TrafficClass0) << 4) | ((hdr)->TrafficClass1)) #define WINDIVERT_IPV6HDR_GET_FLOWLABEL(hdr) \ ((((UINT32)(hdr)->FlowLabel0) << 16) | ((UINT32)(hdr)->FlowLabel1)) #define WINDIVERT_IPV6HDR_SET_TRAFFICCLASS(hdr, val) \ do \ { \ (hdr)->TrafficClass0 = ((UINT8)(val) >> 4); \ (hdr)->TrafficClass1 = (UINT8)(val); \ } \ while (FALSE) #define WINDIVERT_IPV6HDR_SET_FLOWLABEL(hdr, val) \ do \ { \ (hdr)->FlowLabel0 = (UINT8)((val) >> 16); \ (hdr)->FlowLabel1 = (UINT16)(val); \ } \ while (FALSE) typedef struct { UINT8 Type; UINT8 Code; UINT16 Checksum; UINT32 Body; } WINDIVERT_ICMPHDR, *PWINDIVERT_ICMPHDR; typedef struct { UINT8 Type; UINT8 Code; UINT16 Checksum; UINT32 Body; } WINDIVERT_ICMPV6HDR, *PWINDIVERT_ICMPV6HDR; typedef struct { UINT16 SrcPort; UINT16 DstPort; UINT32 SeqNum; UINT32 AckNum; UINT16 Reserved1:4; UINT16 HdrLength:4; UINT16 Fin:1; UINT16 Syn:1; UINT16 Rst:1; UINT16 Psh:1; UINT16 Ack:1; UINT16 Urg:1; UINT16 Reserved2:2; UINT16 Window; UINT16 Checksum; UINT16 UrgPtr; } WINDIVERT_TCPHDR, *PWINDIVERT_TCPHDR; typedef struct { UINT16 SrcPort; UINT16 DstPort; UINT16 Length; UINT16 Checksum; } WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR; #ifdef _MSC_VER #pragma warning(pop) #endif /* * Flags for WinDivertHelperCalcChecksums() */ #define WINDIVERT_HELPER_NO_IP_CHECKSUM 1 #define WINDIVERT_HELPER_NO_ICMP_CHECKSUM 2 #define WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM 4 #define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8 #define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16 #ifndef WINDIVERT_KERNEL /* * Hash a packet. */ WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket( __in const VOID *pPacket, __in UINT packetLen, __in UINT64 seed #ifdef __cplusplus = 0 #endif ); /* * Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet. */ WINDIVERTEXPORT BOOL WinDivertHelperParsePacket( __in const VOID *pPacket, __in UINT packetLen, __out_opt PWINDIVERT_IPHDR *ppIpHdr, __out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr, __out_opt UINT8 *pProtocol, __out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr, __out_opt PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr, __out_opt PWINDIVERT_TCPHDR *ppTcpHdr, __out_opt PWINDIVERT_UDPHDR *ppUdpHdr, __out_opt PVOID *ppData, __out_opt UINT *pDataLen, __out_opt PVOID *ppNext, __out_opt UINT *pNextLen); /* * Parse an IPv4 address. */ WINDIVERTEXPORT BOOL WinDivertHelperParseIPv4Address( __in const char *addrStr, __out_opt UINT32 *pAddr); /* * Parse an IPv6 address. */ WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address( __in const char *addrStr, __out_opt UINT32 *pAddr); /* * Format an IPv4 address. */ WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv4Address( __in UINT32 addr, __out char *buffer, __in UINT bufLen); /* * Format an IPv6 address. */ WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address( __in const UINT32 *pAddr, __out char *buffer, __in UINT bufLen); /* * Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums. */ WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums( __inout VOID *pPacket, __in UINT packetLen, __out_opt WINDIVERT_ADDRESS *pAddr, __in UINT64 flags); /* * Decrement the TTL/HopLimit. */ WINDIVERTEXPORT BOOL WinDivertHelperDecrementTTL( __inout VOID *pPacket, __in UINT packetLen); /* * Compile the given filter string. */ WINDIVERTEXPORT BOOL WinDivertHelperCompileFilter( __in const char *filter, __in WINDIVERT_LAYER layer, __out_opt char *object, __in UINT objLen, __out_opt const char **errorStr, __out_opt UINT *errorPos); /* * Evaluate the given filter string. */ WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter( __in const char *filter, __in const VOID *pPacket, __in UINT packetLen, __in const WINDIVERT_ADDRESS *pAddr); /* * Format the given filter string. */ WINDIVERTEXPORT BOOL WinDivertHelperFormatFilter( __in const char *filter, __in WINDIVERT_LAYER layer, __out char *buffer, __in UINT bufLen); /* * Byte ordering. */ WINDIVERTEXPORT UINT16 WinDivertHelperNtohs( __in UINT16 x); WINDIVERTEXPORT UINT16 WinDivertHelperHtons( __in UINT16 x); WINDIVERTEXPORT UINT32 WinDivertHelperNtohl( __in UINT32 x); WINDIVERTEXPORT UINT32 WinDivertHelperHtonl( __in UINT32 x); WINDIVERTEXPORT UINT64 WinDivertHelperNtohll( __in UINT64 x); WINDIVERTEXPORT UINT64 WinDivertHelperHtonll( __in UINT64 x); WINDIVERTEXPORT void WinDivertHelperNtohIPv6Address( __in const UINT *inAddr, __out UINT *outAddr); WINDIVERTEXPORT void WinDivertHelperHtonIPv6Address( __in const UINT *inAddr, __out UINT *outAddr); /* * Old names to be removed in the next version. */ WINDIVERTEXPORT void WinDivertHelperNtohIpv6Address( __in const UINT *inAddr, __out UINT *outAddr); WINDIVERTEXPORT void WinDivertHelperHtonIpv6Address( __in const UINT *inAddr, __out UINT *outAddr); #endif /* WINDIVERT_KERNEL */ #ifdef __cplusplus } #endif #endif /* __WINDIVERT_H */