ONC+ 開発ガイド

付録 E portmap ユーティリティ

Solaris 環境の旧バージョンのユーティリティである portmap ユーティリティの代わりに rpcbind ユーティリティを使用します。この章は、portmap ユーティリティの話題からポートとネットワークアドレスの解決方法の変遷を理解していただくためのものです。

Solaris の RPC ベースのサービスでは、システム登録サービスとしては portmap を使用していました。portmap は、ポート (論理通信チャネル) と、そこに登録されたサービスとの対応テーブルを管理します。portmap は、サーバーがサポートしている RPC プログラムに対する TCP/IP または UDP/IP のポート番号をクライアントが調べるための標準的な方法を提供します。

システム登録の概要

クライアントプログラムがネットワーク上の分散サービスを利用するには、サーバープログラムのネットワークアドレスを知る必要があります。ネットワークトランスポート (プロトコル) サービスはこのような機能を提供しません。ネットワーク上のプロセス間メッセージを伝送するだけです。つまり、メッセージはトランスポート固有のネットワークアドレスに送信されます。ネットワークアドレスは論理通信チャネルです。特定のネットワークアドレス上で待機することにより、プロセスはネットワークからのメッセージを受信します。

プロセスがどのようにネットワークアドレスを監視するかは、オペレーティングシステムごとに異なりますが、どのオペレーティングシステムでも、メッセージの到着に同期してプロセスがアクティビティを起こすような機能があります。メッセージは受信側プロセスに対してネットワーク上に送信されるのではなく、特定のネットワークアドレスに対して送信され、そこを監視していた受信側プロセスがそのメッセージを取り出します。

ネットワークアドレスが重要なのは、受信側のオペレーティングシステムの方針に依存しない方法で、メッセージの宛先を指定できるからです。TI-RPC はトランスポート独立ですので、ネットワークアドレスの実際の構造については関知しません。その代わりに、TI-RPC は汎用アドレスを使用します。汎用アドレスは NULL で終わる文字列で指定します。汎用アドレスは、各トランスポートプロバイダに固有のルーチンにより、ローカルトランスポートアドレスに変換されます。

rpcbind プロトコルでは、サーバーがサポートする任意のリモートプログラムのネットワークアドレスをクライアントから調べるための標準の方法を提供します。このプロトコルはどのトランスポートにも実現できるので、全クライアント、全サーバー、全ネットワークに適用できるような 1 つの問題解決方法を提供します。

portmap プロトコル

portmap プログラムは、RPC プログラムとバージョン番号を、トランスポート固有のポート番号にマップします。portmap プログラムは、リモートプログラムの動的結合を可能にします。

図 E–1 典型的な Portmap シーケンス (TCP/IP のみ)

Graphic

上記の図は、次のプロセスを示しています。

  1. サーバーが portmap に登録する

  2. クライアントは、サーバーのポートを portmap から得る

  3. クライアントが、サーバーを呼び出す

予約ポート番号は少ないのに対して、リモートプログラム数は非常に多くなる可能性があります。したがって、よく知られたポートでポートマッパーを実行しておけば、その他のリモートプログラムのポート番号はポートマッパーに問い合わせることによって得られます。図 E–1 では、 a111bc はポート番号を表し、111 はポートマッパーに割り当てられたポート番号です。

ポートマッパーはブロードキャスト RPC にも役立ちます。特定の RPC プログラムは通常、異なるマシンへは異なるポート番号を割り当てるため、これらのすべてのプログラムへ直接ブロードキャスト通信を行うことはできません。これに対して、ポートマッパーは固定のポート番号を持っています。そこで、特定のプログラムにブロードキャストするには、クライアントはブロードキャストアドレスにあるポートマッパーにメッセージを送信します。各ポートマッパーは、ブロードキャストを受けて、クライアントが指定しているローカルサービスを呼び出します。portmap はローカルサービスからの応答を取り出すと、それをクライアントに送信します。次のコーディング例で、portmap プロトコル仕様を示します。


例 E–1 portmap プロトコル仕様 (RPC 言語で記述)

const PMAP_PORT = 111;       /* ポートマッパーのポート番号 */
 /*
  * ポート番号のマッピング (プログラム、バージョン、プロトコル) 
  */
 struct pmap {
 	rpcprog_t prog;
 	rpcvers_t vers;
 	rpcprot_t prot;
 	rpcport_t port;
 };
 /*
  * prot フィールドに指定できる値
  */
 const IPPROTO_TCP = 6; /* TCP/IP のプロトコル番号*/
 const IPPROTO_UDP = 17; /* UDP/IP のプロトコル番号  */
 /*
  * マッピングのリスト
  */
 struct pmaplist {
 	pmap map;
 	pmaplist *next;
 };
 /*
  * callit への引数
  */
 struct call_args {
 	rpcprog_t prog;
 rpcvers_t vers;
 rpcproc_t proc;
 	opaque args<>;
 };
 /*
 * callit の戻り値
 */
 struct call_result {
 	rpcport_t port;
 	opaque res<>;
 };
 /*
 * ポートマッパー手続き
 */
 program PMAP_PROG {
 	version PMAP_VERS {
 		void
 		PMAPPROC_NULL(void) = 0;
 		bool
 		PMAPPROC_SET(pmap) = 1;
 		bool
 		PMAPPROC_UNSET(pmap) = 2;
 		unsigned int
 		PMAPPROC_GETPORT(pmap) = 3;
 		pmaplist
 		PMAPPROC_DUMP(void) = 4;
 		call_result
 		PMAPPROC_CALLIT(call_args) = 5;
 	} = 2;
 } = 100000;

portmap の操作

portmap が現在サポートしているプロトコルは 2 つ (TCP/IP と UDP/IP) です。portmap にアクセスするには、どちらかのプロトコルで割り当てられたポート番号 111 (SUNRPC (5)) と通信します。次の節ではポートマッパーの各手続きを説明します。

PMAPPROC_NULL

この手続きは何もしない手続きです。習慣的に、どのプロトコルでも手続き 0 は引数も戻り値もない手続きにします。

PMAPPROC_SET

プログラムは、マシン上で最初に使用可能になるとローカルのポートマッププログラムに自分自身を登録します。プログラムは、プログラム番号 prog、バージョン番号 vers、トランスポートプロトコル番号 prot、サービス要求を受信するポート port を引き渡します。この手続きは、指定したポートに既にマッピングが存在していて結合されていれば、マッピングの設定を拒絶します。マッピングが存在していてポートが未結合の場合は、ポートを登録解除し、要求されたマッピングを設定します。PMAPPROC_SET 手続きは、割り当てが正しく設定されれば TRUE を、設定されない場合は FALSE を返します。 rpc_soc(3NSL) のマニュアルページの pmap_set() 関数も参照してください。

PMAPPROC_UNSET

プログラムが使用不可能になれば、同一マシン上のポートマッパープログラムで自身の登録を解除しなければなりません。PMAPPROC_UNSET の引数と戻り値は PMAPPROC_SET の引数と戻り値と同一の意味を持ちます。引数のうち、プロトコルとポート番号のフィールドは無視されます。rpc_soc(3NSL) のマニュアルページの pmap_unset() 関数も参照してください。

PMAPPROC_GETPORT

プログラム番号 prog、バージョン番号 vers、とトランスポートプロトコル番号 prot を、PMAPPROC_GETPORT 手続きに引き渡すと、そのプログラムが呼び出し要求を待っているポート番号が返されます。ポート番号 0 が返された場合は、そのプログラムが登録されていないことを示します。引数の port フィールドは無視されます。rpc_soc(3NSL) のマニュアルページの pmap_getport() 関数も参照してください。

PMAPPROC_DUMP

PMAPPROC_DUMP 手続きはポートマッパーのデータベース内のすべてのエントリを列挙します。この手続きへの引数はなく、返されるのは、プログラム、バージョン、プロトコル、ポート番号のリストです。rpc_soc(3NSL) のマニュアルページの pmap_getmaps() 関数も参照してください。

PMAPPROC_CALLIT

PMAPPROC_CALLIT 手続きを使用すると、呼び出し側がリモートプロシージャのポート番号がわからなくても、同一マシン上にあるリモートプロシージャを呼び出すことができます。この手続きは、既知のポートマッパーのポートを使用して、任意のリモートプログラムへのブロードキャスト通信をサポートします。引数の progversprocargs はそれぞれプログラム番号、バージョン番号、手続き番号、リモートプロシージャへの引数です。rpc_soc(3NSL) のマニュアルページの pmap_rmtcall() 関数も参照してください。

この手続きは正常終了したときだけ応答を返し、異常終了したときは応答を返しません。また、リモートプログラムのポート番号と、リモートプロシージャからの戻り値を返します。

ポートマッパーがリモートプログラムとの通信に使用できるのは UDP/IP だけです。