1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
7 * Reserved.  This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License").  You may not use this file
10 * except in compliance with the License.  Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT.  Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
26 * unrestricted use provided that this legend is included on all tape
27 * media and as a part of the software program in whole or part.  Users
28 * may copy or modify Sun RPC without charge, but are not authorized
29 * to license or distribute it to anyone else except as part of a product or
30 * program developed by the user.
31 *
32 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
33 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
34 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
35 *
36 * Sun RPC is provided with no support and without any obligation on the
37 * part of Sun Microsystems, Inc. to assist in its use, correction,
38 * modification or enhancement.
39 *
40 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
41 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
42 * OR ANY PART THEREOF.
43 *
44 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
45 * or profits or other special, indirect and consequential damages, even if
46 * Sun has been advised of the possibility of such damages.
47 *
48 * Sun Microsystems, Inc.
49 * 2550 Garcia Avenue
50 * Mountain View, California  94043
51 */
52
53#if defined(LIBC_SCCS) && !defined(lint)
54/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
55static char *rcsid = "$Id: rpc_prot.c,v 1.3 2003/06/23 17:24:59 majka Exp $";
56#endif
57
58/*
59 * rpc_prot.c
60 *
61 * Copyright (C) 1984, Sun Microsystems, Inc.
62 *
63 * This set of routines implements the rpc message definition,
64 * its serializer and some common rpc utility routines.
65 * The routines are meant for various implementations of rpc -
66 * they are NOT for the rpc client or rpc service implementations!
67 * Because authentication stuff is easy and is part of rpc, the opaque
68 * routines are also in this program.
69 */
70
71#include <sys/param.h>
72
73#include <rpc/rpc.h>
74
75/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
76
77#if defined(__APPLE__)
78extern
79#endif
80struct opaque_auth _null_auth;
81
82/*
83 * XDR an opaque authentication struct
84 * (see auth.h)
85 */
86bool_t
87xdr_opaque_auth(xdrs, ap)
88	register XDR *xdrs;
89	register struct opaque_auth *ap;
90{
91
92	if (xdr_enum(xdrs, &(ap->oa_flavor)))
93		return (xdr_bytes(xdrs, &ap->oa_base,
94			&ap->oa_length, MAX_AUTH_BYTES));
95	return (FALSE);
96}
97
98/*
99 * XDR a DES block
100 */
101bool_t
102xdr_des_block(xdrs, blkp)
103	register XDR *xdrs;
104	register des_block *blkp;
105{
106	return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
107}
108
109/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
110
111/*
112 * XDR the MSG_ACCEPTED part of a reply message union
113 */
114bool_t
115xdr_accepted_reply(xdrs, ar)
116	register XDR *xdrs;
117	register struct accepted_reply *ar;
118{
119
120	/* personalized union, rather than calling xdr_union */
121	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
122		return (FALSE);
123	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
124		return (FALSE);
125	switch (ar->ar_stat) {
126
127	case SUCCESS:
128		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where, 0));
129
130	case PROG_MISMATCH:
131		if (! xdr_u_long(xdrs, &(ar->ar_vers.low)))
132			return (FALSE);
133		return (xdr_u_long(xdrs, &(ar->ar_vers.high)));
134	default: break;
135	}
136	return (TRUE);  /* TRUE => open ended set of problems */
137}
138
139/*
140 * XDR the MSG_DENIED part of a reply message union
141 */
142bool_t
143xdr_rejected_reply(xdrs, rr)
144	register XDR *xdrs;
145	register struct rejected_reply *rr;
146{
147
148	/* personalized union, rather than calling xdr_union */
149	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
150		return (FALSE);
151	switch (rr->rj_stat) {
152
153	case RPC_MISMATCH:
154		if (! xdr_u_long(xdrs, &(rr->rj_vers.low)))
155			return (FALSE);
156		return (xdr_u_long(xdrs, &(rr->rj_vers.high)));
157
158	case AUTH_ERROR:
159		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
160	}
161	return (FALSE);
162}
163
164static struct xdr_discrim reply_dscrm[3] = {
165	{ (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
166	{ (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
167	{ __dontcare__, NULL_xdrproc_t } };
168
169/*
170 * XDR a reply message
171 */
172bool_t
173xdr_replymsg(xdrs, rmsg)
174	register XDR *xdrs;
175	register struct rpc_msg *rmsg;
176{
177	if (
178	    xdr_u_long(xdrs, &(rmsg->rm_xid)) &&
179	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
180	    (rmsg->rm_direction == REPLY) )
181		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
182		   (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
183	return (FALSE);
184}
185
186
187/*
188 * Serializes the "static part" of a call message header.
189 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
190 * The rm_xid is not really static, but the user can easily munge on the fly.
191 */
192bool_t
193xdr_callhdr(xdrs, cmsg)
194	register XDR *xdrs;
195	register struct rpc_msg *cmsg;
196{
197
198	cmsg->rm_direction = CALL;
199	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
200	if (
201	    (xdrs->x_op == XDR_ENCODE) &&
202	    xdr_u_long(xdrs, &(cmsg->rm_xid)) &&
203	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
204	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
205	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) )
206	    return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)));
207	return (FALSE);
208}
209
210/* ************************** Client utility routine ************* */
211
212static void
213accepted(acpt_stat, error)
214	register enum accept_stat acpt_stat;
215	register struct rpc_err *error;
216{
217
218	switch (acpt_stat) {
219
220	case PROG_UNAVAIL:
221		error->re_status = RPC_PROGUNAVAIL;
222		return;
223
224	case PROG_MISMATCH:
225		error->re_status = RPC_PROGVERSMISMATCH;
226		return;
227
228	case PROC_UNAVAIL:
229		error->re_status = RPC_PROCUNAVAIL;
230		return;
231
232	case GARBAGE_ARGS:
233		error->re_status = RPC_CANTDECODEARGS;
234		return;
235
236	case SYSTEM_ERR:
237		error->re_status = RPC_SYSTEMERROR;
238		return;
239
240	case SUCCESS:
241		error->re_status = RPC_SUCCESS;
242		return;
243	}
244	/* something's wrong, but we don't know what ... */
245	error->re_status = RPC_FAILED;
246#ifdef __LP64__
247	error->re_lb.s1 = (int)MSG_ACCEPTED;
248	error->re_lb.s2 = (int)acpt_stat;
249#else
250	error->re_lb.s1 = (long)MSG_ACCEPTED;
251	error->re_lb.s2 = (long)acpt_stat;
252#endif
253}
254
255static void
256rejected(rjct_stat, error)
257	register enum reject_stat rjct_stat;
258	register struct rpc_err *error;
259{
260
261	switch (rjct_stat) {
262
263	case RPC_MISMATCH:
264		error->re_status = RPC_VERSMISMATCH;
265		return;
266
267	case AUTH_ERROR:
268		error->re_status = RPC_AUTHERROR;
269		return;
270	default: break;
271	}
272	/* something's wrong, but we don't know what ... */
273	error->re_status = RPC_FAILED;
274#ifdef __LP64__
275	error->re_lb.s1 = (int)MSG_DENIED;
276	error->re_lb.s2 = (int)rjct_stat;
277#else
278	error->re_lb.s1 = (long)MSG_DENIED;
279	error->re_lb.s2 = (long)rjct_stat;
280#endif
281}
282
283/*
284 * given a reply message, fills in the error
285 */
286void
287_seterr_reply(msg, error)
288	register struct rpc_msg *msg;
289	register struct rpc_err *error;
290{
291
292	/* optimized for normal, SUCCESSful case */
293	switch (msg->rm_reply.rp_stat) {
294
295	case MSG_ACCEPTED:
296		if (msg->acpted_rply.ar_stat == SUCCESS) {
297			error->re_status = RPC_SUCCESS;
298			return;
299		};
300		accepted(msg->acpted_rply.ar_stat, error);
301		break;
302
303	case MSG_DENIED:
304		rejected(msg->rjcted_rply.rj_stat, error);
305		break;
306
307	default:
308		error->re_status = RPC_FAILED;
309#ifdef __LP64__
310		error->re_lb.s1 = (int)(msg->rm_reply.rp_stat);
311#else
312		error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
313#endif
314		break;
315	}
316	switch (error->re_status) {
317
318	case RPC_VERSMISMATCH:
319		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
320		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
321		break;
322
323	case RPC_AUTHERROR:
324		error->re_why = msg->rjcted_rply.rj_why;
325		break;
326
327	case RPC_PROGVERSMISMATCH:
328		error->re_vers.low = msg->acpted_rply.ar_vers.low;
329		error->re_vers.high = msg->acpted_rply.ar_vers.high;
330		break;
331
332	default: break;
333	}
334}
335