Пример #1
0
/*
 * Create a socket that is locally bound to a non-reserve port. For
 * any failures, -1 is returned which will cause the RPC code to
 * create the socket.
 */
int
internal_function
__get_socket (struct sockaddr_in *saddr)
{
  int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (so < 0)
    return -1;

  struct sockaddr_in laddr;
  socklen_t namelen = sizeof (laddr);
  laddr.sin_family = AF_INET;
  laddr.sin_port = 0;
  laddr.sin_addr.s_addr = htonl (INADDR_ANY);

  int cc = __bind (so, (struct sockaddr *) &laddr, namelen);
  if (__glibc_unlikely (cc < 0))
    {
    fail:
      __close (so);
      return -1;
    }

  cc = __connect (so, (struct sockaddr *) saddr, namelen);
  if (__glibc_unlikely (cc < 0))
    goto fail;

  return so;
}
static int
open_socket (void)
{
  int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
  if (sock < 0)
    return -1;

  /* Make socket non-blocking.  */
  int fl = __fcntl (sock, F_GETFL);
  if (fl != -1)
    __fcntl (sock, F_SETFL, fl | O_NONBLOCK);

  struct sockaddr_un sun;
  sun.sun_family = AF_UNIX;
  strcpy (sun.sun_path, _PATH_NSCDSOCKET);
  if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
      && errno != EINPROGRESS)
    goto out;

  struct pollfd fds[1];
  fds[0].fd = sock;
  fds[0].events = POLLOUT | POLLERR | POLLHUP;
  if (__poll (fds, 1, 5 * 1000) > 0)
    /* Success.  We do not check for success of the connect call here.
       If it failed, the following operations will fail.  */
    return sock;

 out:
  close_not_cancel_no_status (sock);

  return -1;
}
Пример #3
0
/* Open a NETLINK socket.  */
int
__netlink_open (struct netlink_handle *h)
{
  struct sockaddr_nl nladdr;

  h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
  if (h->fd < 0)
    goto out;

  memset (&nladdr, '\0', sizeof (nladdr));
  nladdr.nl_family = AF_NETLINK;
  if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
    {
    close_and_out:
      __netlink_close (h);
    out:
#if __ASSUME_NETLINK_SUPPORT == 0
      __no_netlink_support = 1;
#endif
      return -1;
    }
  /* Determine the ID the kernel assigned for this netlink connection.
     It is not necessarily the PID if there is more than one socket
     open.  */
  socklen_t addr_len = sizeof (nladdr);
  if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0)
    goto close_and_out;
  h->pid = nladdr.nl_pid;
  return 0;
}
Пример #4
0
/*
 * Usage:
 *      xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
 *
 * Creates, registers, and returns a (rpc) unix based transporter.
 * Once *xprt is initialized, it is registered as a transporter
 * see (svc.h, xprt_register).  This routine returns
 * a NULL if a problem occurred.
 *
 * If sock<0 then a socket is created, else sock is used.
 * If the socket, sock is not bound to a port then svcunix_create
 * binds it to an arbitrary port.  The routine then starts a unix
 * listener on the socket's associated port.  In any (successful) case,
 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
 * associated port number.
 *
 * Since unix streams do buffered io similar to stdio, the caller can specify
 * how big the send and receive buffers are via the second and third parms;
 * 0 => use the system default.
 */
SVCXPRT *
svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
{
  bool_t madesock = FALSE;
  SVCXPRT *xprt;
  struct unix_rendezvous *r;
  struct sockaddr_un addr;
  socklen_t len = sizeof (struct sockaddr_in);

  if (sock == RPC_ANYSOCK)
    {
      if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
	{
	  perror (_("svc_unix.c - AF_UNIX socket creation problem"));
	  return (SVCXPRT *) NULL;
	}
      madesock = TRUE;
    }
  memset (&addr, '\0', sizeof (addr));
  addr.sun_family = AF_UNIX;
  len = strlen (path) + 1;
  memcpy (addr.sun_path, path, len);
  len += sizeof (addr.sun_family);

  bind (sock, (struct sockaddr *) &addr, len);

  if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0
      || listen (sock, 2) != 0)
    {
      perror (_("svc_unix.c - cannot getsockname or listen"));
      if (madesock)
	__close (sock);
      return (SVCXPRT *) NULL;
    }

  r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
  if (r == NULL || xprt == NULL)
    {
#ifdef USE_IN_LIBIO
      if (_IO_fwide (stderr, 0) > 0)
	__fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n"));
      else
#endif
	fputs (_("svcunix_create: out of memory\n"), stderr);
      mem_free (r, sizeof (*r));
      mem_free (xprt, sizeof (SVCXPRT));
      return NULL;
    }
  r->sendsize = sendsize;
  r->recvsize = recvsize;
  xprt->xp_p2 = NULL;
  xprt->xp_p1 = (caddr_t) r;
  xprt->xp_verf = _null_auth;
  xprt->xp_ops = &svcunix_rendezvous_op;
  xprt->xp_port = -1;
  xprt->xp_sock = sock;
  xprt_register (xprt);
  return xprt;
}
int socket(int domain, int type, int protocol) {
    int fd;
    
    fd = __socket(domain, type, protocol);
    if (fdleak_record_backtrace) {
        fdleak_record_backtrace(fd);
    }
    return fd;
}
/*
 * Usage:
 *      xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
 *
 * Creates, registers, and returns a (rpc) tcp based transporter.
 * Once *xprt is initialized, it is registered as a transporter
 * see (svc.h, xprt_register).  This routine returns
 * a NULL if a problem occurred.
 *
 * If sock<0 then a socket is created, else sock is used.
 * If the socket, sock is not bound to a port then svctcp_create
 * binds it to an arbitrary port.  The routine then starts a tcp
 * listener on the socket's associated port.  In any (successful) case,
 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
 * associated port number.
 *
 * Since tcp streams do buffered io similar to stdio, the caller can specify
 * how big the send and receive buffers are via the second and third parms;
 * 0 => use the system default.
 */
SVCXPRT *
svctcp_create (int sock, u_int sendsize, u_int recvsize)
{
  bool_t madesock = FALSE;
  SVCXPRT *xprt;
  struct tcp_rendezvous *r;
  struct sockaddr_in addr;
  socklen_t len = sizeof (struct sockaddr_in);

  if (sock == RPC_ANYSOCK)
    {
      if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
	{
	  perror (_("svc_tcp.c - tcp socket creation problem"));
	  return (SVCXPRT *) NULL;
	}
      madesock = TRUE;
    }
  __bzero ((char *) &addr, sizeof (addr));
  addr.sin_family = AF_INET;
  if (bindresvport (sock, &addr))
    {
      addr.sin_port = 0;
      (void) __bind (sock, (struct sockaddr *) &addr, len);
    }
  if ((__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) ||
      (__listen (sock, SOMAXCONN) != 0))
    {
      perror (_("svc_tcp.c - cannot getsockname or listen"));
      if (madesock)
	(void) __close (sock);
      return (SVCXPRT *) NULL;
    }
  r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r));
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
  if (r == NULL || xprt == NULL)
    {
      (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n"));
      mem_free (r, sizeof (*r));
      mem_free (xprt, sizeof (SVCXPRT));
      return NULL;
    }
  r->sendsize = sendsize;
  r->recvsize = recvsize;
  xprt->xp_p2 = NULL;
  xprt->xp_p1 = (caddr_t) r;
  xprt->xp_verf = _null_auth;
  xprt->xp_ops = &svctcp_rendezvous_op;
  xprt->xp_port = ntohs (addr.sin_port);
  xprt->xp_sock = sock;
  xprt_register (xprt);
  return xprt;
}
Пример #7
0
/*
 * don't use gethostbyname, which would invoke yellow pages
 *
 * Avoid loopback interfaces.  We return information from a loopback
 * interface only if there are no other possible interfaces.
 */
void
get_myaddress (struct sockaddr_in *addr)
{
  int s;
  char buf[BUFSIZ];
  struct ifconf ifc;
  struct ifreq ifreq, *ifr;
  int len, loopback = 0;

  if ((s = __socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    {
      perror ("get_myaddress: socket");
      exit (1);
    }
  ifc.ifc_len = sizeof (buf);
  ifc.ifc_buf = buf;
  if (__ioctl (s, SIOCGIFCONF, (char *) &ifc) < 0)
    {
      perror (_("get_myaddress: ioctl (get interface configuration)"));
      exit (1);
    }

 again:
  ifr = ifc.ifc_req;
  for (len = ifc.ifc_len; len; len -= sizeof ifreq)
    {
      ifreq = *ifr;
      if (__ioctl (s, SIOCGIFFLAGS, (char *) &ifreq) < 0)
	{
          perror ("get_myaddress: ioctl");
          exit (1);
	}
      if ((ifreq.ifr_flags & IFF_UP) && (ifr->ifr_addr.sa_family == AF_INET)
	  && (!(ifreq.ifr_flags & IFF_LOOPBACK) ||
	      (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK))))
	{
	  *addr = *((struct sockaddr_in *) &ifr->ifr_addr);
	  addr->sin_port = htons (PMAPPORT);
	  __close (s);
	  return;
	}
      ifr++;
    }
  if (loopback == 0)
    {
      loopback = 1;
      goto again;
    }
  __close (s);
}
Пример #8
0
static void
internal_function
openlog_internal(const char *ident, int logstat, int logfac)
{
	if (ident != NULL)
		LogTag = ident;
	LogStat = logstat;
	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
		LogFacility = logfac;

	int retry = 0;
	while (retry < 2) {
		if (LogFile == -1) {
			SyslogAddr.sun_family = AF_UNIX;
			(void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
				      sizeof(SyslogAddr.sun_path));
			if (LogStat & LOG_NDELAY) {
				if ((LogFile = __socket(AF_UNIX, LogType, 0))
				    == -1)
					return;
				(void)__fcntl(LogFile, F_SETFD, 1);
			}
		}
		if (LogFile != -1 && !connected)
		{
			int old_errno = errno;
			if (__connect(LogFile, &SyslogAddr, sizeof(SyslogAddr))
			    == -1)
			{
				int saved_errno = errno;
				int fd = LogFile;
				LogFile = -1;
				(void)__close(fd);
				__set_errno (old_errno);
				if (saved_errno == EPROTOTYPE)
				{
					/* retry with the other type: */
					LogType = (LogType == SOCK_DGRAM
						   ? SOCK_STREAM : SOCK_DGRAM);
					++retry;
					continue;
				}
			} else
				connected = 1;
		}
		break;
	}
}
Пример #9
0
/* Return a socket of any type.  The socket can be used in subsequent
   ioctl calls to talk to the kernel.  */
int internal_function
__opensock (void)
{
  /* Cache the last AF that worked, to avoid many redundant calls to
     socket().  */
  static int sock_af = -1;
  int fd = -1;
  __libc_lock_define_initialized (static, lock);

  if (sock_af != -1)
    {
      fd = __socket (sock_af, SOCK_DGRAM, 0);
      if (fd != -1)
        return fd;
    }

  __libc_lock_lock (lock);

  if (sock_af != -1)
    fd = __socket (sock_af, SOCK_DGRAM, 0);

  if (fd == -1)
    {
#ifdef AF_INET
      fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
#endif
#ifdef AF_INET6
      if (fd < 0)
	fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
#endif
#ifdef AF_IPX
      if (fd < 0)
	fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
#endif
#ifdef AF_AX25
      if (fd < 0)
	fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
#endif
#ifdef AF_APPLETALK
      if (fd < 0)
	fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
#endif
    }

  __libc_lock_unlock (lock);
  return fd;
}
Пример #10
0
/* ===========================================================================
 *  TCP Socket Related
 */
int z_socket_tcp_connect (const char *address,
                          const char *port,
                          struct sockaddr_storage *addr)
{
  struct addrinfo hints;
  struct addrinfo *info;
  struct addrinfo *p;
  int status;
  int sock;

  z_memzero(&hints, sizeof(struct addrinfo));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;

  if ((status = getaddrinfo(address, port, &hints, &info)) != 0) {
    fprintf(stderr, "getaddrinfo(): %s", gai_strerror(status));
    return(-1);
  }

  sock = -1;
  for (p = info; p != NULL; p = p->ai_next) {
    if ((sock = __socket(p, 0, 0)) < 0) {
      perror("socket()");
      continue;
    }

    if (connect(sock, p->ai_addr, p->ai_addrlen) < 0) {
      perror("connect()");
      close(sock);
      sock = -1;
      continue;
    }

    if (addr != NULL)
      z_memcpy(addr, p->ai_addr, p->ai_addrlen);

    break;
  }

  freeaddrinfo(info);
  return(sock);
}
Пример #11
0
static int
svc_socket (u_long number, int type, int protocol, int reuse)
{
  struct sockaddr_in addr;
  socklen_t len = sizeof (struct sockaddr_in);
  int sock, ret;
  const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp";

  if ((sock = __socket (AF_INET, type, protocol)) < 0)
    {
      perror (_("svc_socket: socket creation problem"));
      return sock;
    }

  if (reuse)
    {
      ret = 1;
      ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret,
			sizeof (ret));
      if (ret < 0)
	{
	  perror (_("svc_socket: socket reuse problem"));
	  return ret;
	}
    }

  memset (&addr, 0, sizeof (addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(getservport(number, proto));

  if (bind(sock, (struct sockaddr *) &addr, len) < 0)
    {
      perror (_("svc_socket: bind problem"));
      (void) __close(sock);
      sock = -1;
    }

  return svcsock_nonblock(sock);
}
Пример #12
0
static int __socket_bind (const char *address,
                          const char *port,
                          struct addrinfo *hints,
                          struct sockaddr_storage *addr)
{
  struct addrinfo *info;
  struct addrinfo *p;
  int status;
  int sock;

  if ((status = getaddrinfo(address, port, hints, &info)) != 0) {
    fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(status));
    return(-1);
  }

  sock = -1;
  for (p = info; p != NULL; p = p->ai_next) {
    if ((sock = __socket(p, 1, 1)) < 0) {
      perror("socket()");
      continue;
    }

    if (bind(sock, info->ai_addr, info->ai_addrlen) < 0) {
      perror("bind()");
      close(sock);
      sock = -1;
      continue;
    }

    if (addr != NULL)
      z_memcpy(addr, p->ai_addr, p->ai_addrlen);

    break;
  }

  freeaddrinfo(info);
  return(sock);
}
Пример #13
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 *
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;
}
Пример #14
0
static int
svc_socket (u_long number, int type, int protocol, int reuse)
{
  struct sockaddr_in addr;
  socklen_t len = sizeof (struct sockaddr_in);
  int sock, ret;
  const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp";

  if ((sock = __socket (AF_INET, type, protocol)) < 0)
    {
      perror (_("svc_socket: socket creation problem"));
      return sock;
    }

  if (reuse)
    {
      ret = 1;
      ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret,
			sizeof (ret));
      if (ret < 0)
	{
	  perror (_("svc_socket: socket reuse problem"));
	  return ret;
	}
    }

  memset (&addr, 0, sizeof (addr));
  addr.sin_family = AF_INET;
  addr.sin_port = htons(getservport(number, proto));

  if (bind(sock, (struct sockaddr *) &addr, len) < 0)
    {
      perror (_("svc_socket: bind problem"));
      (void) __close(sock);
      sock = -1;
    }

  if (sock >= 0)
    {
	    /* This socket might be shared among multiple processes
	     * if mountd is run multi-threaded.  So it is safest to
	     * make it non-blocking, else all threads might wake
	     * one will get the data, and the others will block
	     * indefinitely.
	     * In all cases, transaction on this socket are atomic
	     * (accept for TCP, packet-read and packet-write for UDP)
	     * so O_NONBLOCK will not confuse unprepared code causing
	     * it to corrupt messages.
	     * It generally safest to have O_NONBLOCK when doing an accept
	     * as if we get a RST after the SYN and before accept runs,
	     * we can block despite being told there was an acceptable
	     * connection.
	     */
	int flags;
	if ((flags = fcntl(sock, F_GETFL)) < 0)
	  {
	      perror (_("svc_socket: can't get socket flags"));
	      (void) __close (sock);
	      sock = -1;
	  }
	else if (fcntl(sock, F_SETFL, flags|O_NONBLOCK) < 0)
	  {
	      perror (_("svc_socket: can't set socket flags"));
	      (void) __close (sock);
	      sock = -1;
	  }
    }

  return sock;
}
Пример #15
0
int
res_send(struct SocketBase *	libPtr,
	 const char *		buf,
	 int			buflen,
	 char *			answer,
	 int 			anslen)
{
	register int n;
	int try, v_circuit, resplen, nscount;
	int gotsomewhere = 0, connected = 0;
	int connreset = 0;
	u_short id, len;
	char *cp;
	fd_set dsmask;
	struct timeval timeout;
	struct in_addr *ns;
	struct sockaddr_in host;
	HEADER *hp = (HEADER *) buf;
	HEADER *anhp = (HEADER *) answer;
	u_char terrno = ETIMEDOUT;
#define JUNK_SIZE 512
	char junk[JUNK_SIZE]; /* buffer for trash data */

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send()\n"));
D(bug("[AROSTCP](res_send.c) res_send: using socket %d\n", res_sock));
#endif

#ifdef RES_DEBUG
		printf("res_send()\n");
		__p_query(buf, libPtr);
#endif /* RES_DEBUG */

	v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
	id = hp->id;
	/*
	 * Send request, RETRY times, or until successful
	 */
	for (try = 0; try < _res.retry; try++) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Attempt %d\n", try));
#endif
	  nscount = 0;
	  DRES(Printf("Retry #%ld\n",try);)
	  for (ns = _res.nsaddr_list; ns->s_addr; ns++) {
	    nscount++;
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Querying server #%ld address = %s\n", nscount,
			      __inet_ntoa(ns->s_addr, libPtr)));
#endif

#ifdef RES_DEBUG
			Printf("Querying server #%ld address = %s\n", nscount,
			      __Inet_NtoA(ns->s_addr, libPtr));
#endif /* RES_DEBUG */
	    host.sin_len = sizeof(host);
	    host.sin_family = AF_INET;
	    host.sin_port = htons(NAMESERVER_PORT);
	    host.sin_addr.s_addr = ns->s_addr;
	    aligned_bzero_const(&host.sin_zero, sizeof(host.sin_zero));
	usevc:
		if (v_circuit) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using v_circuit\n"));
#endif
			int truncated = 0;

			/*
			 * Use virtual circuit;
			 * at most one attempt per server.
			 */
			try = _res.retry;
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_STREAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket!!\n"));
					terrno = readErrnoValue(libPtr);
#endif
#ifdef RES_DEBUG
					    Perror("socket (vc)");
#endif /* RES_DEBUG */
					continue;
				}
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: created socket %d\n", res_sock));
#endif
				if (__connect(res_sock,
					    (struct sockaddr *)&host,
					    sizeof(struct sockaddr), libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to connect\n"));
#endif
				        terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("connect (vc)");
#endif /* RES_DEBUG */
					(void) __CloseSocket(res_sock, libPtr);
					res_sock = -1;
					continue;
				}
			}
			/*
			 * Send length & message
			 */
			len = htons((u_short)buflen);
			if ((__send(res_sock, (char *)&len, sizeof(len), 0, libPtr)
			     != sizeof(len)) ||
			   ((__send(res_sock, (char *)buf, buflen, 0, libPtr)
			     != buflen))) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed sending query\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("write(vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			/*
			 * Receive length & response
			 */
			cp = answer;
			len = sizeof(short);
			while (len != 0 &&
			    (n = __recv(res_sock,
				      (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
				terrno = readErrnoValue(libPtr);
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed recieving response\n"));
#endif
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				/*
				 * A long running process might get its TCP
				 * connection reset if the remote server was
				 * restarted.  Requery the server instead of
				 * trying a new one.  When there is only one
				 * server, this means that a query might work
				 * instead of failing.  We only allow one reset
				 * per query to prevent looping.
				 */
				if (terrno == ECONNRESET && !connreset) {
					connreset = 1;
					ns--;
				}
				continue;
			}
			cp = answer;
			if ((resplen = ntohs(*(u_short *)cp)) > anslen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Truncated response\n"));
#endif
#ifdef RES_DEBUG
				       Printf("response truncated\n");
#endif /* RES_DEBUG */
				len = anslen;
				truncated = 1;
			} else
				len = resplen;
			while (len != 0 &&
			   (n = __recv(res_sock,
				     (char *)cp, (int)len, 0, libPtr)) > 0) {
				cp += n;
				len -= n;
			}
			if (n <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving response\n"));
#endif
				terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					Perror("read (vc)");
#endif /* RES_DEBUG */
				(void) __CloseSocket(res_sock, libPtr);
				res_sock = -1;
				continue;
			}
			if (truncated) {
				/*
				 * Flush rest of answer
				 * so connection stays in synch.
				 */
				anhp->tc = 1;
				len = resplen - anslen;
				while (len != 0) {
					n = (len > JUNK_SIZE ? JUNK_SIZE : len);
					if ((n = __recv(res_sock,
						      junk, n, 0, libPtr)) > 0)
						len -= n;
					else
						break;
				}
			}
		} else {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Using datagrams\n"));
#endif
			/*
			 * Use datagrams.
			 */
			if (res_sock < 0) {
				res_sock = __socket(AF_INET, SOCK_DGRAM, 0, libPtr);
				if (res_sock < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Failed to create socket\n"));
#endif
					terrno = readErrnoValue(libPtr);
#ifdef RES_DEBUG
					    Perror("socket (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}
			/*
			 * I'm tired of answering this question, so:
			 * On a 4.3BSD+ machine (client and server,
			 * actually), sending to a nameserver datagram
			 * port with no nameserver will cause an
			 * ICMP port unreachable message to be returned.
			 * If our datagram socket is "connected" to the
			 * server, we get an ECONNREFUSED error on the next
			 * socket operation, and select returns if the
			 * error message is received.  We can thus detect
			 * the absence of a nameserver without timing out.
			 * If we have sent queries to at least two servers,
			 * however, we don't want to remain connected,
			 * as we wish to receive answers from the first
			 * server to respond.
			 */
#warning "TODO*: see comment here .."
			/* This piece of code still behaves slightly wrong in
			   case of ECONNREFUSED error. On next retry socket will
			   be in disconnected state and instead of getting
			   ECONNREFUSED again we'll timeout in WaitSelect() and
			   get ETIMEDOUT. However, this is not critical and is
			   queued for future - Pavel Fedin*/
			if (try == 0 && nscount == 1) {
				/*
				 * Don't use connect if we might
				 * still receive a response
				 * from another server.
				 */
				if (connected == 0) {
				  if (__connect(res_sock,
					      (struct sockaddr *)&host,
					      sizeof(struct sockaddr),
					      libPtr) < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error connecting\n"));
#endif
#ifdef RES_DEBUG
							Perror("connect (dg)");
#endif /* RES_DEBUG */
						continue;
					}
					connected = 1;
				}
				if (__send(res_sock,
					 buf, buflen, 0, libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error sending\n"));
#endif
#ifdef RES_DEBUG
						Perror("send (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			} else {
				/*
				 * Disconnect if we want to listen
				 * for responses from more than one server.
				 */
				if (connected) {
					(void) __connect(res_sock, &no_addr,
					    sizeof(no_addr), libPtr);
					connected = 0;
				}
				if (__sendto(res_sock, buf, buflen, 0,
				    (struct sockaddr *)&host,
				    sizeof(struct sockaddr), libPtr) != buflen) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__sendto] Error\n"));
#endif
#ifdef RES_DEBUG
						Perror("sendto (dg)");
#endif /* RES_DEBUG */
					continue;
				}
			}

			/*
			 * Wait for reply
			 */
			timeout.tv_sec = (_res.retrans << try);
			if (try > 0)
				timeout.tv_sec /= nscount;
			if (timeout.tv_sec <= 0)
				timeout.tv_sec = 1;
			timeout.tv_usec = 0;
wait:
			FD_ZERO(&dsmask);
			FD_SET(res_sock, &dsmask);
			n = __WaitSelect(res_sock+1, &dsmask, NULL,
				NULL, &timeout, NULL, libPtr);
			if (n < 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: [__WaitSelect] Error\n"));
#endif
#ifdef RES_DEBUG
					Perror("select");
#endif /* RES_DEBUG */

            terrno = readErrnoValue(libPtr);
				if (terrno == EINTR) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: closing socket\n"));
#endif
					__CloseSocket(res_sock, libPtr);
					res_sock = -1;
					return (-1);
				}
				continue;
			}
			if (n == 0) {
				/*
				 * timeout
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Timeout!\n"));
#endif
#ifdef RES_DEBUG
					Printf("timeout\n");
#endif /* RES_DEBUG */
#if 1 || BSD >= 43
				gotsomewhere = 1;
#endif
				continue;
			}
			if ((resplen = __recv(res_sock,
					    answer, anslen, 0, libPtr)) <= 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Error recieving\n"));
#endif
#ifdef RES_DEBUG
					Perror("recv (dg)");
#endif /* RES_DEBUG */
				continue;
			}
			gotsomewhere = 1;
			if (id != anhp->id) {
				/*
				 * response from old query, ignore it
				 */
#ifdef RES_DEBUG
					Printf("old answer:\n");
					__p_query(answer, libPtr);
#endif /* RES_DEBUG */
				goto wait;
			}
			if (!(_res.options & RES_IGNTC) && anhp->tc) {
				/*
				 * get rest of answer;
				 * use TCP with same server.
				 */
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Response is truncated\n"));
#endif
#ifdef RES_DEBUG
					Printf("truncated answer\n");
#endif /* RES_DEBUG */
				(void)__CloseSocket(res_sock, libPtr);
				res_sock = -1;
				v_circuit = 1;
				goto usevc;
			}
		}

#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Recieved answer\n"));
#endif

#ifdef RES_DEBUG
			Printf("got answer:\n");
			__p_query(answer, libPtr);
#endif /* RES_DEBUG */
		/*
		 * If using virtual circuits, we assume that the first server
		 * is preferred * over the rest (i.e. it is on the local
		 * machine) and only keep that one open.
		 * If we have temporarily opened a virtual circuit,
		 * or if we haven't been asked to keep a socket open,
		 * close the socket.
		 */
		if ((v_circuit &&
		    ((_res.options & RES_USEVC) == 0 || ns->s_addr != 0)) ||
		    (_res.options & RES_STAYOPEN) == 0) {
#if defined(__AROS__)
D(bug("[AROSTCP](res_send.c) res_send: Closing socket\n"));
#endif
			(void) __CloseSocket(res_sock, libPtr);
			res_sock = -1;
		}
		return (resplen);
	   }
Пример #16
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;
}
Пример #17
0
/* Create a linked list of `struct ifaddrs' structures, one for each
   network interface on the host machine.  If successful, store the
   list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
int
getifaddrs (struct ifaddrs **ifap)
{
  /* This implementation handles only IPv4 interfaces.
     The various ioctls below will only work on an AF_INET socket.
     Some different mechanism entirely must be used for IPv6.  */
  int fd = __socket (AF_INET, SOCK_DGRAM, 0);
  struct ifreq *ifreqs;
  int nifs;

  if (fd < 0)
    return -1;

  __ifreq (&ifreqs, &nifs, fd);
  if (ifreqs == NULL)		/* XXX doesn't distinguish error vs none */
    {
      __close (fd);
      return -1;
    }

  /* Now we have the list of interfaces and each one's address.
     Put it into the expected format and fill in the remaining details.  */
  if (nifs == 0)
    *ifap = NULL;
  else
    {
      struct
      {
	struct ifaddrs ia;
	struct sockaddr addr, netmask, broadaddr;
	char name[IF_NAMESIZE];
      } *storage;
      struct ifreq *ifr;
      int i;

      storage = malloc (nifs * sizeof storage[0]);
      if (storage == NULL)
	{
	  __close (fd);
	  __if_freereq (ifreqs, nifs);
	  return -1;
	}

      i = 0;
      ifr = ifreqs;
      do
	{
	  /* Fill in pointers to the storage we've already allocated.  */
	  storage[i].ia.ifa_next = &storage[i + 1].ia;
	  storage[i].ia.ifa_addr = &storage[i].addr;

	  /* Now copy the information we already have from SIOCGIFCONF.  */
	  storage[i].ia.ifa_name = strncpy (storage[i].name, ifr->ifr_name,
					    sizeof storage[i].name);
	  storage[i].addr = ifr->ifr_addr;

	  /* The SIOCGIFCONF call filled in only the name and address.
	     Now we must also ask for the other information we need.  */

	  if (__ioctl (fd, SIOCGIFFLAGS, ifr) < 0)
	    break;
	  storage[i].ia.ifa_flags = ifr->ifr_flags;

	  ifr->ifr_addr = storage[i].addr;

	  if (__ioctl (fd, SIOCGIFNETMASK, ifr) < 0)
	    storage[i].ia.ifa_netmask = NULL;
	  else
	    {
	      storage[i].ia.ifa_netmask = &storage[i].netmask;
	      storage[i].netmask = ifr->ifr_netmask;
	    }

	  if (ifr->ifr_flags & IFF_BROADCAST)
	    {
	      ifr->ifr_addr = storage[i].addr;
	      if (__ioctl (fd, SIOCGIFBRDADDR, ifr) < 0)
		storage[i].ia.ifa_broadaddr = NULL;
	      {
		storage[i].ia.ifa_broadaddr = &storage[i].broadaddr;
		storage[i].broadaddr = ifr->ifr_broadaddr;
	      }
	    }
	  else if (ifr->ifr_flags & IFF_POINTOPOINT)
	    {
	      ifr->ifr_addr = storage[i].addr;
	      if (__ioctl (fd, SIOCGIFDSTADDR, ifr) < 0)
		storage[i].ia.ifa_broadaddr = NULL;
	      else
		{
		  storage[i].ia.ifa_broadaddr = &storage[i].broadaddr;
		  storage[i].broadaddr = ifr->ifr_dstaddr;
		}
	    }
	  else
	    storage[i].ia.ifa_broadaddr = NULL;

	  storage[i].ia.ifa_data = NULL; /* Nothing here for now.  */

	  ifr = __if_nextreq (ifr);
	} while (++i < nifs);
      if (i < nifs)		/* Broke out early on error.  */
	{
	  __close (fd);
	  free (storage);
	  __if_freereq (ifreqs, nifs);
	  return -1;
	}

      storage[i - 1].ia.ifa_next = NULL;

      *ifap = &storage[0].ia;

      __close (fd);
      __if_freereq (ifreqs, nifs);
    }

  return 0;
}
int socket(int domain, int type, int protocol) {
    return __socket(domain, type, protocol);
}
Пример #19
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 *
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 ();
      (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 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 = (struct clnt_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);
}
Пример #20
0
/* Return a socket of any type.  The socket can be used in subsequent
   ioctl calls to talk to the kernel.  */
int internal_function
__opensock (void)
{
  static int last_family;	/* Available socket family we will use.  */
  static int last_type;
  static const struct
  {
    int family;
    const char procname[15];
  } afs[] =
    {
      /* The 2.2 kernels cannot handle ioctl(SIOCGIFCONF) on AF_UNIX sockets.
	 Give the kernel a chance to user inet sockets on old kernels.  */
#if __LINUX_KERNEL_VERSION < 132096
      { AF_INET, "" },
      { AF_UNIX, "net/unix" },
#else
      { AF_UNIX, "net/unix" },
      { AF_INET, "" },
#endif
      { AF_INET6, "net/if_inet6" },
      { AF_AX25, "net/ax25" },
      { AF_NETROM, "net/nr" },
      { AF_ROSE, "net/rose" },
      { AF_IPX, "net/ipx" },
      { AF_APPLETALK, "net/appletalk" },
      { AF_ECONET, "sys/net/econet" },
      { AF_ASH, "sys/net/ash" },
      { AF_X25, "net/x25" }
    };
#define nafs (sizeof (afs) / sizeof (afs[0]))
  char fname[sizeof "/proc/" + 14];
  int result;
  int has_proc;
  size_t cnt;

  /* We already know which family to use from the last call.  Use it
     again.  */
  if (last_family != 0)
    {
      assert (last_type != 0);

      result = __socket (last_family, last_type, 0);
      if (result != -1 || errno != EAFNOSUPPORT)
	/* Maybe the socket type isn't supported anymore (module is
	   unloaded).  In this case again try to find the type.  */
	return result;

      /* Reset the values.  They seem not valid anymore.  */
      last_family = 0;
      last_type = 0;
    }

  /* Check whether the /proc filesystem is available.  */
  has_proc = __access ("/proc/net", R_OK) != -1;
  strcpy (fname, "/proc/");

  /* Iterate over the interface families and find one which is
     available.  */
  for (cnt = 0; cnt < nafs; ++cnt)
    {
      int type = SOCK_DGRAM;

      if (has_proc && afs[cnt].procname[0] != '\0')
	{
	  strcpy (fname + 6, afs[cnt].procname);
	  if (__access (fname, R_OK) == -1)
	    /* The /proc entry is not available.  I.e., we cannot
	       create a socket of this type (without loading the
	       module).  Don't look for it since this might trigger
	       loading the module.  */
	    continue;
	}

      if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25)
	type = SOCK_SEQPACKET;

      result = __socket (afs[cnt].family, type, 0);
      if (result != -1)
	{
	  /* Found an available family.  */
	  last_type = type;
	  last_family = afs[cnt].family;
	  return result;
	}
    }

  /* None of the protocol families is available.  It is unclear what kind
     of error is returned.  ENOENT seems like a reasonable choice.  */
  __set_errno (ENOENT);
  return -1;
}
Пример #21
0
int
rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep,
       struct rpc_timeval *timeout)
{
  int s;
  struct pollfd fd;
  int milliseconds;
  int res;
  /* RFC 868 says the time is transmitted as a 32-bit value.  */
  uint32_t thetime;
  struct sockaddr_in from;
  int fromlen;
  int type;

  if (timeout == NULL)
    type = SOCK_STREAM;
  else
    type = SOCK_DGRAM;

  s = __socket (AF_INET, type, 0);
  if (s < 0)
    return (-1);

  addrp->sin_family = AF_INET;
  addrp->sin_port = htons (IPPORT_TIMESERVER);
  if (type == SOCK_DGRAM)
    {
      res = __sendto (s, (char *) &thetime, sizeof (thetime), 0,
		      (struct sockaddr *) addrp, sizeof (*addrp));
      if (res < 0)
	{
	  do_close (s);
	  return -1;
	}
      milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000);
      fd.fd = s;
      fd.events = POLLIN;
      do
	res = __poll (&fd, 1, milliseconds);
      while (res < 0 && errno == EINTR);
      if (res <= 0)
	{
	  if (res == 0)
	    __set_errno (ETIMEDOUT);
	  do_close (s);
	  return (-1);
	}
      fromlen = sizeof (from);
      res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0,
			(struct sockaddr *) &from, &fromlen);
      do_close (s);
      if (res < 0)
	return -1;
    }
  else
    {
      if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0)
	{
	  do_close (s);
	  return -1;
	}
      res = __read (s, (char *) &thetime, sizeof (thetime));
      do_close (s);
      if (res < 0)
	return (-1);
    }
  if (res != sizeof (thetime))
    {
      __set_errno (EIO);
      return -1;
    }
  thetime = ntohl (thetime);
  timep->tv_sec = thetime - TOFFSET;
  timep->tv_usec = 0;
  return 0;
}
Пример #22
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;
}