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