Hi,
We have a TDI filter driver that currently filters TDI_SEND_DATAGRAM requests, and modifies the target host/port to point to a usermode app running on the same machine. We also add a header to the datagram to mention the original target host/port - so that the usermode app can do the needful (encapsulation and relay).
We want to be able to do the reverse - when UDP datagrams are received by the user mode app, to be able to forward them to the TDI client they are actually meant for, spoofing the UDP source address so it appears as if they came from the original source host. The user mode app is some kind of proxy/relay that forwards UDP datagrams.
This is the architecture we came up with - would appreciate your thoughts on it, possible pitfalls, and whether this will work or not ![]()
-
Filter TDI_RECEIVE_DATAGRAM requests, and wait on a semaphore (per Handle semaphore). When the semaphore is signalled, retrieve a datagram (buffer) from an npaged lookaside list, and copy over to the buffer passed in the IRP. Modify the source address to point to the address stored along with the datageam in the npaged lookaside buffer. Free the npaged memory, complete the irp and return STATUS_SUCCESS.
-
Filter TDI_SET_EVENT_HANDLER requests, and check for ClientEventReceiveDatagram - if this event is being set, store the address of the Event Handler in a Per Handle context structure. Complete the IRP - dont pass it down, return STATUS_SUCCESS.
-
Ignore TDI_SET_EVENT_HANDLER for ClientEventChainedReceiveDatagramfor now (note below).
-
When the usermode app has a datagram to send to the TDI client, it sends an IOCTL to the filter driver. The IOCTL passes using buffered I/O the original source address of the datagram, and the datagram itself (payload).
-
The TDI filter driver checks if the TDI client is using TDI_RECEIVE_DATAGRAM - if so, it adds the datagram and source address to the npaged lookaside list, and signals the semaphore.
-
If the TDI client isn’t using TDI_RECEIVE_DATAGRAM, the filter driver checks for an event handler - if present, it just copies over the source address and passes the datagram buffer (the datagram as tsdu) and calls the event handler from the address stored in the per-handle context struct. When the event handler returns, the npaged buffer is cleaned up.
Notes/Questions -
-
Our assumption here is that for ClientEventReceiveDatagram, the tsdu passed is actually just a UDP datagram (no header / IP header). Is this right?
-
When dealing with ClientEventChainedReceiveDatagram, if the event handler returns STATUS_PENDING, then we can’t free the tsdu buffer, and the TDI client will eventually call TdiReturnChainedReceives, with a tsdu descriptor that can only be invalid / NULL (since it is passed by us, not an NDIS protocol driver). Any idea how we can handle this? One way is to pass a NULL tsdu descriptor and simply do a time-delayed free of the tsdu buffer. This does seem risky however.
Your feedback will be very welcome - this is a rather lengthy post to read, so thanks for just reading this far.
Nick