NTSTATUS KrnlHlprTransportHeaderGet()

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;
}