* Use id(1) instead of grep(1) to detect the presence of the smmsp
[dragonfly.git] / lib / libcr / rpc / rpc_prot.c
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/libcr/rpc/Attic/rpc_prot.c,v 1.2 2003/06/17 04:26:45 dillon 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         register XDR *xdrs;
63         register 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         register XDR *xdrs;
78         register 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         register XDR *xdrs;
91         register 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         register XDR *xdrs;
120         register 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         register XDR *xdrs;
150         register 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         register XDR *xdrs;
170         register 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         register enum accept_stat acpt_stat;
190         register 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         register enum reject_stat rjct_stat;
228         register 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         register struct rpc_msg *msg;
255         register 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 }