From e247f01c43a338eb945c31053f983b3335a1b2bd Mon Sep 17 00:00:00 2001 From: basil00 Date: Thu, 2 Jul 2015 21:19:27 +0800 Subject: [PATCH] Remove automatic checksum calculation & legacy API - As discussed in #37, the WINDIVERT_FLAG_NO_CHECKSUM behavior has become the default. This means that outbound packets returned by WinDivertRecv() are no longer guaranteed to have valid checksums, thanks to TCP checksum offloading by the Windows TCP/IP stack. The checksums can still be recovered by calling WinDivertHelperCalcChecksums() manually. - Remove the old WinDivert1.0 legacy API, as nobody should still be using it. --- dll/windivert.c | 57 ----------- dll/windivert.def | 12 +-- include/windivert.h | 80 +-------------- include/windivert_device.h | 4 +- sys/windivert.c | 194 ------------------------------------- 5 files changed, 6 insertions(+), 341 deletions(-) diff --git a/dll/windivert.c b/dll/windivert.c index e2eb116..c841c95 100644 --- a/dll/windivert.c +++ b/dll/windivert.c @@ -723,63 +723,6 @@ static BOOLEAN WinDivertAToX(const char *str, char **endptr, UINT32 *intptr) return TRUE; } -/***************************************************************************/ -/* LEGACY */ -/***************************************************************************/ - -/* - * Legacy functions. - */ -extern HANDLE DivertOpen(const char *filter, DIVERT_LAYER layer, - INT16 priority, UINT64 flags) -{ - return WinDivertOpen(filter, layer, priority, flags); -} -extern BOOL DivertRecv(HANDLE handle, PVOID pPacket, UINT packetLen, - PDIVERT_ADDRESS addr, UINT *readlen) -{ - return WinDivertRecv(handle, pPacket, packetLen, addr, readlen); -} -extern BOOL DivertSend(HANDLE handle, PVOID pPacket, UINT packetLen, - PDIVERT_ADDRESS addr, UINT *writelen) -{ - return WinDivertSend(handle, pPacket, packetLen, addr, writelen); -} -extern BOOL DivertClose(HANDLE handle) -{ - return WinDivertClose(handle); -} -extern BOOL DivertSetParam(HANDLE handle, DIVERT_PARAM param, UINT64 value) -{ - return WinDivertSetParam(handle, param, value); -} -extern BOOL DivertGetParam(HANDLE handle, DIVERT_PARAM param, UINT64 *pValue) -{ - return WinDivertGetParam(handle, param, pValue); -} -extern BOOL DivertHelperParsePacket(PVOID pPacket, UINT packetLen, - PDIVERT_IPHDR *ppIpHdr, PDIVERT_IPV6HDR *ppIpv6Hdr, - PDIVERT_ICMPHDR *ppIcmpHdr, PDIVERT_ICMPV6HDR *ppIcmpv6Hdr, - PDIVERT_TCPHDR *ppTcpHdr, PDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData, - UINT *pDataLen) -{ - return WinDivertHelperParsePacket(pPacket, packetLen, ppIpHdr, ppIpv6Hdr, - ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, ppData, pDataLen); -} -extern UINT DivertHelperCalcChecksums(PVOID pPacket, UINT packetLen, - UINT64 flags) -{ - return WinDivertHelperCalcChecksums(pPacket, packetLen, flags); -} -extern BOOL DivertHelperParseIPv4Address(const char *str, UINT32 *addr_ptr) -{ - return WinDivertHelperParseIPv4Address(str, addr_ptr); -} -extern BOOL DivertHelperParseIPv6Address(const char *str, UINT32 *addr_ptr) -{ - return WinDivertHelperParseIPv6Address(str, addr_ptr); -} - /***************************************************************************/ /* DEBUGGING */ /***************************************************************************/ diff --git a/dll/windivert.def b/dll/windivert.def index cedfe97..2c20d03 100644 --- a/dll/windivert.def +++ b/dll/windivert.def @@ -13,13 +13,5 @@ EXPORTS WinDivertHelperParsePacket WinDivertHelperParseIPv4Address WinDivertHelperParseIPv6Address - DivertOpen - DivertRecv - DivertSend - DivertClose - DivertSetParam - DivertGetParam - DivertHelperCalcChecksums - DivertHelperParsePacket - DivertHelperParseIPv4Address - DivertHelperParseIPv6Address + WinDivertHelperCheckFilter + WinDivertHelperEvalFilter diff --git a/include/windivert.h b/include/windivert.h index 6218645..6bc636e 100644 --- a/include/windivert.h +++ b/include/windivert.h @@ -79,7 +79,6 @@ typedef enum */ #define WINDIVERT_FLAG_SNIFF 1 #define WINDIVERT_FLAG_DROP 2 -#define WINDIVERT_FLAG_NO_CHECKSUM 1024 /* * Divert parameters. @@ -307,7 +306,7 @@ typedef struct } WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR; /* - * Flags for DivertHelperCalcChecksums() + * Flags for WinDivertHelperCalcChecksums() */ #define WINDIVERT_HELPER_NO_IP_CHECKSUM 1 #define WINDIVERT_HELPER_NO_ICMP_CHECKSUM 2 @@ -378,82 +377,7 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperEvalFilter( /* * Deprecated API: */ -typedef WINDIVERT_ADDRESS DIVERT_ADDRESS; -typedef PWINDIVERT_ADDRESS PDIVERT_ADDRESS; -#define DIVERT_DIRECTION_OUTBOUND WINDIVERT_DIRECTION_OUTBOUND -#define DIVERT_DIRECTION_INBOUND WINDIVERT_DIRECTION_INBOUND -typedef WINDIVERT_LAYER DIVERT_LAYER; -typedef PWINDIVERT_LAYER PDIVERT_LAYER; -#define DIVERT_FLAG_SNIFF WINDIVERT_FLAG_SNIFF -#define DIVERT_FLAG_DROP WINDIVERT_FLAG_DROP -typedef WINDIVERT_PARAM DIVERT_PARAM; -typedef PWINDIVERT_PARAM PDIVERT_PARAM; -typedef WINDIVERT_IPHDR DIVERT_IPHDR; -typedef PWINDIVERT_IPHDR PDIVERT_IPHDR; -typedef WINDIVERT_IPV6HDR DIVERT_IPV6HDR; -typedef PWINDIVERT_IPV6HDR PDIVERT_IPV6HDR; -typedef WINDIVERT_ICMPHDR DIVERT_ICMPHDR; -typedef PWINDIVERT_ICMPHDR PDIVERT_ICMPHDR; -typedef WINDIVERT_ICMPV6HDR DIVERT_ICMPV6HDR; -typedef PWINDIVERT_ICMPV6HDR PDIVERT_ICMPV6HDR; -typedef WINDIVERT_TCPHDR DIVERT_TCPHDR; -typedef PWINDIVERT_TCPHDR PDIVERT_TCPHDR; -typedef WINDIVERT_UDPHDR DIVERT_UDPHDR; -typedef PWINDIVERT_UDPHDR PDIVERT_UDPHDR; -#define DIVERT_HELPER_NO_IP_CHECKSUM WINDIVERT_HELPER_NO_IP_CHECKSUM -#define DIVERT_HELPER_NO_ICMP_CHECKSUM WINDIVERT_HELPER_NO_ICMP_CHECKSUM -#define DIVERT_HELPER_NO_ICMPV6_CHECKSUM WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM -#define DIVERT_HELPER_NO_TCP_CHECKSUM WINDIVERT_HELPER_NO_TCP_CHECKSUM -#define DIVERT_HELPER_NO_UDP_CHECKSUM WINDIVERT_HELPER_NO_UDP_CHECKSUM - -extern WINDIVERTEXPORT HANDLE DivertOpen( - __in const char *filter, - __in DIVERT_LAYER layer, - __in INT16 priority, - __in UINT64 flags); -extern WINDIVERTEXPORT BOOL DivertRecv( - __in HANDLE handle, - __out PVOID pPacket, - __in UINT packetLen, - __out_opt PDIVERT_ADDRESS pAddr, - __out_opt UINT *readLen); -extern WINDIVERTEXPORT BOOL DivertSend( - __in HANDLE handle, - __in PVOID pPacket, - __in UINT packetLen, - __in PDIVERT_ADDRESS pAddr, - __out_opt UINT *writeLen); -extern WINDIVERTEXPORT BOOL DivertClose( - __in HANDLE handle); -extern WINDIVERTEXPORT BOOL DivertSetParam( - __in HANDLE handle, - __in DIVERT_PARAM param, - __in UINT64 value); -extern WINDIVERTEXPORT BOOL DivertGetParam( - __in HANDLE handle, - __in DIVERT_PARAM param, - __out UINT64 *pValue); -extern WINDIVERTEXPORT BOOL DivertHelperParsePacket( - __in PVOID pPacket, - __in UINT packetLen, - __out_opt PDIVERT_IPHDR *ppIpHdr, - __out_opt PDIVERT_IPV6HDR *ppIpv6Hdr, - __out_opt PDIVERT_ICMPHDR *ppIcmpHdr, - __out_opt PDIVERT_ICMPV6HDR *ppIcmpv6Hdr, - __out_opt PDIVERT_TCPHDR *ppTcpHdr, - __out_opt PDIVERT_UDPHDR *ppUdpHdr, - __out_opt PVOID *ppData, - __out_opt UINT *pDataLen); -extern WINDIVERTEXPORT BOOL DivertHelperParseIPv4Address( - __in const char *addrStr, - __out_opt UINT32 *pAddr); -extern WINDIVERTEXPORT BOOL DivertHelperParseIPv6Address( - __in const char *addrStr, - __out_opt UINT32 *pAddr); -extern WINDIVERTEXPORT UINT DivertHelperCalcChecksums( - __inout PVOID pPacket, - __in UINT packetLen, - __in UINT64 flags); +#define WINDIVERT_FLAG_NO_CHECKSUM 0 #endif /* WINDIVERT_KERNEL */ diff --git a/include/windivert_device.h b/include/windivert_device.h index 58b08ee..5407540 100644 --- a/include/windivert_device.h +++ b/include/windivert_device.h @@ -131,14 +131,14 @@ * WinDivert flags. */ #define WINDIVERT_FLAGS_ALL \ - (WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP | \ - WINDIVERT_FLAG_NO_CHECKSUM) + (WINDIVERT_FLAG_SNIFF | WINDIVERT_FLAG_DROP) #define WINDIVERT_FLAGS_EXCLUDE(flags, flag1, flag2) \ (((flags) & ((flag1) | (flag2))) != ((flag1) | (flag2))) #define WINDIVERT_FLAGS_VALID(flags) \ ((((flags) & ~WINDIVERT_FLAGS_ALL) == 0) && \ WINDIVERT_FLAGS_EXCLUDE(flags, WINDIVERT_FLAG_SNIFF, \ WINDIVERT_FLAG_DROP)) + /* * WinDivert priorities. */ diff --git a/sys/windivert.c b/sys/windivert.c index b22de73..8d5ae17 100644 --- a/sys/windivert.c +++ b/sys/windivert.c @@ -201,9 +201,6 @@ struct packet_s UINT8 direction; // Packet direction. UINT32 if_idx; // Interface index. UINT32 sub_if_idx; // Sub-interface index. - BOOL ip_checksum; // IP checksum is valid. - BOOL tcp_checksum; // TCP checksum is valid. - BOOL udp_checksum; // UDP checksum is valid. BOOL timer_ticktock; // Time-out ticktock. char data[]; // Packet data. }; @@ -404,8 +401,6 @@ static void windivert_free_packet(packet_t packet); static UINT8 windivert_skip_headers(UINT8 proto, UINT8 **header, size_t *len); static UINT16 windivert_checksum(const void *pseudo_header, size_t pseudo_header_len, const void *data, size_t size); -static void windivert_update_checksums(void *header, size_t len, - BOOL update_ip, BOOL update_tcp, BOOL update_udp); static BOOL windivert_filter(PNET_BUFFER buffer, UINT32 if_idx, UINT32 sub_if_idx, BOOL outbound, BOOL isipv4, filter_t filter); static filter_t windivert_filter_compile(windivert_ioctl_filter_t ioctl_filter, @@ -1391,13 +1386,6 @@ static void windivert_read_service(context_t context) addr->Direction = packet->direction; } - // Compute the IP/TCP/UDP checksums here (if required). - if ((context->flags & WINDIVERT_FLAG_NO_CHECKSUM) == 0) - { - windivert_update_checksums(dst, dst_len, packet->ip_checksum, - packet->tcp_checksum, packet->udp_checksum); - } - status = STATUS_SUCCESS; windivert_read_service_complete: @@ -2343,32 +2331,6 @@ static BOOL windivert_queue_packet(context_t context, PNET_BUFFER buffer, packet->direction = direction; packet->if_idx = if_idx; packet->sub_if_idx = sub_if_idx; - if (direction == WINDIVERT_DIRECTION_OUTBOUND) - { - if (isloopback) - { - // Workaround: Do not trust checksum info for loopback packets. - packet->ip_checksum = TRUE; - packet->tcp_checksum = TRUE; - packet->udp_checksum = TRUE; - } - else - { - checksum_info.Value = NET_BUFFER_LIST_INFO(buffers, - TcpIpChecksumNetBufferListInfo); - - // IPv4 Checksum is not calculated yet - packet->ip_checksum = TRUE; - packet->tcp_checksum = (BOOL)checksum_info.Transmit.TcpChecksum; - packet->udp_checksum = (BOOL)checksum_info.Transmit.UdpChecksum; - } - } - else - { - packet->ip_checksum = FALSE; - packet->tcp_checksum = FALSE; - packet->udp_checksum = FALSE; - } packet->timer_ticktock = context->timer_ticktock; entry = &packet->entry; KeAcquireInStackQueuedSpinLock(&context->lock, &lock_handle); @@ -2608,162 +2570,6 @@ static UINT8 windivert_skip_headers(UINT8 proto, UINT8 **header, size_t *len) } } -/* - * Given a well-formed packet, update the IP and/or TCP/UDP checksums if - * required. - */ -static void windivert_update_checksums(void *header, size_t len, - BOOL update_ip, BOOL update_tcp, BOOL update_udp) -{ - struct - { - UINT32 SrcAddr; - UINT32 DstAddr; - UINT8 Zero; - UINT8 Protocol; - UINT16 Length; - } pseudo_headerv4; - struct - { - UINT32 SrcAddr[4]; - UINT32 DstAddr[4]; - UINT32 Length; - UINT32 Zero:24; - UINT32 NextHdr:8; - } pseudo_headerv6; - void *pseudo_header; - size_t pseudo_header_len; - struct iphdr *ip_header = (struct iphdr *)header; - struct ipv6hdr *ipv6_header = (struct ipv6hdr *)header; - size_t ip_header_len, trans_len; - void *trans_header; - struct tcphdr *tcp_header; - struct udphdr *udp_header; - BOOL is_ipv4 = TRUE; - UINT8 proto; - UINT16 *trans_check_ptr; - UINT sum; - - if (!update_ip && !update_tcp && !update_udp) - { - return; - } - - if (len < sizeof(struct iphdr)) - { - return; - } - - switch (ip_header->Version) - { - case 4: - ip_header_len = ip_header->HdrLength*sizeof(UINT32); - if (len < ip_header_len) - { - return; - } - - if (update_ip) - { - ip_header->Checksum = 0; - ip_header->Checksum = windivert_checksum(NULL, 0, ip_header, - ip_header_len); - } - - proto = ip_header->Protocol; - trans_len = len - ip_header_len; - trans_header = (UINT8 *)ip_header + ip_header_len; - break; - - case 6: - if (!update_tcp && !update_udp) - { - return; - } - is_ipv4 = FALSE; - if (len < sizeof(struct ipv6hdr)) - { - return; - } - - trans_len = len - sizeof(struct ipv6hdr); - trans_header = (UINT8 *)(ipv6_header + 1); - - // Skip extension headers: - proto = windivert_skip_headers(ipv6_header->NextHdr, - (UINT8 **)&trans_header, &trans_len); - break; - - default: - return; - } - - switch (proto) - { - case IPPROTO_TCP: - if (!update_tcp) - { - return; - } - tcp_header = (struct tcphdr *)trans_header; - if (trans_len < sizeof(struct tcphdr)) - { - return; - } - trans_check_ptr = &tcp_header->Checksum; - break; - case IPPROTO_UDP: - if (!update_udp) - { - return; - } - udp_header = (struct udphdr *)trans_header; - if (trans_len < sizeof(struct udphdr)) - { - return; - } - trans_check_ptr = &udp_header->Checksum; - break; - default: - return; - } - - if (is_ipv4) - { - pseudo_headerv4.SrcAddr = ip_header->SrcAddr; - pseudo_headerv4.DstAddr = ip_header->DstAddr; - pseudo_headerv4.Zero = 0x0; - pseudo_headerv4.Protocol = proto; - pseudo_headerv4.Length = RtlUshortByteSwap((UINT16)trans_len); - pseudo_header = &pseudo_headerv4; - pseudo_header_len = sizeof(pseudo_headerv4); - } - else - { - RtlCopyMemory(&pseudo_headerv6.SrcAddr, ipv6_header->SrcAddr, - sizeof(pseudo_headerv6.SrcAddr)); - RtlCopyMemory(&pseudo_headerv6.DstAddr, ipv6_header->DstAddr, - sizeof(pseudo_headerv6.DstAddr)); - pseudo_headerv6.Length = RtlUlongByteSwap((UINT32)trans_len); - pseudo_headerv6.NextHdr = proto; - pseudo_headerv6.Zero = 0x0; - pseudo_header = &pseudo_headerv6; - pseudo_header_len = sizeof(pseudo_headerv6); - } - - *trans_check_ptr = 0x0; - sum = windivert_checksum(pseudo_header, pseudo_header_len, trans_header, - trans_len); - if (sum == 0 && proto == IPPROTO_UDP) - { - *trans_check_ptr = 0xFFFF; - } - else - { - *trans_check_ptr = (UINT16)sum; - } -} - /* * Checks if the given packet is of interest. */