2 * clnt_unix.c, Implements a TCP/IP based, client side RPC.
4 * Copyright (c) 2010, Oracle America, 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 the "Oracle America, 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>
58 #include <shlib-compat.h>
60 extern u_long
_create_xid (void);
62 #define MCALL_MSG_SIZE 24
68 struct timeval ct_wait
;
69 bool_t ct_waitset
; /* wait set by clnt_control? */
70 struct sockaddr_un ct_addr
;
71 struct rpc_err ct_error
;
72 char ct_mcall
[MCALL_MSG_SIZE
]; /* marshalled callmsg */
73 u_int ct_mpos
; /* pos after marshal */
77 static int readunix (char *, char *, int);
78 static int writeunix (char *, char *, int);
80 static enum clnt_stat
clntunix_call (CLIENT
*, u_long
, xdrproc_t
, caddr_t
,
81 xdrproc_t
, caddr_t
, struct timeval
);
82 static void clntunix_abort (void);
83 static void clntunix_geterr (CLIENT
*, struct rpc_err
*);
84 static bool_t
clntunix_freeres (CLIENT
*, xdrproc_t
, caddr_t
);
85 static bool_t
clntunix_control (CLIENT
*, int, char *);
86 static void clntunix_destroy (CLIENT
*);
88 static const struct clnt_ops unix_ops
=
99 * Create a client handle for a tcp/ip connection.
100 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
101 * connected to raddr. If *sockp non-negative then
102 * raddr is ignored. The rpc/tcp package does buffering
103 * similar to stdio, so the client must pick send and receive buffer sizes,];
104 * 0 => use the default.
105 * If raddr->sin_port is 0, then a binder on the remote machine is
106 * consulted for the right port number.
107 * NB: *sockp is copied into a private area.
108 * NB: It is the clients responsibility to close *sockp.
109 * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
110 * something more useful.
113 clntunix_create (struct sockaddr_un
*raddr
, u_long prog
, u_long vers
,
114 int *sockp
, u_int sendsz
, u_int recvsz
)
117 struct ct_data
*ct
= (struct ct_data
*) mem_alloc (sizeof (*ct
));
118 struct rpc_msg call_msg
;
121 h
= (CLIENT
*) mem_alloc (sizeof (*h
));
122 if (h
== NULL
|| ct
== NULL
)
124 struct rpc_createerr
*ce
= &get_rpc_createerr ();
125 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
126 ce
->cf_stat
= RPC_SYSTEMERROR
;
127 ce
->cf_error
.re_errno
= ENOMEM
;
132 * If no socket given, open one
136 *sockp
= __socket (AF_UNIX
, SOCK_STREAM
, 0);
137 len
= strlen (raddr
->sun_path
) + sizeof (raddr
->sun_family
) + 1;
139 || __connect (*sockp
, (struct sockaddr
*) raddr
, len
) < 0)
141 struct rpc_createerr
*ce
= &get_rpc_createerr ();
142 ce
->cf_stat
= RPC_SYSTEMERROR
;
143 ce
->cf_error
.re_errno
= errno
;
148 ct
->ct_closeit
= TRUE
;
152 ct
->ct_closeit
= FALSE
;
156 * Set up private data struct
158 ct
->ct_sock
= *sockp
;
159 ct
->ct_wait
.tv_usec
= 0;
160 ct
->ct_waitset
= FALSE
;
161 ct
->ct_addr
= *raddr
;
164 * Initialize call message
166 call_msg
.rm_xid
= _create_xid ();
167 call_msg
.rm_direction
= CALL
;
168 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
169 call_msg
.rm_call
.cb_prog
= prog
;
170 call_msg
.rm_call
.cb_vers
= vers
;
173 * pre-serialize the static part of the call msg and stash it away
175 xdrmem_create (&(ct
->ct_xdrs
), ct
->ct_mcall
, MCALL_MSG_SIZE
, XDR_ENCODE
);
176 if (!xdr_callhdr (&(ct
->ct_xdrs
), &call_msg
))
182 ct
->ct_mpos
= XDR_GETPOS (&(ct
->ct_xdrs
));
183 XDR_DESTROY (&(ct
->ct_xdrs
));
186 * Create a client handle which uses xdrrec for serialization
187 * and authnone for authentication.
189 xdrrec_create (&(ct
->ct_xdrs
), sendsz
, recvsz
,
190 (caddr_t
) ct
, readunix
, writeunix
);
191 h
->cl_ops
= (struct clnt_ops
*) &unix_ops
;
192 h
->cl_private
= (caddr_t
) ct
;
193 h
->cl_auth
= authnone_create ();
198 * Something goofed, free stuff and barf
200 mem_free ((caddr_t
) ct
, sizeof (struct ct_data
));
201 mem_free ((caddr_t
) h
, sizeof (CLIENT
));
202 return (CLIENT
*) NULL
;
204 libc_hidden_nolink_sunrpc (clntunix_create
, GLIBC_2_1
)
206 static enum clnt_stat
207 clntunix_call (CLIENT
*h
, u_long proc
, xdrproc_t xdr_args
, caddr_t args_ptr
,
208 xdrproc_t xdr_results
, caddr_t results_ptr
,
209 struct timeval timeout
)
211 struct ct_data
*ct
= (struct ct_data
*) h
->cl_private
;
212 XDR
*xdrs
= &(ct
->ct_xdrs
);
213 struct rpc_msg reply_msg
;
215 uint32_t *msg_x_id
= (uint32_t *) (ct
->ct_mcall
); /* yuk */
221 ct
->ct_wait
= timeout
;
225 (xdr_results
== (xdrproc_t
) 0 && ct
->ct_wait
.tv_sec
== 0
226 && ct
->ct_wait
.tv_usec
== 0) ? FALSE
: TRUE
;
229 xdrs
->x_op
= XDR_ENCODE
;
230 ct
->ct_error
.re_status
= RPC_SUCCESS
;
231 x_id
= ntohl (--(*msg_x_id
));
232 if ((!XDR_PUTBYTES (xdrs
, ct
->ct_mcall
, ct
->ct_mpos
)) ||
233 (!XDR_PUTLONG (xdrs
, (long *) &proc
)) ||
234 (!AUTH_MARSHALL (h
->cl_auth
, xdrs
)) ||
235 (!(*xdr_args
) (xdrs
, args_ptr
)))
237 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
238 ct
->ct_error
.re_status
= RPC_CANTENCODEARGS
;
239 (void) xdrrec_endofrecord (xdrs
, TRUE
);
240 return ct
->ct_error
.re_status
;
242 if (!xdrrec_endofrecord (xdrs
, shipnow
))
243 return ct
->ct_error
.re_status
= RPC_CANTSEND
;
247 * Hack to provide rpc-based message passing
249 if (ct
->ct_wait
.tv_sec
== 0 && ct
->ct_wait
.tv_usec
== 0)
250 return ct
->ct_error
.re_status
= RPC_TIMEDOUT
;
254 * Keep receiving until we get a valid transaction id
256 xdrs
->x_op
= XDR_DECODE
;
259 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
260 reply_msg
.acpted_rply
.ar_results
.where
= NULL
;
261 reply_msg
.acpted_rply
.ar_results
.proc
= (xdrproc_t
)xdr_void
;
262 if (!xdrrec_skiprecord (xdrs
))
263 return ct
->ct_error
.re_status
;
264 /* now decode and validate the response header */
265 if (!xdr_replymsg (xdrs
, &reply_msg
))
267 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
269 return ct
->ct_error
.re_status
;
271 if (reply_msg
.rm_xid
== x_id
)
278 _seterr_reply (&reply_msg
, &(ct
->ct_error
));
279 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
281 if (!AUTH_VALIDATE (h
->cl_auth
, &reply_msg
.acpted_rply
.ar_verf
))
283 ct
->ct_error
.re_status
= RPC_AUTHERROR
;
284 ct
->ct_error
.re_why
= AUTH_INVALIDRESP
;
286 else if (!(*xdr_results
) (xdrs
, results_ptr
))
288 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
289 ct
->ct_error
.re_status
= RPC_CANTDECODERES
;
291 /* free verifier ... */
292 if (reply_msg
.acpted_rply
.ar_verf
.oa_base
!= NULL
)
294 xdrs
->x_op
= XDR_FREE
;
295 (void) xdr_opaque_auth (xdrs
, &(reply_msg
.acpted_rply
.ar_verf
));
297 } /* end successful completion */
300 /* maybe our credentials need to be refreshed ... */
301 if (refreshes
-- && AUTH_REFRESH (h
->cl_auth
))
303 } /* end of unsuccessful completion */
304 return ct
->ct_error
.re_status
;
308 clntunix_geterr (CLIENT
*h
, struct rpc_err
*errp
)
310 struct ct_data
*ct
= (struct ct_data
*) h
->cl_private
;
312 *errp
= ct
->ct_error
;
316 clntunix_freeres (CLIENT
*cl
, xdrproc_t xdr_res
, caddr_t res_ptr
)
318 struct ct_data
*ct
= (struct ct_data
*) cl
->cl_private
;
319 XDR
*xdrs
= &(ct
->ct_xdrs
);
321 xdrs
->x_op
= XDR_FREE
;
322 return (*xdr_res
) (xdrs
, res_ptr
);
326 clntunix_abort (void)
331 clntunix_control (CLIENT
*cl
, int request
, char *info
)
333 struct ct_data
*ct
= (struct ct_data
*) cl
->cl_private
;
340 ct
->ct_closeit
= TRUE
;
342 case CLSET_FD_NCLOSE
:
343 ct
->ct_closeit
= FALSE
;
346 ct
->ct_wait
= *(struct timeval
*) info
;
349 *(struct timeval
*) info
= ct
->ct_wait
;
351 case CLGET_SERVER_ADDR
:
352 *(struct sockaddr_un
*) info
= ct
->ct_addr
;
355 *(int *)info
= ct
->ct_sock
;
359 * use the knowledge that xid is the
360 * first element in the call structure *.
361 * This will get the xid of the PREVIOUS call
363 memcpy (&ui32
, ct
->ct_mcall
, sizeof (ui32
));
365 memcpy (info
, &ul
, sizeof (ul
));
368 /* This will set the xid of the NEXT call */
369 memcpy (&ul
, info
, sizeof (ul
));
370 ui32
= htonl (ul
- 1);
371 memcpy (ct
->ct_mcall
, &ui32
, sizeof (ui32
));
372 /* decrement by 1 as clntunix_call() increments once */
376 * This RELIES on the information that, in the call body,
377 * the version number field is the fifth field from the
378 * beginning of the RPC header. MUST be changed if the
379 * call_struct is changed
381 memcpy (&ui32
, ct
->ct_mcall
+ 4 * BYTES_PER_XDR_UNIT
, sizeof (ui32
));
383 memcpy (info
, &ul
, sizeof (ul
));
386 memcpy (&ul
, info
, sizeof (ul
));
388 memcpy (ct
->ct_mcall
+ 4 * BYTES_PER_XDR_UNIT
, &ui32
, sizeof (ui32
));
392 * This RELIES on the information that, in the call body,
393 * the program number field is the field from the
394 * beginning of the RPC header. MUST be changed if the
395 * call_struct is changed
397 memcpy (&ui32
, ct
->ct_mcall
+ 3 * BYTES_PER_XDR_UNIT
, sizeof (ui32
));
399 memcpy (info
, &ul
, sizeof (ul
));
402 memcpy (&ul
, info
, sizeof (ul
));
404 memcpy (ct
->ct_mcall
+ 3 * BYTES_PER_XDR_UNIT
, &ui32
, sizeof (ui32
));
406 /* The following are only possible with TI-RPC */
407 case CLGET_RETRY_TIMEOUT
:
408 case CLSET_RETRY_TIMEOUT
:
411 case CLSET_PUSH_TIMOD
:
412 case CLSET_POP_TIMOD
:
421 clntunix_destroy (CLIENT
*h
)
424 (struct ct_data
*) h
->cl_private
;
428 (void) __close (ct
->ct_sock
);
430 XDR_DESTROY (&(ct
->ct_xdrs
));
431 mem_free ((caddr_t
) ct
, sizeof (struct ct_data
));
432 mem_free ((caddr_t
) h
, sizeof (CLIENT
));
436 __msgread (int sock
, void *data
, size_t cnt
)
440 #ifdef SCM_CREDENTIALS
441 static char cm
[CMSG_SPACE(sizeof (struct ucred
))];
452 #ifdef SCM_CREDENTIALS
453 msg
.msg_control
= (caddr_t
) &cm
;
454 msg
.msg_controllen
= CMSG_SPACE(sizeof (struct ucred
));
461 if (__setsockopt (sock
, SOL_SOCKET
, SO_PASSCRED
, &on
, sizeof (on
)))
467 len
= __recvmsg (sock
, &msg
, 0);
470 if (msg
.msg_flags
& MSG_CTRUNC
|| len
== 0)
481 __msgwrite (int sock
, void *data
, size_t cnt
)
483 #ifndef SCM_CREDENTIALS
484 /* We cannot implement this reliably. */
485 __set_errno (ENOSYS
);
490 struct cmsghdr
*cmsg
= alloca (CMSG_SPACE(sizeof (struct ucred
)));
494 /* XXX I'm not sure, if gete?id() is always correct, or if we should use
495 get?id(). But since keyserv needs geteuid(), we have no other chance.
496 It would be much better, if the kernel could pass both to the server. */
497 cred
.pid
= __getpid ();
498 cred
.uid
= __geteuid ();
499 cred
.gid
= __getegid ();
501 memcpy (CMSG_DATA(cmsg
), &cred
, sizeof (struct ucred
));
502 cmsg
->cmsg_level
= SOL_SOCKET
;
503 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
504 cmsg
->cmsg_len
= sizeof(*cmsg
) + sizeof(struct ucred
);
513 msg
.msg_control
= cmsg
;
514 msg
.msg_controllen
= CMSG_ALIGN(cmsg
->cmsg_len
);
518 len
= __sendmsg (sock
, &msg
, 0);
530 * Interface between xdr serializer and unix connection.
531 * Behaves like the system calls, read & write, but keeps some error state
532 * around for the rpc level.
535 readunix (char *ctptr
, char *buf
, int len
)
537 struct ct_data
*ct
= (struct ct_data
*) ctptr
;
539 int milliseconds
= ((ct
->ct_wait
.tv_sec
* 1000)
540 + (ct
->ct_wait
.tv_usec
/ 1000));
549 switch (__poll (&fd
, 1, milliseconds
))
552 ct
->ct_error
.re_status
= RPC_TIMEDOUT
;
558 ct
->ct_error
.re_status
= RPC_CANTRECV
;
559 ct
->ct_error
.re_errno
= errno
;
564 switch (len
= __msgread (ct
->ct_sock
, buf
, len
))
569 ct
->ct_error
.re_errno
= ECONNRESET
;
570 ct
->ct_error
.re_status
= RPC_CANTRECV
;
571 len
= -1; /* it's really an error */
575 ct
->ct_error
.re_errno
= errno
;
576 ct
->ct_error
.re_status
= RPC_CANTRECV
;
583 writeunix (char *ctptr
, char *buf
, int len
)
586 struct ct_data
*ct
= (struct ct_data
*) ctptr
;
588 for (cnt
= len
; cnt
> 0; cnt
-= i
, buf
+= i
)
590 if ((i
= __msgwrite (ct
->ct_sock
, buf
, cnt
)) == -1)
592 ct
->ct_error
.re_errno
= errno
;
593 ct
->ct_error
.re_status
= RPC_CANTSEND
;