---
name: "rpc"
section: "3"
platform: "macos"
package: "Libinfo"
version: "600"
release: "macOS 26.5"
platforms: ["linux", "freebsd", "macos"]
url: "https://new.carta.tech/rpc"
---

# rpc(3)

library routines for remote procedure calls

## NAME

rpc - library routines for remote procedure calls

## SYNOPSIS AND DESCRIPTION

These routines allow C programs to make procedure calls on other machines across the network. First, the client calls a procedure to send a data packet to the server. Upon receipt of the packet, the server calls a dispatch routine to perform the requested service, and then sends back a reply. Finally, the procedure call returns to the client.

Routines that are used for Secure RPC (DES authentication) are described in **rpc\_secure**(3N). Secure RPC can be used only if DES encryption is available.

```

#include <rpc/rpc.h>
```

```

void
auth_destroy(auth)
AUTH *auth;
```

-

  A macro that destroys the authentication information associated with *auth*. Destruction usually involves deallocation of private data structures. The use of *auth* is undefined after calling **auth\_destroy()**.\

```

AUTH *
authnone_create()
```

-

  Create and returns an RPC authentication handle that passes nonusable authentication information with each remote procedure call. This is the default authentication used by RPC.

```

AUTH *
authunix_create(host, uid, gid, len, aup_gids)
char *host;
int uid, gid, len, *aup.gids;
```

-

  Create and return an RPC authentication handle that contains authentication information. The parameter *host* is the name of the machine on which the information was created; *uid* is the user's user ID ; *gid* is the user's current group ID ; *len* and *aup\_gids* refer to a counted array of groups to which the user belongs. It is easy to impersonate a user.\

```

AUTH *
authunix_create_default()
```

-

  Calls **authunix\_create()** with the appropriate parameters.\

```

callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
char *host;
u_long prognum, versnum, procnum;
char *in, *out;
xdrproc_t inproc, outproc;
```

-

  Call the remote procedure associated with *prognum*, *versnum*, and *procnum* on the machine, *host*. The parameter *in* is the address of the procedure's argument(s), and *out* is the address of where to place the result(s); *inproc* is used to encode the procedure's parameters, and *outproc* is used to decode the procedure's results. This routine returns zero if it succeeds, or the value of **enum clnt\_stat** cast to an integer if it fails. The routine **clnt\_perrno()** is handy for translating failure statuses into messages.

-

  Warning: calling remote procedures with this routine uses UDP/IP as a transport; see **clntudp\_create()** for restrictions. You do not have control of timeouts or authentication using this routine.\

```

enum clnt_stat
clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult)
u_long prognum, versnum, procnum;
char *in, *out;
xdrproc_t inproc, outproc;
resultproc_t eachresult;
```

-

  Like **callrpc()**, except the call message is broadcast to all locally connected broadcast nets. Each time it receives a response, this routine calls **eachresult()**, whose form is:

-

  ```
  eachresult(out, addr)
  char *out;
  struct sockaddr_in *addr;
  ```

-

  where *out* is the same as *out* passed to **clnt\_broadcast()**, except that the remote procedure's output is decoded there; *addr* points to the address of the machine that sent the results. If **eachresult()** returns zero, **clnt\_broadcast()** waits for more replies; otherwise it returns with appropriate status.

-

  Warning: broadcast sockets are limited in size to the maximum transfer unit of the data link. For ethernet, this value is 1500 bytes.\

```

enum clnt_stat
clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
CLIENT *clnt;
u_long
procnum;
xdrproc_t inproc, outproc;
char *in, *out;
struct timeval tout;
```

-

  A macro that calls the remote procedure *procnum* associated with the client handle, *clnt*, which is obtained with an RPC client creation routine such as **clnt\_create()**. The parameter *in* is the address of the procedure's argument(s), and *out* is the address of where to place the result(s); *inproc* is used to encode the procedure's parameters, and *outproc* is used to decode the procedure's results; *tout* is the time allowed for results to come back.\

```

clnt_destroy(clnt)
CLIENT *clnt;
```

-

  A macro that destroys the client's RPC handle. Destruction usually involves deallocation of private data structures, including *clnt* itself.  Use of *clnt* is undefined after calling **clnt\_destroy()**. If the RPC library opened the associated socket, it will close it also. Otherwise, the socket remains open.\

```

CLIENT *
clnt_create(host, prog, vers, proto)
char *host;
u_long prog, vers;
char *proto;
```

-

  Generic client creation routine. *host* identifies the name of the remote host where the server is located. *proto* indicates which kind of transport protocol to use. The currently supported values for this field are “udp” and “tcp”. Default timeouts are set, but can be modified using **clnt\_control()**.

-

  Warning: Using UDP has its shortcomings.  Since UDP-based RPC messages can only hold up to 8 Kbytes of encoded data, this transport cannot be used for procedures that take large arguments or return huge results.\

```

bool_t
clnt_control(cl, req, info)
CLIENT *cl;
char *info;
```

-

  A macro used to change or retrieve various information about a client object. *req* indicates the type of operation, and *info* is a pointer to the information. For both UDP and TCP, the supported values of *req* and their argument types and what they do are:

-

  ```
  CLSET_TIMEOUT struct timeval set total timeout
  CLGET_TIMEOUT struct timeval get total timeout
  ```

-

  Note: if you set the timeout using **clnt\_control()**, the timeout parameter passed to **clnt\_call()** will be ignored in all future calls.

-

  ```
  CLGET_SERVER_ADDR struct sockaddr_in get server's address
  ```

-

  The following operations are valid for UDP only:

-

  ```
  CLSET_RETRY_TIMEOUT struct timeval set the retry timeout
  CLGET_RETRY_TIMEOUT struct timeval get the retry timeout
  ```

-

  The retry timeout is the time that UDP RPC waits for the server to reply before retransmitting the request.\

```

clnt_freeres(clnt, outproc, out)
CLIENT *clnt;
xdrproc_t outproc;
char *out;
```

-

  A macro that frees any data allocated by the RPC/XDR system when it decoded the results of an RPC call.  The parameter *out* is the address of the results, and *outproc* is the XDR routine describing the results. This routine returns one if the results were successfully freed, and zero otherwise.\

```

void
clnt_geterr(clnt, errp)
CLIENT *clnt;
struct rpc_err *errp;
```

-

  A macro that copies the error structure out of the client handle to the structure at address *errp*.\

```

void
clnt_pcreateerror(s)
char *s;
```

-

  Print a message to standard error indicating why a client RPC handle could not be created. The message is prepended with string *s* and a colon. Used when a **clnt\_create()**, **clntraw\_create()**, **clnttcp\_create()**, or **clntudp\_create()** call fails.\

```

void
clnt_perrno(stat)
enum clnt_stat stat;
```

-

  Print a message to standard error corresponding to the condition indicated by *stat*. Used after **callrpc()**.\

```

clnt_perror(clnt, s)
CLIENT *clnt;
char *s;
```

-

  Print a message to standard error indicating why an RPC call failed; *clnt* is the handle used to do the call. The message is prepended with string *s* and a colon. Used after **clnt\_call()**.\

```

char *
clnt_spcreateerror
char *s;
```

-

  Like **clnt\_pcreateerror()**, except that it returns a string instead of printing to the standard error.

-

  Bugs: returns pointer to static data that is overwritten on each call.\

```

char *
clnt_sperrno(stat)
enum clnt_stat stat;
```

-

  Take the same arguments as **clnt\_perrno()**, but instead of sending a message to the standard error indicating why an RPC call failed, return a pointer to a string which contains the message.  The string ends with a NEWLINE.

-

  **clnt\_sperrno()** is used instead of **clnt\_perrno()** if the program does not have a standard error (as a program running as a server quite likely does not), or if the programmer does not want the message to be output with **printf**, or if a message format different than that supported by **clnt\_perrno()** is to be used. Note: unlike **clnt\_sperror()** and **clnt\_spcreaterror()**, **clnt\_sperrno()** returns pointer to static data, but the result will not get overwritten on each call.\

```

char *
clnt_sperror(rpch, s)
CLIENT *rpch;
char *s;
```

-

  Like **clnt\_perror()**, except that (like **clnt\_sperrno()**) it returns a string instead of printing to standard error.

-

  Bugs: returns pointer to static data that is overwritten on each call.\

```

CLIENT *
clntraw_create(prognum, versnum)
u_long prognum, versnum;
```

-

  This routine creates a toy RPC client for the remote program *prognum*, version *versnum*. The transport used to pass messages to the service is actually a buffer within the process's address space, so the corresponding RPC server should live in the same address space; see **svcraw\_create()**. This allows simulation of RPC and acquisition of RPC overheads, such as round trip times, without any kernel interference. This routine returns NULL if it fails.\

```

CLIENT *
clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz)
struct sockaddr_in *addr;
u_long prognum, versnum;
int *sockp;
u_int sendsz, recvsz;
```

-

  This routine creates an RPC client for the remote program *prognum*, version *versnum*; the client uses TCP/IP as a transport. The remote program is located at Internet address *\*addr*. If **addr-\>sin\_port** is zero, then it is set to the actual port that the remote program is listening on (the remote **portmap** service is consulted for this information). The parameter *sockp* is a socket; if it is **RPC\_ANYSOCK**, then this routine opens a new one and sets *sockp*. Since TCP-based RPC uses buffered I/O , the user may specify the size of the send and receive buffers with the parameters *sendsz* and *recvsz*; values of zero choose suitable defaults. This routine returns NULL if it fails.\

```

CLIENT *
clntudp_create(addr, prognum, versnum, wait, sockp)
struct sockaddr_in *addr;
u_long prognum, versnum;
struct timeval wait;
int *sockp;
```

-

  This routine creates an RPC client for the remote program *prognum*, version *versnum*; the client uses use UDP/IP as a transport. The remote program is located at Internet address *addr*. If **addr-\>sin\_port** is zero, then it is set to actual port that the remote program is listening on (the remote **portmap** service is consulted for this information). The parameter *sockp* is a socket; if it is **RPC\_ANYSOCK**, then this routine opens a new one and sets *sockp*. The UDP transport resends the call message in intervals of **wait** time until a response is received or until the call times out. The total time for the call to time out is specified by **clnt\_call()**.

-

  Warning: since UDP-based RPC messages can only hold up to 8 Kbytes of encoded data, this transport cannot be used for procedures that take large arguments or return huge results.\

```

CLIENT *
clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize)
struct sockaddr_in *addr;
u_long prognum, versnum;
struct timeval wait;
int *sockp;
unsigned int sendsize;
unsigned int recosize;
```

-

  This routine creates an RPC client for the remote program *prognum*, on *versnum*; the client uses use UDP/IP as a transport. The remote program is located at Internet address *addr*. If **addr-\>sin\_port** is zero, then it is set to actual port that the remote program is listening on (the remote **portmap** service is consulted for this information). The parameter *sockp* is a socket; if it is **RPC\_ANYSOCK**, then this routine opens a new one and sets **sockp**. The UDP transport resends the call message in intervals of **wait** time until a response is received or until the call times out. The total time for the call to time out is specified by **clnt\_call()**.

-

  This allows the user to specify the maximun packet size for sending and receiving  UDP-based RPC messages.\

```

void
get_myaddress(addr)
struct sockaddr_in *addr;
```

-

  Stuff the machine's IP address into *\*addr*, without consulting the library routines that deal with **/etc/hosts**. The port number is always set to **htons(PMAPPORT)**.\

```

struct pmaplist *
pmap_getmaps(addr)
struct sockaddr_in *addr;
```

-

  A user interface to the **portmap** service, which returns a list of the current RPC program-to-port mappings on the host located at IP address *\*addr*. This routine can return NULL . The command \`**rpcinfo -p**' uses this routine.\

```

u_short
pmap_getport(addr, prognum, versnum, protocol)
struct sockaddr_in *addr;
u_long prognum, versnum, protocol;
```

-

  A user interface to the **portmap** service, which returns the port number on which waits a service that supports program number *prognum*, version *versnum*, and speaks the transport protocol associated with *protocol*. The value of *protocol* is most likely IPPROTO\_UDP **or**  **IPPROTO\_TCP**. A return value of zero means that the mapping does not exist or that the RPC system failured to contact the remote **portmap** service.  In the latter case, the global variable **rpc\_createerr()** contains the RPC status.\

```

enum clnt_stat
pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp)
struct sockaddr_in *addr;
u_long prognum, versnum, procnum;
char *in, *out;
xdrproc_t inproc, outproc;
struct timeval tout;
u_long *portp;
```

-

  A user interface to the **portmap** service, which instructs **portmap** on the host at IP address *\*addr* to make an RPC call on your behalf to a procedure on that host. The parameter *\*portp* will be modified to the program's port number if the procedure succeeds. The definitions of other parameters are discussed in **callrpc()** and **clnt\_call()**. This procedure should be used for a “ping” and nothing else. See also **clnt\_broadcast()**.\

```

pmap_set(prognum, versnum, protocol, port)
u_long prognum, versnum, protocol;
u_short port;
```

-

  A user interface to the **portmap** service, which establishes a mapping between the triple \[*prognum*,*versnum*,*protocol\]* and *port* on the machine's **portmap** service. The value of *protocol* is most likely IPPROTO\_UDP **or**  **IPPROTO\_TCP**. This routine returns one if it succeeds, zero otherwise. Automatically done by **svc\_register()**.\

```

pmap_unset(prognum, versnum)
u_long prognum, versnum;
```

-

  A user interface to the **portmap** service, which destroys all mapping between the triple \[*prognum*,*versnum*,*\*\]* and **ports** on the machine's **portmap** service. This routine returns one if it succeeds, zero otherwise.\

```

registerrpc(prognum, versnum, procnum, procname, inproc, outproc)
u_long prognum, versnum, procnum;
char *(*procname) () ;
xdrproc_t inproc, outproc;
```

-

  Register procedure *procname* with the RPC service package.  If a request arrives for program *prognum*, version *versnum*, and procedure *procnum*, *procname* is called with a pointer to its parameter(s); *progname* should return a pointer to its static result(s); *inproc* is used to decode the parameters while *outproc* is used to encode the results. This routine returns zero if the registration succeeded, -1 otherwise.

-

  Warning: remote procedures registered in this form are accessed using the UDP/IP transport; see **svcudp\_create()** for restrictions.\

```

struct rpc_createerr     rpc_createerr;
```

-

  A global variable whose value is set by any RPC client creation routine that does not succeed.  Use the routine **clnt\_pcreateerror()** to print the reason why.

```

svc_destroy(xprt)
SVCXPRT *
xprt;
```

-

  A macro that destroys the RPC service transport handle, *xprt*. Destruction usually involves deallocation of private data structures, including *xprt* itself.  Use of *xprt* is undefined after calling this routine.\

```

fd_set svc_fdset;
```

-

  A global variable reflecting the RPC service side's read file descriptor bit mask; it is suitable as a parameter to the **select** system call. This is only of interest if a service implementor does not call **svc\_run()**, but rather does his own asynchronous event processing. This variable is read-only (do not pass its address to **select**!), yet it may change after calls to **svc\_getreqset()** or any creation routines.\

```

int svc_fds;
```

-

  Similar to **svc\_fedset()**, but limited to 32 descriptors. This interface is obsoleted by **svc\_fdset()**.\

```

svc_freeargs(xprt, inproc, in)
SVCXPRT *xprt;
xdrproc_t inproc;
char *in;
```

-

  A macro that frees any data allocated by the RPC/XDR system when it decoded the arguments to a service procedure using **svc\_getargs()**. This routine returns 1 if the results were successfully freed, and zero otherwise.\

```

svc_getargs(xprt, inproc, in)
SVCXPRT *xprt;
xdrproc_t inproc;
char *in;
```

-

  A macro that decodes the arguments of an RPC request associated with the RPC service transport handle, *xprt*. The parameter *in* is the address where the arguments will be placed; *inproc* is the XDR routine used to decode the arguments. This routine returns one if decoding succeeds, and zero otherwise.\

```

struct sockaddr_in *
svc_getcaller(xprt)
SVCXPRT *xprt;
```

-

  The approved way of getting the network address of the caller of a procedure associated with the RPC service transport handle, *xprt*.\

```

svc_getreqset(rdfds)
fd_set *rdfds;
```

-

  This routine is only of interest if a service implementor does not call **svc\_run()**, but instead implements custom asynchronous event processing. It is called when the **select** system call has determined that an RPC request has arrived on some RPC **socket(s) ;** *rdfds* is the resultant read file descriptor bit mask. The routine returns when all sockets associated with the value of *rdfds* have been serviced.\

```

svc_getreq(rdfds)
int rdfds;
```

-

  Similar to **svc\_getreqset()**, but limited to 32 descriptors. This interface is obsoleted by **svc\_getreqset()**.\

```

svc_register(xprt, prognum, versnum, dispatch, protocol)
SVCXPRT *xprt;
u_long prognum, versnum;
void (*dispatch) ();
u_long protocol;
```

-

  Associates *prognum* and *versnum* with the service dispatch procedure, *dispatch*. If *protocol* is zero, the service is not registered with the **portmap** service.  If *protocol* is non-zero, then a mapping of the triple \[*prognum*,*versnum*,*protocol\]* to **xprt-\>xp\_port** is established with the local **portmap** service (generally *protocol* is zero, IPPROTO\_UDP **or**  IPPROTO\_TCP **).** The procedure *dispatch* has the following form:

  ```
  dispatch(request, xprt)
  struct svc_req *request;
  SVCXPRT *xprt;
  ```

-

  The **svc\_register()** routine returns one if it succeeds, and zero otherwise.\

```

svc_run()
```

-

  This routine never returns. It waits for RPC requests to arrive, and calls the appropriate service procedure using **svc\_getreq()** when one arrives. This procedure is usually waiting for a **select()** system call to return.\

```

svc_sendreply(xprt, outproc, out)
SVCXPRT *xprt;
xdrproc_t outproc;
char *out;
```

-

  Called by an RPC service's dispatch routine to send the results of a remote procedure call.  The parameter *xprt* is the request's associated transport handle; *outproc* is the XDR routine which is used to encode the results; and *out* is the address of the results. This routine returns one if it succeeds, zero otherwise.\

```

void
svc_unregister(prognum, versnum)
u_long prognum, versnum;
```

-

  Remove all mapping of the double \[*prognum*,*versnum*\] to dispatch routines, and of the triple \[*prognum*,*versnum*,*\*\]* to port number.\

```

void
svcerr_auth(xprt, why)
SVCXPRT *xprt;
enum auth_stat why;
```

-

  Called by a service dispatch routine that refuses to perform a remote procedure call due to an authentication error.\

```

void
svcerr_decode(xprt)
SVCXPRT *xprt;
```

-

  Called by a service dispatch routine that cannot successfully decode its parameters. See also **svc\_getargs()**.\

```

void
svcerr_noproc(xprt)
SVCXPRT *xprt;
```

-

  Called by a service dispatch routine that does not implement the procedure number that the caller requests.\

```

void
svcerr_noprog(xprt)
SVCXPRT *xprt;
```

-

  Called when the desired program is not registered with the RPC package. Service implementors usually do not need this routine.\

```

void
svcerr_progvers(xprt)
SVCXPRT *xprt;
```

-

  Called when the desired version of a program is not registered with the RPC package. Service implementors usually do not need this routine.\

```

void
svcerr_systemerr(xprt)
SVCXPRT *xprt;
```

-

  Called by a service dispatch routine when it detects a system error not covered by any particular protocol. For example, if a service can no longer allocate storage, it may call this routine.\

```

void
svcerr_weakauth(xprt)
SVCXPRT *xprt;
```

-

  Called by a service dispatch routine that refuses to perform a remote procedure call due to insufficient authentication parameters.  The routine calls **svcerr\_auth(xprt, AUTH\_TOOWEAK)**.\

```

SVCXPRT *
svcraw_create()
```

-

  This routine creates a toy RPC service transport, to which it returns a pointer.  The transport is really a buffer within the process's address space, so the corresponding RPC client should live in the same address space; see **clntraw\_create()**. This routine allows simulation of RPC and acquisition of RPC overheads (such as round trip times), without any kernel interference. This routine returns NULL if it fails.\

```

SVCXPRT *
svctcp_create(sock, send_buf_size, recv_buf_size)
int sock;
u_int send_buf_size, recv_buf_size;
```

-

  This routine creates a TCP/IP-based RPC service transport, to which it returns a pointer. The transport is associated with the socket *sock*, which may be **RPC\_ANYSOCK**, in which case a new socket is created. If the socket is not bound to a local TCP port, then this routine binds it to an arbitrary port.  Upon completion, **xprt-\>xp\_sock** is the transport's socket descriptor, and **xprt-\>xp\_port** is the transport's port number. This routine returns NULL if it fails. Since TCP-based RPC uses buffered I/O , users may specify the size of buffers; values of zero choose suitable defaults.\

```

SVCXPRT *
svcfd_create(fd, sendsize, recvsize)
int fd;
u_int sendsize;
u_int recvsize;
```

-

  Create a service on top of any open descriptor. Typically, this descriptor is a connected socket for a stream protocol such as TCP. *sendsize* and *recvsize* indicate sizes for the send and receive buffers.  If they are zero, a reasonable default is chosen.\

```

SVCXPRT *
svcudp_bufcreate(sock, sendsize, recosize)
int sock;
```

-

  This routine creates a UDP/IP-based RPC service transport, to which it returns a pointer. The transport is associated with the socket *sock*, which may be **RPC\_ANYSOCK ,** in which case a new socket is created. If the socket is not bound to a local UDP port, then this routine binds it to an arbitrary port. Upon completion, **xprt-\>xp\_sock** is the transport's socket descriptor, and **xprt-\>xp\_port** is the transport's port number. This routine returns NULL if it fails.

-

  This allows the user to specify the maximun packet size for sending and  receiving UDP-based RPC messages.\

```

xdr_accepted_reply(xdrs, ar)
XDR *xdrs;
struct accepted_reply *ar;
```

-

  Used for encoding RPC reply messages. This routine is useful for users who wish to generate RPC-style messages without using the RPC package.\

```

xdr_authunix_parms(xdrs, aupp)
XDR *xdrs;
struct authunix_parms *aupp;
```

-

  Used for describing UNIX credentials. This routine is useful for users who wish to generate these credentials without using the RPC authentication package.\

```

void
xdr_callhdr(xdrs, chdr)
XDR *xdrs;
struct rpc_msg *chdr;
```

-

  Used for describing RPC call header messages. This routine is useful for users who wish to generate RPC-style messages without using the RPC package.\

```

xdr_callmsg(xdrs, cmsg)
XDR *xdrs;
struct rpc_msg *cmsg;
```

-

  Used for describing RPC call messages. This routine is useful for users who wish to generate RPC-style messages without using the RPC package.\

```

xdr_opaque_auth(xdrs, ap)
XDR *xdrs;
struct opaque_auth *ap;
```

-

  Used for describing RPC authentication information messages. This routine is useful for users who wish to generate RPC-style messages without using the RPC package.\

```

xdr_pmap(xdrs, regs)
XDR *xdrs;
struct pmap *regs;
```

-

  Used for describing parameters to various **portmap** procedures, externally. This routine is useful for users who wish to generate these parameters without using the **pmap** interface.\

```

xdr_pmaplist(xdrs, rp)
XDR *xdrs;
struct pmaplist **rp;
```

-

  Used for describing a list of port mappings, externally. This routine is useful for users who wish to generate these parameters without using the **pmap** interface.\

```

xdr_rejected_reply(xdrs, rr)
XDR *xdrs;
struct rejected_reply *rr;
```

-

  Used for describing RPC reply messages. This routine is useful for users who wish to generate RPC-style messages without using the RPC package.\

```

xdr_replymsg(xdrs, rmsg)
XDR *xdrs;
struct rpc_msg *rmsg;
```

-

  Used for describing RPC reply messages. This routine is useful for users who wish to generate RPC style messages without using the RPC package.\

```

void
xprt_register(xprt)
SVCXPRT *xprt;
```

-

  After RPC service transport handles are created, they should register themselves with the RPC service package. This routine modifies the global variable **svc\_fds()**. Service implementors usually do not need this routine.\

```

void
xprt_unregister(xprt)
SVCXPRT *xprt;
```

-

  Before an RPC service transport handle is destroyed, it should unregister itself with the RPC service package. This routine modifies the global variable **svc\_fds()**. Service implementors usually do not need this routine.

## SEE ALSO

**rpc\_secure**(3N), **xdr**(3N)\
 The following manuals:

*Remote Procedure Calls: Protocol Specification*\
 *Remote Procedure Call Programming Guide*\
 *rpcgen Programming Guide*\

*RPC: Remote Procedure Call Protocol Specification*, RFC1050, Sun Microsystems, Inc., USC-ISI.
