1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 /*
30 * Portions of this source code were derived from Berkeley
31 * 4.3 BSD under license from the Regents of the University of
32 * California.
33 */
34
35 /*
36 * clnt_raw.c
37 *
38 * Memory based rpc for simple testing and timing.
39 * Interface to create an rpc client and server in the same process.
40 * This lets us simulate rpc and get round trip overhead, without
41 * any interference from the kernel.
42 */
43 #include "mt.h"
44 #include "rpc_mt.h"
45 #include <stdlib.h>
46 #include <rpc/rpc.h>
47 #include <syslog.h>
48
49 extern mutex_t clntraw_lock;
50 #define MCALL_MSG_SIZE 24
51
52 /*
53 * This is the "network" we will be moving stuff over.
54 */
55 static struct clnt_raw_private {
56 CLIENT client_object;
57 struct netbuf *raw_netbuf;
58 char mashl_callmsg[MCALL_MSG_SIZE];
59 uint_t mcnt;
60 } *clnt_raw_private;
61
62 static struct clnt_ops *clnt_raw_ops();
63
64 extern bool_t xdr_opaque_auth();
65
66 /*
67 * This netbuf is shared with the raw server.
68 */
69 extern struct netbuf _rawcomnetbuf;
70
71 /*
72 * Create a client handle for memory based rpc.
73 */
74 CLIENT *
clnt_raw_create(const rpcprog_t prog,const rpcvers_t vers)75 clnt_raw_create(const rpcprog_t prog, const rpcvers_t vers)
76 {
77 struct clnt_raw_private *clp;
78 struct rpc_msg call_msg;
79 XDR xdrs;
80 CLIENT *client;
81 uint_t start;
82
83 /* VARIABLES PROTECTED BY clntraw_lock: clp */
84
85 (void) mutex_lock(&clntraw_lock);
86 clp = clnt_raw_private;
87 if (clp != NULL) {
88 (void) mutex_unlock(&clntraw_lock);
89 return (&clp->client_object);
90 }
91
92 clp = calloc(1, sizeof (*clp));
93 if (clp == NULL) {
94 (void) mutex_unlock(&clntraw_lock);
95 return (NULL);
96 }
97
98 clp->raw_netbuf = &_rawcomnetbuf;
99
100 /*
101 * pre-serialize the static part of the call msg and stash it away
102 */
103 call_msg.rm_direction = CALL;
104 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
105 call_msg.rm_call.cb_prog = prog;
106 call_msg.rm_call.cb_vers = vers;
107
108 xdrmem_create(&xdrs, clp->mashl_callmsg, sizeof (clp->mashl_callmsg),
109 XDR_ENCODE);
110 start = XDR_GETPOS(&xdrs);
111 if (!xdr_callhdr(&xdrs, &call_msg)) {
112 free(clp);
113 (void) syslog(LOG_ERR,
114 "clnt_raw_create: Fatal header serialization error");
115
116 (void) mutex_unlock(&clntraw_lock);
117 return (NULL);
118 }
119 clp->mcnt = XDR_GETPOS(&xdrs) - start;
120 XDR_DESTROY(&xdrs);
121
122 /*
123 * create client handle
124 */
125 client = &clp->client_object;
126 client->cl_ops = clnt_raw_ops();
127 client->cl_auth = authnone_create();
128
129 clnt_raw_private = clp;
130
131 (void) mutex_unlock(&clntraw_lock);
132 return (client);
133 }
134
135 /*ARGSUSED*/
136 static enum clnt_stat
clnt_raw_call(CLIENT * h,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp,xdrproc_t xresults,caddr_t resultsp,struct timeval timeout)137 clnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp,
138 xdrproc_t xresults, caddr_t resultsp, struct timeval timeout)
139 {
140 struct clnt_raw_private *clp;
141 XDR xdrs;
142 struct rpc_msg msg;
143 uint_t start;
144
145 rpc_callerr.re_errno = 0;
146 rpc_callerr.re_terrno = 0;
147
148 (void) mutex_lock(&clntraw_lock);
149 clp = clnt_raw_private;
150 if (clp == NULL) {
151 (void) mutex_unlock(&clntraw_lock);
152 return (rpc_callerr.re_status = RPC_FAILED);
153 }
154 (void) mutex_unlock(&clntraw_lock);
155
156 call_again:
157 /*
158 * send request
159 */
160 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->maxlen,
161 XDR_ENCODE);
162 start = XDR_GETPOS(&xdrs);
163 /* LINTED pointer alignment */
164 ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid++;
165 if ((!XDR_PUTBYTES(&xdrs, clp->mashl_callmsg, clp->mcnt)) ||
166 (!XDR_PUTINT32(&xdrs, (int32_t *)&proc)) ||
167 (!AUTH_MARSHALL(h->cl_auth, &xdrs)) ||
168 (!(*xargs)(&xdrs, argsp))) {
169 XDR_DESTROY(&xdrs);
170 return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
171 }
172 clp->raw_netbuf->len = XDR_GETPOS(&xdrs) - start;
173 XDR_DESTROY(&xdrs);
174
175 /*
176 * We have to call server input routine here because this is
177 * all going on in one process.
178 * By convention using FD_SETSIZE as the pseudo file descriptor.
179 */
180 svc_getreq_common(FD_SETSIZE);
181
182 /*
183 * get results
184 */
185 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->len,
186 XDR_DECODE);
187 msg.acpted_rply.ar_verf = _null_auth;
188 msg.acpted_rply.ar_results.where = resultsp;
189 msg.acpted_rply.ar_results.proc = xresults;
190 if (!xdr_replymsg(&xdrs, &msg)) {
191 XDR_DESTROY(&xdrs);
192 return (rpc_callerr.re_status = RPC_CANTDECODERES);
193 }
194 XDR_DESTROY(&xdrs);
195 if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
196 (msg.acpted_rply.ar_stat == SUCCESS))
197 rpc_callerr.re_status = RPC_SUCCESS;
198 else
199 __seterr_reply(&msg, &rpc_callerr);
200
201 if (rpc_callerr.re_status == RPC_SUCCESS) {
202 if (!AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
203 rpc_callerr.re_status = RPC_AUTHERROR;
204 rpc_callerr.re_why = AUTH_INVALIDRESP;
205 }
206 if (msg.acpted_rply.ar_verf.oa_base != NULL) {
207 xdr_free(xdr_opaque_auth,
208 (char *)&(msg.acpted_rply.ar_verf));
209 }
210 /* end successful completion */
211 } else {
212 if (AUTH_REFRESH(h->cl_auth, &msg))
213 goto call_again;
214 /* end of unsuccessful completion */
215 }
216
217 return (rpc_callerr.re_status);
218 }
219
220 /*ARGSUSED*/
221 static enum clnt_stat
clnt_raw_send(CLIENT * h,rpcproc_t proc,xdrproc_t xargs,caddr_t argsp)222 clnt_raw_send(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp)
223 {
224 struct clnt_raw_private *clp;
225 XDR xdrs;
226 uint_t start;
227
228 rpc_callerr.re_errno = 0;
229 rpc_callerr.re_terrno = 0;
230
231 (void) mutex_lock(&clntraw_lock);
232 clp = clnt_raw_private;
233 if (clp == NULL) {
234 (void) mutex_unlock(&clntraw_lock);
235 return (rpc_callerr.re_status = RPC_FAILED);
236 }
237 (void) mutex_unlock(&clntraw_lock);
238
239 /*
240 * send request
241 */
242 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->maxlen,
243 XDR_ENCODE);
244 start = XDR_GETPOS(&xdrs);
245 /* LINTED pointer alignment */
246 ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid++;
247 if ((!XDR_PUTBYTES(&xdrs, clp->mashl_callmsg, clp->mcnt)) ||
248 (!XDR_PUTINT32(&xdrs, (int32_t *)&proc)) ||
249 (!AUTH_MARSHALL(h->cl_auth, &xdrs)) ||
250 (!(*xargs)(&xdrs, argsp))) {
251 XDR_DESTROY(&xdrs);
252 return (rpc_callerr.re_status = RPC_CANTENCODEARGS);
253 }
254 clp->raw_netbuf->len = XDR_GETPOS(&xdrs) - start;
255 XDR_DESTROY(&xdrs);
256
257 /*
258 * We have to call server input routine here because this is
259 * all going on in one process.
260 * By convention using FD_SETSIZE as the pseudo file descriptor.
261 */
262 svc_getreq_common(FD_SETSIZE);
263
264 return (rpc_callerr.re_status = RPC_SUCCESS);
265 }
266
267 /*ARGSUSED*/
268 static void
clnt_raw_geterr(CLIENT * cl,struct rpc_err * errp)269 clnt_raw_geterr(CLIENT *cl, struct rpc_err *errp)
270 {
271 *errp = rpc_callerr;
272 }
273
274 /*ARGSUSED*/
275 static bool_t
clnt_raw_freeres(CLIENT * cl,xdrproc_t xdr_res,caddr_t res_ptr)276 clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
277 {
278 struct clnt_raw_private *clp;
279
280 (void) mutex_lock(&clntraw_lock);
281 clp = clnt_raw_private;
282 if (clp == NULL) {
283 (void) mutex_unlock(&clntraw_lock);
284 return (FALSE);
285 }
286 (void) mutex_unlock(&clntraw_lock);
287
288 xdr_free(xdr_res, res_ptr);
289
290 return (TRUE);
291 }
292
293 /*ARGSUSED*/
294 static void
clnt_raw_abort(CLIENT * cl,struct rpc_err * errp)295 clnt_raw_abort(CLIENT *cl, struct rpc_err *errp)
296 {
297 }
298
299 /*ARGSUSED*/
300 static bool_t
clnt_raw_control(CLIENT * cl,int request,char * info)301 clnt_raw_control(CLIENT *cl, int request, char *info)
302 {
303 return (FALSE);
304 }
305
306 /*ARGSUSED*/
307 static void
clnt_raw_destroy(CLIENT * cl)308 clnt_raw_destroy(CLIENT *cl)
309 {
310 }
311
312 static struct clnt_ops *
clnt_raw_ops(void)313 clnt_raw_ops(void)
314 {
315 static struct clnt_ops ops;
316 extern mutex_t ops_lock;
317
318 /* VARIABLES PROTECTED BY ops_lock: ops */
319
320 (void) mutex_lock(&ops_lock);
321 if (ops.cl_call == NULL) {
322 ops.cl_call = clnt_raw_call;
323 ops.cl_send = clnt_raw_send;
324 ops.cl_abort = clnt_raw_abort;
325 ops.cl_geterr = clnt_raw_geterr;
326 ops.cl_freeres = clnt_raw_freeres;
327 ops.cl_destroy = clnt_raw_destroy;
328 ops.cl_control = clnt_raw_control;
329 }
330 (void) mutex_unlock(&ops_lock);
331 return (&ops);
332 }
333