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.
49 #define authnone_create __authnone_create
50 #define xdrrec_create __xdrrec_create
51 #define xdrrec_endofrecord __xdrrec_endofrecord
52 #define xdrrec_skiprecord __xdrrec_skiprecord
53 #define xdr_callhdr __xdr_callhdr
54 #define xdr_replymsg __xdr_replymsg
55 #define xdr_opaque_auth __xdr_opaque_auth
56 #define xdrmem_create __xdrmem_create
57 #define getegid __getegid
58 #define geteuid __geteuid
70 #include <sys/socket.h>
71 #include <rpc/pmap_clnt.h>
76 extern u_long _create_xid (void) attribute_hidden;
78 #define MCALL_MSG_SIZE 24
84 struct timeval ct_wait;
85 bool_t ct_waitset; /* wait set by clnt_control? */
86 struct sockaddr_un ct_addr;
87 struct rpc_err ct_error;
88 char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
89 u_int ct_mpos; /* pos after marshal */
93 static int readunix (char *, char *, int);
94 static int writeunix (char *, char *, int);
96 static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
97 xdrproc_t, caddr_t, struct timeval);
98 static void clntunix_abort (void);
99 static void clntunix_geterr (CLIENT *, struct rpc_err *);
100 static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
101 static bool_t clntunix_control (CLIENT *, int, char *);
102 static void clntunix_destroy (CLIENT *);
104 static struct clnt_ops unix_ops =
115 * Create a client handle for a tcp/ip connection.
116 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
117 * connected to raddr. If *sockp non-negative then
118 * raddr is ignored. The rpc/tcp package does buffering
119 * similar to stdio, so the client must pick send and receive buffer sizes,];
120 * 0 => use the default.
121 * If raddr->sin_port is 0, then a binder on the remote machine is
122 * consulted for the right port number.
123 * NB: *sockp is copied into a private area.
124 * NB: It is the clients responsibility to close *sockp.
125 * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
126 * something more useful.
128 CLIENT attribute_hidden *
129 __clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
130 int *sockp, u_int sendsz, u_int recvsz)
133 struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
134 struct rpc_msg call_msg;
137 h = (CLIENT *) mem_alloc (sizeof (*h));
138 if (h == NULL || ct == NULL)
140 struct rpc_createerr *ce = &get_rpc_createerr ();
142 if (_IO_fwide (stderr, 0) > 0)
143 (void) __fwprintf (stderr, L"%s",
144 _("clntunix_create: out of memory\n"));
147 (void) fputs (_("clntunix_create: out of memory\n"), stderr);
148 ce->cf_stat = RPC_SYSTEMERROR;
149 ce->cf_error.re_errno = ENOMEM;
154 * If no socket given, open one
158 *sockp = socket (AF_UNIX, SOCK_STREAM, 0);
159 len = __strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
161 || connect (*sockp, (struct sockaddr *) raddr, len) < 0)
163 struct rpc_createerr *ce = &get_rpc_createerr ();
164 ce->cf_stat = RPC_SYSTEMERROR;
165 ce->cf_error.re_errno = errno;
170 ct->ct_closeit = TRUE;
174 ct->ct_closeit = FALSE;
178 * Set up private data struct
180 ct->ct_sock = *sockp;
181 ct->ct_wait.tv_usec = 0;
182 ct->ct_waitset = FALSE;
183 ct->ct_addr = *raddr;
186 * Initialize call message
188 call_msg.rm_xid = _create_xid ();
189 call_msg.rm_direction = CALL;
190 call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
191 call_msg.rm_call.cb_prog = prog;
192 call_msg.rm_call.cb_vers = vers;
195 * pre-serialize the static part of the call msg and stash it away
197 xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
198 if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
204 ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
205 XDR_DESTROY (&(ct->ct_xdrs));
208 * Create a client handle which uses xdrrec for serialization
209 * and authnone for authentication.
211 xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
212 (caddr_t) ct, readunix, writeunix);
213 h->cl_ops = &unix_ops;
214 h->cl_private = (caddr_t) ct;
215 h->cl_auth = authnone_create ();
220 * Something goofed, free stuff and barf
222 mem_free ((caddr_t) ct, sizeof (struct ct_data));
223 mem_free ((caddr_t) h, sizeof (CLIENT));
224 return (CLIENT *) NULL;
226 strong_alias(__clntunix_create,clntunix_create)
228 static enum clnt_stat
229 clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
234 xdrproc_t xdr_results;
236 struct timeval timeout;
238 struct ct_data *ct = (struct ct_data *) h->cl_private;
239 XDR *xdrs = &(ct->ct_xdrs);
240 struct rpc_msg reply_msg;
242 u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */
248 ct->ct_wait = timeout;
252 (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
253 && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
256 xdrs->x_op = XDR_ENCODE;
257 ct->ct_error.re_status = RPC_SUCCESS;
258 x_id = ntohl (--(*msg_x_id));
259 if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
260 (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
261 (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
262 (!(*xdr_args) (xdrs, args_ptr)))
264 if (ct->ct_error.re_status == RPC_SUCCESS)
265 ct->ct_error.re_status = RPC_CANTENCODEARGS;
266 (void) xdrrec_endofrecord (xdrs, TRUE);
267 return ct->ct_error.re_status;
269 if (!xdrrec_endofrecord (xdrs, shipnow))
270 return ct->ct_error.re_status = RPC_CANTSEND;
274 * Hack to provide rpc-based message passing
276 if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
277 return ct->ct_error.re_status = RPC_TIMEDOUT;
281 * Keep receiving until we get a valid transaction id
283 xdrs->x_op = XDR_DECODE;
286 reply_msg.acpted_rply.ar_verf = _null_auth;
287 reply_msg.acpted_rply.ar_results.where = NULL;
288 reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
289 if (!xdrrec_skiprecord (xdrs))
290 return ct->ct_error.re_status;
291 /* now decode and validate the response header */
292 if (!xdr_replymsg (xdrs, &reply_msg))
294 if (ct->ct_error.re_status == RPC_SUCCESS)
296 return ct->ct_error.re_status;
298 if (reply_msg.rm_xid == x_id)
305 _seterr_reply (&reply_msg, &(ct->ct_error));
306 if (ct->ct_error.re_status == RPC_SUCCESS)
308 if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
310 ct->ct_error.re_status = RPC_AUTHERROR;
311 ct->ct_error.re_why = AUTH_INVALIDRESP;
313 else if (!(*xdr_results) (xdrs, results_ptr))
315 if (ct->ct_error.re_status == RPC_SUCCESS)
316 ct->ct_error.re_status = RPC_CANTDECODERES;
318 /* free verifier ... */
319 if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
321 xdrs->x_op = XDR_FREE;
322 (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
324 } /* end successful completion */
327 /* maybe our credentials need to be refreshed ... */
328 if (refreshes-- && AUTH_REFRESH (h->cl_auth))
330 } /* end of unsuccessful completion */
331 return ct->ct_error.re_status;
335 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
337 struct ct_data *ct = (struct ct_data *) h->cl_private;
339 *errp = ct->ct_error;
343 clntunix_freeres (cl, xdr_res, res_ptr)
348 struct ct_data *ct = (struct ct_data *) cl->cl_private;
349 XDR *xdrs = &(ct->ct_xdrs);
351 xdrs->x_op = XDR_FREE;
352 return (*xdr_res) (xdrs, res_ptr);
361 clntunix_control (CLIENT *cl, int request, char *info)
363 struct ct_data *ct = (struct ct_data *) cl->cl_private;
369 ct->ct_closeit = TRUE;
371 case CLSET_FD_NCLOSE:
372 ct->ct_closeit = FALSE;
375 ct->ct_wait = *(struct timeval *) info;
378 *(struct timeval *) info = ct->ct_wait;
380 case CLGET_SERVER_ADDR:
381 *(struct sockaddr_un *) info = ct->ct_addr;
384 *(int *)info = ct->ct_sock;
388 * use the knowledge that xid is the
389 * first element in the call structure *.
390 * This will get the xid of the PREVIOUS call
392 *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
395 /* This will set the xid of the NEXT call */
396 *(u_long *) ct->ct_mcall = htonl (*(u_long *)info - 1);
397 /* decrement by 1 as clntunix_call() increments once */
400 * This RELIES on the information that, in the call body,
401 * the version number field is the fifth field from the
402 * begining of the RPC header. MUST be changed if the
403 * call_struct is changed
405 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
406 + 4 * BYTES_PER_XDR_UNIT));
409 *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
410 = htonl (*(u_long *) info);
414 * This RELIES on the information that, in the call body,
415 * the program number field is the field from the
416 * begining of the RPC header. MUST be changed if the
417 * call_struct is changed
419 *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
420 + 3 * BYTES_PER_XDR_UNIT));
423 *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
424 = htonl(*(u_long *) info);
426 /* The following are only possible with TI-RPC */
427 case CLGET_RETRY_TIMEOUT:
428 case CLSET_RETRY_TIMEOUT:
431 case CLSET_PUSH_TIMOD:
432 case CLSET_POP_TIMOD:
441 clntunix_destroy (CLIENT *h)
444 (struct ct_data *) h->cl_private;
448 (void) __close (ct->ct_sock);
450 XDR_DESTROY (&(ct->ct_xdrs));
451 mem_free ((caddr_t) ct, sizeof (struct ct_data));
452 mem_free ((caddr_t) h, sizeof (CLIENT));
456 __msgread (int sock, void *data, size_t cnt)
460 #ifdef SCM_CREDENTIALS
461 static char cm[CMSG_SPACE(sizeof (struct ucred))];
472 #ifdef SCM_CREDENTIALS
473 msg.msg_control = (caddr_t) &cm;
474 msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
481 if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
487 len = recvmsg (sock, &msg, 0);
490 if (msg.msg_flags & MSG_CTRUNC || len == 0)
501 __msgwrite (int sock, void *data, size_t cnt)
503 #ifndef SCM_CREDENTIALS
504 /* We cannot implement this reliably. */
505 __set_errno (ENOSYS);
510 struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
514 /* XXX I'm not sure, if gete?id() is always correct, or if we should use
515 get?id(). But since keyserv needs geteuid(), we have no other chance.
516 It would be much better, if the kernel could pass both to the server. */
517 cred.pid = __getpid ();
518 cred.uid = geteuid ();
519 cred.gid = getegid ();
521 __memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
522 cmsg->cmsg_level = SOL_SOCKET;
523 cmsg->cmsg_type = SCM_CREDENTIALS;
524 cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
533 msg.msg_control = cmsg;
534 msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
538 len = sendmsg (sock, &msg, 0);
550 * Interface between xdr serializer and unix connection.
551 * Behaves like the system calls, read & write, but keeps some error state
552 * around for the rpc level.
555 readunix (char *ctptr, char *buf, int len)
557 struct ct_data *ct = (struct ct_data *) ctptr;
559 int milliseconds = ((ct->ct_wait.tv_sec * 1000)
560 + (ct->ct_wait.tv_usec / 1000));
569 switch (poll (&fd, 1, milliseconds))
572 ct->ct_error.re_status = RPC_TIMEDOUT;
578 ct->ct_error.re_status = RPC_CANTRECV;
579 ct->ct_error.re_errno = errno;
584 switch (len = __msgread (ct->ct_sock, buf, len))
589 ct->ct_error.re_errno = ECONNRESET;
590 ct->ct_error.re_status = RPC_CANTRECV;
591 len = -1; /* it's really an error */
595 ct->ct_error.re_errno = errno;
596 ct->ct_error.re_status = RPC_CANTRECV;
603 writeunix (char *ctptr, char *buf, int len)
606 struct ct_data *ct = (struct ct_data *) ctptr;
608 for (cnt = len; cnt > 0; cnt -= i, buf += i)
610 if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
612 ct->ct_error.re_errno = errno;
613 ct->ct_error.re_status = RPC_CANTSEND;