Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/lib/libc/rpc/clnt_raw.c
39476 views
1
/* $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ */
2
3
/*-
4
* SPDX-License-Identifier: BSD-3-Clause
5
*
6
* Copyright (c) 2009, Sun Microsystems, Inc.
7
* All rights reserved.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions are met:
11
* - Redistributions of source code must retain the above copyright notice,
12
* this list of conditions and the following disclaimer.
13
* - Redistributions in binary form must reproduce the above copyright notice,
14
* this list of conditions and the following disclaimer in the documentation
15
* and/or other materials provided with the distribution.
16
* - Neither the name of Sun Microsystems, Inc. nor the names of its
17
* contributors may be used to endorse or promote products derived
18
* from this software without specific prior written permission.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
* POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
/*
34
* clnt_raw.c
35
*
36
* Copyright (C) 1984, Sun Microsystems, Inc.
37
*
38
* Memory based rpc for simple testing and timing.
39
* Interface to create an rpc client and server in the same process.
40
* This lets us similate rpc and get round trip overhead, without
41
* any interference from the kernel.
42
*/
43
44
#include "namespace.h"
45
#include "reentrant.h"
46
#include <assert.h>
47
#include <err.h>
48
#include <stdio.h>
49
#include <stdlib.h>
50
51
#include <rpc/rpc.h>
52
#include <rpc/raw.h>
53
#include "un-namespace.h"
54
#include "mt_misc.h"
55
56
#define MCALL_MSG_SIZE 24
57
58
/*
59
* This is the "network" we will be moving stuff over.
60
*/
61
static struct clntraw_private {
62
CLIENT client_object;
63
XDR xdr_stream;
64
char *_raw_buf;
65
union {
66
struct rpc_msg mashl_rpcmsg;
67
char mashl_callmsg[MCALL_MSG_SIZE];
68
} u;
69
u_int mcnt;
70
} *clntraw_private;
71
72
static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
73
xdrproc_t, void *, struct timeval);
74
static void clnt_raw_geterr(CLIENT *, struct rpc_err *);
75
static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *);
76
static void clnt_raw_abort(CLIENT *);
77
static bool_t clnt_raw_control(CLIENT *, u_int, void *);
78
static void clnt_raw_destroy(CLIENT *);
79
static struct clnt_ops *clnt_raw_ops(void);
80
81
/*
82
* Create a client handle for memory based rpc.
83
*/
84
CLIENT *
85
clnt_raw_create(rpcprog_t prog, rpcvers_t vers)
86
{
87
struct clntraw_private *clp;
88
struct rpc_msg call_msg;
89
XDR *xdrs;
90
CLIENT *client;
91
92
mutex_lock(&clntraw_lock);
93
if ((clp = clntraw_private) == NULL) {
94
clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
95
if (clp == NULL) {
96
mutex_unlock(&clntraw_lock);
97
return NULL;
98
}
99
if (__rpc_rawcombuf == NULL)
100
__rpc_rawcombuf =
101
(char *)calloc(UDPMSGSIZE, sizeof (char));
102
clp->_raw_buf = __rpc_rawcombuf;
103
clntraw_private = clp;
104
}
105
xdrs = &clp->xdr_stream;
106
client = &clp->client_object;
107
108
/*
109
* pre-serialize the static part of the call msg and stash it away
110
*/
111
call_msg.rm_direction = CALL;
112
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
113
/* XXX: prog and vers have been long historically :-( */
114
call_msg.rm_call.cb_prog = (u_int32_t)prog;
115
call_msg.rm_call.cb_vers = (u_int32_t)vers;
116
xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
117
if (! xdr_callhdr(xdrs, &call_msg))
118
warnx("clntraw_create - Fatal header serialization error.");
119
clp->mcnt = XDR_GETPOS(xdrs);
120
XDR_DESTROY(xdrs);
121
122
/*
123
* Set xdrmem for client/server shared buffer
124
*/
125
xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
126
127
/*
128
* create client handle
129
*/
130
client->cl_ops = clnt_raw_ops();
131
client->cl_auth = authnone_create();
132
mutex_unlock(&clntraw_lock);
133
return (client);
134
}
135
136
/* ARGSUSED */
137
static enum clnt_stat
138
clnt_raw_call(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, void *argsp,
139
xdrproc_t xresults, void *resultsp, struct timeval timeout)
140
{
141
struct clntraw_private *clp = clntraw_private;
142
XDR *xdrs = &clp->xdr_stream;
143
struct rpc_msg msg;
144
enum clnt_stat status;
145
struct rpc_err error;
146
147
assert(h != NULL);
148
149
mutex_lock(&clntraw_lock);
150
if (clp == NULL) {
151
mutex_unlock(&clntraw_lock);
152
return (RPC_FAILED);
153
}
154
mutex_unlock(&clntraw_lock);
155
156
call_again:
157
/*
158
* send request
159
*/
160
xdrs->x_op = XDR_ENCODE;
161
XDR_SETPOS(xdrs, 0);
162
clp->u.mashl_rpcmsg.rm_xid ++ ;
163
if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
164
(! XDR_PUTINT32(xdrs, &proc)) ||
165
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
166
(! (*xargs)(xdrs, argsp))) {
167
return (RPC_CANTENCODEARGS);
168
}
169
(void)XDR_GETPOS(xdrs); /* called just to cause overhead */
170
171
/*
172
* We have to call server input routine here because this is
173
* all going on in one process. Yuk.
174
*/
175
svc_getreq_common(FD_SETSIZE);
176
177
/*
178
* get results
179
*/
180
xdrs->x_op = XDR_DECODE;
181
XDR_SETPOS(xdrs, 0);
182
msg.acpted_rply.ar_verf = _null_auth;
183
msg.acpted_rply.ar_results.where = resultsp;
184
msg.acpted_rply.ar_results.proc = xresults;
185
if (! xdr_replymsg(xdrs, &msg)) {
186
/*
187
* It's possible for xdr_replymsg() to fail partway
188
* through its attempt to decode the result from the
189
* server. If this happens, it will leave the reply
190
* structure partially populated with dynamically
191
* allocated memory. (This can happen if someone uses
192
* clntudp_bufcreate() to create a CLIENT handle and
193
* specifies a receive buffer size that is too small.)
194
* This memory must be free()ed to avoid a leak.
195
*/
196
int op = xdrs->x_op;
197
xdrs->x_op = XDR_FREE;
198
xdr_replymsg(xdrs, &msg);
199
xdrs->x_op = op;
200
return (RPC_CANTDECODERES);
201
}
202
_seterr_reply(&msg, &error);
203
status = error.re_status;
204
205
if (status == RPC_SUCCESS) {
206
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
207
status = RPC_AUTHERROR;
208
}
209
} /* end successful completion */
210
else {
211
if (AUTH_REFRESH(h->cl_auth, &msg))
212
goto call_again;
213
} /* end of unsuccessful completion */
214
215
if (status == RPC_SUCCESS) {
216
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
217
status = RPC_AUTHERROR;
218
}
219
if (msg.acpted_rply.ar_verf.oa_base != NULL) {
220
xdrs->x_op = XDR_FREE;
221
(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
222
}
223
}
224
225
return (status);
226
}
227
228
/*ARGSUSED*/
229
static void
230
clnt_raw_geterr(CLIENT *cl, struct rpc_err *err)
231
{
232
}
233
234
235
/* ARGSUSED */
236
static bool_t
237
clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr)
238
{
239
struct clntraw_private *clp = clntraw_private;
240
XDR *xdrs = &clp->xdr_stream;
241
bool_t rval;
242
243
mutex_lock(&clntraw_lock);
244
if (clp == NULL) {
245
rval = (bool_t) RPC_FAILED;
246
mutex_unlock(&clntraw_lock);
247
return (rval);
248
}
249
mutex_unlock(&clntraw_lock);
250
xdrs->x_op = XDR_FREE;
251
return ((*xdr_res)(xdrs, res_ptr));
252
}
253
254
/*ARGSUSED*/
255
static void
256
clnt_raw_abort(CLIENT *cl)
257
{
258
}
259
260
/*ARGSUSED*/
261
static bool_t
262
clnt_raw_control(CLIENT *cl, u_int ui, void *str)
263
{
264
return (FALSE);
265
}
266
267
/*ARGSUSED*/
268
static void
269
clnt_raw_destroy(CLIENT *cl)
270
{
271
}
272
273
static struct clnt_ops *
274
clnt_raw_ops(void)
275
{
276
static struct clnt_ops ops;
277
278
/* VARIABLES PROTECTED BY ops_lock: ops */
279
280
mutex_lock(&ops_lock);
281
if (ops.cl_call == NULL) {
282
ops.cl_call = clnt_raw_call;
283
ops.cl_abort = clnt_raw_abort;
284
ops.cl_geterr = clnt_raw_geterr;
285
ops.cl_freeres = clnt_raw_freeres;
286
ops.cl_destroy = clnt_raw_destroy;
287
ops.cl_control = clnt_raw_control;
288
}
289
mutex_unlock(&ops_lock);
290
return (&ops);
291
}
292
293