Exemple #1
0
/* Send N bytes of BUF on socket FD to peer at address ADDR (which is
   ADDR_LEN bytes long).  Returns the number sent, or -1 for errors.  */
ssize_t
__sendto (int fd,
	  const void *buf,
	  size_t n,
	  int flags,
	  const struct sockaddr_un *addr,
	  socklen_t addr_len)
{
  addr_port_t aport = MACH_PORT_NULL;
  error_t err;
  size_t wrote;

  /* Get an address port for the desired destination address.  */
  error_t create_address_port (io_t port,
			       const struct sockaddr_un *addr,
			       socklen_t addr_len,
			       addr_port_t *aport)
    {
      error_t err_port;

      if (addr->sun_family == AF_LOCAL)
	{
	  /* For the local domain, we must look up the name as a file and talk
	     to it with the ifsock protocol.  */
	  file_t file = __file_name_lookup (addr->sun_path, 0, 0);
	  if (file == MACH_PORT_NULL)
	    return errno;
	  err_port = __ifsock_getsockaddr (file, aport);
	  __mach_port_deallocate (__mach_task_self (), file);
	  if (err_port == MIG_BAD_ID || err_port == EOPNOTSUPP)
	    /* The file did not grok the ifsock protocol.  */
	    err_port = ENOTSOCK;
	}
      else
	{
	  err_port = __socket_create_address (port,
					      addr->sun_family,
					      (char *) addr,
					      addr_len,
					      aport);
	}

      return err_port;
    }
Exemple #2
0
/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
int
__bind  (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
{
  addr_port_t aport;
  error_t err;
  const struct sockaddr_un *addr = addrarg.__sockaddr_un__;

  if (addr->sun_family == AF_LOCAL)
    {
      /* For the local domain, we must create a node in the filesystem
	 using the ifsock translator and then fetch the address from it.  */
      file_t dir, node;
      char name[len - offsetof (struct sockaddr_un, sun_path) + 1], *n;

      strncpy (name, addr->sun_path, sizeof name - 1);
      name[sizeof name - 1] = '\0'; /* Make sure */

      dir = __file_name_split (name, &n);
      if (dir == MACH_PORT_NULL)
	return -1;

      /* Create a new, unlinked node in the target directory.  */
      err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node);

      if (! err)
	{
	  /* Set the node's translator to make it a local-domain socket.  */
	  err = __file_set_translator (node,
				       FS_TRANS_EXCL | FS_TRANS_SET,
				       FS_TRANS_EXCL | FS_TRANS_SET, 0,
				       _HURD_IFSOCK, sizeof _HURD_IFSOCK,
				       MACH_PORT_NULL,
				       MACH_MSG_TYPE_COPY_SEND);
	  if (! err)
	    {
	      /* Link the node, now a socket, into the target directory.  */
	      err = __dir_link (dir, node, n, 1);
	      if (err == EEXIST)
		err = EADDRINUSE;
	    }
	  __mach_port_deallocate (__mach_task_self (), node);
	  if (! err)
	    {
	      /* Get a port to the ifsock translator.  */
	      file_t ifsock = __file_name_lookup_under (dir, n, 0, 0);
	      if (ifsock == MACH_PORT_NULL)
		{
		  err = errno;
		  /* If we failed, get rid of the node we created.  */
		  __dir_unlink (dir, n);
		}
	      else
		{
		  /* Get the address port.  */
		  err = __ifsock_getsockaddr (ifsock, &aport);
		  if (err == MIG_BAD_ID || err == EOPNOTSUPP)
		    /* We are not talking to /hurd/ifsock.  Probably
		       someone came in after we linked our node, unlinked
		       it, and replaced it with a different node, before we
		       did our lookup.  Treat it as if our link had failed
		       with EEXIST.  */
		    err = EADDRINUSE;
		}
	      __mach_port_deallocate (__mach_task_self (), ifsock);
	    }
	}
      __mach_port_deallocate (__mach_task_self (), dir);

      if (err)
	return __hurd_fail (err);
    }
Exemple #3
0
/* Give the socket FD the local address ADDR (which is LEN bytes long).  */
int
__bind  (int fd, __CONST_SOCKADDR_ARG addrarg, socklen_t len)
{
    addr_port_t aport;
    error_t err;
    const struct sockaddr_un *addr = addrarg.__sockaddr_un__;

    if (addr->sun_family == AF_LOCAL)
    {
        /* For the local domain, we must create a node in the filesystem
        using the ifsock translator and then fetch the address from it.  */
        file_t dir, node, ifsock;
        char name[len - offsetof (struct sockaddr_un, sun_path) + 1], *n;

        strncpy (name, addr->sun_path, sizeof name - 1);
        name[sizeof name - 1] = '\0'; /* Make sure */

        dir = __file_name_split (name, &n);
        if (dir == MACH_PORT_NULL)
            return -1;

        /* Create a new, unlinked node in the target directory.  */
        err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node);

        if (! err)
        {
            /* Set the node's translator to make it a local-domain socket.  */
            err = __file_set_translator (node,
                                         FS_TRANS_EXCL | FS_TRANS_SET,
                                         FS_TRANS_EXCL | FS_TRANS_SET, 0,
                                         _HURD_IFSOCK, sizeof _HURD_IFSOCK,
                                         MACH_PORT_NULL,
                                         MACH_MSG_TYPE_COPY_SEND);
            if (! err)
            {
                enum retry_type doretry;
                char retryname[1024];
                /* Get a port to the ifsock translator.  */
                err = __dir_lookup (node, "", 0, 0, &doretry, retryname, &ifsock);
                if (! err && (doretry != FS_RETRY_NORMAL || retryname[0] != '\0'))
                    err = EADDRINUSE;
            }
            if (! err)
            {
                /* Get the address port.  */
                err = __ifsock_getsockaddr (ifsock, &aport);
                if (err == MIG_BAD_ID || err == EOPNOTSUPP)
                    err = EGRATUITOUS;
                if (! err)
                {
                    /* Link the node, now a socket with proper mode, into the
                       target directory.  */
                    err = __dir_link (dir, node, n, 1);
                    if (err == EEXIST)
                        err = EADDRINUSE;
                    if (err)
                        __mach_port_deallocate (__mach_task_self (), aport);
                }
                __mach_port_deallocate (__mach_task_self (), ifsock);
            }
            __mach_port_deallocate (__mach_task_self (), node);
        }
        __mach_port_deallocate (__mach_task_self (), dir);

        if (err)
            return __hurd_fail (err);
    }