NDIS LWF - FilterRestart と FilterPause
-
20-12-2019 - |
質問
NDIS LWF ドライバーは初めてですが、Win7 上の WFP が私の要件を満たさないと判断し、NDIS LWF ドライバーに移行する必要がありました。したがって、これがあまりにも基本的な質問でないことを願っています。
私の要件は基本的に、マルチ NIC システム上の選択された NIC で無差別にリッスンできることを必要とします。LWF サンプルを変更してインターフェイスを無差別モードにしましたが、指定されたアダプターを設定する方法で行き詰まっています。LWF はすべてのアダプターの上に位置するため、単に NdisOpenAdapterEx を呼び出すことができるプロトコルとは異なりますが、特定のアダプターを無視するには何らかのフィルタリング メカニズムが必要であると考えられます。
対象となるインターフェイスの選択された MAC アドレスをドライバーに IOCTL できる必要があります。ドライバーをロードしてもフィルターを特定のインターフェイスでのみ実行することは可能ですか、それとも FilterReceiveNetBufferLists で気にしない他のインターフェイスからの呼び出しを無視する必要がありますか。特定のインターフェイスに対して何もしない場合は、FilterReceiveNetBufferLists コールバックを使用する必要がない方が効率的であるように思えます。
私をつまずかせているのは、FilterRestart が DriverEntry 中に (NdisFRegisterFilterDriver 経由で) 自動的に呼び出されることと、NdisFPauseFilter が存在しないように見えることです (ただし、NdisFRestartFilter は存在します)。理想的には、フィルタリングが開始される前に必要なパラメータを設定できるようにしたいと考えています。また、必要に応じて動的に再タスクを実行する機能が必要なため、DriverEntry 中にレジストリを使用しないようにしたいと考えています。
最後に、NDIS の内部構造をよりよく理解するために、フィルター モジュールが一時停止されるとスタック全体が一時停止されるのでしょうか、それとも NDIS は一時停止されたモジュールを迂回してルーティングするのでしょうか?
解決
これらは良い質問です。
ドライバーをロードしても、フィルターを特定のインターフェイスでのみ実行することは可能ですか?
はい。ここには 3 つのオプションがあります。
- ユーザーモードで静的にバインディングを無効にします。または
- 実行時にバインディングを拒否します。
- データパスを動的にバイパスして再度有効にする. 。(これについてはすでに MSDN で説明されているため、ここでは詳しく説明しません。)
バインディングを静的に無効にするには、次のようにします。 INetCfg API フィルタ ドライバと NIC の間のバインディングを見つけて、それを無効にします。これは次のようになります。
INetCfg::Initialize
myFilter = INetCfg::FindComponent
myFilter->QueryInterface(INetCfgComponentBindings)
for each binding in bindings
if binding is to undesirable NIC
INetCfgBindingPath::Enable(FALSE)
ドライバーがインストールされたら、いつでもこれを行うことができます。したがって、たとえば、ユーザーモード アプリは、GUI の実行中に特定の NIC へのバインドのみを有効にすることを決定する場合があります。
しかし、ユーザーモード コードを実行することが常に便利であるとは限りません。ドライバーにユーザーモードが存在しない場合、いくつかのバインドを無効にするためだけにユーザーモードを作成するのはおそらくやりすぎです。ここで 2 番目のテクニックが役に立ちます。ユーザーモードではバインディングを静的に有効にしたままにすることができますが、実行時にはバインドを拒否します。
実行時にバインドを拒否するにはどうすればよいですか?多くの場合、必要なのは、ユーザーから失敗ステータスを返すことだけです。 FilterAttach
ハンドラ。これは、フィルターが NIC に接続できない (または接続されない) ことを NDIS に認識させるのに十分です。ただし、フィルターが次のようにマークされている場合は、 必須 (つまり、INF の FilterRunType が 1)、失敗します。 FilterAttach
NIC が動作不能になります。(結局のところ、それは 要点全体 必須であること。フィルターが存在しない場合、データパス してはなりません ただし、とにかく NIC の実行を開始できるようにしたい場合は、 NDIS_FILTER_ATTACH_FLAGS_IGNORE_MANDATORY
あなたの中のフラグ NDIS_FILTER_ATTACH_PARAMETERS::Flags
フィルターがエラー コードを返す直前のフィールド FilterAttach
.
特定のインターフェイスに対して何もしない場合は、FilterReceiveNetBufferLists コールバックを使用する必要がない方が効率的であるように思えます。
あなたの直感は正しいです。データパスにフィルターを置くとオーバーヘッドが発生し、フィルターが何もしないと CPU サイクルが無駄になります。ただし、このオプションをまだ消去しないでください。場合によっては、このオプションのシンプルさが (比較的小さい) CPU コストを上回ります。つまり、ターゲット市場がすべての CPU サイクルをカウントしていない限り、この単純なオプションを使用するだけで十分である可能性があります。
必要に応じて動的に再タスクを実行する機能が引き続き必要になるため、DriverEntry 中にレジストリを使用しないようにしたいと考えています。
上で述べたように、あなたは できる ユーザーモードコードを使用して再タスクします。ユーザーモードが INetCfg::Apply を呼び出すたびに、NDIS は FilterAttach
または FilterDetach
適切な変化を起こすために必要です。
2 番目のテクニックを使用する場合、再タスクを実行することは実際には不可能です。特定の NIC を再タスクする必要がある場合は、1 番目または 3 番目の手法を使用する必要があります。
フィルター モジュールが一時停止されると、スタック全体が一時停止されますか、それとも NDIS は一時停止されたモジュールを迂回してルーティングしますか?
スタック全体が一時停止されます。NDIS はフィルターを「ルーティング」しません。(フィルターがオプションの場合、フィルターが実行されていないとき、トラフィックはフィルターをバイパスします。ただし、フィルターが NIC に接続されている限り、NBL と OID はフィルターを通過します。)