diff options
author | Jonny Lamb <jonnylamb@gnome.org> | 2011-03-29 12:44:06 +0100 |
---|---|---|
committer | Jonny Lamb <jonnylamb@gnome.org> | 2011-03-29 13:00:12 +0100 |
commit | 701c29a68bc4eb1694148f0abe2c1b612723fa87 (patch) | |
tree | 85db56d572e914ce37ed4795032a17617c5d27fc | |
parent | c9bc758e8d638f2dd37b38249ae0a9a1034d0854 (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.c | 31 |
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); } |