Calling GetBestRoute2 (Netioapi.h) from an NDIS filter driver

Hi,

I’m calling GetBestRoute2 inside an NDIS filter driver, in order to obtain the best route towards a remote computer.
The call returns STATUS_INVALID_ADDRESS_COMPONENT (0xC0000207).
I’m calling it inside the FilterRestart callback.
The call has this shape:

    SOCKADDR_INET DestinationAddress = { 0 };
    DestinationAddress.si_family = AF_INET;
    DestinationAddress.Ipv4.sin_addr.S_un.S_addr = 0x0166a8c0UL // 192.168.102.1
    MIB_IPFORWARD_ROW2 BestRoute = { 0 };
    SOCKADDR_INET BestSourceAddress = { 0 };
    NTSTATUS Status = GetBestRoute2(NULL, InterfaceIndex, NULL, &DestinationAddress, 0, &BestRoute, &BestSourceAddress);

InterfaceIndex is taken from the value received in FilterAttach (AttachParameters->BaseMiniportIfIndex) and I’ve confirmed through the debugger that it’s correct.
The interface has a fixed unicast address in the same network: 192.168.102.11.
I’ve tested (in the same machine) with the user mode equivalent (GetBestRoute2, same call layout and same parameters) and it works (it returns 0, although BestRoute.NextHop contains {AF_UNSPEC, 0.0.0.0:2}, which is strange; I expected NextHop = {AF_INET, 192.168.102.1:0}).

The question is: am I doing something wrong, as to explain the STATUS_INVALID_ADDRESS_COMPONENT I get in the driver?

Thank you very much.
Best regards.

I don’t know enough about GetBestRoute2 to tell you where that error comes from. But I would advise caution about making an upcall from an NDIS driver into the IP stack. If you do it from within FilterAttach, you do run a risk of deadlock: the implementation of any TCPIP api might block on an NDIS binding completing. Or, maybe more likely, TCPIP apis might fail because they can’t send OIDs while the bindings are being rewired.

If you need to make an upcall from an NDIS driver, I suggest doing it from a dedicated workitem/thread, without holding a lock that ties you to NDIS state.

It’s strange that the same call works in usermode. The network stack shares most of its implementation between modes, here, so there’s not really much opportunity for the kernel to be more picky than usermode.