(root)/
glibc-2.38/
sunrpc/
clnt_unix.c
       1  /*
       2   * clnt_unix.c, Implements a TCP/IP based, client side RPC.
       3   *
       4   * Copyright (c) 2010, Oracle America, 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 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.
      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  #include <wchar.h>
      58  #include <shlib-compat.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 const 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 || ct == NULL)
     123      {
     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;
     128        goto fooy;
     129      }
     130  
     131    /*
     132     * If no socket given, open one
     133     */
     134    if (*sockp < 0)
     135      {
     136        *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
     137        len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
     138        if (*sockp < 0
     139  	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
     140  	{
     141  	  struct rpc_createerr *ce = &get_rpc_createerr ();
     142  	  ce->cf_stat = RPC_SYSTEMERROR;
     143  	  ce->cf_error.re_errno = errno;
     144  	  if (*sockp != -1)
     145  	    __close (*sockp);
     146  	  goto fooy;
     147  	}
     148        ct->ct_closeit = TRUE;
     149      }
     150    else
     151      {
     152        ct->ct_closeit = FALSE;
     153      }
     154  
     155    /*
     156     * Set up private data struct
     157     */
     158    ct->ct_sock = *sockp;
     159    ct->ct_wait.tv_usec = 0;
     160    ct->ct_waitset = FALSE;
     161    ct->ct_addr = *raddr;
     162  
     163    /*
     164     * Initialize call message
     165     */
     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;
     171  
     172    /*
     173     * pre-serialize the static part of the call msg and stash it away
     174     */
     175    xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
     176    if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
     177      {
     178        if (ct->ct_closeit)
     179  	__close (*sockp);
     180        goto fooy;
     181      }
     182    ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
     183    XDR_DESTROY (&(ct->ct_xdrs));
     184  
     185    /*
     186     * Create a client handle which uses xdrrec for serialization
     187     * and authnone for authentication.
     188     */
     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 ();
     194    return h;
     195  
     196  fooy:
     197    /*
     198     * Something goofed, free stuff and barf
     199     */
     200    mem_free ((caddr_t) ct, sizeof (struct ct_data));
     201    mem_free ((caddr_t) h, sizeof (CLIENT));
     202    return (CLIENT *) NULL;
     203  }
     204  libc_hidden_nolink_sunrpc (clntunix_create, GLIBC_2_1)
     205  
     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)
     210  {
     211    struct ct_data *ct = (struct ct_data *) h->cl_private;
     212    XDR *xdrs = &(ct->ct_xdrs);
     213    struct rpc_msg reply_msg;
     214    u_long x_id;
     215    uint32_t *msg_x_id = (uint32_t *) (ct->ct_mcall);	/* yuk */
     216    bool_t shipnow;
     217    int refreshes = 2;
     218  
     219    if (!ct->ct_waitset)
     220      {
     221        ct->ct_wait = timeout;
     222      }
     223  
     224    shipnow =
     225      (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0
     226       && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE;
     227  
     228  call_again:
     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)))
     236      {
     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;
     241      }
     242    if (!xdrrec_endofrecord (xdrs, shipnow))
     243      return ct->ct_error.re_status = RPC_CANTSEND;
     244    if (!shipnow)
     245      return RPC_SUCCESS;
     246    /*
     247     * Hack to provide rpc-based message passing
     248     */
     249    if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.tv_usec == 0)
     250      return ct->ct_error.re_status = RPC_TIMEDOUT;
     251  
     252  
     253    /*
     254     * Keep receiving until we get a valid transaction id
     255     */
     256    xdrs->x_op = XDR_DECODE;
     257    while (TRUE)
     258      {
     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))
     266  	{
     267  	  if (ct->ct_error.re_status == RPC_SUCCESS)
     268  	    continue;
     269  	  return ct->ct_error.re_status;
     270  	}
     271        if (reply_msg.rm_xid == x_id)
     272  	break;
     273      }
     274  
     275    /*
     276     * process header
     277     */
     278    _seterr_reply (&reply_msg, &(ct->ct_error));
     279    if (ct->ct_error.re_status == RPC_SUCCESS)
     280      {
     281        if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf))
     282  	{
     283  	  ct->ct_error.re_status = RPC_AUTHERROR;
     284  	  ct->ct_error.re_why = AUTH_INVALIDRESP;
     285  	}
     286        else if (!(*xdr_results) (xdrs, results_ptr))
     287  	{
     288  	  if (ct->ct_error.re_status == RPC_SUCCESS)
     289  	    ct->ct_error.re_status = RPC_CANTDECODERES;
     290  	}
     291        /* free verifier ... */
     292        if (reply_msg.acpted_rply.ar_verf.oa_base != NULL)
     293  	{
     294  	  xdrs->x_op = XDR_FREE;
     295  	  (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf));
     296  	}
     297      }				/* end successful completion */
     298    else
     299      {
     300        /* maybe our credentials need to be refreshed ... */
     301        if (refreshes-- && AUTH_REFRESH (h->cl_auth))
     302  	goto call_again;
     303      }				/* end of unsuccessful completion */
     304    return ct->ct_error.re_status;
     305  }
     306  
     307  static void
     308  clntunix_geterr (CLIENT *h, struct rpc_err *errp)
     309  {
     310    struct ct_data *ct = (struct ct_data *) h->cl_private;
     311  
     312    *errp = ct->ct_error;
     313  }
     314  
     315  static bool_t
     316  clntunix_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr)
     317  {
     318    struct ct_data *ct = (struct ct_data *) cl->cl_private;
     319    XDR *xdrs = &(ct->ct_xdrs);
     320  
     321    xdrs->x_op = XDR_FREE;
     322    return (*xdr_res) (xdrs, res_ptr);
     323  }
     324  
     325  static void
     326  clntunix_abort (void)
     327  {
     328  }
     329  
     330  static bool_t
     331  clntunix_control (CLIENT *cl, int request, char *info)
     332  {
     333    struct ct_data *ct = (struct ct_data *) cl->cl_private;
     334    u_long ul;
     335    uint32_t ui32;
     336  
     337    switch (request)
     338      {
     339      case CLSET_FD_CLOSE:
     340        ct->ct_closeit = TRUE;
     341        break;
     342      case CLSET_FD_NCLOSE:
     343        ct->ct_closeit = FALSE;
     344        break;
     345      case CLSET_TIMEOUT:
     346        ct->ct_wait = *(struct timeval *) info;
     347        break;
     348      case CLGET_TIMEOUT:
     349        *(struct timeval *) info = ct->ct_wait;
     350        break;
     351      case CLGET_SERVER_ADDR:
     352        *(struct sockaddr_un *) info = ct->ct_addr;
     353        break;
     354      case CLGET_FD:
     355        *(int *)info = ct->ct_sock;
     356        break;
     357      case CLGET_XID:
     358        /*
     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
     362         */
     363        memcpy (&ui32, ct->ct_mcall, sizeof (ui32));
     364        ul = ntohl (ui32);
     365        memcpy (info, &ul, sizeof (ul));
     366        break;
     367      case CLSET_XID:
     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 */
     373        break;
     374      case CLGET_VERS:
     375        /*
     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
     380         */
     381        memcpy (&ui32, ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, sizeof (ui32));
     382        ul = ntohl (ui32);
     383        memcpy (info, &ul, sizeof (ul));
     384        break;
     385      case CLSET_VERS:
     386        memcpy (&ul, info, sizeof (ul));
     387        ui32 = htonl (ul);
     388        memcpy (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32));
     389        break;
     390      case CLGET_PROG:
     391        /*
     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
     396         */
     397        memcpy (&ui32, ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, sizeof (ui32));
     398        ul = ntohl (ui32);
     399        memcpy (info, &ul, sizeof (ul));
     400        break;
     401      case CLSET_PROG:
     402        memcpy (&ul, info, sizeof (ul));
     403        ui32 = htonl (ul);
     404        memcpy (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32));
     405        break;
     406      /* The following are only possible with TI-RPC */
     407      case CLGET_RETRY_TIMEOUT:
     408      case CLSET_RETRY_TIMEOUT:
     409      case CLGET_SVC_ADDR:
     410      case CLSET_SVC_ADDR:
     411      case CLSET_PUSH_TIMOD:
     412      case CLSET_POP_TIMOD:
     413      default:
     414        return FALSE;
     415      }
     416    return TRUE;
     417  }
     418  
     419  
     420  static void
     421  clntunix_destroy (CLIENT *h)
     422  {
     423    struct ct_data *ct =
     424    (struct ct_data *) h->cl_private;
     425  
     426    if (ct->ct_closeit)
     427      {
     428        (void) __close (ct->ct_sock);
     429      }
     430    XDR_DESTROY (&(ct->ct_xdrs));
     431    mem_free ((caddr_t) ct, sizeof (struct ct_data));
     432    mem_free ((caddr_t) h, sizeof (CLIENT));
     433  }
     434  
     435  static int
     436  __msgread (int sock, void *data, size_t cnt)
     437  {
     438    struct iovec iov;
     439    struct msghdr msg;
     440  #ifdef SCM_CREDENTIALS
     441    static char cm[CMSG_SPACE(sizeof (struct ucred))];
     442  #endif
     443    int len;
     444  
     445    iov.iov_base = data;
     446    iov.iov_len = cnt;
     447  
     448    msg.msg_iov = &iov;
     449    msg.msg_iovlen = 1;
     450    msg.msg_name = NULL;
     451    msg.msg_namelen = 0;
     452  #ifdef SCM_CREDENTIALS
     453    msg.msg_control = (caddr_t) &cm;
     454    msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred));
     455  #endif
     456    msg.msg_flags = 0;
     457  
     458  #ifdef SO_PASSCRED
     459    {
     460      int on = 1;
     461      if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
     462        return -1;
     463    }
     464  #endif
     465  
     466   restart:
     467    len = __recvmsg (sock, &msg, 0);
     468    if (len >= 0)
     469      {
     470        if (msg.msg_flags & MSG_CTRUNC || len == 0)
     471  	return 0;
     472        else
     473  	return len;
     474      }
     475    if (errno == EINTR)
     476      goto restart;
     477    return -1;
     478  }
     479  
     480  static int
     481  __msgwrite (int sock, void *data, size_t cnt)
     482  {
     483  #ifndef SCM_CREDENTIALS
     484    /* We cannot implement this reliably.  */
     485    __set_errno (ENOSYS);
     486    return -1;
     487  #else
     488    struct iovec iov;
     489    struct msghdr msg;
     490    struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred)));
     491    struct ucred cred;
     492    int len;
     493  
     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 ();
     500  
     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);
     505  
     506    iov.iov_base = data;
     507    iov.iov_len = cnt;
     508  
     509    msg.msg_iov = &iov;
     510    msg.msg_iovlen = 1;
     511    msg.msg_name = NULL;
     512    msg.msg_namelen = 0;
     513    msg.msg_control = cmsg;
     514    msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
     515    msg.msg_flags = 0;
     516  
     517   restart:
     518    len = __sendmsg (sock, &msg, 0);
     519    if (len >= 0)
     520      return len;
     521    if (errno == EINTR)
     522      goto restart;
     523    return -1;
     524  
     525  #endif
     526  }
     527  
     528  
     529  /*
     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.
     533   */
     534  static int
     535  readunix (char *ctptr, char *buf, int len)
     536  {
     537    struct ct_data *ct = (struct ct_data *) ctptr;
     538    struct pollfd fd;
     539    int milliseconds = ((ct->ct_wait.tv_sec * 1000)
     540  		      + (ct->ct_wait.tv_usec / 1000));
     541  
     542    if (len == 0)
     543      return 0;
     544  
     545    fd.fd = ct->ct_sock;
     546    fd.events = POLLIN;
     547    while (TRUE)
     548      {
     549        switch (__poll (&fd, 1, milliseconds))
     550  	{
     551  	case 0:
     552  	  ct->ct_error.re_status = RPC_TIMEDOUT;
     553  	  return -1;
     554  
     555  	case -1:
     556  	  if (errno == EINTR)
     557  	    continue;
     558  	  ct->ct_error.re_status = RPC_CANTRECV;
     559  	  ct->ct_error.re_errno = errno;
     560  	  return -1;
     561  	}
     562        break;
     563      }
     564    switch (len = __msgread (ct->ct_sock, buf, len))
     565      {
     566  
     567      case 0:
     568        /* premature eof */
     569        ct->ct_error.re_errno = ECONNRESET;
     570        ct->ct_error.re_status = RPC_CANTRECV;
     571        len = -1;			/* it's really an error */
     572        break;
     573  
     574      case -1:
     575        ct->ct_error.re_errno = errno;
     576        ct->ct_error.re_status = RPC_CANTRECV;
     577        break;
     578      }
     579    return len;
     580  }
     581  
     582  static int
     583  writeunix (char *ctptr, char *buf, int len)
     584  {
     585    int i, cnt;
     586    struct ct_data *ct = (struct ct_data *) ctptr;
     587  
     588    for (cnt = len; cnt > 0; cnt -= i, buf += i)
     589      {
     590        if ((i = __msgwrite (ct->ct_sock, buf, cnt)) == -1)
     591  	{
     592  	  ct->ct_error.re_errno = errno;
     593  	  ct->ct_error.re_status = RPC_CANTSEND;
     594  	  return -1;
     595  	}
     596      }
     597    return len;
     598  }