1 /* $NetBSD: rpc_prot.c,v 1.18 2003/05/29 18:15:25 christos Exp $ */
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
27 * Sun Microsystems, Inc.
29 * Mountain View, California 94043
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
35 static char *sccsid
= "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
36 static char *sccsid
= "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";
38 __RCSID("$NetBSD: rpc_prot.c,v 1.18 2003/05/29 18:15:25 christos Exp $");
45 * Copyright (C) 1984, Sun Microsystems, Inc.
47 * This set of routines implements the rpc message definition,
48 * its serializer and some common rpc utility routines.
49 * The routines are meant for various implementations of rpc -
50 * they are NOT for the rpc client or rpc service implementations!
51 * Because authentication stuff is easy and is part of rpc, the opaque
52 * routines are also in this program.
55 #include "namespace.h"
57 #include <sys/param.h>
64 __weak_alias(xdr_accepted_reply
,_xdr_accepted_reply
)
65 __weak_alias(xdr_callhdr
,_xdr_callhdr
)
66 __weak_alias(xdr_des_block
,_xdr_des_block
)
67 __weak_alias(xdr_opaque_auth
,_xdr_opaque_auth
)
68 __weak_alias(xdr_rejected_reply
,_xdr_rejected_reply
)
69 __weak_alias(xdr_replymsg
,_xdr_replymsg
)
72 static void accepted
__P((enum accept_stat
, struct rpc_err
*));
73 static void rejected
__P((enum reject_stat
, struct rpc_err
*));
75 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
78 * XDR an opaque authentication struct
82 xdr_opaque_auth(xdrs
, ap
)
84 struct opaque_auth
*ap
;
87 _DIAGASSERT(xdrs
!= NULL
);
88 _DIAGASSERT(ap
!= NULL
);
90 if (xdr_enum(xdrs
, &(ap
->oa_flavor
)))
91 return (xdr_bytes(xdrs
, &ap
->oa_base
,
92 &ap
->oa_length
, MAX_AUTH_BYTES
));
100 xdr_des_block(xdrs
, blkp
)
105 _DIAGASSERT(xdrs
!= NULL
);
106 _DIAGASSERT(blkp
!= NULL
);
108 return (xdr_opaque(xdrs
, (caddr_t
)(void *)blkp
, sizeof(des_block
)));
111 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
114 * XDR the MSG_ACCEPTED part of a reply message union
117 xdr_accepted_reply(xdrs
, ar
)
119 struct accepted_reply
*ar
;
122 _DIAGASSERT(xdrs
!= NULL
);
123 _DIAGASSERT(ar
!= NULL
);
125 /* personalized union, rather than calling xdr_union */
126 if (! xdr_opaque_auth(xdrs
, &(ar
->ar_verf
)))
128 if (! xdr_enum(xdrs
, (enum_t
*)(void *)&(ar
->ar_stat
)))
130 switch (ar
->ar_stat
) {
133 return ((*(ar
->ar_results
.proc
))(xdrs
, ar
->ar_results
.where
));
136 if (! xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.low
)))
138 return (xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.high
)));
146 return (TRUE
); /* TRUE => open ended set of problems */
150 * XDR the MSG_DENIED part of a reply message union
153 xdr_rejected_reply(xdrs
, rr
)
155 struct rejected_reply
*rr
;
158 _DIAGASSERT(xdrs
!= NULL
);
159 _DIAGASSERT(rr
!= NULL
);
161 /* personalized union, rather than calling xdr_union */
162 if (! xdr_enum(xdrs
, (enum_t
*)(void *)&(rr
->rj_stat
)))
164 switch (rr
->rj_stat
) {
167 if (! xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.low
)))
169 return (xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.high
)));
172 return (xdr_enum(xdrs
, (enum_t
*)(void *)&(rr
->rj_why
)));
178 static const struct xdr_discrim reply_dscrm
[3] = {
179 { (int)MSG_ACCEPTED
, (xdrproc_t
)xdr_accepted_reply
},
180 { (int)MSG_DENIED
, (xdrproc_t
)xdr_rejected_reply
},
181 { __dontcare__
, NULL_xdrproc_t
} };
184 * XDR a reply message
187 xdr_replymsg(xdrs
, rmsg
)
189 struct rpc_msg
*rmsg
;
191 _DIAGASSERT(xdrs
!= NULL
);
192 _DIAGASSERT(rmsg
!= NULL
);
195 xdr_u_int32_t(xdrs
, &(rmsg
->rm_xid
)) &&
196 xdr_enum(xdrs
, (enum_t
*)(void *)&(rmsg
->rm_direction
)) &&
197 (rmsg
->rm_direction
== REPLY
) )
198 return (xdr_union(xdrs
, (enum_t
*)(void *)&(rmsg
->rm_reply
.rp_stat
),
199 (caddr_t
)(void *)&(rmsg
->rm_reply
.ru
), reply_dscrm
,
206 * Serializes the "static part" of a call message header.
207 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
208 * The rm_xid is not really static, but the user can easily munge on the fly.
211 xdr_callhdr(xdrs
, cmsg
)
213 struct rpc_msg
*cmsg
;
216 _DIAGASSERT(xdrs
!= NULL
);
217 _DIAGASSERT(cmsg
!= NULL
);
219 cmsg
->rm_direction
= CALL
;
220 cmsg
->rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
222 (xdrs
->x_op
== XDR_ENCODE
) &&
223 xdr_u_int32_t(xdrs
, &(cmsg
->rm_xid
)) &&
224 xdr_enum(xdrs
, (enum_t
*)(void *)&(cmsg
->rm_direction
)) &&
225 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_rpcvers
)) &&
226 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_prog
)) )
227 return (xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_vers
)));
231 /* ************************** Client utility routine ************* */
234 accepted(acpt_stat
, error
)
235 enum accept_stat acpt_stat
;
236 struct rpc_err
*error
;
239 _DIAGASSERT(error
!= NULL
);
244 error
->re_status
= RPC_PROGUNAVAIL
;
248 error
->re_status
= RPC_PROGVERSMISMATCH
;
252 error
->re_status
= RPC_PROCUNAVAIL
;
256 error
->re_status
= RPC_CANTDECODEARGS
;
260 error
->re_status
= RPC_SYSTEMERROR
;
264 error
->re_status
= RPC_SUCCESS
;
268 /* something's wrong, but we don't know what ... */
269 error
->re_status
= RPC_FAILED
;
270 error
->re_lb
.s1
= (int32_t)MSG_ACCEPTED
;
271 error
->re_lb
.s2
= (int32_t)acpt_stat
;
275 rejected(rjct_stat
, error
)
276 enum reject_stat rjct_stat
;
277 struct rpc_err
*error
;
280 _DIAGASSERT(error
!= NULL
);
284 error
->re_status
= RPC_VERSMISMATCH
;
288 error
->re_status
= RPC_AUTHERROR
;
291 /* something's wrong, but we don't know what ... */
293 error
->re_status
= RPC_FAILED
;
294 error
->re_lb
.s1
= (int32_t)MSG_DENIED
;
295 error
->re_lb
.s2
= (int32_t)rjct_stat
;
299 * given a reply message, fills in the error
302 _seterr_reply(msg
, error
)
304 struct rpc_err
*error
;
307 _DIAGASSERT(msg
!= NULL
);
308 _DIAGASSERT(error
!= NULL
);
310 /* optimized for normal, SUCCESSful case */
311 switch (msg
->rm_reply
.rp_stat
) {
314 if (msg
->acpted_rply
.ar_stat
== SUCCESS
) {
315 error
->re_status
= RPC_SUCCESS
;
318 accepted(msg
->acpted_rply
.ar_stat
, error
);
322 rejected(msg
->rjcted_rply
.rj_stat
, error
);
326 error
->re_status
= RPC_FAILED
;
327 error
->re_lb
.s1
= (int32_t)(msg
->rm_reply
.rp_stat
);
330 switch (error
->re_status
) {
332 case RPC_VERSMISMATCH
:
333 error
->re_vers
.low
= msg
->rjcted_rply
.rj_vers
.low
;
334 error
->re_vers
.high
= msg
->rjcted_rply
.rj_vers
.high
;
338 error
->re_why
= msg
->rjcted_rply
.rj_why
;
341 case RPC_PROGVERSMISMATCH
:
342 error
->re_vers
.low
= msg
->acpted_rply
.ar_vers
.low
;
343 error
->re_vers
.high
= msg
->acpted_rply
.ar_vers
.high
;
348 case RPC_PROGNOTREGISTERED
:
349 case RPC_PMAPFAILURE
:
350 case RPC_UNKNOWNPROTO
:
351 case RPC_UNKNOWNHOST
:
352 case RPC_SYSTEMERROR
:
353 case RPC_CANTDECODEARGS
:
354 case RPC_PROCUNAVAIL
:
355 case RPC_PROGUNAVAIL
:
359 case RPC_CANTDECODERES
:
360 case RPC_CANTENCODEARGS
: