diff options
Diffstat (limited to 'network/trans/WFPSampler/syslib/HelperFunctions_ClassifyData.cpp')
| -rw-r--r-- | network/trans/WFPSampler/syslib/HelperFunctions_ClassifyData.cpp | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/network/trans/WFPSampler/syslib/HelperFunctions_ClassifyData.cpp b/network/trans/WFPSampler/syslib/HelperFunctions_ClassifyData.cpp new file mode 100644 index 00000000..fa2d4103 --- /dev/null +++ b/network/trans/WFPSampler/syslib/HelperFunctions_ClassifyData.cpp @@ -0,0 +1,493 @@ +//////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2012 Microsoft Corporation. All Rights Reserved. +// +// Module Name: +// HelperFunctions_ClassifyData.cpp +// +// Abstract: +// This module contains kernel helper functions that assist with CLASSIFY_DATA. +// +// Naming Convention: +// +// <Module><Object><Action><Modifier> +// +// i.e. +// +// KrnlHlprClassifyDataCreateLocalCopy +// +// <Module> +// KrnlHlpr - Function is located in syslib\ and applies to kernel mode. +// <Object> +// ClassifyData - Function pertains to CLASSIFY_DATA objects. +// <Action> +// { +// Acquire - Function will take a reference on an object +// Create - Function allocates and fills memory. +// Destroy - Function cleans up and frees memory. +// Release - Function releases the reference on the object +// } +// <Modifer> +// LocalCopy - Function performs a deep copy of the parameters or takes references +// on complex structures. +// +// Private Functions: +// +// Public Functions: +// KrnlHlprAcquireDataCreateLocalCopy(), +// KrnlHlprClassifyDataCreateLocalCopy(), +// KrnlHlprClassifyDataDestroyLocalCopy(), +// KrnlHlprClassifyDataReleaseLocalCopy(), +// +// Author: +// Dusty Harper (DHarper) +// +// Revision History: +// +// [ Month ][Day] [Year] - [Revision]-[ Comments ] +// May 01, 2010 - 1.0 - Creation +// +//////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "HelperFunctions_Include.h" /// . +#include "HelperFunctions_ClassifyData.tmh" /// $(OBJ_PATH)\$(O)\ + +INT64 g_OutstandingNBLReferences = 0; + +/** + @kernel_helper_function="KrnlHlprClassifyDataReleaseLocalCopy" + + Purpose: Release reference on NBLs and cleanup a local copy of a CLASSIFY_DATA. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551159.aspx <br> + HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551208.aspx <br> +*/ +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +inline VOID KrnlHlprClassifyDataReleaseLocalCopy(_Inout_ CLASSIFY_DATA* pClassifyData) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> KrnlHlprClassifyDataReleaseLocalCopy()\n"); + +#endif /// DBG + + NT_ASSERT(pClassifyData); + + KrnlHlprFwpsClassifyOutDestroyLocalCopy((FWPS_CLASSIFY_OUT**)&(pClassifyData->pClassifyOut)); + + pClassifyData->flowContext = 0; + + KrnlHlprFwpsFilterDestroyLocalCopy((FWPS_FILTER**)&(pClassifyData->pFilter)); + +#if(NTDDI_VERSION >= NTDDI_WIN7) + + if(pClassifyData->classifyContextHandle) + FwpsReleaseClassifyHandle(pClassifyData->classifyContextHandle); + +#endif /// (NTDDI_VERSION >= NTDDI_WIN7) + + if(pClassifyData->pPacket) + { + if(pClassifyData->pClassifyValues) + { + if(pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V4 || + pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V4_DISCARD || + pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V6 || + pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V6_DISCARD) + KrnlHlprFwpsStreamCalloutIOPacketDestroyLocalCopy((FWPS_STREAM_CALLOUT_IO_PACKET**)&(pClassifyData->pPacket)); + else if(pClassifyData->chainedNBL) + { + BOOLEAN isDispatch = (KeGetCurrentIrql() == DISPATCH_LEVEL) ? TRUE : FALSE; + UINT32 numChainedNBLs = pClassifyData->numChainedNBLs; + + for(NET_BUFFER_LIST* pCurrentNBL = (NET_BUFFER_LIST*)pClassifyData->pPacket; + pCurrentNBL && + numChainedNBLs; + numChainedNBLs--) + { + NET_BUFFER_LIST* pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL); + + FwpsDereferenceNetBufferList(pCurrentNBL, + isDispatch); + + pCurrentNBL = pNextNBL; + +#if DBG + + InterlockedDecrement64((LONG64*)&(g_OutstandingNBLReferences)); + +#endif /// DBG + + } + } + else + { + BOOLEAN isDispatch = (KeGetCurrentIrql() == DISPATCH_LEVEL) ? TRUE : FALSE; + + FwpsDereferenceNetBufferList((NET_BUFFER_LIST*)pClassifyData->pPacket, + isDispatch); + +#if DBG + + InterlockedDecrement64((LONG64*)&(g_OutstandingNBLReferences)); + +#endif /// DBG + + } + } + + pClassifyData->pPacket = 0; + } + + KrnlHlprFwpsIncomingMetadataValuesDestroyLocalCopy((FWPS_INCOMING_METADATA_VALUES**)&(pClassifyData->pMetadataValues)); + + if(pClassifyData->pClassifyValues) + KrnlHlprFwpsIncomingValuesDestroyLocalCopy((FWPS_INCOMING_VALUES**)&(pClassifyData->pClassifyValues)); + + RtlZeroMemory(pClassifyData, + sizeof(CLASSIFY_DATA)); + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- KrnlHlprClassifyDataReleaseLocalCopy()\n"); + +#endif /// DBG + + return; +} + +/** + @kernel_helper_function="KrnlHlprClassifyDataDestroyLocalCopy" + + Purpose: Release reference on packet and cleanup and free a local copy of CLASSIFY_DATA. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: <br> +*/ +_At_(*ppClassifyData, _Pre_ _Notnull_) +_At_(*ppClassifyData, _Post_ _Null_ __drv_freesMem(Pool)) +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Success_(*ppClassifyData == 0) +inline VOID KrnlHlprClassifyDataDestroyLocalCopy(_Inout_ CLASSIFY_DATA** ppClassifyData) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> KrnlHlprClassifyDataDestroyLocalCopy()\n"); + +#endif /// DBG + + NT_ASSERT(ppClassifyData); + + if(*ppClassifyData) + { + KrnlHlprClassifyDataReleaseLocalCopy(*ppClassifyData); + + HLPR_DELETE(*ppClassifyData, + WFPSAMPLER_SYSLIB_TAG); + } + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- KrnlHlprClassifyDataDestroyLocalCopy()\n"); + +#endif /// DBG + + return; +} + +/** + @kernel_helper_function="KrnlHlprClassifyDataAcquireLocalCopy" + + Purpose: Ppopulate a CLASSIFY_DATA with a local copy of data obtained from a + callout's classification. This local copy requiires taking a reference + on pPacket. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF550085.aspx <br> + HTTP://MSDN.Microsoft.com/En-US/Library/Windows/Hardware/FF551206.aspx <br> +*/ +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Success_(return == STATUS_SUCCESS) +NTSTATUS KrnlHlprClassifyDataAcquireLocalCopy(_Inout_ CLASSIFY_DATA* pClassifyData, + _In_ const FWPS_INCOMING_VALUES* pClassifyValues, + _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, + _In_opt_ VOID* pPacket, + _In_opt_ const VOID* pClassifyContext, + _In_ const FWPS_FILTER* pFilter, + _In_ const UINT64 flowContext, + _In_ FWPS_CLASSIFY_OUT* pClassifyOut) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> KrnlHlprClassifyDataAcquireLocalCopy()\n"); + +#endif /// DBG + + NT_ASSERT(pClassifyData); + NT_ASSERT(pClassifyValues); + NT_ASSERT(pMetadata); + NT_ASSERT(pFilter); + NT_ASSERT(pClassifyOut); + + NTSTATUS status = STATUS_SUCCESS; + + pClassifyData->pClassifyValues = KrnlHlprFwpsIncomingValuesCreateLocalCopy(pClassifyValues); + HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyValues, + status); + + pClassifyData->pMetadataValues = KrnlHlprFwpsIncomingMetadataValuesCreateLocalCopy(pMetadata); + HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pMetadataValues, + status); + + if(pPacket) + { + if(pClassifyValues->layerId == FWPS_LAYER_STREAM_V4 || + pClassifyValues->layerId == FWPS_LAYER_STREAM_V4_DISCARD || + pClassifyValues->layerId == FWPS_LAYER_STREAM_V6 || + pClassifyValues->layerId == FWPS_LAYER_STREAM_V6_DISCARD) + { + pClassifyData->pPacket = KrnlHlprFwpsStreamCalloutIOPacketCreateLocalCopy((FWPS_STREAM_CALLOUT_IO_PACKET*)pPacket); + HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pPacket, + status); + } + +#if(NTDDI_VERSION >= NTDDI_WIN7) + + /// LayerData at the FWPM_LAYER_ALE_{BIND/CONNECT}_REDIRECT_V{4/6} is obtained via KrnlHlprRedirectDataCreate() + else if(pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 || + pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 || + pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V4 || + pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V6) + { + pClassifyData->pPacket = 0; + } + +#endif /// (NTDDI_VERSION >= NTDDI_WIN7) + + else + { + if(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket)) + { + pClassifyData->chainedNBL = TRUE; + pClassifyData->numChainedNBLs = 1; + } + + if(pClassifyData->chainedNBL && + ( + /// The IPPACKET and IPFORWARD Layers allow for Fragment Grouping if the option is enabled + pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 || + pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6 || + pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V4 || + pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V6 + +#if(NTDDI_VERSION >= NTDDI_WIN8) + + /// The NDIS layers allow for batched NBLs provided the callout was registered with FWP_CALLOUT_FLAG_ALLOW_L2_BATCH_CLASSIFY set + || + 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 + +#endif /// (NTDDI_VERSION >= NTDDI_WIN8) + + )) + { + for(NET_BUFFER_LIST* pCurrentNBL = (NET_BUFFER_LIST*)pPacket; + pCurrentNBL; + pClassifyData->numChainedNBLs++) + { + NET_BUFFER_LIST* pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL); + + FwpsReferenceNetBufferList(pCurrentNBL, + TRUE); + + pCurrentNBL = pNextNBL; + +#if DBG + + InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); + +#endif /// DBG + + } + + pClassifyData->pPacket = pPacket; + } + else + { + /// Otherwise we expect to receive a single NBL + NT_ASSERT(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket) == 0); + + FwpsReferenceNetBufferList((NET_BUFFER_LIST*)pPacket, + TRUE); + + pClassifyData->pPacket = pPacket; + +#if DBG + + InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); + +#endif /// DBG + + } + } + } + +#if(NTDDI_VERSION >= NTDDI_WIN7) + + if(pClassifyContext) + { + /// ClassifyHandle for these layers is obtained in REDIRECT_DATA + if(pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 && + pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 && + pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V4 && + pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V6) + { + status = FwpsAcquireClassifyHandle((VOID*)pClassifyContext, + 0, + &(pClassifyData->classifyContextHandle)); + HLPR_BAIL_ON_FAILURE(status); + } + } +#else + + UNREFERENCED_PARAMETER(pClassifyContext); + +#endif /// (NTDDI_VERSION >= NTDDI_WIN7) + + if(pFilter) + { + pClassifyData->pFilter = KrnlHlprFwpsFilterCreateLocalCopy(pFilter); + HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pFilter, + status); + } + + pClassifyData->flowContext = flowContext; + + if(pClassifyOut) + { + pClassifyData->pClassifyOut = KrnlHlprFwpsClassifyOutCreateLocalCopy(pClassifyOut); + HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyOut, + status); + } + + HLPR_BAIL_LABEL: + + if(status != STATUS_SUCCESS) + KrnlHlprClassifyDataReleaseLocalCopy(pClassifyData); + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " <--- KrnlHlprClassifyDataAcquireLocalCopy() [status: %#x]\n", + status); + +#endif /// DBG + + return status; +} + +/** + @kernel_helper_function="KrnlHlprClassifyDataCreateLocalCopy" + + Purpose: Allocate and populate a CLASSIFY_DATA with a local copy of data obtained from a + callout's classifyFn. This local copy requiires taking a reference on pPacket. <br> + <br> + Notes: <br> + <br> + MSDN_Ref: <br> +*/ +_At_(*ppClassifyData, _Pre_ _Null_) +_When_(return != STATUS_SUCCESS, _At_(*ppClassifyData, _Post_ _Null_)) +_When_(return == STATUS_SUCCESS, _At_(*ppClassifyData, _Post_ _Notnull_ __drv_allocatesMem(Pool))) +_IRQL_requires_min_(PASSIVE_LEVEL) +_IRQL_requires_max_(DISPATCH_LEVEL) +_IRQL_requires_same_ +_Check_return_ +_Success_(return == STATUS_SUCCESS) +NTSTATUS KrnlHlprClassifyDataCreateLocalCopy(_Outptr_ CLASSIFY_DATA** ppClassifyData, + _In_ const FWPS_INCOMING_VALUES* pClassifyValues, + _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, + _In_opt_ VOID* pPacket, + _In_opt_ const VOID* pClassifyContext, + _In_ const FWPS_FILTER* pFilter, + _In_ const UINT64 flowContext, + _In_ FWPS_CLASSIFY_OUT* pClassifyOut) +{ +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> KrnlHlprClassifyDataCreateLocalCopy()\n"); + +#endif /// DBG + + NT_ASSERT(ppClassifyData); + NT_ASSERT(pClassifyValues); + NT_ASSERT(pMetadata); + NT_ASSERT(pFilter); + NT_ASSERT(pClassifyOut); + + NTSTATUS status = STATUS_SUCCESS; + + HLPR_NEW(*ppClassifyData, + CLASSIFY_DATA, + WFPSAMPLER_SYSLIB_TAG); + HLPR_BAIL_ON_ALLOC_FAILURE(*ppClassifyData, + status); + + status = KrnlHlprClassifyDataAcquireLocalCopy(*ppClassifyData, + pClassifyValues, + pMetadata, + pPacket, + pClassifyContext, + pFilter, + flowContext, + pClassifyOut); + + HLPR_BAIL_LABEL: + +#pragma warning(push) +#pragma warning(disable: 6001) /// *ppClassifyData initialized with call to HLPR_NEW & KrnlHlprClassifyDataAcquireLocalCopy + + if(status != STATUS_SUCCESS && + *ppClassifyData) + KrnlHlprClassifyDataDestroyLocalCopy(ppClassifyData); + +#pragma warning(pop) + +#if DBG + + DbgPrintEx(DPFLTR_IHVNETWORK_ID, + DPFLTR_INFO_LEVEL, + " ---> KrnlHlprClassifyDataCreateLocalCopy() [status: %#x]\n", + status); + +#endif /// DBG + + return status; +} |
