in network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp [2050:2507]
NTSTATUS KrnlHlprTransportHeaderGet(_In_ NET_BUFFER_LIST* pNetBufferList,
_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
_Outptr_result_buffer_(*pTransportHeaderSize) VOID** ppTransportHeader,
_Inout_ BOOLEAN* pNeedToFreeMemory,
_Inout_opt_ IPPROTO* pProtocol, /* 0 */
_Inout_opt_ FWP_DIRECTION* pDirection, /* 0 */
_Inout_opt_ UINT32* pTransportHeaderSize) /* 0 */
{
NT_ASSERT(pNetBufferList);
NT_ASSERT(pClassifyValues);
NT_ASSERT(pMetadata);
NT_ASSERT(ppTransportHeader);
NT_ASSERT(pNeedToFreeMemory);
NTSTATUS status = STATUS_SUCCESS;
UINT32 bytesRetreated = 0;
UINT32 bytesAdvanced = 0;
UINT32 ipHeaderSize = 0;
UINT32 transportHeaderSize = 0;
FWP_DIRECTION direction = FWP_DIRECTION_MAX;
IPPROTO protocol = IPPROTO_MAX;
BOOLEAN transportHeaderAvailable = TRUE;
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_IP_HEADER_SIZE))
ipHeaderSize = pMetadata->ipHeaderSize;
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE))
transportHeaderSize = pMetadata->transportHeaderSize;
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_PACKET_DIRECTION))
direction = pMetadata->packetDirection;
switch(pClassifyValues->layerId)
{
case FWPS_LAYER_INBOUND_IPPACKET_V4:
case FWPS_LAYER_INBOUND_IPPACKET_V6:
{
/// At the Transport Header
break;
}
case FWPS_LAYER_INBOUND_IPPACKET_V4_DISCARD:
case FWPS_LAYER_INBOUND_IPPACKET_V6_DISCARD:
{
if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata,
FWPS_METADATA_FIELD_DISCARD_REASON))
{
if(pMetadata->discardMetadata.discardModule == FWPS_DISCARD_MODULE_GENERAL &&
pMetadata->discardMetadata.discardReason == FWPS_DISCARD_FIREWALL_POLICY)
{
/// At the Transport Header
}
}
break;
}
case FWPS_LAYER_OUTBOUND_IPPACKET_V4:
case FWPS_LAYER_OUTBOUND_IPPACKET_V4_DISCARD:
case FWPS_LAYER_OUTBOUND_IPPACKET_V6:
case FWPS_LAYER_OUTBOUND_IPPACKET_V6_DISCARD:
{
bytesAdvanced = ipHeaderSize;
break;
}
case FWPS_LAYER_IPFORWARD_V4:
case FWPS_LAYER_IPFORWARD_V4_DISCARD:
case FWPS_LAYER_IPFORWARD_V6:
case FWPS_LAYER_IPFORWARD_V6_DISCARD:
{
bytesAdvanced = ipHeaderSize;
break;
}
case FWPS_LAYER_INBOUND_TRANSPORT_V4:
case FWPS_LAYER_INBOUND_TRANSPORT_V4_DISCARD:
case FWPS_LAYER_INBOUND_TRANSPORT_V6:
case FWPS_LAYER_INBOUND_TRANSPORT_V6_DISCARD:
{
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_PROTOCOL].value.uint8);
if(protocol == IPPROTO_ICMP ||
protocol == IPPROTO_ICMPV6)
{
/// At the Transport Header
}
else
bytesRetreated = transportHeaderSize;
break;
}
case FWPS_LAYER_OUTBOUND_TRANSPORT_V4:
case FWPS_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD:
case FWPS_LAYER_OUTBOUND_TRANSPORT_V6:
case FWPS_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD:
{
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_OUTBOUND_TRANSPORT_V4_IP_PROTOCOL].value.uint8);
/// At the Transport Header
break;
}
case FWPS_LAYER_STREAM_V4:
case FWPS_LAYER_STREAM_V4_DISCARD:
case FWPS_LAYER_STREAM_V6:
case FWPS_LAYER_STREAM_V6_DISCARD:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_DATAGRAM_DATA_V4:
case FWPS_LAYER_DATAGRAM_DATA_V4_DISCARD:
case FWPS_LAYER_DATAGRAM_DATA_V6:
case FWPS_LAYER_DATAGRAM_DATA_V6_DISCARD:
{
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8);
direction = (FWP_DIRECTION)pClassifyValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint32;
if(direction == FWP_DIRECTION_OUTBOUND)
{
/// At the Transport Header
}
else
{
if(protocol == IPPROTO_ICMP ||
protocol == IPPROTO_ICMPV6)
{
/// At the Transport Header
}
else
bytesRetreated = transportHeaderSize;
}
break;
}
case FWPS_LAYER_INBOUND_ICMP_ERROR_V4:
case FWPS_LAYER_INBOUND_ICMP_ERROR_V4_DISCARD:
case FWPS_LAYER_INBOUND_ICMP_ERROR_V6:
case FWPS_LAYER_INBOUND_ICMP_ERROR_V6_DISCARD:
{
direction = FWP_DIRECTION_INBOUND;
bytesRetreated = transportHeaderSize;
break;
}
case FWPS_LAYER_OUTBOUND_ICMP_ERROR_V4:
case FWPS_LAYER_OUTBOUND_ICMP_ERROR_V4_DISCARD:
case FWPS_LAYER_OUTBOUND_ICMP_ERROR_V6:
case FWPS_LAYER_OUTBOUND_ICMP_ERROR_V6_DISCARD:
{
direction = FWP_DIRECTION_OUTBOUND;
/// At the Transport Header
break;
}
case FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4:
case FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4_DISCARD:
case FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6:
case FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6_DISCARD:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_AUTH_LISTEN_V4:
case FWPS_LAYER_ALE_AUTH_LISTEN_V4_DISCARD:
case FWPS_LAYER_ALE_AUTH_LISTEN_V6:
case FWPS_LAYER_ALE_AUTH_LISTEN_V6_DISCARD:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4:
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4_DISCARD:
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6:
case FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6_DISCARD:
{
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL].value.uint8);
if(direction == FWP_DIRECTION_OUTBOUND)
{
/// At the Transport Header
}
else
{
if(protocol == IPPROTO_ICMP ||
protocol == IPPROTO_ICMPV6)
{
/// At the Transport Header
}
else
bytesRetreated = transportHeaderSize;
}
break;
}
case FWPS_LAYER_ALE_AUTH_CONNECT_V4:
case FWPS_LAYER_ALE_AUTH_CONNECT_V4_DISCARD:
case FWPS_LAYER_ALE_AUTH_CONNECT_V6:
case FWPS_LAYER_ALE_AUTH_CONNECT_V6_DISCARD:
{
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint8);
if(protocol == IPPROTO_TCP)
transportHeaderAvailable = FALSE;
if(direction == FWP_DIRECTION_INBOUND)
{
/// At the Transport Header
}
else
{
/// At the Transport Header
}
break;
}
case FWPS_LAYER_ALE_FLOW_ESTABLISHED_V4:
case FWPS_LAYER_ALE_FLOW_ESTABLISHED_V4_DISCARD:
case FWPS_LAYER_ALE_FLOW_ESTABLISHED_V6:
case FWPS_LAYER_ALE_FLOW_ESTABLISHED_V6_DISCARD:
{
direction = (FWP_DIRECTION)pClassifyValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_DIRECTION].value.uint32;
protocol = (IPPROTO)(pClassifyValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8);
if(direction == FWP_DIRECTION_OUTBOUND)
{
/// At the Transport Header
}
else
{
if(protocol == IPPROTO_ICMP ||
protocol == IPPROTO_ICMPV6)
{
/// At the Transport Header
}
else
bytesRetreated = transportHeaderSize;
}
break;
}
#if(NTDDI_VERSION >= NTDDI_WIN7)
case FWPS_LAYER_NAME_RESOLUTION_CACHE_V4:
case FWPS_LAYER_NAME_RESOLUTION_CACHE_V6:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_RESOURCE_RELEASE_V4:
case FWPS_LAYER_ALE_RESOURCE_RELEASE_V6:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V4:
case FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V6:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_CONNECT_REDIRECT_V4:
case FWPS_LAYER_ALE_CONNECT_REDIRECT_V6:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_BIND_REDIRECT_V4:
case FWPS_LAYER_ALE_BIND_REDIRECT_V6:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_STREAM_PACKET_V4:
case FWPS_LAYER_STREAM_PACKET_V6:
{
direction = (FWP_DIRECTION)pClassifyValues->incomingValue[FWPS_FIELD_STREAM_PACKET_V4_DIRECTION].value.uint32;
protocol = IPPROTO_TCP;
if(direction == FWP_DIRECTION_OUTBOUND)
{
/// At the Transport Header
}
else
bytesRetreated = transportHeaderSize;
break;
}
#if(NTDDI_VERSION >= NTDDI_WIN8)
case FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET:
case FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET:
case FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE:
case FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE:
case FWPS_LAYER_INGRESS_VSWITCH_ETHERNET:
case FWPS_LAYER_EGRESS_VSWITCH_ETHERNET:
{
transportHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_INGRESS_VSWITCH_TRANSPORT_V4:
case FWPS_LAYER_INGRESS_VSWITCH_TRANSPORT_V6:
{
bytesAdvanced = ipHeaderSize;
break;
}
case FWPS_LAYER_EGRESS_VSWITCH_TRANSPORT_V4:
case FWPS_LAYER_EGRESS_VSWITCH_TRANSPORT_V6:
{
bytesAdvanced = ipHeaderSize;
break;
}
#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
#endif /// (NTDDI_VERSION >= NTDDI_WIN7)
}
if(transportHeaderAvailable)
{
BYTE* pBuffer = 0;
NET_BUFFER* pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufferList);
UINT32 bytesNeeded = transportHeaderSize ? transportHeaderSize : NET_BUFFER_DATA_LENGTH(pNetBuffer);
PVOID pContiguousData = 0;
#pragma warning(push)
#pragma warning(disable: 6014) /// pBuffer is expected to be cleaned up by caller using KrnlHlprTransportHeaderDestroy if *pNeedToFreeMemory is TRUE
HLPR_NEW_ARRAY(pBuffer,
BYTE,
bytesNeeded,
WFPSAMPLER_SYSLIB_TAG);
HLPR_BAIL_ON_ALLOC_FAILURE(pBuffer,
status);
#pragma warning(pop)
*pNeedToFreeMemory = TRUE;
if(bytesAdvanced)
NdisAdvanceNetBufferDataStart(pNetBuffer,
bytesAdvanced,
0,
0);
else if(bytesRetreated)
{
status = NdisRetreatNetBufferDataStart(pNetBuffer,
bytesRetreated,
0,
0);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! KrnlHlpTransportHeaderGet : NdisRetreatNetBufferDataStart() [status: %#x]\n",
status);
HLPR_BAIL;
}
}
pContiguousData = NdisGetDataBuffer(pNetBuffer,
bytesNeeded,
pBuffer,
1,
0);
/// Return to the original offset
if(bytesRetreated)
NdisAdvanceNetBufferDataStart(pNetBuffer,
bytesRetreated,
0,
0);
else if(bytesAdvanced)
{
status = NdisRetreatNetBufferDataStart(pNetBuffer,
bytesAdvanced,
0,
0);
if(status != STATUS_SUCCESS)
{
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! KrnlHlprTransportHeaderGet : NdisRetreatNetBufferDataStart() [status: %#x]\n",
status);
HLPR_BAIL;
}
}
if(!pContiguousData)
{
status = STATUS_UNSUCCESSFUL;
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! KrnlHlprTransportHeaderGet : NdisGetDataBuffer() [status: %#x]\n",
status);
HLPR_BAIL;
}
if(pBuffer != pContiguousData)
{
HLPR_DELETE_ARRAY(pBuffer,
WFPSAMPLER_SYSLIB_TAG);
*pNeedToFreeMemory = FALSE;
}
*ppTransportHeader = pContiguousData;
if(pProtocol)
*pProtocol = protocol;
if(pDirection)
*pDirection = direction;
if(pTransportHeaderSize)
*pTransportHeaderSize = transportHeaderSize;
HLPR_BAIL_LABEL:
if(status != STATUS_SUCCESS &&
*pNeedToFreeMemory &&
pBuffer)
{
KrnlHlprTransportHeaderDestroy((VOID**)&pBuffer);
*pNeedToFreeMemory = FALSE;
}
}
else
status = STATUS_NO_MATCH;
return status;
}