xref: /netbsd-src/lib/libc/rpc/clnt_raw.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: clnt_raw.c,v 1.13 1998/11/15 17:27:35 christos Exp $	*/
2 
3 /*
4  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5  * unrestricted use provided that this legend is included on all tape
6  * media and as a part of the software program in whole or part.  Users
7  * may copy or modify Sun RPC without charge, but are not authorized
8  * to license or distribute it to anyone else except as part of a product or
9  * program developed by the user.
10  *
11  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
14  *
15  * Sun RPC is provided with no support and without any obligation on the
16  * part of Sun Microsystems, Inc. to assist in its use, correction,
17  * modification or enhancement.
18  *
19  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21  * OR ANY PART THEREOF.
22  *
23  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24  * or profits or other special, indirect and consequential damages, even if
25  * Sun has been advised of the possibility of such damages.
26  *
27  * Sun Microsystems, Inc.
28  * 2550 Garcia Avenue
29  * Mountain View, California  94043
30  */
31 
32 #include <sys/cdefs.h>
33 #if defined(LIBC_SCCS) && !defined(lint)
34 #if 0
35 static char *sccsid = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
36 static char *sccsid = "@(#)clnt_raw.c	2.2 88/08/01 4.0 RPCSRC";
37 #else
38 __RCSID("$NetBSD: clnt_raw.c,v 1.13 1998/11/15 17:27:35 christos Exp $");
39 #endif
40 #endif
41 
42 /*
43  * clnt_raw.c
44  *
45  * Copyright (C) 1984, Sun Microsystems, Inc.
46  *
47  * Memory based rpc for simple testing and timing.
48  * Interface to create an rpc client and server in the same process.
49  * This lets us similate rpc and get round trip overhead, without
50  * any interference from the kernal.
51  */
52 
53 #include "namespace.h"
54 
55 #include <err.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 
59 #include <rpc/rpc.h>
60 
61 #ifdef __weak_alias
62 __weak_alias(clntraw_create,_clntraw_create);
63 #endif
64 
65 #define MCALL_MSG_SIZE 24
66 
67 /*
68  * This is the "network" we will be moving stuff over.
69  */
70 static struct clntraw_private {
71 	CLIENT	client_object;
72 	XDR	xdr_stream;
73 	char	_raw_buf[UDPMSGSIZE];
74 	union {
75 	    struct rpc_msg	mashl_rpcmsg;
76 	    char 		mashl_callmsg[MCALL_MSG_SIZE];
77 	} u;
78 	u_int	mcnt;
79 } *clntraw_private;
80 
81 
82 
83 static enum clnt_stat clntraw_call __P((CLIENT *, u_long, xdrproc_t,
84     caddr_t, xdrproc_t, caddr_t, struct timeval));
85 static void clntraw_geterr __P((CLIENT *, struct rpc_err *));
86 static bool_t clntraw_freeres __P((CLIENT *, xdrproc_t, caddr_t));
87 static void clntraw_abort __P((CLIENT *));
88 static bool_t clntraw_control __P((CLIENT *, u_int, char *));
89 static void clntraw_destroy __P((CLIENT *));
90 
91 static const struct clnt_ops client_ops = {
92 	clntraw_call,
93 	clntraw_abort,
94 	clntraw_geterr,
95 	clntraw_freeres,
96 	clntraw_destroy,
97 	clntraw_control
98 };
99 
100 /*
101  * Create a client handle for memory based rpc.
102  */
103 CLIENT *
104 clntraw_create(prog, vers)
105 	u_long prog;
106 	u_long vers;
107 {
108 	struct clntraw_private *clp = clntraw_private;
109 	struct rpc_msg call_msg;
110 	XDR *xdrs = &clp->xdr_stream;
111 	CLIENT	*client = &clp->client_object;
112 
113 	if (clp == 0) {
114 		clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
115 		if (clp == 0)
116 			return (0);
117 		clntraw_private = clp;
118 	}
119 	/*
120 	 * pre-serialize the static part of the call msg and stash it away
121 	 */
122 	call_msg.rm_direction = CALL;
123 	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
124 	/* XXX: prog and vers have been long historically :-( */
125 	call_msg.rm_call.cb_prog = (u_int32_t)prog;
126 	call_msg.rm_call.cb_vers = (u_int32_t)vers;
127 	xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
128 	if (! xdr_callhdr(xdrs, &call_msg))
129 		warnx("clntraw_create - Fatal header serialization error.");
130 	clp->mcnt = XDR_GETPOS(xdrs);
131 	XDR_DESTROY(xdrs);
132 
133 	/*
134 	 * Set xdrmem for client/server shared buffer
135 	 */
136 	xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
137 
138 	/*
139 	 * create client handle
140 	 */
141 	client->cl_ops = &client_ops;
142 	client->cl_auth = authnone_create();
143 	return (client);
144 }
145 
146 /* ARGSUSED */
147 static enum clnt_stat
148 clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
149 	CLIENT *h;
150 	u_long proc;
151 	xdrproc_t xargs;
152 	caddr_t argsp;
153 	xdrproc_t xresults;
154 	caddr_t resultsp;
155 	struct timeval timeout;
156 {
157 	struct clntraw_private *clp = clntraw_private;
158 	XDR *xdrs = &clp->xdr_stream;
159 	struct rpc_msg msg;
160 	enum clnt_stat status;
161 	struct rpc_err error;
162 
163 	if (clp == 0)
164 		return (RPC_FAILED);
165 call_again:
166 	/*
167 	 * send request
168 	 */
169 	xdrs->x_op = XDR_ENCODE;
170 	XDR_SETPOS(xdrs, 0);
171 	clp->u.mashl_rpcmsg.rm_xid ++ ;
172 	if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
173 	    (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
174 	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
175 	    (! (*xargs)(xdrs, argsp))) {
176 		return (RPC_CANTENCODEARGS);
177 	}
178 	(void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
179 
180 	/*
181 	 * We have to call server input routine here because this is
182 	 * all going on in one process. Yuk.
183 	 */
184 	svc_getreq(1);
185 
186 	/*
187 	 * get results
188 	 */
189 	xdrs->x_op = XDR_DECODE;
190 	XDR_SETPOS(xdrs, 0);
191 	msg.acpted_rply.ar_verf = _null_auth;
192 	msg.acpted_rply.ar_results.where = resultsp;
193 	msg.acpted_rply.ar_results.proc = xresults;
194 	if (! xdr_replymsg(xdrs, &msg)) {
195 		/*
196 		 * It's possible for xdr_replymsg() to fail partway
197 		 * through its attempt to decode the result from the
198 		 * server. If this happens, it will leave the reply
199 		 * structure partially populated with dynamically
200 		 * allocated memory. (This can happen if someone uses
201 		 * clntudp_bufcreate() to create a CLIENT handle and
202 		 * specifies a receive buffer size that is too small.)
203 		 * This memory must be free()ed to avoid a leak.
204 		 */
205 		int op = xdrs->x_op;
206 		xdrs->x_op = XDR_FREE;
207 		xdr_replymsg(xdrs, &msg);
208 		xdrs->x_op = op;
209 		return (RPC_CANTDECODERES);
210 	}
211 	_seterr_reply(&msg, &error);
212 	status = error.re_status;
213 
214 	if (status == RPC_SUCCESS) {
215 		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
216 			status = RPC_AUTHERROR;
217 		}
218 	}  /* end successful completion */
219 	else {
220 		if (AUTH_REFRESH(h->cl_auth))
221 			goto call_again;
222 	}  /* end of unsuccessful completion */
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, &(msg.acpted_rply.ar_verf));
231 		}
232 	}
233 
234 	return (status);
235 }
236 
237 /*ARGSUSED*/
238 static void
239 clntraw_geterr(cl, err)
240 	CLIENT *cl;
241 	struct rpc_err *err;
242 {
243 }
244 
245 
246 /* ARGSUSED */
247 static bool_t
248 clntraw_freeres(cl, xdr_res, res_ptr)
249 	CLIENT *cl;
250 	xdrproc_t xdr_res;
251 	caddr_t res_ptr;
252 {
253 	struct clntraw_private *clp = clntraw_private;
254 	XDR *xdrs = &clp->xdr_stream;
255 	bool_t rval;
256 
257 	if (clp == 0)
258 	{
259 		rval = (bool_t) RPC_FAILED;
260 		return (rval);
261 	}
262 	xdrs->x_op = XDR_FREE;
263 	return ((*xdr_res)(xdrs, res_ptr));
264 }
265 
266 /*ARGSUSED*/
267 static void
268 clntraw_abort(cl)
269 	CLIENT *cl;
270 {
271 }
272 
273 /*ARGSUSED*/
274 static bool_t
275 clntraw_control(cl, ui, str)
276 	CLIENT *cl;
277 	u_int ui;
278 	char *str;
279 {
280 	return (FALSE);
281 }
282 
283 /*ARGSUSED*/
284 static void
285 clntraw_destroy(cl)
286 	CLIENT *cl;
287 {
288 }
289