From 7a8faaf1771c194af9e36a4ae8ceb3c53c9c8be8 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 8 Mar 2018 13:36:17 +0000 Subject: [PATCH] sysdeps-unix: Set more specific IP-related errors when listening 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 https://bugs.freedesktop.org/show_bug.cgi?id=61922 --- dbus/dbus-sysdeps-unix.c | 13 +++++++------ dbus/dbus-sysdeps.c | 38 ++++++++++++++++++++++++++++++++++++++ dbus/dbus-sysdeps.h | 5 +++++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index d7f16fc7..0ab034ff 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -1562,9 +1562,10 @@ _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)); + + _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen, + "Failed to bind socket", + saved_errno); goto failed; } @@ -1572,9 +1573,9 @@ _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)); + _dbus_set_error_with_inet_sockaddr (error, tmp->ai_addr, tmp->ai_addrlen, + "Failed to listen on socket", + saved_errno); goto failed; } diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index f15e556f..43fa109f 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -870,6 +870,44 @@ _dbus_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 + */ +void +_dbus_set_error_with_inet_sockaddr (DBusError *error, + const void *sockaddr_pointer, + size_t len, + const char *description, + int saved_errno) +{ + char string[INET6_ADDRSTRLEN]; + dbus_uint16_t port; + const struct sockaddr *addr = sockaddr_pointer; + + if (_dbus_inet_sockaddr_to_string (sockaddr_pointer, len, + string, sizeof (string), NULL, &port, + NULL)) + { + 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)); + } +} + /** @} end of sysdeps */ /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 4005a44f..376f6802 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -701,6 +701,11 @@ dbus_bool_t _dbus_inet_sockaddr_to_string (const void *sockaddr_pointer, const char **family_name, dbus_uint16_t *port, DBusError *error); +void _dbus_set_error_with_inet_sockaddr (DBusError *error, + const void *sockaddr_pointer, + size_t len, + const char *description, + int saved_errno); /** @} */ -- 2.12.3