From 77b5b4158c7078191cb6e956a6530622db379f38 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 3 Jul 2019 21:39:34 +0200 Subject: [PATCH] net/ToString: move UnmapV4() to class IPv6Address --- src/net/IPv6Address.cxx | 15 +++++++++++++++ src/net/IPv6Address.hxx | 8 ++++++++ src/net/SocketAddress.cxx | 9 +++++++++ src/net/SocketAddress.hxx | 7 +++++++ src/net/ToString.cxx | 25 +------------------------ 5 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/net/IPv6Address.cxx b/src/net/IPv6Address.cxx index c69aadd9f..5c6d38a62 100644 --- a/src/net/IPv6Address.cxx +++ b/src/net/IPv6Address.cxx @@ -28,6 +28,7 @@ */ #include "IPv6Address.hxx" +#include "IPv4Address.hxx" #include #include @@ -54,6 +55,20 @@ IPv6Address::IsAny() const noexcept &in6addr_any, sizeof(in6addr_any)) == 0; } +IPv4Address +IPv6Address::UnmapV4() const noexcept +{ + assert(IsV4Mapped()); + + struct sockaddr_in buffer{}; + buffer.sin_family = AF_INET; + memcpy(&buffer.sin_addr, ((const char *)&address.sin6_addr) + 12, + sizeof(buffer.sin_addr)); + buffer.sin_port = address.sin6_port; + + return buffer; +} + template static void BitwiseAndT(T *dest, const T *a, const T *b, size_t n) diff --git a/src/net/IPv6Address.hxx b/src/net/IPv6Address.hxx index a3aa695a5..7bc0f66f6 100644 --- a/src/net/IPv6Address.hxx +++ b/src/net/IPv6Address.hxx @@ -43,6 +43,8 @@ #include #endif +class IPv4Address; + /** * An OO wrapper for struct sockaddr_in. */ @@ -183,6 +185,12 @@ public: return IN6_IS_ADDR_V4MAPPED(&address.sin6_addr); } + /** + * Convert "::ffff:127.0.0.1" to "127.0.0.1". + */ + gcc_pure + IPv4Address UnmapV4() const noexcept; + /** * Bit-wise AND of two addresses. This is useful for netmask * calculations. diff --git a/src/net/SocketAddress.cxx b/src/net/SocketAddress.cxx index fd0154833..3b5bcbb6e 100644 --- a/src/net/SocketAddress.cxx +++ b/src/net/SocketAddress.cxx @@ -33,6 +33,7 @@ #include "IPv6Address.hxx" #include "util/StringView.hxx" +#include #include #ifdef HAVE_UN @@ -104,6 +105,14 @@ SocketAddress::IsV4Mapped() const noexcept return GetFamily() == AF_INET6 && IPv6Address::Cast(*this).IsV4Mapped(); } +IPv4Address +SocketAddress::UnmapV4() const noexcept +{ + assert(IsV4Mapped()); + + return IPv6Address::Cast(*this).UnmapV4(); +} + unsigned SocketAddress::GetPort() const noexcept { diff --git a/src/net/SocketAddress.hxx b/src/net/SocketAddress.hxx index 392892c01..c1adc54f3 100644 --- a/src/net/SocketAddress.hxx +++ b/src/net/SocketAddress.hxx @@ -43,6 +43,7 @@ template struct ConstBuffer; struct StringView; +class IPv4Address; /** * An OO wrapper for struct sockaddr. @@ -128,6 +129,12 @@ public: gcc_pure bool IsV4Mapped() const noexcept; + /** + * Convert "::ffff:127.0.0.1" to "127.0.0.1". + */ + gcc_pure + IPv4Address UnmapV4() const noexcept; + /** * Extract the port number. Returns 0 if not applicable. */ diff --git a/src/net/ToString.cxx b/src/net/ToString.cxx index 9282edafb..bd229031c 100644 --- a/src/net/ToString.cxx +++ b/src/net/ToString.cxx @@ -80,29 +80,6 @@ LocalAddressToString(const struct sockaddr_un &s_un, size_t size) noexcept #endif -#if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) - -/** - * Convert "::ffff:127.0.0.1" to "127.0.0.1". - */ -static IPv4Address -UnmapV4(SocketAddress src) noexcept -{ - assert(src.IsV4Mapped()); - - const auto &src6 = *(const struct sockaddr_in6 *)src.GetAddress(); - - struct sockaddr_in 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 buffer; -} - -#endif - std::string ToString(SocketAddress address) noexcept { @@ -116,7 +93,7 @@ ToString(SocketAddress address) noexcept #if defined(HAVE_IPV6) && defined(IN6_IS_ADDR_V4MAPPED) IPv4Address ipv4_buffer; if (address.IsV4Mapped()) - address = ipv4_buffer = UnmapV4(address); + address = ipv4_buffer = address.UnmapV4(); #endif char host[NI_MAXHOST], serv[NI_MAXSERV];