xref: /openbsd-src/lib/libc/rpc/rpc_prot.c (revision 62a742911104f98b9185b2c6b6007d9b1c36396c)
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 
30 #if defined(LIBC_SCCS) && !defined(lint)
31 static char *rcsid = "$OpenBSD: rpc_prot.c,v 1.6 1998/03/19 00:27:21 millert Exp $";
32 #endif /* LIBC_SCCS and not lint */
33 
34 /*
35  * rpc_prot.c
36  *
37  * Copyright (C) 1984, Sun Microsystems, Inc.
38  *
39  * This set of routines implements the rpc message definition,
40  * its serializer and some common rpc utility routines.
41  * The routines are meant for various implementations of rpc -
42  * they are NOT for the rpc client or rpc service implementations!
43  * Because authentication stuff is easy and is part of rpc, the opaque
44  * routines are also in this program.
45  */
46 
47 #include <sys/param.h>
48 
49 #include <rpc/rpc.h>
50 
51 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
52 
53 struct opaque_auth _null_auth;
54 
55 /*
56  * XDR an opaque authentication struct
57  * (see auth.h)
58  */
59 bool_t
60 xdr_opaque_auth(xdrs, ap)
61 	register XDR *xdrs;
62 	register struct opaque_auth *ap;
63 {
64 
65 	if (xdr_enum(xdrs, &(ap->oa_flavor)))
66 		return (xdr_bytes(xdrs, &ap->oa_base,
67 		    &ap->oa_length, MAX_AUTH_BYTES));
68 	return (FALSE);
69 }
70 
71 /*
72  * XDR a DES block
73  */
74 bool_t
75 xdr_des_block(xdrs, blkp)
76 	register XDR *xdrs;
77 	register des_block *blkp;
78 {
79 	return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
80 }
81 
82 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
83 
84 /*
85  * XDR the MSG_ACCEPTED part of a reply message union
86  */
87 bool_t
88 xdr_accepted_reply(xdrs, ar)
89 	register XDR *xdrs;
90 	register struct accepted_reply *ar;
91 {
92 
93 	/* personalized union, rather than calling xdr_union */
94 	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
95 		return (FALSE);
96 	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
97 		return (FALSE);
98 
99 	switch (ar->ar_stat) {
100 	case SUCCESS:
101 		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
102 	case PROG_MISMATCH:
103 		if (!xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
104 			return (FALSE);
105 		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
106 	default:
107 		return (TRUE);  /* TRUE => open ended set of problems */
108 	}
109 }
110 
111 /*
112  * XDR the MSG_DENIED part of a reply message union
113  */
114 bool_t
115 xdr_rejected_reply(xdrs, rr)
116 	register XDR *xdrs;
117 	register struct rejected_reply *rr;
118 {
119 
120 	/* personalized union, rather than calling xdr_union */
121 	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
122 		return (FALSE);
123 
124 	switch (rr->rj_stat) {
125 	case RPC_MISMATCH:
126 		if (!xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
127 			return (FALSE);
128 		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
129 	case AUTH_ERROR:
130 		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
131 	}
132 	return (FALSE);
133 }
134 
135 static struct xdr_discrim reply_dscrm[3] = {
136 	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
137 	{ (int)MSG_DENIED, xdr_rejected_reply },
138 	{ __dontcare__, NULL_xdrproc_t } };
139 
140 /*
141  * XDR a reply message
142  */
143 bool_t
144 xdr_replymsg(xdrs, rmsg)
145 	register XDR *xdrs;
146 	register struct rpc_msg *rmsg;
147 {
148 	if (xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
149 	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
150 	    rmsg->rm_direction == REPLY)
151 		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
152 		   (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
153 	return (FALSE);
154 }
155 
156 
157 /*
158  * Serializes the "static part" of a call message header.
159  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
160  * The rm_xid is not really static, but the user can easily munge on the fly.
161  */
162 bool_t
163 xdr_callhdr(xdrs, cmsg)
164 	register XDR *xdrs;
165 	register struct rpc_msg *cmsg;
166 {
167 
168 	cmsg->rm_direction = CALL;
169 	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
170 	if (xdrs->x_op == XDR_ENCODE &&
171 	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
172 	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
173 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
174 	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)))
175 		return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
176 	return (FALSE);
177 }
178 
179 /* ************************** Client utility routine ************* */
180 
181 static void
182 accepted(acpt_stat, error)
183 	register enum accept_stat acpt_stat;
184 	register struct rpc_err *error;
185 {
186 
187 	switch (acpt_stat) {
188 
189 	case PROG_UNAVAIL:
190 		error->re_status = RPC_PROGUNAVAIL;
191 		return;
192 
193 	case PROG_MISMATCH:
194 		error->re_status = RPC_PROGVERSMISMATCH;
195 		return;
196 
197 	case PROC_UNAVAIL:
198 		error->re_status = RPC_PROCUNAVAIL;
199 		return;
200 
201 	case GARBAGE_ARGS:
202 		error->re_status = RPC_CANTDECODEARGS;
203 		return;
204 
205 	case SYSTEM_ERR:
206 		error->re_status = RPC_SYSTEMERROR;
207 		return;
208 
209 	case SUCCESS:
210 		error->re_status = RPC_SUCCESS;
211 		return;
212 	}
213 	/* something's wrong, but we don't know what ... */
214 	error->re_status = RPC_FAILED;
215 	error->re_lb.s1 = (long)MSG_ACCEPTED;
216 	error->re_lb.s2 = (long)acpt_stat;
217 }
218 
219 static void
220 rejected(rjct_stat, error)
221 	register enum reject_stat rjct_stat;
222 	register struct rpc_err *error;
223 {
224 
225 	switch (rjct_stat) {
226 
227 	case RPC_MISMATCH:
228 		error->re_status = RPC_VERSMISMATCH;
229 		return;
230 
231 	case AUTH_ERROR:
232 		error->re_status = RPC_AUTHERROR;
233 		return;
234 	}
235 	/* something's wrong, but we don't know what ... */
236 	error->re_status = RPC_FAILED;
237 	error->re_lb.s1 = (long)MSG_DENIED;
238 	error->re_lb.s2 = (long)rjct_stat;
239 }
240 
241 /*
242  * given a reply message, fills in the error
243  */
244 void
245 _seterr_reply(msg, error)
246 	register struct rpc_msg *msg;
247 	register struct rpc_err *error;
248 {
249 
250 	/* optimized for normal, SUCCESSful case */
251 	switch (msg->rm_reply.rp_stat) {
252 
253 	case MSG_ACCEPTED:
254 		if (msg->acpted_rply.ar_stat == SUCCESS) {
255 			error->re_status = RPC_SUCCESS;
256 			return;
257 		};
258 		accepted(msg->acpted_rply.ar_stat, error);
259 		break;
260 
261 	case MSG_DENIED:
262 		rejected(msg->rjcted_rply.rj_stat, error);
263 		break;
264 
265 	default:
266 		error->re_status = RPC_FAILED;
267 		error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
268 		break;
269 	}
270 	switch (error->re_status) {
271 
272 	case RPC_VERSMISMATCH:
273 		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
274 		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
275 		break;
276 
277 	case RPC_AUTHERROR:
278 		error->re_why = msg->rjcted_rply.rj_why;
279 		break;
280 
281 	case RPC_PROGVERSMISMATCH:
282 		error->re_vers.low = msg->acpted_rply.ar_vers.low;
283 		error->re_vers.high = msg->acpted_rply.ar_vers.high;
284 		break;
285 	}
286 }
287