1 /* $NetBSD: rpc_prot.c,v 1.21 2013/03/11 20:19:29 tron Exp $ */
4 * Copyright (c) 2010, Oracle America, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 #if defined(LIBC_SCCS) && !defined(lint)
37 static char *sccsid
= "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
38 static char *sccsid
= "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";
40 __RCSID("$NetBSD: rpc_prot.c,v 1.21 2013/03/11 20:19:29 tron Exp $");
47 * Copyright (C) 1984, Sun Microsystems, Inc.
49 * This set of routines implements the rpc message definition,
50 * its serializer and some common rpc utility routines.
51 * The routines are meant for various implementations of rpc -
52 * they are NOT for the rpc client or rpc service implementations!
53 * Because authentication stuff is easy and is part of rpc, the opaque
54 * routines are also in this program.
57 #include "namespace.h"
59 #include <sys/param.h>
66 __weak_alias(xdr_accepted_reply
,_xdr_accepted_reply
)
67 __weak_alias(xdr_callhdr
,_xdr_callhdr
)
68 __weak_alias(xdr_des_block
,_xdr_des_block
)
69 __weak_alias(xdr_opaque_auth
,_xdr_opaque_auth
)
70 __weak_alias(xdr_rejected_reply
,_xdr_rejected_reply
)
71 __weak_alias(xdr_replymsg
,_xdr_replymsg
)
74 static void accepted(enum accept_stat
, struct rpc_err
*);
75 static void rejected(enum reject_stat
, struct rpc_err
*);
77 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
80 * XDR an opaque authentication struct
84 xdr_opaque_auth(XDR
*xdrs
, 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(XDR
*xdrs
, des_block
*blkp
)
103 _DIAGASSERT(xdrs
!= NULL
);
104 _DIAGASSERT(blkp
!= NULL
);
106 return (xdr_opaque(xdrs
, (caddr_t
)(void *)blkp
,
107 (u_int
)sizeof(des_block
)));
110 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
113 * XDR the MSG_ACCEPTED part of a reply message union
116 xdr_accepted_reply(XDR
*xdrs
, struct accepted_reply
*ar
)
119 _DIAGASSERT(xdrs
!= NULL
);
120 _DIAGASSERT(ar
!= NULL
);
122 /* personalized union, rather than calling xdr_union */
123 if (! xdr_opaque_auth(xdrs
, &(ar
->ar_verf
)))
125 if (! xdr_enum(xdrs
, (enum_t
*)(void *)&(ar
->ar_stat
)))
127 switch (ar
->ar_stat
) {
130 return ((*(ar
->ar_results
.proc
))(xdrs
, ar
->ar_results
.where
));
133 if (! xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.low
)))
135 return (xdr_u_int32_t(xdrs
, &(ar
->ar_vers
.high
)));
143 return (TRUE
); /* TRUE => open ended set of problems */
147 * XDR the MSG_DENIED part of a reply message union
150 xdr_rejected_reply(XDR
*xdrs
, struct rejected_reply
*rr
)
153 _DIAGASSERT(xdrs
!= NULL
);
154 _DIAGASSERT(rr
!= NULL
);
156 /* personalized union, rather than calling xdr_union */
157 if (! xdr_enum(xdrs
, (enum_t
*)(void *)&(rr
->rj_stat
)))
159 switch (rr
->rj_stat
) {
162 if (! xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.low
)))
164 return (xdr_u_int32_t(xdrs
, &(rr
->rj_vers
.high
)));
167 return (xdr_enum(xdrs
, (enum_t
*)(void *)&(rr
->rj_why
)));
173 static const struct xdr_discrim reply_dscrm
[3] = {
174 { (int)MSG_ACCEPTED
, (xdrproc_t
)xdr_accepted_reply
},
175 { (int)MSG_DENIED
, (xdrproc_t
)xdr_rejected_reply
},
176 { __dontcare__
, NULL_xdrproc_t
} };
179 * XDR a reply message
182 xdr_replymsg(XDR
*xdrs
, struct rpc_msg
*rmsg
)
184 _DIAGASSERT(xdrs
!= NULL
);
185 _DIAGASSERT(rmsg
!= NULL
);
188 xdr_u_int32_t(xdrs
, &(rmsg
->rm_xid
)) &&
189 xdr_enum(xdrs
, (enum_t
*)(void *)&(rmsg
->rm_direction
)) &&
190 (rmsg
->rm_direction
== REPLY
) )
191 return (xdr_union(xdrs
, (enum_t
*)(void *)&(rmsg
->rm_reply
.rp_stat
),
192 (caddr_t
)(void *)&(rmsg
->rm_reply
.ru
), reply_dscrm
,
199 * Serializes the "static part" of a call message header.
200 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
201 * The rm_xid is not really static, but the user can easily munge on the fly.
204 xdr_callhdr(XDR
*xdrs
, struct rpc_msg
*cmsg
)
207 _DIAGASSERT(xdrs
!= NULL
);
208 _DIAGASSERT(cmsg
!= NULL
);
210 cmsg
->rm_direction
= CALL
;
211 cmsg
->rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
213 (xdrs
->x_op
== XDR_ENCODE
) &&
214 xdr_u_int32_t(xdrs
, &(cmsg
->rm_xid
)) &&
215 xdr_enum(xdrs
, (enum_t
*)(void *)&(cmsg
->rm_direction
)) &&
216 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_rpcvers
)) &&
217 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_prog
)) )
218 return (xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_vers
)));
222 /* ************************** Client utility routine ************* */
225 accepted(enum accept_stat acpt_stat
, struct rpc_err
*error
)
228 _DIAGASSERT(error
!= NULL
);
233 error
->re_status
= RPC_PROGUNAVAIL
;
237 error
->re_status
= RPC_PROGVERSMISMATCH
;
241 error
->re_status
= RPC_PROCUNAVAIL
;
245 error
->re_status
= RPC_CANTDECODEARGS
;
249 error
->re_status
= RPC_SYSTEMERROR
;
253 error
->re_status
= RPC_SUCCESS
;
257 /* something's wrong, but we don't know what ... */
258 error
->re_status
= RPC_FAILED
;
259 error
->re_lb
.s1
= (int32_t)MSG_ACCEPTED
;
260 error
->re_lb
.s2
= (int32_t)acpt_stat
;
264 rejected(enum reject_stat rjct_stat
, struct rpc_err
*error
)
267 _DIAGASSERT(error
!= NULL
);
271 error
->re_status
= RPC_VERSMISMATCH
;
275 error
->re_status
= RPC_AUTHERROR
;
278 /* something's wrong, but we don't know what ... */
280 error
->re_status
= RPC_FAILED
;
281 error
->re_lb
.s1
= (int32_t)MSG_DENIED
;
282 error
->re_lb
.s2
= (int32_t)rjct_stat
;
286 * given a reply message, fills in the error
289 _seterr_reply(struct rpc_msg
*msg
, struct rpc_err
*error
)
292 _DIAGASSERT(msg
!= NULL
);
293 _DIAGASSERT(error
!= NULL
);
295 /* optimized for normal, SUCCESSful case */
296 switch (msg
->rm_reply
.rp_stat
) {
299 if (msg
->acpted_rply
.ar_stat
== SUCCESS
) {
300 error
->re_status
= RPC_SUCCESS
;
303 accepted(msg
->acpted_rply
.ar_stat
, error
);
307 rejected(msg
->rjcted_rply
.rj_stat
, error
);
311 error
->re_status
= RPC_FAILED
;
312 error
->re_lb
.s1
= (int32_t)(msg
->rm_reply
.rp_stat
);
315 switch (error
->re_status
) {
317 case RPC_VERSMISMATCH
:
318 error
->re_vers
.low
= msg
->rjcted_rply
.rj_vers
.low
;
319 error
->re_vers
.high
= msg
->rjcted_rply
.rj_vers
.high
;
323 error
->re_why
= msg
->rjcted_rply
.rj_why
;
326 case RPC_PROGVERSMISMATCH
:
327 error
->re_vers
.low
= msg
->acpted_rply
.ar_vers
.low
;
328 error
->re_vers
.high
= msg
->acpted_rply
.ar_vers
.high
;
333 case RPC_PROGNOTREGISTERED
:
334 case RPC_PMAPFAILURE
:
335 case RPC_UNKNOWNPROTO
:
336 case RPC_UNKNOWNHOST
:
337 case RPC_SYSTEMERROR
:
338 case RPC_CANTDECODEARGS
:
339 case RPC_PROCUNAVAIL
:
340 case RPC_PROGUNAVAIL
:
344 case RPC_CANTDECODERES
:
345 case RPC_CANTENCODEARGS
: