174462Salfred/* $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ */ 274462Salfred 3261046Smav/*- 4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261046Smav * All rights reserved. 68870Srgrimes * 7261046Smav * Redistribution and use in source and binary forms, with or without 8261046Smav * modification, are permitted provided that the following conditions are met: 9261046Smav * - Redistributions of source code must retain the above copyright notice, 10261046Smav * this list of conditions and the following disclaimer. 11261046Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261046Smav * this list of conditions and the following disclaimer in the documentation 13261046Smav * and/or other materials provided with the distribution. 14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261046Smav * contributors may be used to endorse or promote products derived 16261046Smav * from this software without specific prior written permission. 17261046Smav * 18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261046Smav * POSSIBILITY OF SUCH DAMAGE. 291901Swollman */ 301901Swollman 311901Swollman#if defined(LIBC_SCCS) && !defined(lint) 32136581Sobrienstatic char *sccsid2 = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro"; 3374462Salfredstatic char *sccsid = "@(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC"; 341901Swollman#endif 3592990Sobrien#include <sys/cdefs.h> 3692990Sobrien__FBSDID("$FreeBSD: stable/10/lib/libc/rpc/clnt_raw.c 309487 2016-12-03 17:27:28Z ngie $"); 371901Swollman 381901Swollman/* 391901Swollman * clnt_raw.c 401901Swollman * 411901Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 421901Swollman * 431901Swollman * Memory based rpc for simple testing and timing. 441901Swollman * Interface to create an rpc client and server in the same process. 451901Swollman * This lets us similate rpc and get round trip overhead, without 4685138Salfred * any interference from the kernel. 471901Swollman */ 481901Swollman 4975094Siedowse#include "namespace.h" 5074462Salfred#include "reentrant.h" 5174462Salfred#include <assert.h> 5274462Salfred#include <err.h> 5374462Salfred#include <stdio.h> 5411666Sphk#include <stdlib.h> 551901Swollman 5674462Salfred#include <rpc/rpc.h> 5774462Salfred#include <rpc/raw.h> 5874462Salfred#include "un-namespace.h" 59156090Sdeischen#include "mt_misc.h" 6074462Salfred 611901Swollman#define MCALL_MSG_SIZE 24 621901Swollman 631901Swollman/* 641901Swollman * This is the "network" we will be moving stuff over. 651901Swollman */ 661901Swollmanstatic struct clntraw_private { 671901Swollman CLIENT client_object; 681901Swollman XDR xdr_stream; 6974462Salfred char *_raw_buf; 7074462Salfred union { 7174462Salfred struct rpc_msg mashl_rpcmsg; 7274462Salfred char mashl_callmsg[MCALL_MSG_SIZE]; 7374462Salfred } u; 741901Swollman u_int mcnt; 751901Swollman} *clntraw_private; 761901Swollman 7795658Sdesstatic enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *, 7895658Sdes xdrproc_t, void *, struct timeval); 7992905Sobrienstatic void clnt_raw_geterr(CLIENT *, struct rpc_err *); 8095658Sdesstatic bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *); 8192905Sobrienstatic void clnt_raw_abort(CLIENT *); 8299996Salfredstatic bool_t clnt_raw_control(CLIENT *, u_int, void *); 8392905Sobrienstatic void clnt_raw_destroy(CLIENT *); 8492905Sobrienstatic struct clnt_ops *clnt_raw_ops(void); 851901Swollman 861901Swollman/* 871901Swollman * Create a client handle for memory based rpc. 881901Swollman */ 891901SwollmanCLIENT * 90309487Sngieclnt_raw_create(rpcprog_t prog, rpcvers_t vers) 911901Swollman{ 92199786Swollman struct clntraw_private *clp; 931901Swollman struct rpc_msg call_msg; 94199786Swollman XDR *xdrs; 95199786Swollman CLIENT *client; 961901Swollman 9774462Salfred mutex_lock(&clntraw_lock); 98199786Swollman if ((clp = clntraw_private) == NULL) { 991901Swollman clp = (struct clntraw_private *)calloc(1, sizeof (*clp)); 10074462Salfred if (clp == NULL) { 10174462Salfred mutex_unlock(&clntraw_lock); 10274462Salfred return NULL; 10374462Salfred } 10474462Salfred if (__rpc_rawcombuf == NULL) 10574462Salfred __rpc_rawcombuf = 10674462Salfred (char *)calloc(UDPMSGSIZE, sizeof (char)); 10774462Salfred clp->_raw_buf = __rpc_rawcombuf; 1081901Swollman clntraw_private = clp; 1091901Swollman } 110199786Swollman xdrs = &clp->xdr_stream; 111199786Swollman client = &clp->client_object; 112199786Swollman 1131901Swollman /* 11411845Sadam * pre-serialize the static part of the call msg and stash it away 1151901Swollman */ 1161901Swollman call_msg.rm_direction = CALL; 1171901Swollman call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 11874462Salfred /* XXX: prog and vers have been long historically :-( */ 11974462Salfred call_msg.rm_call.cb_prog = (u_int32_t)prog; 12074462Salfred call_msg.rm_call.cb_vers = (u_int32_t)vers; 12174462Salfred xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 12274462Salfred if (! xdr_callhdr(xdrs, &call_msg)) 12374462Salfred warnx("clntraw_create - Fatal header serialization error."); 1241901Swollman clp->mcnt = XDR_GETPOS(xdrs); 1251901Swollman XDR_DESTROY(xdrs); 1261901Swollman 1271901Swollman /* 1281901Swollman * Set xdrmem for client/server shared buffer 1291901Swollman */ 1301901Swollman xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE); 1311901Swollman 1321901Swollman /* 1331901Swollman * create client handle 1341901Swollman */ 13574462Salfred client->cl_ops = clnt_raw_ops(); 1361901Swollman client->cl_auth = authnone_create(); 13774462Salfred mutex_unlock(&clntraw_lock); 1381901Swollman return (client); 1391901Swollman} 1401901Swollman 14174462Salfred/* ARGSUSED */ 14274462Salfredstatic enum clnt_stat 143309487Sngieclnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, void *argsp, 144309487Sngie xdrproc_t xresults, void *resultsp, struct timeval timeout) 1451901Swollman{ 14674462Salfred struct clntraw_private *clp = clntraw_private; 14774462Salfred XDR *xdrs = &clp->xdr_stream; 1481901Swollman struct rpc_msg msg; 1491901Swollman enum clnt_stat status; 1501901Swollman struct rpc_err error; 1511901Swollman 15274462Salfred assert(h != NULL); 15374462Salfred 15474462Salfred mutex_lock(&clntraw_lock); 15574462Salfred if (clp == NULL) { 15674462Salfred mutex_unlock(&clntraw_lock); 1571901Swollman return (RPC_FAILED); 15874462Salfred } 15974462Salfred mutex_unlock(&clntraw_lock); 16074462Salfred 1611901Swollmancall_again: 1621901Swollman /* 1631901Swollman * send request 1641901Swollman */ 1651901Swollman xdrs->x_op = XDR_ENCODE; 1661901Swollman XDR_SETPOS(xdrs, 0); 16774462Salfred clp->u.mashl_rpcmsg.rm_xid ++ ; 16874462Salfred if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) || 16974462Salfred (! XDR_PUTINT32(xdrs, &proc)) || 1701901Swollman (! AUTH_MARSHALL(h->cl_auth, xdrs)) || 1711901Swollman (! (*xargs)(xdrs, argsp))) { 1721901Swollman return (RPC_CANTENCODEARGS); 1731901Swollman } 1741901Swollman (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ 1751901Swollman 1761901Swollman /* 1771901Swollman * We have to call server input routine here because this is 1781901Swollman * all going on in one process. Yuk. 1791901Swollman */ 18074462Salfred svc_getreq_common(FD_SETSIZE); 1811901Swollman 1821901Swollman /* 1831901Swollman * get results 1841901Swollman */ 1851901Swollman xdrs->x_op = XDR_DECODE; 1861901Swollman XDR_SETPOS(xdrs, 0); 1871901Swollman msg.acpted_rply.ar_verf = _null_auth; 1881901Swollman msg.acpted_rply.ar_results.where = resultsp; 1891901Swollman msg.acpted_rply.ar_results.proc = xresults; 19074462Salfred if (! xdr_replymsg(xdrs, &msg)) { 19174462Salfred /* 19274462Salfred * It's possible for xdr_replymsg() to fail partway 19374462Salfred * through its attempt to decode the result from the 19474462Salfred * server. If this happens, it will leave the reply 19574462Salfred * structure partially populated with dynamically 19674462Salfred * allocated memory. (This can happen if someone uses 19774462Salfred * clntudp_bufcreate() to create a CLIENT handle and 19874462Salfred * specifies a receive buffer size that is too small.) 19974462Salfred * This memory must be free()ed to avoid a leak. 20074462Salfred */ 20174462Salfred int op = xdrs->x_op; 20274462Salfred xdrs->x_op = XDR_FREE; 20374462Salfred xdr_replymsg(xdrs, &msg); 20474462Salfred xdrs->x_op = op; 2051901Swollman return (RPC_CANTDECODERES); 20674462Salfred } 2071901Swollman _seterr_reply(&msg, &error); 2081901Swollman status = error.re_status; 2091901Swollman 2101901Swollman if (status == RPC_SUCCESS) { 2111901Swollman if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { 2121901Swollman status = RPC_AUTHERROR; 2131901Swollman } 2141901Swollman } /* end successful completion */ 2151901Swollman else { 21674462Salfred if (AUTH_REFRESH(h->cl_auth, &msg)) 2171901Swollman goto call_again; 2181901Swollman } /* end of unsuccessful completion */ 2191901Swollman 2201901Swollman if (status == RPC_SUCCESS) { 2211901Swollman if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { 2221901Swollman status = RPC_AUTHERROR; 2231901Swollman } 2241901Swollman if (msg.acpted_rply.ar_verf.oa_base != NULL) { 2251901Swollman xdrs->x_op = XDR_FREE; 2261901Swollman (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf)); 2271901Swollman } 2281901Swollman } 2291901Swollman 2301901Swollman return (status); 2311901Swollman} 2321901Swollman 23374462Salfred/*ARGSUSED*/ 2341901Swollmanstatic void 235309487Sngieclnt_raw_geterr(CLIENT *cl, struct rpc_err *err) 2361901Swollman{ 2371901Swollman} 2381901Swollman 2391901Swollman 24074462Salfred/* ARGSUSED */ 2411901Swollmanstatic bool_t 242309487Sngieclnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) 2431901Swollman{ 24474462Salfred struct clntraw_private *clp = clntraw_private; 24574462Salfred XDR *xdrs = &clp->xdr_stream; 2461901Swollman bool_t rval; 2471901Swollman 24874462Salfred mutex_lock(&clntraw_lock); 24974462Salfred if (clp == NULL) { 2501901Swollman rval = (bool_t) RPC_FAILED; 25174462Salfred mutex_unlock(&clntraw_lock); 2521901Swollman return (rval); 2531901Swollman } 25474462Salfred mutex_unlock(&clntraw_lock); 2551901Swollman xdrs->x_op = XDR_FREE; 2561901Swollman return ((*xdr_res)(xdrs, res_ptr)); 2571901Swollman} 2581901Swollman 25974462Salfred/*ARGSUSED*/ 2601901Swollmanstatic void 261309487Sngieclnt_raw_abort(CLIENT *cl) 2621901Swollman{ 2631901Swollman} 2641901Swollman 26574462Salfred/*ARGSUSED*/ 2661901Swollmanstatic bool_t 267309487Sngieclnt_raw_control(CLIENT *cl, u_int ui, void *str) 2681901Swollman{ 2691901Swollman return (FALSE); 2701901Swollman} 2711901Swollman 27274462Salfred/*ARGSUSED*/ 2731901Swollmanstatic void 274309487Sngieclnt_raw_destroy(CLIENT *cl) 2751901Swollman{ 2761901Swollman} 27774462Salfred 27874462Salfredstatic struct clnt_ops * 279309487Sngieclnt_raw_ops(void) 28074462Salfred{ 28174462Salfred static struct clnt_ops ops; 28274462Salfred 28374462Salfred /* VARIABLES PROTECTED BY ops_lock: ops */ 28474462Salfred 28574462Salfred mutex_lock(&ops_lock); 28674462Salfred if (ops.cl_call == NULL) { 28774462Salfred ops.cl_call = clnt_raw_call; 28874462Salfred ops.cl_abort = clnt_raw_abort; 28974462Salfred ops.cl_geterr = clnt_raw_geterr; 29074462Salfred ops.cl_freeres = clnt_raw_freeres; 29174462Salfred ops.cl_destroy = clnt_raw_destroy; 29274462Salfred ops.cl_control = clnt_raw_control; 29374462Salfred } 29474462Salfred mutex_unlock(&ops_lock); 29574462Salfred return (&ops); 29674462Salfred} 297