Sun agreed to a change of the license for the RPC code to a BSD-like license.
[platform/upstream/glibc.git] / sunrpc / clnt_unix.c
1 /*
2  * clnt_unix.c, Implements a TCP/IP based, client side RPC.
3  *
4  * Copyright (C) 1984, Sun Microsystems, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *
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.
19  *
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.
32  *
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).
38  *
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....
43  *
44  * Now go hang yourself.
45  */
46
47 #include <netdb.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <libintl.h>
52 #include <rpc/rpc.h>
53 #include <sys/uio.h>
54 #include <sys/poll.h>
55 #include <sys/socket.h>
56 #include <rpc/pmap_clnt.h>
57 #ifdef USE_IN_LIBIO
58 # include <wchar.h>
59 #endif
60
61 extern u_long _create_xid (void);
62
63 #define MCALL_MSG_SIZE 24
64
65 struct ct_data
66   {
67     int ct_sock;
68     bool_t ct_closeit;
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 */
75     XDR ct_xdrs;
76   };
77
78 static int readunix (char *, char *, int);
79 static int writeunix (char *, char *, int);
80
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 *);
88
89 static const struct clnt_ops unix_ops =
90 {
91   clntunix_call,
92   clntunix_abort,
93   clntunix_geterr,
94   clntunix_freeres,
95   clntunix_destroy,
96   clntunix_control
97 };
98
99 /*
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.
112  */
113 CLIENT *
114 clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
115                  int *sockp, u_int sendsz, u_int recvsz)
116 {
117   CLIENT *h;
118   struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
119   struct rpc_msg call_msg;
120   int len;
121
122   h = (CLIENT *) mem_alloc (sizeof (*h));
123   if (h == NULL || ct == NULL)
124     {
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;
129       goto fooy;
130     }
131
132   /*
133    * If no socket given, open one
134    */
135   if (*sockp < 0)
136     {
137       *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
138       len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
139       if (*sockp < 0
140           || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
141         {
142           struct rpc_createerr *ce = &get_rpc_createerr ();
143           ce->cf_stat = RPC_SYSTEMERROR;
144           ce->cf_error.re_errno = errno;
145           if (*sockp != -1)
146             __close (*sockp);
147           goto fooy;
148         }
149       ct->ct_closeit = TRUE;
150     }
151   else
152     {
153       ct->ct_closeit = FALSE;
154     }
155
156   /*
157    * Set up private data struct
158    */
159   ct->ct_sock = *sockp;
160   ct->ct_wait.tv_usec = 0;
161   ct->ct_waitset = FALSE;
162   ct->ct_addr = *raddr;
163
164   /*
165    * Initialize call message
166    */
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;
172
173   /*
174    * pre-serialize the static part of the call msg and stash it away
175    */
176   INTUSE(xdrmem_create) (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
177                          XDR_ENCODE);
178   if (!INTUSE(xdr_callhdr) (&(ct->ct_xdrs), &call_msg))
179     {
180       if (ct->ct_closeit)
181         __close (*sockp);
182       goto fooy;
183     }
184   ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
185   XDR_DESTROY (&(ct->ct_xdrs));
186
187   /*
188    * Create a client handle which uses xdrrec for serialization
189    * and authnone for authentication.
190    */
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) ();
196   return h;
197
198 fooy:
199   /*
200    * Something goofed, free stuff and barf
201    */
202   mem_free ((caddr_t) ct, sizeof (struct ct_data));
203   mem_free ((caddr_t) h, sizeof (CLIENT));
204   return (CLIENT *) NULL;
205 }
206 INTDEF (clntunix_create)
207
208 static enum clnt_stat
209 clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
210      CLIENT *h;
211      u_long proc;
212      xdrproc_t xdr_args;
213      caddr_t args_ptr;
214      xdrproc_t xdr_results;
215      caddr_t results_ptr;
216      struct timeval timeout;
217 {
218   struct ct_data *ct = (struct ct_data *) h->cl_private;
219   XDR *xdrs = &(ct->ct_xdrs);
220   struct rpc_msg reply_msg;
221   u_long x_id;
222   u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall);   /* yuk */
223   bool_t shipnow;
224   int refreshes = 2;
225
226   if (!ct->ct_waitset)
227     {
228       ct->ct_wait = timeout;
229     }
230
231   shipnow =
232     (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
233      && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
234
235 call_again:
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)))
243     {
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;
248     }
249   if (!INTUSE(xdrrec_endofrecord) (xdrs, shipnow))
250     return ct->ct_error.re_status = RPC_CANTSEND;
251   if (!shipnow)
252     return RPC_SUCCESS;
253   /*
254    * Hack to provide rpc-based message passing
255    */
256   if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
257     return ct->ct_error.re_status = RPC_TIMEDOUT;
258
259
260   /*
261    * Keep receiving until we get a valid transaction id
262    */
263   xdrs->x_op = XDR_DECODE;
264   while (TRUE)
265     {
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))
273         {
274           if (ct->ct_error.re_status == RPC_SUCCESS)
275             continue;
276           return ct->ct_error.re_status;
277         }
278       if (reply_msg.rm_xid == x_id)
279         break;
280     }
281
282   /*
283    * process header
284    */
285   _seterr_reply (&reply_msg, &(ct->ct_error));
286   if (ct->ct_error.re_status == RPC_SUCCESS)
287     {
288       if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
289         {
290           ct->ct_error.re_status = RPC_AUTHERROR;
291           ct->ct_error.re_why = AUTH_INVALIDRESP;
292         }
293       else if (!(*xdr_results) (xdrs, results_ptr))
294         {
295           if (ct->ct_error.re_status == RPC_SUCCESS)
296             ct->ct_error.re_status = RPC_CANTDECODERES;
297         }
298       /* free verifier ... */
299       if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
300         {
301           xdrs->x_op = XDR_FREE;
302           (void) INTUSE(xdr_opaque_auth) (xdrs,
303                                           &(reply_msg.acpted_rply.ar_verf));
304         }
305     }                           /* end successful completion */
306   else
307     {
308       /* maybe our credentials need to be refreshed ... */
309       if (refreshes-- && AUTH_REFRESH (h->cl_auth))
310         goto call_again;
311     }                           /* end of unsuccessful completion */
312   return ct->ct_error.re_status;
313 }
314
315 static void
316 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
317 {
318   struct ct_data *ct = (struct ct_data *) h->cl_private;
319
320   *errp = ct->ct_error;
321 }
322
323 static bool_t
324 clntunix_freeres (cl, xdr_res, res_ptr)
325      CLIENT *cl;
326      xdrproc_t xdr_res;
327      caddr_t res_ptr;
328 {
329   struct ct_data *ct = (struct ct_data *) cl->cl_private;
330   XDR *xdrs = &(ct->ct_xdrs);
331
332   xdrs->x_op = XDR_FREE;
333   return (*xdr_res) (xdrs, res_ptr);
334 }
335
336 static void
337 clntunix_abort ()
338 {
339 }
340
341 static bool_t
342 clntunix_control (CLIENT *cl, int request, char *info)
343 {
344   struct ct_data *ct = (struct ct_data *) cl->cl_private;
345
346
347   switch (request)
348     {
349     case CLSET_FD_CLOSE:
350       ct->ct_closeit = TRUE;
351       break;
352     case CLSET_FD_NCLOSE:
353       ct->ct_closeit = FALSE;
354       break;
355     case CLSET_TIMEOUT:
356       ct->ct_wait = *(struct timeval *) info;
357       break;
358     case CLGET_TIMEOUT:
359       *(struct timeval *) info = ct->ct_wait;
360       break;
361     case CLGET_SERVER_ADDR:
362       *(struct sockaddr_un *) info = ct->ct_addr;
363       break;
364     case CLGET_FD:
365       *(int *)info = ct->ct_sock;
366       break;
367     case CLGET_XID:
368       /*
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
372        */
373       *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
374       break;
375     case CLSET_XID:
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 */
379     case CLGET_VERS:
380       /*
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
385        */
386       *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
387                                              + 4 * BYTES_PER_XDR_UNIT));
388       break;
389     case CLSET_VERS:
390       *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
391         = htonl (*(u_long *) info);
392       break;
393     case CLGET_PROG:
394       /*
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
399        */
400       *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
401                                              + 3 * BYTES_PER_XDR_UNIT));
402       break;
403     case CLSET_PROG:
404       *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
405         = htonl(*(u_long *) info);
406       break;
407     /* The following are only possible with TI-RPC */
408     case CLGET_RETRY_TIMEOUT:
409     case CLSET_RETRY_TIMEOUT:
410     case CLGET_SVC_ADDR:
411     case CLSET_SVC_ADDR:
412     case CLSET_PUSH_TIMOD:
413     case CLSET_POP_TIMOD:
414     default:
415       return FALSE;
416     }
417   return TRUE;
418 }
419
420
421 static void
422 clntunix_destroy (CLIENT *h)
423 {
424   struct ct_data *ct =
425   (struct ct_data *) h->cl_private;
426
427   if (ct->ct_closeit)
428     {
429       (void) __close (ct->ct_sock);
430     }
431   XDR_DESTROY (&(ct->ct_xdrs));
432   mem_free ((caddr_t) ct, sizeof (struct ct_data));
433   mem_free ((caddr_t) h, sizeof (CLIENT));
434 }
435
436 static int
437 __msgread (int sock, void *data, size_t cnt)
438 {
439   struct iovec iov;
440   struct msghdr msg;
441 #ifdef SCM_CREDENTIALS
442   static char cm[CMSG_SPACE(sizeof (struct ucred))];
443 #endif
444   int len;
445
446   iov.iov_base = data;
447   iov.iov_len = cnt;
448
449   msg.msg_iov = &iov;
450   msg.msg_iovlen = 1;
451   msg.msg_name = NULL;
452   msg.msg_namelen = 0;
453 #ifdef SCM_CREDENTIALS
454   msg.msg_control = (caddr_t) &cm;
455   msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
456 #endif
457   msg.msg_flags = 0;
458
459 #ifdef SO_PASSCRED
460   {
461     int on = 1;
462     if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
463       return -1;
464   }
465 #endif
466
467  restart:
468   len = __recvmsg (sock, &msg, 0);
469   if (len >= 0)
470     {
471       if (msg.msg_flags & MSG_CTRUNC || len == 0)
472         return 0;
473       else
474         return len;
475     }
476   if (errno == EINTR)
477     goto restart;
478   return -1;
479 }
480
481 static int
482 __msgwrite (int sock, void *data, size_t cnt)
483 {
484 #ifndef SCM_CREDENTIALS
485   /* We cannot implement this reliably.  */
486   __set_errno (ENOSYS);
487   return -1;
488 #else
489   struct iovec iov;
490   struct msghdr msg;
491   struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
492   struct ucred cred;
493   int len;
494
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 ();
501
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);
506
507   iov.iov_base = data;
508   iov.iov_len = cnt;
509
510   msg.msg_iov = &iov;
511   msg.msg_iovlen = 1;
512   msg.msg_name = NULL;
513   msg.msg_namelen = 0;
514   msg.msg_control = cmsg;
515   msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
516   msg.msg_flags = 0;
517
518  restart:
519   len = __sendmsg (sock, &msg, 0);
520   if (len >= 0)
521     return len;
522   if (errno == EINTR)
523     goto restart;
524   return -1;
525
526 #endif
527 }
528
529
530 /*
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.
534  */
535 static int
536 readunix (char *ctptr, char *buf, int len)
537 {
538   struct ct_data *ct = (struct ct_data *) ctptr;
539   struct pollfd fd;
540   int milliseconds = ((ct->ct_wait.tv_sec * 1000)
541                       + (ct->ct_wait.tv_usec / 1000));
542
543   if (len == 0)
544     return 0;
545
546   fd.fd = ct->ct_sock;
547   fd.events = POLLIN;
548   while (TRUE)
549     {
550       switch (__poll (&fd, 1, milliseconds))
551         {
552         case 0:
553           ct->ct_error.re_status = RPC_TIMEDOUT;
554           return -1;
555
556         case -1:
557           if (errno == EINTR)
558             continue;
559           ct->ct_error.re_status = RPC_CANTRECV;
560           ct->ct_error.re_errno = errno;
561           return -1;
562         }
563       break;
564     }
565   switch (len = __msgread (ct->ct_sock, buf, len))
566     {
567
568     case 0:
569       /* premature eof */
570       ct->ct_error.re_errno = ECONNRESET;
571       ct->ct_error.re_status = RPC_CANTRECV;
572       len = -1;                 /* it's really an error */
573       break;
574
575     case -1:
576       ct->ct_error.re_errno = errno;
577       ct->ct_error.re_status = RPC_CANTRECV;
578       break;
579     }
580   return len;
581 }
582
583 static int
584 writeunix (char *ctptr, char *buf, int len)
585 {
586   int i, cnt;
587   struct ct_data *ct = (struct ct_data *) ctptr;
588
589   for (cnt = len; cnt > 0; cnt -= i, buf += i)
590     {
591       if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
592         {
593           ct->ct_error.re_errno = errno;
594           ct->ct_error.re_status = RPC_CANTSEND;
595           return -1;
596         }
597     }
598   return len;
599 }