Question

I'm new to NDIS LWF drivers but I had to move to them after determining that WFP on Win7 would not meet my requirements. So hopefully this isn't too basic of a question.

My requirements basically entail being able to promiscuously listen on a selected NIC on a multi-NIC system. I've modified the LWF sample to put the interfaces into promiscuous mode but I'm now stuck on how to set the specified adapter. I realize that LWF's sit on top of all adapters so it's not like a protocol where I could just call NdisOpenAdapterEx but I would assume there has to be some filtering mechanism to ignore certain adapters.

I need to be able to IOCTL to the driver the selected MAC address(es) of the interface I care about. Is it possible to load the driver but only have the filter running on specific interfaces or will I just have to just ignore calls coming from others that I don't care about in FilterReceiveNetBufferLists. It just seems like it would be more efficient to not have to have the FilterReceiveNetBufferLists callback if I won't do anything with it for a particular interface.

The things that are tripping me up are the fact that, FilterRestart is called automatically during DriverEntry (via NdisFRegisterFilterDriver) and that there doesn't seem to be NdisFPauseFilter (but there is a NdisFRestartFilter). Ideally, I'd like to be able to set the necessary params before any filtering begins and I'd like to stay away from using the registry during DriverEntry because I'll still need the ability to dynamically re-task as required.

And finally, just for a better understanding of NDIS internals, when a filter module is paused does the whole stack become paused or does NDIS route around the paused module?

Was it helpful?

Solution

These are good questions.

Is it possible to load the driver but only have the filter running on specific interfaces

Yes. You have three options here.

  1. Disable the binding statically in usermode; or
  2. Decline the binding at runtime.
  3. Dynamically bypass and re-enable the datapath. (This won't be detailed here, since it's already outlined on MSDN.)

To statically disable the binding, you'd use the INetCfg API to find the binding between your filter driver and the NIC, then disable it. This might look like:

INetCfg::Initialize
myFilter = INetCfg::FindComponent
myFilter->QueryInterface(INetCfgComponentBindings)
for each binding in bindings
    if binding is to undesirable NIC
        INetCfgBindingPath::Enable(FALSE)

You can do this at any time, once your driver is installed. So for example, your usermode app might decide to only enable bindings to certain NICs when its GUI is running.

But it's not always convenient to run usermode code, and if your driver doesn't already have a usermode presence, it's probably overkill to create one just to disable a few bindings. This is where the second technique comes in handy. You can leave the bindings statically enabled in usermode, but decline to bind at runtime.

How do you decline to bind at runtime? In many cases, all you have to do is return a failure status from your FilterAttach handler. That's enough to convince NDIS that your filter can not (or will not) attach to the NIC. But — if your filter is marked as Mandatory (i.e., the INF's FilterRunType is 1), then failing your FilterAttach will cause the NIC to become inoperable. (After all, that's the whole point of being mandatory. If your filter is not present, then the datapath must not run.) But if you want to allow the NIC to start running anyway, set the NDIS_FILTER_ATTACH_FLAGS_IGNORE_MANDATORY flag in your NDIS_FILTER_ATTACH_PARAMETERS::Flags field just before your filter returns a failure code from its FilterAttach.

It just seems like it would be more efficient to not have to have the FilterReceiveNetBufferLists callback if I won't do anything with it for a particular interface.

Your instincts are correct. There is overhead to having a filter in the datapath, and if the filter does nothing, than that's wasted CPU cycles. But don't write this option off just yet. In some cases, the simplicity of this option outweighs its (relatively small) CPU cost. That is, unless your target market is counting every CPU cycle, it might be good enough to just go with this simple option.

I'd like to stay away from using the registry during DriverEntry because I'll still need the ability to dynamically re-task as required.

As mentioned above, you can re-task with usermode code. Every time usermode calls INetCfg::Apply, NDIS will call any FilterAttach or FilterDetach needed to make the right changes happen.

It is not really possible to re-task when you use the second technique. If you do need to re-task a particular NIC, then you should either use the first or third technique.

when a filter module is paused does the whole stack become paused or does NDIS route around the paused module?

The whole stack is paused. NDIS doesn't "route around" filters. (If your filter is Optional, then traffic will bypass your filter when your filter isn't running. But as long as your filter is attached to the NIC, NBLs & OIDs will go through your filter.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top