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