📄 filter.c
字号:
/////////////////////////////////////////////////////////////////////////////
//// 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 + -