EternalWindows
LSP / サービスプロバイダ

本章では、Winsockをこれまでとは別の角度から取り上げます。 一般にWinsockは、低レベルで柔軟なネットワーク通信が可能なAPIとして利用されますが、 このAPIの本当の役割はサービスプロバイダにアプリケーションからの処理内容を伝えることです。 サービスプロバイダとは、Winsockの機能を強化する目的で追加されたDLLであり、 たとえばTCPやUDPといったプロトコルを実装しているのは、 mswsock.dllというサービスプロバイダです。 Winsock関数はws2_32.dllによってエクスポートされていますが、 これらの関数はアプリケーションとサービスプロバイダを繋ぐための仲介であり、 ソケットを作成するといった具体的な実装を持っているわけではないのです。

サービスプロバイダには、トランスポートサービスプロバイダと名前空間サービスプロバイダの2種類が存在します。 トランスポートサービスプロバイダは、先に述べたような特定のプロトコルを実装するDLLであり、 基本的にWinsock関数と一対一で対応する関数を実装しています。 たとえば、Winsockのconnect関数を呼び出した場合、トランスポートサービスプロバイダのWSPConnectという関数が呼ばれることになります。 一方、名前空間サービスプロバイダは、ホスト名からIPアドレスの変換が必要な場合などに呼び出されることになります。 本章では、トランスポートサービスプロバイダの開発について取り上げます。

開発者にとって、トランスポートサービスプロバイダを開発する目的は主に2通り考えられます。 まず1つは、新しいプロトコルを実装するという目的です。 このようなサービスプロバイダが追加されていれば、 Winsockアプリケーションはsocket関数に新しいプロトコルを指定し、 そのプロトコル独自の通信を行えるようになります。 基本的に、こうしたサービスプロバイダは、ネットワークドライバと通信するためのコードを含むことになるでしょう。 そしてもう1つは、既存のサービスプロバイダへの要求を検出するという目的です。 具体的には、開発したサービスプロバイダを既存のサービスプロバイダの上にインストールし、 ws2_32.dllからの要求を代わりに検出するのです。

通常、アプリケーションがIPPROTO_TCPを指定したsocketを呼び出した場合、 ws2_32.dllはTCPプロトコルを実装するmswsock.dllを呼び出し側プロセスにロードします。 そして、socketに対応するWSPSocketという関数を呼び出し、 サービスプロバイダはソケットを作成するコードを実行することになります。 ただし、mswsock.dllの上にIPPROTO_TCPを実装する別のサービスプロバイダをインストールした場合、 そのサービスプロバイダがsocketを呼び出したプロセスにロードされることになります。 理由は、ws2_32.dllによるプロトコルの検索で、mswsock.dllよりも先に一致したからです。 このように、特定のプロトコル上にインストールされたサービスプロバイダは、 LSP(Layered Service Provider)と呼ばれます。 LSPの関数が制御を返した後に、ws2_32.dllによって下のサービスプロバイダの関数が呼ばれるようなことはないため、 呼び出し側にWinsock関数本来の機能を提供したいのであれば、 下に存在するサービスプロバイダの関数を明示的に呼び出す必要があります。 逆に、本来の処理を行いたくない場合は、サービスプロバイダの関数を呼ばなければよいでしょう。 LSP内でWinsock関数を呼び出すと、再びそのプロセスにLSPがロードされる事態が発生するため、 この点については注意しておく必要があります。

LSPで行えることは、非常に広範です。 たとえば、LSPが実装するWSPConnectでは、通信先のIPアドレスを取得することができるため、 特定のIPアドレスに対する接続を遮断することが可能です。 また、送信データの解析したり、ローカルコンピュータ上にキャッシュしたりするようなこともできるでしょう。 今回最終的に開発することになるLSPは、Winsock関数の呼び出しを監視することを目的とし、 次のようなファイルを作成しています。

このように関数呼び出しを記録すれば、 どのプロセスがどの関数を呼び出したのかが一目で分かるようになります。 また、関数によっては引数の内容を記録するのもよいでしょう。 1つ注意しなければならないのは、この記録された関数をプロセスが直接呼び出したかどうかは分からないという点です。 たとえば、WinINetというネットワークAPIはWinsockの上位実装であり、 内部でWinsockの関数を呼び出すことになっています。 このため、WinINetのInternetOpenUrlを呼び出してみると、 WSAStartupからrecvまでの関数が記録されることが分かります。 つまり、LSPはWinsock関数を直接呼び出すアプリケーションだけでなく、 内部的に呼び出すアプリケーションの動作も検出することができるのです。

サービスプロバイダが実装する関数、またはアプリケーションがサービスプロバイダを操作する関数などはWinscok SPIと呼ばれています。 Winscok SPIは、次のように種類分けすることができます。

プレフィックス 意味
WSP トランスポートサービスプロバイダが実装する関数。 つまり、DLLにおけるエクスポート関数。
WPU サービスプロバイダから、ws2_32.dllの機能を利用したい場合に呼び出す関数。
WSC サービスプロバイダを操作するための関数。 アプリケーションとサービスプロバイダの両方が呼び出すことができる。
NSP 名前空間サービスプロバイダが実装する関数。 つまり、DLLにおけるエクスポート関数。

本章では、トランスポートサービスプロバイダを開発することになるため、 論点の焦点となるのは、トランスポートサービスプロバイダがエクスポートするWSP関数を どのように実装すればよいかという点になります。 ただし、インストールを実行しないことには、 トランスポートサービスプロバイダが機能しないため、 まずはWSC関数を利用したインストールの方法について見ていくことになります。


戻る