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: releng/10.3/lib/libc/rpc/clnt_raw.c 261046 2014-01-22 23:45:27Z mav $"); 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 * 9074462Salfredclnt_raw_create(prog, vers) 9174462Salfred rpcprog_t prog; 9274462Salfred rpcvers_t vers; 931901Swollman{ 94199786Swollman struct clntraw_private *clp; 951901Swollman struct rpc_msg call_msg; 96199786Swollman XDR *xdrs; 97199786Swollman CLIENT *client; 981901Swollman 9974462Salfred mutex_lock(&clntraw_lock); 100199786Swollman if ((clp = clntraw_private) == NULL) { 1011901Swollman clp = (struct clntraw_private *)calloc(1, sizeof (*clp)); 10274462Salfred if (clp == NULL) { 10374462Salfred mutex_unlock(&clntraw_lock); 10474462Salfred return NULL; 10574462Salfred } 10674462Salfred if (__rpc_rawcombuf == NULL) 10774462Salfred __rpc_rawcombuf = 10874462Salfred (char *)calloc(UDPMSGSIZE, sizeof (char)); 10974462Salfred clp->_raw_buf = __rpc_rawcombuf; 1101901Swollman clntraw_private = clp; 1111901Swollman } 112199786Swollman xdrs = &clp->xdr_stream; 113199786Swollman client = &clp->client_object; 114199786Swollman 1151901Swollman /* 11611845Sadam * pre-serialize the static part of the call msg and stash it away 1171901Swollman */ 1181901Swollman call_msg.rm_direction = CALL; 1191901Swollman call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; 12074462Salfred /* XXX: prog and vers have been long historically :-( */ 12174462Salfred call_msg.rm_call.cb_prog = (u_int32_t)prog; 12274462Salfred call_msg.rm_call.cb_vers = (u_int32_t)vers; 12374462Salfred xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE); 12474462Salfred if (! xdr_callhdr(xdrs, &call_msg)) 12574462Salfred warnx("clntraw_create - Fatal header serialization error."); 1261901Swollman clp->mcnt = XDR_GETPOS(xdrs); 1271901Swollman XDR_DESTROY(xdrs); 1281901Swollman 1291901Swollman /* 1301901Swollman * Set xdrmem for client/server shared buffer 1311901Swollman */ 1321901Swollman xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE); 1331901Swollman 1341901Swollman /* 1351901Swollman * create client handle 1361901Swollman */ 13774462Salfred client->cl_ops = clnt_raw_ops(); 1381901Swollman client->cl_auth = authnone_create(); 13974462Salfred mutex_unlock(&clntraw_lock); 1401901Swollman return (client); 1411901Swollman} 1421901Swollman 14374462Salfred/* ARGSUSED */ 14474462Salfredstatic enum clnt_stat 14574462Salfredclnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout) 1461901Swollman CLIENT *h; 14774462Salfred rpcproc_t proc; 1481901Swollman xdrproc_t xargs; 14995658Sdes void *argsp; 1501901Swollman xdrproc_t xresults; 15195658Sdes void *resultsp; 1521901Swollman struct timeval timeout; 1531901Swollman{ 15474462Salfred struct clntraw_private *clp = clntraw_private; 15574462Salfred XDR *xdrs = &clp->xdr_stream; 1561901Swollman struct rpc_msg msg; 1571901Swollman enum clnt_stat status; 1581901Swollman struct rpc_err error; 1591901Swollman 16074462Salfred assert(h != NULL); 16174462Salfred 16274462Salfred mutex_lock(&clntraw_lock); 16374462Salfred if (clp == NULL) { 16474462Salfred mutex_unlock(&clntraw_lock); 1651901Swollman return (RPC_FAILED); 16674462Salfred } 16774462Salfred mutex_unlock(&clntraw_lock); 16874462Salfred 1691901Swollmancall_again: 1701901Swollman /* 1711901Swollman * send request 1721901Swollman */ 1731901Swollman xdrs->x_op = XDR_ENCODE; 1741901Swollman XDR_SETPOS(xdrs, 0); 17574462Salfred clp->u.mashl_rpcmsg.rm_xid ++ ; 17674462Salfred if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) || 17774462Salfred (! XDR_PUTINT32(xdrs, &proc)) || 1781901Swollman (! AUTH_MARSHALL(h->cl_auth, xdrs)) || 1791901Swollman (! (*xargs)(xdrs, argsp))) { 1801901Swollman return (RPC_CANTENCODEARGS); 1811901Swollman } 1821901Swollman (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ 1831901Swollman 1841901Swollman /* 1851901Swollman * We have to call server input routine here because this is 1861901Swollman * all going on in one process. Yuk. 1871901Swollman */ 18874462Salfred svc_getreq_common(FD_SETSIZE); 1891901Swollman 1901901Swollman /* 1911901Swollman * get results 1921901Swollman */ 1931901Swollman xdrs->x_op = XDR_DECODE; 1941901Swollman XDR_SETPOS(xdrs, 0); 1951901Swollman msg.acpted_rply.ar_verf = _null_auth; 1961901Swollman msg.acpted_rply.ar_results.where = resultsp; 1971901Swollman msg.acpted_rply.ar_results.proc = xresults; 19874462Salfred if (! xdr_replymsg(xdrs, &msg)) { 19974462Salfred /* 20074462Salfred * It's possible for xdr_replymsg() to fail partway 20174462Salfred * through its attempt to decode the result from the 20274462Salfred * server. If this happens, it will leave the reply 20374462Salfred * structure partially populated with dynamically 20474462Salfred * allocated memory. (This can happen if someone uses 20574462Salfred * clntudp_bufcreate() to create a CLIENT handle and 20674462Salfred * specifies a receive buffer size that is too small.) 20774462Salfred * This memory must be free()ed to avoid a leak. 20874462Salfred */ 20974462Salfred int op = xdrs->x_op; 21074462Salfred xdrs->x_op = XDR_FREE; 21174462Salfred xdr_replymsg(xdrs, &msg); 21274462Salfred xdrs->x_op = op; 2131901Swollman return (RPC_CANTDECODERES); 21474462Salfred } 2151901Swollman _seterr_reply(&msg, &error); 2161901Swollman status = error.re_status; 2171901Swollman 2181901Swollman if (status == RPC_SUCCESS) { 2191901Swollman if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { 2201901Swollman status = RPC_AUTHERROR; 2211901Swollman } 2221901Swollman } /* end successful completion */ 2231901Swollman else { 22474462Salfred if (AUTH_REFRESH(h->cl_auth, &msg)) 2251901Swollman goto call_again; 2261901Swollman } /* end of unsuccessful completion */ 2271901Swollman 2281901Swollman if (status == RPC_SUCCESS) { 2291901Swollman if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) { 2301901Swollman status = RPC_AUTHERROR; 2311901Swollman } 2321901Swollman if (msg.acpted_rply.ar_verf.oa_base != NULL) { 2331901Swollman xdrs->x_op = XDR_FREE; 2341901Swollman (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf)); 2351901Swollman } 2361901Swollman } 2371901Swollman 2381901Swollman return (status); 2391901Swollman} 2401901Swollman 24174462Salfred/*ARGSUSED*/ 2421901Swollmanstatic void 24374462Salfredclnt_raw_geterr(cl, err) 24474462Salfred CLIENT *cl; 24574462Salfred struct rpc_err *err; 2461901Swollman{ 2471901Swollman} 2481901Swollman 2491901Swollman 25074462Salfred/* ARGSUSED */ 2511901Swollmanstatic bool_t 25274462Salfredclnt_raw_freeres(cl, xdr_res, res_ptr) 2531901Swollman CLIENT *cl; 2541901Swollman xdrproc_t xdr_res; 25595658Sdes void *res_ptr; 2561901Swollman{ 25774462Salfred struct clntraw_private *clp = clntraw_private; 25874462Salfred XDR *xdrs = &clp->xdr_stream; 2591901Swollman bool_t rval; 2601901Swollman 26174462Salfred mutex_lock(&clntraw_lock); 26274462Salfred if (clp == NULL) { 2631901Swollman rval = (bool_t) RPC_FAILED; 26474462Salfred mutex_unlock(&clntraw_lock); 2651901Swollman return (rval); 2661901Swollman } 26774462Salfred mutex_unlock(&clntraw_lock); 2681901Swollman xdrs->x_op = XDR_FREE; 2691901Swollman return ((*xdr_res)(xdrs, res_ptr)); 2701901Swollman} 2711901Swollman 27274462Salfred/*ARGSUSED*/ 2731901Swollmanstatic void 27474462Salfredclnt_raw_abort(cl) 27574462Salfred CLIENT *cl; 2761901Swollman{ 2771901Swollman} 2781901Swollman 27974462Salfred/*ARGSUSED*/ 2801901Swollmanstatic bool_t 28174462Salfredclnt_raw_control(cl, ui, str) 28274462Salfred CLIENT *cl; 28374462Salfred u_int ui; 28499996Salfred void *str; 2851901Swollman{ 2861901Swollman return (FALSE); 2871901Swollman} 2881901Swollman 28974462Salfred/*ARGSUSED*/ 2901901Swollmanstatic void 29174462Salfredclnt_raw_destroy(cl) 29274462Salfred CLIENT *cl; 2931901Swollman{ 2941901Swollman} 29574462Salfred 29674462Salfredstatic struct clnt_ops * 29774462Salfredclnt_raw_ops() 29874462Salfred{ 29974462Salfred static struct clnt_ops ops; 30074462Salfred 30174462Salfred /* VARIABLES PROTECTED BY ops_lock: ops */ 30274462Salfred 30374462Salfred mutex_lock(&ops_lock); 30474462Salfred if (ops.cl_call == NULL) { 30574462Salfred ops.cl_call = clnt_raw_call; 30674462Salfred ops.cl_abort = clnt_raw_abort; 30774462Salfred ops.cl_geterr = clnt_raw_geterr; 30874462Salfred ops.cl_freeres = clnt_raw_freeres; 30974462Salfred ops.cl_destroy = clnt_raw_destroy; 31074462Salfred ops.cl_control = clnt_raw_control; 31174462Salfred } 31274462Salfred mutex_unlock(&ops_lock); 31374462Salfred return (&ops); 31474462Salfred} 315