1d7fc626048b2cfbd4f33c4c72a7cafb9e9aab76
[platform/upstream/krb5.git] / src / lib / rpc / clnt_raw.c
1 /* @(#)clnt_raw.c       2.2 88/08/01 4.0 RPCSRC */
2 /*
3  * Copyright (c) 2010, Oracle America, Inc.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *
18  *     * Neither the name of the "Oracle America, Inc." nor the names of
19  *       its contributors may be used to endorse or promote products
20  *       derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
23  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #if !defined(lint) && defined(SCCSIDS)
35 static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
36 #endif
37
38 /*
39  * clnt_raw.c
40  *
41  * Memory based rpc for simple testing and timing.
42  * Interface to create an rpc client and server in the same process.
43  * This lets us similate rpc and get round trip overhead, without
44  * any interference from the kernal.
45  */
46
47 #include <gssrpc/rpc.h>
48
49 #define MCALL_MSG_SIZE 24
50
51 /*
52  * This is the "network" we will be moving stuff over.
53  */
54 static struct clntraw_private {
55         CLIENT  client_object;
56         XDR     xdr_stream;
57         char    _raw_buf[UDPMSGSIZE];
58         union {
59           struct rpc_msg    mashl_rpcmsg;
60           char              mashl_callmsg[MCALL_MSG_SIZE];
61         } u;
62         u_int   mcnt;
63 } *clntraw_private;
64
65 static enum clnt_stat   clntraw_call(CLIENT *, rpcproc_t, xdrproc_t,
66                                      void *, xdrproc_t, void *,
67                                      struct timeval);
68 static void             clntraw_abort(CLIENT *);
69 static void             clntraw_geterr(CLIENT *, struct rpc_err *);
70 static bool_t           clntraw_freeres(CLIENT *, xdrproc_t, void *);
71 static bool_t           clntraw_control(CLIENT *, int, void *);
72 static void             clntraw_destroy(CLIENT *);
73
74 static struct clnt_ops client_ops = {
75         clntraw_call,
76         clntraw_abort,
77         clntraw_geterr,
78         clntraw_freeres,
79         clntraw_destroy,
80         clntraw_control
81 };
82
83 void    svc_getreq();
84
85 /*
86  * Create a client handle for memory based rpc.
87  */
88 CLIENT *
89 clntraw_create(
90         rpcprog_t prog,
91         rpcvers_t vers)
92 {
93         struct clntraw_private *clp;
94         struct rpc_msg call_msg;
95         XDR *xdrs;
96         CLIENT *client;
97
98         if (clntraw_private == NULL) {
99                 clntraw_private = calloc(1, sizeof(*clp));
100                 if (clntraw_private == NULL)
101                         return (NULL);
102         }
103         clp = clntraw_private;
104         xdrs = &clp->xdr_stream;
105         client = &clp->client_object;
106         /*
107          * pre-serialize the staic part of the call msg and stash it away
108          */
109         call_msg.rm_direction = CALL;
110         call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
111         call_msg.rm_call.cb_prog = prog;
112         call_msg.rm_call.cb_vers = vers;
113         xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
114         if (! xdr_callhdr(xdrs, &call_msg)) {
115                 perror("clnt_raw.c - Fatal header serialization error.");
116         }
117         clp->mcnt = XDR_GETPOS(xdrs);
118         XDR_DESTROY(xdrs);
119
120         /*
121          * Set xdrmem for client/server shared buffer
122          */
123         xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
124
125         /*
126          * create client handle
127          */
128         client->cl_ops = &client_ops;
129         client->cl_auth = authnone_create();
130         return (client);
131 }
132
133 static enum clnt_stat
134 clntraw_call(
135         CLIENT *h,
136         rpcproc_t proc,
137         xdrproc_t xargs,
138         void * argsp,
139         xdrproc_t xresults,
140         void * resultsp,
141         struct timeval timeout)
142 {
143         register struct clntraw_private *clp = clntraw_private;
144         register XDR *xdrs = &clp->xdr_stream;
145         struct rpc_msg msg;
146         enum clnt_stat status;
147         struct rpc_err error;
148         long procl = proc;
149
150         if (clp == 0)
151                 return (RPC_FAILED);
152 call_again:
153         /*
154          * send request
155          */
156         xdrs->x_op = XDR_ENCODE;
157         XDR_SETPOS(xdrs, 0);
158         clp->u.mashl_rpcmsg.rm_xid ++ ;
159         if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
160             (! XDR_PUTLONG(xdrs, &procl)) ||
161             (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
162             (! (*xargs)(xdrs, argsp))) {
163                 return (RPC_CANTENCODEARGS);
164         }
165         (void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
166
167         /*
168          * We have to call server input routine here because this is
169          * all going on in one process. Yuk.
170          */
171         svc_getreq(1);
172
173         /*
174          * get results
175          */
176         xdrs->x_op = XDR_DECODE;
177         XDR_SETPOS(xdrs, 0);
178         msg.acpted_rply.ar_verf = gssrpc__null_auth;
179         msg.acpted_rply.ar_results.where = resultsp;
180         msg.acpted_rply.ar_results.proc = xresults;
181         if (! xdr_replymsg(xdrs, &msg)) {
182                 /*
183                  * It's possible for xdr_replymsg() to fail partway
184                  * through its attempt to decode the result from the
185                  * server. If this happens, it will leave the reply
186                  * structure partially populated with dynamically
187                  * allocated memory. (This can happen if someone uses
188                  * clntudp_bufcreate() to create a CLIENT handle and
189                  * specifies a receive buffer size that is too small.)
190                  * This memory must be free()ed to avoid a leak.
191                  */
192                 enum xdr_op op = xdrs->x_op;
193                 xdrs->x_op = XDR_FREE;
194                 xdr_replymsg(xdrs, &msg);
195                 xdrs->x_op = op;
196                 return (RPC_CANTDECODERES);
197         }
198         gssrpc__seterr_reply(&msg, &error);
199         status = error.re_status;
200
201         if (status == RPC_SUCCESS) {
202                 if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
203                         status = RPC_AUTHERROR;
204                 }
205         }  /* end successful completion */
206         else {
207                 if (AUTH_REFRESH(h->cl_auth, &msg))
208                         goto call_again;
209         }  /* end of unsuccessful completion */
210
211         if (status == RPC_SUCCESS) {
212                 if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
213                         status = RPC_AUTHERROR;
214                 }
215                 if (msg.acpted_rply.ar_verf.oa_base != NULL) {
216                         xdrs->x_op = XDR_FREE;
217                         (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
218                 }
219         }
220
221         return (status);
222 }
223
224 /*ARGSUSED*/
225 static void
226 clntraw_geterr(
227         CLIENT *cl,
228         struct rpc_err *err)
229 {
230 }
231
232
233 static bool_t
234 clntraw_freeres(
235         CLIENT *cl,
236         xdrproc_t xdr_res,
237         void *res_ptr)
238 {
239         register struct clntraw_private *clp = clntraw_private;
240         register XDR *xdrs = &clp->xdr_stream;
241         bool_t rval;
242
243         if (clp == 0)
244         {
245                 rval = (bool_t) RPC_FAILED;
246                 return (rval);
247         }
248         xdrs->x_op = XDR_FREE;
249         return ((*xdr_res)(xdrs, res_ptr));
250 }
251
252 /*ARGSUSED*/
253 static void
254 clntraw_abort(CLIENT *cl)
255 {
256 }
257
258 /*ARGSUSED*/
259 static bool_t
260 clntraw_control(
261         CLIENT *cl,
262         int request,
263         void *info)
264 {
265         return (FALSE);
266 }
267
268 /*ARGSUSED*/
269 static void
270 clntraw_destroy(CLIENT *cl)
271 {
272 }