2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
25 * Sun Microsystems, Inc.
27 * Mountain View, California 94043
29 * @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro
30 * @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC
31 * $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $
32 * $FreeBSD: src/lib/libc/rpc/rpc_prot.c,v 1.13 2007/11/20 01:51:20 jb Exp $
33 * $DragonFly: src/lib/libc/rpc/rpc_prot.c,v 1.4 2005/11/13 12:27:04 swildner Exp $
39 * Copyright (C) 1984, Sun Microsystems, Inc.
41 * This set of routines implements the rpc message definition,
42 * its serializer and some common rpc utility routines.
43 * The routines are meant for various implementations of rpc -
44 * they are NOT for the rpc client or rpc service implementations!
45 * Because authentication stuff is easy and is part of rpc, the opaque
46 * routines are also in this program.
49 #include "namespace.h"
50 #include <sys/param.h>
55 #include "un-namespace.h"
57 static void accepted(enum accept_stat
, struct rpc_err
*);
58 static void rejected(enum reject_stat
, struct rpc_err
*);
60 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
62 extern struct opaque_auth _null_auth
;
65 * XDR an opaque authentication struct
69 xdr_opaque_auth(XDR
*xdrs
, struct opaque_auth
*ap
)
75 if (xdr_enum(xdrs
, &(ap
->oa_flavor
)))
76 return (xdr_bytes(xdrs
, &ap
->oa_base
,
77 &ap
->oa_length
, MAX_AUTH_BYTES
));
85 xdr_des_block(XDR
*xdrs
, des_block
*blkp
)
91 return (xdr_opaque(xdrs
, (caddr_t
)(void *)blkp
, sizeof(des_block
)));
94 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
97 * XDR the MSG_ACCEPTED part of a reply message union
100 xdr_accepted_reply(XDR
*xdrs
, struct accepted_reply
*ar
)
102 enum accept_stat
*par_stat
;
104 assert(xdrs
!= NULL
);
107 par_stat
= &ar
->ar_stat
;
109 /* personalized union, rather than calling xdr_union */
110 if (! xdr_opaque_auth(xdrs
, &(ar
->ar_verf
)))
112 if (! xdr_enum(xdrs
, (enum_t
*) par_stat
))
114 switch (ar
->ar_stat
) {
117 return ((*(ar
->ar_results
.proc
))(xdrs
, ar
->ar_results
.where
));
120 if (! xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.low
)))
122 return (xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.high
)));
130 return (TRUE
); /* TRUE => open ended set of problems */
134 * XDR the MSG_DENIED part of a reply message union
137 xdr_rejected_reply(XDR
*xdrs
, struct rejected_reply
*rr
)
139 enum reject_stat
*prj_stat
;
140 enum auth_stat
*prj_why
;
142 assert(xdrs
!= NULL
);
145 prj_stat
= &rr
->rj_stat
;
147 /* personalized union, rather than calling xdr_union */
148 if (! xdr_enum(xdrs
, (enum_t
*) prj_stat
))
150 switch (rr
->rj_stat
) {
153 if (! xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.low
)))
155 return (xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.high
)));
158 prj_why
= &rr
->rj_why
;
159 return (xdr_enum(xdrs
, (enum_t
*) prj_why
));
166 static const struct xdr_discrim reply_dscrm
[3] = {
167 { (int)MSG_ACCEPTED
, (xdrproc_t
)xdr_accepted_reply
},
168 { (int)MSG_DENIED
, (xdrproc_t
)xdr_rejected_reply
},
169 { __dontcare__
, NULL_xdrproc_t
} };
172 * XDR a reply message
175 xdr_replymsg(XDR
*xdrs
, struct rpc_msg
*rmsg
)
177 enum msg_type
*prm_direction
;
178 enum reply_stat
*prp_stat
;
180 assert(xdrs
!= NULL
);
181 assert(rmsg
!= NULL
);
183 prm_direction
= &rmsg
->rm_direction
;
184 prp_stat
= &rmsg
->rm_reply
.rp_stat
;
187 xdr_u_int32_t(xdrs
, &(rmsg
->rm_xid
)) &&
188 xdr_enum(xdrs
, (enum_t
*) prm_direction
) &&
189 (rmsg
->rm_direction
== REPLY
) )
190 return (xdr_union(xdrs
, (enum_t
*) prp_stat
,
191 (caddr_t
)(void *)&(rmsg
->rm_reply
.ru
), reply_dscrm
,
198 * Serializes the "static part" of a call message header.
199 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
200 * The rm_xid is not really static, but the user can easily munge on the fly.
203 xdr_callhdr(XDR
*xdrs
, struct rpc_msg
*cmsg
)
205 enum msg_type
*prm_direction
;
207 assert(xdrs
!= NULL
);
208 assert(cmsg
!= NULL
);
210 prm_direction
= &cmsg
->rm_direction
;
212 cmsg
->rm_direction
= CALL
;
213 cmsg
->rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
215 (xdrs
->x_op
== XDR_ENCODE
) &&
216 xdr_u_int32_t(xdrs
, &(cmsg
->rm_xid
)) &&
217 xdr_enum(xdrs
, (enum_t
*) prm_direction
) &&
218 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_rpcvers
)) &&
219 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_prog
)) )
220 return (xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_vers
)));
224 /* ************************** Client utility routine ************* */
227 accepted(enum accept_stat acpt_stat
, struct rpc_err
*error
)
230 assert(error
!= NULL
);
235 error
->re_status
= RPC_PROGUNAVAIL
;
239 error
->re_status
= RPC_PROGVERSMISMATCH
;
243 error
->re_status
= RPC_PROCUNAVAIL
;
247 error
->re_status
= RPC_CANTDECODEARGS
;
251 error
->re_status
= RPC_SYSTEMERROR
;
255 error
->re_status
= RPC_SUCCESS
;
259 /* something's wrong, but we don't know what ... */
260 error
->re_status
= RPC_FAILED
;
261 error
->re_lb
.s1
= (int32_t)MSG_ACCEPTED
;
262 error
->re_lb
.s2
= (int32_t)acpt_stat
;
266 rejected(enum reject_stat rjct_stat
, struct rpc_err
*error
)
269 assert(error
!= NULL
);
273 error
->re_status
= RPC_VERSMISMATCH
;
277 error
->re_status
= RPC_AUTHERROR
;
280 /* something's wrong, but we don't know what ... */
282 error
->re_status
= RPC_FAILED
;
283 error
->re_lb
.s1
= (int32_t)MSG_DENIED
;
284 error
->re_lb
.s2
= (int32_t)rjct_stat
;
288 * given a reply message, fills in the error
291 _seterr_reply(struct rpc_msg
*msg
, struct rpc_err
*error
)
295 assert(error
!= NULL
);
297 /* optimized for normal, SUCCESSful case */
298 switch (msg
->rm_reply
.rp_stat
) {
301 if (msg
->acpted_rply
.ar_stat
== SUCCESS
) {
302 error
->re_status
= RPC_SUCCESS
;
305 accepted(msg
->acpted_rply
.ar_stat
, error
);
309 rejected(msg
->rjcted_rply
.rj_stat
, error
);
313 error
->re_status
= RPC_FAILED
;
314 error
->re_lb
.s1
= (int32_t)(msg
->rm_reply
.rp_stat
);
317 switch (error
->re_status
) {
319 case RPC_VERSMISMATCH
:
320 error
->re_vers
.low
= msg
->rjcted_rply
.rj_vers
.low
;
321 error
->re_vers
.high
= msg
->rjcted_rply
.rj_vers
.high
;
325 error
->re_why
= msg
->rjcted_rply
.rj_why
;
328 case RPC_PROGVERSMISMATCH
:
329 error
->re_vers
.low
= msg
->acpted_rply
.ar_vers
.low
;
330 error
->re_vers
.high
= msg
->acpted_rply
.ar_vers
.high
;
335 case RPC_PROGNOTREGISTERED
:
336 case RPC_PMAPFAILURE
:
337 case RPC_UNKNOWNPROTO
:
338 case RPC_UNKNOWNHOST
:
339 case RPC_SYSTEMERROR
:
340 case RPC_CANTDECODEARGS
:
341 case RPC_PROCUNAVAIL
:
342 case RPC_PROGUNAVAIL
:
346 case RPC_CANTDECODERES
:
347 case RPC_CANTENCODEARGS
: