Blame sunrpc/svc_unix.c

Packit Service 82fcde
/*
Packit Service 82fcde
 * svc_unix.c, Server side for TCP/IP based RPC.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Copyright (C) 2012-2018 Free Software Foundation, Inc.
Packit Service 82fcde
 * This file is part of the GNU C Library.
Packit Service 82fcde
 *
Packit Service 82fcde
 * The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
 * modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
 * License as published by the Free Software Foundation; either
Packit Service 82fcde
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
 *
Packit Service 82fcde
 * The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
 * Lesser General Public License for more details.
Packit Service 82fcde
 *
Packit Service 82fcde
 * You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
 * License along with the GNU C Library; if not, see
Packit Service 82fcde
 * <http://www.gnu.org/licenses/>.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Copyright (c) 2010, Oracle America, Inc.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Redistribution and use in source and binary forms, with or without
Packit Service 82fcde
 * modification, are permitted provided that the following conditions are
Packit Service 82fcde
 * met:
Packit Service 82fcde
 *
Packit Service 82fcde
 *     * Redistributions of source code must retain the above copyright
Packit Service 82fcde
 *       notice, this list of conditions and the following disclaimer.
Packit Service 82fcde
 *     * Redistributions in binary form must reproduce the above
Packit Service 82fcde
 *       copyright notice, this list of conditions and the following
Packit Service 82fcde
 *       disclaimer in the documentation and/or other materials
Packit Service 82fcde
 *       provided with the distribution.
Packit Service 82fcde
 *     * Neither the name of the "Oracle America, Inc." nor the names of its
Packit Service 82fcde
 *       contributors may be used to endorse or promote products derived
Packit Service 82fcde
 *       from this software without specific prior written permission.
Packit Service 82fcde
 *
Packit Service 82fcde
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit Service 82fcde
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service 82fcde
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit Service 82fcde
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit Service 82fcde
 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Packit Service 82fcde
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit Service 82fcde
 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
Packit Service 82fcde
 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit Service 82fcde
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit Service 82fcde
 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit Service 82fcde
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit Service 82fcde
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Actually implements two flavors of transporter -
Packit Service 82fcde
 * a unix rendezvouser (a listener and connection establisher)
Packit Service 82fcde
 * and a record/unix stream.
Packit Service 82fcde
 */
Packit Service 82fcde
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <rpc/rpc.h>
Packit Service 82fcde
#include <rpc/svc.h>
Packit Service 82fcde
#include <sys/socket.h>
Packit Service 82fcde
#include <sys/uio.h>
Packit Service 82fcde
#include <sys/poll.h>
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <libintl.h>
Packit Service 82fcde
#include <wchar.h>
Packit Service 82fcde
#include <shlib-compat.h>
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Ops vector for AF_UNIX based rpc service handle
Packit Service 82fcde
 */
Packit Service 82fcde
static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
Packit Service 82fcde
static enum xprt_stat svcunix_stat (SVCXPRT *);
Packit Service 82fcde
static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
Packit Service 82fcde
static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
Packit Service 82fcde
static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
Packit Service 82fcde
static void svcunix_destroy (SVCXPRT *);
Packit Service 82fcde
Packit Service 82fcde
static const struct xp_ops svcunix_op =
Packit Service 82fcde
{
Packit Service 82fcde
  svcunix_recv,
Packit Service 82fcde
  svcunix_stat,
Packit Service 82fcde
  svcunix_getargs,
Packit Service 82fcde
  svcunix_reply,
Packit Service 82fcde
  svcunix_freeargs,
Packit Service 82fcde
  svcunix_destroy
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Ops vector for AF_UNIX rendezvous handler
Packit Service 82fcde
 */
Packit Service 82fcde
static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
Packit Service 82fcde
static enum xprt_stat rendezvous_stat (SVCXPRT *);
Packit Service 82fcde
static void svcunix_rendezvous_abort (void) __attribute__ ((__noreturn__));
Packit Service 82fcde
Packit Service 82fcde
/* This function makes sure abort() relocation goes through PLT
Packit Service 82fcde
   and thus can be lazy bound.  */
Packit Service 82fcde
static void
Packit Service 82fcde
svcunix_rendezvous_abort (void)
Packit Service 82fcde
{
Packit Service 82fcde
  abort ();
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static const struct xp_ops svcunix_rendezvous_op =
Packit Service 82fcde
{
Packit Service 82fcde
  rendezvous_request,
Packit Service 82fcde
  rendezvous_stat,
Packit Service 82fcde
  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
Packit Service 82fcde
  (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort,
Packit Service 82fcde
  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
Packit Service 82fcde
  svcunix_destroy
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static int readunix (char*, char *, int);
Packit Service 82fcde
static int writeunix (char *, char *, int);
Packit Service 82fcde
static SVCXPRT *makefd_xprt (int, u_int, u_int);
Packit Service 82fcde
Packit Service 82fcde
struct unix_rendezvous {        /* kept in xprt->xp_p1 */
Packit Service 82fcde
  u_int sendsize;
Packit Service 82fcde
  u_int recvsize;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
struct unix_conn {		/* kept in xprt->xp_p1 */
Packit Service 82fcde
  enum xprt_stat strm_stat;
Packit Service 82fcde
  u_long x_id;
Packit Service 82fcde
  XDR xdrs;
Packit Service 82fcde
  char verf_body[MAX_AUTH_BYTES];
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Usage:
Packit Service 82fcde
 *      xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
Packit Service 82fcde
 *
Packit Service 82fcde
 * Creates, registers, and returns a (rpc) unix based transporter.
Packit Service 82fcde
 * Once *xprt is initialized, it is registered as a transporter
Packit Service 82fcde
 * see (svc.h, xprt_register).  This routine returns
Packit Service 82fcde
 * a NULL if a problem occurred.
Packit Service 82fcde
 *
Packit Service 82fcde
 * If sock<0 then a socket is created, else sock is used.
Packit Service 82fcde
 * If the socket, sock is not bound to a port then svcunix_create
Packit Service 82fcde
 * binds it to an arbitrary port.  The routine then starts a unix
Packit Service 82fcde
 * listener on the socket's associated port.  In any (successful) case,
Packit Service 82fcde
 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
Packit Service 82fcde
 * associated port number.
Packit Service 82fcde
 *
Packit Service 82fcde
 * Since unix streams do buffered io similar to stdio, the caller can specify
Packit Service 82fcde
 * how big the send and receive buffers are via the second and third parms;
Packit Service 82fcde
 * 0 => use the system default.
Packit Service 82fcde
 */
Packit Service 82fcde
SVCXPRT *
Packit Service 82fcde
svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
Packit Service 82fcde
{
Packit Service 82fcde
  bool_t madesock = FALSE;
Packit Service 82fcde
  SVCXPRT *xprt;
Packit Service 82fcde
  struct unix_rendezvous *r;
Packit Service 82fcde
  struct sockaddr_un addr;
Packit Service 82fcde
  socklen_t len = sizeof (struct sockaddr_in);
Packit Service 82fcde
Packit Service 82fcde
  if (sock == RPC_ANYSOCK)
Packit Service 82fcde
    {
Packit Service 82fcde
      if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  perror (_("svc_unix.c - AF_UNIX socket creation problem"));
Packit Service 82fcde
	  return (SVCXPRT *) NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
      madesock = TRUE;
Packit Service 82fcde
    }
Packit Service 82fcde
  memset (&addr, '\0', sizeof (addr));
Packit Service 82fcde
  addr.sun_family = AF_UNIX;
Packit Service 82fcde
  len = strlen (path) + 1;
Packit Service 82fcde
  memcpy (addr.sun_path, path, len);
Packit Service 82fcde
  len += sizeof (addr.sun_family);
Packit Service 82fcde
Packit Service 82fcde
  __bind (sock, (struct sockaddr *) &addr, len);
Packit Service 82fcde
Packit Service 82fcde
  if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
Packit Service 82fcde
      || __listen (sock, SOMAXCONN) != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      perror (_("svc_unix.c - cannot getsockname or listen"));
Packit Service 82fcde
      if (madesock)
Packit Service 82fcde
	__close (sock);
Packit Service 82fcde
      return (SVCXPRT *) NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
Packit Service 82fcde
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
Packit Service 82fcde
  if (r == NULL || xprt == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
Packit Service 82fcde
      mem_free (r, sizeof (*r));
Packit Service 82fcde
      mem_free (xprt, sizeof (SVCXPRT));
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  r->sendsize = sendsize;
Packit Service 82fcde
  r->recvsize = recvsize;
Packit Service 82fcde
  xprt->xp_p2 = NULL;
Packit Service 82fcde
  xprt->xp_p1 = (caddr_t) r;
Packit Service 82fcde
  xprt->xp_verf = _null_auth;
Packit Service 82fcde
  xprt->xp_ops = &svcunix_rendezvous_op;
Packit Service 82fcde
  xprt->xp_port = -1;
Packit Service 82fcde
  xprt->xp_sock = sock;
Packit Service 82fcde
  xprt_register (xprt);
Packit Service 82fcde
  return xprt;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_nolink_sunrpc (svcunix_create, GLIBC_2_1)
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * Like svunix_create(), except the routine takes any *open* UNIX file
Packit Service 82fcde
 * descriptor as its first input.
Packit Service 82fcde
 */
Packit Service 82fcde
SVCXPRT *
Packit Service 82fcde
svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
Packit Service 82fcde
{
Packit Service 82fcde
  return makefd_xprt (fd, sendsize, recvsize);
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_nolink_sunrpc (svcunixfd_create, GLIBC_2_1)
Packit Service 82fcde
Packit Service 82fcde
static SVCXPRT *
Packit Service 82fcde
makefd_xprt (int fd, u_int sendsize, u_int recvsize)
Packit Service 82fcde
{
Packit Service 82fcde
  SVCXPRT *xprt;
Packit Service 82fcde
  struct unix_conn *cd;
Packit Service 82fcde
Packit Service 82fcde
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
Packit Service 82fcde
  cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
Packit Service 82fcde
  if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      (void) __fxprintf (NULL, "%s: %s", "svc_unix: makefd_xprt",
Packit Service 82fcde
			 _("out of memory\n"));
Packit Service 82fcde
      mem_free (xprt, sizeof (SVCXPRT));
Packit Service 82fcde
      mem_free (cd, sizeof (struct unix_conn));
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  cd->strm_stat = XPRT_IDLE;
Packit Service 82fcde
  xdrrec_create (&(cd->xdrs), sendsize, recvsize,
Packit Service 82fcde
		 (caddr_t) xprt, readunix, writeunix);
Packit Service 82fcde
  xprt->xp_p2 = NULL;
Packit Service 82fcde
  xprt->xp_p1 = (caddr_t) cd;
Packit Service 82fcde
  xprt->xp_verf.oa_base = cd->verf_body;
Packit Service 82fcde
  xprt->xp_addrlen = 0;
Packit Service 82fcde
  xprt->xp_ops = &svcunix_op;	/* truly deals with calls */
Packit Service 82fcde
  xprt->xp_port = 0;		/* this is a connection, not a rendezvouser */
Packit Service 82fcde
  xprt->xp_sock = fd;
Packit Service 82fcde
  xprt_register (xprt);
Packit Service 82fcde
  return xprt;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool_t
Packit Service 82fcde
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
Packit Service 82fcde
{
Packit Service 82fcde
  int sock;
Packit Service 82fcde
  struct unix_rendezvous *r;
Packit Service 82fcde
  struct sockaddr_un addr;
Packit Service 82fcde
  struct sockaddr_in in_addr;
Packit Service 82fcde
  socklen_t len;
Packit Service 82fcde
Packit Service 82fcde
  r = (struct unix_rendezvous *) xprt->xp_p1;
Packit Service 82fcde
again:
Packit Service 82fcde
  len = sizeof (struct sockaddr_un);
Packit Service 82fcde
  if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (errno == EINTR)
Packit Service 82fcde
	goto again;
Packit Service 82fcde
      __svc_accept_failed ();
Packit Service 82fcde
      return FALSE;
Packit Service 82fcde
    }
Packit Service 82fcde
  /*
Packit Service 82fcde
   * make a new transporter (re-uses xprt)
Packit Service 82fcde
   */
Packit Service 82fcde
  memset (&in_addr, '\0', sizeof (in_addr));
Packit Service 82fcde
  in_addr.sin_family = AF_UNIX;
Packit Service 82fcde
  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
Packit Service 82fcde
  memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
Packit Service 82fcde
  xprt->xp_addrlen = len;
Packit Service 82fcde
  return FALSE;		/* there is never an rpc msg to be processed */
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static enum xprt_stat
Packit Service 82fcde
rendezvous_stat (SVCXPRT *xprt)
Packit Service 82fcde
{
Packit Service 82fcde
  return XPRT_IDLE;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
svcunix_destroy (SVCXPRT *xprt)
Packit Service 82fcde
{
Packit Service 82fcde
  struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
Packit Service 82fcde
Packit Service 82fcde
  xprt_unregister (xprt);
Packit Service 82fcde
  __close (xprt->xp_sock);
Packit Service 82fcde
  if (xprt->xp_port != 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* a rendezvouser socket */
Packit Service 82fcde
      xprt->xp_port = 0;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* an actual connection socket */
Packit Service 82fcde
      XDR_DESTROY (&(cd->xdrs));
Packit Service 82fcde
    }
Packit Service 82fcde
  mem_free ((caddr_t) cd, sizeof (struct unix_conn));
Packit Service 82fcde
  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifdef SCM_CREDENTIALS
Packit Service 82fcde
struct cmessage {
Packit Service 82fcde
  struct cmsghdr cmsg;
Packit Service 82fcde
  struct ucred cmcred;
Packit Service 82fcde
  /* hack to make sure we have enough memory */
Packit Service 82fcde
  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* XXX This is not thread safe, but since the main functions in svc.c
Packit Service 82fcde
   and the rpcgen generated *_svc functions for the daemon are also not
Packit Service 82fcde
   thread safe and uses static global variables, it doesn't matter. */
Packit Service 82fcde
static struct cmessage cm;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
__msgread (int sock, void *data, size_t cnt)
Packit Service 82fcde
{
Packit Service 82fcde
  struct iovec iov;
Packit Service 82fcde
  struct msghdr msg;
Packit Service 82fcde
  int len;
Packit Service 82fcde
Packit Service 82fcde
  iov.iov_base = data;
Packit Service 82fcde
  iov.iov_len = cnt;
Packit Service 82fcde
Packit Service 82fcde
  msg.msg_iov = &iov;
Packit Service 82fcde
  msg.msg_iovlen = 1;
Packit Service 82fcde
  msg.msg_name = NULL;
Packit Service 82fcde
  msg.msg_namelen = 0;
Packit Service 82fcde
#ifdef SCM_CREDENTIALS
Packit Service 82fcde
  msg.msg_control = (caddr_t) &cm;
Packit Service 82fcde
  msg.msg_controllen = sizeof (struct cmessage);
Packit Service 82fcde
#endif
Packit Service 82fcde
  msg.msg_flags = 0;
Packit Service 82fcde
Packit Service 82fcde
#ifdef SO_PASSCRED
Packit Service 82fcde
  {
Packit Service 82fcde
    int on = 1;
Packit Service 82fcde
    if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
Packit Service 82fcde
      return -1;
Packit Service 82fcde
  }
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
 restart:
Packit Service 82fcde
  len = __recvmsg (sock, &msg, 0);
Packit Service 82fcde
  if (len >= 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (msg.msg_flags & MSG_CTRUNC || len == 0)
Packit Service 82fcde
	return 0;
Packit Service 82fcde
      else
Packit Service 82fcde
	return len;
Packit Service 82fcde
    }
Packit Service 82fcde
  if (errno == EINTR)
Packit Service 82fcde
    goto restart;
Packit Service 82fcde
  return -1;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
__msgwrite (int sock, void *data, size_t cnt)
Packit Service 82fcde
{
Packit Service 82fcde
#ifndef SCM_CREDENTIALS
Packit Service 82fcde
  /* We cannot implement this reliably.  */
Packit Service 82fcde
  __set_errno (ENOSYS);
Packit Service 82fcde
  return -1;
Packit Service 82fcde
#else
Packit Service 82fcde
  struct iovec iov;
Packit Service 82fcde
  struct msghdr msg;
Packit Service 82fcde
  struct cmsghdr *cmsg = &cm.cmsg;
Packit Service 82fcde
  struct ucred cred;
Packit Service 82fcde
  int len;
Packit Service 82fcde
Packit Service 82fcde
  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
Packit Service 82fcde
     get?id(). But since keyserv needs geteuid(), we have no other chance.
Packit Service 82fcde
     It would be much better, if the kernel could pass both to the server. */
Packit Service 82fcde
  cred.pid = __getpid ();
Packit Service 82fcde
  cred.uid = __geteuid ();
Packit Service 82fcde
  cred.gid = __getegid ();
Packit Service 82fcde
Packit Service 82fcde
  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
Packit Service 82fcde
  cmsg->cmsg_level = SOL_SOCKET;
Packit Service 82fcde
  cmsg->cmsg_type = SCM_CREDENTIALS;
Packit Service 82fcde
  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
Packit Service 82fcde
Packit Service 82fcde
  iov.iov_base = data;
Packit Service 82fcde
  iov.iov_len = cnt;
Packit Service 82fcde
Packit Service 82fcde
  msg.msg_iov = &iov;
Packit Service 82fcde
  msg.msg_iovlen = 1;
Packit Service 82fcde
  msg.msg_name = NULL;
Packit Service 82fcde
  msg.msg_namelen = 0;
Packit Service 82fcde
  msg.msg_control = cmsg;
Packit Service 82fcde
  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
Packit Service 82fcde
  msg.msg_flags = 0;
Packit Service 82fcde
Packit Service 82fcde
 restart:
Packit Service 82fcde
  len = __sendmsg (sock, &msg, 0);
Packit Service 82fcde
  if (len >= 0)
Packit Service 82fcde
    return len;
Packit Service 82fcde
  if (errno == EINTR)
Packit Service 82fcde
    goto restart;
Packit Service 82fcde
  return -1;
Packit Service 82fcde
Packit Service 82fcde
#endif
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * reads data from the unix connection.
Packit Service 82fcde
 * any error is fatal and the connection is closed.
Packit Service 82fcde
 * (And a read of zero bytes is a half closed stream => error.)
Packit Service 82fcde
 */
Packit Service 82fcde
static int
Packit Service 82fcde
readunix (char *xprtptr, char *buf, int len)
Packit Service 82fcde
{
Packit Service 82fcde
  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
Packit Service 82fcde
  int sock = xprt->xp_sock;
Packit Service 82fcde
  int milliseconds = 35 * 1000;
Packit Service 82fcde
  struct pollfd pollfd;
Packit Service 82fcde
Packit Service 82fcde
  do
Packit Service 82fcde
    {
Packit Service 82fcde
      pollfd.fd = sock;
Packit Service 82fcde
      pollfd.events = POLLIN;
Packit Service 82fcde
      switch (__poll (&pollfd, 1, milliseconds))
Packit Service 82fcde
	{
Packit Service 82fcde
	case -1:
Packit Service 82fcde
	  if (errno == EINTR)
Packit Service 82fcde
	    continue;
Packit Service 82fcde
	  /*FALLTHROUGH*/
Packit Service 82fcde
	case 0:
Packit Service 82fcde
	  goto fatal_err;
Packit Service 82fcde
	default:
Packit Service 82fcde
	  if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
Packit Service 82fcde
	      || (pollfd.revents & POLLNVAL))
Packit Service 82fcde
	    goto fatal_err;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  while ((pollfd.revents & POLLIN) == 0);
Packit Service 82fcde
Packit Service 82fcde
  if ((len = __msgread (sock, buf, len)) > 0)
Packit Service 82fcde
    return len;
Packit Service 82fcde
Packit Service 82fcde
 fatal_err:
Packit Service 82fcde
  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
Packit Service 82fcde
  return -1;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
/*
Packit Service 82fcde
 * writes data to the unix connection.
Packit Service 82fcde
 * Any error is fatal and the connection is closed.
Packit Service 82fcde
 */
Packit Service 82fcde
static int
Packit Service 82fcde
writeunix (char *xprtptr, char * buf, int len)
Packit Service 82fcde
{
Packit Service 82fcde
  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
Packit Service 82fcde
  int i, cnt;
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = len; cnt > 0; cnt -= i, buf += i)
Packit Service 82fcde
    {
Packit Service 82fcde
      if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
Packit Service 82fcde
	{
Packit Service 82fcde
	  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
Packit Service 82fcde
	  return -1;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
  return len;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static enum xprt_stat
Packit Service 82fcde
svcunix_stat (SVCXPRT *xprt)
Packit Service 82fcde
{
Packit Service 82fcde
  struct unix_conn *cd =
Packit Service 82fcde
  (struct unix_conn *) (xprt->xp_p1);
Packit Service 82fcde
Packit Service 82fcde
  if (cd->strm_stat == XPRT_DIED)
Packit Service 82fcde
    return XPRT_DIED;
Packit Service 82fcde
  if (!xdrrec_eof (&(cd->xdrs)))
Packit Service 82fcde
    return XPRT_MOREREQS;
Packit Service 82fcde
  return XPRT_IDLE;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool_t
Packit Service 82fcde
svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
Packit Service 82fcde
{
Packit Service 82fcde
  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
Packit Service 82fcde
  XDR *xdrs = &(cd->xdrs);
Packit Service 82fcde
Packit Service 82fcde
  xdrs->x_op = XDR_DECODE;
Packit Service 82fcde
  xdrrec_skiprecord (xdrs);
Packit Service 82fcde
  if (xdr_callmsg (xdrs, msg))
Packit Service 82fcde
    {
Packit Service 82fcde
      cd->x_id = msg->rm_xid;
Packit Service 82fcde
      /* set up verifiers */
Packit Service 82fcde
#ifdef SCM_CREDENTIALS
Packit Service 82fcde
      msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
Packit Service 82fcde
      msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
Packit Service 82fcde
      msg->rm_call.cb_verf.oa_length = sizeof (cm);
Packit Service 82fcde
#endif
Packit Service 82fcde
      return TRUE;
Packit Service 82fcde
    }
Packit Service 82fcde
  cd->strm_stat = XPRT_DIED;	/* XXXX */
Packit Service 82fcde
  return FALSE;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool_t
Packit Service 82fcde
svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
Packit Service 82fcde
{
Packit Service 82fcde
  return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
Packit Service 82fcde
		      args_ptr);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool_t
Packit Service 82fcde
svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
Packit Service 82fcde
{
Packit Service 82fcde
  XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
Packit Service 82fcde
Packit Service 82fcde
  xdrs->x_op = XDR_FREE;
Packit Service 82fcde
  return (*xdr_args) (xdrs, args_ptr);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
static bool_t
Packit Service 82fcde
svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
Packit Service 82fcde
{
Packit Service 82fcde
  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
Packit Service 82fcde
  XDR *xdrs = &(cd->xdrs);
Packit Service 82fcde
  bool_t stat;
Packit Service 82fcde
Packit Service 82fcde
  xdrs->x_op = XDR_ENCODE;
Packit Service 82fcde
  msg->rm_xid = cd->x_id;
Packit Service 82fcde
  stat = xdr_replymsg (xdrs, msg);
Packit Service 82fcde
  (void) xdrrec_endofrecord (xdrs, TRUE);
Packit Service 82fcde
  return stat;
Packit Service 82fcde
}