Move pseduo checksum calculation inside driver.
This means WinDivertSend() no longer needs to modify the packet and address buffers. See #134.
This commit is contained in:
@@ -51,19 +51,6 @@
|
||||
#define WINDIVERT_DRIVER32_SYS L"\\" WINDIVERT_DRIVER_NAME L"32.sys"
|
||||
#define WINDIVERT_DRIVER64_SYS L"\\" WINDIVERT_DRIVER_NAME L"64.sys"
|
||||
|
||||
/*
|
||||
* Definitions to remove (some) external dependencies:
|
||||
*/
|
||||
#define BYTESWAP16(x) \
|
||||
((((x) >> 8) & 0x00FF) | (((x) << 8) & 0xFF00))
|
||||
#define BYTESWAP32(x) \
|
||||
((((x) >> 24) & 0x000000FF) | (((x) >> 8) & 0x0000FF00) | \
|
||||
(((x) << 8) & 0x00FF0000) | (((x) << 24) & 0xFF000000))
|
||||
#define ntohs(x) BYTESWAP16(x)
|
||||
#define htons(x) BYTESWAP16(x)
|
||||
#define ntohl(x) BYTESWAP32(x)
|
||||
#define htonl(x) BYTESWAP32(x)
|
||||
|
||||
static BOOLEAN WinDivertIsXDigit(char c);
|
||||
static BOOLEAN WinDivertIsSpace(char c);
|
||||
static BOOLEAN WinDivertIsAlNum(char c);
|
||||
@@ -532,41 +519,6 @@ extern HANDLE WinDivertOpen(const char *filter, WINDIVERT_LAYER layer,
|
||||
return handle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for #134
|
||||
*/
|
||||
static void WinDivertFixChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ADDRESS addr)
|
||||
{
|
||||
UINT64 flags =
|
||||
WINDIVERT_HELPER_NO_IP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_TCP_CHECKSUM |
|
||||
WINDIVERT_HELPER_NO_UDP_CHECKSUM;
|
||||
BOOL calc = FALSE;
|
||||
if (addr->PseudoIPChecksum != 0)
|
||||
{
|
||||
addr->PseudoIPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_IP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (addr->PseudoTCPChecksum != 0)
|
||||
{
|
||||
addr->PseudoTCPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_TCP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (addr->PseudoUDPChecksum != 0)
|
||||
{
|
||||
addr->PseudoUDPChecksum = 0;
|
||||
flags &= ~WINDIVERT_HELPER_NO_UDP_CHECKSUM;
|
||||
calc = TRUE;
|
||||
}
|
||||
if (calc)
|
||||
{
|
||||
WinDivertHelperCalcChecksums(pPacket, packetLen, addr, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Receive a WinDivert packet.
|
||||
*/
|
||||
@@ -612,7 +564,6 @@ extern BOOL WinDivertSend(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertFixChecksums(pPacket, packetLen, addr);
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, 0, (UINT64)addr,
|
||||
pPacket, packetLen, writelen);
|
||||
}
|
||||
@@ -629,7 +580,6 @@ extern BOOL WinDivertSendEx(HANDLE handle, PVOID pPacket, UINT packetLen,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertFixChecksums(pPacket, packetLen, addr);
|
||||
if (overlapped == NULL)
|
||||
{
|
||||
return WinDivertIoControl(handle, IOCTL_WINDIVERT_SEND, 0,
|
||||
|
||||
+3
-415
@@ -252,8 +252,6 @@ typedef UINT64 ERROR, *PERROR;
|
||||
#define IS_ERROR(err) \
|
||||
(GET_CODE(err) != WINDIVERT_ERROR_NONE)
|
||||
|
||||
#define MAX(a, b) ((a) > (b)? (a): (b))
|
||||
|
||||
/*
|
||||
* Prototypes.
|
||||
*/
|
||||
@@ -261,233 +259,11 @@ static PEXPR WinDivertParseFilter(HANDLE pool, TOKEN *toks, UINT *i,
|
||||
INT depth, BOOL and, PERROR error);
|
||||
static BOOL WinDivertCondExecFilter(PWINDIVERT_FILTER filter, UINT length,
|
||||
UINT8 field, UINT32 arg);
|
||||
static UINT16 WinDivertInitPseudoHeader(PWINDIVERT_IPHDR ip_header,
|
||||
PWINDIVERT_IPV6HDR ipv6_header, UINT8 protocol, UINT len,
|
||||
void *pseudo_header);
|
||||
static UINT16 WinDivertHelperCalcChecksum(PVOID pseudo_header,
|
||||
UINT16 pseudo_header_len, PVOID data, UINT len);
|
||||
static BOOL WinDivertDeserializeFilter(PWINDIVERT_STREAM stream,
|
||||
PWINDIVERT_FILTER filter, UINT *length);
|
||||
static void WinDivertFormatExpr(PWINDIVERT_STREAM stream, PEXPR expr,
|
||||
BOOL top_level, BOOL and);
|
||||
|
||||
/*
|
||||
* Skip well-known IPv6 extension headers.
|
||||
*/
|
||||
static UINT8 WinDivertSkipExtHeaders(UINT8 proto, UINT8 **header, UINT *len)
|
||||
{
|
||||
UINT hdrlen;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
if (*len <= 2)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
hdrlen = (UINT)*(*header + 1);
|
||||
switch (proto)
|
||||
{
|
||||
case IPPROTO_FRAGMENT:
|
||||
hdrlen = 8;
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
hdrlen += 2;
|
||||
hdrlen *= 4;
|
||||
break;
|
||||
case IPPROTO_HOPOPTS:
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
hdrlen++;
|
||||
hdrlen *= 8;
|
||||
break;
|
||||
case IPPROTO_NONE:
|
||||
return proto;
|
||||
default:
|
||||
return proto;
|
||||
}
|
||||
|
||||
if (hdrlen >= *len)
|
||||
{
|
||||
return IPPROTO_NONE;
|
||||
}
|
||||
|
||||
proto = **header;
|
||||
*header += hdrlen;
|
||||
*len -= hdrlen;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
static BOOL WinDivertHelperParsePacket_2(PVOID pPacket, UINT packetLen,
|
||||
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_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;
|
||||
UINT16 header_len;
|
||||
UINT8 trans_proto = 0;
|
||||
PVOID data = NULL;
|
||||
UINT data_len = 0;
|
||||
BOOL success;
|
||||
|
||||
if (pPacket == NULL || packetLen < sizeof(UINT8))
|
||||
{
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = pPacket;
|
||||
data_len = packetLen;
|
||||
|
||||
ip_header = (PWINDIVERT_IPHDR)data;
|
||||
switch (ip_header->Version)
|
||||
{
|
||||
case 4:
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5 ||
|
||||
data_len < ip_header->HdrLength*sizeof(UINT32) ||
|
||||
ntohs(ip_header->Length) != data_len)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ip_header->Protocol;
|
||||
header_len = ip_header->HdrLength*sizeof(UINT32);
|
||||
data = (PVOID)((UINT8 *)data + header_len);
|
||||
data_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))
|
||||
{
|
||||
ipv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ipv6_header->NextHdr;
|
||||
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_IPV6HDR);
|
||||
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
|
||||
&data_len);
|
||||
break;
|
||||
default:
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
switch (trans_proto)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_TCPHDR) ||
|
||||
tcp_header->HdrLength < 5 ||
|
||||
data_len < tcp_header->HdrLength*sizeof(UINT32))
|
||||
{
|
||||
tcp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
header_len = tcp_header->HdrLength*sizeof(UINT32);
|
||||
data = ((UINT8 *)data + header_len);
|
||||
data_len -= header_len;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
udp_header = (PWINDIVERT_UDPHDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_UDPHDR) ||
|
||||
ntohs(udp_header->Length) != data_len)
|
||||
{
|
||||
udp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_UDPHDR));
|
||||
data_len -= sizeof(WINDIVERT_UDPHDR);
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
icmp_header = (PWINDIVERT_ICMPHDR)data;
|
||||
if (ip_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPHDR))
|
||||
{
|
||||
icmp_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPHDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPHDR);
|
||||
break;
|
||||
case IPPROTO_ICMPV6:
|
||||
icmpv6_header = (PWINDIVERT_ICMPV6HDR)data;
|
||||
if (ipv6_header == NULL ||
|
||||
data_len < sizeof(WINDIVERT_ICMPV6HDR))
|
||||
{
|
||||
icmpv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = ((UINT8 *)data + sizeof(WINDIVERT_ICMPV6HDR));
|
||||
data_len -= sizeof(WINDIVERT_ICMPV6HDR);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (data_len == 0)
|
||||
{
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
WinDivertHelperParsePacketExit:
|
||||
success = TRUE;
|
||||
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;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
@@ -497,196 +273,8 @@ extern BOOL WinDivertHelperParsePacket(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_TCPHDR *ppTcpHdr, PWINDIVERT_UDPHDR *ppUdpHdr, PVOID *ppData,
|
||||
UINT *pDataLen)
|
||||
{
|
||||
return WinDivertHelperParsePacket_2(pPacket, packetLen, ppIpHdr,
|
||||
ppIpv6Hdr, ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL,
|
||||
ppData, pDataLen);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_ADDRESS pAddr, UINT64 flags)
|
||||
{
|
||||
UINT8 pseudo_header[
|
||||
MAX(sizeof(WINDIVERT_PSEUDOHDR), sizeof(WINDIVERT_PSEUDOV6HDR))];
|
||||
UINT16 pseudo_header_len;
|
||||
PWINDIVERT_IPHDR ip_header;
|
||||
PWINDIVERT_IPV6HDR ipv6_header;
|
||||
PWINDIVERT_ICMPHDR icmp_header;
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header;
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT payload_len, checksum_len;
|
||||
UINT count = 0;
|
||||
|
||||
WinDivertHelperParsePacket_2(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))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
if (pAddr == NULL || pAddr->PseudoIPChecksum == 0)
|
||||
{
|
||||
ip_header->Checksum = WinDivertHelperCalcChecksum(NULL, 0,
|
||||
ip_header, ip_header->HdrLength*sizeof(UINT32));
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertHelperCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
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 = WinDivertHelperCalcChecksum(pseudo_header,
|
||||
pseudo_header_len, icmpv6_header, checksum_len);
|
||||
count++;
|
||||
return count;
|
||||
}
|
||||
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
if (pAddr == NULL || pAddr->PseudoTCPChecksum == 0)
|
||||
{
|
||||
// Full TCP checksum
|
||||
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 = WinDivertHelperCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, tcp_header, checksum_len);
|
||||
}
|
||||
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)
|
||||
{
|
||||
// Full UDP checksum
|
||||
checksum_len = payload_len + sizeof(WINDIVERT_UDPHDR);
|
||||
pseudo_header_len = WinDivertInitPseudoHeader(ip_header,
|
||||
ipv6_header, IPPROTO_UDP, checksum_len, pseudo_header);
|
||||
udp_header->Checksum = 0;
|
||||
udp_header->Checksum = WinDivertHelperCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, udp_header, checksum_len);
|
||||
if (udp_header->Checksum == 0)
|
||||
{
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
}
|
||||
else if (pAddr->Outbound)
|
||||
{
|
||||
// Pseudo UDP checksum
|
||||
udp_header->Checksum = 0;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the IP/IPv6 pseudo header.
|
||||
*/
|
||||
static UINT16 WinDivertInitPseudoHeader(PWINDIVERT_IPHDR ip_header,
|
||||
PWINDIVERT_IPV6HDR ipv6_header, UINT8 protocol, UINT len,
|
||||
void *pseudo_header)
|
||||
{
|
||||
if (ip_header != NULL)
|
||||
{
|
||||
PWINDIVERT_PSEUDOHDR pseudo_header_v4 =
|
||||
(PWINDIVERT_PSEUDOHDR)pseudo_header;
|
||||
pseudo_header_v4->SrcAddr = ip_header->SrcAddr;
|
||||
pseudo_header_v4->DstAddr = ip_header->DstAddr;
|
||||
pseudo_header_v4->Zero = 0;
|
||||
pseudo_header_v4->Protocol = protocol;
|
||||
pseudo_header_v4->Length = htons((UINT16)len);
|
||||
return sizeof(WINDIVERT_PSEUDOHDR);
|
||||
}
|
||||
else
|
||||
{
|
||||
PWINDIVERT_PSEUDOV6HDR pseudo_header_v6 =
|
||||
(PWINDIVERT_PSEUDOV6HDR)pseudo_header;
|
||||
memcpy(pseudo_header_v6->SrcAddr, ipv6_header->SrcAddr,
|
||||
sizeof(pseudo_header_v6->SrcAddr));
|
||||
memcpy(pseudo_header_v6->DstAddr, ipv6_header->DstAddr,
|
||||
sizeof(pseudo_header_v6->DstAddr));
|
||||
pseudo_header_v6->Length = htonl((UINT32)len);
|
||||
pseudo_header_v6->NextHdr = protocol;
|
||||
pseudo_header_v6->Zero = 0;
|
||||
return sizeof(WINDIVERT_PSEUDOV6HDR);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic checksum computation.
|
||||
*/
|
||||
static UINT16 WinDivertHelperCalcChecksum(PVOID pseudo_header,
|
||||
UINT16 pseudo_header_len, PVOID data, UINT len)
|
||||
{
|
||||
register const UINT16 *data16 = (const UINT16 *)pseudo_header;
|
||||
register size_t len16 = pseudo_header_len >> 1;
|
||||
register UINT32 sum = 0;
|
||||
size_t i;
|
||||
|
||||
// Pseudo header:
|
||||
for (i = 0; i < len16; i++)
|
||||
{
|
||||
sum += (UINT32)data16[i];
|
||||
}
|
||||
|
||||
// Main data:
|
||||
data16 = (const UINT16 *)data;
|
||||
len16 = len >> 1;
|
||||
for (i = 0; i < len16; i++)
|
||||
{
|
||||
sum += (UINT32)data16[i];
|
||||
}
|
||||
|
||||
if (len & 0x1)
|
||||
{
|
||||
const UINT8 *data8 = (const UINT8 *)data;
|
||||
sum += (UINT16)data8[len-1];
|
||||
}
|
||||
|
||||
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||
sum += (sum >> 16);
|
||||
sum = ~sum;
|
||||
return (UINT16)sum;
|
||||
return WinDivertParsePacket(pPacket, packetLen, ppIpHdr, ppIpv6Hdr,
|
||||
ppIcmpHdr, ppIcmpv6Hdr, ppTcpHdr, ppUdpHdr, NULL, ppData, pDataLen);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2563,7 +2151,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, PVOID packet,
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
WinDivertHelperParsePacket_2(packet, packet_len, &iphdr, &ipv6hdr,
|
||||
WinDivertParsePacket(packet, packet_len, &iphdr, &ipv6hdr,
|
||||
&icmphdr, &icmpv6hdr, &tcphdr, &udphdr, &protocol, NULL,
|
||||
&payload_len);
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
|
||||
+2
-2
@@ -413,8 +413,6 @@ typedef struct
|
||||
UINT16 Checksum;
|
||||
} WINDIVERT_UDPHDR, *PWINDIVERT_UDPHDR;
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Flags for WinDivertHelperCalcChecksums()
|
||||
*/
|
||||
@@ -424,6 +422,8 @@ typedef struct
|
||||
#define WINDIVERT_HELPER_NO_TCP_CHECKSUM 8
|
||||
#define WINDIVERT_HELPER_NO_UDP_CHECKSUM 16
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
|
||||
/*
|
||||
* Parse IPv4/IPv6/ICMP/ICMPv6/TCP/UDP headers from a raw packet.
|
||||
*/
|
||||
|
||||
+32
-15
@@ -663,7 +663,7 @@ static struct layer_s layer_resource_assignment_ipv4_0 =
|
||||
0
|
||||
};
|
||||
static layer_t layer_resource_assignment_ipv4 =
|
||||
&layer_resource_assignment_ipv4_0;
|
||||
&layer_resource_assignment_ipv4_0;
|
||||
|
||||
static struct layer_s layer_resource_assignment_ipv6_0 =
|
||||
{
|
||||
@@ -680,7 +680,7 @@ static struct layer_s layer_resource_assignment_ipv6_0 =
|
||||
0
|
||||
};
|
||||
static layer_t layer_resource_assignment_ipv6 =
|
||||
&layer_resource_assignment_ipv6_0;
|
||||
&layer_resource_assignment_ipv6_0;
|
||||
|
||||
static struct layer_s layer_auth_connect_ipv4_0 =
|
||||
{
|
||||
@@ -810,6 +810,11 @@ static struct layer_s layer_flow_established_ipv6_0 =
|
||||
};
|
||||
static layer_t layer_flow_established_ipv6 = &layer_flow_established_ipv6_0;
|
||||
|
||||
/*
|
||||
* Shared functions.
|
||||
*/
|
||||
#include "windivert_shared.c"
|
||||
|
||||
/*
|
||||
* WinDivert malloc/free.
|
||||
*/
|
||||
@@ -887,18 +892,18 @@ extern NTSTATUS DriverEntry(IN PDRIVER_OBJECT driver_obj,
|
||||
FWPM_LAYER_ALE_FLOW_ESTABLISHED_V4;
|
||||
layer_flow_established_ipv6->layer_guid =
|
||||
FWPM_LAYER_ALE_FLOW_ESTABLISHED_V6;
|
||||
layer_resource_assignment_ipv4->layer_guid =
|
||||
layer_resource_assignment_ipv4->layer_guid =
|
||||
FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V4;
|
||||
layer_resource_assignment_ipv6->layer_guid =
|
||||
layer_resource_assignment_ipv6->layer_guid =
|
||||
FWPM_LAYER_ALE_RESOURCE_ASSIGNMENT_V6;
|
||||
layer_auth_connect_ipv4->layer_guid = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||
layer_auth_connect_ipv6->layer_guid = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||
layer_auth_listen_ipv4->layer_guid = FWPM_LAYER_ALE_AUTH_LISTEN_V4;
|
||||
layer_auth_listen_ipv6->layer_guid = FWPM_LAYER_ALE_AUTH_LISTEN_V6;
|
||||
layer_auth_recv_accept_ipv4->layer_guid =
|
||||
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
|
||||
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4;
|
||||
layer_auth_recv_accept_ipv6->layer_guid =
|
||||
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6;
|
||||
FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6;
|
||||
layer_inbound_network_ipv4->sublayer_guid =
|
||||
WINDIVERT_SUBLAYER_INBOUND_IPV4_GUID;
|
||||
layer_outbound_network_ipv4->sublayer_guid =
|
||||
@@ -2119,7 +2124,7 @@ static NTSTATUS windivert_write(context_t context, WDFREQUEST request,
|
||||
BOOL ipv4;
|
||||
UINT8 layer;
|
||||
UINT32 priority;
|
||||
UINT64 flags;
|
||||
UINT64 flags, checksums;
|
||||
HANDLE handle, compl_handle;
|
||||
PNET_BUFFER_LIST buffers = NULL;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
@@ -2183,6 +2188,7 @@ windivert_write_bad_packet:
|
||||
goto windivert_write_exit;
|
||||
}
|
||||
|
||||
// Copy packet data:
|
||||
data_copy = windivert_malloc(data_len, FALSE);
|
||||
if (data_copy == NULL)
|
||||
{
|
||||
@@ -2191,7 +2197,6 @@ windivert_write_bad_packet:
|
||||
status);
|
||||
goto windivert_write_exit;
|
||||
}
|
||||
|
||||
RtlCopyMemory(data_copy, data, sizeof(WINDIVERT_IPHDR));
|
||||
ip_header = (PWINDIVERT_IPHDR)data_copy;
|
||||
switch (ip_header->Version)
|
||||
@@ -2225,6 +2230,19 @@ windivert_write_bad_packet:
|
||||
(char *)data + sizeof(WINDIVERT_IPHDR),
|
||||
data_len - sizeof(WINDIVERT_IPHDR));
|
||||
}
|
||||
|
||||
// Fix checksums:
|
||||
if (addr->PseudoIPChecksum != 0 || addr->PseudoTCPChecksum != 0 ||
|
||||
addr->PseudoUDPChecksum != 0)
|
||||
{
|
||||
checksums =
|
||||
(addr->PseudoIPChecksum? 0: WINDIVERT_HELPER_NO_IP_CHECKSUM) |
|
||||
(addr->PseudoTCPChecksum? 0: WINDIVERT_HELPER_NO_TCP_CHECKSUM) |
|
||||
(addr->PseudoUDPChecksum? 0: WINDIVERT_HELPER_NO_UDP_CHECKSUM);
|
||||
WinDivertHelperCalcChecksums(data_copy, data_len, NULL, checksums);
|
||||
}
|
||||
|
||||
// Decrement TTL for impostor packets:
|
||||
if (addr->Impostor && !windivert_decrement_ttl(data_copy, ipv4,
|
||||
(addr->PseudoIPChecksum == 0)))
|
||||
{
|
||||
@@ -2232,6 +2250,7 @@ windivert_write_bad_packet:
|
||||
goto windivert_write_exit;
|
||||
}
|
||||
|
||||
// Allocate packet:
|
||||
mdl_copy = IoAllocateMdl(data_copy, data_len, FALSE, FALSE, NULL);
|
||||
if (mdl_copy == NULL)
|
||||
{
|
||||
@@ -2239,7 +2258,6 @@ windivert_write_bad_packet:
|
||||
DEBUG_ERROR("failed to allocate MDL for injected packet", status);
|
||||
goto windivert_write_exit;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(mdl_copy);
|
||||
status = FwpsAllocateNetBufferAndNetBufferList0(nbl_pool_handle, 0, 0,
|
||||
mdl_copy, 0, data_len, &buffers);
|
||||
@@ -2250,6 +2268,7 @@ windivert_write_bad_packet:
|
||||
goto windivert_write_exit;
|
||||
}
|
||||
|
||||
// Inject packet:
|
||||
handle = (ipv4? inject_handle: injectv6_handle);
|
||||
compl_handle = ((flags & WINDIVERT_FLAG_DEBUG) != 0? (HANDLE)request: NULL);
|
||||
if (layer == WINDIVERT_LAYER_NETWORK_FORWARD)
|
||||
@@ -3521,7 +3540,7 @@ static void windivert_resource_assignment_v4_classify(
|
||||
socket_data.RemoteAddr[2] = 0;
|
||||
socket_data.RemoteAddr[3] = 0;
|
||||
value = fixed_vals->incomingValue[
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_PORT].value;
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V4_IP_LOCAL_PORT].value;
|
||||
socket_data.LocalPort = (value.type == FWP_UINT16? value.uint16: 0);
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = fixed_vals->incomingValue[
|
||||
@@ -3575,7 +3594,7 @@ static void windivert_resource_assignment_v6_classify(
|
||||
socket_data.RemoteAddr[2] = 0;
|
||||
socket_data.RemoteAddr[3] = 0;
|
||||
value = fixed_vals->incomingValue[
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_PORT].value;
|
||||
FWPS_FIELD_ALE_RESOURCE_ASSIGNMENT_V6_IP_LOCAL_PORT].value;
|
||||
socket_data.LocalPort = (value.type == FWP_UINT16? value.uint16: 0);
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = fixed_vals->incomingValue[
|
||||
@@ -3697,7 +3716,7 @@ static void windivert_auth_listen_v4_classify(
|
||||
socket_data.RemoteAddr[2] = 0;
|
||||
socket_data.RemoteAddr[3] = 0;
|
||||
socket_data.LocalPort = fixed_vals->incomingValue[
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_PORT].value.uint16;
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V4_IP_LOCAL_PORT].value.uint16;
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = IPPROTO_TCP;
|
||||
|
||||
@@ -3737,7 +3756,7 @@ static void windivert_auth_listen_v6_classify(
|
||||
socket_data.RemoteAddr[2] = 0;
|
||||
socket_data.RemoteAddr[3] = 0;
|
||||
socket_data.LocalPort = fixed_vals->incomingValue[
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_PORT].value.uint16;
|
||||
FWPS_FIELD_ALE_AUTH_LISTEN_V6_IP_LOCAL_PORT].value.uint16;
|
||||
socket_data.RemotePort = 0;
|
||||
socket_data.Protocol = IPPROTO_TCP;
|
||||
|
||||
@@ -5456,8 +5475,6 @@ windivert_filter_compile_error:
|
||||
/* WINDIVERT REFLECT MANAGER IMPLEMENTATION */
|
||||
/****************************************************************************/
|
||||
|
||||
#include "windivert_shared.c"
|
||||
|
||||
/*
|
||||
* WinDivert reflect state.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user