Example #1
0
CLIENT *
clnttcp_create (struct sockaddr_in *raddr, u_long prog, u_long vers,
		int *sockp, u_int sendsz, u_int recvsz)
{
  CLIENT *h;
  struct ct_data *ct;
  struct rpc_msg call_msg;

  h = (CLIENT *) mem_alloc (sizeof (*h));
  ct = (struct ct_data *) mem_alloc (sizeof (*ct));
  if (h == NULL || ct == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
      if (_IO_fwide (stderr, 0) > 0)
	(void) fwprintf (stderr, L"%s",
			   _("clnttcp_create: out of memory\n"));
      else
#endif
	(void) fputs (_("clnttcp_create: out of memory\n"), stderr);
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }

  /*
   * If no port number given ask the pmap for one
   */
  if (raddr->sin_port == 0)
    {
      u_short port;
      if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0)
	{
	  mem_free ((caddr_t) ct, sizeof (struct ct_data));
	  mem_free ((caddr_t) h, sizeof (CLIENT));
	  return ((CLIENT *) NULL);
	}
      raddr->sin_port = htons (port);
    }

  /*
   * If no socket given, open one
   */
  if (*sockp < 0)
    {
      *sockp = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
      if ((*sockp < 0)
	  || (connect (*sockp, (struct sockaddr *) raddr,
			 sizeof (*raddr)) < 0))
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  if (*sockp >= 0)
	    (void) close (*sockp);
	  goto fooy;
	}
      ct->ct_closeit = TRUE;
    }
  else
    {
      ct->ct_closeit = FALSE;
    }

  /*
   * Set up private data struct
   */
  ct->ct_sock = *sockp;
  ct->ct_wait.tv_usec = 0;
  ct->ct_waitset = FALSE;
  ct->ct_addr = *raddr;

  /*
   * Initialize call message
   */
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = prog;
  call_msg.rm_call.cb_vers = vers;

  /*
   * pre-serialize the static part of the call msg and stash it away
   */
  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
		 XDR_ENCODE);
  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
    {
      if (ct->ct_closeit)
	{
	  (void) close (*sockp);
	}
      goto fooy;
    }
  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
  XDR_DESTROY (&(ct->ct_xdrs));

  /*
   * Create a client handle which uses xdrrec for serialization
   * and authnone for authentication.
   */
  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
		 (caddr_t) ct, readtcp, writetcp);
  h->cl_ops = &tcp_ops;
  h->cl_private = (caddr_t) ct;
  h->cl_auth = authnone_create ();
  return h;

fooy:
  /*
   * Something goofed, free stuff and barf
   */
  mem_free ((caddr_t) ct, sizeof (struct ct_data));
  mem_free ((caddr_t) h, sizeof (CLIENT));
  return ((CLIENT *) NULL);
}
Example #2
0
/* libc_hidden_proto(clntudp_bufcreate) */
CLIENT *
clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version,
		   struct timeval wait, int *sockp, u_int sendsz,
		   u_int recvsz)
{
  CLIENT *cl;
  struct cu_data *cu = NULL;
  struct rpc_msg call_msg;

  cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
  sendsz = ((sendsz + 3) / 4) * 4;
  recvsz = ((recvsz + 3) / 4) * 4;
  cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
  if (cl == NULL || cu == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
#ifdef USE_IN_LIBIO
      if (_IO_fwide (stderr, 0) > 0)
	(void) fwprintf (stderr, L"%s",
			   _("clntudp_create: out of memory\n"));
      else
#endif
	(void) fputs (_("clntudp_create: out of memory\n"), stderr);
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }
  cu->cu_outbuf = &cu->cu_inbuf[recvsz];

  if (raddr->sin_port == 0)
    {
      u_short port;
      if ((port =
	   pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0)
	{
	  goto fooy;
	}
      raddr->sin_port = htons (port);
    }
  cl->cl_ops = &udp_ops;
  cl->cl_private = (caddr_t) cu;
  cu->cu_raddr = *raddr;
  cu->cu_rlen = sizeof (cu->cu_raddr);
  cu->cu_wait = wait;
  cu->cu_total.tv_sec = -1;
  cu->cu_total.tv_usec = -1;
  cu->cu_sendsz = sendsz;
  cu->cu_recvsz = recvsz;
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = program;
  call_msg.rm_call.cb_vers = version;
  xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf,
		 sendsz, XDR_ENCODE);
  if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg))
    {
      goto fooy;
    }
  cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs));
  if (*sockp < 0)
    {
      int dontblock = 1;

      *sockp = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
      if (*sockp < 0)
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  goto fooy;
	}
      /* attempt to bind to prov port */
      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
      /* the sockets rpc controls are non-blocking */
      (void) ioctl (*sockp, FIONBIO, (char *) &dontblock);
#ifdef IP_RECVERR
      {
	int on = 1;
	setsockopt(*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
      }
#endif
      cu->cu_closeit = TRUE;
    }
  else
    {
      cu->cu_closeit = FALSE;
    }
  cu->cu_sock = *sockp;
  cl->cl_auth = authnone_create ();
  return cl;
fooy:
  if (cu)
    mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz);
  if (cl)
    mem_free ((caddr_t) cl, sizeof (CLIENT));
  return (CLIENT *) NULL;
}
Example #3
0
/*
 * Create a UDP based client handle.
 * If *sockp<0, *sockp is set to a newly created UPD socket.
 * If raddr->sin_port is 0 a binder on the remote machine
 * is consulted for the correct port number.
 * NB: It is the clients responsibility to close *sockp.
 * NB: The rpch->cl_auth is initialized to null authentication.
 *     Caller may wish to set this something more useful.
 *
 * wait is the amount of time used between retransmitting a call if
 * no response has been heard; retransmission occurs until the actual
 * rpc call times out.
 *
 * sendsz and recvsz are the maximum allowable packet sizes that can be
 * sent and received.
 */
CLIENT *
__libc_clntudp_bufcreate (struct sockaddr_in *raddr, u_long program,
			  u_long version, struct timeval wait, int *sockp,
			  u_int sendsz, u_int recvsz, int flags)
{
  CLIENT *cl;
  struct cu_data *cu = NULL;
  struct rpc_msg call_msg;

  cl = (CLIENT *) mem_alloc (sizeof (CLIENT));
  sendsz = ((sendsz + 3) / 4) * 4;
  recvsz = ((recvsz + 3) / 4) * 4;
  cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz);
  if (cl == NULL || cu == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
      (void) __fxprintf (NULL, "%s: %s",
			 "clntudp_create", _("out of memory\n"));
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }
  cu->cu_outbuf = &cu->cu_inbuf[recvsz];

  if (raddr->sin_port == 0)
    {
      u_short port;
      if ((port =
	   pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0)
	{
	  goto fooy;
	}
      raddr->sin_port = htons (port);
    }
  cl->cl_ops = (struct clnt_ops *) &udp_ops;
  cl->cl_private = (caddr_t) cu;
  cu->cu_raddr = *raddr;
  cu->cu_rlen = sizeof (cu->cu_raddr);
  cu->cu_wait = wait;
  cu->cu_total.tv_sec = -1;
  cu->cu_total.tv_usec = -1;
  cu->cu_sendsz = sendsz;
  cu->cu_recvsz = recvsz;
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = program;
  call_msg.rm_call.cb_vers = version;
  xdrmem_create (&(cu->cu_outxdrs), cu->cu_outbuf, sendsz, XDR_ENCODE);
  if (!xdr_callhdr (&(cu->cu_outxdrs), &call_msg))
    {
      goto fooy;
    }
  cu->cu_xdrpos = XDR_GETPOS (&(cu->cu_outxdrs));
  if (*sockp < 0)
    {
#ifdef SOCK_NONBLOCK
# ifndef __ASSUME_SOCK_CLOEXEC
      if (__have_sock_cloexec >= 0)
# endif
	{
	  *sockp = __socket (AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|flags,
			     IPPROTO_UDP);
# ifndef __ASSUME_SOCK_CLOEXEC
	  if (__have_sock_cloexec == 0)
	    __have_sock_cloexec = *sockp >= 0 || errno != EINVAL ? 1 : -1;
# endif
	}
#endif
#ifndef __ASSUME_SOCK_CLOEXEC
# ifdef SOCK_CLOEXEC
      if (__have_sock_cloexec < 0)
# endif
	{
	  *sockp = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
# ifdef SOCK_CLOEXEC
	  if (flags & SOCK_CLOEXEC)
	    __fcntl (*sockp, F_SETFD, FD_CLOEXEC);
# endif
	}
#endif
      if (__builtin_expect (*sockp < 0, 0))
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  goto fooy;
	}
      /* attempt to bind to prov port */
      (void) bindresvport (*sockp, (struct sockaddr_in *) 0);
#ifndef __ASSUME_SOCK_CLOEXEC
# ifdef SOCK_CLOEXEC
      if (__have_sock_cloexec < 0)
# endif
	{
	  /* the sockets rpc controls are non-blocking */
	  int dontblock = 1;
	  (void) __ioctl (*sockp, FIONBIO, (char *) &dontblock);
	}
#endif
#ifdef IP_RECVERR
      {
	int on = 1;
	__setsockopt (*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on));
      }
#endif
      cu->cu_closeit = TRUE;
    }
  else
    {
      cu->cu_closeit = FALSE;
    }
  cu->cu_sock = *sockp;
  cl->cl_auth = authnone_create ();
  return cl;
fooy:
  if (cu)
    mem_free ((caddr_t) cu, sizeof (*cu) + sendsz + recvsz);
  if (cl)
    mem_free ((caddr_t) cl, sizeof (CLIENT));
  return (CLIENT *) NULL;
}
Example #4
0
/*
 * Create a client handle for a tcp/ip connection.
 * If *sockp<0, *sockp is set to a newly created TCP socket and it is
 * connected to raddr.  If *sockp non-negative then
 * raddr is ignored.  The rpc/tcp package does buffering
 * similar to stdio, so the client must pick send and receive buffer sizes,];
 * 0 => use the default.
 * If raddr->sin_port is 0, then a binder on the remote machine is
 * consulted for the right port number.
 * NB: *sockp is copied into a private area.
 * NB: It is the clients responsibility to close *sockp.
 * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this
 * something more useful.
 */
CLIENT *
clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers,
		 int *sockp, u_int sendsz, u_int recvsz)
{
  CLIENT *h;
  struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct));
  struct rpc_msg call_msg;
  int len;

  h = (CLIENT *) mem_alloc (sizeof (*h));
  if (h == NULL || ct == NULL)
    {
      struct rpc_createerr *ce = &get_rpc_createerr ();
      (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
      ce->cf_stat = RPC_SYSTEMERROR;
      ce->cf_error.re_errno = ENOMEM;
      goto fooy;
    }

  /*
   * If no socket given, open one
   */
  if (*sockp < 0)
    {
      *sockp = __socket (AF_UNIX, SOCK_STREAM, 0);
      len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1;
      if (*sockp < 0
	  || __connect (*sockp, (struct sockaddr *) raddr, len) < 0)
	{
	  struct rpc_createerr *ce = &get_rpc_createerr ();
	  ce->cf_stat = RPC_SYSTEMERROR;
	  ce->cf_error.re_errno = errno;
	  if (*sockp != -1)
	    __close (*sockp);
	  goto fooy;
	}
      ct->ct_closeit = TRUE;
    }
  else
    {
      ct->ct_closeit = FALSE;
    }

  /*
   * Set up private data struct
   */
  ct->ct_sock = *sockp;
  ct->ct_wait.tv_usec = 0;
  ct->ct_waitset = FALSE;
  ct->ct_addr = *raddr;

  /*
   * Initialize call message
   */
  call_msg.rm_xid = _create_xid ();
  call_msg.rm_direction = CALL;
  call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  call_msg.rm_call.cb_prog = prog;
  call_msg.rm_call.cb_vers = vers;

  /*
   * pre-serialize the static part of the call msg and stash it away
   */
  xdrmem_create (&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, XDR_ENCODE);
  if (!xdr_callhdr (&(ct->ct_xdrs), &call_msg))
    {
      if (ct->ct_closeit)
	__close (*sockp);
      goto fooy;
    }
  ct->ct_mpos = XDR_GETPOS (&(ct->ct_xdrs));
  XDR_DESTROY (&(ct->ct_xdrs));

  /*
   * Create a client handle which uses xdrrec for serialization
   * and authnone for authentication.
   */
  xdrrec_create (&(ct->ct_xdrs), sendsz, recvsz,
		 (caddr_t) ct, readunix, writeunix);
  h->cl_ops = (struct clnt_ops *) &unix_ops;
  h->cl_private = (caddr_t) ct;
  h->cl_auth = authnone_create ();
  return h;

fooy:
  /*
   * Something goofed, free stuff and barf
   */
  mem_free ((caddr_t) ct, sizeof (struct ct_data));
  mem_free ((caddr_t) h, sizeof (CLIENT));
  return (CLIENT *) NULL;
}
Example #5
0
enum clnt_stat
clnt_broadcast (
     u_long prog,		/* program number */
     u_long vers,		/* version number */
     u_long proc,		/* procedure number */
     xdrproc_t xargs,		/* xdr routine for args */
     caddr_t argsp,		/* pointer to args */
     xdrproc_t xresults,	/* xdr routine for results */
     caddr_t resultsp,		/* pointer to results */
     resultproc_t eachresult	/* call with each result obtained */)
{
  enum clnt_stat stat = RPC_FAILED;
  AUTH *unix_auth = authunix_create_default ();
  XDR xdr_stream;
  XDR *xdrs = &xdr_stream;
  struct timeval t;
  int outlen, inlen, nets;
  socklen_t fromlen;
  int sock;
  int on = 1;
  struct pollfd fd;
  int milliseconds;
  int i;
  bool_t done = FALSE;
  u_long xid;
  u_long port;
  struct in_addr addrs[20];
  struct sockaddr_in baddr, raddr;	/* broadcast and response addresses */
  struct rmtcallargs a;
  struct rmtcallres r;
  struct rpc_msg msg;
  char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];

  /*
   * initialization: create a socket, a broadcast address, and
   * preserialize the arguments into a send buffer.
   */
  if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
      perror (_("Cannot create socket for broadcast rpc"));
      stat = RPC_CANTSEND;
      goto done_broad;
    }
#ifdef SO_BROADCAST
  if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
    {
      perror (_("Cannot set socket option SO_BROADCAST"));
      stat = RPC_CANTSEND;
      goto done_broad;
    }
#endif /* def SO_BROADCAST */
  fd.fd = sock;
  fd.events = POLLIN;
  nets = getbroadcastnets (addrs, sock, inbuf);
  memset ((char *) &baddr, 0, sizeof (baddr));
  baddr.sin_family = AF_INET;
  baddr.sin_port = htons (PMAPPORT);
  baddr.sin_addr.s_addr = htonl (INADDR_ANY);
/*      baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
  msg.rm_xid = xid = _create_xid ();
  t.tv_usec = 0;
  msg.rm_direction = CALL;
  msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  msg.rm_call.cb_prog = PMAPPROG;
  msg.rm_call.cb_vers = PMAPVERS;
  msg.rm_call.cb_proc = PMAPPROC_CALLIT;
  msg.rm_call.cb_cred = unix_auth->ah_cred;
  msg.rm_call.cb_verf = unix_auth->ah_verf;
  a.prog = prog;
  a.vers = vers;
  a.proc = proc;
  a.xdr_args = xargs;
  a.args_ptr = argsp;
  r.port_ptr = &port;
  r.xdr_results = xresults;
  r.results_ptr = resultsp;
  xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
  if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a)))
    {
      stat = RPC_CANTENCODEARGS;
      goto done_broad;
    }
  outlen = (int) xdr_getpos (xdrs);
  xdr_destroy (xdrs);
  /*
   * Basic loop: broadcast a packet and wait a while for response(s).
   * The response timeout grows larger per iteration.
   */
  for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2)
    {
      for (i = 0; i < nets; i++)
	{
	  baddr.sin_addr = addrs[i];
	  if (sendto (sock, outbuf, outlen, 0,
		      (struct sockaddr *) &baddr,
		      sizeof (struct sockaddr)) != outlen)
	    {
	      perror (_("Cannot send broadcast packet"));
	      stat = RPC_CANTSEND;
	      goto done_broad;
	    }
	}
      if (eachresult == NULL)
	{
	  stat = RPC_SUCCESS;
	  goto done_broad;
	}
    recv_again:
      msg.acpted_rply.ar_verf = _null_auth;
      msg.acpted_rply.ar_results.where = (caddr_t) & r;
      msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres;
      milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000;
      switch (poll(&fd, 1, milliseconds))
	{

	case 0:		/* timed out */
	  stat = RPC_TIMEDOUT;
	  continue;

	case -1:		/* some kind of error */
	  if (errno == EINTR)
	    goto recv_again;
	  perror (_("Broadcast poll problem"));
	  stat = RPC_CANTRECV;
	  goto done_broad;

	}			/* end of poll results switch */
    try_again:
      fromlen = sizeof (struct sockaddr);
      inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0,
			(struct sockaddr *) &raddr, &fromlen);
      if (inlen < 0)
	{
	  if (errno == EINTR)
	    goto try_again;
	  perror (_("Cannot receive reply to broadcast"));
	  stat = RPC_CANTRECV;
	  goto done_broad;
	}
      if ((size_t) inlen < sizeof (u_long))
	goto recv_again;
      /*
       * see if reply transaction id matches sent id.
       * If so, decode the results.
       */
      xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE);
      if (xdr_replymsg (xdrs, &msg))
	{
	  if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) &&
	      (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
	      (msg.acpted_rply.ar_stat == SUCCESS))
	    {
	      raddr.sin_port = htons ((u_short) port);
	      done = (*eachresult) (resultsp, &raddr);
	    }
	  /* otherwise, we just ignore the errors ... */
	}
      else
	{
#ifdef notdef
	  /* some kind of deserialization problem ... */
	  if ((u_int32_t) msg.rm_xid == (u_int32_t) xid)
	    fprintf (stderr, "Broadcast deserialization problem");
	  /* otherwise, just random garbage */
#endif
	}
      xdrs->x_op = XDR_FREE;
      msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
      (void) xdr_replymsg (xdrs, &msg);
      (void) (*xresults) (xdrs, resultsp);
      xdr_destroy (xdrs);
      if (done)
	{
	  stat = RPC_SUCCESS;
	  goto done_broad;
	}
      else
	{
	  goto recv_again;
	}
    }
done_broad:
  (void) close (sock);
  AUTH_DESTROY (unix_auth);
  return stat;
}