お久しぶりです。さなえすです。
今日は前回 8 月の投稿でお約束した、ネットワークのバインド (Bind) について書こうと思います。
● バインド (Bind) とは?
英語の “bind” のそもそもの意味は、バラバラになっているものを紐などを使って「束ねる」ことを指しますが、ネットワークにおけるバインドの概念も同じことです。システム上には、ネットワークモジュールが複数存在していて、かつ、異なるレイヤーに位置していることは前回お話しました。バインドという動作は、それらのバラバラになっているモジュールを束ねて、どのようなネットワークパスを構成するかという結びつきを表します。通常、ネットワークドライバーは、インストールされただけでは動作せず、バインドされた時点で動作開始とみなしますし、その分、上下のドライバーに依存して動作しています。また、NDIS 6 以降からは新たなステータス管理の仕組みがサポートされ、動的なバインドも行われるようになりました。このため、適切な実装をしていないドライバーは、バインドができずに動作しないばかりか、BugCheck という最悪のシナリオさえ引き起こしてしまうこともあり得ます。このようなわけで、バインドはネットワーク ドライバーの特徴の 1 つでもあるとともに、動作上重要な役割を担っています。
まず手始めに、ネットワークのプロパティのダイアログボックスをご紹介します。Windows Internals 5th Edition でもネットワークのバインドの説明で、バインドの確認や、バインド順を変更するための方法として紹介されていました。ドライバー開発者以外の方であれば、こちらのインターフェースのほうが、“ネットワークのバインド“ として馴染みがあるかもしれません。
1.[ネットワーク接続]を開く
コントロール パネル
> ネットワークとインターネット
> ネットワークと共有センター
> アダプターの設定変更
2.エクスプローラーのメニューの [詳細設定(N)] から [詳細設定(S)...] を選択
(エクスプローラーのメニューが表示されていない場合は、’Alt’ キーを押下して表示させてください)
この方法では、ローカルエリア接続に紐づいているバインド情報の一部を確認することができます。
さらに、プロトコルを選択して、右の矢印を押下すると、バインドの順番を変更することも可能となっています。
3. 1.の手順後、任意の [ローカルエリア接続] を右クリックして、プロパティを表示
上記 2. と一部重複しますが、ローカル エリア接続に紐づいているネットワークコンポーネントの情報は、このようにプロパティからも確認できます。下の例は、「Local Area Connection 2」を右クリックしてプロパティを表示したところです。バインド順までは特定できませんが、上記 2. の UI で見た時よりも、ネットワーク接続の構成には、より多くのモジュールが関わっていることが確認できるかと思います。
● バインドの制御について ~ はじめに ~
ここからは、WDK の観点で、バインド順を決定する要素や、バインドを制御するためのインターフェースについてお話しするつもりです。ここで皆さまの期待が膨らんでしまう前に予めお話ししておきたいのですが、時々、『バインド時に、特定のドライバーを、構成されるネットワークパスの最下層 (NIC寄りの) レイヤーに指定し、且つ、それを常に保証したい』といったようなお問い合わせを頂くことがあります。背景としては、例えば、ドライバー同士の競合が起こったり、それによってアプリケーションとドライバーで通信できなくなってしまったりする恐れがあるため、新しく追加される可能性のある他のドライバーのバインド順をも制御したいという理由があったりします。
先に結論を言いますと、このような未知のドライバーのインストールシナリオまでも念頭に入れた場合、特定のドライバーのバインド順を常に保証する方法はありません。
ただ、既存のバインド情報を変更する方法であれば、既にご紹介したネットワークのプロパティからの変更をはじめ、INetCfg インターフェース群を使って制御することが可能です。つまり、変更が加わったことを検知して、元の状態に近いものに戻すことはできるということです。さらに INetCfg インターフェース群は、ネットワークのプロパティからの変更方法よりももっと細かな制御が可能となります。(ちなみにネットワークのプロパティも内部では INetCfg インターフェースを使用しています。)
中には、それでもあきらめられず「でも、INF ファイルを使えば、インストールのタイミングのバインドを制御できるはず。レジストリを書き換える方法で何とかなるのでは?」とお考えの方もいらっしゃるかもしれません。これについては、まず、レジストリの書き換えは正しい方法ではないので行わないでください。そして、確かに、以下でも紹介する INF ファイルでのインターフェースの指定などによって挙動が変わりますので、結果として問題が回避できる場合もあるかもしれません。ただし、やはりこれも本質的ではありません。INF ファイルでのインターフェースの指定は、あくまでもドライバーを適切なレイヤーにインストールして動作させるための設定であって、バインド順を自由に制御するための方法ではないからです。むしろ、デバイスやドライバーの仕様によって決まってきてしまうものなので、変更できない場合のほうが多いかと思います。
というわけで、この後、INF ファイルでのインターフェースの話や、おいおい INetCfg インターフェースなども紹介していこうかと思っていますが、この先読み進めても、特定のドライバーのバインド順を常に保証する方法は出てきませんので、どうぞご了承くださいませ。
● バインドの制御について ~ INF ファイル ~
さて、先にも少し触れましたが、ネットワークドライバーのバインド順を決める要素として、INF ファイルで指定するインターフェースがあります。ネットワーク ドライバーの INF ファイルでは、通常の INF ファイルの役割に加えて、ネットワークドライバー特有のインターフェースがあり、どのレイヤーでどのようにバインドされるかを記述します。INF ファイルで指定できるのはあくまでもインターフェースに対しての設定であって、個別のコンポーネントに対しての制御ではない、という点にご注意ください。先ほど「INF ファイルでのインターフェースの指定は、あくまでもドライバーを適切なレイヤーにインストールして動作させるための設定であって、バインド順を自由に制御するための方法ではない」と言ったのは、このような理由からです。
バインドに関連するインターフェースとしては、基本的には、Add Registry のセクションで、Ndi キーを使用して指定する、上位のインターフェース (UpperRange) と下位のインターフェース(LowerRange) と、下位のハードウェアメディアを指定するインターフェースなどがあります。ネットワーク ドライバーの種類によっては、指定できるインターフェースや、逆に指定してはいけないインターフェースがありますので、詳細は下記の Reference を参考にドキュメントで確認するようにしてください。
(1)ミニポート ドライバーの場合
WDK の Netvmini サンプルの INF ファイルの例です。
; Microsoft Virtual Miniport Common
;
[NetVMini.Reg]
HKR, , BusNumber, 0, "0"
HKR, Ndi, Service, 0, "NetVMini620"
HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"・・・①
HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"・・②
;-----------------------------------------------------------------------------
; Driver and Service Section
[NetVMini.CopyFiles]
NetVMini620.sys,,,2
[NetVMini.Service]
DisplayName = %NetVMini.Service.DispName%
ServiceType = 1 ;%SERVICE_KERNEL_DRIVER%
StartType = 3 ;%SERVICE_DEMAND_START%
ErrorControl = 1 ;%SERVICE_ERROR_NORMAL%
ServiceBinary = %12%\netvmini620.sys
LoadOrderGroup = NDIS
上記の Netvimini の例では、① が上位の UpperRange を指定している箇所で、②が下位の LowerRange をしている箇所です。UpperRange には、”ndis5” というインターフェースが指定されていますので、上位に NDIS が来ます。また、LowerRange には、ミニポート ドライバーが制御するハードウェアのメディアタイプ (この場合は、”ethernet” ) が指定されています。その他、ミニポートドライバーの場合、指定できるインターフェースは以下の通りです。
UpperRange:
ndis5, ndisatm, ndiswan, ndiscowan, noupper, ndis5_atalk, ndis5_dlc, ndis5_ip, ndis5_ipx, ndis5_nbf, ndis5_streams
LowerRange:
ethernet, atm, tokenring, serial, fddi, baseband, broadband, arcnet, isdn, localtalk, wan
補足ですが、Netvmini は、NDIS がロードされるタイミングでロードするよう LoadOrderGroup で指定されています。LoadOrderGroup の指定はオプションであり、またネットワーク特有のものではありません。しかしながら、バインドする相手のドライバーがロードされていないタイミングでドライバーをロードしても、当然正しくバインドできませんので、LoadOrderGroup の指定を行う場合は気を付けてください。
(2)プロトコル ドライバーの場合
WDK の Ndisprot サンプルの INF ファイルの例です。
;-------------------------------------------------------------------------
; Ndi installation support
[Inst_Ndi]
HKR,Ndi,Service,,"Ndisprot"
HKR,Ndi,HelpText,,%NDISPROT_HelpText%
HKR,Ndi\Interfaces, UpperRange,, noupper ・・・・・・・・①
HKR,"Ndi\Interfaces","LowerRange",,"ndis5,ndis4,ndis5_prot" ・・・②
; Service installation support
[Install.Services]
AddService=Ndisprot,,NDISPROT_Service_Inst
[NDISPROT_Service_Inst]
DisplayName = %NDISPROT_Desc%
ServiceType = 1 ;SERVICE_KERNEL_DRIVER
StartType = 3 ;SERVICE_DEMAND_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary = %12%\ndisprot.sys
Description = %NDISPROT_Desc%
上記の Ndisprot の例では、同様に ① が上位の UpperRange を指定している箇所で、”noupper” というインターフェースが指定されています。そのため、上位には何もバインドされません。Ndisprot サンプルのように、上位に専用のアプリケーションやサービスを持つ独自のプロトコルドライバーではこのような指定をします。また、② の下位の LowerRange には、NDIS のインターフェースが指定されていますので、基本的に ATM ネットワークアダプター以外のネットワークアダプターのミニポート ドライバーとバインドします。 (Ndisprot.inf の記述には古い Obsolete なインターフェースも使われているようですね。)
プロトコル ドライバーの場合、指定できるインターフェースは以下の通りです。
netbios, ipx, tdi, winsock, noupper
ndis5, ndisatm, nolower
(3)中間層ドライバーの場合 (※中間層ドライバーは NDIS 6.x の環境下ではレガシーとなります)
中間層ドライバーでは、種類(フィルター、MUX )によって指定の方法が若干異なります。
中間層フィルター ドライバーの場合、プロトコル側の INF ファイルで指定する FilterMediaTypes のエントリーによってバインドが決定します。例えば、以下の Passthru サンプルの例では、Ethernet、トークンリング、FDDI、WAN のミニポートドライバとのバインドを行うことになります。なお、ミニポート側の INF では何も指定しません。
HKR, Ndi, FilterClass, , failover
HKR, Ndi, FilterDeviceInfId, , ms_passthrump
HKR, Ndi, Service, , Passthru
HKR, Ndi\Interfaces, UpperRange, , noupper
HKR, Ndi\Interfaces, LowerRange, , nolower
HKR, Ndi\Interfaces, FilterMediaTypes, , "ethernet, tokenring, fddi, wan"
そして中間層フィルター ドライバーの場合、NDIS がメディアタイプをもとに、既存のバインドに適宜挿入する動作となっているため、UpperRange、LowerRange へ指定できるインターフェースは noupper と nolower のみです。
noupper
nolower
これに対して、同じ中間層ドライバーでも、MUX の場合、プロトコル側の INF ファイルと、ミニポート側の INF ファイルの両方で指定が必要になります。以下の例でいう “ndis5” の部分は任意となりますが、プロトコル側の UpperRange は noupper、ミニポート側の LowerRange は nolower である必要があります。
プロトコル側 INF (muxp.inf)
[MUXP.ndi.AddReg]
HKR, Ndi, ClsID, 0, {ee6cd6fc-a32b-4a26-8a1c-dbc97988ad7a}
HKR, Ndi, ComponentDll, , mux.dll
HKR, Ndi, HelpText, 0, "%MUXP_HELP%"
HKR, Ndi, Service, 0, "MUXP"
HKR, Ndi\Interfaces, UpperRange, 0, "noupper"
HKR, Ndi\Interfaces, LowerRange, 0, "ndis5"
ミニポート側 INF (muxp_mp.inf)
[MUXMP.ndi.AddReg]
HKR, Ndi, Service, 0, MUXMP
HKR, Ndi, HelpText, 0, "%MUXMP_HELP%"
HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
HKR, Ndi\Interfaces, LowerRange, 0, "nolower"
このように中間層ドライバーの場合少しややこしいのでご注意ください。
これらのドライバー(Netvmini / Ndisprot / Passthru)を実際にロードした場合、以下のようになります。
netvimini – Passthru (プロトコル側) / Passthru (ミニポート側) – Ndisprot のような構成ができていることが確認できるかと思います。
例えば Netvmini は LowerRange を、Passthru は FilterMediaType をそれぞれ ”ethernet” として指定していましたので、バインドが作成されています。
Passthru の中間層ドライバーも上記の指定通り、物理 NIC、仮想 NIC に関わらず、インスタンスが作成されており、また、Ndisprot は、Passthru の中間層ドライバーが間に入る形で、バインドがされています。
//Miniport Drivers List
0: kd> !ndiskd.miniport
MiniDriver Miniport Name _
86cd5de8 856660e0 Microsoft Virtual Ethernet Adapter (NDIS 6.20) //Netvmini
8646e170 8646f0e0 WAN Miniport (SSTP)
8646c880 8646d0e0 WAN Miniport (PPTP)
86469be8 8646b0e0 WAN Miniport (PPPOE)
86462340 864680e0 WAN Miniport (IPv6) - Passthru Miniport
86462340 864660e0 WAN Miniport (Network Monitor) - Passthru Miniport
86462340 864640e0 WAN Miniport (IP) - Passthru Miniport
86462340 863f70e0 Broadcom NetXtreme 57xx Gigabit Controller - Passthru Miniport //Passthru Miniport Edge
86462340 863f50e0 Microsoft Virtual Ethernet Adapter (NDIS 6.20) - Passthru Miniport //Passthru Miniport Edge
85de4cc0 863f30e0 WAN Miniport (IPv6)
85de4cc0 863f10e0 WAN Miniport (IP)
85de4cc0 863ed0e0 WAN Miniport (Network Monitor)
863f01a8 863eb0e0 WAN Miniport (L2TP)
86373268 863ef0e0 WAN Miniport (IKEv2)
86331780 863520e0 Broadcom NetXtreme 57xx Gigabit Controller
862de960 862be0e0 Microsoft ISATAP Adapter #2
862de960 85e2e0e0 Microsoft ISATAP Adapter
//Protocol Drivers List
0: kd> !ndiskd.protocol
8532e838 - NDISPROT
857921e8 - Microsoft Virtual Ethernet Adapter (NDIS 6.20) - Passthru Miniport// Binding between Ndisprot <-> Passthru Miniport Edge
8588eaa8 - Broadcom NetXtreme 57xx Gigabit Controller - Passthru Miniport
:
(中略)
86462190 – PASSTHRU //Passthru Protocol Edge
8561eaa8 - Broadcom NetXtreme 57xx Gigabit Controller
856596b0 - Microsoft Virtual Ethernet Adapter (NDIS 6.20) // Binding between Passthru Protocol Edge <-> Netvmini
86eff230 - WAN Miniport (IPv6)
8578f1f8 - WAN Miniport (IP)
856155c8 - WAN Miniport (Network Monitor)
//------------------------------------------
// Binding between Netvmini <-> Passthru Protocol Edge
//Netvmini
0: kd> !ndiskd.miniport 856660e0
MINIPORT
Microsoft Virtual Ethernet Adapter (NDIS 6.20)
Ndis Handle 856660e0
Ndis API Version v6.20
Adapter Context 868524c0
Miniport Driver 86cd5de8 - NetVMini620 v4.2
Ndis Verifier [No flags set]
Media Type 802.3
Physical Medium 802.3
Device Path \??\Root#UNKNOWN#0000#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{E9E35515-F814-4541-BD08-7E45F26DDCFD}
Device Object 85666028
MAC Address 02-50-f2-f6-07-0a
STATE
Miniport Running
Device PnP Started
Datapath Normal
Interface Up
Media Connected
Power D0
References 3
User Handles 0
Total Resets 0
Pending OID None
Flags NOT_BUS_MASTER, DEFAULT_PORT_ACTIVATED,
NOT_SUPPORTS_MEDIA_SENSE, DOES_NOT_DO_LOOPBACK,
MEDIA_CONNECTED [28452000]
PnPFlags VIRTUAL_DEVICE, RECEIVED_START, NDIS_WDM_DRIVER
[00410002]
BINDINGS
Filter List Filter Filter Driver Context _
No filters are bound
Open List Open Protocol Context _
PASSTHRU 856596b0 86462190 857f8340
MORE INFORMATION
→ Driver handlers → Task offloads
→ Power management → PM protocol offloads
→ Pending OIDs → Timers
→ Pending NBLs → Receive Side Throttling
→ Wake-on-LAN (WoL) → Packet filter
→ Receive queues → Receive filtering
→ RSS → NIC switch
→ NDIS ports
//Bind Information
0: kd> !ndiskd.mopen 856596b0
OPEN
Ndis Handle 856596b0
Flags USE_MULTICAST_LIST, OPEN_WRAPPED [11000000]
References 1
State Running
Pause requests 1
Miniport 856660e0 - Microsoft Virtual Ethernet Adapter (NDIS 6.20)
Miniport Context 868524c0
Protocol 86462190 - PASSTHRU
Protocol Context 857f8340
RECEIVE PATH
This protocol will receive all traffic indicated by the miniport, because:
- this is the only open bound to the miniport
Packet filter DIRECTED, MULTICAST, BROADCAST [0000000b]
Frame Type(s) [This protocol has not registered any frame types]
Multicast groups 33-33-00-00-00-01 → See all on miniport
00-00-01-00-00-00
01-00-5e-00-00-01
33-33-00-01-00-03
2c-08-01-00-00-00
33-33-00-00-00-0c
//Passthru Protocol Edge
0: kd> !ndiskd.protocol 86462190
PROTOCOL
PASSTHRU
Ndis Handle 86462190
Ndis API Version v5.0
Reference Count 6
Flags [No flags set]
Associated Miniport 86462340 - passthru
Open Miniport Miniport Name _
8561eaa8 863520e0 Broadcom NetXtreme 57xx Gigabit Controller
856596b0 856660e0 Microsoft Virtual Ethernet Adapter (NDIS 6.20)
86eff230 863f30e0 WAN Miniport (IPv6)
8578f1f8 863f10e0 WAN Miniport (IP)
856155c8 863ed0e0 WAN Miniport (Network Monitor)
HANDLERS
Protocol Handler Function pointer Symbol (if available)
BindAdapterHandler 9404c4a0 bp passthru!PtBindAdapter
UnbindAdapterHandler 9404c8d0 bp passthru!PtUnbindAdapter
PnPEventHandler 9404d420 bp passthru!PtPNPHandler
UnloadHandler 9404cb20 bp passthru!PtUnloadProtocol
OpenAdapterCompleteHandler 9404c880 bp passthru!PtOpenAdapterComplete
CloseAdapterCompleteHandler 9404cb70 bp passthru!PtCloseAdapterComplete
SendCompleteHandler 9404cea0 bp passthru!PtSendComplete
TransferDataCompleteHandler 9404cf80 bp passthru!PtTransferDataComplete
ReceiveHandler 9404cfd0 bp passthru!PtReceive
ReceivePacketHandler 9404d290 bp passthru!PtReceivePacket
ReceiveCompleteHandler 9404d1c0 bp passthru!PtReceiveComplete
StatusHandler 9404cdb0 bp passthru!PtStatus
StatusCompleteHandler 9404ce50 bp passthru!PtStatusComplete
RequestCompleteHandler 9404cbf0 bp passthru!PtRequestComplete
ResetCompleteHandler 9404cbc0 bp passthru!PtResetComplete
// Binding between Passthru Miniport Edge <-> Ndisprot
//Passthru Miniport Edge on Netvmini
0: kd> !ndiskd.miniport 863f50e0
Microsoft Virtual Ethernet Adapter (NDIS 6.20) - Passthru Miniport
Ndis Handle 863f50e0
Ndis API Version v5.1
Adapter Context 857f8340
Miniport Driver 86462340 - passthru v10.100
Physical Medium NdisPhysicalMediumUnspecified
Device Path \??\Root#MS_PASSTHRUMP#0000#{ad498944-762f-11d0-8dcb-00c04fc3358c}\{CDD842EC-73E4-41A5-BD0F-CE809BCCC209}
Device Object 863f5028
References 8
Flags NOT_BUS_MASTER, IGNORE_PACKET_QUEUE,
IGNORE_REQUEST_QUEUE, IGNORE_TOKEN_RING_ERRORS,
INTERMEDIATE_DRIVER, DEFAULT_PORT_ACTIVATED,
DESERIALIZED, RESOURCES_AVAILABLE, SUPPORTS_MEDIA_SENSE,
DOES_LOOPBACK, MEDIA_CONNECTED [2445b800]
PnPFlags PM_SUPPORTED, DEVICE_POWER_ENABLED, HIDDEN,
NO_HALT_ON_SUSPEND, RECEIVED_START, FILTER_IM [08019021]
WFP LightWeight Filter-0000
85815970 86286ad0 8543c4c0
QoS Packet Scheduler-0000
85613190 86286488 8538c008
TCPIP6 8587a008 85f0a520 857ac008
TCPIP 86862008 85f0a008 86f03d00
LLTDIO 857b8aa8 86c900a8 86001de0
RSPNDR 86863aa8 86c6b7f0 858a4828
NDISPROT 857921e8 8532e838 8538b380
→ Driver handlers
→ Power management
0: kd> !ndiskd.mopen 857921e8
Ndis Handle 857921e8
Pause requests 0 [Open can restart]
Miniport 863f50e0 - Microsoft Virtual Ethernet Adapter (NDIS 6.20) - Passthru Miniport
Miniport Context 857f8340
Protocol 8532e838 - NDISPROT
Protocol Context 8538b380
Packet filter [No flags set]
Frame Type(s) 0x888e, 0x8100
Multicast groups [This protocol has not added any multicast groups]
//Ndisprot
0: kd> !ndiskd.protocol 8532e838
NDISPROT
Ndis Handle 8532e838
Ndis API Version v6.0
Driver Context NULL
Driver Version v0.0
Reference Count 3
8680f358 863f50e0 Microsoft Virtual Ethernet Adapter (NDIS 6.20) - Passthru Miniport
856596b0 863f70e0 Broadcom NetXtreme 57xx Gigabit Controller - Passthru Miniport
BindAdapterHandlerEx 9928a830 bp ndisprot!NdisprotBindAdapter
UnbindAdapterHandlerEx 9928aa20 bp ndisprot!NdisprotUnbindAdapter
OpenAdapterCompleteHandlerEx 9928a9c0 bp ndisprot!NdisprotOpenAdapterComplete
CloseAdapterCompleteHandlerEx 9928aaf0 bp ndisprot!NdisprotCloseAdapterComplete
NetPnPEventHandler 9928ab50 bp ndisprot!NdisprotPnPEventHandler
UninstallHandler 0
SendNetBufferListsCompleteHandler 9928e8a0 bp ndisprot!NdisprotSendComplete
ReceiveNetBufferListsHandler 9928d480 bp ndisprot!NdisprotReceiveNetBufferLists
StatusHandlerEx 9928bf50 bp ndisprot!NdisprotStatus
OidRequestCompleteHandler 9928bee0 bp ndisprot!NdisprotRequestComplete
DirectOidRequestCompleteHandler 0
次回のさなえすの投稿では、Bindview.exe と INetCfg インターフェースを紹介しながら、バインドのお話を続けたいと思っています。
皆さま、風邪やインフルエンザが流行っていますが、くれぐれもお気を付け下さいませ。
それでは また!
●Reference
- Mark E. Russinovich, David A. Solomon, Windows Internals 5th Edition, 2009, P1064–1065
- Specifying Binding Interfaces
<http://msdn.microsoft.com/en-us/library/ff570839(v=VS.85).aspx>
- Installation Requirements for Network Components
<http://msdn.microsoft.com/en-us/library/ff554949(v=VS.85).aspx>
-Installing an Intermediate Driver
<http://msdn.microsoft.com/en-us/library/ff554964(VS.85).aspx>
-MUX Intermediate Driver Installation
<http://msdn.microsoft.com/en-us/library/ff560584(VS.85).aspx>
- Intermediate Driver UpperRange And LowerRange INF File Entries
<http://msdn.microsoft.com/en-us/library/ff556014(v=VS.85).aspx>