📄 filter.c
字号:
// the ADAPT structure.
//
// Parameters
// pAdapt - pointer to ADAPT structure to be freed.
//
// Return Value
// Nothing.
//
// Remarks
// Called from protocol.c and miniport.c immediately after adapter is
// closed and just prior to freeing the ADAPT structure.
//
VOID
FltOnDeinitAdapter(
IN PADAPT pAdapt
)
{
PADAPT_FILTER_RSVD pFilterContext;
//
// Deinitialize FilterReserved Area In ADAPT Structure
//
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
if( pFilterContext->pIPv4BlockAddrArray )
{
NdisFreeMemory( pFilterContext->pIPv4BlockAddrArray, 0, 0);
}
pFilterContext->pIPv4BlockAddrArray = NULL;
}
////////////////////////////////////////////////////////////////////////////
// Send Packet Filter Functions //
////////////////////////////////////////////////////////////////////////////
int IPv4AddrCompare( const void *pKey, const void *pElement )
{
ULONG a1 = *(PULONG )pKey;
ULONG a2 = *(PULONG )pElement;
if( a1 == a2 )
{
return( 0 );
}
if( a1 < a2 )
{
return( -1 );
}
return( 1 );
}
/////////////////////////////////////////////////////////////////////////////
//// FltFilterSendPacket
//
// Purpose
// Called to filter each packet packet being sent.
//
// Parameters
// pAdapt - pointer to ADAPT structure that the send is on.
// pSendPacket - pointer to send packet to be filtered.
// DispatchLevel - TRUE if caller is running at IRQL DISPATCH_LEVEL.
// FALSE of caller is running at IRQL <= DISPATCH_LEVEL.
//
// Return Value
// A ULONG containing the send filter bitmap defined in filter.h
//
// Remarks
// Called from MPSendPackets for each individual packet in the send
// packet array and from MPSend.
//
// Runs at IRQL <= DISPATCH_LEVEL if called from MPSendPackets or
// at IRQL == DISPATCH_LEVEL if called from MPSend.
//
ULONG
FltFilterSendPacket(
IN PADAPT pAdapt,
IN PNDIS_PACKET pSendPacket,
IN BOOLEAN DispatchLevel // TRUE -> IRQL == DISPATCH_LEVEL
)
{
PADAPT_FILTER_RSVD pFilterContext;
ULONG SndFltAction = SND_FLT_SIMPLE_PASSTHRU;
USHORT EtherType;
ULONG NumberOfBytesRead;
struct ip IPHeader;
//
// Hold Adapter Spin Lock When Using Filter Data
// ---------------------------------------------
// See note at ADAPT_FILTER_RSVD structure declaration.
//
if( DispatchLevel )
NdisDprAcquireSpinLock(&pAdapt->Lock);
else
NdisAcquireSpinLock(&pAdapt->Lock);
//
// Find FilterReserved Area In ADAPT Structure
//
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
++pFilterContext->IPv4Stats.MPSendPktsCt; // SpinLock Already Held
//
// Pass All Packets If No Filter Is Set
//
if( !pFilterContext->pIPv4BlockAddrArray )
{
goto ExitTheFilter;
}
//
// Filter On EtherType
// -------------------
// We only filter IP at this point. The switch below is provided simply
// to illustrate how other EtherTypes could be identified and handled
// differently.
//
FltReadOnPacket(
pSendPacket,
&EtherType,
sizeof( EtherType ),
FIELD_OFFSET( struct ether_header, ether_type ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( EtherType ) )
{
goto ExitTheFilter;
}
switch( ntohs( EtherType ) )
{
// See ..\B2Winet/ethernet.h for ETHERTYPE Definitions
case ETHERTYPE_IP:
break;
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
case ETHERTYPE_NETBEUI:
default:
goto ExitTheFilter;
}
//
// Fetch The IP Header
// -------------------
// The logic of the send packet filter and the recceive packet filter
// is identical - except for whether the IP destination address of the
// IP source address should be checked.
//
// However. for illustrative purposes there is a difference in the
// filter implementation.
//
// The send packet filter uses FltReadOnPacket to fetch the entire
// IP header and then accesses information using fields in struct ip.
//
// The receive packet filter uses a different technique. It uses
// FltReadOnPacket to fetch only specific fields of interest.
//
FltReadOnPacket(
pSendPacket,
&IPHeader,
sizeof( IPHeader ),
sizeof( struct ether_header ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( IPHeader ) )
{
goto ExitTheFilter;
}
//
// Only Filter IPv4 For Now...
//
switch( IPHeader.ip_v )
{
case 4: // IPv4
break;
case 6: // IPv6
default:
goto ExitTheFilter;
}
//
// Do Binary Search On Sorted List Of IP Addresses To Block
//
if( bsearch(
&IPHeader.ip_dst.s_addr, // 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.MPSendPktsDropped; // SpinLock Already Held
SndFltAction = SND_FLT_BLOCK_PACKET;
}
ExitTheFilter:
//
// Release Adapter Spin Lock After Filtering
//
if( DispatchLevel )
NdisDprReleaseSpinLock(&pAdapt->Lock);
else
NdisReleaseSpinLock(&pAdapt->Lock);
return( SndFltAction );
}
////////////////////////////////////////////////////////////////////////////
// Receive Packet Filter Functions //
////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//// FltFilterReceivePacket
//
// Purpose
// Called to filter each received packet.
//
// Parameters
// pAdapt - pointer to ADAPT structure that the send is on.
// pReceivedPacket - pointer to receive packet to be filtered.
//
// Return Value
// A ULONG containing the receive filter action bitmap defined
// in filter.h
//
// Remarks
// Called from PtReceivePacket for each received packet.
//
// Runs at IRQL DISPATCH_LEVEL.
//
ULONG
FltFilterReceivePacket(
IN PADAPT pAdapt,
IN PNDIS_PACKET pReceivedPacket
)
{
PADAPT_FILTER_RSVD pFilterContext;
ULONG RcvFltAction = RCV_FLT_SIMPLE_PASSTHRU;
USHORT EtherType;
ULONG NumberOfBytesRead;
ULONG PktSrcAddr;
UCHAR IPVersion;
//
// Hold Adapter Spin Lock When Using Filter Data
// ---------------------------------------------
// See note at ADAPT_FILTER_RSVD structure declaration.
//
NdisDprAcquireSpinLock(&pAdapt->Lock);
//
// Find FilterReserved Area In ADAPT Structure
//
pFilterContext = (PADAPT_FILTER_RSVD )&pAdapt->FilterReserved;
++pFilterContext->IPv4Stats.PTRcvPktCt; // SpinLock Already Held
//
// Pass All Packets If No Filter Is Set
//
if( !pFilterContext->pIPv4BlockAddrArray )
{
goto ExitTheFilter;
}
//
// Filter On EtherType
// -------------------
// We only filter IP at this point. The switch below is provided simply
// to illustrate how other EtherTypes could be identified and handled
// differently.
//
FltReadOnPacket(
pReceivedPacket,
&EtherType,
sizeof( EtherType ),
FIELD_OFFSET( struct ether_header, ether_type ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( EtherType ) )
{
goto ExitTheFilter;
}
switch( ntohs( EtherType ) )
{
// See ..\B2Winet/ethernet.h for ETHERTYPE Definitions
case ETHERTYPE_IP:
break;
case ETHERTYPE_ARP:
case ETHERTYPE_REVARP:
case ETHERTYPE_NETBEUI:
default:
goto ExitTheFilter;
}
//
// The logic of the send packet filter and the recceive packet filter
// is identical - except for whether the IP destination address of the
// IP source address should be checked.
//
// However. for illustrative purposes there is a difference in the
// filter implementation.
//
// The receive packet filter uses FltReadOnPacket to fetch only specific
// fields of interest.
//
// The send packet filter uses FltReadOnPacket to fetch the entire
// IP header and then accesses information using fields in struct ip.
//
//
// Only Filter IPv4 For Now...
//
FltReadOnPacket(
pReceivedPacket,
&IPVersion,
sizeof( IPVersion ),
sizeof( struct ether_header ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( IPVersion ) )
{
goto ExitTheFilter;
}
if( NumberOfBytesRead != sizeof( IPVersion ) )
{
goto ExitTheFilter;
}
switch( IPVersion >> 4 )
{
case 4: // IPv4
break;
case 6: // IPv6
default:
goto ExitTheFilter;
}
//
// Fetch IPv4 Source Address
//
FltReadOnPacket(
pReceivedPacket,
&PktSrcAddr,
sizeof( PktSrcAddr ),
sizeof( struct ether_header ) + FIELD_OFFSET( struct ip, ip_src.s_addr ),
&NumberOfBytesRead
);
if( NumberOfBytesRead != sizeof( PktSrcAddr ) )
{
goto ExitTheFilter;
}
//
// 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.PTRcvPktDropped; // SpinLock Already Held
RcvFltAction = RCV_FLT_BLOCK_PACKET;
}
ExitTheFilter:
//
// Release Adapter Spin Lock After Filtering
//
NdisDprReleaseSpinLock(&pAdapt->Lock);
return( RcvFltAction );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -