1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 /* 36 * clnt_raw.c 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 simulate rpc and get round trip overhead, without 41 * any interference from the kernel. 42 */ 43 #include "mt.h" 44 #include "rpc_mt.h" 45 #include <stdlib.h> 46 #include <rpc/rpc.h> 47 #include <syslog.h> 48 49 extern mutex_t clntraw_lock; 50 #define MCALL_MSG_SIZE 24 51 52 /* 53 * This is the "network" we will be moving stuff over. 54 */ 55 static struct clnt_raw_private { 56 CLIENT client_object; 57 struct netbuf *raw_netbuf; 58 char mashl_callmsg[MCALL_MSG_SIZE]; 59 uint_t mcnt; 60 } *clnt_raw_private; 61 62 static struct clnt_ops *clnt_raw_ops(); 63 64 extern bool_t xdr_opaque_auth(); 65 66 /* 67 * This netbuf is shared with the raw server. 68 */ 69 extern struct netbuf _rawcomnetbuf; 70 71 /* 72 * Create a client handle for memory based rpc. 73 */ 74 CLIENT * 75 clnt_raw_create(const rpcprog_t prog, const rpcvers_t vers) 76 { 77 struct clnt_raw_private *clp; 78 struct rpc_msg call_msg; 79 XDR xdrs; 80 CLIENT *client; 81 uint_t start; 82 83 /* VARIABLES PROTECTED BY clntraw_lock: clp */ 84 85 (void) mutex_lock(&clntraw_lock); 86 clp = clnt_raw_private; 87 if (clp != NULL) { 88 (void) mutex_unlock(&clntraw_lock); 89 return (&clp->client_object); 90 } 91 92 clp = calloc(1, sizeof (*clp)); 93 if (clp == NULL) { 94 (void) mutex_unlock(&clntraw_lock); 95 return (NULL); 96 } 97 98 clp->raw_netbuf = &_rawcomnetbuf; 99 100 /* 101 * pre-serialize the static part of the call msg and stash it away 102 */ 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; 107 108 xdrmem_create(&xdrs, clp->mashl_callmsg, sizeof (clp->mashl_callmsg), 109 XDR_ENCODE); 110 start = XDR_GETPOS(&xdrs); 111 if (!xdr_callhdr(&xdrs, &call_msg)) { 112 free(clp); 113 (void) syslog(LOG_ERR, 114 "clnt_raw_create: Fatal header serialization error"); 115 116 (void) mutex_unlock(&clntraw_lock); 117 return (NULL); 118 } 119 clp->mcnt = XDR_GETPOS(&xdrs) - start; 120 XDR_DESTROY(&xdrs); 121 122 /* 123 * create client handle 124 */ 125 client = &clp->client_object; 126 client->cl_ops = clnt_raw_ops(); 127 client->cl_auth = authnone_create(); 128 129 clnt_raw_private = clp; 130 131 (void) mutex_unlock(&clntraw_lock); 132 return (client); 133 } 134 135 /*ARGSUSED*/ 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) 139 { 140 struct clnt_raw_private *clp; 141 XDR xdrs; 142 struct rpc_msg msg; 143 uint_t start; 144 145 rpc_callerr.re_errno = 0; 146 rpc_callerr.re_terrno = 0; 147 148 (void) mutex_lock(&clntraw_lock); 149 clp = clnt_raw_private; 150 if (clp == NULL) { 151 (void) mutex_unlock(&clntraw_lock); 152 return (rpc_callerr.re_status = RPC_FAILED); 153 } 154 (void) mutex_unlock(&clntraw_lock); 155 156 call_again: 157 /* 158 * send request 159 */ 160 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->maxlen, 161 XDR_ENCODE); 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))) { 169 XDR_DESTROY(&xdrs); 170 return (rpc_callerr.re_status = RPC_CANTENCODEARGS); 171 } 172 clp->raw_netbuf->len = XDR_GETPOS(&xdrs) - start; 173 XDR_DESTROY(&xdrs); 174 175 /* 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. 179 */ 180 svc_getreq_common(FD_SETSIZE); 181 182 /* 183 * get results 184 */ 185 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->len, 186 XDR_DECODE); 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)) { 191 XDR_DESTROY(&xdrs); 192 return (rpc_callerr.re_status = RPC_CANTDECODERES); 193 } 194 XDR_DESTROY(&xdrs); 195 if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && 196 (msg.acpted_rply.ar_stat == SUCCESS)) 197 rpc_callerr.re_status = RPC_SUCCESS; 198 else 199 __seterr_reply(&msg, &rpc_callerr); 200 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; 205 } 206 if (msg.acpted_rply.ar_verf.oa_base != NULL) { 207 xdr_free(xdr_opaque_auth, 208 (char *)&(msg.acpted_rply.ar_verf)); 209 } 210 /* end successful completion */ 211 } else { 212 if (AUTH_REFRESH(h->cl_auth, &msg)) 213 goto call_again; 214 /* end of unsuccessful completion */ 215 } 216 217 return (rpc_callerr.re_status); 218 } 219 220 /*ARGSUSED*/ 221 static enum clnt_stat 222 clnt_raw_send(CLIENT *h, rpcproc_t proc, xdrproc_t xargs, caddr_t argsp) 223 { 224 struct clnt_raw_private *clp; 225 XDR xdrs; 226 uint_t start; 227 228 rpc_callerr.re_errno = 0; 229 rpc_callerr.re_terrno = 0; 230 231 (void) mutex_lock(&clntraw_lock); 232 clp = clnt_raw_private; 233 if (clp == NULL) { 234 (void) mutex_unlock(&clntraw_lock); 235 return (rpc_callerr.re_status = RPC_FAILED); 236 } 237 (void) mutex_unlock(&clntraw_lock); 238 239 /* 240 * send request 241 */ 242 xdrmem_create(&xdrs, clp->raw_netbuf->buf, clp->raw_netbuf->maxlen, 243 XDR_ENCODE); 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))) { 251 XDR_DESTROY(&xdrs); 252 return (rpc_callerr.re_status = RPC_CANTENCODEARGS); 253 } 254 clp->raw_netbuf->len = XDR_GETPOS(&xdrs) - start; 255 XDR_DESTROY(&xdrs); 256 257 /* 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. 261 */ 262 svc_getreq_common(FD_SETSIZE); 263 264 return (rpc_callerr.re_status = RPC_SUCCESS); 265 } 266 267 /*ARGSUSED*/ 268 static void 269 clnt_raw_geterr(CLIENT *cl, struct rpc_err *errp) 270 { 271 *errp = rpc_callerr; 272 } 273 274 /*ARGSUSED*/ 275 static bool_t 276 clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) 277 { 278 struct clnt_raw_private *clp; 279 280 (void) mutex_lock(&clntraw_lock); 281 clp = clnt_raw_private; 282 if (clp == NULL) { 283 (void) mutex_unlock(&clntraw_lock); 284 return (FALSE); 285 } 286 (void) mutex_unlock(&clntraw_lock); 287 288 xdr_free(xdr_res, res_ptr); 289 290 return (TRUE); 291 } 292 293 /*ARGSUSED*/ 294 static void 295 clnt_raw_abort(CLIENT *cl, struct rpc_err *errp) 296 { 297 } 298 299 /*ARGSUSED*/ 300 static bool_t 301 clnt_raw_control(CLIENT *cl, int request, char *info) 302 { 303 return (FALSE); 304 } 305 306 /*ARGSUSED*/ 307 static void 308 clnt_raw_destroy(CLIENT *cl) 309 { 310 } 311 312 static struct clnt_ops * 313 clnt_raw_ops(void) 314 { 315 static struct clnt_ops ops; 316 extern mutex_t ops_lock; 317 318 /* VARIABLES PROTECTED BY ops_lock: ops */ 319 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; 329 } 330 (void) mutex_unlock(&ops_lock); 331 return (&ops); 332 } 333