xref: /freebsd/crypto/krb5/src/lib/rpc/clnt_raw.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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 *
clntraw_create(rpcprog_t prog,rpcvers_t vers)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
clntraw_call(CLIENT * h,rpcproc_t proc,xdrproc_t xargs,void * argsp,xdrproc_t xresults,void * resultsp,struct timeval timeout)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
clntraw_geterr(CLIENT * cl,struct rpc_err * err)226 clntraw_geterr(
227 	CLIENT *cl,
228 	struct rpc_err *err)
229 {
230 }
231 
232 
233 static bool_t
clntraw_freeres(CLIENT * cl,xdrproc_t xdr_res,void * res_ptr)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
clntraw_abort(CLIENT * cl)254 clntraw_abort(CLIENT *cl)
255 {
256 }
257 
258 /*ARGSUSED*/
259 static bool_t
clntraw_control(CLIENT * cl,int request,void * info)260 clntraw_control(
261 	CLIENT *cl,
262 	int request,
263 	void *info)
264 {
265 	return (FALSE);
266 }
267 
268 /*ARGSUSED*/
269 static void
clntraw_destroy(CLIENT * cl)270 clntraw_destroy(CLIENT *cl)
271 {
272 }
273