Minor API improvements.

- addr.Pseudo*Checksum flags replaced by simpler
  addr.*Checksum flags.
- WinDivertHelperParsePacket() can now handle
  batched packets.
- WinDivertHelperParsePacket() can now return the
  transport protocol.
- WinDivertHelperCalcChecksums() can now handle
  batched packets.
- WinDivertHelperCalcChecksums() now sets address
  checksum flags that were calculated.
- A bunch of WINDIVERT_* macros have been moved
  to windivert.h for windivert_device.h.
This commit is contained in:
basil00
2019-02-17 11:08:10 +08:00
parent 42bf883096
commit ab50ffebd5
11 changed files with 218 additions and 232 deletions
+7 -20
View File
@@ -284,19 +284,6 @@ static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
WINDIVERT_LAYER layer, BOOL top_level, BOOL and);
/*
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
UINT *pDataLen)
{
return WinDivertParsePacket((PVOID)pPacket, packetLen, ppIpHdr, ppIpv6Hdr,
ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL, ppData, pDataLen);
}
/*
* Parse an IPv4 address.
*/
@@ -2446,9 +2433,9 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
WinDivertParsePacket((PVOID)packet, packet_len, &iphdr, &ipv6hdr,
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
&payload_len);
WinDivertHelperParsePacket((PVOID)packet, packet_len, &protocol,
&iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr, &tcphdr, &udphdr,
NULL, &payload_len, NULL, NULL);
header_len = packet_len - payload_len;
if ((addr->IPv6 && ipv6hdr == NULL) ||
(!addr->IPv6 && iphdr == NULL))
@@ -4599,9 +4586,9 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
PWINDIVERT_TCPHDR tcp_header = NULL;
PWINDIVERT_UDPHDR udp_header = NULL;
WinDivertParsePacket((PVOID)pPacket, packetLen, &ip_header, &ipv6_header,
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL,
NULL, NULL);
WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header,
NULL, NULL, NULL, NULL);
return WinDivertHashPacket(seed, ip_header, ipv6_header, icmp_header,
icmpv6_header, tcp_header, udp_header);
}
@@ -4635,7 +4622,7 @@ extern UINT64 WinDivertHelperHtonll(UINT64 x)
}
static void WinDivertByteSwap128(const UINT *inAddr, UINT *outAddr)
{
UINT32 tmp[4], i; // tmp[] allows overlapping
UINT32 tmp[4], i; // tmp[] allows overlapping inAddr/outAddr
for (i = 0; i < 4; i++)
{
tmp[3-i] = BYTESWAP32(inAddr[0]);
+102 -93
View File
@@ -283,11 +283,11 @@ static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
/*
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
*/
static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
UINT8 *pProtocol, PWINDIVERT_IPHDR *ppIpHdr, PWINDIVERT_IPV6HDR *ppIpv6Hdr,
PWINDIVERT_ICMPHDR *ppIcmpHdr, PWINDIVERT_ICMPV6HDR *ppIcmpv6Hdr,
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, UINT8 *pProto,
PVOID *ppData, UINT *pDataLen)
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
UINT *pDataLen, PVOID *ppNext, UINT *pNextLen)
{
PWINDIVERT_IPHDR ip_header = NULL;
PWINDIVERT_IPV6HDR ipv6_header = NULL;
@@ -297,15 +297,15 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
PWINDIVERT_UDPHDR udp_header = NULL;
UINT16 header_len;
UINT8 trans_proto = 0;
PVOID data = NULL;
UINT data_len = 0;
BOOL success;
PVOID data = NULL, next = NULL;
UINT data_len = 0, next_len = 0, packet_len;
BOOL success = FALSE;
if (pPacket == NULL || packetLen < sizeof(UINT8))
if (pPacket == NULL || packetLen < sizeof(WINDIVERT_IPHDR))
{
goto WinDivertHelperParsePacketExit;
}
data = pPacket;
data = (PVOID)pPacket;
data_len = packetLen;
ip_header = (PWINDIVERT_IPHDR)data;
@@ -315,29 +315,41 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
if (data_len < sizeof(WINDIVERT_IPHDR) ||
ip_header->HdrLength < 5 ||
data_len < ip_header->HdrLength*sizeof(UINT32) ||
ntohs(ip_header->Length) != data_len)
(UINT)ntohs(ip_header->Length) > data_len)
{
ip_header = NULL;
goto WinDivertHelperParsePacketExit;
}
trans_proto = ip_header->Protocol;
packet_len = (UINT)ntohs(ip_header->Length);
header_len = ip_header->HdrLength*sizeof(UINT32);
if (packet_len < data_len)
{
next = (PVOID)((UINT8 *)data + packet_len);
next_len = data_len - packet_len;
}
data = (PVOID)((UINT8 *)data + header_len);
data_len -= header_len;
data_len = packet_len - header_len;
break;
case 6:
ip_header = NULL;
ipv6_header = (PWINDIVERT_IPV6HDR)data;
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
ntohs(ipv6_header->Length) !=
data_len - sizeof(WINDIVERT_IPV6HDR))
ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR) >
data_len)
{
ipv6_header = NULL;
goto WinDivertHelperParsePacketExit;
}
trans_proto = ipv6_header->NextHdr;
packet_len = ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR);
if (packet_len < data_len)
{
next = (PVOID)((UINT8 *)data + packet_len);
next_len = data_len - packet_len;
}
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
data_len -= sizeof(WINDIVERT_IPV6HDR);
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
&data_len);
break;
@@ -345,6 +357,7 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
ip_header = NULL;
goto WinDivertHelperParsePacketExit;
}
success = TRUE;
switch (trans_proto)
{
case IPPROTO_TCP:
@@ -403,50 +416,51 @@ static BOOL WinDivertParsePacket(PVOID pPacket, UINT packetLen,
}
WinDivertHelperParsePacketExit:
success = TRUE;
if (pProtocol != NULL)
{
*pProtocol = trans_proto;
}
if (ppIpHdr != NULL)
{
*ppIpHdr = ip_header;
success = success && (ip_header != NULL);
}
if (ppIpv6Hdr != NULL)
{
*ppIpv6Hdr = ipv6_header;
success = success && (ipv6_header != NULL);
}
if (ppIcmpHdr != NULL)
{
*ppIcmpHdr = icmp_header;
success = success && (icmp_header != NULL);
}
if (ppIcmpv6Hdr != NULL)
{
*ppIcmpv6Hdr = icmpv6_header;
success = success && (icmpv6_header != NULL);
}
if (ppTcpHdr != NULL)
{
*ppTcpHdr = tcp_header;
success = success && (tcp_header != NULL);
}
if (ppUdpHdr != NULL)
{
*ppUdpHdr = udp_header;
success = success && (udp_header != NULL);
}
if (pProto != NULL)
{
*pProto = trans_proto;
}
if (ppData != NULL)
{
*ppData = data;
success = success && (data != NULL);
}
if (pDataLen != NULL)
{
*pDataLen = data_len;
}
if (ppNext != NULL)
{
*ppNext = next;
}
if (pNextLen != NULL)
{
*pNextLen = next_len;
}
return success;
}
@@ -454,7 +468,7 @@ WinDivertHelperParsePacketExit:
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
*/
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
const WINDIVERT_ADDRESS *pAddr, UINT64 flags)
WINDIVERT_ADDRESS *pAddr, UINT64 flags)
{
UINT8 pseudo_header[
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
@@ -468,83 +482,78 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
UINT payload_len, checksum_len;
UINT count = 0;
WinDivertParsePacket(pPacket, packetLen, &ip_header, &ipv6_header,
&icmp_header, &icmpv6_header, &tcp_header, &udp_header, NULL, NULL,
&payload_len);
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
while (WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, &payload_len, &pPacket, &packetLen))
{
ip_header->Checksum = 0;
if (pAddr == NULL || pAddr->PseudoIPChecksum == 0)
{
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0,
ip_header, ip_header->HdrLength*sizeof(UINT32));
}
count++;
}
if (icmp_header != NULL)
{
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
{
return count;
ip_header->Checksum = 0;
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
ip_header->HdrLength*sizeof(UINT32));
if (pAddr != NULL)
{
pAddr->IPChecksum = 1;
}
count++;
}
icmp_header->Checksum = 0;
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
count++;
return count;
}
if (icmpv6_header != NULL)
{
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
if (icmp_header != NULL)
{
return count;
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
{
continue;
}
icmp_header->Checksum = 0;
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
count++;
continue;
}
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
IPPROTO_ICMPV6, checksum_len, pseudo_header);
icmpv6_header->Checksum = 0;
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
pseudo_header_len, icmpv6_header, checksum_len);
count++;
return count;
}
if (tcp_header != NULL)
{
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
if (icmpv6_header != NULL)
{
return count;
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
{
continue;
}
checksum_len = payload_len + sizeof(WINDIVERT_ICMPV6HDR);
pseudo_header_len = WinDivertInitPseudoHeader(NULL, ipv6_header,
IPPROTO_ICMPV6, checksum_len, pseudo_header);
icmpv6_header->Checksum = 0;
icmpv6_header->Checksum = WinDivertCalcChecksum(pseudo_header,
pseudo_header_len, icmpv6_header, checksum_len);
count++;
continue;
}
if (pAddr == NULL || pAddr->PseudoTCPChecksum == 0)
if (tcp_header != NULL)
{
// Full TCP checksum
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
{
continue;
}
checksum_len = payload_len + tcp_header->HdrLength*sizeof(UINT32);
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
ipv6_header, IPPROTO_TCP, checksum_len, pseudo_header);
tcp_header->Checksum = 0;
tcp_header->Checksum = WinDivertCalcChecksum(
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
if (pAddr != NULL)
{
pAddr->TCPChecksum = 1;
}
count++;
continue;
}
else if (pAddr->Outbound)
{
// Pseudo TCP checksum
tcp_header->Checksum = 0;
}
count++;
return count;
}
if (udp_header != NULL)
{
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
{
return count;
}
if (pAddr == NULL || pAddr->PseudoUDPChecksum == 0)
if (udp_header != NULL)
{
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
{
continue;
}
// Full UDP checksum
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
@@ -556,14 +565,14 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
{
udp_header->Checksum = 0xFFFF;
}
if (pAddr != NULL)
{
pAddr->UDPChecksum = 1;
}
count++;
}
else if (pAddr->Outbound)
{
// Pseudo UDP checksum
udp_header->Checksum = 0;
}
count++;
}
return count;
}
+2 -2
View File
@@ -147,9 +147,9 @@ int __cdecl main(int argc, char **argv)
}
// Print info about the matching packet.
WinDivertHelperParsePacket(packet, packet_len, &ip_header,
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, NULL);
&udp_header, NULL, NULL, NULL, NULL);
if (ip_header == NULL && ipv6_header == NULL)
{
fprintf(stderr, "warning: junk packet\n");
+2 -2
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,
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
&udp_header, NULL, &payload_len);
&udp_header, NULL, &payload_len, NULL, NULL);
if (ip_header == NULL && ipv6_header == NULL)
{
continue;
+3 -2
View File
@@ -250,8 +250,9 @@ read_failed:
}
cleanup(ioport, &overlapped);
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, NULL, NULL))
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, NULL, NULL, NULL, NULL);
if (ip_header == NULL || tcp_header == NULL)
{
warning("failed to parse packet (%d)", GetLastError());
continue;
+4 -2
View File
@@ -204,8 +204,10 @@ int __cdecl main(int argc, char **argv)
continue;
}
if (!WinDivertHelperParsePacket(packet, packet_len, &ip_header, NULL,
NULL, NULL, &tcp_header, NULL, &payload, &payload_len) ||
WinDivertHelperParsePacket(packet, packet_len, NULL, &ip_header,
NULL, NULL, NULL, &tcp_header, NULL, &payload, &payload_len,
NULL, NULL);
if (ip_header == NULL || tcp_header == NULL || payload == NULL ||
!BlackListPayloadMatch(blacklist, payload, (UINT16)payload_len))
{
// Packet does not match the blacklist; simply reinject it.
+1 -1
View File
@@ -390,7 +390,7 @@ usage:
fputs(" filter=", stdout);
SetConsoleTextAttribute(console, FOREGROUND_RED | FOREGROUND_GREEN);
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
NULL, NULL, &object, NULL);
NULL, NULL, NULL, &object, NULL, NULL, NULL);
if (WinDivertHelperFormatFilter((char *)object, addr.Reflect.Layer,
filter_str, sizeof(filter_str)))
{
+24 -5
View File
@@ -140,9 +140,9 @@ typedef struct
UINT64 Loopback:1; /* Packet is loopback? */
UINT64 Impostor:1; /* Packet is impostor? */
UINT64 IPv6:1; /* Packet is IPv6? */
UINT64 PseudoIPChecksum:1; /* Packet has pseudo IPv4 checksum? */
UINT64 PseudoTCPChecksum:1; /* Packet has pseudo TCP checksum? */
UINT64 PseudoUDPChecksum:1; /* Packet has pseudo UDP checksum? */
UINT64 IPChecksum:1; /* Packet has valid IPv4 checksum? */
UINT64 TCPChecksum:1; /* Packet has valid TCP checksum? */
UINT64 UDPChecksum:1; /* Packet has valid UDP checksum? */
UINT64 Reserved:41;
union
{
@@ -292,6 +292,22 @@ extern WINDIVERTEXPORT BOOL WinDivertGetParam(
#endif /* WINDIVERT_KERNEL */
/*
* WinDivert constants.
*/
#define WINDIVERT_PRIORITY_LOWEST 30000
#define WINDIVERT_PRIORITY_HIGHEST (-WINDIVERT_PRIORITY_LOWEST)
#define WINDIVERT_PARAM_QUEUE_LEN_DEFAULT 2048
#define WINDIVERT_PARAM_QUEUE_LEN_MIN 16
#define WINDIVERT_PARAM_QUEUE_LEN_MAX 16384
#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 1000 /* 1s */
#define WINDIVERT_PARAM_QUEUE_TIME_MIN 20 /* 20ms */
#define WINDIVERT_PARAM_QUEUE_TIME_MAX 8000 /* 8s */
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 /* 4MB */
#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 /* 64KB */
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 /* 32MB */
#define WINDIVERT_BATCH_MAX 0xFF /* 255 */
/****************************************************************************/
/* WINDIVERT HELPER API */
/****************************************************************************/
@@ -459,6 +475,7 @@ extern WINDIVERTEXPORT UINT64 WinDivertHelperHashPacket(
extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
__in const VOID *pPacket,
__in UINT packetLen,
__out_opt UINT8 *pProtocol,
__out_opt PWINDIVERT_IPHDR *ppIpHdr,
__out_opt PWINDIVERT_IPV6HDR *ppIpv6Hdr,
__out_opt PWINDIVERT_ICMPHDR *ppIcmpHdr,
@@ -466,7 +483,9 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperParsePacket(
__out_opt PWINDIVERT_TCPHDR *ppTcpHdr,
__out_opt PWINDIVERT_UDPHDR *ppUdpHdr,
__out_opt PVOID *ppData,
__out_opt UINT *pDataLen);
__out_opt UINT *pDataLen,
__out_opt PVOID *ppNext,
__out_opt UINT *pNextLen);
/*
* Parse an IPv4 address.
@@ -504,7 +523,7 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums(
__inout VOID *pPacket,
__in UINT packetLen,
__in_opt const WINDIVERT_ADDRESS *pAddr,
__out_opt WINDIVERT_ADDRESS *pAddr,
__in UINT64 flags);
/*
+2 -20
View File
@@ -212,26 +212,8 @@
* WinDivert priorities.
*/
#define WINDIVERT_PRIORITY_DEFAULT 0
#define WINDIVERT_PRIORITY_MAX 30000
#define WINDIVERT_PRIORITY_MIN -WINDIVERT_PRIORITY_MAX
/*
* WinDivert parameters.
*/
#define WINDIVERT_PARAM_QUEUE_LEN_DEFAULT 2048
#define WINDIVERT_PARAM_QUEUE_LEN_MIN 16
#define WINDIVERT_PARAM_QUEUE_LEN_MAX 16384
#define WINDIVERT_PARAM_QUEUE_TIME_DEFAULT 1000 // 1s
#define WINDIVERT_PARAM_QUEUE_TIME_MIN 20 // 20ms
#define WINDIVERT_PARAM_QUEUE_TIME_MAX 8000 // 8s
#define WINDIVERT_PARAM_QUEUE_SIZE_MIN 65535 // 64KB
#define WINDIVERT_PARAM_QUEUE_SIZE_MAX 33554432 // 32MB
#define WINDIVERT_PARAM_QUEUE_SIZE_DEFAULT 4194304 // 4MB
/*
* WinDivert batch limits.
*/
#define WINDIVERT_BATCH_MAX 0xFF
#define WINDIVERT_PRIORITY_MAX WINDIVERT_PRIORITY_LOWEST
#define WINDIVERT_PRIORITY_MIN WINDIVERT_PRIORITY_HIGHEST
/*
* WinDivert message definitions.
+66 -80
View File
@@ -251,9 +251,9 @@ struct packet_s
UINT64 loopback:1; // Packet is loopback?
UINT64 impostor:1; // Packet is impostor?
UINT64 ipv6:1; // Packet is IPv6?
UINT64 pseudo_ip_checksum:1; // Packet has pseudo IPv4 check?
UINT64 pseudo_tcp_checksum:1; // Packet has pseudo TCP check?
UINT64 pseudo_udp_checksum:1; // Packet has pseudo UDP check?
UINT64 ip_checksum:1; // Packet has IPv4 checksum?
UINT64 tcp_checksum:1; // Packet has TCP checksum?
UINT64 udp_checksum:1; // Packet has UDP checksum?
UINT64 match:1; // Packet matches filter?
UINT32 priority; // Packet priority.
UINT32 packet_len; // Length of the packet.
@@ -2006,17 +2006,17 @@ static void windivert_read_service_request(context_t context, packet_t packet,
// Copy the address data:
if (addr != NULL)
{
addr[i].Timestamp = (INT64)packet->timestamp;
addr[i].Layer = packet->layer;
addr[i].Event = packet->event;
addr[i].Outbound = packet->outbound;
addr[i].Loopback = packet->loopback;
addr[i].Impostor = packet->impostor;
addr[i].IPv6 = packet->ipv6;
addr[i].PseudoIPChecksum = packet->pseudo_ip_checksum;
addr[i].PseudoTCPChecksum = packet->pseudo_tcp_checksum;
addr[i].PseudoUDPChecksum = packet->pseudo_udp_checksum;
addr[i].Reserved = 0;
addr[i].Timestamp = (INT64)packet->timestamp;
addr[i].Layer = packet->layer;
addr[i].Event = packet->event;
addr[i].Outbound = packet->outbound;
addr[i].Loopback = packet->loopback;
addr[i].Impostor = packet->impostor;
addr[i].IPv6 = packet->ipv6;
addr[i].IPChecksum = packet->ip_checksum;
addr[i].TCPChecksum = packet->tcp_checksum;
addr[i].UDPChecksum = packet->udp_checksum;
addr[i].Reserved = 0;
layer_data = (PVOID)packet->data;
switch (packet->layer)
{
@@ -2119,7 +2119,7 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
PWINDIVERT_ADDRESS addr;
UINT *addr_len_ptr;
NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO checksums;
BOOL pseudo_ip_checksum, pseudo_tcp_checksum, pseudo_udp_checksum;
BOOL ip_checksum, tcp_checksum, udp_checksum;
NTSTATUS status = STATUS_SUCCESS;
// This function bypasses the normal work_queue -> packet_queue flow, but
@@ -2184,18 +2184,15 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
TcpIpChecksumNetBufferListInfo);
if (outbound)
{
pseudo_ip_checksum = (checksums.Transmit.IpHeaderChecksum != 0);
pseudo_tcp_checksum = (checksums.Transmit.TcpChecksum != 0);
pseudo_udp_checksum = (checksums.Transmit.UdpChecksum != 0);
ip_checksum = (checksums.Transmit.IpHeaderChecksum == 0);
tcp_checksum = (checksums.Transmit.TcpChecksum == 0);
udp_checksum = (checksums.Transmit.UdpChecksum == 0);
}
else
{
pseudo_ip_checksum =
(checksums.Receive.IpChecksumSucceeded != 0);
pseudo_tcp_checksum =
(checksums.Receive.TcpChecksumSucceeded != 0);
pseudo_udp_checksum =
(checksums.Receive.UdpChecksumSucceeded != 0);
ip_checksum = (checksums.Receive.IpChecksumSucceeded == 0);
tcp_checksum = (checksums.Receive.TcpChecksumSucceeded == 0);
udp_checksum = (checksums.Receive.UdpChecksumSucceeded == 0);
}
break;
@@ -2203,14 +2200,12 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
dst_len = (dst_len < packet_len? dst_len: packet_len);
RtlCopyMemory(dst, packet, dst_len);
read_len = dst_len;
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
FALSE;
ip_checksum = tcp_checksum = udp_checksum = FALSE;
break;
default:
read_len = 0;
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
FALSE;
ip_checksum = tcp_checksum = udp_checksum = FALSE;
break;
}
@@ -2220,17 +2215,17 @@ static void windivert_fast_read_service_request(PVOID packet, ULONG packet_len,
if (addr != NULL)
{
addr->Timestamp = timestamp;
addr->Layer = layer;
addr->Event = event;
addr->Outbound = (outbound? 1: 0);
addr->Loopback = (loopback? 1: 0);
addr->Impostor = (impostor? 1: 0);
addr->IPv6 = (ipv4? 0: 1);
addr->PseudoIPChecksum = (pseudo_ip_checksum? 1: 0);
addr->PseudoTCPChecksum = (pseudo_tcp_checksum? 1: 0);
addr->PseudoUDPChecksum = (pseudo_udp_checksum? 1: 0);
addr->Reserved = 0;
addr->Timestamp = timestamp;
addr->Layer = layer;
addr->Event = event;
addr->Outbound = (outbound? 1: 0);
addr->Loopback = (loopback? 1: 0);
addr->Impostor = (impostor? 1: 0);
addr->IPv6 = (ipv4? 0: 1);
addr->IPChecksum = (ip_checksum? 1: 0);
addr->TCPChecksum = (tcp_checksum? 1: 0);
addr->UDPChecksum = (udp_checksum? 1: 0);
addr->Reserved = 0;
switch (layer)
{
case WINDIVERT_LAYER_NETWORK:
@@ -2474,15 +2469,15 @@ windivert_write_too_small_packet:
RtlCopyMemory(data_copy, data, packet_len);
// Fix checksums:
if (addr[i].PseudoIPChecksum != 0 || addr[i].PseudoTCPChecksum != 0 ||
addr[i].PseudoUDPChecksum != 0)
if (addr[i].IPChecksum == 0 || addr[i].TCPChecksum == 0 ||
addr[i].UDPChecksum == 0)
{
checksums =
(addr[i].PseudoIPChecksum? 0:
(addr[i].IPChecksum == 0? 0:
WINDIVERT_HELPER_NO_IP_CHECKSUM) |
(addr[i].PseudoTCPChecksum? 0:
(addr[i].TCPChecksum == 0? 0:
WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
(addr[i].PseudoUDPChecksum? 0:
(addr[i].UDPChecksum == 0? 0:
WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
@@ -4276,7 +4271,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
PWINDIVERT_DATA_FLOW flow_data;
PWINDIVERT_DATA_SOCKET socket_data;
PWINDIVERT_DATA_REFLECT reflect_data;
BOOL pseudo_ip_checksum, pseudo_tcp_checksum, pseudo_udp_checksum;
BOOL ip_checksum, tcp_checksum, udp_checksum;
WDFREQUEST request = NULL;
NTSTATUS status;
@@ -4347,18 +4342,15 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
TcpIpChecksumNetBufferListInfo);
if (outbound)
{
pseudo_ip_checksum = (checksums.Transmit.IpHeaderChecksum != 0);
pseudo_tcp_checksum = (checksums.Transmit.TcpChecksum != 0);
pseudo_udp_checksum = (checksums.Transmit.UdpChecksum != 0);
ip_checksum = (checksums.Transmit.IpHeaderChecksum == 0);
tcp_checksum = (checksums.Transmit.TcpChecksum == 0);
udp_checksum = (checksums.Transmit.UdpChecksum == 0);
}
else
{
pseudo_ip_checksum =
(checksums.Receive.IpChecksumSucceeded != 0);
pseudo_tcp_checksum =
(checksums.Receive.TcpChecksumSucceeded != 0);
pseudo_udp_checksum =
(checksums.Receive.UdpChecksumSucceeded != 0);
ip_checksum = (checksums.Receive.IpChecksumSucceeded == 0);
tcp_checksum = (checksums.Receive.TcpChecksumSucceeded == 0);
udp_checksum = (checksums.Receive.UdpChecksumSucceeded == 0);
}
break;
@@ -4373,8 +4365,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
work->packet_len = 0;
data = WINDIVERT_LAYER_DATA_PTR(work);
RtlCopyMemory(data, flow_data, sizeof(WINDIVERT_DATA_FLOW));
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
FALSE;
ip_checksum = tcp_checksum = udp_checksum = FALSE;
break;
case WINDIVERT_LAYER_SOCKET:
@@ -4388,8 +4379,7 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
work->packet_len = 0;
data = WINDIVERT_LAYER_DATA_PTR(work);
RtlCopyMemory(data, socket_data, sizeof(WINDIVERT_DATA_SOCKET));
pseudo_ip_checksum = pseudo_tcp_checksum = pseudo_udp_checksum =
FALSE;
ip_checksum = tcp_checksum = udp_checksum = FALSE;
break;
case WINDIVERT_LAYER_REFLECT:
@@ -4406,26 +4396,25 @@ static BOOL windivert_queue_work(context_t context, PVOID packet,
RtlCopyMemory(data, reflect_data, sizeof(WINDIVERT_DATA_REFLECT));
data = WINDIVERT_PACKET_DATA_PTR(WINDIVERT_DATA_REFLECT, work);
RtlCopyMemory(data, packet, packet_len);
pseudo_ip_checksum = TRUE;
pseudo_tcp_checksum = pseudo_udp_checksum = FALSE;
ip_checksum = tcp_checksum = udp_checksum = FALSE;
break;
default:
return TRUE;
}
work->layer = layer;
work->event = event;
work->outbound = (outbound? 1: 0);
work->loopback = (loopback? 1: 0);
work->impostor = (impostor? 1: 0);
work->ipv6 = (!ipv4? 1: 0);
work->pseudo_ip_checksum = (pseudo_ip_checksum? 1: 0);
work->pseudo_tcp_checksum = (pseudo_tcp_checksum? 1: 0);
work->pseudo_udp_checksum = (pseudo_udp_checksum? 1: 0);
work->match = match;
work->priority = priority;
work->timestamp = timestamp;
work->layer = layer;
work->event = event;
work->outbound = (outbound? 1: 0);
work->loopback = (loopback? 1: 0);
work->impostor = (impostor? 1: 0);
work->ipv6 = (!ipv4? 1: 0);
work->ip_checksum = (ip_checksum? 1: 0);
work->tcp_checksum = (tcp_checksum? 1: 0);
work->udp_checksum = (udp_checksum? 1: 0);
work->match = match;
work->priority = priority;
work->timestamp = timestamp;
old_entry = NULL;
KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle);
@@ -4561,16 +4550,13 @@ static void windivert_reinject_packet(packet_t packet)
packet_len = packet->packet_len;
// Fix checksums:
if (packet->pseudo_ip_checksum != 0 || packet->pseudo_tcp_checksum != 0 ||
packet->pseudo_udp_checksum != 0)
if (packet->ip_checksum == 0 || packet->tcp_checksum == 0 ||
packet->udp_checksum == 0)
{
checksums =
(packet->pseudo_ip_checksum != 0? 0:
WINDIVERT_HELPER_NO_IP_CHECKSUM) |
(packet->pseudo_tcp_checksum != 0? 0:
WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
(packet->pseudo_udp_checksum != 0? 0:
WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
(packet->ip_checksum == 0? 0: WINDIVERT_HELPER_NO_IP_CHECKSUM) |
(packet->tcp_checksum == 0? 0: WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
(packet->udp_checksum == 0? 0: WINDIVERT_HELPER_NO_UDP_CHECKSUM) |
WINDIVERT_HELPER_NO_ICMP_CHECKSUM |
WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM;
WinDivertHelperCalcChecksums(packet_data, packet_len, NULL, checksums);
+5 -5
View File
@@ -1061,10 +1061,10 @@ static BOOL run_test(HANDLE inject_handle, const char *filter,
// (2) Inject the packet:
memset(&addr_send, 0, sizeof(addr_send));
addr_send.Outbound = TRUE;
addr_send.PseudoIPChecksum = TRUE;
addr_send.PseudoTCPChecksum = TRUE;
addr_send.PseudoUDPChecksum = TRUE;
addr_send.Outbound = TRUE;
addr_send.IPChecksum = FALSE;
addr_send.TCPChecksum = FALSE;
addr_send.UDPChecksum = FALSE;
if (!WinDivertSend(inject_handle, (PVOID)packet, packet_len, &addr_send,
NULL))
{
@@ -1242,7 +1242,7 @@ static DWORD monitor_worker(LPVOID arg)
exit(EXIT_FAILURE);
}
WinDivertHelperParsePacket(packet, packet_len, NULL, NULL, NULL, NULL,
NULL, NULL, (void **)&object_2, NULL);
NULL, NULL, NULL, (void **)&object_2, NULL, NULL, NULL);
if (strcmp(object_1, object_2) != 0)
{
// Filter is not the same.