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
+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);