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