Dear all,
first of all thanks for the valuable information provided by OSR Online and this forum threads.
I am a newbie in Windows driver development and I am trying to learn how to writer a NDIS 6.0 filter driver that drops those packets on the send-to-network path which match certain criterias.
I started using the NDIS filter driver sample project provided by VS2013. Next, I modified the functions FilterSendNetBufferLists(…) and FilterSendNetBufferListsComplete(…). I started with creating cloned NET_BUFFER_LISTs in FilterSendNetBufferLists() which are freed in FilterSendNetBufferListsComplete(). The cloned NET_BUFFER_LISTs are then sent. The driver currently does not drop any packet since in the first step I just wanted to create a clone of all NET_BUFFER_LISTs (NBL) and send these cloned NBLs in order to see if it works. Unfortunately, as soon as the driver is installed, the machine “looses” its IP address and acquires an IP address from 169.254.149.x. So I assume that the driver does not send any network packets to the network and thus, the machine has no connectivity…
The code of FilterSendNetBufferLists(…) is as follows:
Use_decl_annotations
VOID
FilterSendNetBufferLists(
NDIS_HANDLE FilterModuleContext,
PNET_BUFFER_LIST NetBufferLists,
NDIS_PORT_NUMBER PortNumber,
ULONG SendFlags
)
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
BOOLEAN DispatchLevel;
BOOLEAN bFalse = FALSE;
PNBL_QUEUE_HEADER NblSendQueue; // NBLs to passthrough to lower-level miniport
PNET_BUFFER_LIST pCurrentNetBufferList;
PNET_BUFFER_LIST pNextNetBufferList;
PNET_BUFFER_LIST CloneNbl;
DEBUGP(DL_TRACE, “===>SendNetBufferList: NBL = %p.\n”, NetBufferLists);
INIT_NBL_QUEUE_HEADER(&NblSendQueue);
do {
DispatchLevel = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags);
FILTER_ACQUIRE_LOCK(&pFilter->Lock, DispatchLevel);
pCurrentNetBufferList = NetBufferLists;
while (pCurrentNetBufferList) {
// Locate the Next NetBufferList
pNextNetBufferList = NET_BUFFER_LIST_NEXT_NBL(pCurrentNetBufferList);
// Unlink NBLs Following The Original NBL
NET_BUFFER_LIST_NEXT_NBL(pCurrentNetBufferList) = NULL;
CloneNbl = NdisAllocateCloneNetBufferList(pCurrentNetBufferList,
NULL,
NULL,
NDIS_CLONE_FLAGS_USE_ORIGINAL_MDLS);
if (!CloneNbl) {
DEBUGP(DL_TRACE, “\tCloning the NET_BUFFER_LIST %p failed.\n”, pCurrentNetBufferList);
INSERT_TAIL_NBL_QUEUE(&NblSendQueue, pCurrentNetBufferList);
} else {
DEBUGP(DL_TRACE, “\tSend cloned NET_BUFFER_LIST.\n”);
pCurrentNetBufferList->ChildRefCount++;
CloneNbl->ParentNetBufferList = pCurrentNetBufferList;
CloneNbl->SourceHandle = FilterModuleContext;
INSERT_TAIL_NBL_QUEUE(&NblSendQueue, CloneNbl);
}
}
// Move to the Next NetBufferList
pCurrentNetBufferList = pNextNetBufferList;
}
FILTER_RELEASE_LOCK(&pFilter->Lock, DispatchLevel);
// Send Passthrough NetBufferLists
if (!IS_NBL_QUEUE_EMPTY(&NblSendQueue)) {
NdisFSendNetBufferLists(pFilter->FilterHandle,
GET_NBL_QUEUE_HEAD(&NblSendQueue),
PortNumber,
SendFlags);
}
} while (bFalse);
DEBUGP(DL_TRACE, “<===SendNetBufferList. \n”);
}
And the function FilterSendNetBufferListsComplete(…) looks as follows:
Use_decl_annotations
VOID
FilterSendNetBufferListsComplete(
NDIS_HANDLE FilterModuleContext,
PNET_BUFFER_LIST NetBufferLists,
ULONG SendCompleteFlags
)
{
PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
ULONG NumOfSendCompletes = 0;
BOOLEAN DispatchLevel;
PNET_BUFFER_LIST CurrNbl;
PNET_BUFFER_LIST NblIter;
PNET_BUFFER_LIST PrevNbl;
PNET_BUFFER_LIST NextNbl;
PNET_BUFFER_LIST ParentNbl;
DEBUGP(DL_TRACE, “===>SendNBLComplete, NetBufferList: %p.\n”, NetBufferLists);
PrevNbl = NULL;
NblIter = NetBufferLists;
NextNbl = NULL;
while (NblIter) {
NextNbl = NET_BUFFER_LIST_NEXT_NBL(NblIter);
if (NblIter->SourceHandle == FilterModuleContext) {
ParentNbl = NblIter->ParentNetBufferList;
if (ParentNbl) {
NET_BUFFER_LIST_STATUS(ParentNbl) = NET_BUFFER_LIST_STATUS(NblIter);
ParentNbl->ChildRefCount–;
NET_BUFFER_LIST_NEXT_NBL(ParentNbl) = NET_BUFFER_LIST_NEXT_NBL(NblIter);
if (!PrevNbl) {
NetBufferLists = ParentNbl;
}
else {
NET_BUFFER_LIST_NEXT_NBL(PrevNbl) = ParentNbl;
}
PrevNbl = ParentNbl;
} else {
PrevNbl = NblIter;
}
NblIter->ParentNetBufferList = NULL;
NdisFreeCloneNetBufferList(NblIter, NDIS_CLONE_FLAGS_USE_ORIGINAL_MDLS);
} else {
PrevNbl = NblIter;
}
// Move to the next net buffer listPrevNbl = NblIter;
NblIter = NextNbl;
}
// Send complete the NBLs. If you removed any NBLs from the chain, make
// sure the chain isn’t empty (i.e., NetBufferLists!=NULL).
if (NetBufferLists) {
NdisFSendNetBufferListsComplete(pFilter->FilterHandle, NetBufferLists, SendCompleteFlags);
}
DEBUGP(DL_TRACE, “<===SendNBLComplete.\n”);
}
So, what`s wrong with my code? Any help, ideas and notes are welcome!
Thanks, sk