summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonny Lamb <jonnylamb@gnome.org>2011-03-29 12:44:06 +0100
committerJonny Lamb <jonnylamb@gnome.org>2011-03-29 13:00:12 +0100
commit701c29a68bc4eb1694148f0abe2c1b612723fa87 (patch)
tree85db56d572e914ce37ed4795032a17617c5d27fc
parentc9bc758e8d638f2dd37b38249ae0a9a1034d0854 (diff)
gsocket: normalize ipv6 addresses before returning themv6only
If the socket family is AF_INET6 the remote address can be a v6-in-v4 address (such as ::ffff:172.22.64.188) which is actually quite annoying. If we are in this case, normalize the address to AF_INET instead. Signed-off-by: Jonny Lamb <jonnylamb@gnome.org>
-rw-r--r--gio/gsocket.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/gio/gsocket.c b/gio/gsocket.c
index 01792a7fe..2d32396c0 100644
--- a/gio/gsocket.c
+++ b/gio/gsocket.c
@@ -1216,6 +1216,33 @@ g_socket_get_fd (GSocket *socket)
return socket->priv->fd;
}
+/* If the family is AF_INET6 then this could be a v6-in-v4 which, when
+ * get_local_address or get_remote_address is called, should never be
+ * returned as is. No-one wants to have their IPv4 addresses
+ * represented by IPv6 addresses like ::ffff:172.22.64.188. Therefore,
+ * let's convert it to a real IPv4 address. */
+static void
+g_socket_normalize_address (struct sockaddr_storage *addr)
+{
+#if defined (IN6_IS_ADDR_V4MAPPED)
+ struct sockaddr_in *s4 = (struct sockaddr_in *) addr;
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) addr;
+
+ if (s6->sin6_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED (&(s6->sin6_addr)))
+ {
+ u_int32_t addr_big_endian;
+ u_int16_t port;
+
+ memcpy (&addr_big_endian, s6->sin6_addr.s6_addr + 12, 4);
+ port = s6->sin6_port;
+
+ s4->sin_family = AF_INET;
+ s4->sin_addr.s_addr = addr_big_endian;
+ s4->sin_port = port;
+ }
+#endif
+}
+
/**
* g_socket_get_local_address:
* @socket: a #GSocket.
@@ -1247,6 +1274,8 @@ g_socket_get_local_address (GSocket *socket,
return NULL;
}
+ g_socket_normalize_address (&buffer);
+
return g_socket_address_new_from_native (&buffer, len);
}
@@ -1290,6 +1319,8 @@ g_socket_get_remote_address (GSocket *socket,
return NULL;
}
+ g_socket_normalize_address (&buffer);
+
socket->priv->remote_address = g_socket_address_new_from_native (&buffer, len);
}