[LIBTIRPC]
[reactos.git] / reactos / dll / 3rdparty / libtirpc / src / rpc_prot.c
1 /*
2 * Copyright (c) 2009, Sun Microsystems, Inc.
3 * All rights reserved.
4 *
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.
15 *
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.
27 */
28
29 /*
30 * rpc_prot.c
31 *
32 * Copyright (C) 1984, Sun Microsystems, Inc.
33 *
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.
40 */
41
42 /* NFSv4.1 client for Windows
43 * Copyright © 2012 The Regents of the University of Michigan
44 *
45 * Olga Kornievskaia <aglo@umich.edu>
46 * Casey Bodley <cbodley@umich.edu>
47 *
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.
52 *
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.
57 *
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
61 */
62
63 #include <wintirpc.h>
64 //#include <sys/param.h>
65
66 #include <assert.h>
67
68 #include <rpc/rpc.h>
69
70 static void accepted(enum accept_stat, struct rpc_err *);
71 static void rejected(enum reject_stat, struct rpc_err *);
72
73 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
74
75 extern struct opaque_auth _null_auth;
76
77 /*
78 * XDR an opaque authentication struct
79 * (see auth.h)
80 */
81 bool_t
82 xdr_opaque_auth(xdrs, ap)
83 XDR *xdrs;
84 struct opaque_auth *ap;
85 {
86
87 assert(xdrs != NULL);
88 assert(ap != NULL);
89
90 if (xdr_enum(xdrs, &(ap->oa_flavor)))
91 return (xdr_bytes(xdrs, &ap->oa_base,
92 &ap->oa_length, MAX_AUTH_BYTES));
93 return (FALSE);
94 }
95
96 /*
97 * XDR a DES block
98 */
99 bool_t
100 xdr_des_block(xdrs, blkp)
101 XDR *xdrs;
102 des_block *blkp;
103 {
104
105 assert(xdrs != NULL);
106 assert(blkp != NULL);
107
108 return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
109 }
110
111 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
112
113 /*
114 * XDR the MSG_ACCEPTED part of a reply message union
115 */
116 bool_t
117 xdr_accepted_reply(xdrs, ar)
118 XDR *xdrs;
119 struct accepted_reply *ar;
120 {
121
122 assert(xdrs != NULL);
123 assert(ar != NULL);
124
125 /* personalized union, rather than calling xdr_union */
126 if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
127 return (FALSE);
128 if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
129 return (FALSE);
130 switch (ar->ar_stat) {
131
132 case SUCCESS:
133 return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
134
135 case PROG_MISMATCH:
136 if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
137 return (FALSE);
138 return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
139
140 case GARBAGE_ARGS:
141 case SYSTEM_ERR:
142 case PROC_UNAVAIL:
143 case PROG_UNAVAIL:
144 break;
145 }
146 return (TRUE); /* TRUE => open ended set of problems */
147 }
148
149 /*
150 * XDR the MSG_DENIED part of a reply message union
151 */
152 bool_t
153 xdr_rejected_reply(xdrs, rr)
154 XDR *xdrs;
155 struct rejected_reply *rr;
156 {
157
158 assert(xdrs != NULL);
159 assert(rr != NULL);
160
161 /* personalized union, rather than calling xdr_union */
162 if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
163 return (FALSE);
164 switch (rr->rj_stat) {
165
166 case RPC_MISMATCH:
167 if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
168 return (FALSE);
169 return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
170
171 case AUTH_ERROR:
172 return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
173 }
174 /* NOTREACHED */
175 assert(0);
176 return (FALSE);
177 }
178
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 } };
183
184 /*
185 * XDR a reply message
186 */
187 bool_t
188 xdr_replymsg(xdrs, rmsg)
189 XDR *xdrs;
190 struct rpc_msg *rmsg;
191 {
192 assert(xdrs != NULL);
193 assert(rmsg != NULL);
194
195 if (
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,
201 NULL_xdrproc_t));
202 return (FALSE);
203 }
204
205 /*
206 * XDR a reply message in pieces, first xid and direction, then union
207 */
208 bool_t
209 xdr_getxiddir(xdrs, rmsg)
210 XDR *xdrs;
211 struct rpc_msg *rmsg;
212 {
213 assert(xdrs != NULL);
214 assert(rmsg != NULL);
215
216 return (xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
217 xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)));
218 }
219
220 bool_t
221 xdr_getreplyunion(xdrs, rmsg)
222 XDR *xdrs;
223 struct rpc_msg *rmsg;
224 {
225 assert(xdrs != NULL);
226 assert(rmsg != NULL);
227
228 return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
229 (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
230 NULL_xdrproc_t));
231 }
232
233 bool_t
234 xdr_getcallbody(xdrs, rmsg)
235 XDR *xdrs;
236 struct rpc_msg *rmsg;
237 {
238 assert(xdrs != NULL);
239 assert(rmsg != NULL);
240
241 if (
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)));
248 return FALSE;
249 }
250
251 /*
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.
255 */
256 bool_t
257 xdr_callhdr(xdrs, cmsg)
258 XDR *xdrs;
259 struct rpc_msg *cmsg;
260 {
261
262 assert(xdrs != NULL);
263 assert(cmsg != NULL);
264
265 cmsg->rm_direction = CALL;
266 cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
267 if (
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)));
274 return (FALSE);
275 }
276
277 /* ************************** Client utility routine ************* */
278
279 static void
280 accepted(acpt_stat, error)
281 enum accept_stat acpt_stat;
282 struct rpc_err *error;
283 {
284
285 assert(error != NULL);
286
287 switch (acpt_stat) {
288
289 case PROG_UNAVAIL:
290 error->re_status = RPC_PROGUNAVAIL;
291 return;
292
293 case PROG_MISMATCH:
294 error->re_status = RPC_PROGVERSMISMATCH;
295 return;
296
297 case PROC_UNAVAIL:
298 error->re_status = RPC_PROCUNAVAIL;
299 return;
300
301 case GARBAGE_ARGS:
302 error->re_status = RPC_CANTDECODEARGS;
303 return;
304
305 case SYSTEM_ERR:
306 error->re_status = RPC_SYSTEMERROR;
307 return;
308
309 case SUCCESS:
310 error->re_status = RPC_SUCCESS;
311 return;
312 }
313 /* NOTREACHED */
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;
318 }
319
320 static void
321 rejected(rjct_stat, error)
322 enum reject_stat rjct_stat;
323 struct rpc_err *error;
324 {
325
326 assert(error != NULL);
327
328 switch (rjct_stat) {
329 case RPC_MISMATCH:
330 error->re_status = RPC_VERSMISMATCH;
331 return;
332
333 case AUTH_ERROR:
334 error->re_status = RPC_AUTHERROR;
335 return;
336 }
337 /* something's wrong, but we don't know what ... */
338 /* NOTREACHED */
339 error->re_status = RPC_FAILED;
340 error->re_lb.s1 = (int32_t)MSG_DENIED;
341 error->re_lb.s2 = (int32_t)rjct_stat;
342 }
343
344 /*
345 * given a reply message, fills in the error
346 */
347 void
348 _seterr_reply(msg, error)
349 struct rpc_msg *msg;
350 struct rpc_err *error;
351 {
352
353 assert(msg != NULL);
354 assert(error != NULL);
355
356 /* optimized for normal, SUCCESSful case */
357 switch (msg->rm_reply.rp_stat) {
358
359 case MSG_ACCEPTED:
360 if (msg->acpted_rply.ar_stat == SUCCESS) {
361 error->re_status = RPC_SUCCESS;
362 return;
363 }
364 accepted(msg->acpted_rply.ar_stat, error);
365 break;
366
367 case MSG_DENIED:
368 rejected(msg->rjcted_rply.rj_stat, error);
369 break;
370
371 default:
372 error->re_status = RPC_FAILED;
373 error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
374 break;
375 }
376 switch (error->re_status) {
377
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;
381 break;
382
383 case RPC_AUTHERROR:
384 error->re_why = msg->rjcted_rply.rj_why;
385 break;
386
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;
390 break;
391
392 case RPC_FAILED:
393 case RPC_SUCCESS:
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:
402 case RPC_TIMEDOUT:
403 case RPC_CANTRECV:
404 case RPC_CANTSEND:
405 case RPC_CANTDECODERES:
406 case RPC_CANTENCODEARGS:
407 default:
408 break;
409 }
410 }