The Remote Procedure Call (RPC) message protocol consists of two distinct structures: the call message and the reply message. A client makes a remote procedure call to a network server and receives a reply containing the results of the procedure's execution. By providing a unique specification for the remote procedure, RPC can match a reply message to each call (or request) message.
The RPC message protocol is defined using the eXternal Data Representation (XDR) data description, which includes structures, enumerations, and unions. See "RPC Language Descriptions" for more information.
When RPC messages are passed using the TCP/IP byte-stream protocol for data transport, it is important to identify the end of one message and the start of the next one.
RPC Protocol Requirements
The RPC message protocol requires:
- Unique specification of a procedure to call
- Matching of response messages to request messages
- Authentication of caller to service and service to caller
To help reduce network administration and eliminate protocol roll-over errors, implementation bugs, and user errors, features that detect the following conditions are useful:
- RPC protocol mismatches
- Remote program protocol version mismatches
- Protocol errors (such as misspecification of a procedure's parameters)
- Reasons why remote authentication failed
- Any other reasons why the desired procedure was not called
RPC Messages
The initial structure of an RPC message is as follows:
structrpc_msg{unsignedintxid;unionswitch(enummsg_typemtype){caseCALL:call_bodycbody;caseREPLY;reply_bodyrbody;}body;};
All RPC call and reply messages start with a transaction identifier, xid, which is followed by a two-armed discriminated union. The union's discriminant is msg_type, which switches to one of the following message types: CALL or REPLY. The msg_type has the following enumeration:
enummsg_type{CALL=0,REPLY=1};
The xid parameter is used by clients matching a reply message to a call message or by servers detecting retransmissions. The server side does not treat the xid parameter as a sequence number.
The initial structure of an RPC message is followed by the body of the message. The body of a call message has one form. The body of a reply message, however, takes one of two forms, depending on whether a call is accepted or rejected by the server.
RPC Call Message
Each remote procedure call message contains the following unsigned integer fields to uniquely identify the remote procedure:
The body of an RPC call message takes the following form:
structcall_body{unsignedintrpcvers;unsignedintprog;unsignedintvers;unsignedintproc;opaque_authcred;opaque_authverf;1parameter2parameter...};
The parameters for this structure are:
The client can send a broadcast packet to the network and wait for numerous replies from various servers. The client can also send an arbitrarily large sequence of call messages in a batch to the server.
RPC Reply Message
The RPC protocol for a reply message varies depending on whether the call message is accepted or rejected by the network server.
The reply message to a request contains information to distinguish the following conditions:
- RPC executed the call message successfully.
- The remote implementation of RPC is not protocol version 2. The lowest and highest supported RPC version numbers are returned.
- The remote program is not available on the remote system.
- The remote program does not support the requested version number. The lowest and highest supported remote program version numbers are returned.
- The requested procedure number does not exist. This is usually a caller-side protocol or programming error.
The RPC reply message takes the following form:
enumreply_statstat{MSG_ACCEPTED=0,MSG_DENIED=1};
The enumreply_stat discriminant acts as a switch to the rejected or accepted reply message forms.
The Reply to an Accepted Request
An RPC reply message for a request accepted by the network server has the following structure:
structaccepted_replyareply{opaque_authverf;unionswitch(enumaccept_statstat){caseSUCCESS:opaqueresults{0};/*procedurespecificresultsstarthere*/casePROG_MISMATCH:struct{unsignedintlow;unsignedinthigh;}mismatch_info;default:void;}reply_data;};
The structures within the accepted reply are:
The accept_stat enumeration data type has the following definitions:
enumaccept_stat{SUCCESS=0,/*RPCexecutedsuccessfully*/PROG_UNAVAIL=1,/*remotehasnotexportedprogram*/PROG_MISMATCH=2,/*remotecannotsupportversion#*/PROC_UNAVAIL=3,/*programcannotsupportprocedure*/GARBAGE_ARGS=4,/*procedurecannotdecodeparams*/};
The structures within the accept_stat enumeration data type are defined as follows:
Note: An error condition can exist even when a call message is accepted by the server.
The Reply to a Rejected Request
A call message can be rejected by the server for two reasons: either the server is not running a compatible version of the RPC protocol, or there is an authentication failure.
An RPC reply message for a request rejected by the network server has the following structure:
structrejected_replyrreply{unionswitch(enumreject_statstat){caseRPC_MISMATCH:struct{unsignedintlow;unsignedinthigh;}mismatch_info;caseAUTH_ERROR:enumauth_statstat;};
The enumreject_stat discriminant acts as a switch between RPC_MISMATCH and AUTH_ERROR. The rejected call message returns one of the following status conditions:
enumreject_stat{RPC_MISMATCH=0,/*RPCversionnumberisnot2*/AUTH_ERROR=1,/*remotecannotauthenticatecaller*/};
Marking Records in RPC Messages
When RPC messages are passed using the TCP/IP byte-stream protocol for data transport, it is important to identify the end of one message and the start of the next one. This is called record marking (RM).
A record is composed of one or more record fragments. A record fragment is a four-byte header, followed by 0 to 232 -1 bytes of fragment data. The bytes encode an unsigned binary number, similar to XDR integers, in which the order of bytes is from highest to lowest. This binary number encodes a Boolean and an unsigned binary value of 31 bits.
The Boolean value is the highest-order bit of the header. A Boolean value of 1 indicates the last fragment of the record. The unsigned binary value is the length, in bytes, of the data fragment.
Note: A protocol disagreement between client and server can cause remote procedure parameters to be unintelligible to the server.