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 kernel.
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 *
clntraw_create(rpcprog_t prog,rpcvers_t vers)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
clntraw_call(CLIENT * h,rpcproc_t proc,xdrproc_t xargs,void * argsp,xdrproc_t xresults,void * resultsp,struct timeval timeout)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 struct clntraw_private *clp = clntraw_private;
144 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
clntraw_geterr(CLIENT * cl,struct rpc_err * err)226 clntraw_geterr(
227 CLIENT *cl,
228 struct rpc_err *err)
229 {
230 }
231
232
233 static bool_t
clntraw_freeres(CLIENT * cl,xdrproc_t xdr_res,void * res_ptr)234 clntraw_freeres(
235 CLIENT *cl,
236 xdrproc_t xdr_res,
237 void *res_ptr)
238 {
239 struct clntraw_private *clp = clntraw_private;
240 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
clntraw_abort(CLIENT * cl)254 clntraw_abort(CLIENT *cl)
255 {
256 }
257
258 /*ARGSUSED*/
259 static bool_t
clntraw_control(CLIENT * cl,int request,void * info)260 clntraw_control(
261 CLIENT *cl,
262 int request,
263 void *info)
264 {
265 return (FALSE);
266 }
267
268 /*ARGSUSED*/
269 static void
clntraw_destroy(CLIENT * cl)270 clntraw_destroy(CLIENT *cl)
271 {
272 }
273