char hostip[INET6_ADDRSTRLEN];
socklen_t size = sizeof (socket);
DBusString path_str;
+ const char *family_name = NULL;
+ dbus_uint16_t port;
if (getsockname (fd.fd, &socket.sa, &size))
goto err;
break;
case AF_INET:
- if (inet_ntop (AF_INET, &socket.ipv4.sin_addr, hostip, sizeof (hostip)))
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ _dbus_string_init_const (&path_str, hostip);
+
+ if (_dbus_inet_sockaddr_to_string (&socket, size, hostip, sizeof (hostip),
+ &family_name, &port, error))
{
- if (_dbus_string_append_printf (address, "tcp:family=ipv4,host=%s,port=%u",
- hostip, ntohs (socket.ipv4.sin_port)))
+ if (_dbus_string_append_printf (address, "tcp:family=%s,port=%u,host=",
+ family_name, port) &&
+ _dbus_address_append_escaped (address, &path_str))
{
return TRUE;
}
return FALSE;
}
}
- goto err;
-
-#ifdef AF_INET6
- case AF_INET6:
- _dbus_string_init_const (&path_str, hostip);
- if (inet_ntop (AF_INET6, &socket.ipv6.sin6_addr, hostip, sizeof (hostip)))
+ else
{
- if (_dbus_string_append_printf (address, "tcp:family=ipv6,port=%u,host=",
- ntohs (socket.ipv6.sin6_port)) &&
- _dbus_address_append_escaped (address, &path_str))
- else
- {
- _DBUS_SET_OOM (error);
- return FALSE;
- }
+ return FALSE;
}
- goto err;
+ /* not reached */
+ break;
-#endif
default:
dbus_set_error (error,
_dbus_error_from_errno (EINVAL),
extern char **environ;
#endif
+#ifdef DBUS_WIN
+#include "dbus-sockets-win.h"
+#else
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#endif
+
/**
* @defgroup DBusSysdeps Internal system-dependent API
* @ingroup DBusInternals
va_end (args);
}
+/*
+ * Try to convert the IPv4 or IPv6 address pointed to by
+ * sockaddr_pointer into a string.
+ *
+ * @param sockaddr_pointer A struct sockaddr_in or struct sockaddr_in6
+ * @param len The length of the struct pointed to by sockaddr_pointer
+ * @param string An array to write the address into
+ * @param string_len Length of string (should usually be at least INET6_ADDRSTRLEN)
+ * @param family_name Used to return "ipv4" or "ipv6", or NULL to ignore
+ * @param port Used to return the port number, or NULL to ignore
+ * @returns #FALSE with errno set if the address family was not understood
+ */
+dbus_bool_t
+_dbus_inet_sockaddr_to_string (const void *sockaddr_pointer,
+ size_t len,
+ char *string,
+ size_t string_len,
+ const char **family_name,
+ dbus_uint16_t *port,
+ DBusError *error)
+{
+ union
+ {
+ struct sockaddr sa;
+ struct sockaddr_storage storage;
+ struct sockaddr_in ipv4;
+ struct sockaddr_in6 ipv6;
+ } addr;
+ int saved_errno;
+
+ if (len > sizeof (addr))
+ return FALSE;
+
+ _DBUS_ZERO (addr);
+ memcpy (&addr, sockaddr_pointer, len);
+
+ switch (addr.sa.sa_family)
+ {
+ case AF_INET:
+ if (inet_ntop (AF_INET, &addr.ipv4.sin_addr, string, string_len) != NULL)
+ {
+ if (family_name != NULL)
+ *family_name = "ipv4";
+
+ if (port != NULL)
+ *port = ntohs (addr.ipv4.sin_port);
+
+ return TRUE;
+ }
+ else
+ {
+ saved_errno = _dbus_get_low_level_socket_errno ();
+ dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+ "Failed to get identity of IPv4 socket: %s",
+ _dbus_strerror (saved_errno));
+ }
+
+ return FALSE;
+
+#ifdef AF_INET6
+ case AF_INET6:
+ if (inet_ntop (AF_INET6, &addr.ipv6.sin6_addr, string, string_len) != NULL)
+ {
+ if (family_name != NULL)
+ *family_name = "ipv6";
+
+ if (port != NULL)
+ *port = ntohs (addr.ipv6.sin6_port);
+
+ return TRUE;
+ }
+ else
+ {
+ saved_errno = _dbus_get_low_level_socket_errno ();
+ dbus_set_error (error, _dbus_error_from_errno (saved_errno),
+ "Failed to get identity of IPv6 socket: %s",
+ _dbus_strerror (saved_errno));
+ }
+
+ return FALSE;
+#endif
+
+ default:
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Failed to get identity of socket: unknown family");
+ return FALSE;
+ }
+}
+
/** @} end of sysdeps */
/* tests in dbus-sysdeps-util.c */