Logo Search packages:      
Sourcecode: dbus version File versions

int _dbus_listen_unix_socket ( const char *  path,
dbus_bool_t  abstract,
DBusError error 
)

Creates a socket and binds it to the given path, then listens on the socket. The socket is set to be nonblocking.

Uses abstract sockets instead of filesystem-linked sockets if requested (it's possible only on Linux; see "man 7 unix" on Linux). On non-Linux abstract socket usage always fails.

Parameters:
path the socket name
abstract TRUE to use abstract namespace
error return location for errors
Returns:
the listening file descriptor or -1 on error

Definition at line 482 of file dbus-sysdeps.c.

References _dbus_error_from_errno(), _DBUS_MAX_SUN_PATH_LENGTH, _dbus_set_fd_nonblocking(), _dbus_strerror(), _dbus_warn(), and dbus_set_error().

Referenced by _dbus_server_new_for_domain_socket().

{
  int listen_fd;
  struct sockaddr_un addr;

  _DBUS_ASSERT_ERROR_IS_CLEAR (error);

  _dbus_verbose ("listening on unix socket %s abstract=%d\n",
                 path, abstract);
  
  listen_fd = socket (PF_UNIX, SOCK_STREAM, 0);
  
  if (listen_fd < 0)
    {
      dbus_set_error (error, _dbus_error_from_errno (errno),
                      "Failed to create socket \"%s\": %s",
                      path, _dbus_strerror (errno));
      return -1;
    }

  _DBUS_ZERO (addr);
  addr.sun_family = AF_UNIX;
  
  if (abstract)
    {
#ifdef HAVE_ABSTRACT_SOCKETS
      /* remember that abstract names aren't nul-terminated so we rely
       * on sun_path being filled in with zeroes above.
       */
      addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
      strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2);
      /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
#else /* HAVE_ABSTRACT_SOCKETS */
      dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
                      "Operating system does not support abstract socket namespace\n");
      close (listen_fd);
      return -1;
#endif /* ! HAVE_ABSTRACT_SOCKETS */
    }
  else
    {
      /* FIXME discussed security implications of this with Nalin,
       * and we couldn't think of where it would kick our ass, but
       * it still seems a bit sucky. It also has non-security suckage;
       * really we'd prefer to exit if the socket is already in use.
       * But there doesn't seem to be a good way to do this.
       *
       * Just to be extra careful, I threw in the stat() - clearly
       * the stat() can't *fix* any security issue, but it at least
       * avoids inadvertent/accidental data loss.
       */
      {
        struct stat sb;

        if (stat (path, &sb) == 0 &&
            S_ISSOCK (sb.st_mode))
          unlink (path);
      }

      strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1);
    }
  
  if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0)
    {
      dbus_set_error (error, _dbus_error_from_errno (errno),
                      "Failed to bind socket \"%s\": %s",
                      path, _dbus_strerror (errno));
      close (listen_fd);
      return -1;
    }

  if (listen (listen_fd, 30 /* backlog */) < 0)
    {
      dbus_set_error (error, _dbus_error_from_errno (errno),
                      "Failed to listen on socket \"%s\": %s",
                      path, _dbus_strerror (errno));
      close (listen_fd);
      return -1;
    }

  if (!_dbus_set_fd_nonblocking (listen_fd, error))
    {
      _DBUS_ASSERT_ERROR_IS_SET (error);
      close (listen_fd);
      return -1;
    }
  
  /* Try opening up the permissions, but if we can't, just go ahead
   * and continue, maybe it will be good enough.
   */
  if (!abstract && chmod (path, 0777) < 0)
    _dbus_warn ("Could not set mode 0777 on socket %s\n",
                path);
  
  return listen_fd;
}


Generated by  Doxygen 1.6.0   Back to index