aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-02-28 15:20:33 +0100
committerMax Kellermann <max@duempel.org>2009-02-28 15:20:33 +0100
commite085deb9444bc049401a4296c3e7ad87659a663a (patch)
tree84c38666a068be56059f964badc0b69ea6f4e444
parentb55d9fcdb8a4ad0164f34f45d523bf165bcb496d (diff)
downloadmpd-e085deb9444bc049401a4296c3e7ad87659a663a.tar.gz
mpd-e085deb9444bc049401a4296c3e7ad87659a663a.tar.xz
mpd-e085deb9444bc049401a4296c3e7ad87659a663a.zip
socket_util: unpack V4MAPPED addresses
Unpack IPv4 addresses which are packed inside an IPv6 address, i.e. return "127.0.0.1" rather than "::ffff:127.0.0.1".
-rw-r--r--src/socket_util.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/socket_util.c b/src/socket_util.c
index 240577fc6..31b656326 100644
--- a/src/socket_util.c
+++ b/src/socket_util.c
@@ -29,9 +29,29 @@
char *
sockaddr_to_string(const struct sockaddr *sa, size_t length, GError **error)
{
+#ifdef HAVE_IPV6
+ const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)sa;
+ struct sockaddr_in a4;
+#endif
int ret;
char host[NI_MAXHOST], serv[NI_MAXSERV];
+#ifdef HAVE_IPV6
+ if (sa->sa_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) {
+ /* convert "::ffff:127.0.0.1" to "127.0.0.1" */
+
+ memset(&a4, 0, sizeof(a4));
+ a4.sin_family = AF_INET;
+ memcpy(&a4.sin_addr, ((const char *)&a6->sin6_addr) + 12,
+ sizeof(a4.sin_addr));
+ a4.sin_port = a6->sin6_port;
+
+ sa = (const struct sockaddr *)&a4;
+ length = sizeof(a4);
+ }
+#endif
+
ret = getnameinfo(sa, length, host, sizeof(host), serv, sizeof(serv),
NI_NUMERICHOST|NI_NUMERICSERV);
if (ret != 0) {