diff --git a/src/network/network_config.cpp b/src/network/network_config.cpp index 1898a378f..9f4702792 100644 --- a/src/network/network_config.cpp +++ b/src/network/network_config.cpp @@ -232,7 +232,7 @@ void NetworkConfig::detectIPType() SocketAddress stun_v4(ipv4_it->first, 0/*port specified in addr*/, AF_INET); bool sent_ipv4 = false; - if (!stun_v4.isUnset()) + if (!stun_v4.isUnset() && stun_v4.getFamily() == AF_INET) { sendto(ipv4->getENetHost()->socket, s.getData(), s.size(), 0, stun_v4.getSockaddr(), stun_v4.getSocklen()); @@ -242,7 +242,7 @@ void NetworkConfig::detectIPType() SocketAddress stun_v6(ipv6_it->first, 0/*port specified in addr*/, AF_INET6); bool sent_ipv6 = false; - if (!stun_v6.isUnset()) + if (!stun_v6.isUnset() && stun_v6.getFamily() == AF_INET6) { sendto(ipv6->getENetHost()->socket, s.getData(), s.size(), 0, stun_v6.getSockaddr(), stun_v6.getSocklen()); diff --git a/src/network/protocols/connect_to_server.cpp b/src/network/protocols/connect_to_server.cpp index 789a7c5bd..4708a68f7 100644 --- a/src/network/protocols/connect_to_server.cpp +++ b/src/network/protocols/connect_to_server.cpp @@ -256,7 +256,7 @@ void ConnectToServer::asynchronousUpdate() if (m_server->supportsEncryption()) { STKHost::get()->setPublicAddress( - !m_server->useIPV6Connection()); + m_server->useIPV6Connection() ? AF_INET6 : AF_INET); if (!STKHost::get()->getValidPublicAddress().empty()) registerWithSTKServer(); } diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index fafa9ac24..6e495854b 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -1371,12 +1371,12 @@ void ServerLobby::asynchronousUpdate() // Set the IPv6 address first for possible IPv6 only server if (isIPv6Socket() && ip_type >= NetworkConfig::IP_V6) { - STKHost::get()->setPublicAddress(false/*ipv4*/); + STKHost::get()->setPublicAddress(AF_INET6); } if (ip_type == NetworkConfig::IP_V4 || ip_type == NetworkConfig::IP_DUAL_STACK) { - STKHost::get()->setPublicAddress(true/*ipv4*/); + STKHost::get()->setPublicAddress(AF_INET); } if (STKHost::get()->getPublicAddress().isUnset() && STKHost::get()->getPublicIPv6Address().empty()) diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index 6b6572599..9875eeaa0 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -410,12 +410,11 @@ BareNetworkString STKHost::getStunRequest(uint8_t* stun_tansaction_id) //----------------------------------------------------------------------------- void STKHost::getIPFromStun(int socket, const std::string& stun_address, - bool ipv4, SocketAddress* result) + short family, SocketAddress* result) { - short family = ipv4 ? AF_INET : AF_INET6; // The IPv4 stun address has no AAAA record, so give it an AF_INET6 will // return one using NAT64 and DNS64 - if (isIPv6Socket() && ipv4 && + if (isIPv6Socket() && family == AF_INET && NetworkConfig::get()->getIPType() == NetworkConfig::IP_V6_NAT64) family = AF_INET6; @@ -620,9 +619,9 @@ void STKHost::getIPFromStun(int socket, const std::string& stun_address, //----------------------------------------------------------------------------- /** Set the public address using stun protocol. */ -void STKHost::setPublicAddress(bool ipv4) +void STKHost::setPublicAddress(short family) { - auto& stun_map = ipv4 ? UserConfigParams::m_stun_servers_v4 : + auto& stun_map = family == AF_INET ? UserConfigParams::m_stun_servers_v4 : UserConfigParams::m_stun_servers; std::vector > untried_server; for (auto& p : stun_map) @@ -649,13 +648,22 @@ void STKHost::setPublicAddress(bool ipv4) Log::debug("STKHost", "Using STUN server %s", server_name.c_str()); uint64_t ping = StkTime::getMonoTimeMs(); SocketAddress result; - getIPFromStun((int)m_network->getENetHost()->socket, server_name, ipv4, + getIPFromStun((int)m_network->getENetHost()->socket, server_name, family, &result); if (!result.isUnset()) { + if (result.getFamily() != family) + { + Log::error("STKHost", + "Public address family differ from request"); + // This happens when you force to use IPv6 connection to detect + // public address if there is only IPv4 connection, which it + // will give you an IPv4 address, so we can exit earlier + return; + } // For dual stack server we get the IPv6 address and then IPv4, if // their ports differ we discard the public IPv6 address of server - if (NetworkConfig::get()->isServer() && ipv4 && + if (NetworkConfig::get()->isServer() && family == AF_INET && result.getPort() != m_public_address->getPort()) { if (isIPv6Socket()) @@ -665,7 +673,7 @@ void STKHost::setPublicAddress(bool ipv4) } m_public_ipv6_address.clear(); } - if (ipv4) + if (family == AF_INET) *m_public_address = result; else m_public_ipv6_address = result.toString(false/*show_port*/); diff --git a/src/network/stk_host.hpp b/src/network/stk_host.hpp index c216197f5..8df656c99 100644 --- a/src/network/stk_host.hpp +++ b/src/network/stk_host.hpp @@ -177,8 +177,8 @@ private: // ------------------------------------------------------------------------ void mainLoop(); // ------------------------------------------------------------------------ - void getIPFromStun(int socket, const std::string& stun_address, bool ipv4, - SocketAddress* result); + void getIPFromStun(int socket, const std::string& stun_address, + short family, SocketAddress* result); public: /** If a network console should be started. */ static bool m_enable_console; @@ -221,7 +221,7 @@ public: // ------------------------------------------------------------------------ uint16_t getPrivatePort() const; // ------------------------------------------------------------------------ - void setPublicAddress(bool ipv4); + void setPublicAddress(short family); // ------------------------------------------------------------------------ void disconnectAllPeers(bool timeout_waiting = false); //-------------------------------------------------------------------------