Set correct address when using --address=systemd:
authorSimon Peeters <peeters.simon@gmail.com>
Sun, 7 Oct 2012 14:59:30 +0000 (16:59 +0200)
committerColin Walters <walters@verbum.org>
Mon, 8 Oct 2012 20:58:10 +0000 (16:58 -0400)
When dbus gets launched through systemd, we need to create an address
string based on the sockets passed.

The _dbus_append_addres_from_socket() function is responsible for
extracting the address information from the file-descriptor and
formatting it in a dbus friendly way.

This fixes bus activation when running dbus under a systemd session.

https://bugs.freedesktop.org/show_bug.cgi?id=50962

Signed-off-by: Simon Peeters <peeters.simon@gmail.com>
dbus/dbus-server-unix.c
dbus/dbus-sysdeps-unix.c
dbus/dbus-sysdeps-unix.h

index 130f66e..d995240 100644 (file)
@@ -149,7 +149,7 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
     }
   else if (strcmp (method, "systemd") == 0)
     {
-      int n, *fds;
+      int i, n, *fds;
       DBusString address;
 
       n = _dbus_listen_systemd_sockets (&fds, error);
@@ -159,27 +159,39 @@ _dbus_server_listen_platform_specific (DBusAddressEntry *entry,
           return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
         }
 
-      _dbus_string_init_const (&address, "systemd:");
+      if (!_dbus_string_init (&address))
+          goto systemd_oom;
 
-      *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
-      if (*server_p == NULL)
+      for (i = 0; i < n; i++)
         {
-          int i;
-
-          for (i = 0; i < n; i++)
+          if (i > 0)
             {
-              _dbus_close_socket (fds[i], NULL);
+              if (!_dbus_string_append (&address, ";"))
+                goto systemd_oom;
             }
-          dbus_free (fds);
-
-          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
-          return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+          if (!_dbus_append_address_from_socket (fds[i], &address, error))
+            goto systemd_err;
         }
 
+      *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL);
+      if (*server_p == NULL)
+        goto systemd_oom;
+
       dbus_free (fds);
 
       return DBUS_SERVER_LISTEN_OK;
-       }
+  systemd_oom:
+      _DBUS_SET_OOM (error);
+  systemd_err:
+      for (i = 0; i < n; i++)
+        {
+          _dbus_close_socket (fds[i], NULL);
+        }
+      dbus_free (fds);
+      _dbus_string_free (&address);
+
+      return DBUS_SERVER_LISTEN_DID_NOT_CONNECT;
+    }
 #ifdef DBUS_ENABLE_LAUNCHD
   else if (strcmp (method, "launchd") == 0)
     {
index b4ecc96..55743b1 100644 (file)
@@ -55,6 +55,7 @@
 #include <netinet/in.h>
 #include <netdb.h>
 #include <grp.h>
+#include <arpa/inet.h>
 
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
@@ -4160,4 +4161,71 @@ _dbus_check_setuid (void)
 #endif
 }
 
+/**
+ * Read the address from the socket and append it to the string
+ *
+ * @param fd the socket
+ * @param address
+ * @param error return location for error code
+ */
+dbus_bool_t
+_dbus_append_address_from_socket (int         fd,
+                                  DBusString *address,
+                                  DBusError  *error)
+{
+  union {
+      struct sockaddr sa;
+      struct sockaddr_storage storage;
+      struct sockaddr_un un;
+      struct sockaddr_in ipv4;
+      struct sockaddr_in6 ipv6;
+  } socket;
+  char hostip[INET6_ADDRSTRLEN];
+  int size = sizeof (socket);
+
+  if (getsockname (fd, &socket.sa, &size))
+    goto err;
+
+  switch (socket.sa.sa_family)
+    {
+    case AF_UNIX:
+      if (socket.un.sun_path[0]=='\0')
+        {
+          if (_dbus_string_append_printf (address, "unix:abstract=%s", &(socket.un.sun_path[1])))
+            return TRUE;
+        }
+      else
+        {
+          if (_dbus_string_append_printf (address, "unix:path=%s", socket.un.sun_path))
+            return TRUE;
+        }
+      break;
+    case AF_INET:
+      if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
+        if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
+                   hostip, ntohs (socket.ipv4.sin_port)))
+          return TRUE;
+      break;
+#ifdef AF_INET6
+    case AF_INET6:
+      if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
+        if (_dbus_string_append_printf (address, "tcp:family=ipv6,host=%s,port=%u",
+                   hostip, ntohs (socket.ipv6.sin6_port)))
+          return TRUE;
+      break;
+#endif
+    default:
+      dbus_set_error (error,
+                      _dbus_error_from_errno (EINVAL),
+                      "Failed to read address from socket: Unknown socket type.");
+      return FALSE;
+    }
+ err:
+  dbus_set_error (error,
+                  _dbus_error_from_errno (errno),
+                  "Failed to open socket: %s",
+                  _dbus_strerror (errno));
+  return FALSE;
+}
+
 /* tests in dbus-sysdeps-util.c */
index 9b70896..a265b33 100644 (file)
@@ -138,6 +138,10 @@ dbus_bool_t _dbus_parse_uid (const DBusString  *uid_str,
 
 void _dbus_close_all (void);
 
+dbus_bool_t _dbus_append_address_from_socket (int         fd,
+                                              DBusString *address,
+                                              DBusError  *error);
+
 /** @} */
 
 DBUS_END_DECLS