diff --git a/dll/windivert_helper.c b/dll/windivert_helper.c index 255190d..ff6a94f 100644 --- a/dll/windivert_helper.c +++ b/dll/windivert_helper.c @@ -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]); diff --git a/dll/windivert_shared.c b/dll/windivert_shared.c index dfe2dd0..9960cd2 100644 --- a/dll/windivert_shared.c +++ b/dll/windivert_shared.c @@ -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; } diff --git a/examples/netdump/netdump.c b/examples/netdump/netdump.c index 4904b9e..ad8566d 100644 --- a/examples/netdump/netdump.c +++ b/examples/netdump/netdump.c @@ -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"); diff --git a/examples/netfilter/netfilter.c b/examples/netfilter/netfilter.c index 758a346..9936a18 100644 --- a/examples/netfilter/netfilter.c +++ b/examples/netfilter/netfilter.c @@ -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; diff --git a/examples/streamdump/streamdump.c b/examples/streamdump/streamdump.c index b1010c3..09c8424 100644 --- a/examples/streamdump/streamdump.c +++ b/examples/streamdump/streamdump.c @@ -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; diff --git a/examples/webfilter/webfilter.c b/examples/webfilter/webfilter.c index cb1c1a5..3d2f130 100644 --- a/examples/webfilter/webfilter.c +++ b/examples/webfilter/webfilter.c @@ -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. diff --git a/examples/windivertctl/windivertctl.c b/examples/windivertctl/windivertctl.c index 285ee92..8bc30a2 100644 --- a/examples/windivertctl/windivertctl.c +++ b/examples/windivertctl/windivertctl.c @@ -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))) { diff --git a/include/windivert.h b/include/windivert.h index deef7dd..6fc9957 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -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); /* diff --git a/include/windivert_device.h b/include/windivert_device.h index 2589e7b..2fda204 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -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. diff --git a/sys/windivert.c b/sys/windivert.c index 6b6358c..823c3f5 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -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); diff --git a/test/test.c b/test/test.c index f61cdbd..3f460bc 100644 --- a/test/test.c +++ b/test/test.c @@ -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.