in network/trans/WFPSampler/sys/ClassifyFunctions_BasicPacketModificationCallouts.cpp [4016:4878]
NTSTATUS PerformBasicPacketModificationAtInboundTransport(_In_ CLASSIFY_DATA** ppClassifyData,
_In_ INJECTION_DATA** ppInjectionData,
_In_ PC_BASIC_PACKET_MODIFICATION_DATA* pModificationData,
_In_ BOOLEAN isInline = FALSE)
{
#if DBG
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_INFO_LEVEL,
" ---> PerformBasicPacketModificationAtInboundTransport()\n");
#endif /// DBG
NT_ASSERT(ppClassifyData);
NT_ASSERT(ppInjectionData);
NT_ASSERT(pModificationData);
NT_ASSERT(*ppClassifyData);
NT_ASSERT(*ppInjectionData);
NTSTATUS status = STATUS_SUCCESS;
FWPS_INCOMING_VALUES* pClassifyValues = (FWPS_INCOMING_VALUES*)(*ppClassifyData)->pClassifyValues;
FWPS_INCOMING_METADATA_VALUES* pMetadata = (FWPS_INCOMING_METADATA_VALUES*)(*ppClassifyData)->pMetadataValues;
COMPARTMENT_ID compartmentID = DEFAULT_COMPARTMENT_ID;
IF_INDEX interfaceIndex = 0;
IF_INDEX subInterfaceIndex = 0;
UINT32 flags = 0;
NET_BUFFER_LIST* pNetBufferList = 0;
BASIC_PACKET_MODIFICATION_COMPLETION_DATA* pCompletionData = 0;
UINT32 ipHeaderSize = 0;
UINT32 transportHeaderSize = 0;
UINT32 bytesRetreated = 0;
IPPROTO protocol = IPPROTO_MAX;
FWP_VALUE* pProtocol = 0;
FWP_VALUE* pInterfaceIndex = 0;
FWP_VALUE* pSubInterfaceIndex = 0;
FWP_VALUE* pFlags = 0;
FWPS_PACKET_LIST_INFORMATION* pPacketInformation = 0;
BOOLEAN bypassInjection = FALSE;
UINT64 endpointHandle = 0;
BYTE* pSourceAddress = 0;
BYTE* pDestinationAddress = 0;
NDIS_TCP_IP_CHECKSUM_PACKET_INFO checksumInfo = {0};
#if DBG
KIRQL irql = KeGetCurrentIrql();
#endif /// DBG
#pragma warning(push)
#pragma warning(disable: 6014) /// pCompletionData will be freed in completionFn using BasicPacketModificationCompletionDataDestroy
HLPR_NEW(pCompletionData,
BASIC_PACKET_MODIFICATION_COMPLETION_DATA,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(pCompletionData,
status);
#pragma warning(pop)
KeInitializeSpinLock(&(pCompletionData->spinLock));
pCompletionData->performedInline = isInline;
pCompletionData->pClassifyData = *ppClassifyData;
pCompletionData->pInjectionData = *ppInjectionData;
/// Responsibility for freeing this memory has been transferred to the pCompletionData
*ppClassifyData = 0;
*ppInjectionData = 0;
HLPR_NEW(pPacketInformation,
FWPS_PACKET_LIST_INFORMATION,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(pPacketInformation,
status);
pInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_INTERFACE_INDEX);
if(pInterfaceIndex &&
pInterfaceIndex->type == FWP_UINT32)
interfaceIndex = (IF_INDEX)pInterfaceIndex->uint32;
pSubInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_SUB_INTERFACE_INDEX);
if(pSubInterfaceIndex &&
pSubInterfaceIndex->type == FWP_UINT32)
subInterfaceIndex = (IF_INDEX)pSubInterfaceIndex->uint32;
pFlags = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_FLAGS);
if(pFlags &&
pFlags->type == FWP_UINT32)
flags = pFlags->uint32;
if(pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V4)
protocol = IPPROTO_ICMP;
else if(pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V6 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V6)
protocol = IPPROTO_ICMPV6;
#if(NTDDI_VERSION >= NTDDI_WIN7)
else if(pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V6)
protocol = IPPROTO_TCP;
#endif /// (NTDDI_VERSION >= NTDDI_WIN7)
else
{
pProtocol = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_PROTOCOL);
HLPR_BAIL_ON_NULL_POINTER(pProtocol);
protocol = (IPPROTO)pProtocol->uint8;
}
if(pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V4)
{
ipHeaderSize = IPV4_HEADER_MIN_SIZE;
if(protocol == IPPROTO_ICMP)
transportHeaderSize = ICMP_HEADER_MIN_SIZE;
else if(protocol == IPPROTO_TCP)
transportHeaderSize = TCP_HEADER_MIN_SIZE;
else if(protocol == IPPROTO_UDP)
transportHeaderSize = UDP_HEADER_MIN_SIZE;
}
else if(pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V6)
{
ipHeaderSize = IPV6_HEADER_MIN_SIZE;
if(protocol == IPPROTO_ICMPV6)
transportHeaderSize = ICMP_HEADER_MIN_SIZE;
else if(protocol == IPPROTO_TCP)
transportHeaderSize = TCP_HEADER_MIN_SIZE;
else if(protocol == IPPROTO_UDP)
transportHeaderSize = UDP_HEADER_MIN_SIZE;
}
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_COMPARTMENT_ID))
compartmentID = (COMPARTMENT_ID)pMetadata->compartmentId;
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_IP_HEADER_SIZE) &&
pMetadata->ipHeaderSize)
ipHeaderSize = pMetadata->ipHeaderSize;
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE) &&
pMetadata->transportHeaderSize)
transportHeaderSize = pMetadata->transportHeaderSize;
bytesRetreated = ipHeaderSize;
if(protocol != IPPROTO_ICMP &&
protocol != IPPROTO_ICMPV6)
{
if(!isInline &&
protocol != IPPROTO_TCP &&
!(protocol == IPPROTO_UDP &&
flags & FWP_CONDITION_FLAG_IS_RAW_ENDPOINT) &&
(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6))
{
/// For asynchronous execution, the drop will cause the stack to continue processing on the
/// NBL for auditing purposes. This processing retreats the NBL Offset to the Transport header.
/// We need to take this into account because we only took a reference on the NBL.
}
else
{
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE))
bytesRetreated += transportHeaderSize;
}
}
else
{
if(pClassifyValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V4 ||
pClassifyValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V6 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V4 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V6)
{
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE))
bytesRetreated += transportHeaderSize;
}
}
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE))
endpointHandle = pMetadata->transportEndpointHandle;
/// Query to see if IPsec has applied tunnel mode SA's to this NET_BUFFER_LIST ...
status = FwpsGetPacketListSecurityInformation((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket,
FWPS_PACKET_LIST_INFORMATION_QUERY_ALL_INBOUND,
pPacketInformation);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport: FwpsGetPacketListSecurityInformation() [status: %#x]\n",
status);
HLPR_BAIL;
}
/// ... if it has, then bypass the injection until the NET_BUFFER_LIST has come out of the tunnel
if((pPacketInformation->ipsecInformation.inbound.isTunnelMode &&
!(pPacketInformation->ipsecInformation.inbound.isDeTunneled)) ||
pPacketInformation->ipsecInformation.inbound.isSecure)
{
bypassInjection = TRUE;
HLPR_BAIL;
}
/// Initial offset is at the data, so retreat the size of the IP Header and Transport Header ...
/// except for ICMP, offset is at the ICMP Header, so retreat the size of the IP Header ...
status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
bytesRetreated,
0,
0);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport: NdisRetreatNetBufferDataStart() [status: %#x]\n",
status);
HLPR_BAIL;
}
/// ... clone the entire NET_BUFFER_LIST ...
status = FwpsAllocateCloneNetBufferList((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket,
g_pNDISPoolData->nblPoolHandle,
g_pNDISPoolData->nbPoolHandle,
0,
&pNetBufferList);
/// ... and advance the offset back to the original position.
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket),
bytesRetreated,
FALSE,
0);
if(status != STATUS_SUCCESS ||
!pNetBufferList)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport: FwpsAllocateCloneNetBufferList() [status: %#x]\n",
status);
HLPR_BAIL;
}
checksumInfo.Value = (ULONG)(ULONG_PTR)NET_BUFFER_LIST_INFO((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket,
TcpIpChecksumNetBufferListInfo);
/// Handle if the packet was IPsec secured
if(pCompletionData->pInjectionData->isIPsecSecured)
{
/// For performance reasons, IPsec leaves the original ESP / AH information in the IP Header ...
UINT32 headerIncludeSize = 0;
UINT32 ipv4Address = 0;
UINT32 addressSize = 0;
FWP_VALUE* pRemoteAddressValue = 0;
FWP_VALUE* pLocalAddressValue = 0;
FWP_VALUE* pProtocolValue = 0;
pRemoteAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_REMOTE_ADDRESS);
if(pRemoteAddressValue)
{
if(pRemoteAddressValue->type == FWP_BYTE_ARRAY16_TYPE)
addressSize = IPV6_ADDRESS_SIZE;
else
addressSize = IPV4_ADDRESS_SIZE;
HLPR_NEW_ARRAY(pSourceAddress,
BYTE,
addressSize,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(pSourceAddress,
status);
if(pRemoteAddressValue->type == FWP_BYTE_ARRAY16_TYPE)
RtlCopyMemory(pSourceAddress,
pRemoteAddressValue->byteArray16->byteArray16,
addressSize);
else
{
ipv4Address = htonl(pRemoteAddressValue->uint32);
RtlCopyMemory(pSourceAddress,
&ipv4Address,
addressSize);
}
}
pLocalAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_LOCAL_ADDRESS);
if(pLocalAddressValue)
{
if(pLocalAddressValue->type == FWP_BYTE_ARRAY16_TYPE)
addressSize = IPV6_ADDRESS_SIZE;
else
addressSize = IPV4_ADDRESS_SIZE;
HLPR_NEW_ARRAY(pDestinationAddress,
BYTE,
addressSize,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(pDestinationAddress,
status);
if(pLocalAddressValue->type == FWP_BYTE_ARRAY16_TYPE)
RtlCopyMemory(pDestinationAddress,
pLocalAddressValue->byteArray16->byteArray16,
addressSize);
else
{
ipv4Address = htonl(pLocalAddressValue->uint32);
RtlCopyMemory(pDestinationAddress,
&ipv4Address,
addressSize);
}
}
pProtocolValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_PROTOCOL);
if(pProtocolValue &&
pProtocolValue->type == FWP_UINT8)
protocol = (IPPROTO)pProtocolValue->uint8;
else
protocol = IPPROTO_MAX;
NT_ASSERT(protocol != IPPROTO_MAX);
#if (NTDDI_VERSION >= NTDDI_WIN6SP1)
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_HEADER_INCLUDE_HEADER))
headerIncludeSize = pMetadata->headerIncludeHeaderLength;
#endif // (NTDDI_VERSION >= NTDDI_WIN6SP1)
if(pSourceAddress == 0 ||
pDestinationAddress == 0)
{
status = STATUS_INVALID_MEMBER;
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport() [status: %#x][pSourceAddress: %#p][pDestinationAddress: %#p]\n",
status,
pSourceAddress,
pDestinationAddress);
HLPR_BAIL;
}
/// ... so we must re-construct the IPHeader with the appropriate information
/// for checksum offload, this will recalculate the checksums
status = FwpsConstructIpHeaderForTransportPacket(pNetBufferList,
headerIncludeSize,
pCompletionData->pInjectionData->addressFamily,
pSourceAddress,
pDestinationAddress,
protocol,
endpointHandle,
(const WSACMSGHDR*)pCompletionData->pInjectionData->pControlData,
pCompletionData->pInjectionData->controlDataLength,
0,
0,
interfaceIndex,
subInterfaceIndex);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketInjectionAtInboundTransport: FwpsConstructIpHeaderForTransportPacket() [status: %#x]\n",
status);
HLPR_BAIL;
}
}
/// Handle if this packet had the IP or Transport checksums offloaded or if it's loopback
else if(checksumInfo.Receive.NdisPacketIpChecksumSucceeded ||
checksumInfo.Receive.NdisPacketTcpChecksumSucceeded ||
checksumInfo.Receive.NdisPacketUdpChecksumSucceeded ||
flags & FWP_CONDITION_FLAG_IS_LOOPBACK)
{
/// Prevent TCP/IP Zone crossing and recalculate the checksums
if(flags & FWP_CONDITION_FLAG_IS_LOOPBACK)
{
FWP_VALUE* pLocalAddress = 0;
FWP_VALUE* pRemoteAddress = 0;
FWP_VALUE* pLoopbackAddress = 0;
pLocalAddress = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_REMOTE_ADDRESS);
if(pLocalAddress &&
((pLocalAddress->type == FWP_UINT32 &&
RtlCompareMemory(&(pLocalAddress->uint32),
IPV4_LOOPBACK_ADDRESS,
IPV4_ADDRESS_SIZE)) ||
(pLocalAddress->type == FWP_BYTE_ARRAY16_TYPE &&
RtlCompareMemory(pLocalAddress->byteArray16->byteArray16,
IPV6_LOOPBACK_ADDRESS,
IPV6_ADDRESS_SIZE))))
pLoopbackAddress = pLocalAddress;
if(!pLoopbackAddress)
{
pRemoteAddress = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_REMOTE_ADDRESS);
if(pRemoteAddress &&
((pRemoteAddress->type == FWP_UINT32 &&
RtlCompareMemory(&(pRemoteAddress->uint32),
IPV4_LOOPBACK_ADDRESS,
IPV4_ADDRESS_SIZE)) ||
(pRemoteAddress->type == FWP_BYTE_ARRAY16_TYPE &&
RtlCompareMemory(pRemoteAddress->byteArray16->byteArray16,
IPV6_LOOPBACK_ADDRESS,
IPV6_ADDRESS_SIZE))))
pLoopbackAddress = pRemoteAddress;
}
if(pLoopbackAddress)
{
status = KrnlHlprIPHeaderModifyLoopbackToLocal(pMetadata,
pLoopbackAddress,
ipHeaderSize,
pNetBufferList,
(const WSACMSGHDR*)pCompletionData->pInjectionData->pControlData,
pCompletionData->pInjectionData->controlDataLength);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport: KrnlHlprIPHeaderModifyLoopbackToLocal() [status: %#x]\n",
status);
HLPR_BAIL;
}
}
}
else
{
/// Recalculate the checksum
if(pCompletionData->pInjectionData->addressFamily == AF_INET)
KrnlHlprIPHeaderCalculateV4Checksum(pNetBufferList,
ipHeaderSize);
}
}
pCompletionData->refCount = KrnlHlprNBLGetRequiredRefCount(pNetBufferList);
if(pModificationData->flags)
{
FWP_VALUE* pLocalAddressValue = 0;
FWP_VALUE* pRemoteAddressValue = 0;
BYTE pIPDestinationAddress[16] = {0};
BYTE pIPSourceAddress[16] = {0};
pRemoteAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_REMOTE_ADDRESS);
HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pRemoteAddressValue,
status);
pLocalAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_LOCAL_ADDRESS);
HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pLocalAddressValue,
status);
if(pCompletionData->pInjectionData->addressFamily == AF_INET6)
{
RtlCopyMemory(pIPSourceAddress,
pRemoteAddressValue->byteArray16->byteArray16,
IPV6_ADDRESS_SIZE);
RtlCopyMemory(pIPDestinationAddress,
pLocalAddressValue->byteArray16->byteArray16,
IPV6_ADDRESS_SIZE);
}
else
{
UINT32 sourceAddress = htonl(pRemoteAddressValue->uint32);
UINT32 destinationAddress = htonl(pLocalAddressValue->uint32);
RtlCopyMemory(pIPSourceAddress,
&sourceAddress,
IPV4_ADDRESS_SIZE);
RtlCopyMemory(pIPDestinationAddress,
&destinationAddress,
IPV4_ADDRESS_SIZE);
}
if(pModificationData->flags & PCPMDF_MODIFY_TRANSPORT_HEADER)
{
UINT32 tmpStatus = STATUS_SUCCESS;
FWP_VALUE* pProtocolValue = 0;
/// The clone is at the IP Header, so advance by the size of the IP Header.
NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pNetBufferList),
ipHeaderSize,
FALSE,
0);
pProtocolValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_PROTOCOL);
if(pProtocolValue &&
pProtocolValue->type == FWP_UINT8)
protocol = (IPPROTO)pProtocolValue->uint8;
else
protocol = IPPROTO_MAX;
NT_ASSERT(protocol != IPPROTO_MAX);
if(pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V4)
protocol = IPPROTO_ICMP;
else if(pClassifyValues->layerId == FWPS_LAYER_INBOUND_ICMP_ERROR_V6)
protocol = IPPROTO_ICMPV6;
switch(protocol)
{
case IPPROTO_ICMP:
{
UINT32 icmpHeaderSize = transportHeaderSize ? transportHeaderSize : ICMP_HEADER_MIN_SIZE;
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_ICMP_TYPE)
{
FWP_VALUE0 icmpType;
icmpType.type = FWP_UINT8;
icmpType.uint8 = (UINT8)ntohs(pModificationData->transportData.sourcePort);
status = KrnlHlprICMPv4HeaderModifyType(&icmpType,
pNetBufferList,
icmpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_ICMP_CODE)
{
FWP_VALUE0 icmpCode;
icmpCode.type = FWP_UINT8;
icmpCode.uint8 = (UINT8)ntohs(pModificationData->transportData.destinationPort);
status = KrnlHlprICMPv4HeaderModifyCode(&icmpCode,
pNetBufferList,
icmpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
break;
}
case IPPROTO_TCP:
{
UINT32 tcpHeaderSize = transportHeaderSize ? transportHeaderSize : TCP_HEADER_MIN_SIZE;
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_SOURCE_PORT)
{
FWP_VALUE0 srcPort;
srcPort.type = FWP_UINT16;
srcPort.uint16 = pModificationData->transportData.sourcePort;
status = KrnlHlprTCPHeaderModifySourcePort(&srcPort,
pNetBufferList,
tcpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_DESTINATION_PORT)
{
FWP_VALUE0 dstPort;
dstPort.type = FWP_UINT16;
dstPort.uint16 = pModificationData->transportData.destinationPort;
status = KrnlHlprTCPHeaderModifyDestinationPort(&dstPort,
pNetBufferList,
tcpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
break;
}
case IPPROTO_UDP:
{
UINT32 udpHeaderSize = transportHeaderSize ? transportHeaderSize : UDP_HEADER_MIN_SIZE;
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_SOURCE_PORT)
{
FWP_VALUE0 srcPort;
srcPort.type = FWP_UINT16;
srcPort.uint16 = pModificationData->transportData.sourcePort;
status = KrnlHlprUDPHeaderModifySourcePort(&srcPort,
pNetBufferList,
udpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_DESTINATION_PORT)
{
FWP_VALUE0 dstPort;
dstPort.type = FWP_UINT16;
dstPort.uint16 = pModificationData->transportData.destinationPort;
status = KrnlHlprUDPHeaderModifyDestinationPort(&dstPort,
pNetBufferList,
udpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
break;
}
case IPPROTO_ICMPV6:
{
UINT32 icmpHeaderSize = transportHeaderSize ? transportHeaderSize : ICMP_HEADER_MIN_SIZE;
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_ICMP_TYPE)
{
FWP_VALUE0 icmpType;
icmpType.type = FWP_UINT8;
icmpType.uint8 = (UINT8)ntohs(pModificationData->transportData.sourcePort);
status = KrnlHlprICMPv6HeaderModifyType(&icmpType,
pNetBufferList,
icmpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
if(pModificationData->transportData.flags & PCPMDF_MODIFY_TRANSPORT_HEADER_ICMP_CODE)
{
FWP_VALUE0 icmpCode;
icmpCode.type = FWP_UINT8;
icmpCode.uint8 = (UINT8)ntohs(pModificationData->transportData.destinationPort);
status = KrnlHlprICMPv6HeaderModifyCode(&icmpCode,
pNetBufferList,
icmpHeaderSize);
HLPR_BAIL_ON_FAILURE_2(status);
}
break;
}
}
HLPR_BAIL_LABEL_2:
/// return the data offset to the beginning of the IP Header
tmpStatus = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(pNetBufferList),
ipHeaderSize,
0,
0);
if(tmpStatus != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketModificationAtInboundTransport: NdisRetreatNetBufferDataStart() [status: %#x]\n",
status);
HLPR_BAIL;
}
HLPR_BAIL_ON_FAILURE(status);
}
if(pModificationData->flags & PCPMDF_MODIFY_IP_HEADER)
{
if(pModificationData->ipData.flags & PCPMDF_MODIFY_IP_HEADER_INTERFACE_INDEX)
interfaceIndex = pModificationData->ipData.interfaceIndex;
if(pModificationData->ipData.flags & PCPMDF_MODIFY_IP_HEADER_SOURCE_ADDRESS)
{
FWP_VALUE value;
RtlZeroMemory(&value,
sizeof(FWP_VALUE));
if(pCompletionData->pInjectionData->addressFamily == AF_INET)
{
value.type = FWP_UINT32;
RtlCopyMemory(&(value.uint32),
pModificationData->ipData.sourceAddress.pIPv4,
IPV4_ADDRESS_SIZE);
RtlCopyMemory(pIPSourceAddress,
pModificationData->ipData.sourceAddress.pIPv4,
IPV4_ADDRESS_SIZE);
}
else
{
HLPR_NEW(value.byteArray16,
FWP_BYTE_ARRAY16,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(value.byteArray16,
status);
value.type = FWP_BYTE_ARRAY16_TYPE;
RtlCopyMemory(value.byteArray16->byteArray16,
pModificationData->ipData.sourceAddress.pIPv6,
IPV6_ADDRESS_SIZE);
RtlCopyMemory(pIPSourceAddress,
pModificationData->ipData.sourceAddress.pIPv6,
IPV6_ADDRESS_SIZE);
}
status = KrnlHlprIPHeaderModifySourceAddress(&value,
pNetBufferList,
FALSE);
KrnlHlprFwpValuePurgeLocalCopy(&value);
HLPR_BAIL_ON_FAILURE(status);
}
if(pModificationData->ipData.flags & PCPMDF_MODIFY_IP_HEADER_DESTINATION_ADDRESS)
{
FWP_VALUE value;
RtlZeroMemory(&value,
sizeof(FWP_VALUE));
if(pCompletionData->pInjectionData->addressFamily == AF_INET)
{
value.type = FWP_UINT32;
RtlCopyMemory(&(value.uint32),
pModificationData->ipData.destinationAddress.pIPv4,
IPV4_ADDRESS_SIZE);
RtlCopyMemory(pIPDestinationAddress,
pModificationData->ipData.destinationAddress.pIPv4,
IPV4_ADDRESS_SIZE);
}
else
{
#pragma warning(push)
#pragma warning(disable: 6014) /// value.byteArray16 will be freed in with call to KrnlHlprFwpValuePurgeLocalCopy
HLPR_NEW(value.byteArray16,
FWP_BYTE_ARRAY16,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(value.byteArray16,
status);
#pragma warning(pop)
value.type = FWP_BYTE_ARRAY16_TYPE;
RtlCopyMemory(value.byteArray16->byteArray16,
pModificationData->ipData.destinationAddress.pIPv6,
IPV6_ADDRESS_SIZE);
RtlCopyMemory(pIPDestinationAddress,
pModificationData->ipData.destinationAddress.pIPv6,
IPV6_ADDRESS_SIZE);
}
status = KrnlHlprIPHeaderModifyDestinationAddress(&value,
pNetBufferList,
FALSE);
KrnlHlprFwpValuePurgeLocalCopy(&value);
HLPR_BAIL_ON_FAILURE(status);
}
}
status = FwpsConstructIpHeaderForTransportPacket(pNetBufferList,
ipHeaderSize,
pCompletionData->pInjectionData->addressFamily,
(UCHAR*)pIPSourceAddress,
(UCHAR*)pIPDestinationAddress,
protocol,
endpointHandle,
(const WSACMSGHDR*)pCompletionData->pInjectionData->pControlData,
pCompletionData->pInjectionData->controlDataLength,
0,
0,
interfaceIndex,
subInterfaceIndex);
HLPR_BAIL_ON_FAILURE(status);
}
status = FwpsInjectTransportReceiveAsync(pCompletionData->pInjectionData->injectionHandle,
pCompletionData->pInjectionData->injectionContext,
0,
0,
pCompletionData->pInjectionData->addressFamily,
compartmentID,
interfaceIndex,
subInterfaceIndex,
pNetBufferList,
CompleteBasicPacketModification,
pCompletionData);
NT_ASSERT(irql == KeGetCurrentIrql());
if(status != STATUS_SUCCESS)
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! PerformBasicPacketInjectionAtInboundTransport: FwpsInjectTransportReceiveAsync() [status: %#x]\n",
status);
HLPR_BAIL_LABEL:
NT_ASSERT(status == STATUS_SUCCESS);
if(status != STATUS_SUCCESS ||
bypassInjection)
{
if(pNetBufferList)
{
FwpsFreeCloneNetBufferList(pNetBufferList,
0);
pNetBufferList = 0;
}
if(pCompletionData)
BasicPacketModificationCompletionDataDestroy(&pCompletionData,
TRUE);
}
HLPR_DELETE_ARRAY(pSourceAddress,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_DELETE_ARRAY(pDestinationAddress,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
HLPR_DELETE(pPacketInformation,
WFPSAMPLER_CALLOUT_DRIVER_TAG);
#if DBG
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_INFO_LEVEL,
" <--- PerformBasicPacketModificationAtInboundTransport() [status: %#x]\n",
status);
#endif /// DBG
return status;
}