From 41543f595b269daf337923bfbf6fd9694f8667ae Mon Sep 17 00:00:00 2001 Message-Id: <41543f595b269daf337923bfbf6fd9694f8667ae.1349621982.git.peeters.simon@gmail.com> From: Simon Peeters Date: Sun, 7 Oct 2012 16:59:30 +0200 Subject: [PATCH] Set correct address when using --address=systemd: 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 --- dbus/dbus-server-unix.c | 38 ++++++++++++++++++--------- dbus/dbus-sysdeps-unix.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-sysdeps-unix.h | 4 +++ 3 files changed, 97 insertions(+), 13 deletions(-) diff --git a/dbus/dbus-server-unix.c b/dbus/dbus-server-unix.c index 130f66e..d995240 100644 --- a/dbus/dbus-server-unix.c +++ b/dbus/dbus-server-unix.c @@ -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) { diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index b4ecc96..6ce96d2 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef HAVE_ERRNO_H #include @@ -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 */ diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 9b70896..a265b33 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -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 -- 1.7.12.1