ONC+ 開発ガイド

RPC メッセージプロトコル

この節では、RPC メッセージプロトコルを、XDR データ記述言語を使用して説明します。メッセージは、次の例のように、トップダウン方式で定義されます。


例 B–1 RPC メッセージプロトコル

enum msg_type {
 	CALL = 0,
 	REPLY = 1
 };

/*
 * 呼び出しメッセージに対する応答には、2 つの形式があります。メッセージが
 * 受け入れられた場合と拒絶された場合のどちらかです。
 */
 enum reply_stat {
 	MSG_ACCEPTED = 0,
 	MSG_DENIED = 1
 };

/*
 * 呼び出しメッセージが受け入れられた場合、
 * リモートプロシージャを呼び出したときの
 * ステータスが次のように示されます。
 */
enum accept_stat {
 	SUCCESS = 0,       /* RPC が正常に実行された */
 	PROG_UNAVAIL = 1,
              /* リモートサービスにエクスポートされたプログラムがない */
 	PROG_MISMATCH = 2, /* リモートサービスがそのバージョン番号を
			    * サポートしていない */
 	PROC_UNAVAIL = 3,  /* プログラムがその手続きをサポートしていない */
 	GARBAGE_ARGS = 4   /* 手続きが引数を復号化できない */
};

/*
 * 呼び出しメッセージが拒絶された原因
 */
enum reject_stat {
 	RPC_MISMATCH = 0,  /* RPC のバージョン番号が 2 でない */
 	AUTH_ERROR = 1     /* リモートサービスで呼び出し側の認証エラー */
};
/*
 * 認証が失敗した原因
 */
enum auth_stat {
 	AUTH_BADCRED = 1,       /* 認証エラーの原因 */
 	AUTH_REJECTEDCRED = 2,  /* クライアントは新規セッションが必要 */
 	AUTH_BADVERF = 3,       /* ベリファイアのエラー */
 	AUTH_REJECTEDVERF = 4,  /* ベリファイアの失効または再使用 */
 	AUTH_TOOWEAK = 5        /* セキュリティによる拒絶 */
};

/*
 * RPC メッセージ:
* どのメッセージもトランザクションID xid と
* それに続く識別型共用体(アームは 2 つ) で始まります。
* 共用体の要素識別子はmsg_type で、2 つのメッセージタイプのうち
* どちらのタイプのメッセージかを示します。REPLY メッセージの xid は、
* 対応するCALL メッセージのxid に一致します。注意: xid フィールドは、
* クライアント側で応答メッセージがどの呼び出しメッセージに対応するかを
* 調べるか、サーバー側で再送信かどうかを調べるためにだけ使用できます。
* サービス側では xid をシーケンス番号として使用することはできません。
 */
struct rpc_msg {
 	unsigned int xid;
 	union switch (msg_type mtype) {
 		case CALL:
 			call_body cbody;
 		case REPLY:
 			reply_body rbody;
 	} body;
};

/*
 * RPC 要求呼び出しの本体:
 * RPC プロトコル仕様のバージョン 2 では、rpcvers は 2 でなければ
 * なりません。prog、vers、proc の各フィールドにはそれぞれ、
 * リモートプログラム、そのバージョン番号、リモートプログラムに入っている
 * 呼び出し対象の手続きを指定します。これらのフィールドに続いて
 * 2 つの認証パラメータ cred (認証資格) と verf (認証ベリファイア)
 * があります。この 2 つの認証パラメータの後には、
 * リモートプロシージャへの引数が入りますが、それらは特定プログラムの
 * プロトコルで指定されます。
 */
struct call_body {
 	unsigned int rpcvers; /* この値は 2 でなければならない */
 	unsigned int prog;
 	unsigned int vers;
 	unsigned int proc;
 	opaque_auth cred;
 	opaque_auth verf;
 	/* ここからは手続きに固有の引数 */
 };

/*
 * RPC 要求への応答の本体:
 * 呼び出しメッセージは受け入れられたか拒絶されたかのどちらか
 */
union reply_body switch (reply_stat stat) {
 	case MSG_ACCEPTED:
 		accepted_reply areply;
 	case MSG_DENIED:
 		rejected_reply rreply;
} reply;

/*
 * RPC 要求がサーバーに受け入れられた場合の応答: 要求が受け入れられた場合も
 * エラーはあり得ます。最初のフィールドはサーバーが呼び出し側に自分自身を
 * 証明する認証ベリファイアです。次のフィールドは共用体で、
 * 要素識別子は列挙型 accept_stat です。この共用体の SUCCESS アームは
 * プロトコルによって異なります。
 * PROG_UNAVAIL、PROC_UNAVAIL、GARBAGE_ARGP の
 * アームは void です。PROG_MISMATCH アームにはサーバーが
 * サポートしているリモートプログラムのバージョン番号の
 * 最大値と最小値が入ります。
 */
struct accepted_reply {
 	opaque_auth verf;
 	union switch (accept_stat stat) {
 		case SUCCESS:
 			opaque results[0];
 			/* ここからは手続き固有の戻り値 */
 		case PROG_MISMATCH:
 			struct {
 				unsigned int low;
 				unsigned int high;
 			} mismatch_info;
 		default:
 			/*
 			 *  PROG_UNAVAIL、PROC_UNAVAIL、GARBAGE_ARGS
* の場合はvoid
 			 */
 			void;
 	} reply_data;
 };

/*
 * RPC 要求がサーバーに拒絶された場合の応答:
 * 要求が拒絶されるのには 2 つの原因があります。互換性のあるバージョンの
 * RPC プロトコルがサーバーで実行されていない場合(RPC_MISMATCH) と、
 * サーバーが呼び出し側の認証を拒否した場合(AUTH_ERROR) です。
 * RPC バージョンの不一致の場合は、サーバーがサポートしている 
 * RPC バージョンの最大値と最小値が返されます。
 * 認証拒否の場合は、異常終了ステータスが返されます。
 */
union rejected_reply switch (reject_stat stat) {
 	case RPC_MISMATCH:
 		struct {
 			unsigned int low;
 			unsigned int high;
 		} mismatch_info;
 	case AUTH_ERROR:
 		auth_stat stat;
};