2 * Copyright (c) 2009, Sun Microsystems, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of Sun Microsystems, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
32 * Copyright (C) 1984, Sun Microsystems, Inc.
34 * This set of routines implements the rpc message definition,
35 * its serializer and some common rpc utility routines.
36 * The routines are meant for various implementations of rpc -
37 * they are NOT for the rpc client or rpc service implementations!
38 * Because authentication stuff is easy and is part of rpc, the opaque
39 * routines are also in this program.
42 /* NFSv4.1 client for Windows
43 * Copyright © 2012 The Regents of the University of Michigan
45 * Olga Kornievskaia <aglo@umich.edu>
46 * Casey Bodley <cbodley@umich.edu>
48 * This library is free software; you can redistribute it and/or modify it
49 * under the terms of the GNU Lesser General Public License as published by
50 * the Free Software Foundation; either version 2.1 of the License, or (at
51 * your option) any later version.
53 * This library is distributed in the hope that it will be useful, but
54 * without any warranty; without even the implied warranty of merchantability
55 * or fitness for a particular purpose. See the GNU Lesser General Public
56 * License for more details.
58 * You should have received a copy of the GNU Lesser General Public License
59 * along with this library; if not, write to the Free Software Foundation,
60 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
64 //#include <sys/param.h>
70 static void accepted(enum accept_stat
, struct rpc_err
*);
71 static void rejected(enum reject_stat
, struct rpc_err
*);
73 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
75 extern struct opaque_auth _null_auth
;
78 * XDR an opaque authentication struct
82 xdr_opaque_auth(xdrs
, ap
)
84 struct opaque_auth
*ap
;
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 assert(xdrs
!= NULL
);
106 assert(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 assert(xdrs
!= 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
*)&(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 assert(xdrs
!= NULL
);
161 /* personalized union, rather than calling xdr_union */
162 if (! xdr_enum(xdrs
, (enum_t
*)&(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
*)&(rr
->rj_why
)));
179 static const struct xdr_discrim reply_dscrm
[3] = {
180 { (int)MSG_ACCEPTED
, (xdrproc_t
)xdr_accepted_reply
},
181 { (int)MSG_DENIED
, (xdrproc_t
)xdr_rejected_reply
},
182 { __dontcare__
, NULL_xdrproc_t
} };
185 * XDR a reply message
188 xdr_replymsg(xdrs
, rmsg
)
190 struct rpc_msg
*rmsg
;
192 assert(xdrs
!= NULL
);
193 assert(rmsg
!= NULL
);
196 xdr_u_int32_t(xdrs
, &(rmsg
->rm_xid
)) &&
197 xdr_enum(xdrs
, (enum_t
*)&(rmsg
->rm_direction
)) &&
198 (rmsg
->rm_direction
== REPLY
) )
199 return (xdr_union(xdrs
, (enum_t
*)&(rmsg
->rm_reply
.rp_stat
),
200 (caddr_t
)(void *)&(rmsg
->rm_reply
.ru
), reply_dscrm
,
206 * XDR a reply message in pieces, first xid and direction, then union
209 xdr_getxiddir(xdrs
, rmsg
)
211 struct rpc_msg
*rmsg
;
213 assert(xdrs
!= NULL
);
214 assert(rmsg
!= NULL
);
216 return (xdr_u_int32_t(xdrs
, &(rmsg
->rm_xid
)) &&
217 xdr_enum(xdrs
, (enum_t
*)&(rmsg
->rm_direction
)));
221 xdr_getreplyunion(xdrs
, rmsg
)
223 struct rpc_msg
*rmsg
;
225 assert(xdrs
!= NULL
);
226 assert(rmsg
!= NULL
);
228 return (xdr_union(xdrs
, (enum_t
*)&(rmsg
->rm_reply
.rp_stat
),
229 (caddr_t
)(void *)&(rmsg
->rm_reply
.ru
), reply_dscrm
,
234 xdr_getcallbody(xdrs
, rmsg
)
236 struct rpc_msg
*rmsg
;
238 assert(xdrs
!= NULL
);
239 assert(rmsg
!= NULL
);
242 xdr_u_int32_t(xdrs
, &(rmsg
->rm_call
.cb_rpcvers
)) &&
243 xdr_u_int32_t(xdrs
, &(rmsg
->rm_call
.cb_prog
)) &&
244 xdr_u_int32_t(xdrs
, &(rmsg
->rm_call
.cb_vers
)) &&
245 xdr_u_int32_t(xdrs
, &(rmsg
->rm_call
.cb_proc
)) &&
246 xdr_opaque_auth(xdrs
, &(rmsg
->rm_call
.cb_cred
)) )
247 return (xdr_opaque_auth(xdrs
, &(rmsg
->rm_call
.cb_verf
)));
252 * Serializes the "static part" of a call message header.
253 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
254 * The rm_xid is not really static, but the user can easily munge on the fly.
257 xdr_callhdr(xdrs
, cmsg
)
259 struct rpc_msg
*cmsg
;
262 assert(xdrs
!= NULL
);
263 assert(cmsg
!= NULL
);
265 cmsg
->rm_direction
= CALL
;
266 cmsg
->rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
268 (xdrs
->x_op
== XDR_ENCODE
) &&
269 xdr_u_int32_t(xdrs
, &(cmsg
->rm_xid
)) &&
270 xdr_enum(xdrs
, (enum_t
*)&(cmsg
->rm_direction
)) &&
271 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_rpcvers
)) &&
272 xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_prog
)) )
273 return (xdr_u_int32_t(xdrs
, &(cmsg
->rm_call
.cb_vers
)));
277 /* ************************** Client utility routine ************* */
280 accepted(acpt_stat
, error
)
281 enum accept_stat acpt_stat
;
282 struct rpc_err
*error
;
285 assert(error
!= NULL
);
290 error
->re_status
= RPC_PROGUNAVAIL
;
294 error
->re_status
= RPC_PROGVERSMISMATCH
;
298 error
->re_status
= RPC_PROCUNAVAIL
;
302 error
->re_status
= RPC_CANTDECODEARGS
;
306 error
->re_status
= RPC_SYSTEMERROR
;
310 error
->re_status
= RPC_SUCCESS
;
314 /* something's wrong, but we don't know what ... */
315 error
->re_status
= RPC_FAILED
;
316 error
->re_lb
.s1
= (int32_t)MSG_ACCEPTED
;
317 error
->re_lb
.s2
= (int32_t)acpt_stat
;
321 rejected(rjct_stat
, error
)
322 enum reject_stat rjct_stat
;
323 struct rpc_err
*error
;
326 assert(error
!= NULL
);
330 error
->re_status
= RPC_VERSMISMATCH
;
334 error
->re_status
= RPC_AUTHERROR
;
337 /* something's wrong, but we don't know what ... */
339 error
->re_status
= RPC_FAILED
;
340 error
->re_lb
.s1
= (int32_t)MSG_DENIED
;
341 error
->re_lb
.s2
= (int32_t)rjct_stat
;
345 * given a reply message, fills in the error
348 _seterr_reply(msg
, error
)
350 struct rpc_err
*error
;
354 assert(error
!= NULL
);
356 /* optimized for normal, SUCCESSful case */
357 switch (msg
->rm_reply
.rp_stat
) {
360 if (msg
->acpted_rply
.ar_stat
== SUCCESS
) {
361 error
->re_status
= RPC_SUCCESS
;
364 accepted(msg
->acpted_rply
.ar_stat
, error
);
368 rejected(msg
->rjcted_rply
.rj_stat
, error
);
372 error
->re_status
= RPC_FAILED
;
373 error
->re_lb
.s1
= (int32_t)(msg
->rm_reply
.rp_stat
);
376 switch (error
->re_status
) {
378 case RPC_VERSMISMATCH
:
379 error
->re_vers
.low
= msg
->rjcted_rply
.rj_vers
.low
;
380 error
->re_vers
.high
= msg
->rjcted_rply
.rj_vers
.high
;
384 error
->re_why
= msg
->rjcted_rply
.rj_why
;
387 case RPC_PROGVERSMISMATCH
:
388 error
->re_vers
.low
= msg
->acpted_rply
.ar_vers
.low
;
389 error
->re_vers
.high
= msg
->acpted_rply
.ar_vers
.high
;
394 case RPC_PROGNOTREGISTERED
:
395 case RPC_PMAPFAILURE
:
396 case RPC_UNKNOWNPROTO
:
397 case RPC_UNKNOWNHOST
:
398 case RPC_SYSTEMERROR
:
399 case RPC_CANTDECODEARGS
:
400 case RPC_PROCUNAVAIL
:
401 case RPC_PROGUNAVAIL
:
405 case RPC_CANTDECODERES
:
406 case RPC_CANTENCODEARGS
: