Localize rpcgen
[platform/upstream/glibc.git] / sunrpc / rpc_prot.c
1 /*
2  * rpc_prot.c
3  *
4  * Copyright (c) 2010, Oracle America, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above
13  *       copyright notice, this list of conditions and the following
14  *       disclaimer in the documentation and/or other materials
15  *       provided with the distribution.
16  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  * This set of routines implements the rpc message definition,
34  * its serializer and some common rpc utility routines.
35  * The routines are meant for various implementations of rpc -
36  * they are NOT for the rpc client or rpc service implementations!
37  * Because authentication stuff is easy and is part of rpc, the opaque
38  * routines are also in this program.
39  */
40
41 #include <sys/param.h>
42
43 #include <rpc/rpc.h>
44
45 /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
46
47 /*
48  * XDR an opaque authentication struct
49  * (see auth.h)
50  */
51 bool_t
52 xdr_opaque_auth (XDR *xdrs, struct opaque_auth *ap)
53 {
54
55   if (xdr_enum (xdrs, &(ap->oa_flavor)))
56     return xdr_bytes (xdrs, &ap->oa_base,
57                       &ap->oa_length, MAX_AUTH_BYTES);
58   return FALSE;
59 }
60 libc_hidden_nolink_sunrpc (xdr_opaque_auth, GLIBC_2_0)
61
62 /*
63  * XDR a DES block
64  */
65 bool_t
66 xdr_des_block (XDR *xdrs, des_block *blkp)
67 {
68   return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block));
69 }
70 libc_hidden_nolink_sunrpc (xdr_des_block, GLIBC_2_0)
71
72 /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
73
74 /*
75  * XDR the MSG_ACCEPTED part of a reply message union
76  */
77 bool_t
78 xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar)
79 {
80   /* personalized union, rather than calling xdr_union */
81   if (!xdr_opaque_auth (xdrs, &(ar->ar_verf)))
82     return FALSE;
83   if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat)))
84     return FALSE;
85   switch (ar->ar_stat)
86     {
87     case SUCCESS:
88       return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where));
89     case PROG_MISMATCH:
90       if (!xdr_u_long (xdrs, &(ar->ar_vers.low)))
91         return FALSE;
92       return (xdr_u_long (xdrs, &(ar->ar_vers.high)));
93     default:
94       return TRUE;
95     }
96   return TRUE;          /* TRUE => open ended set of problems */
97 }
98 libc_hidden_nolink_sunrpc (xdr_accepted_reply, GLIBC_2_0)
99
100 /*
101  * XDR the MSG_DENIED part of a reply message union
102  */
103 bool_t
104 xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr)
105 {
106   /* personalized union, rather than calling xdr_union */
107   if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat)))
108     return FALSE;
109   switch (rr->rj_stat)
110     {
111     case RPC_MISMATCH:
112       if (!xdr_u_long (xdrs, &(rr->rj_vers.low)))
113         return FALSE;
114       return xdr_u_long (xdrs, &(rr->rj_vers.high));
115
116     case AUTH_ERROR:
117       return xdr_enum (xdrs, (enum_t *) & (rr->rj_why));
118     }
119   return FALSE;
120 }
121 libc_hidden_nolink_sunrpc (xdr_rejected_reply, GLIBC_2_0)
122
123 static const struct xdr_discrim reply_dscrm[3] =
124 {
125   {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply},
126   {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply},
127   {__dontcare__, NULL_xdrproc_t}};
128
129 /*
130  * XDR a reply message
131  */
132 bool_t
133 xdr_replymsg (xdrs, rmsg)
134      XDR *xdrs;
135      struct rpc_msg *rmsg;
136 {
137   if (xdr_u_long (xdrs, &(rmsg->rm_xid)) &&
138       xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) &&
139       (rmsg->rm_direction == REPLY))
140     return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat),
141                       (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm,
142                       NULL_xdrproc_t);
143   return FALSE;
144 }
145 libc_hidden_nolink_sunrpc (xdr_replymsg, GLIBC_2_0)
146
147
148 /*
149  * Serializes the "static part" of a call message header.
150  * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
151  * The rm_xid is not really static, but the user can easily munge on the fly.
152  */
153 bool_t
154 xdr_callhdr (xdrs, cmsg)
155      XDR *xdrs;
156      struct rpc_msg *cmsg;
157 {
158
159   cmsg->rm_direction = CALL;
160   cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
161   if (
162        (xdrs->x_op == XDR_ENCODE) &&
163        xdr_u_long (xdrs, &(cmsg->rm_xid)) &&
164        xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) &&
165        xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
166        xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)))
167     return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers));
168   return FALSE;
169 }
170 libc_hidden_nolink_sunrpc (xdr_callhdr, GLIBC_2_0)
171
172 /* ************************** Client utility routine ************* */
173
174 static void
175 accepted (enum accept_stat acpt_stat,
176           struct rpc_err *error)
177 {
178   switch (acpt_stat)
179     {
180
181     case PROG_UNAVAIL:
182       error->re_status = RPC_PROGUNAVAIL;
183       return;
184
185     case PROG_MISMATCH:
186       error->re_status = RPC_PROGVERSMISMATCH;
187       return;
188
189     case PROC_UNAVAIL:
190       error->re_status = RPC_PROCUNAVAIL;
191       return;
192
193     case GARBAGE_ARGS:
194       error->re_status = RPC_CANTDECODEARGS;
195       return;
196
197     case SYSTEM_ERR:
198       error->re_status = RPC_SYSTEMERROR;
199       return;
200
201     case SUCCESS:
202       error->re_status = RPC_SUCCESS;
203       return;
204     }
205   /* something's wrong, but we don't know what ... */
206   error->re_status = RPC_FAILED;
207   error->re_lb.s1 = (long) MSG_ACCEPTED;
208   error->re_lb.s2 = (long) acpt_stat;
209 }
210
211 static void
212 rejected (enum reject_stat rjct_stat,
213           struct rpc_err *error)
214 {
215   switch (rjct_stat)
216     {
217     case RPC_MISMATCH:
218       error->re_status = RPC_VERSMISMATCH;
219       return;
220     case AUTH_ERROR:
221       error->re_status = RPC_AUTHERROR;
222       return;
223     default:
224       /* something's wrong, but we don't know what ... */
225       error->re_status = RPC_FAILED;
226       error->re_lb.s1 = (long) MSG_DENIED;
227       error->re_lb.s2 = (long) rjct_stat;
228       return;
229     }
230 }
231
232 /*
233  * given a reply message, fills in the error
234  */
235 void
236 _seterr_reply (struct rpc_msg *msg,
237                struct rpc_err *error)
238 {
239   /* optimized for normal, SUCCESSful case */
240   switch (msg->rm_reply.rp_stat)
241     {
242     case MSG_ACCEPTED:
243       if (msg->acpted_rply.ar_stat == SUCCESS)
244         {
245           error->re_status = RPC_SUCCESS;
246           return;
247         };
248       accepted (msg->acpted_rply.ar_stat, error);
249       break;
250
251     case MSG_DENIED:
252       rejected (msg->rjcted_rply.rj_stat, error);
253       break;
254
255     default:
256       error->re_status = RPC_FAILED;
257       error->re_lb.s1 = (long) (msg->rm_reply.rp_stat);
258       break;
259     }
260   switch (error->re_status)
261     {
262
263     case RPC_VERSMISMATCH:
264       error->re_vers.low = msg->rjcted_rply.rj_vers.low;
265       error->re_vers.high = msg->rjcted_rply.rj_vers.high;
266       break;
267
268     case RPC_AUTHERROR:
269       error->re_why = msg->rjcted_rply.rj_why;
270       break;
271
272     case RPC_PROGVERSMISMATCH:
273       error->re_vers.low = msg->acpted_rply.ar_vers.low;
274       error->re_vers.high = msg->acpted_rply.ar_vers.high;
275       break;
276     default:
277       break;
278     }
279 }
280 libc_hidden_nolink_sunrpc (_seterr_reply, GLIBC_2_0)