mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-31 03:00:11 +01:00
sysdeps-unix: Handle errors from getaddrinfo correctly
getaddrinfo and getnameinfo have their own error-handling convention in which the library call returns either 0 or an EAI_* error code unrelated to errno. If the error code is not EAI_SYSTEM, then the value of errno is undefined (in particular it might be carried over from a previous system call or library call). Introduce a new helper function _dbus_error_from_gai() to handle this. The equivalent code paths in Windows appear to be OK: the Windows implementation of getaddrinfo() is documented to return a Winsock error code, which we seem to be handling correctly. Signed-off-by: Simon McVittie <smcv@collabora.com> Reviewed-by: Philip Withnall <withnall@endlessm.com> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=106395
This commit is contained in:
parent
7c7786ae27
commit
60cedd0cfd
1 changed files with 65 additions and 5 deletions
|
|
@ -1325,6 +1325,56 @@ _dbus_listen_systemd_sockets (DBusSocket **fds,
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Convert an error code from getaddrinfo() or getnameinfo() into
|
||||
* a D-Bus error name. */
|
||||
static const char *
|
||||
_dbus_error_from_gai (int gai_res,
|
||||
int saved_errno)
|
||||
{
|
||||
switch (gai_res)
|
||||
{
|
||||
#ifdef EAI_FAMILY
|
||||
case EAI_FAMILY:
|
||||
/* ai_family not supported (at all) */
|
||||
return DBUS_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
#ifdef EAI_SOCKTYPE
|
||||
case EAI_SOCKTYPE:
|
||||
/* ai_socktype not supported (at all) */
|
||||
return DBUS_ERROR_NOT_SUPPORTED;
|
||||
#endif
|
||||
|
||||
#ifdef EAI_MEMORY
|
||||
case EAI_MEMORY:
|
||||
/* Out of memory */
|
||||
return DBUS_ERROR_NO_MEMORY;
|
||||
#endif
|
||||
|
||||
#ifdef EAI_SYSTEM
|
||||
case EAI_SYSTEM:
|
||||
/* Unspecified system error, details in errno */
|
||||
return _dbus_error_from_errno (saved_errno);
|
||||
#endif
|
||||
|
||||
case 0:
|
||||
/* It succeeded, but we didn't get any addresses? */
|
||||
return DBUS_ERROR_FAILED;
|
||||
|
||||
/* EAI_AGAIN: Transient failure */
|
||||
/* EAI_BADFLAGS: invalid ai_flags (programming error) */
|
||||
/* EAI_FAIL: Non-recoverable failure */
|
||||
/* EAI_NODATA: host exists but has no addresses */
|
||||
/* EAI_NONAME: host does not exist */
|
||||
/* EAI_OVERFLOW: argument buffer overflow */
|
||||
/* EAI_SERVICE: service not available for specified socket
|
||||
* type (we should never see this because we use numeric
|
||||
* ports) */
|
||||
default:
|
||||
return DBUS_ERROR_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a socket and connects to a socket at the given host
|
||||
* and port. The connection fd is returned, and is set up as
|
||||
|
|
@ -1386,7 +1436,7 @@ _dbus_connect_tcp_socket_with_nonce (const char *host,
|
|||
if ((res = getaddrinfo(host, port, &hints, &ai)) != 0)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
_dbus_error_from_errno (errno),
|
||||
_dbus_error_from_gai (res, errno),
|
||||
"Failed to lookup host/port: \"%s:%s\": %s (%d)",
|
||||
host, port, gai_strerror(res), res);
|
||||
_dbus_socket_invalidate (&fd);
|
||||
|
|
@ -1545,7 +1595,7 @@ _dbus_listen_tcp_socket (const char *host,
|
|||
if ((res = getaddrinfo(host, port, &hints, &ai)) != 0 || !ai)
|
||||
{
|
||||
dbus_set_error (error,
|
||||
_dbus_error_from_errno (errno),
|
||||
_dbus_error_from_gai (res, errno),
|
||||
"Failed to lookup host/port: \"%s:%s\": %s (%d)",
|
||||
host ? host : "*", port, gai_strerror(res), res);
|
||||
goto failed;
|
||||
|
|
@ -1673,16 +1723,26 @@ _dbus_listen_tcp_socket (const char *host,
|
|||
addrlen = sizeof(addr);
|
||||
result = getsockname(fd, (struct sockaddr*) &addr, &addrlen);
|
||||
|
||||
if (result == -1 ||
|
||||
(res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
|
||||
if (result == -1)
|
||||
{
|
||||
saved_errno = errno;
|
||||
dbus_set_error (error, _dbus_error_from_errno (saved_errno),
|
||||
"Failed to retrieve socket name for \"%s:%s\": %s",
|
||||
host ? host : "*", port, _dbus_strerror (saved_errno));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if ((res = getnameinfo ((struct sockaddr*)&addr, addrlen, NULL, 0,
|
||||
portbuf, sizeof(portbuf),
|
||||
NI_NUMERICHOST | NI_NUMERICSERV)) != 0)
|
||||
{
|
||||
dbus_set_error (error, _dbus_error_from_errno (errno),
|
||||
saved_errno = errno;
|
||||
dbus_set_error (error, _dbus_error_from_gai (res, saved_errno),
|
||||
"Failed to resolve port \"%s:%s\": %s (%d)",
|
||||
host ? host : "*", port, gai_strerror(res), res);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (!_dbus_string_append(retport, portbuf))
|
||||
{
|
||||
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue