xref: /minix3/lib/libc/rpc/clnt_raw.c (revision 84d9c625bfea59e274550651111ae9edfdc40fbd)
1*84d9c625SLionel Sambuc /*	$NetBSD: clnt_raw.c,v 1.32 2013/03/11 20:19:29 tron Exp $	*/
22fe8fb19SBen Gras 
32fe8fb19SBen Gras /*
4*84d9c625SLionel Sambuc  * Copyright (c) 2010, Oracle America, Inc.
52fe8fb19SBen Gras  *
6*84d9c625SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
7*84d9c625SLionel Sambuc  * modification, are permitted provided that the following conditions are
8*84d9c625SLionel Sambuc  * met:
92fe8fb19SBen Gras  *
10*84d9c625SLionel Sambuc  *     * Redistributions of source code must retain the above copyright
11*84d9c625SLionel Sambuc  *       notice, this list of conditions and the following disclaimer.
12*84d9c625SLionel Sambuc  *     * Redistributions in binary form must reproduce the above
13*84d9c625SLionel Sambuc  *       copyright notice, this list of conditions and the following
14*84d9c625SLionel Sambuc  *       disclaimer in the documentation and/or other materials
15*84d9c625SLionel Sambuc  *       provided with the distribution.
16*84d9c625SLionel Sambuc  *     * Neither the name of the "Oracle America, Inc." nor the names of its
17*84d9c625SLionel Sambuc  *       contributors may be used to endorse or promote products derived
18*84d9c625SLionel Sambuc  *       from this software without specific prior written permission.
192fe8fb19SBen Gras  *
20*84d9c625SLionel Sambuc  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*84d9c625SLionel Sambuc  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*84d9c625SLionel Sambuc  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*84d9c625SLionel Sambuc  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24*84d9c625SLionel Sambuc  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25*84d9c625SLionel Sambuc  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*84d9c625SLionel Sambuc  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27*84d9c625SLionel Sambuc  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*84d9c625SLionel Sambuc  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29*84d9c625SLionel Sambuc  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30*84d9c625SLionel Sambuc  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*84d9c625SLionel Sambuc  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322fe8fb19SBen Gras  */
332fe8fb19SBen Gras 
342fe8fb19SBen Gras #include <sys/cdefs.h>
352fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
362fe8fb19SBen Gras #if 0
372fe8fb19SBen Gras static char *sccsid = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
382fe8fb19SBen Gras static char *sccsid = "@(#)clnt_raw.c	2.2 88/08/01 4.0 RPCSRC";
392fe8fb19SBen Gras #else
40*84d9c625SLionel Sambuc __RCSID("$NetBSD: clnt_raw.c,v 1.32 2013/03/11 20:19:29 tron Exp $");
412fe8fb19SBen Gras #endif
422fe8fb19SBen Gras #endif
432fe8fb19SBen Gras 
442fe8fb19SBen Gras /*
452fe8fb19SBen Gras  * clnt_raw.c
462fe8fb19SBen Gras  *
472fe8fb19SBen Gras  * Copyright (C) 1984, Sun Microsystems, Inc.
482fe8fb19SBen Gras  *
492fe8fb19SBen Gras  * Memory based rpc for simple testing and timing.
502fe8fb19SBen Gras  * Interface to create an rpc client and server in the same process.
512fe8fb19SBen Gras  * This lets us similate rpc and get round trip overhead, without
522fe8fb19SBen Gras  * any interference from the kernel.
532fe8fb19SBen Gras  */
542fe8fb19SBen Gras 
552fe8fb19SBen Gras #include "namespace.h"
562fe8fb19SBen Gras #include "reentrant.h"
572fe8fb19SBen Gras #include <assert.h>
582fe8fb19SBen Gras #include <err.h>
592fe8fb19SBen Gras #include <stdio.h>
602fe8fb19SBen Gras #include <stdlib.h>
612fe8fb19SBen Gras 
622fe8fb19SBen Gras #include <rpc/rpc.h>
632fe8fb19SBen Gras #include <rpc/raw.h>
642fe8fb19SBen Gras 
652fe8fb19SBen Gras #ifdef __weak_alias
662fe8fb19SBen Gras __weak_alias(clntraw_create,_clntraw_create)
672fe8fb19SBen Gras __weak_alias(clnt_raw_create,_clnt_raw_create)
682fe8fb19SBen Gras #endif
692fe8fb19SBen Gras 
702fe8fb19SBen Gras #ifdef _REENTRANT
712fe8fb19SBen Gras extern mutex_t clntraw_lock;
722fe8fb19SBen Gras #endif
732fe8fb19SBen Gras 
742fe8fb19SBen Gras #define MCALL_MSG_SIZE 24
752fe8fb19SBen Gras 
762fe8fb19SBen Gras /*
772fe8fb19SBen Gras  * This is the "network" we will be moving stuff over.
782fe8fb19SBen Gras  */
792fe8fb19SBen Gras static struct clntraw_private {
802fe8fb19SBen Gras 	CLIENT	client_object;
812fe8fb19SBen Gras 	XDR	xdr_stream;
822fe8fb19SBen Gras 	char	*_raw_buf;
832fe8fb19SBen Gras 	union {
842fe8fb19SBen Gras 	    struct rpc_msg	mashl_rpcmsg;
852fe8fb19SBen Gras 	    char 		mashl_callmsg[MCALL_MSG_SIZE];
862fe8fb19SBen Gras 	} u;
872fe8fb19SBen Gras 	u_int	mcnt;
882fe8fb19SBen Gras } *clntraw_private;
892fe8fb19SBen Gras 
90f14fb602SLionel Sambuc static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t,
91f14fb602SLionel Sambuc     const char *, xdrproc_t, caddr_t, struct timeval);
92f14fb602SLionel Sambuc static void clnt_raw_geterr(CLIENT *, struct rpc_err *);
93f14fb602SLionel Sambuc static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, caddr_t);
94f14fb602SLionel Sambuc static void clnt_raw_abort(CLIENT *);
95f14fb602SLionel Sambuc static bool_t clnt_raw_control(CLIENT *, u_int, char *);
96f14fb602SLionel Sambuc static void clnt_raw_destroy(CLIENT *);
97f14fb602SLionel Sambuc static struct clnt_ops *clnt_raw_ops(void);
982fe8fb19SBen Gras 
992fe8fb19SBen Gras /*
1002fe8fb19SBen Gras  * Create a client handle for memory based rpc.
1012fe8fb19SBen Gras  */
1022fe8fb19SBen Gras CLIENT *
clnt_raw_create(rpcprog_t prog,rpcvers_t vers)103f14fb602SLionel Sambuc clnt_raw_create(rpcprog_t prog, rpcvers_t vers)
1042fe8fb19SBen Gras {
1052fe8fb19SBen Gras 	struct clntraw_private *clp = clntraw_private;
1062fe8fb19SBen Gras 	struct rpc_msg call_msg;
1072fe8fb19SBen Gras 	XDR *xdrs = &clp->xdr_stream;
1082fe8fb19SBen Gras 	CLIENT	*client = &clp->client_object;
1092fe8fb19SBen Gras 
1102fe8fb19SBen Gras 	mutex_lock(&clntraw_lock);
1112fe8fb19SBen Gras 	if (clp == NULL) {
1122fe8fb19SBen Gras 		clp = calloc((size_t)1, sizeof (*clp));
1132fe8fb19SBen Gras 		if (clp == NULL)
1142fe8fb19SBen Gras 			goto out;
1152fe8fb19SBen Gras 		if (__rpc_rawcombuf == NULL)
1162fe8fb19SBen Gras 			__rpc_rawcombuf =
1172fe8fb19SBen Gras 			    malloc(UDPMSGSIZE);
1182fe8fb19SBen Gras 		if (__rpc_rawcombuf == NULL)
1192fe8fb19SBen Gras 			goto out;
1202fe8fb19SBen Gras 		clp->_raw_buf = __rpc_rawcombuf;
1212fe8fb19SBen Gras 		clntraw_private = clp;
1222fe8fb19SBen Gras 	}
1232fe8fb19SBen Gras 	/*
1242fe8fb19SBen Gras 	 * pre-serialize the static part of the call msg and stash it away
1252fe8fb19SBen Gras 	 */
1262fe8fb19SBen Gras 	call_msg.rm_direction = CALL;
1272fe8fb19SBen Gras 	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
1282fe8fb19SBen Gras 	/* XXX: prog and vers have been long historically :-( */
1292fe8fb19SBen Gras 	call_msg.rm_call.cb_prog = (u_int32_t)prog;
1302fe8fb19SBen Gras 	call_msg.rm_call.cb_vers = (u_int32_t)vers;
1312fe8fb19SBen Gras 	xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
1322fe8fb19SBen Gras 	if (! xdr_callhdr(xdrs, &call_msg))
133*84d9c625SLionel Sambuc 		warnx("%s: Fatal header serialization error", __func__);
1342fe8fb19SBen Gras 	clp->mcnt = XDR_GETPOS(xdrs);
1352fe8fb19SBen Gras 	XDR_DESTROY(xdrs);
1362fe8fb19SBen Gras 
1372fe8fb19SBen Gras 	/*
1382fe8fb19SBen Gras 	 * Set xdrmem for client/server shared buffer
1392fe8fb19SBen Gras 	 */
1402fe8fb19SBen Gras 	xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
1412fe8fb19SBen Gras 
1422fe8fb19SBen Gras 	/*
1432fe8fb19SBen Gras 	 * create client handle
1442fe8fb19SBen Gras 	 */
1452fe8fb19SBen Gras 	client->cl_ops = clnt_raw_ops();
1462fe8fb19SBen Gras 	client->cl_auth = authnone_create();
1472fe8fb19SBen Gras 	mutex_unlock(&clntraw_lock);
1482fe8fb19SBen Gras 	return (client);
1492fe8fb19SBen Gras out:
1502fe8fb19SBen Gras 	if (clp)
1512fe8fb19SBen Gras 		free(clp);
1522fe8fb19SBen Gras 	mutex_unlock(&clntraw_lock);
1532fe8fb19SBen Gras 	return NULL;
1542fe8fb19SBen Gras 
1552fe8fb19SBen Gras }
1562fe8fb19SBen Gras 
1572fe8fb19SBen Gras /* ARGSUSED */
1582fe8fb19SBen Gras static enum clnt_stat
clnt_raw_call(CLIENT * h,rpcproc_t proc,xdrproc_t xargs,const char * argsp,xdrproc_t xresults,caddr_t resultsp,struct timeval timeout)159f14fb602SLionel Sambuc clnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, const char *argsp,
160f14fb602SLionel Sambuc 	xdrproc_t xresults, caddr_t resultsp, struct timeval timeout)
1612fe8fb19SBen Gras {
1622fe8fb19SBen Gras 	struct clntraw_private *clp = clntraw_private;
1632fe8fb19SBen Gras 	XDR *xdrs = &clp->xdr_stream;
1642fe8fb19SBen Gras 	struct rpc_msg msg;
1652fe8fb19SBen Gras 	enum clnt_stat status;
1662fe8fb19SBen Gras 	struct rpc_err error;
1672fe8fb19SBen Gras 
1682fe8fb19SBen Gras 	_DIAGASSERT(h != NULL);
1692fe8fb19SBen Gras 
1702fe8fb19SBen Gras 	mutex_lock(&clntraw_lock);
1712fe8fb19SBen Gras 	if (clp == NULL) {
1722fe8fb19SBen Gras 		mutex_unlock(&clntraw_lock);
1732fe8fb19SBen Gras 		return (RPC_FAILED);
1742fe8fb19SBen Gras 	}
1752fe8fb19SBen Gras 	mutex_unlock(&clntraw_lock);
1762fe8fb19SBen Gras 
1772fe8fb19SBen Gras call_again:
1782fe8fb19SBen Gras 	/*
1792fe8fb19SBen Gras 	 * send request
1802fe8fb19SBen Gras 	 */
1812fe8fb19SBen Gras 	xdrs->x_op = XDR_ENCODE;
1822fe8fb19SBen Gras 	XDR_SETPOS(xdrs, 0);
1832fe8fb19SBen Gras 	clp->u.mashl_rpcmsg.rm_xid ++ ;
1842fe8fb19SBen Gras 	if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
1852fe8fb19SBen Gras 	    (! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
1862fe8fb19SBen Gras 	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
1872fe8fb19SBen Gras 	    (! (*xargs)(xdrs, __UNCONST(argsp)))) {
1882fe8fb19SBen Gras 		return (RPC_CANTENCODEARGS);
1892fe8fb19SBen Gras 	}
1902fe8fb19SBen Gras 	(void)XDR_GETPOS(xdrs);  /* called just to cause overhead */
1912fe8fb19SBen Gras 
1922fe8fb19SBen Gras 	/*
1932fe8fb19SBen Gras 	 * We have to call server input routine here because this is
1942fe8fb19SBen Gras 	 * all going on in one process. Yuk.
1952fe8fb19SBen Gras 	 */
1962fe8fb19SBen Gras 	svc_getreq_common(FD_SETSIZE);
1972fe8fb19SBen Gras 
1982fe8fb19SBen Gras 	/*
1992fe8fb19SBen Gras 	 * get results
2002fe8fb19SBen Gras 	 */
2012fe8fb19SBen Gras 	xdrs->x_op = XDR_DECODE;
2022fe8fb19SBen Gras 	XDR_SETPOS(xdrs, 0);
2032fe8fb19SBen Gras 	msg.acpted_rply.ar_verf = _null_auth;
2042fe8fb19SBen Gras 	msg.acpted_rply.ar_results.where = resultsp;
2052fe8fb19SBen Gras 	msg.acpted_rply.ar_results.proc = xresults;
2062fe8fb19SBen Gras 	if (! xdr_replymsg(xdrs, &msg)) {
2072fe8fb19SBen Gras 		/*
2082fe8fb19SBen Gras 		 * It's possible for xdr_replymsg() to fail partway
2092fe8fb19SBen Gras 		 * through its attempt to decode the result from the
2102fe8fb19SBen Gras 		 * server. If this happens, it will leave the reply
2112fe8fb19SBen Gras 		 * structure partially populated with dynamically
2122fe8fb19SBen Gras 		 * allocated memory. (This can happen if someone uses
2132fe8fb19SBen Gras 		 * clntudp_bufcreate() to create a CLIENT handle and
2142fe8fb19SBen Gras 		 * specifies a receive buffer size that is too small.)
2152fe8fb19SBen Gras 		 * This memory must be free()ed to avoid a leak.
2162fe8fb19SBen Gras 		 */
2172fe8fb19SBen Gras 		int op = xdrs->x_op;
2182fe8fb19SBen Gras 		xdrs->x_op = XDR_FREE;
2192fe8fb19SBen Gras 		xdr_replymsg(xdrs, &msg);
2202fe8fb19SBen Gras 		xdrs->x_op = op;
2212fe8fb19SBen Gras 		return (RPC_CANTDECODERES);
2222fe8fb19SBen Gras 	}
2232fe8fb19SBen Gras 	_seterr_reply(&msg, &error);
2242fe8fb19SBen Gras 	status = error.re_status;
2252fe8fb19SBen Gras 
2262fe8fb19SBen Gras 	if (status == RPC_SUCCESS) {
2272fe8fb19SBen Gras 		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
2282fe8fb19SBen Gras 			status = RPC_AUTHERROR;
2292fe8fb19SBen Gras 		}
2302fe8fb19SBen Gras 	}  /* end successful completion */
2312fe8fb19SBen Gras 	else {
2322fe8fb19SBen Gras 		if (AUTH_REFRESH(h->cl_auth))
2332fe8fb19SBen Gras 			goto call_again;
2342fe8fb19SBen Gras 	}  /* end of unsuccessful completion */
2352fe8fb19SBen Gras 
2362fe8fb19SBen Gras 	if (status == RPC_SUCCESS) {
2372fe8fb19SBen Gras 		if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
2382fe8fb19SBen Gras 			status = RPC_AUTHERROR;
2392fe8fb19SBen Gras 		}
2402fe8fb19SBen Gras 		if (msg.acpted_rply.ar_verf.oa_base != NULL) {
2412fe8fb19SBen Gras 			xdrs->x_op = XDR_FREE;
2422fe8fb19SBen Gras 			(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
2432fe8fb19SBen Gras 		}
2442fe8fb19SBen Gras 	}
2452fe8fb19SBen Gras 
2462fe8fb19SBen Gras 	return (status);
2472fe8fb19SBen Gras }
2482fe8fb19SBen Gras 
2492fe8fb19SBen Gras /*ARGSUSED*/
2502fe8fb19SBen Gras static void
clnt_raw_geterr(CLIENT * cl,struct rpc_err * error)251f14fb602SLionel Sambuc clnt_raw_geterr(CLIENT *cl, struct rpc_err *error)
2522fe8fb19SBen Gras {
2532fe8fb19SBen Gras }
2542fe8fb19SBen Gras 
2552fe8fb19SBen Gras 
2562fe8fb19SBen Gras /* ARGSUSED */
2572fe8fb19SBen Gras static bool_t
clnt_raw_freeres(CLIENT * cl,xdrproc_t xdr_res,caddr_t res_ptr)258f14fb602SLionel Sambuc clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
2592fe8fb19SBen Gras {
2602fe8fb19SBen Gras 	struct clntraw_private *clp = clntraw_private;
2612fe8fb19SBen Gras 	XDR *xdrs = &clp->xdr_stream;
2622fe8fb19SBen Gras 	bool_t rval;
2632fe8fb19SBen Gras 
2642fe8fb19SBen Gras 	mutex_lock(&clntraw_lock);
2652fe8fb19SBen Gras 	if (clp == NULL) {
2662fe8fb19SBen Gras 		rval = (bool_t) RPC_FAILED;
2672fe8fb19SBen Gras 		mutex_unlock(&clntraw_lock);
2682fe8fb19SBen Gras 		return (rval);
2692fe8fb19SBen Gras 	}
2702fe8fb19SBen Gras 	mutex_unlock(&clntraw_lock);
2712fe8fb19SBen Gras 	xdrs->x_op = XDR_FREE;
2722fe8fb19SBen Gras 	return ((*xdr_res)(xdrs, res_ptr));
2732fe8fb19SBen Gras }
2742fe8fb19SBen Gras 
2752fe8fb19SBen Gras /*ARGSUSED*/
2762fe8fb19SBen Gras static void
clnt_raw_abort(CLIENT * cl)277f14fb602SLionel Sambuc clnt_raw_abort(CLIENT *cl)
2782fe8fb19SBen Gras {
2792fe8fb19SBen Gras }
2802fe8fb19SBen Gras 
2812fe8fb19SBen Gras /*ARGSUSED*/
2822fe8fb19SBen Gras static bool_t
clnt_raw_control(CLIENT * cl,u_int ui,char * str)283f14fb602SLionel Sambuc clnt_raw_control(CLIENT *cl, u_int ui, char *str)
2842fe8fb19SBen Gras {
2852fe8fb19SBen Gras 	return (FALSE);
2862fe8fb19SBen Gras }
2872fe8fb19SBen Gras 
2882fe8fb19SBen Gras /*ARGSUSED*/
2892fe8fb19SBen Gras static void
clnt_raw_destroy(CLIENT * cl)290f14fb602SLionel Sambuc clnt_raw_destroy(CLIENT *cl)
2912fe8fb19SBen Gras {
2922fe8fb19SBen Gras }
2932fe8fb19SBen Gras 
2942fe8fb19SBen Gras static struct clnt_ops *
clnt_raw_ops(void)295f14fb602SLionel Sambuc clnt_raw_ops(void)
2962fe8fb19SBen Gras {
2972fe8fb19SBen Gras 	static struct clnt_ops ops;
2982fe8fb19SBen Gras #ifdef _REENTRANT
2992fe8fb19SBen Gras 	extern mutex_t  ops_lock;
3002fe8fb19SBen Gras #endif
3012fe8fb19SBen Gras 
3022fe8fb19SBen Gras 	/* VARIABLES PROTECTED BY ops_lock: ops */
3032fe8fb19SBen Gras 
3042fe8fb19SBen Gras 	mutex_lock(&ops_lock);
3052fe8fb19SBen Gras 	if (ops.cl_call == NULL) {
3062fe8fb19SBen Gras 		ops.cl_call = clnt_raw_call;
3072fe8fb19SBen Gras 		ops.cl_abort = clnt_raw_abort;
3082fe8fb19SBen Gras 		ops.cl_geterr = clnt_raw_geterr;
3092fe8fb19SBen Gras 		ops.cl_freeres = clnt_raw_freeres;
3102fe8fb19SBen Gras 		ops.cl_destroy = clnt_raw_destroy;
3112fe8fb19SBen Gras 		ops.cl_control = clnt_raw_control;
3122fe8fb19SBen Gras 	}
3132fe8fb19SBen Gras 	mutex_unlock(&ops_lock);
3142fe8fb19SBen Gras 	return (&ops);
3152fe8fb19SBen Gras }
316