in network/trans/WFPSampler/syslib/HelperFunctions_Headers.cpp [593:1074]
NTSTATUS KrnlHlprIPHeaderGet(_In_ NET_BUFFER_LIST* pNetBufferList,
_In_ const FWPS_INCOMING_VALUES* pClassifyValues,
_In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata,
_Outptr_result_buffer_(*pIPHeaderSize) VOID** ppIPHeader,
_Inout_ BOOLEAN* pNeedToFreeMemory,
_Inout_opt_ FWP_DIRECTION* pDirection, /* 0 */
_Inout_opt_ UINT32* pIPHeaderSize) /* 0 */
{
NT_ASSERT(pNetBufferList);
NT_ASSERT(pClassifyValues);
NT_ASSERT(pMetadata);
NT_ASSERT(ppIPHeader);
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;
BOOLEAN ipHeaderAvailable = TRUE;
#if(NTDDI_VERSION >= NTDDI_WIN8)
UINT32 ethernetHeaderSize = 0;
if(FWPS_IS_L2_METADATA_FIELD_PRESENT(pMetadata,
FWPS_L2_METADATA_FIELD_ETHERNET_MAC_HEADER_SIZE))
ethernetHeaderSize = pMetadata->ethernetMacHeaderSize;
#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
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:
{
direction = FWP_DIRECTION_INBOUND;
bytesRetreated = ipHeaderSize;
break;
}
case FWPS_LAYER_INBOUND_IPPACKET_V4_DISCARD:
case FWPS_LAYER_INBOUND_IPPACKET_V6_DISCARD:
{
direction = FWP_DIRECTION_INBOUND;
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)
bytesRetreated = ipHeaderSize;
}
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:
{
direction = FWP_DIRECTION_OUTBOUND;
/// At the IP Header
break;
}
case FWPS_LAYER_IPFORWARD_V4:
case FWPS_LAYER_IPFORWARD_V4_DISCARD:
case FWPS_LAYER_IPFORWARD_V6:
case FWPS_LAYER_IPFORWARD_V6_DISCARD:
{
/// At the IP Header
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:
{
direction = FWP_DIRECTION_INBOUND;
if(pClassifyValues->incomingValue[FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMP ||
pClassifyValues->incomingValue[FWPS_FIELD_INBOUND_TRANSPORT_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMPV6)
bytesRetreated = ipHeaderSize;
else
bytesRetreated = ipHeaderSize + 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:
{
direction = FWP_DIRECTION_OUTBOUND;
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_STREAM_V4:
case FWPS_LAYER_STREAM_V4_DISCARD:
case FWPS_LAYER_STREAM_V6:
case FWPS_LAYER_STREAM_V6_DISCARD:
{
ipHeaderAvailable = 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:
{
direction = (FWP_DIRECTION)pClassifyValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint32;
if(direction == FWP_DIRECTION_OUTBOUND)
bytesRetreated = ipHeaderSize;
else
{
if(pClassifyValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMP ||
pClassifyValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMPV6)
bytesRetreated = ipHeaderSize;
else
bytesRetreated = ipHeaderSize + 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 = ipHeaderSize + 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;
bytesRetreated = ipHeaderSize;
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:
{
ipHeaderAvailable = 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:
{
ipHeaderAvailable = 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:
{
if(direction == FWP_DIRECTION_OUTBOUND)
{
ipHeaderAvailable = FALSE;
}
else
{
if(pClassifyValues->incomingValue[FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMP ||
pClassifyValues->incomingValue[FWPS_FIELD_ALE_AUTH_RECV_ACCEPT_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMPV6)
bytesRetreated = ipHeaderSize;
else
bytesRetreated = ipHeaderSize + 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:
{
if(pClassifyValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint8 == IPPROTO_TCP)
ipHeaderAvailable = FALSE;
else if(direction == FWP_DIRECTION_INBOUND)
ipHeaderAvailable = FALSE;
else
ipHeaderAvailable = FALSE;
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;
if(direction == FWP_DIRECTION_OUTBOUND)
bytesRetreated = ipHeaderSize;
else
{
if(pClassifyValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V4_IP_PROTOCOL].value.uint8 == IPPROTO_ICMP ||
pClassifyValues->incomingValue[FWPS_FIELD_ALE_FLOW_ESTABLISHED_V6_IP_PROTOCOL].value.uint8 == IPPROTO_ICMPV6)
bytesRetreated = ipHeaderSize;
else
bytesRetreated = ipHeaderSize + transportHeaderSize;
}
break;
}
#if(NTDDI_VERSION >= NTDDI_WIN7)
case FWPS_LAYER_NAME_RESOLUTION_CACHE_V4:
case FWPS_LAYER_NAME_RESOLUTION_CACHE_V6:
{
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_RESOURCE_RELEASE_V4:
case FWPS_LAYER_ALE_RESOURCE_RELEASE_V6:
{
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V4:
case FWPS_LAYER_ALE_ENDPOINT_CLOSURE_V6:
{
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_CONNECT_REDIRECT_V4:
case FWPS_LAYER_ALE_CONNECT_REDIRECT_V6:
{
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_ALE_BIND_REDIRECT_V4:
case FWPS_LAYER_ALE_BIND_REDIRECT_V6:
{
ipHeaderAvailable = 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;
if(direction == FWP_DIRECTION_OUTBOUND)
bytesRetreated = ipHeaderSize;
else
bytesRetreated = ipHeaderSize + transportHeaderSize;
break;
}
#if(NTDDI_VERSION >= NTDDI_WIN8)
case FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET:
{
UINT16 etherType = pClassifyValues->incomingValue[FWPS_FIELD_INBOUND_MAC_FRAME_ETHERNET_ETHER_TYPE].value.uint16;
if(etherType != 0x86DD &&
etherType != 0x0800)
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET:
{
UINT16 etherType = pClassifyValues->incomingValue[FWPS_FIELD_OUTBOUND_MAC_FRAME_ETHERNET_ETHER_TYPE].value.uint16;
if(etherType == 0x86DD ||
etherType == 0x0800)
bytesAdvanced = ethernetHeaderSize;
else
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE:
case FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE:
{
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_INGRESS_VSWITCH_ETHERNET:
{
UINT16 etherType = pClassifyValues->incomingValue[FWPS_FIELD_INGRESS_VSWITCH_ETHERNET_ETHER_TYPE].value.uint16;
if(etherType == 0x86DD ||
etherType == 0x0800)
bytesAdvanced = ethernetHeaderSize;
else
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_EGRESS_VSWITCH_ETHERNET:
{
UINT16 etherType = pClassifyValues->incomingValue[FWPS_FIELD_EGRESS_VSWITCH_ETHERNET_ETHER_TYPE].value.uint16;
if(etherType == 0x86DD ||
etherType == 0x0800)
bytesAdvanced = ethernetHeaderSize;
else
ipHeaderAvailable = FALSE;
break;
}
case FWPS_LAYER_INGRESS_VSWITCH_TRANSPORT_V4:
case FWPS_LAYER_INGRESS_VSWITCH_TRANSPORT_V6:
{
/// At the IP Header
break;
}
case FWPS_LAYER_EGRESS_VSWITCH_TRANSPORT_V4:
case FWPS_LAYER_EGRESS_VSWITCH_TRANSPORT_V6:
{
/// At the IP Header
break;
}
#endif /// (NTDDI_VERSION >= NTDDI_WIN8)
#endif /// (NTDDI_VERSION >= NTDDI_WIN7)
}
if(ipHeaderAvailable)
{
BYTE* pBuffer = 0;
NET_BUFFER* pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pNetBufferList);
UINT32 bytesNeeded = ipHeaderSize ? ipHeaderSize : 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 KrnlHlprIPHeaderDestroy 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,
" !!!! KrnlHlprIPHeaderGet : 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,
" !!!! KrnlHlprIPHeaderGet : NdisRetreatNetBufferDataStart() [status: %#x]\n",
status);
HLPR_BAIL;
}
}
if(!pContiguousData)
{
status = STATUS_UNSUCCESSFUL;
DbgPrintEx(DPFLTR_IHVNETWORK_ID,
DPFLTR_ERROR_LEVEL,
" !!!! KrnlHlprIPHeaderGet : NdisGetDataBuffer() [status: %#x]\n",
status);
HLPR_BAIL;
}
if(pBuffer != pContiguousData)
{
HLPR_DELETE_ARRAY(pBuffer,
WFPSAMPLER_SYSLIB_TAG);
*pNeedToFreeMemory = FALSE;
}
*ppIPHeader = pContiguousData;
if(pDirection)
*pDirection = direction;
if(pIPHeaderSize)
*pIPHeaderSize = ipHeaderSize;
HLPR_BAIL_LABEL:
if(status != STATUS_SUCCESS &&
*pNeedToFreeMemory &&
pBuffer)
{
KrnlHlprIPHeaderDestroy((VOID**)&pBuffer);
*pNeedToFreeMemory = FALSE;
}
}
else
status = STATUS_NO_MATCH;
return status;
}