From 48484915dc60ac2f7cb65d809793b761c55e23c5 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 8 Mar 2018 13:36:17 +0000 Subject: [PATCH 4/7] _dbus_listen_tcp_socket: Set more specific IP-related errors When we have resolved a hostname/port pair to a list of IPv4 or IPv6 addresses, if we are unable to listen on a a specific one of those addresses, we should report which one. When IPv6 is disabled for the loopback interface, this changes the diagnostic from: Failed to bind socket "localhost:1234": Cannot assign requested address to the more informative Failed to bind socket "::1" port 1234: Cannot assign requested address Signed-off-by: Simon McVittie --- dbus/dbus-sysdeps-unix.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 0eb5e86e..4ee239c6 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1396,6 +1396,43 @@ inet_sockaddr_to_string (const void *sockaddr_pointer, } } +/* + * Format an error appropriate for saved_errno for the IPv4 or IPv6 + * address pointed to by sockaddr_pointer of length sockaddr_len. + * + * @param error The error to set + * @param sockaddr_pointer A struct sockaddr_in or struct sockaddr_in6 + * @param len The length of the struct pointed to by sockaddr_pointer + * @param description A prefix like "Failed to listen on socket" + * @param saved_errno The OS-level error number to use + */ +static void +set_error_with_inet_sockaddr (DBusError *error, + const void *sockaddr_pointer, + socklen_t len, + const char *description, + int saved_errno) +{ + char string[INET6_ADDRSTRLEN]; + dbus_uint16_t port; + const struct sockaddr *addr = sockaddr_pointer; + + if (inet_sockaddr_to_string (sockaddr_pointer, len, string, sizeof (string), + NULL, &port)) + { + dbus_set_error (error, _dbus_error_from_errno (saved_errno), + "%s \"%s\" port %u: %s", + description, string, port, _dbus_strerror (saved_errno)); + } + else + { + dbus_set_error (error, _dbus_error_from_errno (saved_errno), + "%s
: %s", + description, addr->sa_family, + _dbus_strerror (saved_errno)); + } +} + /** * Creates a socket and connects to a socket at the given host * and port. The connection fd is returned, and is set up as @@ -1633,9 +1670,9 @@ _dbus_listen_tcp_socket (const char *host, tmp = tmp->ai_next; continue; } - dbus_set_error (error, _dbus_error_from_errno (saved_errno), - "Failed to bind socket \"%s:%s\": %s", - host ? host : "*", port, _dbus_strerror (saved_errno)); + + set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen, + "Failed to bind socket", saved_errno); goto failed; } @@ -1643,9 +1680,8 @@ _dbus_listen_tcp_socket (const char *host, { saved_errno = errno; _dbus_close (fd, NULL); - dbus_set_error (error, _dbus_error_from_errno (saved_errno), - "Failed to listen on socket \"%s:%s\": %s", - host ? host : "*", port, _dbus_strerror (saved_errno)); + set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen, + "Failed to listen on socket", saved_errno); goto failed; } -- 2.16.2