4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
30 * Portions of this source code were derived from Berkeley
31 * 4.3 BSD under license from the Regents of the University of
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 simulate rpc and get round trip overhead, without
41 * any interference from the kernel.
49 extern mutex_t clntraw_lock
;
50 #define MCALL_MSG_SIZE 24
53 * This is the "network" we will be moving stuff over.
55 static struct clnt_raw_private
{
57 struct netbuf
*raw_netbuf
;
58 char mashl_callmsg
[MCALL_MSG_SIZE
];
62 static struct clnt_ops
*clnt_raw_ops();
64 extern bool_t
xdr_opaque_auth();
67 * This netbuf is shared with the raw server.
69 extern struct netbuf _rawcomnetbuf
;
72 * Create a client handle for memory based rpc.
75 clnt_raw_create(const rpcprog_t prog
, const rpcvers_t vers
)
77 struct clnt_raw_private
*clp
;
78 struct rpc_msg call_msg
;
83 /* VARIABLES PROTECTED BY clntraw_lock: clp */
85 (void) mutex_lock(&clntraw_lock
);
86 clp
= clnt_raw_private
;
88 (void) mutex_unlock(&clntraw_lock
);
89 return (&clp
->client_object
);
92 clp
= calloc(1, sizeof (*clp
));
94 (void) mutex_unlock(&clntraw_lock
);
98 clp
->raw_netbuf
= &_rawcomnetbuf
;
101 * pre-serialize the static part of the call msg and stash it away
103 call_msg
.rm_direction
= CALL
;
104 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
105 call_msg
.rm_call
.cb_prog
= prog
;
106 call_msg
.rm_call
.cb_vers
= vers
;
108 xdrmem_create(&xdrs
, clp
->mashl_callmsg
, sizeof (clp
->mashl_callmsg
),
110 start
= XDR_GETPOS(&xdrs
);
111 if (!xdr_callhdr(&xdrs
, &call_msg
)) {
113 (void) syslog(LOG_ERR
,
114 "clnt_raw_create: Fatal header serialization error");
116 (void) mutex_unlock(&clntraw_lock
);
119 clp
->mcnt
= XDR_GETPOS(&xdrs
) - start
;
123 * create client handle
125 client
= &clp
->client_object
;
126 client
->cl_ops
= clnt_raw_ops();
127 client
->cl_auth
= authnone_create();
129 clnt_raw_private
= clp
;
131 (void) mutex_unlock(&clntraw_lock
);
136 static enum clnt_stat
137 clnt_raw_call(CLIENT
*h
, rpcproc_t proc
, xdrproc_t xargs
, caddr_t argsp
,
138 xdrproc_t xresults
, caddr_t resultsp
, struct timeval timeout
)
140 struct clnt_raw_private
*clp
;
145 rpc_callerr
.re_errno
= 0;
146 rpc_callerr
.re_terrno
= 0;
148 (void) mutex_lock(&clntraw_lock
);
149 clp
= clnt_raw_private
;
151 (void) mutex_unlock(&clntraw_lock
);
152 return (rpc_callerr
.re_status
= RPC_FAILED
);
154 (void) mutex_unlock(&clntraw_lock
);
160 xdrmem_create(&xdrs
, clp
->raw_netbuf
->buf
, clp
->raw_netbuf
->maxlen
,
162 start
= XDR_GETPOS(&xdrs
);
163 /* LINTED pointer alignment */
164 ((struct rpc_msg
*)clp
->mashl_callmsg
)->rm_xid
++;
165 if ((!XDR_PUTBYTES(&xdrs
, clp
->mashl_callmsg
, clp
->mcnt
)) ||
166 (!XDR_PUTINT32(&xdrs
, (int32_t *)&proc
)) ||
167 (!AUTH_MARSHALL(h
->cl_auth
, &xdrs
)) ||
168 (!(*xargs
)(&xdrs
, argsp
))) {
170 return (rpc_callerr
.re_status
= RPC_CANTENCODEARGS
);
172 clp
->raw_netbuf
->len
= XDR_GETPOS(&xdrs
) - start
;
176 * We have to call server input routine here because this is
177 * all going on in one process.
178 * By convention using FD_SETSIZE as the pseudo file descriptor.
180 svc_getreq_common(FD_SETSIZE
);
185 xdrmem_create(&xdrs
, clp
->raw_netbuf
->buf
, clp
->raw_netbuf
->len
,
187 msg
.acpted_rply
.ar_verf
= _null_auth
;
188 msg
.acpted_rply
.ar_results
.where
= resultsp
;
189 msg
.acpted_rply
.ar_results
.proc
= xresults
;
190 if (!xdr_replymsg(&xdrs
, &msg
)) {
192 return (rpc_callerr
.re_status
= RPC_CANTDECODERES
);
195 if ((msg
.rm_reply
.rp_stat
== MSG_ACCEPTED
) &&
196 (msg
.acpted_rply
.ar_stat
== SUCCESS
))
197 rpc_callerr
.re_status
= RPC_SUCCESS
;
199 __seterr_reply(&msg
, &rpc_callerr
);
201 if (rpc_callerr
.re_status
== RPC_SUCCESS
) {
202 if (!AUTH_VALIDATE(h
->cl_auth
, &msg
.acpted_rply
.ar_verf
)) {
203 rpc_callerr
.re_status
= RPC_AUTHERROR
;
204 rpc_callerr
.re_why
= AUTH_INVALIDRESP
;
206 if (msg
.acpted_rply
.ar_verf
.oa_base
!= NULL
) {
207 xdr_free(xdr_opaque_auth
,
208 (char *)&(msg
.acpted_rply
.ar_verf
));
210 /* end successful completion */
212 if (AUTH_REFRESH(h
->cl_auth
, &msg
))
214 /* end of unsuccessful completion */
217 return (rpc_callerr
.re_status
);
221 static enum clnt_stat
222 clnt_raw_send(CLIENT
*h
, rpcproc_t proc
, xdrproc_t xargs
, caddr_t argsp
)
224 struct clnt_raw_private
*clp
;
228 rpc_callerr
.re_errno
= 0;
229 rpc_callerr
.re_terrno
= 0;
231 (void) mutex_lock(&clntraw_lock
);
232 clp
= clnt_raw_private
;
234 (void) mutex_unlock(&clntraw_lock
);
235 return (rpc_callerr
.re_status
= RPC_FAILED
);
237 (void) mutex_unlock(&clntraw_lock
);
242 xdrmem_create(&xdrs
, clp
->raw_netbuf
->buf
, clp
->raw_netbuf
->maxlen
,
244 start
= XDR_GETPOS(&xdrs
);
245 /* LINTED pointer alignment */
246 ((struct rpc_msg
*)clp
->mashl_callmsg
)->rm_xid
++;
247 if ((!XDR_PUTBYTES(&xdrs
, clp
->mashl_callmsg
, clp
->mcnt
)) ||
248 (!XDR_PUTINT32(&xdrs
, (int32_t *)&proc
)) ||
249 (!AUTH_MARSHALL(h
->cl_auth
, &xdrs
)) ||
250 (!(*xargs
)(&xdrs
, argsp
))) {
252 return (rpc_callerr
.re_status
= RPC_CANTENCODEARGS
);
254 clp
->raw_netbuf
->len
= XDR_GETPOS(&xdrs
) - start
;
258 * We have to call server input routine here because this is
259 * all going on in one process.
260 * By convention using FD_SETSIZE as the pseudo file descriptor.
262 svc_getreq_common(FD_SETSIZE
);
264 return (rpc_callerr
.re_status
= RPC_SUCCESS
);
269 clnt_raw_geterr(CLIENT
*cl
, struct rpc_err
*errp
)
276 clnt_raw_freeres(CLIENT
*cl
, xdrproc_t xdr_res
, caddr_t res_ptr
)
278 struct clnt_raw_private
*clp
;
280 (void) mutex_lock(&clntraw_lock
);
281 clp
= clnt_raw_private
;
283 (void) mutex_unlock(&clntraw_lock
);
286 (void) mutex_unlock(&clntraw_lock
);
288 xdr_free(xdr_res
, res_ptr
);
295 clnt_raw_abort(CLIENT
*cl
, struct rpc_err
*errp
)
301 clnt_raw_control(CLIENT
*cl
, int request
, char *info
)
308 clnt_raw_destroy(CLIENT
*cl
)
312 static struct clnt_ops
*
315 static struct clnt_ops ops
;
316 extern mutex_t ops_lock
;
318 /* VARIABLES PROTECTED BY ops_lock: ops */
320 (void) mutex_lock(&ops_lock
);
321 if (ops
.cl_call
== NULL
) {
322 ops
.cl_call
= clnt_raw_call
;
323 ops
.cl_send
= clnt_raw_send
;
324 ops
.cl_abort
= clnt_raw_abort
;
325 ops
.cl_geterr
= clnt_raw_geterr
;
326 ops
.cl_freeres
= clnt_raw_freeres
;
327 ops
.cl_destroy
= clnt_raw_destroy
;
328 ops
.cl_control
= clnt_raw_control
;
330 (void) mutex_unlock(&ops_lock
);