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