Fix possible address family mismatch (found in android)

This commit is contained in:
Benau 2020-02-02 10:52:19 +08:00
parent ecb31ad217
commit 906dca1a94
5 changed files with 24 additions and 16 deletions

View File

@ -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());

View File

@ -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();
}

View File

@ -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())

View File

@ -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<std::pair<std::string, uint32_t> > 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*/);

View File

@ -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);
//-------------------------------------------------------------------------