Windows 8 で NDIS 5.x の LAN カードドライバが動かない場合の応急処置

Windows 8 の Consumer Preview 版が 2 月末に公開されたので、PacketiX VPN、UT-VPN が動作するかどうかの検証を行ったところ、Server、Bridge は問題なく動作するが、Client の仮想 LAN カードがうまく動作せず、全く通信できないことがわかった。


PacketiX VPN や UT-VPNVPN Client の仮想 LAN カードドライバは、NDIS 5.0 の規格で書かれている。NDIS 5.x は Windows 2000Windows XP, Windows Server 2003 におけるネットワークドライバの規格であり、Windows Vista 以降 (NDIS 6.0) と比較すると時代遅れになっている。しかし、時代遅れといっても Windows Vista 以降は NDIS 5.x をサポートするラッパーが搭載されていたので、実用上は問題がない。また、通信速度もほとんど変わらない。(NDIS 6.0 以降でなければ実装することができない機能もあるが、PacketiX VPN Client では使用していないので問題ない。)


しかし、PacketiX VPN の仮想 LAN カードドライバを NDIS 5.0 のまま Windows 8 CP で動作させようとしたところ、LAN カードの初期化などは問題ないものの、全く通信ができない現象が発生した。Windows 8 については Microsoft がまだ完全なデバイスドライバに関するドキュメントを公開していないため、何が原因であるか追求するには多大な時間がかかったが、どうやら、なぜか NDIS 5.x のドライバモデルのうち「Serialized Driver」モデルの場合にトラブルが発生するっぽい、ということがわかった。


Windows 8 でも NDIS 5.x は引き続きサポートされている。カーネル全体は NDIS 6.x を搭載しているので、NDIS 6.x から 5.x をサポートするためのラッパーが Windows Vista 以降にあるのだが、どうもこの部分に原因があるのではないかと思うようになった、Windows 8 CP の Debug ビルド (最適化などを OFF にしてビルドされた Windows の開発者向けバージョン) を使用して青画面をわざと何度も発生させながら WinDbg で検証した結果、NDIS 6.0 -> 5.x ラッパーの中のパケットのメモリ解放部分でラッパーが 2 重解放をしているように思われる挙動が確認できた。これによってメモリ内のデータ構造がおかしくなって通信ができないか、場合によってはブルースクリーンになってしまうこともある。


もちろん最初は PacketiX VPN Client 仮想 LAN カード側のバグであることを疑った。しかし、他社のまともな LAN カード (某社製) の Windows XP 用ドライバが NDIS 5.x なのでそれを用いて通信してみると、やはり、同様にブルースクリーンになってしまうので、NDIS 5.x を Windows 8 CP で使用するとバグが出るのではないか、つまり原因は Windows 8 CP 側にある、という結論に至った。


そこで、なぜ Windows Vista / 7 / Server 2008 / Server 2008 R2 では NDIS 5.x の PacketiX VPN Client 仮想 LAN カードドライバが問題なく動作したにもかかわらず Windows 8 CP では動作しなくなったのか (そして Windows 8 Developer Preview という 1 つ前のビルドでは問題なく動作したか) を考えた。Windows 8Windows 7 とは NDIS 周辺に何らかの重要な機能拡張や仕様変更が行われた可能性は低い。一方、Windows 8 では新たに ARM プロセッサをサポートすることになり、ARM プロセッサをサポートするため、これまでいいかげんに書いて動いていた Windows 7 以前の NDIS の一部のコードを、たとえばアライメントの問題に対応するために修正したり、最適化したのではないか。それが何らかの副作用を生じさせ、NDIS 5.x の古いドライバが Windows 8 CP でうまく動作しない (またはブルースクリーンになってしまう) 現象が発生している可能性がある。


そのため、Windows 8 CP で仮想 LAN カードドライバを動かすことができるようにする修正を考えた。もし今回の原因が Microsoft 側にあるとしても、リリース時までこのバグを直さない可能性もあるから、こちら側の仮想 LAN カード側でこのバグを踏まないようにする修正を考えるのが最も安心できる方法である。思い切って NDIS 6.0 へ移行することも考えたが、特に NDIS 6.0 を必要とする機能は使用していないにもかかわらず、インターフェイスを大幅に変更する開発をするのはコストがもったいないので、できれば NDIS 5.0 のままのドライバを維持して何とかしたいと思った。色々試した結果、NDIS 5.x の「Serialized Driver」モデル (現在のモデル) をやめて、代わりに「Deserialized Driver」モデルに変更すればうまくいくことがわかった。Deserialized Driver モデルを採用するにはいくつかの場所を非同期な処理に書き換える必要があったが、IntelNIC のドライバのソースコードを参考にして実装したら、動作するようになった。この状態で 1 週間以上、VM や実マシンを用いてテストをしたが、動作は不安定にはならなかった。


なお、Windows 8 CP で動作するバージョンの PacketiX VPN Client のベータ版は http://download.softether.co.jp/folder/vpn3_ipsec_beta/v3.04-7865-beta2_fix1-2012.04.05/ に密かに置いた。


PacketiX VPN の仮想 LAN カードドライバに関わらず、他の NDIS 5.x インターフェイスを採用している LAN カードのドライバの開発者の方は、Windows 8 CP でなぜか動作しなくなった場合は、ドライバモデルを「Deserialized Driver」に変更してみれば解決するかも知れない。