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