Transport Device Interface Frequently Asked Questions
In this section I will try to cover the most popular questions which appears in the mind of a newbie when he starts to deal with TDI. Take into account, that this is not a substition to PCAUSA FAQ, I just want to add the missing issues which are not covered by PCAUSA.
Q: What is TDI designed for?
A.: According to "Microsoft Windows Server 2003 TCP/IP Implementation Details" document, TDI has the following purpose:
[...] Microsoft developed the Transport Driver Interface (TDI) to provide greater flexibility and functionality than is provided by existing interfaces, such as NetBIOS and Windows Sockets. All Windows transport providers expose TDI. The TDI specification describes the set of primitive functions by which transport drivers and TDI clients communicate and the call mechanisms used for accessing them. Currently, TDI is kernel-mode only. [...]
Q.: Can I use TDI to filter network data? What methods can I use and what is the difference between them?
A.: Yes. One is able to filter the network data using legal filtering technique, i.e. IoAttachDriver and handling IRPs which comes to protocol providers, thus filter the network data. This is the suggested by Microsoft way of how to intercept packets. Unlike this way, there is another way - so called 'TDI hooking'. This method impies on hooking dispatch table of TDI provider and then dispatching the calls to originals handlers of IRP's.
Both methods has advantages and disadvantages. For example, to make legal TDI filter driver you will need to write more code: since you will need to keep tracks to original device objects of protocol drivers you filter. You also should forget about dynamical unloading with filter driver, because if your driver is not on the top of stack, it's unloading will cause BSOD. You cannot reoder dynamically the filters stack, so if one filter is unloaded, another filter will call it's dispatch handler when IRP will come. Calling to illegal address will cause blue screen for sure.
In case of TDI hook driver one is able to dynamically unload the driver, of course before unloadigng the dispatch pointers should be restored. But the problem is that accessing TDI dispatch table is illegal and dangerous - there is no syncronization mechanism and once you write into dispatch memory, the network event can occure, and ... for sure nothing good will happen.
Q.: Does TDI is supported on Vista?
A.: Yes. But it's depricated, and TDI will not be supported on next OS after Vista. A year ago I recieved a reply regarding this question from Mike Flasko, MSFT, WNDP team:
Properly written TDI Filter Drivers can still intercept TCP/IP traffic to/from WSK clients. But with considerable performance degradation. A properly written TDI filter driver is one that layers itself between TDI clients and TDI providers by using the IoAttachDeviceToDeviceStack or IoAttachDevice calls. An improper TDI filter driver is one that attempts to intercept TDI calls by hooking the dispatch table of the TDI provider.
However, illegal methods will be still working Vista. One is able to hook dispatch of TDI provider on Vista x32 and intercept network packets.
Q.: Does TDI support netbious names?
A.: No. The whole TDI is IP based.
Q.: How can one resolve a netbios name in TDI filter driver?
A.: Unfrotunatly, there is no legal way to accomplish this in kernel. I guess, directly talking with Netbios.sys would do the trick, but it's protocol is not documented, and is prone to changes. General recommendation is to use user mode helper application.
Q.: How can I obtain destination port and destination IP of connection in TDI filter driver?
A.: This data can be obtained from PIO_STACK_LOCATION->Parameters field in dispatch handler of filter driver. This field is a pointer to TDI_REQUEST_KERNEL_CONNECT structure which has RequestConnectionInformation->RemoteAddress field.
Q.: How can I obtain source port and source IP of connection in TDI filter driver?
A.: For this one needs to build an IRP with TDI_QUERY_INFORMATION query and TDI_QUERY_ADDRESS_INFO control code and send it to protocol driver. The reply will be in the view of TDI_ADDRESS_INFO structure.