2 * clnt_unix.c, Implements a TCP/IP based, client side RPC.
4 * Copyright (C) 1984, Sun Microsystems, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * 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.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * TCP based RPC supports 'batched calls'.
34 * A sequence of calls may be batched-up in a send buffer. The rpc call
35 * return immediately to the client even though the call was not necessarily
36 * sent. The batching occurs if the results' xdr routine is NULL (0) AND
37 * the rpc timeout value is zero (see clnt.h, rpc).
39 * Clients should NOT casually batch calls that in fact return results; that is,
40 * the server side should be aware that a call is batched and not produce any
41 * return message. Batched calls that produce many result messages can
42 * deadlock (netlock) the client and the server....
44 * Now go hang yourself.
55 #include <sys/socket.h>
56 #include <rpc/pmap_clnt.h>
61 extern u_long _create_xid (void);
63 #define MCALL_MSG_SIZE 24
69 struct timeval ct_wait;
70 bool_t ct_waitset; /* wait set by clnt_control? */
71 struct sockaddr_un ct_addr;
72 struct rpc_err ct_error;
73 char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
74 u_int ct_mpos; /* pos after marshal */
78 static int readunix (char *, char *, int);
79 static int writeunix (char *, char *, int);
81 static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
82 xdrproc_t, caddr_t, struct timeval);
83 static void clntunix_abort (void);
84 static void clntunix_geterr (CLIENT *, struct rpc_err *);
85 static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
86 static bool_t clntunix_control (CLIENT *, int, char *);
87 static void clntunix_destroy (CLIENT *);
89 static const struct clnt_ops unix_ops =
100 * Create a client handle for a tcp/ip connection.
101 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
102 * connected to raddr. If *sockp non-negative then
103 * raddr is ignored. The rpc/tcp package does buffering
104 * similar to stdio, so the client must pick send and receive buffer sizes,];
105 * 0 => use the default.
106 * If raddr->sin_port is 0, then a binder on the remote machine is
107 * consulted for the right port number.
108 * NB: *sockp is copied into a private area.
109 * NB: It is the clients responsibility to close *sockp.
110 * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
111 * something more useful.
114 clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
115 int *sockp, u_int sendsz, u_int recvsz)
118 struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
119 struct rpc_msg call_msg;
122 h = (CLIENT *) mem_alloc (sizeof (*h));
123 if (h == NULL || ct == NULL)
125 struct rpc_createerr *ce = &get_rpc_createerr ();
126 (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
127 ce->cf_stat = RPC_SYSTEMERROR;
128 ce->cf_error.re_errno = ENOMEM;
133 * If no socket given, open one
137 *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
138 len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
140 || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
142 struct rpc_createerr *ce = &get_rpc_createerr ();
143 ce->cf_stat = RPC_SYSTEMERROR;
144 ce->cf_error.re_errno = errno;
149 ct->ct_closeit = TRUE;
153 ct->ct_closeit = FALSE;
157 * Set up private data struct
159 ct->ct_sock = *sockp;
160 ct->ct_wait.tv_usec = 0;
161 ct->ct_waitset = FALSE;
162 ct->ct_addr = *raddr;
165 * Initialize call message
167 call_msg.rm_xid = _create_xid ();
168 call_msg.rm_direction = CALL;
169 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
170 call_msg.rm_call.cb_prog = prog;
171 call_msg.rm_call.cb_vers = vers;
174 * pre-serialize the static part of the call msg and stash it away
176 INTUSE(xdrmem_create) (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
178 if (!INTUSE(xdr_callhdr) (&(ct->ct_xdrs), &call_msg))
184 ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
185 XDR_DESTROY (&(ct->ct_xdrs));
188 * Create a client handle which uses xdrrec for serialization
189 * and authnone for authentication.
191 INTUSE(xdrrec_create) (&(ct->ct_xdrs), sendsz, recvsz,
192 (caddr_t) ct, readunix, writeunix);
193 h->cl_ops = (struct clnt_ops *) &unix_ops;
194 h->cl_private = (caddr_t) ct;
195 h->cl_auth = INTUSE(authnone_create) ();
200 * Something goofed, free stuff and barf
202 mem_free ((caddr_t) ct, sizeof (struct ct_data));
203 mem_free ((caddr_t) h, sizeof (CLIENT));
204 return (CLIENT *) NULL;
206 INTDEF (clntunix_create)
208 static enum clnt_stat
209 clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
214 xdrproc_t xdr_results;
216 struct timeval timeout;
218 struct ct_data *ct = (struct ct_data *) h->cl_private;
219 XDR *xdrs = &(ct->ct_xdrs);
220 struct rpc_msg reply_msg;
222 u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
228 ct->ct_wait = timeout;
232 (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
233 && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
236 xdrs->x_op = XDR_ENCODE;
237 ct->ct_error.re_status = RPC_SUCCESS;
238 x_id = ntohl (--(*msg_x_id));
239 if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
240 (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
241 (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
242 (!(*xdr_args) (xdrs, args_ptr)))
244 if (ct->ct_error.re_status == RPC_SUCCESS)
245 ct->ct_error.re_status = RPC_CANTENCODEARGS;
246 (void) INTUSE(xdrrec_endofrecord) (xdrs, TRUE);
247 return ct->ct_error.re_status;
249 if (!INTUSE(xdrrec_endofrecord) (xdrs, shipnow))
250 return ct->ct_error.re_status = RPC_CANTSEND;
254 * Hack to provide rpc-based message passing
256 if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
257 return ct->ct_error.re_status = RPC_TIMEDOUT;
261 * Keep receiving until we get a valid transaction id
263 xdrs->x_op = XDR_DECODE;
266 reply_msg.acpted_rply.ar_verf = _null_auth;
267 reply_msg.acpted_rply.ar_results.where = NULL;
268 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)INTUSE(xdr_void);
269 if (!INTUSE(xdrrec_skiprecord) (xdrs))
270 return ct->ct_error.re_status;
271 /* now decode and validate the response header */
272 if (!INTUSE(xdr_replymsg) (xdrs, &reply_msg))
274 if (ct->ct_error.re_status == RPC_SUCCESS)
276 return ct->ct_error.re_status;
278 if (reply_msg.rm_xid == x_id)
285 _seterr_reply (&reply_msg, &(ct->ct_error));
286 if (ct->ct_error.re_status == RPC_SUCCESS)
288 if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
290 ct->ct_error.re_status = RPC_AUTHERROR;
291 ct->ct_error.re_why = AUTH_INVALIDRESP;
293 else if (!(*xdr_results) (xdrs, results_ptr))
295 if (ct->ct_error.re_status == RPC_SUCCESS)
296 ct->ct_error.re_status = RPC_CANTDECODERES;
298 /* free verifier ... */
299 if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
301 xdrs->x_op = XDR_FREE;
302 (void) INTUSE(xdr_opaque_auth) (xdrs,
303 &(reply_msg.acpted_rply.ar_verf));
305 } /* end successful completion */
308 /* maybe our credentials need to be refreshed ... */
309 if (refreshes-- && AUTH_REFRESH (h->cl_auth))
311 } /* end of unsuccessful completion */
312 return ct->ct_error.re_status;
316 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
318 struct ct_data *ct = (struct ct_data *) h->cl_private;
320 *errp = ct->ct_error;
324 clntunix_freeres (cl, xdr_res, res_ptr)
329 struct ct_data *ct = (struct ct_data *) cl->cl_private;
330 XDR *xdrs = &(ct->ct_xdrs);
332 xdrs->x_op = XDR_FREE;
333 return (*xdr_res) (xdrs, res_ptr);
342 clntunix_control (CLIENT *cl, int request, char *info)
344 struct ct_data *ct = (struct ct_data *) cl->cl_private;
350 ct->ct_closeit = TRUE;
352 case CLSET_FD_NCLOSE:
353 ct->ct_closeit = FALSE;
356 ct->ct_wait = *(struct timeval *) info;
359 *(struct timeval *) info = ct->ct_wait;
361 case CLGET_SERVER_ADDR:
362 *(struct sockaddr_un *) info = ct->ct_addr;
365 *(int *)info = ct->ct_sock;
369 * use the knowledge that xid is the
370 * first element in the call structure *.
371 * This will get the xid of the PREVIOUS call
373 *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
376 /* This will set the xid of the NEXT call */
377 *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1);
378 /* decrement by 1 as clntunix_call() increments once */
381 * This RELIES on the information that, in the call body,
382 * the version number field is the fifth field from the
383 * begining of the RPC header. MUST be changed if the
384 * call_struct is changed
386 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
387 + 4 * BYTES_PER_XDR_UNIT));
390 *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
391 = htonl (*(u_long *) info);
395 * This RELIES on the information that, in the call body,
396 * the program number field is the field from the
397 * begining of the RPC header. MUST be changed if the
398 * call_struct is changed
400 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
401 + 3 * BYTES_PER_XDR_UNIT));
404 *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
405 = htonl(*(u_long *) info);
407 /* The following are only possible with TI-RPC */
408 case CLGET_RETRY_TIMEOUT:
409 case CLSET_RETRY_TIMEOUT:
412 case CLSET_PUSH_TIMOD:
413 case CLSET_POP_TIMOD:
422 clntunix_destroy (CLIENT *h)
425 (struct ct_data *) h->cl_private;
429 (void) __close (ct->ct_sock);
431 XDR_DESTROY (&(ct->ct_xdrs));
432 mem_free ((caddr_t) ct, sizeof (struct ct_data));
433 mem_free ((caddr_t) h, sizeof (CLIENT));
437 __msgread (int sock, void *data, size_t cnt)
441 #ifdef SCM_CREDENTIALS
442 static char cm[CMSG_SPACE(sizeof (struct ucred))];
453 #ifdef SCM_CREDENTIALS
454 msg.msg_control = (caddr_t) &cm;
455 msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
462 if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
468 len = __recvmsg (sock, &msg, 0);
471 if (msg.msg_flags & MSG_CTRUNC || len == 0)
482 __msgwrite (int sock, void *data, size_t cnt)
484 #ifndef SCM_CREDENTIALS
485 /* We cannot implement this reliably. */
486 __set_errno (ENOSYS);
491 struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
495 /* XXX I'm not sure, if gete?id() is always correct, or if we should use
496 get?id(). But since keyserv needs geteuid(), we have no other chance.
497 It would be much better, if the kernel could pass both to the server. */
498 cred.pid = __getpid ();
499 cred.uid = __geteuid ();
500 cred.gid = __getegid ();
502 memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
503 cmsg->cmsg_level = SOL_SOCKET;
504 cmsg->cmsg_type = SCM_CREDENTIALS;
505 cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
514 msg.msg_control = cmsg;
515 msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
519 len = __sendmsg (sock, &msg, 0);
531 * Interface between xdr serializer and unix connection.
532 * Behaves like the system calls, read & write, but keeps some error state
533 * around for the rpc level.
536 readunix (char *ctptr, char *buf, int len)
538 struct ct_data *ct = (struct ct_data *) ctptr;
540 int milliseconds = ((ct->ct_wait.tv_sec * 1000)
541 + (ct->ct_wait.tv_usec / 1000));
550 switch (__poll (&fd, 1, milliseconds))
553 ct->ct_error.re_status = RPC_TIMEDOUT;
559 ct->ct_error.re_status = RPC_CANTRECV;
560 ct->ct_error.re_errno = errno;
565 switch (len = __msgread (ct->ct_sock, buf, len))
570 ct->ct_error.re_errno = ECONNRESET;
571 ct->ct_error.re_status = RPC_CANTRECV;
572 len = -1; /* it's really an error */
576 ct->ct_error.re_errno = errno;
577 ct->ct_error.re_status = RPC_CANTRECV;
584 writeunix (char *ctptr, char *buf, int len)
587 struct ct_data *ct = (struct ct_data *) ctptr;
589 for (cnt = len; cnt > 0; cnt -= i, buf += i)
591 if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
593 ct->ct_error.re_errno = errno;
594 ct->ct_error.re_status = RPC_CANTSEND;