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>
59 extern u_long
_create_xid (void);
61 #define MCALL_MSG_SIZE 24
67 struct timeval ct_wait
;
68 bool_t ct_waitset
; /* wait set by clnt_control? */
69 struct sockaddr_un ct_addr
;
70 struct rpc_err ct_error
;
71 char ct_mcall
[MCALL_MSG_SIZE
]; /* marshalled callmsg */
72 u_int ct_mpos
; /* pos after marshal */
76 static int readunix (char *, char *, int);
77 static int writeunix (char *, char *, int);
79 static enum clnt_stat
clntunix_call (CLIENT
*, u_long
, xdrproc_t
, caddr_t
,
80 xdrproc_t
, caddr_t
, struct timeval
);
81 static void clntunix_abort (void);
82 static void clntunix_geterr (CLIENT
*, struct rpc_err
*);
83 static bool_t
clntunix_freeres (CLIENT
*, xdrproc_t
, caddr_t
);
84 static bool_t
clntunix_control (CLIENT
*, int, char *);
85 static void clntunix_destroy (CLIENT
*);
87 static const struct clnt_ops unix_ops
=
98 * Create a client handle for a tcp/ip connection.
99 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
100 * connected to raddr. If *sockp non-negative then
101 * raddr is ignored. The rpc/tcp package does buffering
102 * similar to stdio, so the client must pick send and receive buffer sizes,];
103 * 0 => use the default.
104 * If raddr->sin_port is 0, then a binder on the remote machine is
105 * consulted for the right port number.
106 * NB: *sockp is copied into a private area.
107 * NB: It is the clients responsibility to close *sockp.
108 * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
109 * something more useful.
112 clntunix_create (struct sockaddr_un
*raddr
, u_long prog
, u_long vers
,
113 int *sockp
, u_int sendsz
, u_int recvsz
)
116 struct ct_data
*ct
= (struct ct_data
*) mem_alloc (sizeof (*ct
));
117 struct rpc_msg call_msg
;
120 h
= (CLIENT
*) mem_alloc (sizeof (*h
));
121 if (h
== NULL
|| ct
== NULL
)
123 struct rpc_createerr
*ce
= &get_rpc_createerr ();
124 (void) __fxprintf (NULL
, "%s: %s", __func__
, _("out of memory\n"));
125 ce
->cf_stat
= RPC_SYSTEMERROR
;
126 ce
->cf_error
.re_errno
= ENOMEM
;
131 * If no socket given, open one
135 *sockp
= __socket (AF_UNIX
, SOCK_STREAM
, 0);
136 len
= strlen (raddr
->sun_path
) + sizeof (raddr
->sun_family
) + 1;
138 || __connect (*sockp
, (struct sockaddr
*) raddr
, len
) < 0)
140 struct rpc_createerr
*ce
= &get_rpc_createerr ();
141 ce
->cf_stat
= RPC_SYSTEMERROR
;
142 ce
->cf_error
.re_errno
= errno
;
147 ct
->ct_closeit
= TRUE
;
151 ct
->ct_closeit
= FALSE
;
155 * Set up private data struct
157 ct
->ct_sock
= *sockp
;
158 ct
->ct_wait
.tv_usec
= 0;
159 ct
->ct_waitset
= FALSE
;
160 ct
->ct_addr
= *raddr
;
163 * Initialize call message
165 call_msg
.rm_xid
= _create_xid ();
166 call_msg
.rm_direction
= CALL
;
167 call_msg
.rm_call
.cb_rpcvers
= RPC_MSG_VERSION
;
168 call_msg
.rm_call
.cb_prog
= prog
;
169 call_msg
.rm_call
.cb_vers
= vers
;
172 * pre-serialize the static part of the call msg and stash it away
174 xdrmem_create (&(ct
->ct_xdrs
), ct
->ct_mcall
, MCALL_MSG_SIZE
, XDR_ENCODE
);
175 if (!xdr_callhdr (&(ct
->ct_xdrs
), &call_msg
))
181 ct
->ct_mpos
= XDR_GETPOS (&(ct
->ct_xdrs
));
182 XDR_DESTROY (&(ct
->ct_xdrs
));
185 * Create a client handle which uses xdrrec for serialization
186 * and authnone for authentication.
188 xdrrec_create (&(ct
->ct_xdrs
), sendsz
, recvsz
,
189 (caddr_t
) ct
, readunix
, writeunix
);
190 h
->cl_ops
= (struct clnt_ops
*) &unix_ops
;
191 h
->cl_private
= (caddr_t
) ct
;
192 h
->cl_auth
= authnone_create ();
197 * Something goofed, free stuff and barf
199 mem_free ((caddr_t
) ct
, sizeof (struct ct_data
));
200 mem_free ((caddr_t
) h
, sizeof (CLIENT
));
201 return (CLIENT
*) NULL
;
203 libc_hidden_nolink (clntunix_create
, GLIBC_2_1
)
205 static enum clnt_stat
206 clntunix_call (h
, proc
, xdr_args
, args_ptr
, xdr_results
, results_ptr
, timeout
)
211 xdrproc_t xdr_results
;
213 struct timeval timeout
;
215 struct ct_data
*ct
= (struct ct_data
*) h
->cl_private
;
216 XDR
*xdrs
= &(ct
->ct_xdrs
);
217 struct rpc_msg reply_msg
;
219 u_int32_t
*msg_x_id
= (u_int32_t
*) (ct
->ct_mcall
); /* yuk */
225 ct
->ct_wait
= timeout
;
229 (xdr_results
== (xdrproc_t
) 0 && ct
->ct_wait
.tv_sec
== 0
230 && ct
->ct_wait
.tv_usec
== 0) ? FALSE
: TRUE
;
233 xdrs
->x_op
= XDR_ENCODE
;
234 ct
->ct_error
.re_status
= RPC_SUCCESS
;
235 x_id
= ntohl (--(*msg_x_id
));
236 if ((!XDR_PUTBYTES (xdrs
, ct
->ct_mcall
, ct
->ct_mpos
)) ||
237 (!XDR_PUTLONG (xdrs
, (long *) &proc
)) ||
238 (!AUTH_MARSHALL (h
->cl_auth
, xdrs
)) ||
239 (!(*xdr_args
) (xdrs
, args_ptr
)))
241 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
242 ct
->ct_error
.re_status
= RPC_CANTENCODEARGS
;
243 (void) xdrrec_endofrecord (xdrs
, TRUE
);
244 return ct
->ct_error
.re_status
;
246 if (!xdrrec_endofrecord (xdrs
, shipnow
))
247 return ct
->ct_error
.re_status
= RPC_CANTSEND
;
251 * Hack to provide rpc-based message passing
253 if (ct
->ct_wait
.tv_sec
== 0 && ct
->ct_wait
.tv_usec
== 0)
254 return ct
->ct_error
.re_status
= RPC_TIMEDOUT
;
258 * Keep receiving until we get a valid transaction id
260 xdrs
->x_op
= XDR_DECODE
;
263 reply_msg
.acpted_rply
.ar_verf
= _null_auth
;
264 reply_msg
.acpted_rply
.ar_results
.where
= NULL
;
265 reply_msg
.acpted_rply
.ar_results
.proc
= (xdrproc_t
)xdr_void
;
266 if (!xdrrec_skiprecord (xdrs
))
267 return ct
->ct_error
.re_status
;
268 /* now decode and validate the response header */
269 if (!xdr_replymsg (xdrs
, &reply_msg
))
271 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
273 return ct
->ct_error
.re_status
;
275 if (reply_msg
.rm_xid
== x_id
)
282 _seterr_reply (&reply_msg
, &(ct
->ct_error
));
283 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
285 if (!AUTH_VALIDATE (h
->cl_auth
, &reply_msg
.acpted_rply
.ar_verf
))
287 ct
->ct_error
.re_status
= RPC_AUTHERROR
;
288 ct
->ct_error
.re_why
= AUTH_INVALIDRESP
;
290 else if (!(*xdr_results
) (xdrs
, results_ptr
))
292 if (ct
->ct_error
.re_status
== RPC_SUCCESS
)
293 ct
->ct_error
.re_status
= RPC_CANTDECODERES
;
295 /* free verifier ... */
296 if (reply_msg
.acpted_rply
.ar_verf
.oa_base
!= NULL
)
298 xdrs
->x_op
= XDR_FREE
;
299 (void) xdr_opaque_auth (xdrs
, &(reply_msg
.acpted_rply
.ar_verf
));
301 } /* end successful completion */
304 /* maybe our credentials need to be refreshed ... */
305 if (refreshes
-- && AUTH_REFRESH (h
->cl_auth
))
307 } /* end of unsuccessful completion */
308 return ct
->ct_error
.re_status
;
312 clntunix_geterr (CLIENT
*h
, struct rpc_err
*errp
)
314 struct ct_data
*ct
= (struct ct_data
*) h
->cl_private
;
316 *errp
= ct
->ct_error
;
320 clntunix_freeres (cl
, xdr_res
, res_ptr
)
325 struct ct_data
*ct
= (struct ct_data
*) cl
->cl_private
;
326 XDR
*xdrs
= &(ct
->ct_xdrs
);
328 xdrs
->x_op
= XDR_FREE
;
329 return (*xdr_res
) (xdrs
, res_ptr
);
338 clntunix_control (CLIENT
*cl
, int request
, char *info
)
340 struct ct_data
*ct
= (struct ct_data
*) cl
->cl_private
;
346 ct
->ct_closeit
= TRUE
;
348 case CLSET_FD_NCLOSE
:
349 ct
->ct_closeit
= FALSE
;
352 ct
->ct_wait
= *(struct timeval
*) info
;
355 *(struct timeval
*) info
= ct
->ct_wait
;
357 case CLGET_SERVER_ADDR
:
358 *(struct sockaddr_un
*) info
= ct
->ct_addr
;
361 *(int *)info
= ct
->ct_sock
;
365 * use the knowledge that xid is the
366 * first element in the call structure *.
367 * This will get the xid of the PREVIOUS call
369 *(u_long
*) info
= ntohl (*(u_long
*)ct
->ct_mcall
);
372 /* This will set the xid of the NEXT call */
373 *(u_long
*) ct
->ct_mcall
= htonl (*(u_long
*)info
- 1);
374 /* decrement by 1 as clntunix_call() increments once */
378 * This RELIES on the information that, in the call body,
379 * the version number field is the fifth field from the
380 * begining of the RPC header. MUST be changed if the
381 * call_struct is changed
383 *(u_long
*) info
= ntohl (*(u_long
*) (ct
->ct_mcall
384 + 4 * BYTES_PER_XDR_UNIT
));
387 *(u_long
*) (ct
->ct_mcall
+ 4 * BYTES_PER_XDR_UNIT
)
388 = htonl (*(u_long
*) info
);
392 * This RELIES on the information that, in the call body,
393 * the program number field is the field from the
394 * begining of the RPC header. MUST be changed if the
395 * call_struct is changed
397 *(u_long
*) info
= ntohl (*(u_long
*) (ct
->ct_mcall
398 + 3 * BYTES_PER_XDR_UNIT
));
401 *(u_long
*) (ct
->ct_mcall
+ 3 * BYTES_PER_XDR_UNIT
)
402 = htonl(*(u_long
*) info
);
404 /* The following are only possible with TI-RPC */
405 case CLGET_RETRY_TIMEOUT
:
406 case CLSET_RETRY_TIMEOUT
:
409 case CLSET_PUSH_TIMOD
:
410 case CLSET_POP_TIMOD
:
419 clntunix_destroy (CLIENT
*h
)
422 (struct ct_data
*) h
->cl_private
;
426 (void) __close (ct
->ct_sock
);
428 XDR_DESTROY (&(ct
->ct_xdrs
));
429 mem_free ((caddr_t
) ct
, sizeof (struct ct_data
));
430 mem_free ((caddr_t
) h
, sizeof (CLIENT
));
434 __msgread (int sock
, void *data
, size_t cnt
)
438 #ifdef SCM_CREDENTIALS
439 static char cm
[CMSG_SPACE(sizeof (struct ucred
))];
450 #ifdef SCM_CREDENTIALS
451 msg
.msg_control
= (caddr_t
) &cm
;
452 msg
.msg_controllen
= CMSG_SPACE(sizeof (struct ucred
));
459 if (__setsockopt (sock
, SOL_SOCKET
, SO_PASSCRED
, &on
, sizeof (on
)))
465 len
= __recvmsg (sock
, &msg
, 0);
468 if (msg
.msg_flags
& MSG_CTRUNC
|| len
== 0)
479 __msgwrite (int sock
, void *data
, size_t cnt
)
481 #ifndef SCM_CREDENTIALS
482 /* We cannot implement this reliably. */
483 __set_errno (ENOSYS
);
488 struct cmsghdr
*cmsg
= alloca (CMSG_SPACE(sizeof (struct ucred
)));
492 /* XXX I'm not sure, if gete?id() is always correct, or if we should use
493 get?id(). But since keyserv needs geteuid(), we have no other chance.
494 It would be much better, if the kernel could pass both to the server. */
495 cred
.pid
= __getpid ();
496 cred
.uid
= __geteuid ();
497 cred
.gid
= __getegid ();
499 memcpy (CMSG_DATA(cmsg
), &cred
, sizeof (struct ucred
));
500 cmsg
->cmsg_level
= SOL_SOCKET
;
501 cmsg
->cmsg_type
= SCM_CREDENTIALS
;
502 cmsg
->cmsg_len
= sizeof(*cmsg
) + sizeof(struct ucred
);
511 msg
.msg_control
= cmsg
;
512 msg
.msg_controllen
= CMSG_ALIGN(cmsg
->cmsg_len
);
516 len
= __sendmsg (sock
, &msg
, 0);
528 * Interface between xdr serializer and unix connection.
529 * Behaves like the system calls, read & write, but keeps some error state
530 * around for the rpc level.
533 readunix (char *ctptr
, char *buf
, int len
)
535 struct ct_data
*ct
= (struct ct_data
*) ctptr
;
537 int milliseconds
= ((ct
->ct_wait
.tv_sec
* 1000)
538 + (ct
->ct_wait
.tv_usec
/ 1000));
547 switch (__poll (&fd
, 1, milliseconds
))
550 ct
->ct_error
.re_status
= RPC_TIMEDOUT
;
556 ct
->ct_error
.re_status
= RPC_CANTRECV
;
557 ct
->ct_error
.re_errno
= errno
;
562 switch (len
= __msgread (ct
->ct_sock
, buf
, len
))
567 ct
->ct_error
.re_errno
= ECONNRESET
;
568 ct
->ct_error
.re_status
= RPC_CANTRECV
;
569 len
= -1; /* it's really an error */
573 ct
->ct_error
.re_errno
= errno
;
574 ct
->ct_error
.re_status
= RPC_CANTRECV
;
581 writeunix (char *ctptr
, char *buf
, int len
)
584 struct ct_data
*ct
= (struct ct_data
*) ctptr
;
586 for (cnt
= len
; cnt
> 0; cnt
-= i
, buf
+= i
)
588 if ((i
= __msgwrite (ct
->ct_sock
, buf
, cnt
)) == -1)
590 ct
->ct_error
.re_errno
= errno
;
591 ct
->ct_error
.re_status
= RPC_CANTSEND
;