diff --git a/src/network/network_config.cpp b/src/network/network_config.cpp index dcff148f8..bcef3980c 100644 --- a/src/network/network_config.cpp +++ b/src/network/network_config.cpp @@ -71,6 +71,7 @@ NetworkConfig::NetworkConfig() m_joined_server_version = 0; m_network_ai_tester = false; m_state_frequency = 10; + m_nat64_prefix_data.fill(-1); } // NetworkConfig // ---------------------------------------------------------------------------- @@ -188,6 +189,7 @@ bool NetworkConfig::roundValuesNow() const */ void NetworkConfig::detectIPType() { + m_nat64_prefix_data.fill(-1); #ifdef ENABLE_IPV6 ENetAddress addr; addr.host = STKHost::HOST_ANY; @@ -305,6 +307,20 @@ void NetworkConfig::detectIPType() (struct sockaddr_in6*)res->ai_addr; memcpy(nat64.sin6_addr.s6_addr, out->sin6_addr.s6_addr, 12); + m_nat64_prefix_data[0] = + ((uint32_t)(nat64.sin6_addr.s6_addr[0]) << 8) | nat64.sin6_addr.s6_addr[1]; + m_nat64_prefix_data[1] = + ((uint32_t)(nat64.sin6_addr.s6_addr[2]) << 8) | nat64.sin6_addr.s6_addr[3]; + m_nat64_prefix_data[2] = + ((uint32_t)(nat64.sin6_addr.s6_addr[4]) << 8) | nat64.sin6_addr.s6_addr[5]; + m_nat64_prefix_data[3] = + ((uint32_t)(nat64.sin6_addr.s6_addr[6]) << 8) | nat64.sin6_addr.s6_addr[7]; + m_nat64_prefix_data[4] = + ((uint32_t)(nat64.sin6_addr.s6_addr[8]) << 8) | nat64.sin6_addr.s6_addr[9]; + m_nat64_prefix_data[5] = + ((uint32_t)(nat64.sin6_addr.s6_addr[10]) << 8) | nat64.sin6_addr.s6_addr[11]; + m_nat64_prefix_data[6] = 0; + m_nat64_prefix_data[7] = 0; m_nat64_prefix = getIPV6ReadableFromIn6(&nat64); } freeaddrinfo(res); diff --git a/src/network/network_config.hpp b/src/network/network_config.hpp index 8f6f259fa..c98a5e2aa 100644 --- a/src/network/network_config.hpp +++ b/src/network/network_config.hpp @@ -26,6 +26,7 @@ #include "utils/no_copy.hpp" #include "irrString.h" +#include <array> #include <atomic> #include <memory> #include <set> @@ -109,6 +110,7 @@ private: * use it to connect to ipv4 only servers. STK assumes that for all ipv4 * addresses they use the same prefix for each initIPTest. */ std::string m_nat64_prefix; + std::array<uint32_t, 8> m_nat64_prefix_data; public: /** Singleton get, which creates this object if necessary. */ static NetworkConfig *get() @@ -264,6 +266,9 @@ public: void setIPType(IPType ip_type) { m_ip_type.store(ip_type); } // ------------------------------------------------------------------------ const std::string& getNAT64Prefix() const { return m_nat64_prefix; } + // ------------------------------------------------------------------------ + const std::array<uint32_t, 8>& getNAT64PrefixData() const + { return m_nat64_prefix_data; } }; // class NetworkConfig #endif // HEADER_NETWORK_CONFIG diff --git a/src/network/stk_ipv6.cpp b/src/network/stk_ipv6.cpp index 96e8d254c..48a629478 100644 --- a/src/network/stk_ipv6.cpp +++ b/src/network/stk_ipv6.cpp @@ -45,12 +45,12 @@ extern "C" #include <stdlib.h> #endif +#include "network/network_config.hpp" +#include <array> #include <string> // ============================================================================ // Android STK seems to crash when using inet_ntop so we copy it from linux -#define NS_IN6ADDRSZ 16 -#define NS_INT16SZ 2 static const char * stk_inet_ntop4(const u_char *src, char *dst, socklen_t size) { @@ -76,21 +76,26 @@ stk_inet_ntop6(const uint8_t *src, char *dst, socklen_t size) */ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; struct { int base, len; } best, cur; - uint32_t words[NS_IN6ADDRSZ / NS_INT16SZ]; + std::array<uint32_t, 8> words; int i; /* * Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ - memset(words, '\0', sizeof words); - for (i = 0; i < NS_IN6ADDRSZ; i += 2) - words[i / 2] = (src[i] << 8) | src[i + 1]; + words.fill(0); + for (i = 0; i < 16; i += 2) + words[i / 2] = ((uint32_t)src[i] << 8) | src[i + 1]; + // Test for nat64 prefix (remove the possible IPv4 in the last 32bit) + std::array<uint32_t, 8> test_nat64 = words; + test_nat64[6] = 0; + test_nat64[7] = 0; + best.base = -1; cur.base = -1; best.len = 0; cur.len = 0; - for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) + for (i = 0; i < 8; i++) { if (words[i] == 0) { @@ -120,7 +125,7 @@ stk_inet_ntop6(const uint8_t *src, char *dst, socklen_t size) * Format the result. */ tp = tmp; - for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) + for (i = 0; i < 8; i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) @@ -133,8 +138,10 @@ stk_inet_ntop6(const uint8_t *src, char *dst, socklen_t size) if (i != 0) *tp++ = ':'; /* Is this address an encapsulated IPv4? */ - if (i == 6 && best.base == 0 && - (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) + if (i == 6 && + ((best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) || + test_nat64 == NetworkConfig::get()->getNAT64PrefixData())) { if (!stk_inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp))) return (NULL); @@ -144,7 +151,7 @@ stk_inet_ntop6(const uint8_t *src, char *dst, socklen_t size) tp += sprintf(tp, "%x", words[i]); } /* Was it a trailing run of 0x00's? */ - if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) + if (best.base != -1 && (best.base + best.len) == 8) *tp++ = ':'; *tp++ = '\0'; /*