fdwalk should return 0 on an empty directory
[kopensolaris-gnu/glibc.git] / sunrpc / clnt_unix.c
1 /*
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.
8  *
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.
12  *
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.
16  *
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.
20  *
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.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  */
29
30 /*
31  * clnt_unix.c, Implements a TCP/IP based, client side RPC.
32  *
33  * Copyright (C) 1984, Sun Microsystems, Inc.
34  *
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).
40  *
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....
45  *
46  * Now go hang yourself.
47  */
48
49 #include <netdb.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <unistd.h>
53 #include <libintl.h>
54 #include <rpc/rpc.h>
55 #include <sys/uio.h>
56 #include <sys/poll.h>
57 #include <sys/socket.h>
58 #include <rpc/pmap_clnt.h>
59 #ifdef USE_IN_LIBIO
60 # include <wchar.h>
61 #endif
62
63 extern u_long _create_xid (void);
64
65 #define MCALL_MSG_SIZE 24
66
67 struct ct_data
68   {
69     int ct_sock;
70     bool_t ct_closeit;
71     struct timeval ct_wait;
72     bool_t ct_waitset;          /* wait set by clnt_control? */
73     struct sockaddr_un ct_addr;
74     struct rpc_err ct_error;
75     char ct_mcall[MCALL_MSG_SIZE];      /* marshalled callmsg */
76     u_int ct_mpos;              /* pos after marshal */
77     XDR ct_xdrs;
78   };
79
80 static int readunix (char *, char *, int);
81 static int writeunix (char *, char *, int);
82
83 static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t,
84                                     xdrproc_t, caddr_t, struct timeval);
85 static void clntunix_abort (void);
86 static void clntunix_geterr (CLIENT *, struct rpc_err *);
87 static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t);
88 static bool_t clntunix_control (CLIENT *, int, char *);
89 static void clntunix_destroy (CLIENT *);
90
91 static const struct clnt_ops unix_ops =
92 {
93   clntunix_call,
94   clntunix_abort,
95   clntunix_geterr,
96   clntunix_freeres,
97   clntunix_destroy,
98   clntunix_control
99 };
100
101 /*
102  * Create a client handle for a tcp/ip connection.
103  * If *sockp<0, *sockp is set to a newly created TCP socket and it is
104  * connected to raddr.  If *sockp non-negative then
105  * raddr is ignored.  The rpc/tcp package does buffering
106  * similar to stdio, so the client must pick send and receive buffer sizes,];
107  * 0 => use the default.
108  * If raddr->sin_port is 0, then a binder on the remote machine is
109  * consulted for the right port number.
110  * NB: *sockp is copied into a private area.
111  * NB: It is the clients responsibility to close *sockp.
112  * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
113  * something more useful.
114  */
115 CLIENT *
116 clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
117                  int *sockp, u_int sendsz, u_int recvsz)
118 {
119   CLIENT *h;
120   struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
121   struct rpc_msg call_msg;
122   int len;
123
124   h = (CLIENT *) mem_alloc (sizeof (*h));
125   if (h == NULL || ct == NULL)
126     {
127       struct rpc_createerr *ce = &get_rpc_createerr ();
128       (void) __fxprintf (NULL, "%s", _("clntunix_create: out of memory\n"));
129       ce->cf_stat = RPC_SYSTEMERROR;
130       ce->cf_error.re_errno = ENOMEM;
131       goto fooy;
132     }
133
134   /*
135    * If no socket given, open one
136    */
137   if (*sockp < 0)
138     {
139       *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
140       len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
141       if (*sockp < 0
142           || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
143         {
144           struct rpc_createerr *ce = &get_rpc_createerr ();
145           ce->cf_stat = RPC_SYSTEMERROR;
146           ce->cf_error.re_errno = errno;
147           if (*sockp != -1)
148             __close (*sockp);
149           goto fooy;
150         }
151       ct->ct_closeit = TRUE;
152     }
153   else
154     {
155       ct->ct_closeit = FALSE;
156     }
157
158   /*
159    * Set up private data struct
160    */
161   ct->ct_sock = *sockp;
162   ct->ct_wait.tv_usec = 0;
163   ct->ct_waitset = FALSE;
164   ct->ct_addr = *raddr;
165
166   /*
167    * Initialize call message
168    */
169   call_msg.rm_xid = _create_xid ();
170   call_msg.rm_direction = CALL;
171   call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
172   call_msg.rm_call.cb_prog = prog;
173   call_msg.rm_call.cb_vers = vers;
174
175   /*
176    * pre-serialize the static part of the call msg and stash it away
177    */
178   INTUSE(xdrmem_create) (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
179                          XDR_ENCODE);
180   if (!INTUSE(xdr_callhdr) (&(ct->ct_xdrs), &call_msg))
181     {
182       if (ct->ct_closeit)
183         __close (*sockp);
184       goto fooy;
185     }
186   ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
187   XDR_DESTROY (&(ct->ct_xdrs));
188
189   /*
190    * Create a client handle which uses xdrrec for serialization
191    * and authnone for authentication.
192    */
193   INTUSE(xdrrec_create) (&(ct->ct_xdrs), sendsz, recvsz,
194                          (caddr_t) ct, readunix, writeunix);
195   h->cl_ops = (struct clnt_ops *) &unix_ops;
196   h->cl_private = (caddr_t) ct;
197   h->cl_auth = INTUSE(authnone_create) ();
198   return h;
199
200 fooy:
201   /*
202    * Something goofed, free stuff and barf
203    */
204   mem_free ((caddr_t) ct, sizeof (struct ct_data));
205   mem_free ((caddr_t) h, sizeof (CLIENT));
206   return (CLIENT *) NULL;
207 }
208 INTDEF (clntunix_create)
209
210 static enum clnt_stat
211 clntunix_call (h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
212      CLIENT *h;
213      u_long proc;
214      xdrproc_t xdr_args;
215      caddr_t args_ptr;
216      xdrproc_t xdr_results;
217      caddr_t results_ptr;
218      struct timeval timeout;
219 {
220   struct ct_data *ct = (struct ct_data *) h->cl_private;
221   XDR *xdrs = &(ct->ct_xdrs);
222   struct rpc_msg reply_msg;
223   u_long x_id;
224   u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall);   /* yuk */
225   bool_t shipnow;
226   int refreshes = 2;
227
228   if (!ct->ct_waitset)
229     {
230       ct->ct_wait = timeout;
231     }
232
233   shipnow =
234     (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
235      && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
236
237 call_again:
238   xdrs->x_op = XDR_ENCODE;
239   ct->ct_error.re_status = RPC_SUCCESS;
240   x_id = ntohl (--(*msg_x_id));
241   if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) ||
242       (!XDR_PUTLONG (xdrs, (long *) &proc)) ||
243       (!AUTH_MARSHALL (h->cl_auth, xdrs)) ||
244       (!(*xdr_args) (xdrs, args_ptr)))
245     {
246       if (ct->ct_error.re_status == RPC_SUCCESS)
247         ct->ct_error.re_status = RPC_CANTENCODEARGS;
248       (void) INTUSE(xdrrec_endofrecord) (xdrs, TRUE);
249       return ct->ct_error.re_status;
250     }
251   if (!INTUSE(xdrrec_endofrecord) (xdrs, shipnow))
252     return ct->ct_error.re_status = RPC_CANTSEND;
253   if (!shipnow)
254     return RPC_SUCCESS;
255   /*
256    * Hack to provide rpc-based message passing
257    */
258   if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
259     return ct->ct_error.re_status = RPC_TIMEDOUT;
260
261
262   /*
263    * Keep receiving until we get a valid transaction id
264    */
265   xdrs->x_op = XDR_DECODE;
266   while (TRUE)
267     {
268       reply_msg.acpted_rply.ar_verf = _null_auth;
269       reply_msg.acpted_rply.ar_results.where = NULL;
270       reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)INTUSE(xdr_void);
271       if (!INTUSE(xdrrec_skiprecord) (xdrs))
272         return ct->ct_error.re_status;
273       /* now decode and validate the response header */
274       if (!INTUSE(xdr_replymsg) (xdrs, &reply_msg))
275         {
276           if (ct->ct_error.re_status == RPC_SUCCESS)
277             continue;
278           return ct->ct_error.re_status;
279         }
280       if (reply_msg.rm_xid == x_id)
281         break;
282     }
283
284   /*
285    * process header
286    */
287   _seterr_reply (&reply_msg, &(ct->ct_error));
288   if (ct->ct_error.re_status == RPC_SUCCESS)
289     {
290       if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
291         {
292           ct->ct_error.re_status = RPC_AUTHERROR;
293           ct->ct_error.re_why = AUTH_INVALIDRESP;
294         }
295       else if (!(*xdr_results) (xdrs, results_ptr))
296         {
297           if (ct->ct_error.re_status == RPC_SUCCESS)
298             ct->ct_error.re_status = RPC_CANTDECODERES;
299         }
300       /* free verifier ... */
301       if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
302         {
303           xdrs->x_op = XDR_FREE;
304           (void) INTUSE(xdr_opaque_auth) (xdrs,
305                                           &(reply_msg.acpted_rply.ar_verf));
306         }
307     }                           /* end successful completion */
308   else
309     {
310       /* maybe our credentials need to be refreshed ... */
311       if (refreshes-- && AUTH_REFRESH (h->cl_auth))
312         goto call_again;
313     }                           /* end of unsuccessful completion */
314   return ct->ct_error.re_status;
315 }
316
317 static void
318 clntunix_geterr (CLIENT *h, struct rpc_err *errp)
319 {
320   struct ct_data *ct = (struct ct_data *) h->cl_private;
321
322   *errp = ct->ct_error;
323 }
324
325 static bool_t
326 clntunix_freeres (cl, xdr_res, res_ptr)
327      CLIENT *cl;
328      xdrproc_t xdr_res;
329      caddr_t res_ptr;
330 {
331   struct ct_data *ct = (struct ct_data *) cl->cl_private;
332   XDR *xdrs = &(ct->ct_xdrs);
333
334   xdrs->x_op = XDR_FREE;
335   return (*xdr_res) (xdrs, res_ptr);
336 }
337
338 static void
339 clntunix_abort ()
340 {
341 }
342
343 static bool_t
344 clntunix_control (CLIENT *cl, int request, char *info)
345 {
346   struct ct_data *ct = (struct ct_data *) cl->cl_private;
347
348
349   switch (request)
350     {
351     case CLSET_FD_CLOSE:
352       ct->ct_closeit = TRUE;
353       break;
354     case CLSET_FD_NCLOSE:
355       ct->ct_closeit = FALSE;
356       break;
357     case CLSET_TIMEOUT:
358       ct->ct_wait = *(struct timeval *) info;
359       break;
360     case CLGET_TIMEOUT:
361       *(struct timeval *) info = ct->ct_wait;
362       break;
363     case CLGET_SERVER_ADDR:
364       *(struct sockaddr_un *) info = ct->ct_addr;
365       break;
366     case CLGET_FD:
367       *(int *)info = ct->ct_sock;
368       break;
369     case CLGET_XID:
370       /*
371        * use the knowledge that xid is the
372        * first element in the call structure *.
373        * This will get the xid of the PREVIOUS call
374        */
375       *(u_long *) info = ntohl (*(u_long *)ct->ct_mcall);
376       break;
377     case CLSET_XID:
378       /* This will set the xid of the NEXT call */
379       *(u_long *) ct->ct_mcall =  htonl (*(u_long *)info - 1);
380       /* decrement by 1 as clntunix_call() increments once */
381     case CLGET_VERS:
382       /*
383        * This RELIES on the information that, in the call body,
384        * the version number field is the fifth field from the
385        * begining of the RPC header. MUST be changed if the
386        * call_struct is changed
387        */
388       *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
389                                              + 4 * BYTES_PER_XDR_UNIT));
390       break;
391     case CLSET_VERS:
392       *(u_long *) (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT)
393         = htonl (*(u_long *) info);
394       break;
395     case CLGET_PROG:
396       /*
397        * This RELIES on the information that, in the call body,
398        * the program number field is the  field from the
399        * begining of the RPC header. MUST be changed if the
400        * call_struct is changed
401        */
402       *(u_long *) info = ntohl (*(u_long *) (ct->ct_mcall
403                                              + 3 * BYTES_PER_XDR_UNIT));
404       break;
405     case CLSET_PROG:
406       *(u_long *) (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT)
407         = htonl(*(u_long *) info);
408       break;
409     /* The following are only possible with TI-RPC */
410     case CLGET_RETRY_TIMEOUT:
411     case CLSET_RETRY_TIMEOUT:
412     case CLGET_SVC_ADDR:
413     case CLSET_SVC_ADDR:
414     case CLSET_PUSH_TIMOD:
415     case CLSET_POP_TIMOD:
416     default:
417       return FALSE;
418     }
419   return TRUE;
420 }
421
422
423 static void
424 clntunix_destroy (CLIENT *h)
425 {
426   struct ct_data *ct =
427   (struct ct_data *) h->cl_private;
428
429   if (ct->ct_closeit)
430     {
431       (void) __close (ct->ct_sock);
432     }
433   XDR_DESTROY (&(ct->ct_xdrs));
434   mem_free ((caddr_t) ct, sizeof (struct ct_data));
435   mem_free ((caddr_t) h, sizeof (CLIENT));
436 }
437
438 static int
439 __msgread (int sock, void *data, size_t cnt)
440 {
441   struct iovec iov;
442   struct msghdr msg;
443 #ifdef SCM_CREDENTIALS
444   static char cm[CMSG_SPACE(sizeof (struct ucred))];
445 #endif
446   int len;
447
448   iov.iov_base = data;
449   iov.iov_len = cnt;
450
451   msg.msg_iov = &iov;
452   msg.msg_iovlen = 1;
453   msg.msg_name = NULL;
454   msg.msg_namelen = 0;
455 #ifdef SCM_CREDENTIALS
456   msg.msg_control = (caddr_t) &cm;
457   msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
458 #endif
459   msg.msg_flags = 0;
460
461 #ifdef SO_PASSCRED
462   {
463     int on = 1;
464     if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
465       return -1;
466   }
467 #endif
468
469  restart:
470   len = __recvmsg (sock, &msg, 0);
471   if (len >= 0)
472     {
473       if (msg.msg_flags & MSG_CTRUNC || len == 0)
474         return 0;
475       else
476         return len;
477     }
478   if (errno == EINTR)
479     goto restart;
480   return -1;
481 }
482
483 static int
484 __msgwrite (int sock, void *data, size_t cnt)
485 {
486 #ifndef SCM_CREDENTIALS
487   /* We cannot implement this reliably.  */
488   __set_errno (ENOSYS);
489   return -1;
490 #else
491   struct iovec iov;
492   struct msghdr msg;
493   struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
494   struct ucred cred;
495   int len;
496
497   /* XXX I'm not sure, if gete?id() is always correct, or if we should use
498      get?id(). But since keyserv needs geteuid(), we have no other chance.
499      It would be much better, if the kernel could pass both to the server. */
500   cred.pid = __getpid ();
501   cred.uid = __geteuid ();
502   cred.gid = __getegid ();
503
504   memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
505   cmsg->cmsg_level = SOL_SOCKET;
506   cmsg->cmsg_type = SCM_CREDENTIALS;
507   cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
508
509   iov.iov_base = data;
510   iov.iov_len = cnt;
511
512   msg.msg_iov = &iov;
513   msg.msg_iovlen = 1;
514   msg.msg_name = NULL;
515   msg.msg_namelen = 0;
516   msg.msg_control = cmsg;
517   msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
518   msg.msg_flags = 0;
519
520  restart:
521   len = __sendmsg (sock, &msg, 0);
522   if (len >= 0)
523     return len;
524   if (errno == EINTR)
525     goto restart;
526   return -1;
527
528 #endif
529 }
530
531
532 /*
533  * Interface between xdr serializer and unix connection.
534  * Behaves like the system calls, read & write, but keeps some error state
535  * around for the rpc level.
536  */
537 static int
538 readunix (char *ctptr, char *buf, int len)
539 {
540   struct ct_data *ct = (struct ct_data *) ctptr;
541   struct pollfd fd;
542   int milliseconds = ((ct->ct_wait.tv_sec * 1000)
543                       + (ct->ct_wait.tv_usec / 1000));
544
545   if (len == 0)
546     return 0;
547
548   fd.fd = ct->ct_sock;
549   fd.events = POLLIN;
550   while (TRUE)
551     {
552       switch (__poll (&fd, 1, milliseconds))
553         {
554         case 0:
555           ct->ct_error.re_status = RPC_TIMEDOUT;
556           return -1;
557
558         case -1:
559           if (errno == EINTR)
560             continue;
561           ct->ct_error.re_status = RPC_CANTRECV;
562           ct->ct_error.re_errno = errno;
563           return -1;
564         }
565       break;
566     }
567   switch (len = __msgread (ct->ct_sock, buf, len))
568     {
569
570     case 0:
571       /* premature eof */
572       ct->ct_error.re_errno = ECONNRESET;
573       ct->ct_error.re_status = RPC_CANTRECV;
574       len = -1;                 /* it's really an error */
575       break;
576
577     case -1:
578       ct->ct_error.re_errno = errno;
579       ct->ct_error.re_status = RPC_CANTRECV;
580       break;
581     }
582   return len;
583 }
584
585 static int
586 writeunix (char *ctptr, char *buf, int len)
587 {
588   int i, cnt;
589   struct ct_data *ct = (struct ct_data *) ctptr;
590
591   for (cnt = len; cnt > 0; cnt -= i, buf += i)
592     {
593       if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
594         {
595           ct->ct_error.re_errno = errno;
596           ct->ct_error.re_status = RPC_CANTSEND;
597           return -1;
598         }
599     }
600   return len;
601 }