summaryrefslogtreecommitdiffstats
path: root/lib/libc/rpc/clnt_raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/rpc/clnt_raw.c')
-rw-r--r--lib/libc/rpc/clnt_raw.c188
1 files changed, 130 insertions, 58 deletions
diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c
index 6f228fe..01dfc79 100644
--- a/lib/libc/rpc/clnt_raw.c
+++ b/lib/libc/rpc/clnt_raw.c
@@ -1,3 +1,5 @@
+/* $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ */
+
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -27,9 +29,10 @@
* Mountain View, California 94043
*/
+#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
-/*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
-/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *sccsid = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";
static char *rcsid = "$FreeBSD$";
#endif
@@ -44,9 +47,18 @@ static char *rcsid = "$FreeBSD$";
* any interference from the kernal.
*/
-#include <rpc/rpc.h>
-#include <stdlib.h>
+#include "reentrant.h"
+#include "namespace.h"
+#include <assert.h>
+#include <err.h>
#include <stdio.h>
+#include <stdlib.h>
+
+#include <rpc/rpc.h>
+#include <rpc/raw.h>
+#include "un-namespace.h"
+
+extern mutex_t clntraw_lock;
#define MCALL_MSG_SIZE 24
@@ -56,46 +68,47 @@ static char *rcsid = "$FreeBSD$";
static struct clntraw_private {
CLIENT client_object;
XDR xdr_stream;
- char _raw_buf[UDPMSGSIZE];
- char mashl_callmsg[MCALL_MSG_SIZE];
+ char *_raw_buf;
+ union {
+ struct rpc_msg mashl_rpcmsg;
+ char mashl_callmsg[MCALL_MSG_SIZE];
+ } u;
u_int mcnt;
} *clntraw_private;
-static enum clnt_stat clntraw_call();
-static void clntraw_abort();
-static void clntraw_geterr();
-static bool_t clntraw_freeres();
-static bool_t clntraw_control();
-static void clntraw_destroy();
-
-static struct clnt_ops client_ops = {
- clntraw_call,
- clntraw_abort,
- clntraw_geterr,
- clntraw_freeres,
- clntraw_destroy,
- clntraw_control
-};
-
-void svc_getreq();
+static enum clnt_stat clnt_raw_call __P((CLIENT *, rpcproc_t, xdrproc_t,
+ caddr_t, xdrproc_t, caddr_t, struct timeval));
+static void clnt_raw_geterr __P((CLIENT *, struct rpc_err *));
+static bool_t clnt_raw_freeres __P((CLIENT *, xdrproc_t, caddr_t));
+static void clnt_raw_abort __P((CLIENT *));
+static bool_t clnt_raw_control __P((CLIENT *, u_int, char *));
+static void clnt_raw_destroy __P((CLIENT *));
+static struct clnt_ops *clnt_raw_ops __P((void));
/*
* Create a client handle for memory based rpc.
*/
CLIENT *
-clntraw_create(prog, vers)
- u_long prog;
- u_long vers;
+clnt_raw_create(prog, vers)
+ rpcprog_t prog;
+ rpcvers_t vers;
{
- register struct clntraw_private *clp = clntraw_private;
+ struct clntraw_private *clp = clntraw_private;
struct rpc_msg call_msg;
XDR *xdrs = &clp->xdr_stream;
CLIENT *client = &clp->client_object;
- if (clp == 0) {
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
- if (clp == 0)
- return (0);
+ if (clp == NULL) {
+ mutex_unlock(&clntraw_lock);
+ return NULL;
+ }
+ if (__rpc_rawcombuf == NULL)
+ __rpc_rawcombuf =
+ (char *)calloc(UDPMSGSIZE, sizeof (char));
+ clp->_raw_buf = __rpc_rawcombuf;
clntraw_private = clp;
}
/*
@@ -103,12 +116,12 @@ clntraw_create(prog, vers)
*/
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
- call_msg.rm_call.cb_prog = prog;
- call_msg.rm_call.cb_vers = vers;
- xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
- if (! xdr_callhdr(xdrs, &call_msg)) {
- perror("clnt_raw.c - Fatal header serialization error.");
- }
+ /* XXX: prog and vers have been long historically :-( */
+ call_msg.rm_call.cb_prog = (u_int32_t)prog;
+ call_msg.rm_call.cb_vers = (u_int32_t)vers;
+ xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+ if (! xdr_callhdr(xdrs, &call_msg))
+ warnx("clntraw_create - Fatal header serialization error.");
clp->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
@@ -120,38 +133,47 @@ clntraw_create(prog, vers)
/*
* create client handle
*/
- client->cl_ops = &client_ops;
+ client->cl_ops = clnt_raw_ops();
client->cl_auth = authnone_create();
+ mutex_unlock(&clntraw_lock);
return (client);
}
-static enum clnt_stat
-clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+/* ARGSUSED */
+static enum clnt_stat
+clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
CLIENT *h;
- u_long proc;
+ rpcproc_t proc;
xdrproc_t xargs;
caddr_t argsp;
xdrproc_t xresults;
caddr_t resultsp;
struct timeval timeout;
{
- register struct clntraw_private *clp = clntraw_private;
- register XDR *xdrs = &clp->xdr_stream;
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
struct rpc_msg msg;
enum clnt_stat status;
struct rpc_err error;
- if (clp == 0)
+ assert(h != NULL);
+
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
+ mutex_unlock(&clntraw_lock);
return (RPC_FAILED);
+ }
+ mutex_unlock(&clntraw_lock);
+
call_again:
/*
* send request
*/
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, 0);
- ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
- if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
- (! XDR_PUTLONG(xdrs, (long *)&proc)) ||
+ clp->u.mashl_rpcmsg.rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp))) {
return (RPC_CANTENCODEARGS);
@@ -162,7 +184,7 @@ call_again:
* We have to call server input routine here because this is
* all going on in one process. Yuk.
*/
- svc_getreq(1);
+ svc_getreq_common(FD_SETSIZE);
/*
* get results
@@ -172,8 +194,23 @@ call_again:
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = resultsp;
msg.acpted_rply.ar_results.proc = xresults;
- if (! xdr_replymsg(xdrs, &msg))
+ if (! xdr_replymsg(xdrs, &msg)) {
+ /*
+ * It's possible for xdr_replymsg() to fail partway
+ * through its attempt to decode the result from the
+ * server. If this happens, it will leave the reply
+ * structure partially populated with dynamically
+ * allocated memory. (This can happen if someone uses
+ * clntudp_bufcreate() to create a CLIENT handle and
+ * specifies a receive buffer size that is too small.)
+ * This memory must be free()ed to avoid a leak.
+ */
+ int op = xdrs->x_op;
+ xdrs->x_op = XDR_FREE;
+ xdr_replymsg(xdrs, &msg);
+ xdrs->x_op = op;
return (RPC_CANTDECODERES);
+ }
_seterr_reply(&msg, &error);
status = error.re_status;
@@ -183,7 +220,7 @@ call_again:
}
} /* end successful completion */
else {
- if (AUTH_REFRESH(h->cl_auth))
+ if (AUTH_REFRESH(h->cl_auth, &msg))
goto call_again;
} /* end of unsuccessful completion */
@@ -200,43 +237,78 @@ call_again:
return (status);
}
+/*ARGSUSED*/
static void
-clntraw_geterr()
+clnt_raw_geterr(cl, err)
+ CLIENT *cl;
+ struct rpc_err *err;
{
}
+/* ARGSUSED */
static bool_t
-clntraw_freeres(cl, xdr_res, res_ptr)
+clnt_raw_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
- register struct clntraw_private *clp = clntraw_private;
- register XDR *xdrs = &clp->xdr_stream;
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
bool_t rval;
- if (clp == 0)
- {
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
rval = (bool_t) RPC_FAILED;
+ mutex_unlock(&clntraw_lock);
return (rval);
}
+ mutex_unlock(&clntraw_lock);
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
+/*ARGSUSED*/
static void
-clntraw_abort()
+clnt_raw_abort(cl)
+ CLIENT *cl;
{
}
+/*ARGSUSED*/
static bool_t
-clntraw_control()
+clnt_raw_control(cl, ui, str)
+ CLIENT *cl;
+ u_int ui;
+ char *str;
{
return (FALSE);
}
+/*ARGSUSED*/
static void
-clntraw_destroy()
+clnt_raw_destroy(cl)
+ CLIENT *cl;
{
}
+
+static struct clnt_ops *
+clnt_raw_ops()
+{
+ static struct clnt_ops ops;
+ extern mutex_t ops_lock;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.cl_call == NULL) {
+ ops.cl_call = clnt_raw_call;
+ ops.cl_abort = clnt_raw_abort;
+ ops.cl_geterr = clnt_raw_geterr;
+ ops.cl_freeres = clnt_raw_freeres;
+ ops.cl_destroy = clnt_raw_destroy;
+ ops.cl_control = clnt_raw_control;
+ }
+ mutex_unlock(&ops_lock);
+ return (&ops);
+}
OpenPOWER on IntegriCloud