zapret/nfq/windivert/windivert.h
2024-10-28 09:32:24 +03:00

631 lines
20 KiB
C

/*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 <windows.h>
#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 <stdint.h>
#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 */