in network/trans/WFPSampler/sys/ClassifyFunctions_AdvancedPacketInjectionCallouts.cpp [3717:3990]
VOID NTAPI ClassifyAdvancedPacketInjection(_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
_Inout_opt_ VOID* pNetBufferList,
_In_opt_ const VOID* pClassifyContext,
_In_ const FWPS_FILTER* pFilter,
_In_ UINT64 flowContext,
_Inout_ FWPS_CLASSIFY_OUT* pClassifyOut)
{
NT_ASSERT(pClassifyValues);
NT_ASSERT(pMetadata);
NT_ASSERT(pFilter);
NT_ASSERT(pClassifyOut);
NT_ASSERT(pFilter->providerContext);
NT_ASSERT(pFilter->providerContext->type == FWPM_GENERAL_CONTEXT);
NT_ASSERT(pFilter->providerContext->dataBuffer);
NT_ASSERT(pFilter->providerContext->dataBuffer->size == sizeof(PC_ADVANCED_PACKET_INJECTION_DATA));
#if(NTDDI_VERSION >= NTDDI_WIN8)
NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V6 ||
pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V4 ||
pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V6 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_TRANSPORT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_TRANSPORT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_TRANSPORT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_TRANSPORT_V6 ||
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 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V6 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V6 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE ||
pClassifyValues->layerId == FWPS_LAYER_INGRESS_VSWITCH_ETHERNET ||
pClassifyValues->layerId == FWPS_LAYER_EGRESS_VSWITCH_ETHERNET);
#else
NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_IPPACKET_V6 ||
pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V4 ||
pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V6 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_TRANSPORT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_INBOUND_TRANSPORT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_TRANSPORT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_TRANSPORT_V6 ||
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 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V4 ||
pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_ICMP_ERROR_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V4 ||
pClassifyValues->layerId == FWPS_LAYER_ALE_FLOW_ESTABLISHED_V6 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V6);
#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_INFO_LEVEL,
" ---> ClassifyAdvancedPacketInjection() [Layer: %s][FilterID: %#I64x][Rights: %#x]",
KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
pFilter->filterId,
pClassifyOut->rights);
#if DBG
PrvAdvancedPacketInjectionCountersIncrement(pClassifyValues,
pMetadata,
&g_apiTotalClassifies);
#endif /// DBG
if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE)
{
/// Packets are not available for TCP @ ALE_AUTH_CONNECT, so skip over as there is nothing to inject
if(pNetBufferList)
{
NTSTATUS status = STATUS_SUCCESS;
FWP_VALUE* pFlags = 0;
INJECTION_DATA* pInjectionData = 0;
pClassifyOut->actionType = FWP_ACTION_CONTINUE;
pFlags = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_FLAGS);
if(pFlags &&
pFlags->type == FWP_UINT32)
{
/// For IPsec interop, if ALE classification is required, bypass the injection
if(pFlags->uint32 & FWP_CONDITION_FLAG_IS_IPSEC_SECURED &&
FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_ALE_CLASSIFY_REQUIRED))
HLPR_BAIL;
/// Inject the individual fragments, but not the fragment grouping of those fragments
if(pFlags->uint32 & FWP_CONDITION_FLAG_IS_FRAGMENT_GROUP)
HLPR_BAIL;
}
#pragma warning(push)
#pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using AdvancedPacketInjectionCompletionDataDestroy
status = KrnlHlprInjectionDataCreate(&pInjectionData,
pClassifyValues,
pMetadata,
(NET_BUFFER_LIST*)pNetBufferList,
pFilter);
HLPR_BAIL_ON_FAILURE(status);
#pragma warning(pop)
if(pInjectionData->injectionState != FWPS_PACKET_INJECTED_BY_SELF &&
pInjectionData->injectionState != FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF)
{
BOOLEAN performOutOfBand = TRUE;
FWP_VALUE* pProtocolValue = 0;
PC_ADVANCED_PACKET_INJECTION_DATA* pData = (PC_ADVANCED_PACKET_INJECTION_DATA*)pFilter->providerContext->dataBuffer->data;
pClassifyOut->actionType = FWP_ACTION_BLOCK;
pClassifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
pClassifyOut->rights ^= FWPS_RIGHT_ACTION_WRITE;
#if(NTDDI_VERSION >= NTDDI_WIN8)
if(pMetadata->l2Flags & FWPS_L2_INCOMING_FLAG_RECLASSIFY_MULTI_DESTINATION)
HLPR_BAIL;
#endif
if(pFlags &&
pFlags->type == FWP_UINT32 &&
pFlags->uint32 & FWP_CONDITION_FLAG_IS_IPSEC_SECURED)
pInjectionData->isIPsecSecured = TRUE;
/// Override the default of performing Out of Band with the user's specified setting ...
if(pData->performInline)
performOutOfBand = FALSE;
/// ... however, due to TCP's locking semantics, TCP can only be injected Out of Band at any transport layer or equivalent, ...
pProtocolValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_PROTOCOL);
if((pProtocolValue &&
pProtocolValue->uint8 == IPPROTO_TCP &&
pClassifyValues->layerId > FWPS_LAYER_IPFORWARD_V6_DISCARD) ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V4 ||
pClassifyValues->layerId == FWPS_LAYER_STREAM_PACKET_V6)
performOutOfBand = TRUE;
/// ... and inbound injection of loopback traffic requires us to use Out of Band modification as well due to address lookups.
if(!performOutOfBand &&
pFlags &&
pFlags->type == FWP_UINT32 &&
pFlags->uint32 & FWP_CONDITION_FLAG_IS_LOOPBACK &&
pInjectionData->direction == FWP_DIRECTION_INBOUND)
{
FWP_VALUE* pLocalAddress = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues,
&FWPM_CONDITION_IP_LOCAL_ADDRESS);
FWP_VALUE* pRemoteAddress = 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 &&
pLocalAddress->byteArray16 &&
RtlCompareMemory(&(pLocalAddress->byteArray16->byteArray16),
IPV6_LOOPBACK_ADDRESS,
IPV6_ADDRESS_SIZE)))) ||
(pRemoteAddress &&
((pRemoteAddress->type == FWP_UINT32 &&
RtlCompareMemory(&(pRemoteAddress->uint32),
IPV4_LOOPBACK_ADDRESS,
IPV4_ADDRESS_SIZE)) ||
(pRemoteAddress->type == FWP_BYTE_ARRAY16_TYPE &&
pRemoteAddress->byteArray16 &&
RtlCompareMemory(&(pRemoteAddress->byteArray16->byteArray16),
IPV6_LOOPBACK_ADDRESS,
IPV6_ADDRESS_SIZE)))))
performOutOfBand = TRUE;
}
if(performOutOfBand)
status = TriggerAdvancedPacketInjectionOutOfBand(pClassifyValues,
pMetadata,
pNetBufferList,
pClassifyContext,
pFilter,
flowContext,
pClassifyOut,
pInjectionData,
pData);
else
status = TriggerAdvancedPacketInjectionInline(pClassifyValues,
pMetadata,
pNetBufferList,
pClassifyContext,
pFilter,
flowContext,
pClassifyOut,
&pInjectionData);
}
else
{
pClassifyOut->actionType = FWP_ACTION_PERMIT;
KrnlHlprInjectionDataDestroy(&pInjectionData);
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_INFO_LEVEL,
" -- Injection previously performed.\n");
}
HLPR_BAIL_LABEL:
NT_ASSERT(status == STATUS_SUCCESS);
if(status != STATUS_SUCCESS)
{
KrnlHlprInjectionDataDestroy(&pInjectionData);
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! ClassifyAdvancedPacketInjection() [status: %#x]\n",
status);
}
}
else
pClassifyOut->actionType = FWP_ACTION_PERMIT;
}
#if DBG
PrvAdvancedPacketInjectionCountersIncrementTotalActionResults(pClassifyValues,
pMetadata,
pClassifyOut);
#endif /// DBG
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_INFO_LEVEL,
" <--- ClassifyAdvancedPacketInjection() [Layer: %s][FilterID: %#I64x][Action: %#x][Rights: %#x][Absorb: %s]\n",
KrnlHlprFwpsLayerIDToString(pClassifyValues->layerId),
pFilter->filterId,
pClassifyOut->actionType,
pClassifyOut->rights,
(pClassifyOut->flags & FWPS_CLASSIFY_OUT_FLAG_ABSORB) ? "TRUE" : "FALSE");
return;
}