Add an ETHERNET layer to WinDivert.

Adds a new ETHERNET layer to WinDivert.  This
layer is similar to the NETWORK layers in that
packets can be blocked/modified/injected.  This
change requires Windows 8 or newer.
This commit is contained in:
basil00
2019-12-20 09:09:57 +08:00
parent 091ffb3d49
commit b83e7413be
17 changed files with 2376 additions and 1087 deletions
+1
View File
@@ -479,6 +479,7 @@ HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer, INT16 priority,
// Parameter checking:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
case WINDIVERT_LAYER_FLOW:
+4
View File
@@ -13,8 +13,10 @@ EXPORTS
WinDivertHelperDecrementTTL
WinDivertHelperHashPacket
WinDivertHelperParsePacket
WinDivertHelperParseMACAddress
WinDivertHelperParseIPv4Address
WinDivertHelperParseIPv6Address
WinDivertHelperFormatMACAddress
WinDivertHelperFormatIPv4Address
WinDivertHelperFormatIPv6Address
WinDivertHelperCompileFilter
@@ -26,6 +28,8 @@ EXPORTS
WinDivertHelperHtonl
WinDivertHelperNtohll
WinDivertHelperHtonll
WinDivertHelperNtohMACAddress
WinDivertHelperHtonMACAddress
WinDivertHelperNtohIPv6Address
WinDivertHelperHtonIPv6Address
WinDivertHelperNtohIpv6Address
+2 -2
View File
@@ -105,8 +105,8 @@ static UINT64 WinDivertXXH64Avalanche(UINT64 h64)
* WinDivert packet hash function.
*/
static UINT64 WinDivertHashPacket(UINT64 seed,
const WINDIVERT_IPHDR *ip_header, const WINDIVERT_IPV6HDR *ipv6_header,
const WINDIVERT_ICMPHDR *icmp_header,
const WINDIVERT_ETHHDR *eth_header, const WINDIVERT_IPHDR *ip_header,
const WINDIVERT_IPV6HDR *ipv6_header, const WINDIVERT_ICMPHDR *icmp_header,
const WINDIVERT_ICMPV6HDR *icmpv6_header,
const WINDIVERT_TCPHDR *tcp_header, const WINDIVERT_UDPHDR *udp_header)
{
+386 -164
View File
@@ -143,11 +143,16 @@ typedef enum
TOKEN_PARENT_ENDPOINT_ID,
TOKEN_LAYER,
TOKEN_PRIORITY,
TOKEN_FLOW,
TOKEN_SOCKET,
TOKEN_NETWORK,
TOKEN_NETWORK_FORWARD,
TOKEN_REFLECT,
TOKEN_ETH_DST_ADDR,
TOKEN_ETH_SRC_ADDR,
TOKEN_ETH_TYPE,
TOKEN_LAYER_FLOW,
TOKEN_LAYER_SOCKET,
TOKEN_LAYER_NETWORK,
TOKEN_LAYER_NETWORK_FORWARD,
TOKEN_LAYER_REFLECT,
TOKEN_LAYER_ETHERNET,
TOKEN_EVENT_FRAME,
TOKEN_EVENT_PACKET,
TOKEN_EVENT_ESTABLISHED,
TOKEN_EVENT_DELETED,
@@ -260,10 +265,58 @@ static BOOL WinDivertCondExecFilter(PWINDIVERT_FILTER filter, UINT length,
static int WinDivertCompare128(BOOL neg_a, const UINT32 *a, BOOL neg_b,
const UINT32 *b, BOOL big);
static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
PWINDIVERT_FILTER filter, UINT *length);
WINDIVERT_LAYER layer, PWINDIVERT_FILTER filter, UINT *length);
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
WINDIVERT_LAYER layer, BOOL top_level, BOOL and);
/*
* Parse a MAC address.
*/
extern BOOL WinDivertHelperParseMACAddress(const char *str, UINT8 *addr_ptr)
{
UINT i, j;
UINT8 part;
char c;
for (i = 0; i < 6; i++)
{
part = 0;
for (j = 0; j < 2; j++)
{
c = *str++;
part <<= 4;
if (c >= '0' && c <= '9')
{
part += (UINT8)(c - '0');
}
else if (c >= 'a' && c <= 'f')
{
part += (UINT8)(c - 'a') + 10;
}
else if (c >= 'A' && c <= 'F')
{
part += (UINT8)(c - 'A') + 10;
}
else
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
}
if ((i != 5? *str != ':': *str != '\0'))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
str++;
if (addr_ptr != NULL)
{
addr_ptr[5-i] = part;
}
}
return TRUE;
}
/*
* Parse an IPv4 address.
*/
@@ -463,14 +516,14 @@ static PTOKEN_INFO WinDivertTokenLookup(PTOKEN_INFO token_info,
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
WINDIVERT_LAYER layer, PWINDIVERT_ETHHDR *ppEthHeader,
PWINDIVERT_IPHDR *ppIPHeader, PWINDIVERT_IPV6HDR *ppIPv6Header,
UINT8 *pProtocol, PWINDIVERT_ICMPHDR *ppICMPHeader,
PWINDIVERT_ICMPV6HDR *ppICMPv6Header, PWINDIVERT_TCPHDR *ppTCPHeader,
PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen,
PVOID *ppNext, UINT *pNextLen)
PWINDIVERT_UDPHDR *ppUDPHeader, PVOID *ppData, UINT *pDataLen)
{
WINDIVERT_PACKET info;
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, &info))
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, layer, &info))
{
return FALSE;
}
@@ -483,6 +536,10 @@ BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
{
*pProtocol = info.Protocol;
}
if (ppEthHeader != NULL)
{
*ppEthHeader = info.EthHeader;
}
if (ppIPHeader != NULL)
{
*ppIPHeader = info.IPHeader;
@@ -515,16 +572,6 @@ BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
{
*pDataLen = info.PayloadLength;
}
if (ppNext != NULL)
{
*ppNext = (info.Extended? (PVOID)((UINT8 *)pPacket +
(info.HeaderLength + info.PayloadLength)): NULL);
}
if (pNextLen != NULL)
{
*pNextLen = (info.Extended?
packetLen - (info.HeaderLength + info.PayloadLength): 0);
}
return TRUE;
}
@@ -536,21 +583,27 @@ static BOOL WinDivertExpandMacro(KIND kind, WINDIVERT_LAYER layer, UINT32 *val)
{
switch (kind)
{
case TOKEN_NETWORK:
case TOKEN_LAYER_ETHERNET:
*val = WINDIVERT_LAYER_ETHERNET;
return TRUE;
case TOKEN_LAYER_NETWORK:
*val = WINDIVERT_LAYER_NETWORK;
return TRUE;
case TOKEN_NETWORK_FORWARD:
case TOKEN_LAYER_NETWORK_FORWARD:
*val = WINDIVERT_LAYER_NETWORK_FORWARD;
return TRUE;
case TOKEN_FLOW:
case TOKEN_LAYER_FLOW:
*val = WINDIVERT_LAYER_FLOW;
return TRUE;
case TOKEN_SOCKET:
case TOKEN_LAYER_SOCKET:
*val = WINDIVERT_LAYER_SOCKET;
return TRUE;
case TOKEN_REFLECT:
case TOKEN_LAYER_REFLECT:
*val = WINDIVERT_LAYER_REFLECT;
return TRUE;
case TOKEN_EVENT_FRAME:
*val = WINDIVERT_EVENT_ETHERNET_FRAME;
return (layer == WINDIVERT_LAYER_ETHERNET);
case TOKEN_EVENT_PACKET:
*val = WINDIVERT_EVENT_NETWORK_PACKET;
return (layer == WINDIVERT_LAYER_NETWORK ||
@@ -619,121 +672,128 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
{
static const TOKEN_INFO token_info[] =
{
{"ACCEPT", TOKEN_EVENT_ACCEPT },
{"BIND", TOKEN_EVENT_BIND },
{"CLOSE", TOKEN_EVENT_CLOSE },
{"CONNECT", TOKEN_EVENT_CONNECT },
{"DELETED", TOKEN_EVENT_DELETED },
{"ESTABLISHED", TOKEN_EVENT_ESTABLISHED },
{"FALSE", TOKEN_MACRO_FALSE },
{"FLOW", TOKEN_FLOW },
{"ICMP", TOKEN_MACRO_ICMP },
{"ICMPV6", TOKEN_MACRO_ICMPV6 },
{"LISTEN", TOKEN_EVENT_LISTEN },
{"NETWORK", TOKEN_NETWORK },
{"NETWORK_FORWARD", TOKEN_NETWORK_FORWARD },
{"OPEN", TOKEN_EVENT_OPEN },
{"PACKET", TOKEN_EVENT_PACKET },
{"REFLECT", TOKEN_REFLECT },
{"SOCKET", TOKEN_SOCKET },
{"TCP", TOKEN_MACRO_TCP },
{"TRUE", TOKEN_MACRO_TRUE },
{"UDP", TOKEN_MACRO_UDP },
{"and", TOKEN_AND },
{"endpointId", TOKEN_ENDPOINT_ID },
{"event", TOKEN_EVENT },
{"false", TOKEN_FALSE },
{"fragment", TOKEN_FRAGMENT },
{"icmp", TOKEN_ICMP },
{"icmp.Body", TOKEN_ICMP_BODY },
{"icmp.Checksum", TOKEN_ICMP_CHECKSUM },
{"icmp.Code", TOKEN_ICMP_CODE },
{"icmp.Type", TOKEN_ICMP_TYPE },
{"icmpv6", TOKEN_ICMPV6 },
{"icmpv6.Body", TOKEN_ICMPV6_BODY },
{"icmpv6.Checksum", TOKEN_ICMPV6_CHECKSUM },
{"icmpv6.Code", TOKEN_ICMPV6_CODE },
{"icmpv6.Type", TOKEN_ICMPV6_TYPE },
{"ifIdx", TOKEN_IF_IDX },
{"impostor", TOKEN_IMPOSTOR },
{"inbound", TOKEN_INBOUND },
{"ip", TOKEN_IP },
{"ip.Checksum", TOKEN_IP_CHECKSUM },
{"ip.DF", TOKEN_IP_DF },
{"ip.DstAddr", TOKEN_IP_DST_ADDR },
{"ip.FragOff", TOKEN_IP_FRAG_OFF },
{"ip.HdrLength", TOKEN_IP_HDR_LENGTH },
{"ip.Id", TOKEN_IP_ID },
{"ip.Length", TOKEN_IP_LENGTH },
{"ip.MF", TOKEN_IP_MF },
{"ip.Protocol", TOKEN_IP_PROTOCOL },
{"ip.SrcAddr", TOKEN_IP_SRC_ADDR },
{"ip.TOS", TOKEN_IP_TOS },
{"ip.TTL", TOKEN_IP_TTL },
{"ipv6", TOKEN_IPV6 },
{"ipv6.DstAddr", TOKEN_IPV6_DST_ADDR },
{"ipv6.FlowLabel", TOKEN_IPV6_FLOW_LABEL },
{"ipv6.HopLimit", TOKEN_IPV6_HOP_LIMIT },
{"ipv6.Length", TOKEN_IPV6_LENGTH },
{"ipv6.NextHdr", TOKEN_IPV6_NEXT_HDR },
{"ipv6.SrcAddr", TOKEN_IPV6_SRC_ADDR },
{"ipv6.TrafficClass", TOKEN_IPV6_TRAFFIC_CLASS},
{"layer", TOKEN_LAYER },
{"length", TOKEN_LENGTH },
{"localAddr", TOKEN_LOCAL_ADDR },
{"localPort", TOKEN_LOCAL_PORT },
{"loopback", TOKEN_LOOPBACK },
{"not", TOKEN_NOT },
{"or", TOKEN_OR },
{"outbound", TOKEN_OUTBOUND },
{"packet", TOKEN_PACKET },
{"packet16", TOKEN_PACKET16 },
{"packet32", TOKEN_PACKET32 },
{"parentEndpointId", TOKEN_PARENT_ENDPOINT_ID},
{"priority", TOKEN_PRIORITY },
{"processId", TOKEN_PROCESS_ID },
{"protocol", TOKEN_PROTOCOL },
{"random16", TOKEN_RANDOM16 },
{"random32", TOKEN_RANDOM32 },
{"random8", TOKEN_RANDOM8 },
{"remoteAddr", TOKEN_REMOTE_ADDR },
{"remotePort", TOKEN_REMOTE_PORT },
{"subIfIdx", TOKEN_SUB_IF_IDX },
{"tcp", TOKEN_TCP },
{"tcp.Ack", TOKEN_TCP_ACK },
{"tcp.AckNum", TOKEN_TCP_ACK_NUM },
{"tcp.Checksum", TOKEN_TCP_CHECKSUM },
{"tcp.DstPort", TOKEN_TCP_DST_PORT },
{"tcp.Fin", TOKEN_TCP_FIN },
{"tcp.HdrLength", TOKEN_TCP_HDR_LENGTH },
{"tcp.Payload", TOKEN_TCP_PAYLOAD },
{"tcp.Payload16", TOKEN_TCP_PAYLOAD16 },
{"tcp.Payload32", TOKEN_TCP_PAYLOAD32 },
{"tcp.PayloadLength", TOKEN_TCP_PAYLOAD_LENGTH},
{"tcp.Psh", TOKEN_TCP_PSH },
{"tcp.Rst", TOKEN_TCP_RST },
{"tcp.SeqNum", TOKEN_TCP_SEQ_NUM },
{"tcp.SrcPort", TOKEN_TCP_SRC_PORT },
{"tcp.Syn", TOKEN_TCP_SYN },
{"tcp.Urg", TOKEN_TCP_URG },
{"tcp.UrgPtr", TOKEN_TCP_URG_PTR },
{"tcp.Window", TOKEN_TCP_WINDOW },
{"timestamp", TOKEN_TIMESTAMP },
{"true", TOKEN_TRUE },
{"udp", TOKEN_UDP },
{"udp.Checksum", TOKEN_UDP_CHECKSUM },
{"udp.DstPort", TOKEN_UDP_DST_PORT },
{"udp.Length", TOKEN_UDP_LENGTH },
{"udp.Payload", TOKEN_UDP_PAYLOAD },
{"udp.Payload16", TOKEN_UDP_PAYLOAD16 },
{"udp.Payload32", TOKEN_UDP_PAYLOAD32 },
{"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH},
{"udp.SrcPort", TOKEN_UDP_SRC_PORT },
{"zero", TOKEN_ZERO },
{"ACCEPT", TOKEN_EVENT_ACCEPT },
{"BIND", TOKEN_EVENT_BIND },
{"CLOSE", TOKEN_EVENT_CLOSE },
{"CONNECT", TOKEN_EVENT_CONNECT },
{"DELETED", TOKEN_EVENT_DELETED },
{"ESTABLISHED", TOKEN_EVENT_ESTABLISHED },
{"ETHERNET", TOKEN_LAYER_ETHERNET },
{"FALSE", TOKEN_MACRO_FALSE },
{"FRAME", TOKEN_EVENT_FRAME },
{"FLOW", TOKEN_LAYER_FLOW },
{"ICMP", TOKEN_MACRO_ICMP },
{"ICMPV6", TOKEN_MACRO_ICMPV6 },
{"LISTEN", TOKEN_EVENT_LISTEN },
{"NETWORK", TOKEN_LAYER_NETWORK },
{"NETWORK_FORWARD", TOKEN_LAYER_NETWORK_FORWARD},
{"OPEN", TOKEN_EVENT_OPEN },
{"PACKET", TOKEN_EVENT_PACKET },
{"REFLECT", TOKEN_LAYER_REFLECT },
{"SOCKET", TOKEN_LAYER_SOCKET },
{"TCP", TOKEN_MACRO_TCP },
{"TRUE", TOKEN_MACRO_TRUE },
{"UDP", TOKEN_MACRO_UDP },
{"and", TOKEN_AND },
{"b", TOKEN_BYTES },
{"endpointId", TOKEN_ENDPOINT_ID },
{"eth.DstAddr", TOKEN_ETH_DST_ADDR },
{"eth.SrcAddr", TOKEN_ETH_SRC_ADDR },
{"eth.Type", TOKEN_ETH_TYPE },
{"event", TOKEN_EVENT },
{"false", TOKEN_FALSE },
{"fragment", TOKEN_FRAGMENT },
{"icmp", TOKEN_ICMP },
{"icmp.Body", TOKEN_ICMP_BODY },
{"icmp.Checksum", TOKEN_ICMP_CHECKSUM },
{"icmp.Code", TOKEN_ICMP_CODE },
{"icmp.Type", TOKEN_ICMP_TYPE },
{"icmpv6", TOKEN_ICMPV6 },
{"icmpv6.Body", TOKEN_ICMPV6_BODY },
{"icmpv6.Checksum", TOKEN_ICMPV6_CHECKSUM },
{"icmpv6.Code", TOKEN_ICMPV6_CODE },
{"icmpv6.Type", TOKEN_ICMPV6_TYPE },
{"ifIdx", TOKEN_IF_IDX },
{"impostor", TOKEN_IMPOSTOR },
{"inbound", TOKEN_INBOUND },
{"ip", TOKEN_IP },
{"ip.Checksum", TOKEN_IP_CHECKSUM },
{"ip.DF", TOKEN_IP_DF },
{"ip.DstAddr", TOKEN_IP_DST_ADDR },
{"ip.FragOff", TOKEN_IP_FRAG_OFF },
{"ip.HdrLength", TOKEN_IP_HDR_LENGTH },
{"ip.Id", TOKEN_IP_ID },
{"ip.Length", TOKEN_IP_LENGTH },
{"ip.MF", TOKEN_IP_MF },
{"ip.Protocol", TOKEN_IP_PROTOCOL },
{"ip.SrcAddr", TOKEN_IP_SRC_ADDR },
{"ip.TOS", TOKEN_IP_TOS },
{"ip.TTL", TOKEN_IP_TTL },
{"ipv6", TOKEN_IPV6 },
{"ipv6.DstAddr", TOKEN_IPV6_DST_ADDR },
{"ipv6.FlowLabel", TOKEN_IPV6_FLOW_LABEL },
{"ipv6.HopLimit", TOKEN_IPV6_HOP_LIMIT },
{"ipv6.Length", TOKEN_IPV6_LENGTH },
{"ipv6.NextHdr", TOKEN_IPV6_NEXT_HDR },
{"ipv6.SrcAddr", TOKEN_IPV6_SRC_ADDR },
{"ipv6.TrafficClass", TOKEN_IPV6_TRAFFIC_CLASS },
{"layer", TOKEN_LAYER },
{"length", TOKEN_LENGTH },
{"localAddr", TOKEN_LOCAL_ADDR },
{"localPort", TOKEN_LOCAL_PORT },
{"loopback", TOKEN_LOOPBACK },
{"not", TOKEN_NOT },
{"or", TOKEN_OR },
{"outbound", TOKEN_OUTBOUND },
{"packet", TOKEN_PACKET },
{"packet16", TOKEN_PACKET16 },
{"packet32", TOKEN_PACKET32 },
{"parentEndpointId", TOKEN_PARENT_ENDPOINT_ID },
{"priority", TOKEN_PRIORITY },
{"processId", TOKEN_PROCESS_ID },
{"protocol", TOKEN_PROTOCOL },
{"random16", TOKEN_RANDOM16 },
{"random32", TOKEN_RANDOM32 },
{"random8", TOKEN_RANDOM8 },
{"remoteAddr", TOKEN_REMOTE_ADDR },
{"remotePort", TOKEN_REMOTE_PORT },
{"subIfIdx", TOKEN_SUB_IF_IDX },
{"tcp", TOKEN_TCP },
{"tcp.Ack", TOKEN_TCP_ACK },
{"tcp.AckNum", TOKEN_TCP_ACK_NUM },
{"tcp.Checksum", TOKEN_TCP_CHECKSUM },
{"tcp.DstPort", TOKEN_TCP_DST_PORT },
{"tcp.Fin", TOKEN_TCP_FIN },
{"tcp.HdrLength", TOKEN_TCP_HDR_LENGTH },
{"tcp.Payload", TOKEN_TCP_PAYLOAD },
{"tcp.Payload16", TOKEN_TCP_PAYLOAD16 },
{"tcp.Payload32", TOKEN_TCP_PAYLOAD32 },
{"tcp.PayloadLength", TOKEN_TCP_PAYLOAD_LENGTH },
{"tcp.Psh", TOKEN_TCP_PSH },
{"tcp.Rst", TOKEN_TCP_RST },
{"tcp.SeqNum", TOKEN_TCP_SEQ_NUM },
{"tcp.SrcPort", TOKEN_TCP_SRC_PORT },
{"tcp.Syn", TOKEN_TCP_SYN },
{"tcp.Urg", TOKEN_TCP_URG },
{"tcp.UrgPtr", TOKEN_TCP_URG_PTR },
{"tcp.Window", TOKEN_TCP_WINDOW },
{"timestamp", TOKEN_TIMESTAMP },
{"true", TOKEN_TRUE },
{"udp", TOKEN_UDP },
{"udp.Checksum", TOKEN_UDP_CHECKSUM },
{"udp.DstPort", TOKEN_UDP_DST_PORT },
{"udp.Length", TOKEN_UDP_LENGTH },
{"udp.Payload", TOKEN_UDP_PAYLOAD },
{"udp.Payload16", TOKEN_UDP_PAYLOAD16 },
{"udp.Payload32", TOKEN_UDP_PAYLOAD32 },
{"udp.PayloadLength", TOKEN_UDP_PAYLOAD_LENGTH },
{"udp.SrcPort", TOKEN_UDP_SRC_PORT },
{"zero", TOKEN_ZERO },
};
TOKEN_INFO *result;
char c;
char token[TOKEN_MAXLEN];
UINT8 eth_addr[6];
UINT32 field;
UINT i = 0, j;
UINT tp = 0;
@@ -890,13 +950,6 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
continue;
}
// Check for 'b':
if (token[0] == 'b' && token[1] == '\0')
{
tokens[tp].kind = TOKEN_BYTES;
continue;
}
// Check for base 10 number:
if (WinDivertAToI(token, &end, num, sizeof(num)/sizeof(num[0])))
{
@@ -928,6 +981,22 @@ static ERROR WinDivertTokenizeFilter(const char *filter, WINDIVERT_LAYER layer,
continue;
}
// Check for MAC address:
if (WinDivertHelperParseMACAddress(token, eth_addr))
{
tokens[tp].val[0] =
(UINT32)eth_addr[0] |
((UINT32)eth_addr[1] << 8) |
((UINT32)eth_addr[2] << 16) |
((UINT32)eth_addr[3] << 24);
tokens[tp].val[1] =
(UINT32)eth_addr[4] |
((UINT32)eth_addr[5] << 8);
tokens[tp].kind = TOKEN_NUMBER;
tp++;
continue;
}
// Check for IPv4 address:
if (WinDivertHelperParseIPv4Address(token, tokens[tp].val))
{
@@ -1042,6 +1111,9 @@ static PEXPR WinDivertMakeVar(KIND kind, PERROR error)
{{{0}}, TOKEN_PARENT_ENDPOINT_ID},
{{{0}}, TOKEN_LAYER},
{{{0}}, TOKEN_PRIORITY},
{{{0}}, TOKEN_ETH_DST_ADDR},
{{{0}}, TOKEN_ETH_SRC_ADDR},
{{{0}}, TOKEN_ETH_TYPE},
};
// Binary search:
@@ -1200,6 +1272,9 @@ static PEXPR WinDivertParseTest(HANDLE pool, TOKEN *toks, UINT *i, PERROR error)
case TOKEN_PARENT_ENDPOINT_ID:
case TOKEN_LENGTH:
case TOKEN_LAYER:
case TOKEN_ETH_DST_ADDR:
case TOKEN_ETH_SRC_ADDR:
case TOKEN_ETH_TYPE:
case TOKEN_IP_HDR_LENGTH:
case TOKEN_IP_TOS:
case TOKEN_IP_LENGTH:
@@ -1554,6 +1629,7 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
case TOKEN_IP_FRAG_OFF:
lb[0] = 0; ub[0] = 0x1FFF;
break;
case TOKEN_ETH_TYPE:
case TOKEN_IP_TOS:
case TOKEN_IP_LENGTH:
case TOKEN_IP_ID:
@@ -1607,6 +1683,12 @@ static BOOL WinDivertEvalTest(PEXPR test, BOOL *res)
ub[1] = 0x7FFFFFFF;
neg_lb = TRUE;
break;
case TOKEN_ETH_DST_ADDR:
case TOKEN_ETH_SRC_ADDR:
lb[0] = lb[1] = 0;
ub[0] = 0xFFFFFFFF;
ub[1] = 0xFFFF;
break;
case TOKEN_ENDPOINT_ID:
case TOKEN_PARENT_ENDPOINT_ID:
lb[0] = lb[1] = 0;
@@ -1831,6 +1913,12 @@ static UINT32 WinDivertKindToField(KIND kind)
return WINDIVERT_FILTER_FIELD_TCP;
case TOKEN_UDP:
return WINDIVERT_FILTER_FIELD_UDP;
case TOKEN_ETH_DST_ADDR:
return WINDIVERT_FILTER_FIELD_ETH_DST_ADDR;
case TOKEN_ETH_SRC_ADDR:
return WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR;
case TOKEN_ETH_TYPE:
return WINDIVERT_FILTER_FIELD_ETH_TYPE;
case TOKEN_IP_HDR_LENGTH:
return WINDIVERT_FILTER_FIELD_IP_HDRLENGTH;
case TOKEN_IP_TOS:
@@ -2054,7 +2142,8 @@ static UINT64 WinDivertAnalyzeFilter(WINDIVERT_LAYER layer,
return 0;
}
if (layer == WINDIVERT_LAYER_NETWORK ||
if (layer == WINDIVERT_LAYER_ETHERNET ||
layer == WINDIVERT_LAYER_NETWORK ||
layer == WINDIVERT_LAYER_NETWORK_FORWARD)
{
// Inbound?
@@ -2078,7 +2167,8 @@ static UINT64 WinDivertAnalyzeFilter(WINDIVERT_LAYER layer,
flags |= (result? WINDIVERT_FILTER_FLAG_OUTBOUND: 0);
}
if (layer != WINDIVERT_LAYER_REFLECT)
if (layer != WINDIVERT_LAYER_ETHERNET &&
layer != WINDIVERT_LAYER_REFLECT)
{
// IPv4?
result = WinDivertCondExecFilter(filter, length,
@@ -2258,7 +2348,7 @@ static ERROR WinDivertCompileFilter(const char *filter, HANDLE pool,
stream.max = UINT_MAX;
stream.overflow = FALSE;
if (!WinDivertDeserializeFilter(&stream, object, obj_len))
if (!WinDivertDeserializeFilter(&stream, layer, object, obj_len))
{
SetLastError(ERROR_INVALID_PARAMETER);
return MAKE_ERROR(WINDIVERT_ERROR_BAD_OBJECT, 0);
@@ -2434,17 +2524,19 @@ static BOOL WinDivertGetData(const VOID *packet, UINT packet_len, INT min,
* Evaluate the given filter with the given packet as input.
*/
BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
UINT packet_len, const WINDIVERT_ADDRESS *addr)
UINT packet_len, WINDIVERT_LAYER layer, const WINDIVERT_ADDRESS *addr)
{
ERROR err;
DWORD error;
WINDIVERT_PACKET info;
PWINDIVERT_ETHHDR eth_header = NULL;
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
PWINDIVERT_ICMPHDR icmp_header = NULL;
PWINDIVERT_ICMPV6HDR icmpv6_header = NULL;
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
const WINDIVERT_DATA_ETHERNET *ethernet_data = NULL;
const WINDIVERT_DATA_NETWORK *network_data = NULL;
const WINDIVERT_DATA_FLOW *flow_data = NULL;
const WINDIVERT_DATA_SOCKET *socket_data = NULL;
@@ -2462,8 +2554,9 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch (addr->Layer)
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (packet == NULL)
@@ -2471,12 +2564,14 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!WinDivertHelperParsePacketEx((PVOID)packet, packet_len, &info))
if (!WinDivertHelperParsePacketEx((PVOID)packet, packet_len,
layer, &info))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
protocol = info.Protocol;
eth_header = info.EthHeader;
ip_header = info.IPHeader;
ipv6_header = info.IPv6Header;
icmp_header = info.ICMPHeader;
@@ -2507,8 +2602,11 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
switch (addr->Layer)
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
ethernet_data = &addr->Ethernet;
break;
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
network_data = &addr->Network;
@@ -2539,7 +2637,7 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
{
goto WinDivertHelperEvalFilterError;
}
err = WinDivertCompileFilter(filter, pool, addr->Layer, object, &obj_len);
err = WinDivertCompileFilter(filter, pool, layer, object, &obj_len);
if (IS_ERROR(err))
{
SetLastError(ERROR_INVALID_PARAMETER);
@@ -2548,7 +2646,7 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
result = WinDivertExecuteFilter(
object,
addr->Layer,
layer,
addr->Timestamp,
addr->Event,
(addr->IPv6 != 0? FALSE: TRUE),
@@ -2556,10 +2654,12 @@ BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
(addr->Loopback != 0? TRUE: FALSE),
(addr->Impostor != 0? TRUE: FALSE),
fragment,
ethernet_data,
network_data,
flow_data,
socket_data,
reflect_data,
eth_header,
ip_header,
ipv6_header,
icmp_header,
@@ -2720,7 +2820,7 @@ static BOOL WinDivertDeserializeLabel(PWINDIVERT_STREAM stream, UINT16 *label)
* Deserialize a test.
*/
static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream,
PWINDIVERT_FILTER filter)
WINDIVERT_LAYER layer, PWINDIVERT_FILTER filter)
{
UINT32 val;
UINT16 success, failure;
@@ -2732,7 +2832,7 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream,
}
if (!WinDivertDeserializeNumber(stream, 2, &val) ||
val > WINDIVERT_FILTER_FIELD_MAX)
!WinDivertValidateField(layer, val))
{
return FALSE;
}
@@ -2773,6 +2873,8 @@ static BOOL WinDivertDeserializeTest(PWINDIVERT_STREAM stream,
case WINDIVERT_FILTER_FIELD_ENDPOINTID:
case WINDIVERT_FILTER_FIELD_PARENTENDPOINTID:
case WINDIVERT_FILTER_FIELD_TIMESTAMP:
case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR:
case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR:
if (!WinDivertDeserializeNumber(stream, 7, &filter->arg[1]))
{
return FALSE;
@@ -2854,7 +2956,7 @@ static BOOL WinDivertDeserializeFilterHeader(PWINDIVERT_STREAM stream,
* Deserialize a filter.
*/
static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
PWINDIVERT_FILTER filter, UINT *length)
WINDIVERT_LAYER layer, PWINDIVERT_FILTER filter, UINT *length)
{
UINT i;
@@ -2865,7 +2967,7 @@ static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
for (i = 0; i < *length; i++)
{
if (!WinDivertDeserializeTest(stream, filter + i))
if (!WinDivertDeserializeTest(stream, layer, filter + i))
{
return FALSE;
}
@@ -2967,6 +3069,12 @@ static PEXPR WinDivertDecompileTest(HANDLE pool, PWINDIVERT_FILTER test)
kind = TOKEN_UDP; break;
case WINDIVERT_FILTER_FIELD_ICMPV6:
kind = TOKEN_ICMPV6; break;
case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR:
kind = TOKEN_ETH_DST_ADDR; break;
case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR:
kind = TOKEN_ETH_SRC_ADDR; break;
case WINDIVERT_FILTER_FIELD_ETH_TYPE:
kind = TOKEN_ETH_TYPE; break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
kind = TOKEN_IP_HDR_LENGTH; break;
case WINDIVERT_FILTER_FIELD_IP_TOS:
@@ -3482,6 +3590,36 @@ static void WinDivertFormatHexNumber(PWINDIVERT_STREAM stream,
}
}
/*
* Format a MAC address.
*/
static void WinDivertFormatMacAddr(PWINDIVERT_STREAM stream, const UINT8 *addr)
{
UINT8 part, dig;
INT i, j;
for (i = 0; i < 6; i++)
{
part = addr[5-i];
for (j = 0; j < 2; j++)
{
dig = (j == 0? part >> 4: part & 0xF);
if (dig <= 9)
{
WinDivertPutChar(stream, '0' + dig);
}
else
{
WinDivertPutChar(stream, 'a' + (dig - 10));
}
}
if (i != 5)
{
WinDivertPutChar(stream, ':');
}
}
}
/*
* Format an IPv4 address.
*/
@@ -3548,6 +3686,27 @@ static void WinDivertFormatIPv6Addr(PWINDIVERT_STREAM stream,
}
}
/*
* Format a MAC address.
*/
extern BOOL WinDivertHelperFormatMACAddress(const UINT8 *addr, char *buffer,
UINT bufLen)
{
WINDIVERT_STREAM stream;
stream.data = buffer;
stream.pos = 0;
stream.max = bufLen;
stream.overflow = FALSE;
WinDivertFormatMacAddr(&stream, addr);
WinDivertPutNul(&stream);
if (stream.overflow)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
return TRUE;
}
/*
* Format an IPv4 address.
*/
@@ -3596,8 +3755,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
WINDIVERT_LAYER layer)
{
PEXPR field = expr->arg[0], val = expr->arg[1];
BOOL is_ipv4_addr = FALSE, is_ipv6_addr = FALSE, is_layer = FALSE,
is_event = FALSE, is_hex = FALSE;
BOOL is_eth_addr = FALSE, is_ipv4_addr = FALSE, is_ipv6_addr = FALSE,
is_layer = FALSE, is_event = FALSE, is_hex = FALSE;
switch (field->kind)
{
@@ -3642,8 +3801,20 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
break;
}
break;
case TOKEN_ETH_SRC_ADDR:
case TOKEN_ETH_DST_ADDR:
if (val->val[2] != 0 || val->val[3] != 0 || val->val[1] > 0xFFFF)
{
break;
}
is_eth_addr = TRUE;
break;
case TOKEN_IP_SRC_ADDR:
case TOKEN_IP_DST_ADDR:
if (val->val[2] != 0 || val->val[3] != 0 || val->val[1] != 0xFFFF)
{
break;
}
is_ipv4_addr = TRUE;
break;
case TOKEN_IPV6_SRC_ADDR:
@@ -3673,6 +3844,7 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
case TOKEN_UDP_PAYLOAD32:
case TOKEN_ICMP_CHECKSUM:
case TOKEN_ICMPV6_CHECKSUM:
case TOKEN_ETH_TYPE:
is_hex = TRUE;
break;
default:
@@ -3700,7 +3872,18 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
{
WinDivertPutChar(stream, '-');
}
if (is_ipv4_addr)
if (is_eth_addr)
{
UINT8 eth_addr[6];
eth_addr[0] = (UINT8)val->val[0];
eth_addr[1] = (UINT8)(val->val[0] >> 8);
eth_addr[2] = (UINT8)(val->val[0] >> 16);
eth_addr[3] = (UINT8)(val->val[0] >> 24);
eth_addr[4] = (UINT8)val->val[1];
eth_addr[5] = (UINT8)(val->val[1] >> 8);
WinDivertFormatMacAddr(stream, eth_addr);
}
else if (is_ipv4_addr)
{
WinDivertFormatIPv4Addr(stream, val->val[0]);
}
@@ -3712,6 +3895,8 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
{
switch (val->val[0])
{
case WINDIVERT_LAYER_ETHERNET:
WinDivertPutString(stream, "ETHERNET"); break;
case WINDIVERT_LAYER_NETWORK:
WinDivertPutString(stream, "NETWORK"); break;
case WINDIVERT_LAYER_NETWORK_FORWARD:
@@ -3730,6 +3915,16 @@ static void WinDivertFormatTestExpr(PWINDIVERT_STREAM stream, PEXPR expr,
{
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
if (val->val[0] == WINDIVERT_EVENT_ETHERNET_FRAME)
{
WinDivertPutString(stream, "FRAME");
}
else
{
WinDivertFormatDecNumber32(stream, val->val[0]);
}
break;
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (val->val[0] == WINDIVERT_EVENT_NETWORK_PACKET)
@@ -3920,6 +4115,12 @@ static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
WinDivertPutString(stream, "udp"); return;
case TOKEN_ICMPV6:
WinDivertPutString(stream, "icmpv6"); return;
case TOKEN_ETH_DST_ADDR:
WinDivertPutString(stream, "eth.DstAddr"); return;
case TOKEN_ETH_SRC_ADDR:
WinDivertPutString(stream, "eth.SrcAddr"); return;
case TOKEN_ETH_TYPE:
WinDivertPutString(stream, "eth.Type"); return;
case TOKEN_IP_HDR_LENGTH:
WinDivertPutString(stream, "ip.HdrLength"); return;
case TOKEN_IP_TOS:
@@ -4171,8 +4372,9 @@ WinDivertHelperFormatFilterError:
* WinDivert packet hash function.
*/
UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
UINT64 seed)
WINDIVERT_LAYER layer, UINT64 seed)
{
PWINDIVERT_ETHHDR eth_header = NULL;
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
PWINDIVERT_ICMPHDR icmp_header = NULL;
@@ -4180,14 +4382,14 @@ UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, &ip_header,
&ipv6_header, NULL, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, NULL, NULL, NULL))
if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, layer,
&eth_header, &ip_header, &ipv6_header, NULL, &icmp_header,
&icmpv6_header, &tcp_header, &udp_header, NULL, NULL))
{
return 0;
}
return WinDivertHashPacket(seed, ip_header, ipv6_header, icmp_header,
icmpv6_header, tcp_header, udp_header);
return WinDivertHashPacket(seed, eth_header, ip_header, ipv6_header,
icmp_header, icmpv6_header, tcp_header, udp_header);
}
/*
@@ -4217,6 +4419,26 @@ UINT64 WinDivertHelperHtonll(UINT64 x)
{
return BYTESWAP64(x);
}
static void WinDivertByteSwap48(const UINT8 *inAddr, UINT8 *outAddr)
{
UINT8 tmp[6], i; // tmp[] allows overlapping inAddr/outAddr
for (i = 0; i < 6; i++)
{
tmp[5-i] = inAddr[i];
}
for (i = 0; i < 6; i++)
{
outAddr[i] = tmp[i];
}
}
extern void WinDivertHelperNtohMACAddress(const UINT8 *inAddr, UINT8 *outAddr)
{
WinDivertByteSwap48(inAddr, outAddr);
}
extern void WinDivertHelperHtonMACAddress(const UINT8 *inAddr, UINT8 *outAddr)
{
WinDivertByteSwap48(inAddr, outAddr);
}
static void WinDivertByteSwap128(const UINT *inAddr, UINT *outAddr)
{
UINT32 tmp[4], i; // tmp[] allows overlapping inAddr/outAddr
+407 -216
View File
@@ -45,6 +45,13 @@
#define BYTESWAP32(x) \
((((x) >> 24) & 0x000000FFu) | (((x) >> 8) & 0x0000FF00u) | \
(((x) << 8) & 0x00FF0000u) | (((x) << 24) & 0xFF000000u))
#define BYTESWAP48(x) \
((((x) >> 40) & 0x0000000000FF0000ull) | \
(((x) >> 24) & 0x00000000FF000000ull) | \
(((x) >> 8) & 0x000000FF00000000ull) | \
(((x) << 8) & 0x0000FF0000000000ull) | \
(((x) << 24) & 0x00FF000000000000ull) | \
(((x) << 40) & 0xFF00000000000000ull))
#define BYTESWAP64(x) \
((((x) >> 56) & 0x00000000000000FFull) | \
(((x) >> 40) & 0x000000000000FF00ull) | \
@@ -58,6 +65,11 @@
#define htons(x) BYTESWAP16(x)
#define ntohl(x) BYTESWAP32(x)
#define htonl(x) BYTESWAP32(x)
#define ntohl48(x) BYTESWAP48(x)
#define htonl48(x) BYTESWAP48(x)
#define ETHERTYPE_IP 0x0800
#define ETHERTYPE_IPV6 0x86DD
/*
* Layer flags shorthand.
@@ -68,32 +80,46 @@
#define WINDIVERT_LAYER_FLAG_FLOW (1 << WINDIVERT_LAYER_FLOW)
#define WINDIVERT_LAYER_FLAG_SOCKET (1 << WINDIVERT_LAYER_SOCKET)
#define WINDIVERT_LAYER_FLAG_REFLECT (1 << WINDIVERT_LAYER_REFLECT)
#define LNMFSR (WINDIVERT_LAYER_FLAG_NETWORK | \
#define WINDIVERT_LAYER_FLAG_ETHERNET (1 << WINDIVERT_LAYER_ETHERNET)
#define LENMFSR (WINDIVERT_LAYER_FLAG_ETHERNET | \
WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \
WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET | \
WINDIVERT_LAYER_FLAG_REFLECT)
#define LNMFS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
#define LENMFS_ (WINDIVERT_LAYER_FLAG_ETHERNET | \
WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD | \
WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET)
#define L__F_R (WINDIVERT_LAYER_FLAG_FLOW | \
#define LEN_F__ (WINDIVERT_LAYER_FLAG_ETHERNET | \
WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_FLOW)
#define L___F_R (WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_REFLECT)
#define LN_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
#define LEN_FS_ (WINDIVERT_LAYER_FLAG_ETHERNET | \
WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET)
#define L__FS_ (WINDIVERT_LAYER_FLAG_FLOW | \
#define L_N_FS_ (WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET)
#define L___SR (WINDIVERT_LAYER_FLAG_SOCKET | \
#define L___FS_ (WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET)
#define L____SR (WINDIVERT_LAYER_FLAG_SOCKET | \
WINDIVERT_LAYER_FLAG_REFLECT)
#define L__FSR (WINDIVERT_LAYER_FLAG_FLOW | \
#define L___FSR (WINDIVERT_LAYER_FLAG_FLOW | \
WINDIVERT_LAYER_FLAG_SOCKET | \
WINDIVERT_LAYER_FLAG_REFLECT)
#define LNM___ (WINDIVERT_LAYER_FLAG_NETWORK | \
#define LENM___ (WINDIVERT_LAYER_FLAG_ETHERNET | \
WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD)
#define L__F__ WINDIVERT_LAYER_FLAG_FLOW
#define L___S_ WINDIVERT_LAYER_FLAG_SOCKET
#define L____R WINDIVERT_LAYER_FLAG_REFLECT
#define L_NM___ (WINDIVERT_LAYER_FLAG_NETWORK | \
WINDIVERT_LAYER_FLAG_NETWORK_FORWARD)
#define LE_____ WINDIVERT_LAYER_FLAG_ETHERNET
#define L___F__ WINDIVERT_LAYER_FLAG_FLOW
#define L____S_ WINDIVERT_LAYER_FLAG_SOCKET
#define L_____R WINDIVERT_LAYER_FLAG_REFLECT
#if defined(WIN32) && defined(_MSC_VER)
#pragma intrinsic(__emulu)
@@ -161,6 +187,7 @@ typedef struct
UINT32 Truncated:1;
UINT32 Extended:1;
UINT32 Reserved1:6;
PWINDIVERT_ETHHDR EthHeader;
PWINDIVERT_IPHDR IPHeader;
PWINDIVERT_IPV6HDR IPv6Header;
PWINDIVERT_ICMPHDR ICMPHeader;
@@ -360,9 +387,10 @@ static void WinDivertSerializeFilter(PWINDIVERT_STREAM stream,
/*
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
PWINDIVERT_PACKET pInfo)
static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket,
UINT packetLen, WINDIVERT_LAYER layer, PWINDIVERT_PACKET pInfo)
{
PWINDIVERT_ETHHDR eth_header = NULL;
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
PWINDIVERT_ICMPHDR icmp_header = NULL;
@@ -370,109 +398,168 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
PWINDIVERT_IPV6FRAGHDR frag_header;
UINT8 protocol = 0;
UINT8 ip_protocol = 0;
UINT8 *data = NULL;
UINT packet_len, total_len, header_len, data_len = 0, frag_off = 0;
BOOL MF = FALSE, fragment = FALSE, is_ext_header;
UINT ip_packet_len = 0, ip_total_len = 0, ip_header_len = 0,
trans_header_len, header_len = 0, data_len, frag_off = 0;
BOOL ipv4 = FALSE, MF = FALSE, fragment = FALSE, is_ext_header;
if (pPacket == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
if (pPacket == NULL)
{
return FALSE;
}
data = (UINT8 *)pPacket;
data_len = packetLen;
ip_header = (PWINDIVERT_IPHDR)data;
switch (ip_header->Version)
switch (layer)
{
case 4:
if (packetLen < sizeof(WINDIVERT_IPHDR) ||
ip_header->HdrLength < 5)
case WINDIVERT_LAYER_ETHERNET:
if (data_len < sizeof(WINDIVERT_ETHHDR))
{
return FALSE;
}
total_len = (UINT)ntohs(ip_header->Length);
protocol = ip_header->Protocol;
header_len = ip_header->HdrLength * sizeof(UINT32);
if (total_len < header_len || packetLen < header_len)
eth_header = (PWINDIVERT_ETHHDR)data;
data = (PVOID)(eth_header + 1);
data_len -= sizeof(WINDIVERT_ETHHDR);
header_len = sizeof(WINDIVERT_ETHHDR);
switch (ntohs(eth_header->Type))
{
return FALSE;
}
frag_off = ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header));
MF = (WINDIVERT_IPHDR_GET_MF(ip_header) != 0);
fragment = (MF || frag_off != 0);
packet_len = (total_len < packetLen? total_len: packetLen);
data += header_len;
data_len = packet_len - header_len;
break;
case 6:
ip_header = NULL;
ipv6_header = (PWINDIVERT_IPV6HDR)data;
if (packetLen < sizeof(WINDIVERT_IPV6HDR))
{
return FALSE;
}
protocol = ipv6_header->NextHdr;
total_len = (UINT)ntohs(ipv6_header->Length) +
sizeof(WINDIVERT_IPV6HDR);
packet_len = (total_len < packetLen? total_len: packetLen);
data += sizeof(WINDIVERT_IPV6HDR);
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
while (frag_off == 0 && data_len >= 2)
{
header_len = (UINT)data[1];
is_ext_header = TRUE;
switch (protocol)
{
case IPPROTO_FRAGMENT:
header_len = 8;
if (fragment || data_len < header_len)
{
is_ext_header = FALSE;
break;
}
frag_header = (PWINDIVERT_IPV6FRAGHDR)data;
frag_off = ntohs(
WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(frag_header));
MF = WINDIVERT_IPV6FRAGHDR_GET_MF(frag_header);
fragment = TRUE;
break;
case IPPROTO_AH:
header_len += 2;
header_len *= 4;
break;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_MH:
header_len++;
header_len *= 8;
break;
default:
is_ext_header = FALSE;
break;
}
if (!is_ext_header || data_len < header_len)
{
case ETHERTYPE_IP:
if (data_len < sizeof(WINDIVERT_IPHDR))
{
goto WinDivertHelperParsePacketExit;
}
ipv4 = TRUE;
break;
}
protocol = data[0];
data += header_len;
data_len -= header_len;
case ETHERTYPE_IPV6:
if (data_len < sizeof(WINDIVERT_IPV6HDR))
{
goto WinDivertHelperParsePacketExit;
}
break;
default:
goto WinDivertHelperParsePacketExit;
}
ip_packet_len = data_len;
break;
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (data_len < sizeof(WINDIVERT_IPHDR))
{
return FALSE;
}
switch (((PWINDIVERT_IPHDR)data)->Version)
{
case 4:
ipv4 = TRUE;
break;
case 6:
break;
default:
return FALSE;
}
ip_packet_len = packetLen;
break;
default:
return FALSE;
}
if (ipv4)
{
ip_header = (PWINDIVERT_IPHDR)data;
if (ip_header->HdrLength < 5)
{
WinDivertHelperParsePacketIPError:
if (eth_header == NULL)
{
return FALSE;
}
goto WinDivertHelperParsePacketExit;
}
ip_total_len = (UINT)ntohs(ip_header->Length);
ip_protocol = ip_header->Protocol;
ip_header_len = ip_header->HdrLength * sizeof(UINT32);
if (ip_total_len < ip_header_len || ip_packet_len < ip_header_len)
{
goto WinDivertHelperParsePacketIPError;
}
frag_off = ntohs(WINDIVERT_IPHDR_GET_FRAGOFF(ip_header));
MF = (WINDIVERT_IPHDR_GET_MF(ip_header) != 0);
fragment = (MF || frag_off != 0);
ip_packet_len =
(ip_total_len < ip_packet_len? ip_total_len: ip_packet_len);
data += ip_header_len;
data_len = ip_packet_len - ip_header_len;
header_len += ip_header_len;
}
else
{
if (data_len < sizeof(WINDIVERT_IPV6HDR))
{
goto WinDivertHelperParsePacketIPError;
}
ipv6_header = (PWINDIVERT_IPV6HDR)data;
ip_protocol = ipv6_header->NextHdr;
ip_total_len = (UINT)ntohs(ipv6_header->Length) +
sizeof(WINDIVERT_IPV6HDR);
ip_packet_len =
(ip_total_len < ip_packet_len? ip_total_len: ip_packet_len);
data += sizeof(WINDIVERT_IPV6HDR);
data_len = ip_packet_len - sizeof(WINDIVERT_IPV6HDR);
header_len += ip_header_len;
while (frag_off == 0 && data_len >= 2)
{
ip_header_len = (UINT)data[1];
is_ext_header = TRUE;
switch (ip_protocol)
{
case IPPROTO_FRAGMENT:
ip_header_len = 8;
if (fragment || data_len < ip_header_len)
{
is_ext_header = FALSE;
break;
}
frag_header = (PWINDIVERT_IPV6FRAGHDR)data;
frag_off = ntohs(
WINDIVERT_IPV6FRAGHDR_GET_FRAGOFF(frag_header));
MF = WINDIVERT_IPV6FRAGHDR_GET_MF(frag_header);
fragment = TRUE;
break;
case IPPROTO_AH:
ip_header_len += 2;
ip_header_len *= 4;
break;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
case IPPROTO_ROUTING:
case IPPROTO_MH:
ip_header_len++;
ip_header_len *= 8;
break;
default:
is_ext_header = FALSE;
break;
}
if (!is_ext_header || data_len < ip_header_len)
{
break;
}
ip_protocol = data[0];
data += ip_header_len;
data_len -= ip_header_len;
header_len += ip_header_len;
}
}
if (frag_off != 0)
{
goto WinDivertHelperParsePacketExit;
}
switch (protocol)
switch (ip_protocol)
{
case IPPROTO_TCP:
tcp_header = (PWINDIVERT_TCPHDR)data;
@@ -482,8 +569,9 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
tcp_header = NULL;
goto WinDivertHelperParsePacketExit;
}
header_len = tcp_header->HdrLength * sizeof(UINT32);
header_len = (header_len > data_len? data_len: header_len);
trans_header_len = tcp_header->HdrLength * sizeof(UINT32);
trans_header_len =
(trans_header_len > data_len? data_len: trans_header_len);
break;
case IPPROTO_UDP:
@@ -492,7 +580,7 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
goto WinDivertHelperParsePacketExit;
}
udp_header = (PWINDIVERT_UDPHDR)data;
header_len = sizeof(WINDIVERT_UDPHDR);
trans_header_len = sizeof(WINDIVERT_UDPHDR);
break;
case IPPROTO_ICMP:
@@ -502,7 +590,7 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
goto WinDivertHelperParsePacketExit;
}
icmp_header = (PWINDIVERT_ICMPHDR)data;
header_len = sizeof(WINDIVERT_ICMPHDR);
trans_header_len = sizeof(WINDIVERT_ICMPHDR);
break;
case IPPROTO_ICMPV6:
@@ -512,14 +600,15 @@ static BOOL WinDivertHelperParsePacketEx(const VOID *pPacket, UINT packetLen,
goto WinDivertHelperParsePacketExit;
}
icmpv6_header = (PWINDIVERT_ICMPV6HDR)data;
header_len = sizeof(WINDIVERT_ICMPV6HDR);
trans_header_len = sizeof(WINDIVERT_ICMPV6HDR);
break;
default:
goto WinDivertHelperParsePacketExit;
}
data += header_len;
data_len -= header_len;
data += trans_header_len;
data_len -= trans_header_len;
header_len += trans_header_len;
WinDivertHelperParsePacketExit:
if (pInfo == NULL)
@@ -527,13 +616,14 @@ WinDivertHelperParsePacketExit:
return TRUE;
}
data = (data_len == 0? NULL: data);
pInfo->Protocol = (UINT32)protocol;
pInfo->Protocol = (UINT32)ip_protocol;
pInfo->Fragment = (fragment? 1: 0);
pInfo->MF = (MF? 1: 0);
pInfo->FragOff = (UINT32)frag_off;
pInfo->Truncated = (total_len > packetLen? 1: 0);
pInfo->Extended = (total_len < packetLen? 1: 0);
pInfo->Truncated = (ip_total_len > ip_packet_len? 1: 0);
pInfo->Extended = (ip_total_len < ip_packet_len? 1: 0);
pInfo->Reserved1 = 0;
pInfo->EthHeader = eth_header;
pInfo->IPHeader = ip_header;
pInfo->IPv6Header = ipv6_header;
pInfo->ICMPHeader = icmp_header;
@@ -541,7 +631,7 @@ WinDivertHelperParsePacketExit:
pInfo->TCPHeader = tcp_header;
pInfo->UDPHeader = udp_header;
pInfo->Payload = data;
pInfo->HeaderLength = (UINT32)(packet_len - data_len);
pInfo->HeaderLength = (UINT32)header_len;
pInfo->PayloadLength = (UINT32)data_len;
return TRUE;
}
@@ -550,7 +640,7 @@ WinDivertHelperParsePacketExit:
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
*/
BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
WINDIVERT_ADDRESS *pAddr, UINT64 flags)
WINDIVERT_LAYER layer, WINDIVERT_ADDRESS *pAddr, UINT64 flags)
{
UINT8 pseudo_header[
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
@@ -565,7 +655,7 @@ BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
UINT payload_len, checksum_len;
BOOL truncated;
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, &info))
if (!WinDivertHelperParsePacketEx(pPacket, packetLen, layer, &info))
{
return FALSE;
}
@@ -754,53 +844,104 @@ static UINT16 WinDivertCalcChecksum(PVOID pseudo_header,
/*
* Decrement the TTL.
*/
BOOL WinDivertHelperDecrementTTL(VOID *packet, UINT packetLen)
BOOL WinDivertHelperDecrementTTL(VOID *packet, UINT packetLen,
WINDIVERT_LAYER layer)
{
PWINDIVERT_ETHHDR eth_header;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_IPV6HDR ipv6_header;
BOOL is_ipv6 = FALSE;
if (packet == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
if (packet == NULL)
{
return FALSE;
}
ip_header = (PWINDIVERT_IPHDR)packet;
switch (ip_header->Version)
switch (layer)
{
case 4:
if (ip_header->TTL <= 1)
case WINDIVERT_LAYER_ETHERNET:
if (packetLen < sizeof(WINDIVERT_ETHHDR))
{
return FALSE;
}
ip_header->TTL--;
// Incremental checksum update:
if (ip_header->Checksum >= 0xFFFE)
eth_header = (PWINDIVERT_ETHHDR)packet;
switch (ntohs(eth_header->Type))
{
ip_header->Checksum -= 0xFFFE;
case ETHERTYPE_IP:
if (packetLen < sizeof(WINDIVERT_IPHDR))
{
return FALSE;
}
break;
case ETHERTYPE_IPV6:
if (packetLen < sizeof(WINDIVERT_IPV6HDR))
{
return FALSE;
}
is_ipv6 = TRUE;
break;
default:
return FALSE;
}
else
{
ip_header->Checksum += 1;
}
return TRUE;
packet = (VOID *)(eth_header + 1);
break;
case 6:
if (packetLen < sizeof(WINDIVERT_IPV6HDR))
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
if (packetLen < sizeof(WINDIVERT_IPHDR))
{
return FALSE;
}
ipv6_header = (PWINDIVERT_IPV6HDR)packet;
if (ipv6_header->HopLimit <= 1)
ip_header = (PWINDIVERT_IPHDR)packet;
switch (ip_header->Version)
{
return FALSE;
case 4:
break;
case 6:
if (packetLen < sizeof(WINDIVERT_IPV6HDR))
{
return FALSE;
}
is_ipv6 = TRUE;
break;
default:
return FALSE;
}
ipv6_header->HopLimit--;
return TRUE;
break;
default:
return FALSE;
}
if (!is_ipv6)
{
ip_header = (PWINDIVERT_IPHDR)packet;
if (ip_header->TTL <= 1)
{
return FALSE;
}
ip_header->TTL--;
// Incremental checksum update:
if (ip_header->Checksum >= 0xFFFE)
{
ip_header->Checksum -= 0xFFFE;
}
else
{
ip_header->Checksum += 1;
}
}
else
{
ipv6_header = (PWINDIVERT_IPV6HDR)packet;
if (ipv6_header->HopLimit <= 1)
{
return FALSE;
}
ipv6_header->HopLimit--;
}
return TRUE;
}
/*
@@ -810,92 +951,95 @@ static BOOL WinDivertValidateField(WINDIVERT_LAYER layer, UINT32 field)
{
static const UINT8 flags[] =
{
LNMFSR, /* WINDIVERT_FILTER_FIELD_ZERO */
LN_FS_, /* WINDIVERT_FILTER_FIELD_INBOUND */
LN_FS_, /* WINDIVERT_FILTER_FIELD_OUTBOUND */
LNM___, /* WINDIVERT_FILTER_FIELD_IFIDX */
LNM___, /* WINDIVERT_FILTER_FIELD_SUBIFIDX */
LNMFS_, /* WINDIVERT_FILTER_FIELD_IP */
LNMFS_, /* WINDIVERT_FILTER_FIELD_IPV6 */
LNMFS_, /* WINDIVERT_FILTER_FIELD_ICMP */
LNMFS_, /* WINDIVERT_FILTER_FIELD_TCP */
LNMFS_, /* WINDIVERT_FILTER_FIELD_UDP */
LNMFS_, /* WINDIVERT_FILTER_FIELD_ICMPV6 */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_HDRLENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_TOS */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_LENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_ID */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_DF */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_MF */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_FRAGOFF */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_TTL */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_PROTOCOL */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_CHECKSUM */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_SRCADDR */
LNM___, /* WINDIVERT_FILTER_FIELD_IP_DSTADDR */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_LENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_SRCADDR */
LNM___, /* WINDIVERT_FILTER_FIELD_IPV6_DSTADDR */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_TYPE */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_CODE */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMP_BODY */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_TYPE */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CODE */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM */
LNM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_BODY */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SRCPORT */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_DSTPORT */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SEQNUM */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_ACKNUM */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_URG */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_ACK */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PSH */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_RST */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_SYN */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_FIN */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_WINDOW */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_CHECKSUM */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_URGPTR */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_SRCPORT */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_DSTPORT */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_LENGTH */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_CHECKSUM */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH */
LN_FS_, /* WINDIVERT_FILTER_FIELD_LOOPBACK */
LNM___, /* WINDIVERT_FILTER_FIELD_IMPOSTOR */
L__FSR, /* WINDIVERT_FILTER_FIELD_PROCESSID */
LN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALADDR */
LN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEADDR */
LN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALPORT */
LN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEPORT */
LN_FS_, /* WINDIVERT_FILTER_FIELD_PROTOCOL */
L__FS_, /* WINDIVERT_FILTER_FIELD_ENDPOINTID */
L__FS_, /* WINDIVERT_FILTER_FIELD_PARENTENDPOINTID */
L____R, /* WINDIVERT_FILTER_FIELD_LAYER */
L____R, /* WINDIVERT_FILTER_FIELD_PRIORITY */
LNMFSR, /* WINDIVERT_FILTER_FIELD_EVENT */
LNM___, /* WINDIVERT_FILTER_FIELD_PACKET */
LNM___, /* WINDIVERT_FILTER_FIELD_PACKET16 */
LNM___, /* WINDIVERT_FILTER_FIELD_PACKET32 */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 */
LNM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 */
LNM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 */
LNM___, /* WINDIVERT_FILTER_FIELD_LENGTH */
LNMFSR, /* WINDIVERT_FILTER_FIELD_TIMESTAMP */
LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM8 */
LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM16 */
LNM___, /* WINDIVERT_FILTER_FIELD_RANDOM32 */
LNM___, /* WINDIVERT_FILTER_FIELD_FRAGMENT */
LENMFSR, /* WINDIVERT_FILTER_FIELD_ZERO */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_INBOUND */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_OUTBOUND */
LENM___, /* WINDIVERT_FILTER_FIELD_IFIDX */
LENM___, /* WINDIVERT_FILTER_FIELD_SUBIFIDX */
LENMFS_, /* WINDIVERT_FILTER_FIELD_IP */
LENMFS_, /* WINDIVERT_FILTER_FIELD_IPV6 */
LENMFS_, /* WINDIVERT_FILTER_FIELD_ICMP */
LENMFS_, /* WINDIVERT_FILTER_FIELD_TCP */
LENMFS_, /* WINDIVERT_FILTER_FIELD_UDP */
LENMFS_, /* WINDIVERT_FILTER_FIELD_ICMPV6 */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_HDRLENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_TOS */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_LENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_ID */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_DF */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_MF */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_FRAGOFF */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_TTL */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_PROTOCOL */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_CHECKSUM */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_SRCADDR */
LENM___, /* WINDIVERT_FILTER_FIELD_IP_DSTADDR */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_TRAFFICCLASS */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_FLOWLABEL */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_LENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_NEXTHDR */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_HOPLIMIT */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_SRCADDR */
LENM___, /* WINDIVERT_FILTER_FIELD_IPV6_DSTADDR */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMP_TYPE */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMP_CODE */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMP_CHECKSUM */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMP_BODY */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_TYPE */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CODE */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_CHECKSUM */
LENM___, /* WINDIVERT_FILTER_FIELD_ICMPV6_BODY */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_SRCPORT */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_DSTPORT */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_SEQNUM */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_ACKNUM */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_HDRLENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_URG */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_ACK */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_PSH */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_RST */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_SYN */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_FIN */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_WINDOW */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_CHECKSUM */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_URGPTR */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOADLENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_SRCPORT */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_DSTPORT */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_LENGTH */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_CHECKSUM */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOADLENGTH */
L_N_FS_, /* WINDIVERT_FILTER_FIELD_LOOPBACK */
LENM___, /* WINDIVERT_FILTER_FIELD_IMPOSTOR */
L___FSR, /* WINDIVERT_FILTER_FIELD_PROCESSID */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALADDR */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEADDR */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_LOCALPORT */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_REMOTEPORT */
LEN_FS_, /* WINDIVERT_FILTER_FIELD_PROTOCOL */
L___FS_, /* WINDIVERT_FILTER_FIELD_ENDPOINTID */
L___FS_, /* WINDIVERT_FILTER_FIELD_PARENTENDPOINTID */
L_____R, /* WINDIVERT_FILTER_FIELD_LAYER */
L_____R, /* WINDIVERT_FILTER_FIELD_PRIORITY */
LENMFSR, /* WINDIVERT_FILTER_FIELD_EVENT */
LENM___, /* WINDIVERT_FILTER_FIELD_PACKET */
LENM___, /* WINDIVERT_FILTER_FIELD_PACKET16 */
LENM___, /* WINDIVERT_FILTER_FIELD_PACKET32 */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD16 */
LENM___, /* WINDIVERT_FILTER_FIELD_TCP_PAYLOAD32 */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD16 */
LENM___, /* WINDIVERT_FILTER_FIELD_UDP_PAYLOAD32 */
LENM___, /* WINDIVERT_FILTER_FIELD_LENGTH */
LENMFSR, /* WINDIVERT_FILTER_FIELD_TIMESTAMP */
LENM___, /* WINDIVERT_FILTER_FIELD_RANDOM8 */
LENM___, /* WINDIVERT_FILTER_FIELD_RANDOM16 */
LENM___, /* WINDIVERT_FILTER_FIELD_RANDOM32 */
LENM___, /* WINDIVERT_FILTER_FIELD_FRAGMENT */
LE_____, /* WINDIVERT_FILTER_FIELD_ETH_DST_ADDR */
LE_____, /* WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR */
LE_____, /* WINDIVERT_FILTER_FIELD_ETH_TYPE */
};
if (field > WINDIVERT_FILTER_FIELD_MAX)
@@ -972,10 +1116,12 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
BOOL loopback,
BOOL impostor,
BOOL fragment,
const WINDIVERT_DATA_ETHERNET *ethernet_data,
const WINDIVERT_DATA_NETWORK *network_data,
const WINDIVERT_DATA_FLOW *flow_data,
const WINDIVERT_DATA_SOCKET *socket_data,
const WINDIVERT_DATA_REFLECT *reflect_data,
const WINDIVERT_ETHHDR *eth_header,
const WINDIVERT_IPHDR *ip_header,
const WINDIVERT_IPV6HDR *ipv6_header,
const WINDIVERT_ICMPHDR *icmp_header,
@@ -994,6 +1140,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
UINT16 data16;
UINT32 data32;
ULARGE_INTEGER val64;
const UINT8 *eth_addr;
ip = 0;
ttl = WINDIVERT_FILTER_MAXLEN+1;
@@ -1017,11 +1164,16 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
if (random64 == 0)
{
random64 = WinDivertHashPacket((UINT64)timestamp,
ip_header, ipv6_header, icmp_header, icmpv6_header,
tcp_header, udp_header);
eth_header, ip_header, ipv6_header, icmp_header,
icmpv6_header, tcp_header, udp_header);
random64 |= 0xFF00000000000000ull; // Make non-zero.
}
break;
case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR:
case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR:
case WINDIVERT_FILTER_FIELD_ETH_TYPE:
result = (eth_header != NULL);
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
case WINDIVERT_FILTER_FIELD_IP_TOS:
case WINDIVERT_FILTER_FIELD_IP_LENGTH:
@@ -1174,6 +1326,9 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_IFIDX:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
val[0] = ethernet_data->IfIdx;
break;
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
val[0] = network_data->IfIdx;
@@ -1183,7 +1338,17 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
}
break;
case WINDIVERT_FILTER_FIELD_SUBIFIDX:
val[0] = network_data->SubIfIdx;
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
val[0] = ethernet_data->SubIfIdx;
break;
case WINDIVERT_LAYER_NETWORK:
val[0] = network_data->SubIfIdx;
break;
default:
return -1;
}
break;
case WINDIVERT_FILTER_FIELD_LOOPBACK:
val[0] = (UINT32)loopback;
@@ -1200,6 +1365,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_ICMP:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
val[0] = (UINT32)(icmp_header != NULL);
@@ -1219,6 +1385,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_ICMPV6:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
val[0] = (UINT32)(icmpv6_header != NULL);
@@ -1238,6 +1405,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_TCP:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
val[0] = (UINT32)(tcp_header != NULL);
@@ -1257,6 +1425,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_UDP:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
case WINDIVERT_LAYER_NETWORK_FORWARD:
val[0] = (UINT32)(udp_header != NULL);
@@ -1273,6 +1442,23 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
return -1;
}
break;
case WINDIVERT_FILTER_FIELD_ETH_DST_ADDR:
case WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR:
big = TRUE;
eth_addr =
(filter[ip].field == WINDIVERT_FILTER_FIELD_ETH_DST_ADDR?
eth_header->DstAddr: eth_header->SrcAddr);
val[0] = ((UINT32)eth_addr[2] << 24) |
((UINT32)eth_addr[3] << 16) |
((UINT32)eth_addr[4] << 8) |
((UINT32)eth_addr[5]);
val[1] = ((UINT32)eth_addr[0] << 8) |
((UINT32)eth_addr[1]);
val[2] = val[3] = 0;
break;
case WINDIVERT_FILTER_FIELD_ETH_TYPE:
val[0] = (UINT32)ntohs(eth_header->Type);
break;
case WINDIVERT_FILTER_FIELD_IP_HDRLENGTH:
val[0] = (UINT32)ip_header->HdrLength;
break;
@@ -1435,6 +1621,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
big = TRUE;
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
if (ip_header != NULL)
{
@@ -1483,6 +1670,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
big = TRUE;
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
if (ip_header != NULL)
{
@@ -1530,6 +1718,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_LOCALPORT:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
if (tcp_header != NULL)
{
@@ -1571,6 +1760,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_REMOTEPORT:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
if (tcp_header != NULL)
{
@@ -1612,6 +1802,7 @@ static WINDIVERT_INLINE int WinDivertExecuteFilter(
case WINDIVERT_FILTER_FIELD_PROTOCOL:
switch (layer)
{
case WINDIVERT_LAYER_ETHERNET:
case WINDIVERT_LAYER_NETWORK:
val[0] = (UINT32)protocol;
break;
+381 -196
View File
@@ -1,11 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<title>WinDivert 2.2 Documentation</title>
<title>WinDivert 3.0 Documentation</title>
<meta charset="UTF-8"/>
</head>
<body>
<h1>WinDivert 2.2: Windows Packet Divert</h1>
<h1>WinDivert 3.0: Windows Packet Divert</h1>
<h2>Table of Contents</h2>
<ul>
<li><a href="#introduction">1. Introduction</a></li>
@@ -34,25 +34,28 @@
</li>
<li><a href="#helper_programming_api">6. Helper Programming API</a>
<ul>
<li><a href="#divert_iphdr">6.1 WINDIVERT_IPHDR</a></li>
<li><a href="#divert_ipv6hdr">6.2 WINDIVERT_IPV6HDR</a></li>
<li><a href="#divert_icmphdr">6.3 WINDIVERT_ICMPHDR</a></li>
<li><a href="#divert_icmpv6hdr">6.4 WINDIVERT_ICMPV6HDR</a></li>
<li><a href="#divert_tcphdr">6.5 WINDIVERT_TCPHDR</a></li>
<li><a href="#divert_udphdr">6.6 WINDIVERT_UDPHDR</a></li>
<li><a href="#divert_helper_parse_packet">6.7 WinDivertHelperParsePacket</a></li>
<li><a href="#divert_helper_hash_packet">6.8 WinDivertHelperHashPacket</a></li>
<li><a href="#divert_helper_parse_ipv4_address">6.9 WinDivertHelperParseIPv4Address</a></li>
<li><a href="#divert_helper_parse_ipv6_address">6.10 WinDivertHelperParseIPv6Address</a></li>
<li><a href="#divert_helper_format_ipv4_address">6.11 WinDivertHelperFormatIPv4Address</a></li>
<li><a href="#divert_helper_format_ipv6_address">6.12 WinDivertHelperFormatIPv6Address</a></li>
<li><a href="#divert_helper_calc_checksums">6.13 WinDivertHelperCalcChecksums</a></li>
<li><a href="#divert_helper_dec_ttl">6.14 WinDivertHelperDecrementTTL</a></li>
<li><a href="#divert_helper_compile_filter">6.15 WinDivertHelperCompileFilter</a></li>
<li><a href="#divert_helper_eval_filter">6.16 WinDivertHelperEvalFilter</a></li>
<li><a href="#divert_helper_format_filter">6.17 WinDivertHelperFormatFilter</a></li>
<li><a href="#divert_helper_ntoh">6.18 WinDivertHelperNtoh*</a></li>
<li><a href="#divert_helper_hton">6.19 WinDivertHelperHton*</a></li>
<li><a href="#divert_ethhdr">6.1 WINDIVERT_ETHHDR</a></li>
<li><a href="#divert_iphdr">6.2 WINDIVERT_IPHDR</a></li>
<li><a href="#divert_ipv6hdr">6.3 WINDIVERT_IPV6HDR</a></li>
<li><a href="#divert_icmphdr">6.4 WINDIVERT_ICMPHDR</a></li>
<li><a href="#divert_icmpv6hdr">6.5 WINDIVERT_ICMPV6HDR</a></li>
<li><a href="#divert_tcphdr">6.6 WINDIVERT_TCPHDR</a></li>
<li><a href="#divert_udphdr">6.7 WINDIVERT_UDPHDR</a></li>
<li><a href="#divert_helper_parse_packet">6.8 WinDivertHelperParsePacket</a></li>
<li><a href="#divert_helper_hash_packet">6.9 WinDivertHelperHashPacket</a></li>
<li><a href="#divert_helper_parse_mac_address">6.10 WinDivertHelperParseMACAddress</a></li>
<li><a href="#divert_helper_parse_ipv4_address">6.11 WinDivertHelperParseIPv4Address</a></li>
<li><a href="#divert_helper_parse_ipv6_address">6.12 WinDivertHelperParseIPv6Address</a></li>
<li><a href="#divert_helper_format_mac_address">6.13 WinDivertHelperFormatMacAddress</a></li>
<li><a href="#divert_helper_format_ipv4_address">6.14 WinDivertHelperFormatIPv4Address</a></li>
<li><a href="#divert_helper_format_ipv6_address">6.15 WinDivertHelperFormatIPv6Address</a></li>
<li><a href="#divert_helper_calc_checksums">6.16 WinDivertHelperCalcChecksums</a></li>
<li><a href="#divert_helper_dec_ttl">6.17 WinDivertHelperDecrementTTL</a></li>
<li><a href="#divert_helper_compile_filter">6.18 WinDivertHelperCompileFilter</a></li>
<li><a href="#divert_helper_eval_filter">6.19 WinDivertHelperEvalFilter</a></li>
<li><a href="#divert_helper_format_filter">6.20 WinDivertHelperFormatFilter</a></li>
<li><a href="#divert_helper_ntoh">6.21 WinDivertHelperNtoh*</a></li>
<li><a href="#divert_helper_hton">6.22 WinDivertHelperHton*</a></li>
</ul>
</li>
<li><a href="#filter_language">7. Filter Language</a>
@@ -72,7 +75,7 @@
<p>
WinDivert is a powerful user-mode
capture/sniffing/modification/blocking/re-injection package for
Windows 7, Windows 8 and Windows 10.
Windows 8 and Windows 10, as well as Windows Server 2012/2016/2019.
WinDivert can be used to implement user-mode packet filters, packet sniffers,
firewalls, NAT, VPNs, tunneling applications, etc., without the need to
write kernel-mode code.
@@ -116,25 +119,26 @@ The source code for WinDivert is available for download at:
To build the WinDivert drivers from source:
</p>
<ol>
<li> Download and install <a href="http://www.microsoft.com/whdc/devtools/wdk/default.mspx">
Windows Driver Kit 7.1.0</a>.</li>
<li> Open a <i>x86 Free Build Environment</i> console.</li>
<li> Download and install Visual Studio 2015 and Windows Driver Kit (WDK).</li>
<li> Open a Visual Studio 2015 <i>Developer Command Prompt</i>.</li>
<li> In the WinDivert package root directory, run the command:
<pre>
wddk-build.bat
msvc-build.bat
</pre>
This will build the <code>install\WDDK\i386\WinDivert32.sys</code> driver.</li>
<li> Next, open a <i>x64 Free Build Environment</i> console.</li>
<li> Re-run the <code>wddk-build.bat</code> command to build the
<code>install\WDDK\amd64\WinDivert64.sys</code> driver.</li>
This will build the <code>install\MSVC\i386\WinDivert32.sys</code> and
<code>install\WDDK\amd64\WinDivert64.sys</code> drivers.</li>
</ol>
<p>
To build the WinDivert user-mode library (<code>WinDivert.dll</code>) and sample
programs:
Note that the <code>msvc-build.bat</code> script will also build the
<code>WinDivert.dll</code> and sample programs.
However, these versions are not used in the official distribution
because of the dependency on the Visual Studio 2015 C runtime.
</p><p>
To build the (dependency free) WinDivert user-mode library
(<code>WinDivert.dll</code>) and sample programs:
</p>
<ol>
<li> First, build the WinDivert drivers by running the
<code>wddk-build.bat</code> command described above.</li>
<li> First, build the WinDivert drivers as described above.</li>
<li> In Linux (with the MinGW cross-compilers installed) and in the
WinDivert package root directory, run the command:
<pre>
@@ -272,6 +276,7 @@ typedef enum
WINDIVERT_LAYER_FLOW,
WINDIVERT_LAYER_SOCKET,
WINDIVERT_LAYER_REFLECT,
WINDIVERT_LAYER_ETHERNET,
} <b>WINDIVERT_LAYER</b>, *<b>PWINDIVERT_LAYER</b>;
</pre>
</td></tr></table>
@@ -311,6 +316,15 @@ PID?
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_ETHERNET</code>
</td>
<td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td>
<td>
Ethernet frames to/from the local machine.
</td>
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_NETWORK</code>
</td>
<td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td>
@@ -367,12 +381,21 @@ Here, the layer capabilities are:
an event/packet is available at this layer, or not.
</ul>
<p>
The <code>WINDIVERT_LAYER_NETWORK</code> and
<code>WINDIVERT_LAYER_NETWORK_FORWARD</code>
layers allow the user application to capture/block/inject network packets
The <code>WINDIVERT_LAYER_ETHERNET</code>
layer allows the user application to capture/block/inject ethernet
frames passing to/from the local machine.
An ethernet frame will start with <i>ethernet header</i>,
followed by a packet from an upper layer protocol, such as
IPv4, IPv6, ARP, etc.
</p>
<p>
The <code>WINDIVERT_LAYER_NETWORK</code> (and
<code>WINDIVERT_LAYER_NETWORK_FORWARD</code>)
layers allow the user application to
capture/block/inject network packets
passing to/from (and through) the local machine.
Due to technical limitations, process ID information is not available
at these layers.
Network layer packets start with either an IPv4 or IPv6 header,
typically followed by a transport layer payload (e.g., TCP or UDP).
</p>
<p>
The <code>WINDIVERT_LAYER_FLOW</code> layer captures information about
@@ -393,8 +416,10 @@ The <code>WINDIVERT_LAYER_SOCKET</code> layer can capture or block events
corresponding to socket operations, such as <code>bind()</code>,
<code>connect()</code>, <code>listen()</code>, etc., or the termination
of socket operations, such as a TCP socket disconnection.
Unlike the flow layer, most socket-related events can be blocked.
However, it is not possible to inject new or modified socket events.
Unlike the flow layer, most socket-related events can be blocked,
but it is not possible to inject new or modified socket events.
Some events at this layer may be <i>implicit</i>, meaning that the event
does not correspond to an explicit call to a WinSock2 function.
Process ID information (of the process responsible for the socket operation)
is available at this layer.
Due to technical limitations, this layer cannot capture events that
@@ -434,6 +459,7 @@ typedef enum
WINDIVERT_EVENT_SOCKET_CLOSE,
WINDIVERT_EVENT_REFLECT_OPEN,
WINDIVERT_EVENT_REFLECT_CLOSE,
WINDIVERT_EVENT_ETHERNET_FRAME,
} <b>WINDIVERT_EVENT</b>, *<b>PWINDIVERT_EVENT</b>;
</pre>
</td></tr></table>
@@ -445,6 +471,27 @@ Each layer supports one or more <i>events</i> summarized below:
<ul>
<li>
<p>
<b><code>WINDIVERT_LAYER_ETHERNET</code></b>:
Only a single event is supported:
</p>
<center>
<table border="1" cellpadding="5" width="50%">
<tr>
<th>Event</th>
<th>Description</th>
<tr>
<td>
<code>WINDIVERT_EVENT_ETHERNET_FRAME</code>
</td>
<td>
A new ethernet frame.
</td>
</tr>
</table>
</center>
</li>
<li>
<p>
<b><code>WINDIVERT_LAYER_NETWORK</code></b> and
<b><code>WINDIVERT_LAYER_NETWORK_FORWARD</code></b>:
Only a single event is supported:
@@ -464,8 +511,6 @@ A new network packet.
</tr>
</table>
</center>
<ul>
</ul>
</li>
<li>
<p>
@@ -585,6 +630,12 @@ An old WinDivert handle was closed.
<a name="divert_address"><h3>5.3 WINDIVERT_ADDRESS</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
{
UINT32 IfIdx;
UINT32 SubIfIdx;
} <b>WINDIVERT_DATA_ETHERNET</b>, *<b>PWINDIVERT_DATA_ETHERNET</b>;
typedef struct
{
UINT32 IfIdx;
@@ -627,22 +678,24 @@ typedef struct
typedef struct
{
INT64 Timestamp;
UINT64 Layer:8;
UINT64 Event:8;
UINT64 Sniffed:1;
UINT64 Outbound:1;
UINT64 Loopback:1;
UINT64 Impostor:1;
UINT64 IPv6:1;
UINT64 IPChecksum:1;
UINT64 TCPChecksum:1;
UINT64 UDPChecksum:1;
UINT32 Layer:8;
UINT32 Event:8;
UINT32 Sniffed:1;
UINT32 Outbound:1;
UINT32 Loopback:1;
UINT32 Impostor:1;
UINT32 IPv6:1;
UINT32 IPChecksum:1;
UINT32 TCPChecksum:1;
UINT32 UDPChecksum:1;
UINT32 Length:20;
union
{
WINDIVERT_DATA_NETWORK Network;
WINDIVERT_DATA_FLOW Flow;
WINDIVERT_DATA_SOCKET Socket;
WINDIVERT_DATA_REFLECT Reflect;
WINDIVERT_DATA_ETHERNET Ethernet;
WINDIVERT_DATA_NETWORK Network;
WINDIVERT_DATA_FLOW Flow;
WINDIVERT_DATA_SOCKET Socket;
WINDIVERT_DATA_REFLECT Reflect;
};
} <b>WINDIVERT_ADDRESS</b>, *<b>PWINDIVERT_ADDRESS</b>;
</pre>
@@ -669,6 +722,11 @@ valid, <code>0</code> otherwise.</li>
valid, <code>0</code> otherwise.</li>
<li> <code>UDPChecksum</code>: Set to <code>1</code> if the UDP checksum is
valid, <code>0</code> otherwise.</li>
<li> <code>Length</code>: Set to the length of the packet.</li>
<li> <code>Ethernet.IfIdx</code>: The interface index on which the frame
arrived (for inbound frames), or is to be sent (for outbound frames).</li>
<li> <code>Ethernet.SubIfIdx</code>: The sub-interface index for
<code>IfIdx</code>.</li>
<li> <code>Network.IfIdx</code>: The interface index on which the packet arrived
(for inbound packets), or is to be sent (for outbound packets).</li>
<li> <code>Network.SubIfIdx</code>: The sub-interface index for <code>IfIdx</code>.</li>
@@ -754,11 +812,20 @@ When <i>IP/TCP/UDP checksum offloading</i> is enabled, it is possible that
captured packets do not have valid checksums.
Invalid checksums may be arbitrary values.
</p><p>
The <code>Length</code> field corresponds to the length of the packet.
This is mostly used for <i>batch mode</i>, where multiple packets are
stored in the same buffer.
</p><p>
The <code>Ethernet.*</code> fields are only valid at the
<code>WINDIVERT_LAYER_ETHERNET</code> layer.
The <code>Ethernet.IfIdx</code>/<code>Ethernet.SubIfIdx</code> indicate the
frame's network adapter (a.k.a. interface) index.
</p><p>
The <code>Network.*</code> fields are only valid at the
<code>WINDIVERT_LAYER_NETWORK</code> and
<code>WINDIVERT_LAYER_NETWORK_FORWARD</code> layers.
The <code>Network.IfIdx</code>/<code>Network.SubIfIdx</code> indicate the packet's
network adapter (a.k.a. interface) index.
The <code>Network.IfIdx</code>/<code>Network.SubIfIdx</code> indicate the
packet's network adapter (a.k.a. interface) index.
These values are ignored for <i>outbound</i> packets.
</p><p>
The <code>Flow.*</code> fields are only valid at the
@@ -807,10 +874,18 @@ the opened handle.
Most address fields are ignored by
<a href="#divert_send"><code>WinDivertSend()</code></a>.
The exceptions are
<code>Outbound</code> (for <code>WINDIVERT_LAYER_NETWORK</code> only),
<code>Outbound</code> (for
<code>WINDIVERT_LAYER_ETHERNET</code>/<code>WINDIVERT_LAYER_NETWORK</code>
only),
<code>Impostor</code>, <code>IPChecksum</code>, <code>TCPChecksum</code>,
<code>UDPChecksum</code>, <code>Network.IfIdx</code> and
<code>UDPChecksum</code>, <code>Ethernet.IfIdx</code>,
<code>Ethernet.SubIfIdx</code>, <code>Network.IfIdx</code> and
<code>Network.SubIfIdx</code>.
The <code>Length</code> field is used for <i>batch mode</i> where
multiple packets are injected at once.
That said, the <code>Length</code> field is ignored for the last packet of the
batch, in which case the remaining buffer length determines the
injected packet size.
</p>
</dd></dl>
@@ -991,11 +1066,18 @@ Description
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_NETWORK = 0</code>
<code>WINDIVERT_LAYER_ETHERNET</code>
</td>
<td>
Ethernet frames to/from the local machine.
</td>
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_NETWORK</code>
</td>
<td>
Network packets to/from the local machine.
This is the default layer.
</td>
</tr>
<tr>
@@ -1292,6 +1374,17 @@ Description
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_ETHERNET</code>
</td>
<td>
&#10004;
</td>
<td>
Ethernet frame.
</td>
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_NETWORK</code>
</td>
<td>
@@ -1543,8 +1636,10 @@ modified version, or a completely new packet.
Injected packets can be captured and diverted again by other WinDivert
handles with lower priorities.
</p><p>
Only the <code>WINDIVERT_LAYER_NETWORK</code> and
<code>WINDIVERT_LAYER_NETWORK_FORWARD</code> <a href="#divert_layers">layers</a>
Only the <code>WINDIVERT_LAYER_ETHERMET</code>,
<code>WINDIVERT_LAYER_NETWORK</code> and
<code>WINDIVERT_LAYER_NETWORK_FORWARD</code>
<a href="#divert_layers">layers</a>
support packet injection, as summarized below:
</p>
<center>
@@ -1559,6 +1654,14 @@ Inject?
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_ETHERNET</code>
</td>
<td>
&#10004;
</td>
</tr>
<tr>
<td>
<code>WINDIVERT_LAYER_NETWORK</code>
</td>
<td>
@@ -1597,7 +1700,8 @@ Inject?
</table>
</center>
<p>
For the <code>WINDIVERT_LAYER_NETWORK</code> layer the
For the <code>WINDIVERT_LAYER_ETHERNET</code> and
<code>WINDIVERT_LAYER_NETWORK</code> layers, the
<code>pAddr-&gt;Outbound</code> value determines which direction the packet
is injected.
If the <code>pAddr-&gt;Outbound</code> field is <code>1</code>,
@@ -1958,7 +2062,29 @@ The WinDivert helper programming API is a collection of definitions
and functions designed to make writing WinDivert applications easier.
The use of the helper API is optional.
<a name="divert_iphdr"><h3>6.1 WINDIVERT_IPHDR</h3></a>
<a name="divert_ethhdr"><h3>6.1 WINDIVERT_ETHHDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
{
UINT8 DstAddr[6];
UINT8 SrcAddr[6];
UINT16 Type;
} <b>WINDIVERT_ETHHDR</b>, *<b>PWINDIVERT_ETHHDR</b>;
</pre>
</td></tr></table>
<dl><dd>
<p>
<b>Fields</b><br>
See <a href="https://en.wikipedia.org/wiki/Ethernet_frame#Header">here</a>
for more information.
</p><p>
<b>Remarks</b><br>
Ethernet frame header definition.
</p>
</dl></dd>
<a name="divert_iphdr"><h3>6.2 WINDIVERT_IPHDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2001,7 +2127,7 @@ definitions:
</ul>
</dl></dd>
<a name="divert_ipv6hdr"><h3>6.2 WINDIVERT_IPV6HDR</h3></a>
<a name="divert_ipv6hdr"><h3>6.3 WINDIVERT_IPV6HDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2037,7 +2163,7 @@ definitions:
</ul>
</dl></dd>
<a name="divert_icmphdr"><h3>6.3 WINDIVERT_ICMPHDR</h3></a>
<a name="divert_icmphdr"><h3>6.4 WINDIVERT_ICMPHDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2060,7 +2186,7 @@ ICMP header definition.
</p>
</dl></dd>
<a name="divert_icmpv6hdr"><h3>6.4 WINDIVERT_ICMPV6HDR</h3></a>
<a name="divert_icmpv6hdr"><h3>6.5 WINDIVERT_ICMPV6HDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2083,7 +2209,7 @@ ICMPv6 header definition.
</p>
</dl></dd>
<a name="divert_tcphdr"><h3>6.5 WINDIVERT_TCPHDR</h3></a>
<a name="divert_tcphdr"><h3>6.6 WINDIVERT_TCPHDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2118,7 +2244,7 @@ TCP header definition.
</p>
</dl></dd>
<a name="divert_udphdr"><h3>6.6 WINDIVERT_UDPHDR</h3></a>
<a name="divert_udphdr"><h3>6.7 WINDIVERT_UDPHDR</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
typedef struct
@@ -2141,12 +2267,14 @@ UDP header definition.
</p>
</dl></dd>
<a name="divert_helper_parse_packet"><h3>6.7 WinDivertHelperParsePacket</h3></a>
<a name="divert_helper_parse_packet"><h3>6.8 WinDivertHelperParsePacket</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperParsePacket</b>(
__in PVOID pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__out_opt PWINDIVERT_ETHHDR *ppEthHdr,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
__out_opt UINT8 *pProtocol,
@@ -2155,9 +2283,7 @@ BOOL <b>WinDivertHelperParsePacket</b>(
__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
__out_opt UINT *pDataLen
);
</pre>
</td></tr></table>
@@ -2166,6 +2292,8 @@ BOOL <b>WinDivertHelperParsePacket</b>(
<ul>
<li> <code>pPacket</code>: The packet(s) to be parsed.</li>
<li> <code>packetLen</code>: The total length of the packet(s) <code>pPacket</code>.</li>
<li> <code>layer</code>: The layer.</li>
<li> <code>ppEthHdr</code>: Output pointer to a <code>WINDIVERT_ETHHDR</code>.</li>
<li> <code>ppIpHdr</code>: Output pointer to a <code>WINDIVERT_IPHDR</code>.</li>
<li> <code>ppIpv6Hdr</code>: Output pointer to a <code>WINDIVERT_IPV6HDR</code>.</li>
<li> <code>pProtocol</code>: Output transport protocol.</li>
@@ -2175,17 +2303,17 @@ BOOL <b>WinDivertHelperParsePacket</b>(
<li> <code>ppUdpHdr</code>: Output pointer to a <code>WINDIVERT_UDPHDR</code>.</li>
<li> <code>ppData</code>: Output pointer to the packet's data/payload.</li>
<li> <code>pDataLen</code>: Output data/payload length.</li>
<li> <code>ppNext</code>: Output pointer to the next packet (if present).</li>
<li> <code>pNextLen</code>: Output next packet length.</li>
</ul>
<p>
<b>Return Value</b><br>
<code>TRUE</code> if successful, <code>FALSE</code> if an error occurred.
</p><p>
<b>Remarks</b><br>
Parses a raw packet or batch of packets (e.g. from <a
href="#divert_recv"><code>WinDivertRecv()</code></a>) into the
various packet headers and/or payloads that may or may not be present.
Parses a raw packet (e.g. from <a
href="#divert_recv"><code>WinDivertRecv()</code></a>)
from the <code>WINDIVERT_LAYER_ETHERNET</code> or
<code>WINDIVERT_LAYER_NETWORK*</code> layers
into the various packet headers and/or payloads that may or may not be present.
</p><p>
Each output parameter may be <code>NULL</code> or non-<code>NULL</code>.
For non-<code>NULL</code> parameters, this function will write the pointer to
@@ -2194,41 +2322,24 @@ otherwise.
Any non-<code>NULL</code> pointer that is returned:
</p>
<ol>
<li> Is a pointer into the original <code>pPacket</code> packet buffer; and</li>
<li> Is a pointer into the original <code>pPacket</code> packet buffer
(this function does not allocate any memory); and</li>
<li> There is enough space in <code>pPacket</code> to fit the header.</li>
</ol>
<p>
This function does not do any verification of the header/payload contents
beyond checking the header length and any other minimal information required
for parsing.
This function will always succeed provided the <code>pPacket</code> buffer
contains at least one IPv4 or IPv6 header and the <code>packetLen</code> is
correct.
</p><p>
By default this function will parse a single packet.
However, if either <code>ppNext</code> or <code>pNextLen</code> are
non-<code>NULL</code>, then the <code>pPacket</code> parameter can point
to a batch (&gt;1) of packets
(and <code>packetLen</code> can be the total length of the batch).
In this case, the function will parse the first packet, and a pointer to the
remaining packet(s) will be written to <code>ppNext</code>,
and the remaining length will be written to <code>pNextLen</code>.
This makes it convenient to loop over every packet in the batch as follows:
This function will succeed if at least one header can be parsed.
</p>
<pre>
while (WinDivertHelperParsePacket(pPacket, packetLen, ..., &amp;pPacket, &amp;packetLen))
{
...
}
</pre>
</dd></dl>
<a name="divert_helper_hash_packet"><h3>6.8 WinDivertHelperHashPacket</h3></a>
<a name="divert_helper_hash_packet"><h3>6.9 WinDivertHelperHashPacket</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
UINT64 <b>WinDivertHelperHashPacket</b>(
__in const VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__in UINT64 seed = 0
);
</pre>
@@ -2238,6 +2349,7 @@ UINT64 <b>WinDivertHelperHashPacket</b>(
<ul>
<li> <code>pPacket</code>: The packet to be hashed.</li>
<li> <code>packetLen</code>: The total length of the packet <code>pPacket</code>.</li>
<li> <code>layer</code>: The layer.</li>
<li> <code>seed</code>: An optional seed value.</li>
</ul>
<p>
@@ -2258,7 +2370,37 @@ The optional <code>seed</code> value is also incorporated into the hash.
<p>
</dd></dl>
<a name="divert_helper_parse_ipv4_address"><h3>6.9 WinDivertHelperParseIPv4Address</h3></a>
<a name="divert_helper_parse_mac_address"><h3>6.10 WinDivertHelperParseMACAddress</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperParseMACAddress</b>(
__in const char *addrStr,
__out_opt UINT8 *pAddr
);
</pre>
</td></tr></table>
<dl><dd>
<p><b>Parameters</b></p>
<ul>
<li> <code>addrStr</code>: The address string.</li>
<li> <code>pAddr</code>: Output address.</li>
</ul>
<p>
<b>Return Value</b><br>
<code>TRUE</code> if successful, <code>FALSE</code> if an error occurred.
Use <code>GetLastError()</code> to get the reason for the error.
</p><p>
<b>Remarks</b><br>
Parses a MAC address stored in <code>addrStr</code>.
If <code>pAddr</code> is non-<code>NULL</code>, the result is be stored in
host-byte-order.
Use
<a href="#divert_helper_hton"><code>WinDivertHelperHtonMACAddress()</code></a>
to convert the result into network-byte-order.
</p>
</dd></dl>
<a name="divert_helper_parse_ipv4_address"><h3>6.11 WinDivertHelperParseIPv4Address</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperParseIPv4Address</b>(
@@ -2287,7 +2429,7 @@ to convert the result into network-byte-order.
</p>
</dd></dl>
<a name="divert_helper_parse_ipv6_address"><h3>6.10 WinDivertHelperParseIPv6Address</h3></a>
<a name="divert_helper_parse_ipv6_address"><h3>6.12 WinDivertHelperParseIPv6Address</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperParseIPv6Address</b>(
@@ -2317,7 +2459,34 @@ to convert the result into network-byte-order.
</p>
</dd></dl>
<a name="divert_helper_format_ipv4_address"><h3>6.11 WinDivertHelperParseIPv4Address</h3></a>
<a name="divert_helper_format_mac_address"><h3>6.13 WinDivertHelperParseMacAddress</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperFormatMacAddress</b>(
__in const UINT8 *addr,
__out char *buffer,
__in UINT bufLen
);
</pre>
</td></tr></table>
<dl><dd>
<p><b>Parameters</b></p>
<ul>
<li> <code>addr</code>: The Mac address in host-byte order.</li>
<li> <code>buffer</code>: The buffer to store the formatted string.</li>
<li> <code>bufLen</code>: The length of <code>buffer</code>.
</ul>
<p>
<b>Return Value</b><br>
<code>TRUE</code> if successful, <code>FALSE</code> if an error occurred.
Use <code>GetLastError()</code> to get the reason for the error.
</p><p>
<b>Remarks</b><br>
Convert a Mac address into a string.
</p>
</dd></dl>
<a name="divert_helper_format_ipv4_address"><h3>6.14 WinDivertHelperParseIPv4Address</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperFormatIPv4Address</b>(
@@ -2344,7 +2513,7 @@ Convert an IPv4 address into a string.
</p>
</dd></dl>
<a name="divert_helper_format_ipv6_address"><h3>6.12 WinDivertHelperParseIPv6Address</h3></a>
<a name="divert_helper_format_ipv6_address"><h3>6.15 WinDivertHelperParseIPv6Address</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperFormatIPv6Address</b>(
@@ -2371,12 +2540,13 @@ Convert an IPv6 address into a string.
</p>
</dd></dl>
<a name="divert_helper_calc_checksums"><h3>6.13 WinDivertHelperCalcChecksums</h3></a>
<a name="divert_helper_calc_checksums"><h3>6.16 WinDivertHelperCalcChecksums</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperCalcChecksums</b>(
__inout VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__out_opt WINDIVERT_ADDRESS *pAddr,
__in UINT64 flags
);
@@ -2387,6 +2557,7 @@ BOOL <b>WinDivertHelperCalcChecksums</b>(
<ul>
<li> <code>pPacket</code>: The packet to be modified.</li>
<li> <code>packetLen</code>: The total length of the packet <code>pPacket</code>.</li>
<li> <code>layer</code>: The layer.</li>
<li> <code>pAddr</code>: Optional pointer to a
<a href="#divert_address"><code>WINDIVERT_ADDRESS</code></a> structure.</li>
<li> <code>flags</code>: One or more of the following flags:
@@ -2429,12 +2600,13 @@ packet injection.
</p>
</dd></dl>
<a name="divert_helper_dec_ttl"><h3>6.14 WinDivertHelperDecrementTTL</h3></a>
<a name="divert_helper_dec_ttl"><h3>6.17 WinDivertHelperDecrementTTL</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperDecrementTTL</b>(
__inout VOID *packet,
__in packetLen
__in packetLen,
__in WINDIVERT_LAYER layer
);
</pre>
</td></tr></table>
@@ -2443,6 +2615,7 @@ BOOL <b>WinDivertHelperDecrementTTL</b>(
<ul>
<li> <code>pPacket</code>: The packet to be modified.</li>
<li> <code>packetLen</code>: The total length of the packet <code>pPacket</code>.</li>
<li> <code>layer</code>: The layer.</li>
</ul>
<p>
<b>Return Value</b><br>
@@ -2463,7 +2636,7 @@ This function updates the checksum field incrementally.
</p>
</dd></dl>
<a name="divert_helper_compile_filter"><h3>6.15 WinDivertHelperCompileFilter</h3></a>
<a name="divert_helper_compile_filter"><h3>6.18 WinDivertHelperCompileFilter</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperCompileFilter</b>(
@@ -2514,13 +2687,14 @@ objects, and therefore do not need to be deallocated.
<p>
</dd></dl>
<a name="divert_helper_eval_filter"><h3>6.16 WinDivertHelperEvalFilter</h3></a>
<a name="divert_helper_eval_filter"><h3>6.19 WinDivertHelperEvalFilter</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperEvalFilter</b>(
__in const char *filter,
__in const VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__in const WINDIVERT_ADDRESS *pAddr
);
</pre>
@@ -2531,6 +2705,7 @@ BOOL <b>WinDivertHelperEvalFilter</b>(
<li> <code>filter</code>: The packet filter string to be evaluated.</li>
<li> <code>pPacket</code>: The packet.</li>
<li> <code>packetLen</code>: The total length of the packet <code>pPacket</code>.</li>
<li> <code>layer</code>: The layer.</li>
<li> <code>pAddr</code>: The <code>WINDIVERT_ADDRESS</code> of the packet
<code>pPacket</code>.</li>
</ul>
@@ -2558,10 +2733,10 @@ function.
<p>
</dd></dl>
<a name="divert_helper_format_filter"><h3>6.17 WinDivertHelperFormatFilter</h3></a>
<a name="divert_helper_format_filter"><h3>6.20 WinDivertHelperFormatFilter</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
BOOL <b>WinDivertHelperEvalFilter</b>(
BOOL <b>WinDivertHelperFormatFilter</b>(
__in const char *filter,
__in WINDIVERT_LAYER layer,
__out char *buffer,
@@ -2592,7 +2767,7 @@ returned by <a href="#divert_recv"><code>WinDivertRecv()</code></a>.
</p>
</dd></dl>
<a name="divert_helper_ntoh"><h3>6.18 WinDivertHelperNtoh*</h3></a>
<a name="divert_helper_ntoh"><h3>6.21 WinDivertHelperNtoh*</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
UINT16 <b>WinDivertHelperNtohs</b>(
@@ -2604,6 +2779,9 @@ UINT32 <b>WinDivertHelperNtohl</b>(
UINT64 <b>WinDivertHelperNtohll</b>(
__in UINT64 x
);
void <b>WinDivertHelperNtohMACAddress</b>(
__in const UINT8 *inAddr,
__out UINT8 *outAddr);
void <b>WinDivertHelperNtohIPv6Address</b>(
__in const UINT *inAddr,
__out UINT *outAddr
@@ -2614,8 +2792,8 @@ void <b>WinDivertHelperNtohIPv6Address</b>(
<p><b>Parameters</b></p>
<ul>
<li> <code>x</code>: The input value in network byte-order.</li>
<li> <code>inAddr</code>: The input IPv6 address in network byte-order.</li>
<li> <code>outAddr</code>: A buffer for the output IPv6 address in host
<li> <code>inAddr</code>: The input MAC/IPv6 address in network byte-order.</li>
<li> <code>outAddr</code>: A buffer for the output MAC/IPv6 address in host
byte-order.</li>
</ul>
<p>
@@ -2627,7 +2805,7 @@ Converts a value/IPv6-address from network to host byte-order.
</p>
</dd></dl>
<a name="divert_helper_hton"><h3>6.19 WinDivertHelperHton*</h3></a>
<a name="divert_helper_hton"><h3>6.22 WinDivertHelperHton*</h3></a>
<table border="1" cellpadding="5"><tr><td>
<pre>
UINT16 <b>WinDivertHelperHtons</b>(
@@ -2639,6 +2817,9 @@ UINT32 <b>WinDivertHelperHtonl</b>(
UINT64 <b>WinDivertHelperHtonll</b>(
__in UINT64 x
);
void <b>WinDivertHelperHtonMACAddress</b>(
__in const UINT8 *inAddr,
__out UINT8 *outAddr);
void <b>WinDivertHelperHtonIPv6Address</b>(
__in const UINT *inAddr,
__out UINT *outAddr
@@ -2649,8 +2830,8 @@ void <b>WinDivertHelperHtonIPv6Address</b>(
<p><b>Parameters</b></p>
<ul>
<li> <code>x</code>: The input value in host byte-order.</li>
<li> <code>inAddr</code>: The input IPv6 address in host byte-order.</li>
<li> <code>outAddr</code>: A buffer for the output IPv6 address in network
<li> <code>inAddr</code>: The input MAC/IPv6 address in host byte-order.</li>
<li> <code>outAddr</code>: A buffer for the output MAC/IPv6 address in network
byte-order.</li>
</ul>
<p>
@@ -2681,7 +2862,7 @@ This could be achieved using the following filter.
HANDLE handle = WinDivertOpen(
"outbound and "
"tcp.PayloadLength &gt; 0 and "
"tcp.DstPort == 80", 0, 0, 0);
"tcp.DstPort == 80", WINDIVERT_LAYER_NETWORK, 0, 0);
</pre>
<p>
This filter selects only the subset of all traffic that is:
@@ -2740,55 +2921,56 @@ The possible fields are:
</p>
<center>
<table border="1" cellpadding="5">
<tr><th>Field</th><th colspan="5">Layer</th><th>Description</th></tr>
<tr><th></th><th><code>NETWORK</code></th><th><code>FORWARD</code></th><th><code>FLOW&nbsp;&nbsp;&nbsp;</code></th><th><code>SOCKET&nbsp;</code></th><th><code>REFLECT</code></th><th></th></tr>
<tr><td><code>zero</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The value zero</td></tr>
<tr><td><code>timestamp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The packet/event timestamp</td></tr>
<tr><td><code>event</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The event</td></tr>
<tr><td><code>outbound</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td></td><td></td><td>Is outbound?</td></tr>
<tr><td><code>inbound</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td></td><td></td><td>Is inbound?</td></tr>
<tr><td><code>ifIdx</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Interface index</td></tr>
<tr><td><code>subIfIdx</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Sub-interface index</td></tr>
<tr><td><code>loopback</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is loopback packet?</td></tr>
<tr><td><code>impostor</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Is impostor packet?</td></tr>
<tr><td><code>fragment</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Is IP fragment packet?</td></tr>
<tr><td><code>endpointId</code></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Endpoint ID</td></tr>
<tr><td><code>parentEndpointId</code></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Parent endpoint ID</td></tr>
<tr><td><code>processId</code></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>Process ID</td></tr>
<tr><td><code>random8</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>8-bit random number</td></tr>
<tr><td><code>random16</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>16-bit random number</td></tr>
<tr><td><code>random32</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>32-bit random number</td></tr>
<tr><td><code>layer</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td>The handle's layer</td></tr>
<tr><td><code>priority</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td>The handle's priority</td></tr>
<tr><td><code>packet[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the packet</td></tr>
<tr><td><code>packet16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the packet</td></tr>
<tr><td><code>packet32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the packet</td></tr>
<tr><td><code>length</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The packet length</td></tr>
<tr><td><code>ip</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is IPv4?</td></tr>
<tr><td><code>ipv6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is IPv6?</td></tr>
<tr><td><code>icmp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is ICMP?</td></tr>
<tr><td><code>icmpv6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is ICMPv6?</td></tr>
<tr><td><code>tcp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is TCP?</td></tr>
<tr><td><code>udp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is UDP?</td></tr>
<tr><td><code>protocol</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The protocol</td></tr>
<tr><td><code>localAddr</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The local address</td></tr>
<tr><td><code>localPort</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The local port</td></tr>
<tr><td><code>remoteAddr</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The remote address</td></tr>
<tr><td><code>remotePort</code></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The remote port</td></tr>
<tr><td><code>ip.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>IPv4 fields (see <code>WINDIVERT_IPHDR</code>)</td></tr>
<tr><td><code>ipv6.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>IPv6 fields (see <code>WINDIVERT_IPV6HDR</code>)</td></tr>
<tr><td><code>icmp.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>ICMP fields (see <code>WINDIVERT_ICMPHDR</code>)</td></tr>
<tr><td><code>icmpv6.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>ICMPV6 fields (see <code>WINDIVERT_ICMPV6HDR</code>)</td></tr>
<tr><td><code>tcp.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>TCP fields (see <code>WINDIVERT_TCPHDR</code>)</td></tr>
<tr><td><code>tcp.PayloadLength</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The TCP payload length</td></tr>
<tr><td><code>tcp.Payload[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the TCP payload</td></tr>
<tr><td><code>tcp.Payload16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the TCP payload</td></tr>
<tr><td><code>tcp.Payload32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the TCP payload</td></tr>
<tr><td><code>udp.*</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>UDP fields (see <code>WINDIVERT_UDPHDR</code>)</td></tr>
<tr><td><code>udp.PayloadLength</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The UDP payload length</td></tr>
<tr><td><code>udp.Payload[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the UDP payload</td></tr>
<tr><td><code>udp.Payload16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the UDP payload</td></tr>
<tr><td><code>udp.Payload32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the UDP payload</td></tr>
<tr><th>Field</th><th colspan="6">Layer</th><th>Description</th></tr>
<tr><th></th><th><code>ETHERNET</code></th><th><code>NETWORK</code></th><th><code>FORWARD</code></th><th><code>FLOW&nbsp;&nbsp;&nbsp;</code></th><th><code>SOCKET&nbsp;</code></th><th><code>REFLECT</code></th><th></th></tr>
<tr><td><code>zero</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The value zero</td></tr>
<tr><td><code>timestamp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The packet/event timestamp</td></tr>
<tr><td><code>event</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>The event</td></tr>
<tr><td><code>outbound</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td></td><td></td><td>Is outbound?</td></tr>
<tr><td><code>inbound</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td></td><td></td><td>Is inbound?</td></tr>
<tr><td><code>ifIdx</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Interface index</td></tr>
<tr><td><code>subIfIdx</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Sub-interface index</td></tr>
<tr><td><code>loopback</code></td><td></td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is loopback packet?</td></tr>
<tr><td><code>impostor</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Is impostor packet?</td></tr>
<tr><td><code>fragment</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>Is IP fragment packet?</td></tr>
<tr><td><code>endpointId</code></td><td></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Endpoint ID</td></tr>
<tr><td><code>parentEndpointId</code></td><td></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>Parent endpoint ID</td></tr>
<tr><td><code>processId</code></td><td></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>Process ID</td></tr>
<tr><td><code>random8</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>8-bit random number</td></tr>
<tr><td><code>random16</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>16-bit random number</td></tr>
<tr><td><code>random32</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>32-bit random number</td></tr>
<tr><td><code>layer</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td>The handle's layer</td></tr>
<tr><td><code>priority</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td>The handle's priority</td></tr>
<tr><td><code>packet[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the packet</td></tr>
<tr><td><code>packet16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the packet</td></tr>
<tr><td><code>packet32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the packet</td></tr>
<tr><td><code>length</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The packet length</td></tr>
<tr><td><code>ip</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is IPv4?</td></tr>
<tr><td><code>ipv6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is IPv6?</td></tr>
<tr><td><code>icmp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is ICMP?</td></tr>
<tr><td><code>icmpv6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is ICMPv6?</td></tr>
<tr><td><code>tcp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is TCP?</td></tr>
<tr><td><code>udp</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td>Is UDP?</td></tr>
<tr><td><code>protocol</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The protocol</td></tr>
<tr><td><code>localAddr</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The local address</td></tr>
<tr><td><code>localPort</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The local port</td></tr>
<tr><td><code>remoteAddr</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The remote address</td></tr>
<tr><td><code>remotePort</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td>The remote port</td></tr>
<tr><td><code>eth.*</code></td><td>&#10004;</td><td></td><td></td><td></td><td></td><td></td><td>Ethernet fields (see <code>WINDIVERT_ETHHDR</code>)</td></tr>
<tr><td><code>ip.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>IPv4 fields (see <code>WINDIVERT_IPHDR</code>)</td></tr>
<tr><td><code>ipv6.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>IPv6 fields (see <code>WINDIVERT_IPV6HDR</code>)</td></tr>
<tr><td><code>icmp.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>ICMP fields (see <code>WINDIVERT_ICMPHDR</code>)</td></tr>
<tr><td><code>icmpv6.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>ICMPV6 fields (see <code>WINDIVERT_ICMPV6HDR</code>)</td></tr>
<tr><td><code>tcp.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>TCP fields (see <code>WINDIVERT_TCPHDR</code>)</td></tr>
<tr><td><code>tcp.PayloadLength</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The TCP payload length</td></tr>
<tr><td><code>tcp.Payload[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the TCP payload</td></tr>
<tr><td><code>tcp.Payload16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the TCP payload</td></tr>
<tr><td><code>tcp.Payload32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the TCP payload</td></tr>
<tr><td><code>udp.*</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>UDP fields (see <code>WINDIVERT_UDPHDR</code>)</td></tr>
<tr><td><code>udp.PayloadLength</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The UDP payload length</td></tr>
<tr><td><code>udp.Payload[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 8-bit word of the UDP payload</td></tr>
<tr><td><code>udp.Payload16[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 16-bit word of the UDP payload</td></tr>
<tr><td><code>udp.Payload32[i]</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td>The <code>i</code><sup>th</sup> 32-bit word of the UDP payload</td></tr>
</table>
</center>
<p>
@@ -2799,6 +2981,7 @@ packet does not contain a TCP header.
The <code>processId</code> field matches the ID of the process associated
to an event.
Due to technical limitations, this field is not supported by the
<code>WINDIVERT_LAYER_ETHERNET</code> and
<code>WINDIVERT_LAYER_NETWORK*</code> layers.
That said, it is usually possible to associate process IDs to network packets
matching the same network 5-tuple.
@@ -2843,31 +3026,33 @@ The possible macros are:
</p>
<center>
<table border="1" cellpadding="5" width="75%">
<tr><th>Macro</th><th colspan="5">Layer</th><th>Value</th></tr>
<tr><th></th><th><code>NETWORK</code></th><th><code>FORWARD</code></th><th><code>FLOW&nbsp;&nbsp;&nbsp;</code></th><th><code>SOCKET&nbsp;</code></th><th><code>REFLECT</code></th><th></th></tr>
<tr><td><code>TRUE</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>1</code></td></tr>
<tr><td><code>FALSE</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>0</code></td></tr>
<tr><td><code>TCP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_TCP</code> (<code>6</code>)</td></tr>
<tr><td><code>UDP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_UDP</code> (<code>17</code>)</td></tr>
<tr><td><code>ICMP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_ICMP</code> (<code>1</code>)</td></tr>
<tr><td><code>ICMPV6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_ICMPV6</code> (<code>58</code>)</td></tr>
<tr><td><code>PACKET</code></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td><code>WINDIVERT_EVENT_NETWORK_PACKET</code></td></tr>
<tr><td><code>ESTABLISHED</code></td><td></td><td></td><td>&#10004;</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_ESTABLISHED</code></td></tr>
<tr><td><code>DELETED</code></td><td></td><td></td><td>&#10004;</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_DELETED</code></td></tr>
<tr><td><code>BIND</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_BIND</code></td></tr>
<tr><td><code>CONNECT</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_CONNECT</code></td></tr>
<tr><td><code>ACCEPT</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_ACCEPT</code></td></tr>
<tr><td><code>LISTEN</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_LISTEN</code></td></tr>
<tr><td><code>OPEN</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_EVENT_REFLECT_OPEN</code></td></tr>
<tr><td><code>CLOSE</code></td><td></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td><code>WINDIVERT_EVENT_SOCKET_CLOSE</code>
<tr><th>Macro</th><th colspan="6">Layer</th><th>Value</th></tr>
<tr><th></th><th><code>ETHERNET</code></th><th><code>NETWORK</code></th><th><code>FORWARD</code></th><th><code>FLOW&nbsp;&nbsp;&nbsp;</code></th><th><code>SOCKET&nbsp;</code></th><th><code>REFLECT</code></th><th></th></tr>
<tr><td><code>TRUE</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>1</code></td></tr>
<tr><td><code>FALSE</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>0</code></td></tr>
<tr><td><code>TCP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_TCP</code> (<code>6</code>)</td></tr>
<tr><td><code>UDP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_UDP</code> (<code>17</code>)</td></tr>
<tr><td><code>ICMP</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_ICMP</code> (<code>1</code>)</td></tr>
<tr><td><code>ICMPV6</code></td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td>&#10004;</td><td><code>IPPROTO_ICMPV6</code> (<code>58</code>)</td></tr>
<tr><td><code>FRAME</code></td><td>&#10004;</td><td></td><td></td><td></td><td></td><td></td><td><code>WINDIVERT_EVENT_ETHERNET_FRAME</code></td></tr>
<tr><td><code>PACKET</code></td><td></td><td>&#10004;</td><td>&#10004;</td><td></td><td></td><td></td><td><code>WINDIVERT_EVENT_NETWORK_PACKET</code></td></tr>
<tr><td><code>ESTABLISHED</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_ESTABLISHED</code></td></tr>
<tr><td><code>DELETED</code></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td></td><td><code>WINDIVERT_EVENT_FLOW_DELETED</code></td></tr>
<tr><td><code>BIND</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_BIND</code></td></tr>
<tr><td><code>CONNECT</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_CONNECT</code></td></tr>
<tr><td><code>ACCEPT</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_ACCEPT</code></td></tr>
<tr><td><code>LISTEN</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td></td><td><code>WINDIVERT_EVENT_SOCKET_LISTEN</code></td></tr>
<tr><td><code>OPEN</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_EVENT_REFLECT_OPEN</code></td></tr>
<tr><td><code>CLOSE</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td>&#10004;</td><td><code>WINDIVERT_EVENT_SOCKET_CLOSE</code>
for the <code>SOCKET</code> layer, or
<code>WINDIVERT_EVENT_REFLECT_CLOSE</code> for the <code>REFLECT</code>
layer.</td></tr>
<tr><td><code>NETWORK</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_NETWORK</code></td></tr>
<tr><td><code>NETWORK_FORWARD</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_NETWORK_FORWARD</code></td></tr>
<tr><td><code>FLOW</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_FLOW</code></td></tr>
<tr><td><code>SOCKET</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_SOCKET</code></td></tr>
<tr><td><code>REFLECT</code></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_REFLECT</code></td></tr>
<tr><td><code>ETHERNET</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_ETHERNET</code></td></tr>
<tr><td><code>NETWORK</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_NETWORK</code></td></tr>
<tr><td><code>NETWORK_FORWARD</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_NETWORK_FORWARD</code></td></tr>
<tr><td><code>FLOW</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_FLOW</code></td></tr>
<tr><td><code>SOCKET</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_SOCKET</code></td></tr>
<tr><td><code>REFLECT</code></td><td></td><td></td><td></td><td></td><td></td><td>&#10004;</td><td><code>WINDIVERT_LAYER_REFLECT</code></td></tr>
</table>
</center>
@@ -2880,7 +3065,7 @@ Divert all outbound (non-local) web traffic:
HANDLE handle = WinDivertOpen(
"outbound and !loopback and "
"(tcp.DstPort == 80 or udp.DstPort == 53)",
0, 0, 0
WINDIVERT_LAYER_NETWORK, 0, 0
);
</pre>
</li>
@@ -2890,20 +3075,20 @@ Divert all inbound TCP SYNs:
HANDLE handle = WinDivertOpen(
"inbound and "
"tcp.Syn",
0, 0, 0
WINDIVERT_LAYER_NETWORK, 0, 0
);
</pre>
</li>
<li>
Divert all traffic:
<pre>
HANDLE handle = WinDivertOpen("true", 0, 0, 0);
HANDLE handle = WinDivertOpen("true", WINDIVERT_LAYER_NETWORK, 0, 0);
</pre>
</li>
<li>
Divert no traffic:
<pre>
HANDLE handle = WinDivertOpen("false", 0, 0, 0);
HANDLE handle = WinDivertOpen("false", WINDIVERT_LAYER_NETWORK, 0, 0);
</pre>
This is useful for packet injection.
</ol>
+66 -22
View File
@@ -37,7 +37,7 @@
* This is a simple traffic monitor. It uses a WinDivert handle in SNIFF mode.
* The SNIFF mode copies packets and does not block the original.
*
* usage: netdump.exe windivert-filter [priority]
* usage: netdump.exe windivert-filter [priority] [layer]
*
*/
@@ -60,17 +60,21 @@
int __cdecl main(int argc, char **argv)
{
HANDLE handle, console;
DWORD err;
UINT i;
WINDIVERT_LAYER layer = WINDIVERT_LAYER_NETWORK;
INT16 priority = 0;
unsigned char packet[MAXBUF];
UINT packet_len;
WINDIVERT_ADDRESS addr;
PWINDIVERT_ETHHDR eth_header;
PWINDIVERT_IPHDR ip_header;
PWINDIVERT_IPV6HDR ipv6_header;
PWINDIVERT_ICMPHDR icmp_header;
PWINDIVERT_ICMPV6HDR icmpv6_header;
PWINDIVERT_TCPHDR tcp_header;
PWINDIVERT_UDPHDR udp_header;
UINT8 src_mac[6], dst_mac[6];
UINT32 src_addr[4], dst_addr[4];
UINT64 hash;
char src_str[INET6_ADDRSTRLEN+1], dst_str[INET6_ADDRSTRLEN+1];
@@ -81,19 +85,44 @@ int __cdecl main(int argc, char **argv)
// Check arguments.
switch (argc)
{
case 2:
break;
case 4:
if (strcmp(argv[3], "network") == 0)
{
layer = WINDIVERT_LAYER_NETWORK;
}
else if (strcmp(argv[3], "forward") == 0)
{
layer = WINDIVERT_LAYER_NETWORK_FORWARD;
}
else if (strcmp(argv[3], "ethernet") == 0)
{
layer = WINDIVERT_LAYER_ETHERNET;
}
else
{
goto usage;
}
// Fallthrough
case 3:
priority = (INT16)atoi(argv[2]);
// Fallthrough
case 2:
break;
default:
fprintf(stderr, "usage: %s windivert-filter [priority]\n",
usage:
fprintf(stderr, "usage: %s windivert-filter [priority] [layer]\n\n",
argv[0]);
fprintf(stderr, "where:\n");
fprintf(stderr, "\t- priority is an integer between "
"-30000..30000 (default = %d)\n", (int)priority);
fprintf(stderr, "\t- layer is one of ethernet/network/forward "
"(default = network)\n\n");
fprintf(stderr, "examples:\n");
fprintf(stderr, "\t%s true\n", argv[0]);
fprintf(stderr, "\t%s \"outbound and tcp.DstPort == 80\" 1000\n",
fprintf(stderr, "\t%s \"outbound and tcp.DstPort == 80\" 1000 "
"network\n", argv[0]);
fprintf(stderr, "\t%s \"inbound and tcp.Syn\" -400 ethernet\n",
argv[0]);
fprintf(stderr, "\t%s \"inbound and tcp.Syn\" -400\n", argv[0]);
exit(EXIT_FAILURE);
}
@@ -101,11 +130,11 @@ int __cdecl main(int argc, char **argv)
console = GetStdHandle(STD_OUTPUT_HANDLE);
// Divert traffic matching the filter:
handle = WinDivertOpen(argv[1], WINDIVERT_LAYER_NETWORK, priority,
WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_FRAGMENTS);
handle = WinDivertOpen(argv[1], layer, priority, WINDIVERT_FLAG_SNIFF);
if (handle == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_INVALID_PARAMETER &&
err = GetLastError();
if (err == ERROR_INVALID_PARAMETER &&
!WinDivertHelperCompileFilter(argv[1], WINDIVERT_LAYER_NETWORK,
NULL, 0, &err_str, NULL))
{
@@ -113,7 +142,7 @@ int __cdecl main(int argc, char **argv)
exit(EXIT_FAILURE);
}
fprintf(stderr, "error: failed to open the WinDivert device (%d)\n",
GetLastError());
err);
exit(EXIT_FAILURE);
}
@@ -156,24 +185,39 @@ int __cdecl main(int argc, char **argv)
}
// Print info about the matching packet.
WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header,
NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
NULL, NULL, NULL);
if (ip_header == NULL && ipv6_header == NULL)
{
fprintf(stderr, "warning: junk packet\n");
}
WinDivertHelperParsePacket(packet, packet_len, addr.Layer,
&eth_header, &ip_header, &ipv6_header, NULL, &icmp_header,
&icmpv6_header, &tcp_header, &udp_header, NULL, NULL);
// Dump packet info:
putchar('\n');
SetConsoleTextAttribute(console, FOREGROUND_RED);
time_passed = (double)(addr.Timestamp - base.QuadPart) /
(double)freq.QuadPart;
hash = WinDivertHelperHashPacket(packet, packet_len, 0);
printf("Packet [Timestamp=%.8g, Direction=%s IfIdx=%u SubIfIdx=%u "
"Loopback=%u Hash=0x%.16llX]\n",
time_passed, (addr.Outbound? "outbound": "inbound"),
addr.Network.IfIdx, addr.Network.SubIfIdx, addr.Loopback, hash);
hash = WinDivertHelperHashPacket(packet, packet_len, addr.Layer, 0);
if (eth_header != NULL)
{
printf("Packet [Timestamp=%.8g Length=%u Direction=%s IfIdx=%u "
"SubIfIdx=%u Hash=0x%.16llX]\n",
time_passed, packet_len, (addr.Outbound? "outbound": "inbound"),
addr.Ethernet.IfIdx, addr.Ethernet.SubIfIdx, hash);
WinDivertHelperNtohMACAddress(eth_header->SrcAddr, src_mac);
WinDivertHelperNtohMACAddress(eth_header->DstAddr, dst_mac);
WinDivertHelperFormatMACAddress(src_mac, src_str, sizeof(src_str));
WinDivertHelperFormatMACAddress(dst_mac, dst_str, sizeof(dst_str));
SetConsoleTextAttribute(console,
FOREGROUND_GREEN | FOREGROUND_BLUE);
printf("Ethernet [SrcAddr=%s DstAddr=%s Type=0x%.4X]\n",
src_str, dst_str, ntohs(eth_header->Type));
}
else
{
printf("Packet [Timestamp=%.8g Length=%u Direction=%s IfIdx=%u "
"SubIfIdx=%u Loopback=%u Hash=0x%.16llX]\n",
time_passed, packet_len, (addr.Outbound? "outbound": "inbound"),
addr.Network.IfIdx, addr.Network.SubIfIdx, addr.Loopback,
hash);
}
if (ip_header != NULL)
{
WinDivertHelperFormatIPv4Address(ntohl(ip_header->SrcAddr),
+8 -7
View File
@@ -201,9 +201,9 @@ int __cdecl main(int argc, char **argv)
}
// Print info about the matching packet.
WinDivertHelperParsePacket(packet, packet_len, &ip_header, &ipv6_header,
NULL, &icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
&payload_len, NULL, NULL);
WinDivertHelperParsePacket(packet, packet_len, recv_addr.Layer, NULL,
&ip_header, &ipv6_header, NULL, &icmp_header, &icmpv6_header,
&tcp_header, &udp_header, NULL, &payload_len);
if (ip_header == NULL && ipv6_header == NULL)
{
continue;
@@ -290,7 +290,7 @@ int __cdecl main(int argc, char **argv)
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
send_addr.Outbound = !recv_addr.Outbound;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(TCPPACKET),
&send_addr, 0);
WINDIVERT_LAYER_NETWORK, &send_addr, 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(TCPPACKET),
NULL, &send_addr))
{
@@ -317,7 +317,8 @@ int __cdecl main(int argc, char **argv)
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
send_addr.Outbound = !recv_addr.Outbound;
WinDivertHelperCalcChecksums((PVOID)resetv6,
sizeof(TCPV6PACKET), &send_addr, 0);
sizeof(TCPV6PACKET), WINDIVERT_LAYER_NETWORK, &send_addr,
0);
if (!WinDivertSend(handle, (PVOID)resetv6, sizeof(TCPV6PACKET),
NULL, &send_addr))
{
@@ -343,7 +344,7 @@ int __cdecl main(int argc, char **argv)
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
send_addr.Outbound = !recv_addr.Outbound;
WinDivertHelperCalcChecksums((PVOID)dnr, icmp_length,
&send_addr, 0);
WINDIVERT_LAYER_NETWORK, &send_addr, 0);
if (!WinDivertSend(handle, (PVOID)dnr, icmp_length, NULL,
&send_addr))
{
@@ -366,7 +367,7 @@ int __cdecl main(int argc, char **argv)
memcpy(&send_addr, &recv_addr, sizeof(send_addr));
send_addr.Outbound = !recv_addr.Outbound;
WinDivertHelperCalcChecksums((PVOID)dnrv6, icmpv6_length,
&send_addr, 0);
WINDIVERT_LAYER_NETWORK, &send_addr, 0);
if (!WinDivertSend(handle, (PVOID)dnrv6, icmpv6_length,
NULL, &send_addr))
{
+144 -60
View File
@@ -38,6 +38,7 @@
* useful for performance testing.
*
* usage: passthru.exe [windivert-filter] [num-threads] [batch-size] [priority]
* [layer]
*/
#include <winsock2.h>
@@ -47,69 +48,162 @@
#include "windivert.h"
#define MTU 1500
typedef struct
{
HANDLE handle;
int batch;
} CONFIG, *PCONFIG;
static DWORD passthru(LPVOID arg);
/*
* Options.
*/
static int threads = 1;
static int batch = WINDIVERT_BATCH_MAX;
static int priority = 0;
static WINDIVERT_LAYER layer = WINDIVERT_LAYER_NETWORK;
static int size = (0x10000 + 4096);
/*
* Print usage and exit.
*/
static void usage(const char *prog)
{
fprintf(stderr, "usage: %s [OPTIONS] filter-string\n\n", prog);
fprintf(stderr, "OPTIONS:\n");
fprintf(stderr, "\t--batch N\n");
fprintf(stderr, "\t\tSet the batch size to N (default=%u)\n",
WINDIVERT_BATCH_MAX);
fprintf(stderr, "\t--layer LAYER\n");
fprintf(stderr, "\t\tSet the filter layer to LAYER (default=network).\n");
fprintf(stderr, "\t\tValid values are {ethernet,network,forward}.\n");
fprintf(stderr, "\t--priority N\n");
fprintf(stderr, "\t\tSet the filter priority to N (default=0)\n");
fprintf(stderr, "\t--size N\n");
fprintf(stderr, "\t\tSet the buffer size to N (default=%u)\n",
(0x10000 + 4096));
fprintf(stderr, "\t--threads N\n");
fprintf(stderr, "\t\tSet the number of threads to be N (default=1)\n");
exit(EXIT_FAILURE);
}
/*
* Parse options.
*/
static const char *parse_options(int argc, char **argv)
{
int i;
size_t n;
const char *filter = NULL, *opt, *arg;
for (i = 1; i < argc; i++)
{
opt = argv[i];
if (opt[0] != '-' || opt[1] != '-')
{
if (filter != NULL)
{
usage(argv[0]);
}
filter = opt;
continue;
}
opt += 2;
arg = strchr(opt, '=');
if (arg == NULL)
{
i++;
if (i >= argc)
{
usage(argv[0]);
}
arg = argv[i];
n = strlen(opt);
}
else
{
n = arg - opt;
arg++;
}
if (strncmp(opt, "threads", n) == 0)
{
threads = atoi(arg);
}
else if (strncmp(opt, "batch", n) == 0)
{
batch = atoi(arg);
}
else if (strncmp(opt, "priority", n) == 0)
{
priority = atoi(arg);
}
else if (strncmp(opt, "size", n) == 0)
{
size = atoi(arg);
}
else if (strncmp(opt, "layer", n) == 0)
{
if (strcmp(arg, "ethernet") == 0)
{
layer = WINDIVERT_LAYER_ETHERNET;
}
else if (strcmp(arg, "network") == 0)
{
layer = WINDIVERT_LAYER_NETWORK;
}
else if (strcmp(arg, "forward") == 0)
{
layer = WINDIVERT_LAYER_NETWORK_FORWARD;
}
else
{
usage(argv[0]);
}
}
else
{
usage(argv[0]);
}
}
return (filter == NULL? "true": filter);
}
/*
* Entry.
*/
int __cdecl main(int argc, char **argv)
{
const char *filter = "true";
int threads = 1, batch = 1, priority = 0;
const char *filter;
int i;
HANDLE handle, thread;
CONFIG config;
if (argc > 5)
filter = parse_options(argc, argv);
if (threads < 1 || threads > 64)
{
fprintf(stderr, "usage: %s [filter] [num-threads] [batch-size] "
"[priority]\n", argv[0]);
fprintf(stderr, "error: number of threads must be within "
"the range 1..64, found %d\n", threads);
exit(EXIT_FAILURE);
}
if (argc >= 2)
if (batch < 1 || batch > WINDIVERT_BATCH_MAX)
{
filter = argv[1];
fprintf(stderr, "error: batch size must be within the range 1..%u, "
"found %d\n", WINDIVERT_BATCH_MAX, batch);
exit(EXIT_FAILURE);
}
if (argc >= 3)
if (priority < WINDIVERT_PRIORITY_LOWEST ||
priority > WINDIVERT_PRIORITY_HIGHEST)
{
threads = atoi(argv[2]);
if (threads < 1 || threads > 64)
{
fprintf(stderr, "error: invalid number of threads\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "error: priority must be within the range %d..%d, "
"found %d\n", WINDIVERT_PRIORITY_LOWEST,
WINDIVERT_PRIORITY_HIGHEST, priority);
exit(EXIT_FAILURE);
}
if (argc >= 4)
if (size < 1 || size >= WINDIVERT_BATCH_MAX * WINDIVERT_MTU_MAX)
{
batch = atoi(argv[3]);
if (batch <= 0 || batch > WINDIVERT_BATCH_MAX)
{
fprintf(stderr, "error: invalid batch size\n");
exit(EXIT_FAILURE);
}
}
if (argc >= 5)
{
priority = atoi(argv[4]);
if (priority < WINDIVERT_PRIORITY_LOWEST ||
priority > WINDIVERT_PRIORITY_HIGHEST)
{
fprintf(stderr, "error: invalid priority value\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "error: buffer size must be within the range 1..%d, "
"found %d\n", WINDIVERT_BATCH_MAX * WINDIVERT_MTU_MAX,
size);
exit(EXIT_FAILURE);
}
// Divert traffic matching the filter:
handle = WinDivertOpen(filter, WINDIVERT_LAYER_NETWORK, (INT16)priority,
0);
handle = WinDivertOpen(filter, layer, (INT16)priority, 0);
if (handle == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_INVALID_PARAMETER)
@@ -123,12 +217,10 @@ int __cdecl main(int argc, char **argv)
}
// Start the threads
config.handle = handle;
config.batch = batch;
for (i = 1; i < threads; i++)
{
thread = CreateThread(NULL, 1, (LPTHREAD_START_ROUTINE)passthru,
(LPVOID)&config, 0, NULL);
(LPVOID)handle, 0, NULL);
if (thread == NULL)
{
fprintf(stderr, "error: failed to start passthru thread (%d)\n",
@@ -138,8 +230,8 @@ int __cdecl main(int argc, char **argv)
}
// Main thread:
passthru((LPVOID)&config);
passthru((LPVOID)handle);
return 0;
}
@@ -147,19 +239,11 @@ int __cdecl main(int argc, char **argv)
static DWORD passthru(LPVOID arg)
{
UINT8 *packet;
UINT packet_len, recv_len, addr_len;
UINT packet_len, addr_len;
WINDIVERT_ADDRESS *addr;
PCONFIG config = (PCONFIG)arg;
HANDLE handle;
int batch;
HANDLE handle = (HANDLE)arg;
handle = config->handle;
batch = config->batch;
packet_len = batch * MTU;
packet_len =
(packet_len < WINDIVERT_MTU_MAX? WINDIVERT_MTU_MAX: packet_len);
packet = (UINT8 *)malloc(packet_len);
packet = (UINT8 *)malloc(size);
addr = (WINDIVERT_ADDRESS *)malloc(batch * sizeof(WINDIVERT_ADDRESS));
if (packet == NULL || addr == NULL)
{
@@ -173,7 +257,7 @@ static DWORD passthru(LPVOID arg)
{
// Read a matching packet.
addr_len = batch * sizeof(WINDIVERT_ADDRESS);
if (!WinDivertRecvEx(handle, packet, packet_len, &recv_len, 0,
if (!WinDivertRecvEx(handle, packet, size, &packet_len, 0,
addr, &addr_len, NULL))
{
fprintf(stderr, "warning: failed to read packet (%d)\n",
@@ -182,7 +266,7 @@ static DWORD passthru(LPVOID arg)
}
// Re-inject the matching packet.
if (!WinDivertSendEx(handle, packet, recv_len, NULL, 0, addr,
if (!WinDivertSendEx(handle, packet, packet_len, NULL, 0, addr,
addr_len, NULL))
{
fprintf(stderr, "warning: failed to reinject packet (%d)\n",
+3 -3
View File
@@ -193,8 +193,8 @@ int __cdecl main(int argc, char **argv)
continue;
}
WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL, NULL,
NULL, NULL, &tcp_header, NULL, NULL, NULL, NULL, NULL);
WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL,
&ip_header, NULL, NULL, NULL, NULL, &tcp_header, NULL, NULL, NULL);
if (ip_header == NULL || tcp_header == NULL)
{
warning("failed to parse packet (%d)", GetLastError());
@@ -236,7 +236,7 @@ int __cdecl main(int argc, char **argv)
}
}
WinDivertHelperCalcChecksums(packet, packet_len, &addr, 0);
WinDivertHelperCalcChecksums(packet, packet_len, addr.Layer, &addr, 0);
if (!WinDivertSend(handle, packet, packet_len, NULL, &addr))
{
warning("failed to send packet (%d)", GetLastError());
+9 -6
View File
@@ -204,9 +204,9 @@ int __cdecl main(int argc, char **argv)
continue;
}
WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, NULL, &tcp_header, NULL, &payload, &payload_len,
NULL, NULL);
WinDivertHelperParsePacket(packet, packet_len, addr.Layer, NULL,
&ip_header, NULL, NULL, NULL, NULL, &tcp_header, NULL, &payload,
&payload_len);
if (ip_header == NULL || tcp_header == NULL || payload == NULL ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
@@ -230,7 +230,8 @@ int __cdecl main(int argc, char **argv)
reset->tcp.DstPort = htons(80);
reset->tcp.SeqNum = tcp_header->SeqNum;
reset->tcp.AckNum = tcp_header->AckNum;
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET), &addr, 0);
WinDivertHelperCalcChecksums((PVOID)reset, sizeof(PACKET),
addr.Layer, &addr, 0);
if (!WinDivertSend(handle, (PVOID)reset, sizeof(PACKET), NULL, &addr))
{
fprintf(stderr, "warning: failed to send reset packet (%d)\n",
@@ -245,7 +246,8 @@ int __cdecl main(int argc, char **argv)
blockpage->header.tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
addr.Outbound = !addr.Outbound; // Reverse direction.
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len, &addr, 0);
WinDivertHelperCalcChecksums((PVOID)blockpage, blockpage_len,
addr.Layer, &addr, 0);
if (!WinDivertSend(handle, (PVOID)blockpage, blockpage_len, NULL,
&addr))
{
@@ -263,7 +265,8 @@ int __cdecl main(int argc, char **argv)
htonl(ntohl(tcp_header->AckNum) + sizeof(block_data) - 1);
finish->tcp.AckNum =
htonl(ntohl(tcp_header->SeqNum) + payload_len);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET), &addr, 0);
WinDivertHelperCalcChecksums((PVOID)finish, sizeof(PACKET),
addr.Layer, &addr, 0);
if (!WinDivertSend(handle, (PVOID)finish, sizeof(PACKET), NULL, &addr))
{
fprintf(stderr, "warning: failed to send finish packet (%d)\n",
+4 -1
View File
@@ -244,11 +244,14 @@ usage:
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
switch (addr.Reflect.Layer)
{
case WINDIVERT_LAYER_ETHERNET:
fputs("ETHERNET", stdout);
break;
case WINDIVERT_LAYER_NETWORK:
fputs("NETWORK", stdout);
break;
case WINDIVERT_LAYER_NETWORK_FORWARD:
fputs("NETWORK_FORWARD", stdout);
fputs("FORWARD", stdout);
break;
case WINDIVERT_LAYER_FLOW:
fputs("FLOW", stdout);
+52 -6
View File
@@ -79,8 +79,18 @@ typedef enum
WINDIVERT_LAYER_FLOW = 2, /* Flow layer. */
WINDIVERT_LAYER_SOCKET = 3, /* Socket layer. */
WINDIVERT_LAYER_REFLECT = 4, /* Reflect layer. */
WINDIVERT_LAYER_ETHERNET = 5, /* Ethernet layer. */
} WINDIVERT_LAYER, *PWINDIVERT_LAYER;
/*
* WinDivert ETHERNET layer data.
*/
typedef struct
{
UINT32 IfIdx; /* Packet's interface index. */
UINT32 SubIfIdx; /* Packet's sub-interface index. */
} WINDIVERT_DATA_ETHERNET, *PWINDIVERT_DATA_ETHERNET;
/*
* WinDivert NETWORK and NETWORK_FORWARD layer data.
*/
@@ -153,9 +163,12 @@ typedef struct
UINT32 TCPChecksum:1; /* Packet has valid TCP checksum? */
UINT32 UDPChecksum:1; /* Packet has valid UDP checksum? */
UINT32 Reserved1:8;
UINT32 Reserved2;
UINT32 Reserved2:12;
UINT32 Length:20; /* Packet length. */
union
{
WINDIVERT_DATA_ETHERNET Ethernet;
/* Ethernet layer data. */
WINDIVERT_DATA_NETWORK Network; /* Network layer data. */
WINDIVERT_DATA_FLOW Flow; /* Flow layer data. */
WINDIVERT_DATA_SOCKET Socket; /* Socket layer data. */
@@ -183,6 +196,7 @@ typedef enum
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_ETHERNET_FRAME = 10,/* Ethernet frame. */
} WINDIVERT_EVENT, *PWINDIVERT_EVENT;
/*
@@ -336,8 +350,15 @@ WINDIVERTEXPORT BOOL WinDivertGetParam(
#endif
/*
* IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions.
* Ethernet/IPv4/IPv6/ICMP/ICMPv6/TCP/UDP header definitions.
*/
typedef struct
{
UINT8 DstAddr[6];
UINT8 SrcAddr[6];
UINT16 Type;
} WINDIVERT_ETHHDR, *PWINDIVERT_ETHHDR;
typedef struct
{
UINT8 HdrLength:4;
@@ -490,6 +511,7 @@ typedef struct
WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
__in const VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__in UINT64 seed
#ifdef __cplusplus
= 0
@@ -502,6 +524,8 @@ WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
__in const VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__out_opt PWINDIVERT_ETHHDR *ppEthHdr,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
__out_opt UINT8 *pProtocol,
@@ -510,9 +534,14 @@ WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
__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);
__out_opt UINT *pDataLen);
/*
* Parse a MAC address.
*/
WINDIVERTEXPORT BOOL WinDivertHelperParseMACAddress(
__in const char *addrStr,
__out_opt UINT8 *pAddr);
/*
* Parse an IPv4 address.
@@ -528,6 +557,14 @@ WINDIVERTEXPORT BOOL WinDivertHelperParseIPv6Address(
__in const char *addrStr,
__out_opt UINT32 *pAddr);
/*
* Format a MAC address.
*/
WINDIVERTEXPORT BOOL WinDivertHelperFormatMACAddress(
__in const UINT8 *pAddr,
__out char *buffer,
__in UINT bufLen);
/*
* Format an IPv4 address.
*/
@@ -550,6 +587,7 @@ WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums(
__inout VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__out_opt WINDIVERT_ADDRESS *pAddr,
__in UINT64 flags);
@@ -558,7 +596,8 @@ WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums(
*/
WINDIVERTEXPORT BOOL WinDivertHelperDecrementTTL(
__inout VOID *pPacket,
__in UINT packetLen);
__in UINT packetLen,
__in WINDIVERT_LAYER layer);
/*
* Compile the given filter string.
@@ -578,6 +617,7 @@ WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter(
__in const char *filter,
__in const VOID *pPacket,
__in UINT packetLen,
__in WINDIVERT_LAYER layer,
__in const WINDIVERT_ADDRESS *pAddr);
/*
@@ -604,6 +644,12 @@ WINDIVERTEXPORT UINT64 WinDivertHelperNtohll(
__in UINT64 x);
WINDIVERTEXPORT UINT64 WinDivertHelperHtonll(
__in UINT64 x);
WINDIVERTEXPORT void WinDivertHelperNtohMACAddress(
__in const UINT8 *inAddr,
__out UINT8 *outAddr);
WINDIVERTEXPORT void WinDivertHelperHtonMACAddress(
__in const UINT8 *inAddr,
__out UINT8 *outAddr);
WINDIVERTEXPORT void WinDivertHelperNtohIPv6Address(
__in const UINT *inAddr,
__out UINT *outAddr);
+6 -3
View File
@@ -44,8 +44,8 @@
#define WINDIVERT_KERNEL
#include "windivert.h"
#define WINDIVERT_VERSION_MAJOR 2
#define WINDIVERT_VERSION_MINOR 2
#define WINDIVERT_VERSION_MAJOR 3
#define WINDIVERT_VERSION_MINOR 0
#define WINDIVERT_MAGIC_DLL 0x4C4C447669645724ull
#define WINDIVERT_MAGIC_SYS 0x5359537669645723ull
@@ -150,8 +150,11 @@
#define WINDIVERT_FILTER_FIELD_RANDOM16 83
#define WINDIVERT_FILTER_FIELD_RANDOM32 84
#define WINDIVERT_FILTER_FIELD_FRAGMENT 85
#define WINDIVERT_FILTER_FIELD_ETH_DST_ADDR 86
#define WINDIVERT_FILTER_FIELD_ETH_SRC_ADDR 87
#define WINDIVERT_FILTER_FIELD_ETH_TYPE 88
#define WINDIVERT_FILTER_FIELD_MAX \
WINDIVERT_FILTER_FIELD_FRAGMENT
WINDIVERT_FILTER_FIELD_ETH_TYPE
#define WINDIVERT_FILTER_TEST_EQ 0
#define WINDIVERT_FILTER_TEST_NEQ 1
+898 -397
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -69,7 +69,7 @@
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
<PropertyGroup Label="Configuration">
<TargetVersion>Windows7</TargetVersion>
<TargetVersion>Windows8</TargetVersion>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
<ConfigurationType>Driver</ConfigurationType>
+4 -3
View File
@@ -1274,10 +1274,10 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
// non-matching random values have been lost:
if ((!random &&
WinDivertHelperEvalFilter(filter, buf[idx], buf_len[idx],
&addr[idx]) != result) ||
WINDIVERT_LAYER_NETWORK, &addr[idx]) != result) ||
(random && result &&
!WinDivertHelperEvalFilter(filter, buf[idx], buf_len[idx],
&addr[idx])))
WINDIVERT_LAYER_NETWORK, &addr[idx])))
{
fprintf(stderr, "error: filter \"%s\" does not match the given "
"packet\n", filter);
@@ -1415,7 +1415,8 @@ static DWORD monitor_worker(LPVOID arg)
addr.Outbound = TRUE;
addr.IPv6 = (iphdr->Version == 4? FALSE: TRUE);
if (WinDivertHelperEvalFilter(object_1, tests[i].packet->packet,
tests[i].packet->packet_len, &addr) != tests[i].match)
tests[i].packet->packet_len, WINDIVERT_LAYER_NETWORK, &addr)
!= tests[i].match)
{
fprintf(stderr, "error: failed to match recompiled filter "
"(test = %.3u, filter = \"%s\" formatted = \"%s\", "