xref: /titanic_51/usr/src/lib/libnsl/rpc/clnt_raw.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
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  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27 /*
28  * Portions of this source code were derived from Berkeley
29  * 4.3 BSD under license from the Regents of the University of
30  * California.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
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 similate 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 <rpc/rpc.h>
46 #include <rpc/trace.h>
47 #include <rpc/raw.h>
48 #include <syslog.h>
49 
50 extern mutex_t	clntraw_lock;
51 #define	MCALL_MSG_SIZE 24
52 #ifndef UDPMSGSIZE
53 #define	UDPMSGSIZE 8800
54 #endif
55 
56 /*
57  * This is the "network" we will be moving stuff over.
58  */
59 static struct clnt_raw_private {
60 	CLIENT	client_object;
61 	XDR	xdr_stream;
62 	char	*raw_buf;	/* should be shared with server handle */
63 	char	mashl_callmsg[MCALL_MSG_SIZE];
64 	uint_t	mcnt;
65 } *clnt_raw_private;
66 
67 static struct clnt_ops *clnt_raw_ops();
68 
69 extern char	*calloc();
70 extern void	free();
71 extern void svc_getreq_common(int);
72 extern bool_t xdr_opaque_auth();
73 
74 /*
75  * Create a client handle for memory based rpc.
76  */
77 CLIENT *
78 clnt_raw_create(rpcprog_t prog, rpcvers_t vers)
79 {
80 	struct clnt_raw_private *clp;
81 	struct rpc_msg call_msg;
82 	XDR *xdrs;
83 	CLIENT *client;
84 
85 /* VARIABLES PROTECTED BY clntraw_lock: clp */
86 
87 	trace3(TR_clnt_raw_create, 0, prog, vers);
88 	mutex_lock(&clntraw_lock);
89 	clp = clnt_raw_private;
90 	if (clp == NULL) {
91 /* LINTED pointer alignment */
92 		clp = (struct clnt_raw_private *)calloc(1, sizeof (*clp));
93 		if (clp == NULL) {
94 			mutex_unlock(&clntraw_lock);
95 			trace3(TR_clnt_raw_create, 1, prog, vers);
96 			return ((CLIENT *)NULL);
97 		}
98 		if (_rawcombuf == NULL) {
99 			_rawcombuf = (char *)calloc(UDPMSGSIZE, sizeof (char));
100 			if (_rawcombuf == NULL) {
101 				syslog(LOG_ERR, "clnt_raw_create: "
102 					"out of memory.");
103 				if (clp)
104 					free(clp);
105 				mutex_unlock(&clntraw_lock);
106 				trace3(TR_clnt_raw_create, 1, prog, vers);
107 				return ((CLIENT *)NULL);
108 			}
109 		}
110 		clp->raw_buf = _rawcombuf; /* Share it with the server */
111 		clnt_raw_private = clp;
112 	}
113 	xdrs = &clp->xdr_stream;
114 	client = &clp->client_object;
115 
116 	/*
117 	 * pre-serialize the static part of the call msg and stash it away
118 	 */
119 	call_msg.rm_direction = CALL;
120 	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
121 	call_msg.rm_call.cb_prog = prog;
122 	call_msg.rm_call.cb_vers = vers;
123 	xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
124 	if (! xdr_callhdr(xdrs, &call_msg))
125 		(void) syslog(LOG_ERR,
126 			(const char *) "clnt_raw_create :  \
127 			Fatal header serialization error.");
128 
129 	clp->mcnt = XDR_GETPOS(xdrs);
130 	XDR_DESTROY(xdrs);
131 
132 	/*
133 	 * Set xdrmem for client/server shared buffer
134 	 */
135 	xdrmem_create(xdrs, clp->raw_buf, UDPMSGSIZE, XDR_FREE);
136 
137 	/*
138 	 * create client handle
139 	 */
140 	client->cl_ops = clnt_raw_ops();
141 	client->cl_auth = authnone_create();
142 	mutex_unlock(&clntraw_lock);
143 	trace3(TR_clnt_raw_create, 1, prog, vers);
144 	return (client);
145 }
146 
147 /*ARGSUSED*/
148 static enum clnt_stat
149 clnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp,
150 	xdrproc_t xresults, caddr_t resultsp, struct timeval timeout)
151 {
152 	struct clnt_raw_private *clp;
153 	XDR *xdrs;
154 	struct rpc_msg msg;
155 	enum clnt_stat status;
156 	struct rpc_err error;
157 
158 	trace3(TR_clnt_raw_call, 0, h, proc);
159 	mutex_lock(&clntraw_lock);
160 	clp = clnt_raw_private;
161 	xdrs = &clp->xdr_stream;
162 	if (clp == NULL) {
163 		mutex_unlock(&clntraw_lock);
164 		trace3(TR_clnt_raw_call, 1, h, proc);
165 		return (RPC_FAILED);
166 	}
167 	mutex_unlock(&clntraw_lock);
168 
169 call_again:
170 	/*
171 	 * send request
172 	 */
173 	xdrs->x_op = XDR_ENCODE;
174 	XDR_SETPOS(xdrs, 0);
175 /* LINTED pointer alignment */
176 	((struct rpc_msg *)clp->mashl_callmsg)->rm_xid++;
177 	if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
178 	    (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
179 	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
180 	    (! (*xargs)(xdrs, argsp))) {
181 		trace3(TR_clnt_raw_call, 1, h, proc);
182 		return (RPC_CANTENCODEARGS);
183 	}
184 	(void) XDR_GETPOS(xdrs);  /* called just to cause overhead */
185 
186 	/*
187 	 * We have to call server input routine here because this is
188 	 * all going on in one process.
189 	 * By convention using FD_SETSIZE as the psuedo file descriptor.
190 	 */
191 	svc_getreq_common(FD_SETSIZE);
192 
193 	/*
194 	 * get results
195 	 */
196 	xdrs->x_op = XDR_DECODE;
197 	XDR_SETPOS(xdrs, 0);
198 	msg.acpted_rply.ar_verf = _null_auth;
199 	msg.acpted_rply.ar_results.where = resultsp;
200 	msg.acpted_rply.ar_results.proc = xresults;
201 	if (! xdr_replymsg(xdrs, &msg)) {
202 		trace3(TR_clnt_raw_call, 1, h, proc);
203 		return (RPC_CANTDECODERES);
204 	}
205 	if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
206 		    (msg.acpted_rply.ar_stat == SUCCESS))
207 		status = RPC_SUCCESS;
208 	else {
209 		__seterr_reply(&msg, &error);
210 		status = error.re_status;
211 	}
212 
213 	if (status == RPC_SUCCESS) {
214 		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
215 			status = RPC_AUTHERROR;
216 		}
217 		/* end successful completion */
218 	} else {
219 		if (AUTH_REFRESH(h->cl_auth, &msg))
220 			goto call_again;
221 		/* end of unsuccessful completion */
222 	}
223 
224 	if (status == RPC_SUCCESS) {
225 		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
226 			status = RPC_AUTHERROR;
227 		}
228 		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
229 			xdrs->x_op = XDR_FREE;
230 			(void) xdr_opaque_auth(xdrs,
231 					&(msg.acpted_rply.ar_verf));
232 		}
233 	}
234 	trace3(TR_clnt_raw_call, 1, h, proc);
235 	return (status);
236 }
237 
238 /*ARGSUSED*/
239 static enum clnt_stat
240 clnt_raw_send(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp)
241 {
242 	struct clnt_raw_private *clp;
243 	XDR *xdrs;
244 
245 	trace3(TR_clnt_raw_send, 0, h, proc);
246 
247 	mutex_lock(&clntraw_lock);
248 	clp = clnt_raw_private;
249 	xdrs = &clp->xdr_stream;
250 	if (clp == NULL) {
251 		mutex_unlock(&clntraw_lock);
252 		trace3(TR_clnt_raw_send, 1, h, proc);
253 		return (RPC_FAILED);
254 	}
255 	mutex_unlock(&clntraw_lock);
256 
257 	/*
258 	 * send request
259 	 */
260 	xdrs->x_op = XDR_ENCODE;
261 	XDR_SETPOS(xdrs, 0);
262 /* LINTED pointer alignment */
263 	((struct rpc_msg *)clp->mashl_callmsg)->rm_xid++;
264 	if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
265 	    (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
266 	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
267 	    (! (*xargs)(xdrs, argsp))) {
268 		trace3(TR_clnt_raw_send, 1, h, proc);
269 		return (RPC_CANTENCODEARGS);
270 	}
271 	(void) XDR_GETPOS(xdrs);  /* called just to cause overhead */
272 
273 	/*
274 	 * We have to call server input routine here because this is
275 	 * all going on in one process.
276 	 * By convention using FD_SETSIZE as the psuedo file descriptor.
277 	 */
278 	svc_getreq_common(FD_SETSIZE);
279 
280 	return (RPC_SUCCESS);
281 }
282 
283 /*ARGSUSED*/
284 static void
285 clnt_raw_geterr(CLIENT *cl, struct rpc_err *errp)
286 {
287 	trace1(TR_clnt_raw_geterr, 0);
288 	trace1(TR_clnt_raw_geterr, 1);
289 }
290 
291 /*ARGSUSED*/
292 static bool_t
293 clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
294 {
295 	struct clnt_raw_private *clp;
296 	XDR *xdrs;
297 	static bool_t dummy;
298 
299 	trace2(TR_clnt_raw_freeres, 0, cl);
300 	mutex_lock(&clntraw_lock);
301 	clp = clnt_raw_private;
302 	xdrs = &clp->xdr_stream;
303 	if (clp == NULL) {
304 		mutex_unlock(&clntraw_lock);
305 		trace2(TR_clnt_raw_freeres, 1, cl);
306 		return (FALSE);
307 	}
308 	mutex_unlock(&clntraw_lock);
309 	xdrs->x_op = XDR_FREE;
310 	dummy  = (*xdr_res)(xdrs, res_ptr);
311 	trace2(TR_clnt_raw_freeres, 1, cl);
312 	return (dummy);
313 }
314 
315 /*ARGSUSED*/
316 static void
317 clnt_raw_abort(CLIENT *cl, struct rpc_err *errp)
318 {
319 	trace1(TR_clnt_raw_abort, 0);
320 	trace1(TR_clnt_raw_abort, 1);
321 }
322 
323 /*ARGSUSED*/
324 static bool_t
325 clnt_raw_control(CLIENT *cl, int request, char *info)
326 {
327 	trace1(TR_clnt_raw_control, 0);
328 	trace1(TR_clnt_raw_control, 1);
329 	return (FALSE);
330 }
331 
332 /*ARGSUSED*/
333 static void
334 clnt_raw_destroy(CLIENT *cl)
335 {
336 	trace1(TR_clnt_raw_destroy, 0);
337 	trace1(TR_clnt_raw_destroy, 1);
338 }
339 
340 static struct clnt_ops *
341 clnt_raw_ops(void)
342 {
343 	static struct clnt_ops ops;
344 	extern mutex_t	ops_lock;
345 
346 	/* VARIABLES PROTECTED BY ops_lock: ops */
347 
348 	trace1(TR_clnt_raw_ops, 0);
349 	mutex_lock(&ops_lock);
350 	if (ops.cl_call == NULL) {
351 		ops.cl_call = clnt_raw_call;
352 		ops.cl_send = clnt_raw_send;
353 		ops.cl_abort = clnt_raw_abort;
354 		ops.cl_geterr = clnt_raw_geterr;
355 		ops.cl_freeres = clnt_raw_freeres;
356 		ops.cl_destroy = clnt_raw_destroy;
357 		ops.cl_control = clnt_raw_control;
358 	}
359 	mutex_unlock(&ops_lock);
360 	trace1(TR_clnt_raw_ops, 1);
361 	return (&ops);
362 }
363