2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
25 * Sun Microsystems, Inc.
27 * Mountain View, California 94043
31 * clnt_unix.c, Implements a TCP/IP based, client side RPC.
33 * Copyright (C) 1984, Sun Microsystems, Inc.
35 * TCP based RPC supports 'batched calls'.
36 * A sequence of calls may be batched-up in a send buffer. The rpc call
37 * return immediately to the client even though the call was not necessarily
38 * sent. The batching occurs if the results' xdr routine is NULL (0) AND
39 * the rpc timeout value is zero (see clnt.h, rpc).
41 * Clients should NOT casually batch calls that in fact return results; that is,
42 * the server side should be aware that a call is batched and not produce any
43 * return message. Batched calls that produce many result messages can
44 * deadlock (netlock) the client and the server....
46 * Now go hang yourself.
59 #include <sys/socket.h>
60 #include <rpc/pmap_clnt.h>
63 libc_hidden_proto(fwprintf)
66 libc_hidden_proto(strlen)
67 libc_hidden_proto(memcpy)
68 libc_hidden_proto(socket)
69 libc_hidden_proto(close)
70 libc_hidden_proto(getpid)
71 libc_hidden_proto(authnone_create)
72 libc_hidden_proto(xdrrec_create)
73 libc_hidden_proto(xdrrec_endofrecord)
74 libc_hidden_proto(xdrrec_skiprecord)
75 libc_hidden_proto(xdr_callhdr)
76 libc_hidden_proto(xdr_replymsg)
77 libc_hidden_proto(xdr_opaque_auth)
78 libc_hidden_proto(xdrmem_create)
79 libc_hidden_proto(getegid)
80 libc_hidden_proto(geteuid)
81 libc_hidden_proto(_seterr_reply)
82 libc_hidden_proto(setsockopt)
83 libc_hidden_proto(connect)
84 libc_hidden_proto(recvmsg)
85 libc_hidden_proto(sendmsg)
86 libc_hidden_proto(poll)
87 libc_hidden_proto(fputs)
88 libc_hidden_proto(__rpc_thread_createerr)
90 extern u_long _create_xid (void) attribute_hidden;
92 #define MCALL_MSG_SIZE 24
98 struct timeval ct_wait;
99 bool_t ct_waitset; /* wait set by clnt_control? */
100 struct sockaddr_un ct_addr;
101 struct rpc_err ct_error;
102 char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
103 u_int ct_mpos; /* pos after marshal */
107 static int readunix (char *, char *, int);
108 static int writeunix (char *, char *, int);
110 static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
111 xdrproc_t, caddr_t, struct timeval);
112 static void clntunix_abort (void);
113 static void clntunix_geterr (CLIENT *, struct rpc_err *);
114 static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
115 static bool_t clntunix_control (CLIENT *, int, char *);
116 static void clntunix_destroy (CLIENT *);
118 static struct clnt_ops unix_ops =
129 * Create a client handle for a tcp/ip connection.
130 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
131 * connected to raddr. If *sockp non-negative then
132 * raddr is ignored. The rpc/tcp package does buffering
133 * similar to stdio, so the client must pick send and receive buffer sizes,];
134 * 0 => use the default.
135 * If raddr->sin_port is 0, then a binder on the remote machine is
136 * consulted for the right port number.
137 * NB: *sockp is copied into a private area.
138 * NB: It is the clients responsibility to close *sockp.
139 * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
140 * something more useful.
143 clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
144 int *sockp, u_int sendsz, u_int recvsz)
147 struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
148 struct rpc_msg call_msg;
151 h = (CLIENT *) mem_alloc (sizeof (*h));
152 if (h == NULL || ct == NULL)
154 struct rpc_createerr *ce = &get_rpc_createerr ();
156 if (_IO_fwide (stderr, 0) > 0)
157 (void) fwprintf (stderr, L"%s",
158 _("clntunix_create: out of memory\n"));
161 (void) fputs (_("clntunix_create: out of memory\n"), stderr);
162 ce->cf_stat = RPC_SYSTEMERROR;
163 ce->cf_error.re_errno = ENOMEM;
168 * If no socket given, open one
172 *sockp = socket (AF_UNIX, SOCK_STREAM, 0);
173 len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
175 || connect (*sockp, (struct sockaddr *) raddr, len) < 0)
177 struct rpc_createerr *ce = &get_rpc_createerr ();
178 ce->cf_stat = RPC_SYSTEMERROR;
179 ce->cf_error.re_errno = errno;
184 ct->ct_closeit = TRUE;
188 ct->ct_closeit = FALSE;
192 * Set up private data struct
194 ct->ct_sock = *sockp;
195 ct->ct_wait.tv_usec = 0;
196 ct->ct_waitset = FALSE;
197 ct->ct_addr = *raddr;
200 * Initialize call message
202 call_msg.rm_xid = _create_xid ();
203 call_msg.rm_direction = CALL;
204 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
205 call_msg.rm_call.cb_prog = prog;
206 call_msg.rm_call.cb_vers = vers;
209 * pre-serialize the static part of the call msg and stash it away
211 xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
212 if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
218 ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
219 XDR_DESTROY (&(ct->ct_xdrs));
222 * Create a client handle which uses xdrrec for serialization
223 * and authnone for authentication.
225 xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
226 (caddr_t) ct, readunix, writeunix);
227 h->cl_ops = &unix_ops;
228 h->cl_private = (caddr_t) ct;
229 h->cl_auth = authnone_create ();
234 * Something goofed, free stuff and barf
236 mem_free ((caddr_t) ct, sizeof (struct ct_data));
237 mem_free ((caddr_t) h, sizeof (CLIENT));
238 return (CLIENT *) NULL;
240 libc_hidden_proto(clntunix_create)
241 libc_hidden_def(clntunix_create)
243 static enum clnt_stat
244 clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
249 xdrproc_t xdr_results;
251 struct timeval timeout;
253 struct ct_data *ct = (struct ct_data *) h->cl_private;
254 XDR *xdrs = &(ct->ct_xdrs);
255 struct rpc_msg reply_msg;
257 u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
263 ct->ct_wait = timeout;
267 (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
268 && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
271 xdrs->x_op = XDR_ENCODE;
272 ct->ct_error.re_status = RPC_SUCCESS;
273 x_id = ntohl (--(*msg_x_id));
274 if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
275 (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
276 (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
277 (!(*xdr_args) (xdrs, args_ptr)))
279 if (ct->ct_error.re_status == RPC_SUCCESS)
280 ct->ct_error.re_status = RPC_CANTENCODEARGS;
281 (void) xdrrec_endofrecord (xdrs, TRUE);
282 return ct->ct_error.re_status;
284 if (!xdrrec_endofrecord (xdrs, shipnow))
285 return ct->ct_error.re_status = RPC_CANTSEND;
289 * Hack to provide rpc-based message passing
291 if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
292 return ct->ct_error.re_status = RPC_TIMEDOUT;
296 * Keep receiving until we get a valid transaction id
298 xdrs->x_op = XDR_DECODE;
301 reply_msg.acpted_rply.ar_verf = _null_auth;
302 reply_msg.acpted_rply.ar_results.where = NULL;
303 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
304 if (!xdrrec_skiprecord (xdrs))
305 return ct->ct_error.re_status;
306 /* now decode and validate the response header */
307 if (!xdr_replymsg (xdrs, &reply_msg))
309 if (ct->ct_error.re_status == RPC_SUCCESS)
311 return ct->ct_error.re_status;
313 if (reply_msg.rm_xid == x_id)
320 _seterr_reply (&reply_msg, &(ct->ct_error));
321 if (ct->ct_error.re_status == RPC_SUCCESS)
323 if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
325 ct->ct_error.re_status = RPC_AUTHERROR;
326 ct->ct_error.re_why = AUTH_INVALIDRESP;
328 else if (!(*xdr_results) (xdrs, results_ptr))
330 if (ct->ct_error.re_status == RPC_SUCCESS)
331 ct->ct_error.re_status = RPC_CANTDECODERES;
333 /* free verifier ... */
334 if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
336 xdrs->x_op = XDR_FREE;
337 (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
339 } /* end successful completion */
342 /* maybe our credentials need to be refreshed ... */
343 if (refreshes-- && AUTH_REFRESH (h->cl_auth))
345 } /* end of unsuccessful completion */
346 return ct->ct_error.re_status;
350 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
352 struct ct_data *ct = (struct ct_data *) h->cl_private;
354 *errp = ct->ct_error;
358 clntunix_freeres (cl, xdr_res, res_ptr)
363 struct ct_data *ct = (struct ct_data *) cl->cl_private;
364 XDR *xdrs = &(ct->ct_xdrs);
366 xdrs->x_op = XDR_FREE;
367 return (*xdr_res) (xdrs, res_ptr);
376 clntunix_control (CLIENT *cl, int request, char *info)
378 struct ct_data *ct = (struct ct_data *) cl->cl_private;
384 ct->ct_closeit = TRUE;
386 case CLSET_FD_NCLOSE:
387 ct->ct_closeit = FALSE;
390 ct->ct_wait = *(struct timeval *) info;
393 *(struct timeval *) info = ct->ct_wait;
395 case CLGET_SERVER_ADDR:
396 *(struct sockaddr_un *) info = ct->ct_addr;
399 *(int *)info = ct->ct_sock;
403 * use the knowledge that xid is the
404 * first element in the call structure *.
405 * This will get the xid of the PREVIOUS call
407 *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
410 /* This will set the xid of the NEXT call */
411 *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1);
412 /* decrement by 1 as clntunix_call() increments once */
415 * This RELIES on the information that, in the call body,
416 * the version number field is the fifth field from the
417 * begining of the RPC header. MUST be changed if the
418 * call_struct is changed
420 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
421 + 4 * BYTES_PER_XDR_UNIT));
424 *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
425 = htonl (*(u_long *) info);
429 * This RELIES on the information that, in the call body,
430 * the program number field is the field from the
431 * begining of the RPC header. MUST be changed if the
432 * call_struct is changed
434 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
435 + 3 * BYTES_PER_XDR_UNIT));
438 *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
439 = htonl(*(u_long *) info);
441 /* The following are only possible with TI-RPC */
442 case CLGET_RETRY_TIMEOUT:
443 case CLSET_RETRY_TIMEOUT:
446 case CLSET_PUSH_TIMOD:
447 case CLSET_POP_TIMOD:
456 clntunix_destroy (CLIENT *h)
459 (struct ct_data *) h->cl_private;
463 (void) close (ct->ct_sock);
465 XDR_DESTROY (&(ct->ct_xdrs));
466 mem_free ((caddr_t) ct, sizeof (struct ct_data));
467 mem_free ((caddr_t) h, sizeof (CLIENT));
471 __msgread (int sock, void *data, size_t cnt)
475 #ifdef SCM_CREDENTIALS
476 static char cm[CMSG_SPACE(sizeof (struct ucred))];
487 #ifdef SCM_CREDENTIALS
488 msg.msg_control = (caddr_t) &cm;
489 msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
496 if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
502 len = recvmsg (sock, &msg, 0);
505 if (msg.msg_flags & MSG_CTRUNC || len == 0)
516 __msgwrite (int sock, void *data, size_t cnt)
518 #ifndef SCM_CREDENTIALS
519 /* We cannot implement this reliably. */
520 __set_errno (ENOSYS);
525 struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
529 /* XXX I'm not sure, if gete?id() is always correct, or if we should use
530 get?id(). But since keyserv needs geteuid(), we have no other chance.
531 It would be much better, if the kernel could pass both to the server. */
532 cred.pid = getpid ();
533 cred.uid = geteuid ();
534 cred.gid = getegid ();
536 memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
537 cmsg->cmsg_level = SOL_SOCKET;
538 cmsg->cmsg_type = SCM_CREDENTIALS;
539 cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
548 msg.msg_control = cmsg;
549 msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
553 len = sendmsg (sock, &msg, 0);
565 * Interface between xdr serializer and unix connection.
566 * Behaves like the system calls, read & write, but keeps some error state
567 * around for the rpc level.
570 readunix (char *ctptr, char *buf, int len)
572 struct ct_data *ct = (struct ct_data *) ctptr;
574 int milliseconds = ((ct->ct_wait.tv_sec * 1000)
575 + (ct->ct_wait.tv_usec / 1000));
584 switch (poll (&fd, 1, milliseconds))
587 ct->ct_error.re_status = RPC_TIMEDOUT;
593 ct->ct_error.re_status = RPC_CANTRECV;
594 ct->ct_error.re_errno = errno;
599 switch (len = __msgread (ct->ct_sock, buf, len))
604 ct->ct_error.re_errno = ECONNRESET;
605 ct->ct_error.re_status = RPC_CANTRECV;
606 len = -1; /* it's really an error */
610 ct->ct_error.re_errno = errno;
611 ct->ct_error.re_status = RPC_CANTRECV;
618 writeunix (char *ctptr, char *buf, int len)
621 struct ct_data *ct = (struct ct_data *) ctptr;
623 for (cnt = len; cnt > 0; cnt -= i, buf += i)
625 if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
627 ct->ct_error.re_errno = errno;
628 ct->ct_error.re_status = RPC_CANTSEND;