NDIS filter driver sends packets unsucessfully

I’m writing a NDIS filter driver that originates TCP packets. I was stuck at the problem that the packets I sent were not detected by Wireshark.

Currently I just send one packet that only contains ethernet header, IP header and TCP header. I’m pretty sure that I set all the fields of the headers in user application correctly. Then I call writefile to send the buffer to filter driver.

In the filter driver, I allocated one NBL for the packet and called NdisFSendNetBufferLists to send it. I also modified FilterSendNetBufferListsComplete so that it did not return my packet to overlaying driver and checked the status of NBL is NDIS_STATUS_SUCCESS.

I tried to send a packet from virtual machine to local host, and also from one host to another host. But both of them didn’t work. I have no idea how to identify the problem. Does anyone have such experience? Any suggestions?

You may be doing this already and just didn’t mention the steps.

You must allocate a MDL for the data passed to the driver from your
application:

pWriteMdl = NdisAllocateMdl(
pFilter->FilterHandle,
pWriteIrp->AssociatedIrp.SystemBuffer,
DataLength
);

pWriteMdl->Next = NULL; // No Chained MDLs Here!

Then you must allocate your NB and NBL:

pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
pFilter->UserSendNetBufferListPool,
sizeof(SEND_NETBUFLIST_RSVD), //Request control offset delta
0, // back fill size
pWriteMdl,
0, // Data offset
DataLength);

Here SEND_NETBUFLIST_RSVD is a context area containing whatever you want it
to contain…

You must mark the write IRP as pending and not complete it until the send
completes:

IoMarkIrpPending(pWriteIrp);

So, the write IRP is probably saved in SEND_NETBUFLIST_RSVD.

ATTENTION!!! YOU (that’s YOU) must study and understand how to handle IRPs
in your driver.

ATTENTION!!! YOU (that’s YOU) must study and learn about MDLs, etc. and
kernel memory management.

Then send the NBL:

NdisFSendNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
Flags // Send Flags
);

In your write handler return STATUS_PENDING because you won’t complete the
IRP until your send complete handler is called.

These are the basic steps. You must fill in the gaps.

Understand that Wireshark will NOT show your send packets if Wireshark is
running on the same host as your filter. Perhaps it would if you set
promiscuous mode… Better to run Wireshark on the receiving host. However,
if you have screwed-up the destination MAC address you might not see
anything on the receiving host. In addition, when looking at network traces
at this stage of development look for garbage packets; they’re probably
yours…

Good luck!

Thomas F. Divine
http://www.pcausa.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, April 3, 2013 10:45 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NDIS filter driver sends packets unsucessfully

I’m writing a NDIS filter driver that originates TCP packets. I was stuck at
the problem that the packets I sent were not detected by Wireshark.

Currently I just send one packet that only contains ethernet header, IP
header and TCP header. I’m pretty sure that I set all the fields of the
headers in user application correctly. Then I call writefile to send the
buffer to filter driver.

In the filter driver, I allocated one NBL for the packet and called
NdisFSendNetBufferLists to send it. I also modified
FilterSendNetBufferListsComplete so that it did not return my packet to
overlaying driver and checked the status of NBL is NDIS_STATUS_SUCCESS.

I tried to send a packet from virtual machine to local host, and also from
one host to another host. But both of them didn’t work. I have no idea how
to identify the problem. Does anyone have such experience? Any suggestions?


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

> Understand that Wireshark will NOT show your send packets if Wireshark is running on the same host as your filter.

That would make sense. But unfortunately, NDIS goes to great lengths to make loopback work, even on NDIS 6.x. Packets sent by a filter do get looped back to a promiscuous protocol.

Frankly, we go to *a lot* of trouble to make sure that NPT keeps working. (I probably spent 2 weeks on it this year alone.) I fantasize about the day that WinPCAP goes LWF.

In addition:

Don’t forget to free the MDL in your send completion routine.

There are alternate methods for handling MDLs from read/write routines.
Lookup the following topic on MSDN:

“Methods for Accessing Data Buffers”

Check how you set your device object Flags field in your DriverEntry
routine.

Thomas

-----Original Message-----
From:
Sent: None
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] NDIS filter driver sends packets unsucessfully

You may be doing this already and just didn’t mention the steps.

You must allocate a MDL for the data passed to the driver from your
application:

pWriteMdl = NdisAllocateMdl(
pFilter->FilterHandle,
pWriteIrp->AssociatedIrp.SystemBuffer,
DataLength
);

pWriteMdl->Next = NULL; // No Chained MDLs Here!

Then you must allocate your NB and NBL:

pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
pFilter->UserSendNetBufferListPool,
sizeof(SEND_NETBUFLIST_RSVD), //Request control offset delta
0, // back fill size
pWriteMdl,
0, // Data offset
DataLength);

Here SEND_NETBUFLIST_RSVD is a context area containing whatever you want it
to contain…

You must mark the write IRP as pending and not complete it until the send
completes:

IoMarkIrpPending(pWriteIrp);

So, the write IRP is probably saved in SEND_NETBUFLIST_RSVD.

ATTENTION!!! YOU (that’s YOU) must study and understand how to handle IRPs
in your driver.

ATTENTION!!! YOU (that’s YOU) must study and learn about MDLs, etc. and
kernel memory management.

Then send the NBL:

NdisFSendNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
Flags // Send Flags
);

In your write handler return STATUS_PENDING because you won’t complete the
IRP until your send complete handler is called.

These are the basic steps. You must fill in the gaps.

Understand that Wireshark will NOT show your send packets if Wireshark is
running on the same host as your filter. Perhaps it would if you set
promiscuous mode… Better to run Wireshark on the receiving host.
However, if you have screwed-up the destination MAC address you might not
see anything on the receiving host. In addition, when looking at network
traces at this stage of development look for garbage packets; they’re
probably yours…

Good luck!

Thomas F. Divine
http://www.pcausa.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, April 3, 2013 10:45 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NDIS filter driver sends packets unsucessfully

I’m writing a NDIS filter driver that originates TCP packets. I was stuck at
the problem that the packets I sent were not detected by Wireshark.

Currently I just send one packet that only contains ethernet header, IP
header and TCP header. I’m pretty sure that I set all the fields of the
headers in user application correctly. Then I call writefile to send the
buffer to filter driver.

In the filter driver, I allocated one NBL for the packet and called
NdisFSendNetBufferLists to send it. I also modified
FilterSendNetBufferListsComplete so that it did not return my packet to
overlaying driver and checked the status of NBL is NDIS_STATUS_SUCCESS.

I tried to send a packet from virtual machine to local host, and also from
one host to another host. But both of them didn’t work. I have no idea how
to identify the problem. Does anyone have such experience? Any suggestions?


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

Thanks for your detailed answer. I really appreciate it.
However, now I still cannot locate the problem.

According to your suggestion, I checked the flags field of device object. I use direct I/O for read/write:

DeviceObject->Flags |= DO_DIRECT_IO;

In the write routine, I get the MDL from Irp:

pMdl = pIrp->MdlAddress;

Then I allocate NBL and NB in the same way you said above, where SEND_NETBUFLIST_RSVD stores write Irp for completion later.

To handle the write Irp, I mark it as pending first.

IoMarkIrpPending(pIrp);

Then send the NBL.

In the completion routine, if the NBL is originated by my driver, then I complete the write Irp with the corresponding status.

CompletionStatus = NET_BUFFER_LIST_STATUS(NetBufferLists);
pIrp = ((PSEND_NETBUFLIST_RSVD)NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferLists))->pTrp;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
if (CompletionStatus == NDIS_STATUS_SUCCESS) {
pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
pIrp->IoStatus.Status = STATUS_SUCCESS;
}
else {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

And free the NBL and NBs.

// NET_BUFFER structures that are associated with the NET_BUFFER_LIST structure are not freed unless
// they were preallocated with the NET_BUFFER_LIST structure. Free such structures separately.

CurrNetBuffer = NET_BUFFER_NEXT_NB(NET_BUFFER_LIST_FIRST_NB(NetBufferLists));
while(CurrNetBuffer) {
PrevNetBuffer = CurrNetBuffer;
CurrNetBuffer = NET_BUFFER_NEXT_NB(CurrNetBuffer);
NdisFreeNetBuffer(PrevNetBuffer);
}
NdisFreeNetBufferList(NetBufferLists);

Since I should not call NdisFSendNetBufferListsComplete, I will always get STATUS_PENDING in write handler, right?

I run Wireshark on the receiving host, but didn’t see my packet. Is there anything else I missed?

-----Original Message-----
From:
Sent: None
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] NDIS filter driver sends packets unsucessfully

In addition:

Don’t forget to free the MDL in your send completion routine.

There are alternate methods for handling MDLs from read/write routines.
Lookup the following topic on MSDN:

“Methods for Accessing Data Buffers”

Check how you set your device object Flags field in your DriverEntry
routine.

Thomas

-----Original Message-----
From:
Sent: None
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] NDIS filter driver sends packets unsucessfully

You may be doing this already and just didn’t mention the steps.

You must allocate a MDL for the data passed to the driver from your
application:

pWriteMdl = NdisAllocateMdl(
pFilter->FilterHandle,
pWriteIrp->AssociatedIrp.SystemBuffer,
DataLength
);

pWriteMdl->Next = NULL; // No Chained MDLs Here!

Then you must allocate your NB and NBL:

pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
pFilter->UserSendNetBufferListPool,
sizeof(SEND_NETBUFLIST_RSVD), //Request control offset delta
0, // back fill size
pWriteMdl,
0, // Data offset
DataLength);

Here SEND_NETBUFLIST_RSVD is a context area containing whatever you want it
to contain…

You must mark the write IRP as pending and not complete it until the send
completes:

IoMarkIrpPending(pWriteIrp);

So, the write IRP is probably saved in SEND_NETBUFLIST_RSVD.

ATTENTION!!! YOU (that’s YOU) must study and understand how to handle IRPs
in your driver.

ATTENTION!!! YOU (that’s YOU) must study and learn about MDLs, etc. and
kernel memory management.

Then send the NBL:

NdisFSendNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
Flags // Send Flags
);

In your write handler return STATUS_PENDING because you won’t complete the
IRP until your send complete handler is called.

These are the basic steps. You must fill in the gaps.

Understand that Wireshark will NOT show your send packets if Wireshark is
running on the same host as your filter. Perhaps it would if you set
promiscuous mode… Better to run Wireshark on the receiving host.
However, if you have screwed-up the destination MAC address you might not
see anything on the receiving host. In addition, when looking at network
traces at this stage of development look for garbage packets; they’re
probably yours…

Good luck!

Thomas F. Divine
http://www.pcausa.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, April 3, 2013 10:45 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NDIS filter driver sends packets unsucessfully

I’m writing a NDIS filter driver that originates TCP packets. I was stuck at
the problem that the packets I sent were not detected by Wireshark.

Currently I just send one packet that only contains ethernet header, IP
header and TCP header. I’m pretty sure that I set all the fields of the
headers in user application correctly. Then I call writefile to send the
buffer to filter driver.

In the filter driver, I allocated one NBL for the packet and called
NdisFSendNetBufferLists to send it. I also modified
FilterSendNetBufferListsComplete so that it did not return my packet to
overlaying driver and checked the status of NBL is NDIS_STATUS_SUCCESS.

I tried to send a packet from virtual machine to local host, and also from
one host to another host. But both of them didn’t work. I have no idea how
to identify the problem. Does anyone have such experience? Any suggestions?

You have overlooked something. Don’t know what, however…

You could look at the WDK NDISPROT NDIS 6.0 sample. Although it is a NDIS
protocol driver - not a NDIS filter - there is a lot of common logic in the
send path.

Good luck!

Thomas F. Divine

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Thursday, April 4, 2013 6:10 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] NDIS filter driver sends packets unsucessfully

Thanks for your detailed answer. I really appreciate it.
However, now I still cannot locate the problem.

According to your suggestion, I checked the flags field of device object. I
use direct I/O for read/write:

DeviceObject->Flags |= DO_DIRECT_IO;

In the write routine, I get the MDL from Irp:

pMdl = pIrp->MdlAddress;

Then I allocate NBL and NB in the same way you said above, where
SEND_NETBUFLIST_RSVD stores write Irp for completion later.

To handle the write Irp, I mark it as pending first.

IoMarkIrpPending(pIrp);

Then send the NBL.

In the completion routine, if the NBL is originated by my driver, then I
complete the write Irp with the corresponding status.

CompletionStatus = NET_BUFFER_LIST_STATUS(NetBufferLists);
pIrp =
((PSEND_NETBUFLIST_RSVD)NET_BUFFER_LIST_CONTEXT_DATA_START(NetBufferLists))-

pTrp;
pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
if (CompletionStatus == NDIS_STATUS_SUCCESS) {
pIrp->IoStatus.Information =
pIrpSp->Parameters.Write.Length;
pIrp->IoStatus.Status = STATUS_SUCCESS;
}
else {
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
IoCompleteRequest(pIrp, IO_NO_INCREMENT);

And free the NBL and NBs.

// NET_BUFFER structures that are associated with the
NET_BUFFER_LIST structure are not freed unless
// they were preallocated with the NET_BUFFER_LIST structure. Free
such structures separately.

CurrNetBuffer =
NET_BUFFER_NEXT_NB(NET_BUFFER_LIST_FIRST_NB(NetBufferLists));
while(CurrNetBuffer) {
PrevNetBuffer = CurrNetBuffer;
CurrNetBuffer = NET_BUFFER_NEXT_NB(CurrNetBuffer);
NdisFreeNetBuffer(PrevNetBuffer);
}
NdisFreeNetBufferList(NetBufferLists);

Since I should not call NdisFSendNetBufferListsComplete, I will always get
STATUS_PENDING in write handler, right?

I run Wireshark on the receiving host, but didn’t see my packet. Is there
anything else I missed?

-----Original Message-----
From:
Sent: None
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] NDIS filter driver sends packets unsucessfully

In addition:

Don’t forget to free the MDL in your send completion routine.

There are alternate methods for handling MDLs from read/write routines.
Lookup the following topic on MSDN:

“Methods for Accessing Data Buffers”

Check how you set your device object Flags field in your DriverEntry
routine.

Thomas

-----Original Message-----
From:
Sent: None
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] NDIS filter driver sends packets unsucessfully

You may be doing this already and just didn’t mention the steps.

You must allocate a MDL for the data passed to the driver from your
application:

pWriteMdl = NdisAllocateMdl(
pFilter->FilterHandle,
pWriteIrp->AssociatedIrp.SystemBuffer,
DataLength
);

pWriteMdl->Next = NULL; // No Chained MDLs Here!

Then you must allocate your NB and NBL:

pNetBufferList = NdisAllocateNetBufferAndNetBufferList(
pFilter->UserSendNetBufferListPool,
sizeof(SEND_NETBUFLIST_RSVD), //Request control offset delta
0, // back fill size
pWriteMdl,
0, // Data offset
DataLength);

Here SEND_NETBUFLIST_RSVD is a context area containing whatever you want it
to contain…

You must mark the write IRP as pending and not complete it until the send
completes:

IoMarkIrpPending(pWriteIrp);

So, the write IRP is probably saved in SEND_NETBUFLIST_RSVD.

ATTENTION!!! YOU (that’s YOU) must study and understand how to handle IRPs
in your driver.

ATTENTION!!! YOU (that’s YOU) must study and learn about MDLs, etc. and
kernel memory management.

Then send the NBL:

NdisFSendNetBufferLists(
pFilter->FilterHandle,
pNetBufferList,
NDIS_DEFAULT_PORT_NUMBER,
Flags // Send Flags
);

In your write handler return STATUS_PENDING because you won’t complete the
IRP until your send complete handler is called.

These are the basic steps. You must fill in the gaps.

Understand that Wireshark will NOT show your send packets if Wireshark is
running on the same host as your filter. Perhaps it would if you set
promiscuous mode… Better to run Wireshark on the receiving host.
However, if you have screwed-up the destination MAC address you might not
see anything on the receiving host. In addition, when looking at network
traces at this stage of development look for garbage packets; they’re
probably yours…

Good luck!

Thomas F. Divine
http://www.pcausa.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Wednesday, April 3, 2013 10:45 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] NDIS filter driver sends packets unsucessfully

I’m writing a NDIS filter driver that originates TCP packets. I was stuck at
the problem that the packets I sent were not detected by Wireshark.

Currently I just send one packet that only contains ethernet header, IP
header and TCP header. I’m pretty sure that I set all the fields of the
headers in user application correctly. Then I call writefile to send the
buffer to filter driver.

In the filter driver, I allocated one NBL for the packet and called
NdisFSendNetBufferLists to send it. I also modified
FilterSendNetBufferListsComplete so that it did not return my packet to
overlaying driver and checked the status of NBL is NDIS_STATUS_SUCCESS.

I tried to send a packet from virtual machine to local host, and also from
one host to another host. But both of them didn’t work. I have no idea how
to identify the problem. Does anyone have such experience? Any suggestions?


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