aboutsummaryrefslogtreecommitdiffstats
path: root/src/net
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2015-07-22 10:13:48 +0200
committerMax Kellermann <max@duempel.org>2015-07-22 10:26:18 +0200
commit8fdfe85b5f6c070c02578bb7b58e01aa01024c2f (patch)
treebc80d55976eabfab1bbc25c0295884df4eb61856 /src/net
parentd4d9a85ad8d719ee4b5edba481a4a641c4b3c44c (diff)
downloadmpd-8fdfe85b5f6c070c02578bb7b58e01aa01024c2f.tar.gz
mpd-8fdfe85b5f6c070c02578bb7b58e01aa01024c2f.tar.xz
mpd-8fdfe85b5f6c070c02578bb7b58e01aa01024c2f.zip
net/ToString: move V4 mapping code to functions
Diffstat (limited to 'src/net')
-rw-r--r--src/net/ToString.cxx51
1 files changed, 36 insertions, 15 deletions
diff --git a/src/net/ToString.cxx b/src/net/ToString.cxx
index 28c333374..860820003 100644
--- a/src/net/ToString.cxx
+++ b/src/net/ToString.cxx
@@ -68,6 +68,39 @@ LocalAddressToString(const struct sockaddr_un &s_un, size_t size)
#endif
+#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
+
+gcc_pure
+static bool
+IsV4Mapped(SocketAddress address)
+{
+ if (address.GetFamily() != AF_INET6)
+ return false;
+
+ const auto &a6 = *(const struct sockaddr_in6 *)address.GetAddress();
+ return IN6_IS_ADDR_V4MAPPED(&a6.sin6_addr);
+}
+
+/**
+ * Convert "::ffff:127.0.0.1" to "127.0.0.1".
+ */
+static SocketAddress
+UnmapV4(SocketAddress src, struct sockaddr_in &buffer)
+{
+ assert(IsV4Mapped(src));
+
+ const auto &src6 = *(const struct sockaddr_in6 *)src.GetAddress();
+ memset(&buffer, 0, sizeof(buffer));
+ buffer.sin_family = AF_INET;
+ memcpy(&buffer.sin_addr, ((const char *)&src6.sin6_addr) + 12,
+ sizeof(buffer.sin_addr));
+ buffer.sin_port = src6.sin6_port;
+
+ return { (const struct sockaddr *)&buffer, sizeof(buffer) };
+}
+
+#endif
+
std::string
sockaddr_to_string(SocketAddress address)
{
@@ -79,21 +112,9 @@ sockaddr_to_string(SocketAddress address)
#endif
#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED)
- const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *)
- address.GetAddress();
- struct sockaddr_in a4;
- if (address.GetFamily() == 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;
-
- address = { (const struct sockaddr *)&a4, sizeof(a4) };
- }
+ struct sockaddr_in in_buffer;
+ if (IsV4Mapped(address))
+ address = UnmapV4(address, in_buffer);
#endif
char host[NI_MAXHOST], serv[NI_MAXSERV];