Looks like you are on the right track. But some detail (unknown to me) is
missing.
Below is a snippet of al old write handler for a NDIS 6 LWF. Could be a
little confusing to you because it can send packets either on the network
(down the stack) or to the local host (up the stack).
Some of the logic (W32N_OPEN_CONTEXT and friends) is just mapping the file
handle to the filter context. A user-mode file handle maps to a LWF filter
instance in some mysterious way. I won’t describe how that works. Use your
own scheme.
Perhaps this snippet can provide some help.
Good luck,
Thomas
NTSTATUS
FilterDeviceWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP pWriteIrp
)
{
PIO_STACK_LOCATION pIrpSp;
PMS_FILTER pFilter = NULL;
PW32N_OPEN_CONTEXT pW32NOpenContext = NULL;
ULONG DataLength;
PNET_BUFFER_LIST pNetBufferList;
PNET_BUFFER_LIST_CONTEXT Context;
PSEND_NETBUFLIST_RSVD pSendRsvd;
ULONG Flags = 0;
PMDL pWriteMdl = NULL;
Ndf_DbgPrint(DL_TRACE, DBG_WRITE, “==>FilterDeviceWrite\n”);
//
// Initialize Default Settings
//
pWriteIrp->IoStatus.Information = 0;
//
// Get a pointer to the current stack location in the pWriteIrp. This is
// where the function codes and parameters are located.
//
pIrpSp = IoGetCurrentIrpStackLocation(pWriteIrp);
//
// Find the Win32 Open Context
//
if( pIrpSp->FileObject && pIrpSp->FileObject->FsContext &&
pIrpSp->FileObject->FsContext2 )
{
pFilter = (PMS_FILTER )pIrpSp->FileObject->FsContext;
pW32NOpenContext = W32N_MapOpenRefnum(
pFilter,
(ULONG_PTR )pIrpSp->FileObject->FsContext2
);
}
//
// Sanity Check on Win32 Context
//
if( !pW32NOpenContext )
{
//
// Fail The IRP
//
pWriteIrp->IoStatus.Status = STATUS_INVALID_HANDLE;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_INVALID_HANDLE );
}
if( pW32NOpenContext->m_bIsClosing )
{
//
// Fail The IRP
//
pWriteIrp->IoStatus.Status = STATUS_CANCELLED;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_CANCELLED );
}
DataLength = pIrpSp->Parameters.Write.Length;
if (DataLength < ETHER_HDR_LEN)
{
Ndf_DbgPrint(DL_WARNING, DBG_WRITE, “FilterDeviceWrite: Too small to
be a valid packet (%d bytes)\n”, DataLength);
// Fail The IRP
pWriteIrp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_BUFFER_TOO_SMALL ); // Win32:
ERROR_INSUFFICIENT_BUFFER
}
NDF_ACQUIRE_SPIN_LOCK(&pFilter->Lock, FALSE);
//
// Sanity Check on Filter State
//
if (pFilter->State != FilterRunning)
{
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, FALSE);
Ndf_DbgPrint(DL_WARNING, DBG_WRITE, “FilterDeviceWrite: Filter Not
Running!!!\n”);
// Fail The IRP
pWriteIrp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_DEVICE_NOT_READY ); // Win32: ERROR_NOT_READY
}
ASSERT(pFilter->UserSendNetBufferListPool != NULL);
pWriteMdl = NdisAllocateMdl(
pFilter->FilterHandle,
pWriteIrp->AssociatedIrp.SystemBuffer,
DataLength
);
if( !pWriteMdl )
{
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, FALSE);
Ndf_DbgPrint(DL_WARNING, DBG_WRITE, “FilterDeviceWrite: Could Not
Allocate MDL!!!\n”);
// Fail The IRP
pWriteIrp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_INSUFFICIENT_RESOURCES ); // Win32:
ERROR_NOT_READY
}
pWriteMdl->Next = NULL; // No Chained MDLs Here!
pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
pFilter->UserSendNetBufferListPool,
sizeof(SEND_NETBUFLIST_RSVD), //Request control offset delta
0, // back fill size
pWriteMdl,
0, // Data offset
DataLength);
if (pNetBufferList == NULL)
{
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, FALSE);
Ndf_DbgPrint(DL_WARNING, DBG_WRITE, “FilterDeviceWrite: Binding %p:
Failed to alloc send net buffer list\n”,
pFilter);
NdisFreeMdl( pWriteMdl );
// Fail The IRP
pWriteIrp->IoStatus.Status = STATUS_NO_MEMORY;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_NO_MEMORY );
}
//
// Find and Initialize the Context Area in the NBL
//
Context = pNetBufferList->Context;
ASSERT( Context );
if( !Context )
{
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, FALSE);
NdisFreeMdl( pWriteMdl );
NdisFreeNetBufferList( pNetBufferList );
Ndf_DbgPrint(DL_WARNING, DBG_WRITE, “FilterDeviceWrite: Binding %p:
Context NULL\n”,
pFilter);
// Fail The IRP
pWriteIrp->IoStatus.Status = STATUS_NO_MEMORY;
pWriteIrp->IoStatus.Information = 0; // Nothing Returned
IoCompleteRequest( pWriteIrp, IO_NO_INCREMENT );
return( STATUS_NO_MEMORY );
}
pSendRsvd = (PSEND_NETBUFLIST_RSVD )&Context->ContextData[0];
pSendRsvd->pFilter = pFilter;
pSendRsvd->pW32NOpenContext = pW32NOpenContext;
pSendRsvd->OriginID = ORIGIN_USER_APPLICATION;
pSendRsvd->pIrp = pWriteIrp;
pSendRsvd->DataLength = DataLength;
//
// Add Reference Count to Binding
// ------------------------------
// This reference will be removed when the send completes.
//
filterAddReference( pFilter );
IoMarkIrpPending(pWriteIrp);
pNetBufferList->SourceHandle = pFilter->FilterHandle;
// Increment These Counts With Lock Held
if( pW32NOpenContext->m_bIsVirtualAdapter )
++pFilter->OutstandingRcvs;
else
++pFilter->OutstandingSends;
NDF_RELEASE_SPIN_LOCK(&pFilter->Lock, FALSE);
if( pW32NOpenContext->m_bIsVirtualAdapter )
{
// Write on Virtual Adapter Indicates a Receive to the Host
pSendRsvd->Internal.ReturnPacketHandler = UserIoReturnNetBufferList;
Flags = 0;
NdisFIndicateReceiveNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
1,
Flags // Receive Flags
);
}
else
{
// Write on Lower Adapter Sends a Packet on the Network
pSendRsvd->Internal.SendCompleteHandler = UserIoSendComplete;
Flags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK;
//
// Disable checksum offload on this packet
// ---------------------------------------
// From the DDK:
//
// “If the TCP/IP transport does not set either the IsIPv4 or IsIPv6
flag,
// the miniport driver should not perform checksum tasks on the
packet.”
//
NET_BUFFER_LIST_INFO( pNetBufferList, TcpIpChecksumNetBufferListInfo )
= 0;
NdisFSendNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
Flags // Send Flags
);
}
return STATUS_PENDING;
}
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Thursday, May 9, 2013 6:07 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NDIS filter driver sends packets unsucessfully (continued)
Here is what we were last time:
http://www.osronline.com/showThread.cfm?link=241177
In summary, I was writing a NDIS filter driver that originates TCP packets
(then I modified it to send ethernet packet as what the protocol driver
sample does). The problem is the packets I sent were not detected on
Wireshark.
Then Thomas told me the general processes for sending packets by filter
driver, and finally suggested me to look at the NDIS protocol driver sample.
Since last time, I read the the protocol driver sample, and modified my
filter driver, which now seems almost the same with the protocol driver. But
it turns out the protocol driver works well (I monitor the packets received
by another host on Wireshark), while I still cannot see the packets sent by
filter driver.
Here are what I did:
I made the user application, writing and cancel routine (which never been
called) exactly the same with protocol driver sample. For completion
routine, the only difference is I scans the NBLs and check whether each NBL
was originated by my filter driver. If it was, I free it as protocal driver
does. Otherwise, I link the NBL to a list, and complete the newly-generated
NBLs finally.
Is there any other routine I should pay attention to?
NTDEV is sponsored by OSR
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer