More minor API improvements.
- Revert batching for WinDivertHelperCalcChecksums(). All non-ParsePacket helper functions support a single packet only. This is much simpler. - WinDivertHelperCalcChecksums() now returns a simple BOOL. - More WinDivertHelper*() functions set the error code.
This commit is contained in:
+13
-5
@@ -2416,6 +2416,7 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
UINT32 data32;
|
||||
BOOL pass, big;
|
||||
int cmp;
|
||||
PVOID next;
|
||||
WINDIVERT_FILTER object[WINDIVERT_FILTER_MAXLEN];
|
||||
UINT obj_len;
|
||||
|
||||
@@ -2435,9 +2436,10 @@ extern BOOL WinDivertHelperEvalFilter(const char *filter, const VOID *packet,
|
||||
}
|
||||
WinDivertHelperParsePacket((PVOID)packet, packet_len, &protocol,
|
||||
&iphdr, &ipv6hdr, &icmphdr, &icmpv6hdr, &tcphdr, &udphdr,
|
||||
NULL, &payload_len, NULL, NULL);
|
||||
NULL, &payload_len, &next, NULL);
|
||||
header_len = packet_len - payload_len;
|
||||
if ((addr->IPv6 && ipv6hdr == NULL) ||
|
||||
if (next != NULL ||
|
||||
(addr->IPv6 && ipv6hdr == NULL) ||
|
||||
(!addr->IPv6 && iphdr == NULL))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
@@ -4585,10 +4587,16 @@ extern UINT64 WinDivertHelperHashPacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_ICMPV6HDR icmpv6_header = NULL;
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
PVOID next;
|
||||
|
||||
WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header, &udp_header,
|
||||
NULL, NULL, NULL, NULL);
|
||||
if (!WinDivertHelperParsePacket((PVOID)pPacket, packetLen, NULL,
|
||||
&ip_header, &ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, NULL, &next, NULL) ||
|
||||
next != NULL)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return WinDivertHashPacket(seed, ip_header, ipv6_header, icmp_header,
|
||||
icmpv6_header, tcp_header, udp_header);
|
||||
}
|
||||
|
||||
+97
-89
@@ -296,7 +296,7 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
PWINDIVERT_TCPHDR tcp_header = NULL;
|
||||
PWINDIVERT_UDPHDR udp_header = NULL;
|
||||
UINT16 header_len;
|
||||
UINT8 trans_proto = 0;
|
||||
UINT8 protocol = 0;
|
||||
PVOID data = NULL, next = NULL;
|
||||
UINT data_len = 0, next_len = 0, packet_len;
|
||||
BOOL success = FALSE;
|
||||
@@ -313,17 +313,21 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
{
|
||||
case 4:
|
||||
if (data_len < sizeof(WINDIVERT_IPHDR) ||
|
||||
ip_header->HdrLength < 5 ||
|
||||
data_len < ip_header->HdrLength*sizeof(UINT32) ||
|
||||
(UINT)ntohs(ip_header->Length) > data_len)
|
||||
ip_header->HdrLength < 5)
|
||||
{
|
||||
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)
|
||||
protocol = ip_header->Protocol;
|
||||
if (data_len < header_len || data_len < packet_len ||
|
||||
packet_len < header_len)
|
||||
{
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
else if (packet_len < data_len)
|
||||
{
|
||||
next = (PVOID)((UINT8 *)data + packet_len);
|
||||
next_len = data_len - packet_len;
|
||||
@@ -335,13 +339,13 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
ip_header = NULL;
|
||||
ipv6_header = (PWINDIVERT_IPV6HDR)data;
|
||||
if (data_len < sizeof(WINDIVERT_IPV6HDR) ||
|
||||
ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR) >
|
||||
data_len)
|
||||
data_len < ntohs(ipv6_header->Length) +
|
||||
sizeof(WINDIVERT_IPV6HDR))
|
||||
{
|
||||
ipv6_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
trans_proto = ipv6_header->NextHdr;
|
||||
protocol = ipv6_header->NextHdr;
|
||||
packet_len = ntohs(ipv6_header->Length) + sizeof(WINDIVERT_IPV6HDR);
|
||||
if (packet_len < data_len)
|
||||
{
|
||||
@@ -350,15 +354,16 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
}
|
||||
data = (PVOID)((UINT8 *)data + sizeof(WINDIVERT_IPV6HDR));
|
||||
data_len = packet_len - sizeof(WINDIVERT_IPV6HDR);
|
||||
trans_proto = WinDivertSkipExtHeaders(trans_proto, (UINT8 **)&data,
|
||||
protocol = WinDivertSkipExtHeaders(protocol, (UINT8 **)&data,
|
||||
&data_len);
|
||||
break;
|
||||
default:
|
||||
ip_header = NULL;
|
||||
goto WinDivertHelperParsePacketExit;
|
||||
}
|
||||
data = (data_len == 0? NULL: data);
|
||||
success = TRUE;
|
||||
switch (trans_proto)
|
||||
switch (protocol)
|
||||
{
|
||||
case IPPROTO_TCP:
|
||||
tcp_header = (PWINDIVERT_TCPHDR)data;
|
||||
@@ -418,7 +423,7 @@ extern BOOL WinDivertHelperParsePacket(const VOID *pPacket, UINT packetLen,
|
||||
WinDivertHelperParsePacketExit:
|
||||
if (pProtocol != NULL)
|
||||
{
|
||||
*pProtocol = trans_proto;
|
||||
*pProtocol = protocol;
|
||||
}
|
||||
if (ppIpHdr != NULL)
|
||||
{
|
||||
@@ -461,13 +466,20 @@ WinDivertHelperParsePacketExit:
|
||||
*pNextLen = next_len;
|
||||
}
|
||||
|
||||
#ifndef WINDIVERT_KERNEL
|
||||
if (!success)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
}
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
extern BOOL WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
WINDIVERT_ADDRESS *pAddr, UINT64 flags)
|
||||
{
|
||||
UINT8 pseudo_header[
|
||||
@@ -480,100 +492,96 @@ extern UINT WinDivertHelperCalcChecksums(PVOID pPacket, UINT packetLen,
|
||||
PWINDIVERT_TCPHDR tcp_header;
|
||||
PWINDIVERT_UDPHDR udp_header;
|
||||
UINT payload_len, checksum_len;
|
||||
UINT count = 0;
|
||||
|
||||
while (WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, &payload_len, &pPacket, &packetLen))
|
||||
if (!WinDivertHelperParsePacket(pPacket, packetLen, NULL, &ip_header,
|
||||
&ipv6_header, &icmp_header, &icmpv6_header, &tcp_header,
|
||||
&udp_header, NULL, &payload_len, pPacket, NULL) ||
|
||||
pPacket != NULL)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
if (ip_header != NULL && !(flags & WINDIVERT_HELPER_NO_IP_CHECKSUM))
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
|
||||
ip_header->HdrLength*sizeof(UINT32));
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
ip_header->Checksum = 0;
|
||||
ip_header->Checksum = WinDivertCalcChecksum(NULL, 0, ip_header,
|
||||
ip_header->HdrLength*sizeof(UINT32));
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->IPChecksum = 1;
|
||||
}
|
||||
count++;
|
||||
pAddr->IPChecksum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (icmp_header != NULL)
|
||||
if (icmp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMP_CHECKSUM) != 0)
|
||||
{
|
||||
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;
|
||||
return TRUE;
|
||||
}
|
||||
icmp_header->Checksum = 0;
|
||||
icmp_header->Checksum = WinDivertCalcChecksum(NULL, 0,
|
||||
icmp_header, payload_len + sizeof(WINDIVERT_ICMPHDR));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (icmpv6_header != NULL)
|
||||
if (icmpv6_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_ICMPV6_CHECKSUM) != 0)
|
||||
{
|
||||
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;
|
||||
return TRUE;
|
||||
}
|
||||
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);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (tcp_header != NULL)
|
||||
if (tcp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_TCP_CHECKSUM) != 0)
|
||||
{
|
||||
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;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (udp_header != NULL)
|
||||
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)
|
||||
{
|
||||
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,
|
||||
ipv6_header, IPPROTO_UDP, checksum_len, pseudo_header);
|
||||
udp_header->Checksum = 0;
|
||||
udp_header->Checksum = WinDivertCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, udp_header, checksum_len);
|
||||
if (udp_header->Checksum == 0)
|
||||
{
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->UDPChecksum = 1;
|
||||
}
|
||||
count++;
|
||||
pAddr->TCPChecksum = 1;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (udp_header != NULL)
|
||||
{
|
||||
if ((flags & WINDIVERT_HELPER_NO_UDP_CHECKSUM) != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
// 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 = WinDivertCalcChecksum(
|
||||
pseudo_header, pseudo_header_len, udp_header, checksum_len);
|
||||
if (udp_header->Checksum == 0)
|
||||
{
|
||||
udp_header->Checksum = 0xFFFF;
|
||||
}
|
||||
if (pAddr != NULL)
|
||||
{
|
||||
pAddr->UDPChecksum = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+7
-8
@@ -2027,6 +2027,10 @@ UINT64 <b>WinDivertHelperHashPacket</b>(
|
||||
<p>
|
||||
<b>Return Value</b><br>
|
||||
A 64bit hash value.
|
||||
Returns <code>0</code> with error code <code>ERROR_INVALID_PARAMETER</code>
|
||||
for invalid packets.
|
||||
Note that <code>0</code> (without an error code) is also a legitimate hash
|
||||
value.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
Calculates a 64bit hash value of the given packet.
|
||||
@@ -2158,7 +2162,7 @@ Convert an IPv6 address into a string.
|
||||
<a name="divert_helper_calc_checksums"><h3>6.13 WinDivertHelperCalcChecksums</h3></a>
|
||||
<table border="1" cellpadding="5"><tr><td>
|
||||
<pre>
|
||||
UINT <b>WinDivertHelperCalcChecksums</b>(
|
||||
BOOL <b>WinDivertHelperCalcChecksums</b>(
|
||||
__inout PVOID pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr,
|
||||
@@ -2189,7 +2193,8 @@ UINT <b>WinDivertHelperCalcChecksums</b>(
|
||||
</ul>
|
||||
<p>
|
||||
<b>Return Value</b><br>
|
||||
The number of checksums calculated.
|
||||
<code>TRUE</code> if successful, <code>FALSE</code> if an error occurred.
|
||||
Use <code>GetLastError()</code> to get the reason for the error.
|
||||
</p><p>
|
||||
<b>Remarks</b><br>
|
||||
(Re)calculates the checksum for any IPv4/ICMP/ICMPv6/TCP/UDP checksum present
|
||||
@@ -2198,12 +2203,6 @@ Individual checksum calculations may be disabled via the appropriate flag.
|
||||
Typically this function should be invoked on a modified packet before it is
|
||||
injected with <a href="#divert_send"><code>WinDivertSend()</code></a>.
|
||||
</p><p>
|
||||
The <code>pPacket</code> parameter may also point to a batch (>1) of
|
||||
packets.
|
||||
In this case, <code>packetLen</code> should be the total length of the batch,
|
||||
and this function will (re)calculate the checksums for all packets in the
|
||||
batch.
|
||||
</p><p>
|
||||
By default this function will calculate each checksum from scratch, even if
|
||||
the existing checksum is correct.
|
||||
This may be inefficient for some applications.
|
||||
|
||||
+1
-1
@@ -520,7 +520,7 @@ extern WINDIVERTEXPORT BOOL WinDivertHelperFormatIPv6Address(
|
||||
/*
|
||||
* Calculate IPv4/IPv6/ICMP/ICMPv6/TCP/UDP checksums.
|
||||
*/
|
||||
extern WINDIVERTEXPORT UINT WinDivertHelperCalcChecksums(
|
||||
extern WINDIVERTEXPORT BOOL WinDivertHelperCalcChecksums(
|
||||
__inout VOID *pPacket,
|
||||
__in UINT packetLen,
|
||||
__out_opt WINDIVERT_ADDRESS *pAddr,
|
||||
|
||||
Reference in New Issue
Block a user