⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filter.c

📁 James Antognini和Tom Divine提供的PASSTHRU的编成实例。
💻 C
📖 第 1 页 / 共 3 页
字号:

/////////////////////////////////////////////////////////////////////////////
//// FltFilterReceive
//
// Purpose
//   Called to filter each received packet indication.
//
// Parameters
//    pAdapt - pointer to ADAPT structure that the send is on.
//    Others - See DDK ProtocolReceive documentation.
//
// Return Value
//    A ULONG containing the receive filter action bitmap defined
//    in filter.h
//
// Remarks
//   Called from PtReceive for each received packet indication.
//
//   We are using the structures and other definitions adapted from
//   FreeBSD 5.0 for some of the Internet information. See the files
//   in ../B2Winet.
//
//   Runs at IRQL DISPATCH_LEVEL.
//

ULONG
FltFilterReceive(
   IN PADAPT         pAdapt,
   IN NDIS_HANDLE    MacReceiveContext,
   IN PVOID          HeaderBuffer,
   IN UINT           HeaderBufferSize,
   IN PVOID          LookAheadBuffer,
   IN UINT           LookAheadBufferSize,
   IN UINT           PacketSize
   )
{
   PADAPT_FILTER_RSVD   pFilterContext;
   ULONG                RcvFltAction = RCV_FLT_SIMPLE_PASSTHRU;
   struct ether_header  *pEthHdr;      // See ../B2Winet/ethernet.h
   struct ip            *pIPHeader;    // See ../B2Winet/ip.h
   ULONG                PktSrcAddr;

   //
   // Find FilterReserved Area In ADAPT Structure
   //
   pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;

   //
   // Hold Adapter Spin Lock When Using Filter Data
   // ---------------------------------------------
   // See note at ADAPT_FILTER_RSVD structure declaration.
   //
   NdisDprAcquireSpinLock(&pAdapt->Lock);

   //
   // Pass All Packets If No Filter Is Set
   //
   if( !pFilterContext->pIPv4BlockAddrArray )
   {
      goto ExitTheFilter;
   }

   ++pFilterContext->IPv4Stats.PTRcvCt;  // SpinLock Already Held

   //
   // Locate Ethernet Header
   //
   pEthHdr = (struct ether_header * )HeaderBuffer;

   //
   // Filter On EtherType
   //
   switch( ntohs( pEthHdr->ether_type ) )
   {
      // See ..\B2Winet/ethernet.h for ETHERTYPE Definitions
      case ETHERTYPE_IP:
         break;

      case ETHERTYPE_ARP:
      case ETHERTYPE_REVARP:
      case ETHERTYPE_NETBEUI:
      default:
         goto ExitTheFilter;
   }

   //
   // Locate IP Header
   //
   pIPHeader = (struct ip * )LookAheadBuffer;

   //
   // Only Filter IPv4 For Now...
   //
   switch( pIPHeader->ip_v )
   {
      case 4:        // IPv4
         break;

      case 6:        // IPv6
      default:
         goto ExitTheFilter;
   }

   PktSrcAddr = pIPHeader->ip_src.s_addr;

   //
   // Do Binary Search On Sorted List Of IP Addresses To Block
   //
   if( bsearch(
         &PktSrcAddr,                                          // Key To Search For
         (pFilterContext->pIPv4BlockAddrArray)->IPAddrArray,     // Array Base
         (pFilterContext->pIPv4BlockAddrArray)->NumberElements,  // Number Of Elements In Array
         sizeof( ULONG ),                                      // Bytes Per Element
         IPv4AddrCompare                                      // Comparison Function
         )
      )
   {
      //
      // Reject Packets That Have Matching IP Source Address
      //
      ++pFilterContext->IPv4Stats.PTRcvDropped; // SpinLock Already Held
      RcvFltAction = RCV_FLT_BLOCK_PACKET;
   }

ExitTheFilter:
   //
   // Release Adapter Spin Lock After Filtering
   //
   NdisDprReleaseSpinLock(&pAdapt->Lock);

   return( RcvFltAction );
}

////////////////////////////////////////////////////////////////////////////
//                            Utility Functions                           //
////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
//// FltReadOnPacket
//
// Purpose
// Logical read on the packet data in a NDIS_PACKET.
//
// Parameters
//
// Return Value
//
// Remarks
// The purpose of this function is to provide a convienient mechanism to
// read packet data from an NDIS_PACKET that may have multiple chained
// NDIS_BUFFERs.
//

VOID
FltReadOnPacket(
   IN PNDIS_PACKET Packet,
   IN PVOID lpBufferIn,
   IN ULONG nNumberOfBytesToRead,
   IN ULONG nOffset,                // Byte Offset, Starting With MAC Header
   OUT PULONG lpNumberOfBytesRead
   )
{
   PNDIS_BUFFER    CurrentBuffer;
   UINT            nBufferCount, TotalPacketLength;
   PUCHAR          VirtualAddress = NULL;
   PUCHAR          lpBuffer = (PUCHAR )lpBufferIn;
   UINT            CurrentLength, CurrentOffset;
   UINT            AmountToMove;

   //
   // Sanity Check
   //
   if( !Packet || !lpBuffer || !lpNumberOfBytesRead )
   {
      if( lpNumberOfBytesRead )
      {
         *lpNumberOfBytesRead = 0;
      }
      return;
   }

   *lpNumberOfBytesRead = 0;
   if (!nNumberOfBytesToRead)
      return;

   //
   // Query Packet
   //
   NdisQueryPacket(
      (PNDIS_PACKET )Packet,
      (PUINT )NULL,           // Physical Buffer Count
      (PUINT )&nBufferCount,  // Buffer Count
      &CurrentBuffer,         // First Buffer
      &TotalPacketLength      // TotalPacketLength
      );

   //
   // Query The First Buffer
   //
#if (defined(NDIS50) || defined(NDIS51))
   NdisQueryBufferSafe(
      CurrentBuffer,
      &VirtualAddress,
      &CurrentLength,
      NormalPagePriority
      );
#else
   NdisQueryBuffer(
      CurrentBuffer,
      &VirtualAddress,
      &CurrentLength
      );
#endif

   //
   // Handle Possible Low-Resource Failure Of NdisQueryBufferSafe
   //
   if( !VirtualAddress )
   {
      return;
   }

   __try
   {
      CurrentOffset = 0;

      while( nOffset || nNumberOfBytesToRead )
      {
         while( !CurrentLength )
         {
            NdisGetNextBuffer(
               CurrentBuffer,
               &CurrentBuffer
               );

            // If we've reached the end of the packet.  We return with what
            // we've done so far (which must be shorter than requested).
            if (!CurrentBuffer)
               __leave; // Leave __try and eventually return...

#if (defined(NDIS50) || defined(NDIS51))
            NdisQueryBufferSafe(
               CurrentBuffer,
               &VirtualAddress,
               &CurrentLength,
               NormalPagePriority
               );
#else
            NdisQueryBuffer(
               CurrentBuffer,
               &VirtualAddress,
               &CurrentLength
               );
#endif

            //
            // Handle Possible Low-Resource Failure Of NdisQueryBufferSafe
            //
            if( !VirtualAddress )
            {
               __leave; // Leave __try and eventually return...
            }

            CurrentOffset = 0;
         }

         if( nOffset )
         {
            // Compute how much data to move from this fragment
            if( CurrentLength > nOffset )
               CurrentOffset = nOffset;
            else
               CurrentOffset = CurrentLength;

            nOffset -= CurrentOffset;
            CurrentLength -= CurrentOffset;
         }

         if( nOffset )
         {
            CurrentLength = 0;
            continue;
         }

         if( !CurrentLength )
         {
            continue;
         }

         // Compute how much data to move from this fragment
         if (CurrentLength > nNumberOfBytesToRead)
            AmountToMove = nNumberOfBytesToRead;
         else
            AmountToMove = CurrentLength;

         // Copy the data.
         NdisMoveMemory(
            lpBuffer,
            &VirtualAddress[ CurrentOffset ],
            AmountToMove
            );

         // Update destination pointer
         lpBuffer += AmountToMove;

         // Update counters
         *lpNumberOfBytesRead +=AmountToMove;
         nNumberOfBytesToRead -=AmountToMove;
         CurrentLength = 0;
      }
   }
   __finally
   {
      //
      // lpNumberOfBytesRead may be less then specified if exception
      // occured...
      //
   }
}

/////////////////////////////////////////////////////////////////////////////
//// bsearch
//
// Purpose
// Does a binary search of a sorted array for a key.
//
// Parameters
//  pSearchKey       - key to search for
//  pArrayBase       - base of sorted array to search
//  nNumElements     - number of elements in array
//  nBytesPerElement - number of bytes per element
//  int (*compare)()   - pointer to function that compares two array
//          elements, returning neg when #1 < #2, pos when #1 > #2, and
//          0 when they are equal. Function is passed pointers to two
//          array elements.
//
// Return Value
//  if key is found:
//          returns pointer to occurrence of key in array
//  if key is not found:
//          returns NULL
//
// Remarks
//

PVOID bsearch(
   const PVOID pSearchKey,
   const PVOID pArrayBase,
   ULONG nNumElements,
   ULONG nBytesPerElement,
   BSEARCH_CMP_FCN compare
   )
{
   char *lo = (char *)pArrayBase;
   char *hi = (char *)pArrayBase + (nNumElements - 1) * nBytesPerElement;
   char *mid;
   unsigned int half;
   int result;

   while( lo <= hi )
   {
      if( half = nNumElements / 2 )
      {
         mid = lo + (nNumElements & 1 ? half : (half - 1)) * nBytesPerElement;
         if (!(result = (*compare)(pSearchKey,mid)))
         {
            return(mid);
         }
         else if (result < 0)
         {
            hi = mid - nBytesPerElement;
            nNumElements = nNumElements & 1 ? half : half-1;
         }
         else
         {
            lo = mid + nBytesPerElement;
            nNumElements = half;
         }
      }
      else if (nNumElements)
      {
         return((*compare)(pSearchKey,lo) ? NULL : lo);
      }
      else
      {
         break;
      }
   }

   return(NULL);
}

////////////////////////////////////////////////////////////////////////////
//                              Debug Functions                           //
////////////////////////////////////////////////////////////////////////////

#if DBG

#endif // DBG


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -