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