ONC+ 開発ガイド

RPC メッセージプロトコル

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


例 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;
};