forked from Mirrors/openclonk
Fix host connections on link-local IPv6 addresses
Link-local IPv6 addresses are valid on all interfaces and thus need an interface specifier / scope id, e.g. fe80::1%eth0. This commit adds scope ids for initial host connections only. While not optimal, this is probably enough in practise as the link-local addresses are likely only important when there is no internet connectivity. In this case, connecting clients directly is less of an advantage.ipv6
parent
5d803d3be3
commit
0137c5f929
|
@ -244,6 +244,16 @@ bool C4NetIO::HostAddress::IsLoopback() const
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool C4NetIO::HostAddress::IsLocal() const
|
||||||
|
{
|
||||||
|
if (gen.sa_family == AF_INET6)
|
||||||
|
return IN6_IS_ADDR_LINKLOCAL(&v6.sin6_addr) != 0;
|
||||||
|
// We don't really care about local 169.256.0.0/16 addresses here as users will either have a
|
||||||
|
// router doing DHCP (which will prevent usage of these addresses) or have a network that
|
||||||
|
// doesn't care about IP and IPv6 link-local addresses will work.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void C4NetIO::HostAddress::SetScopeId(int scopeId)
|
void C4NetIO::HostAddress::SetScopeId(int scopeId)
|
||||||
{
|
{
|
||||||
if (gen.sa_family != AF_INET6) return;
|
if (gen.sa_family != AF_INET6) return;
|
||||||
|
|
|
@ -111,6 +111,7 @@ public:
|
||||||
bool IsNull() const;
|
bool IsNull() const;
|
||||||
bool IsMulticast() const;
|
bool IsMulticast() const;
|
||||||
bool IsLoopback() const;
|
bool IsLoopback() const;
|
||||||
|
bool IsLocal() const;
|
||||||
// bool IsBroadcast() const;
|
// bool IsBroadcast() const;
|
||||||
|
|
||||||
StdStrBuf ToString(int flags = 0) const;
|
StdStrBuf ToString(int flags = 0) const;
|
||||||
|
|
|
@ -310,9 +310,25 @@ C4Network2::InitResult C4Network2::InitClient(const class C4Network2Address *pAd
|
||||||
for (int i = 0; i < iAddrCount; i++)
|
for (int i = 0; i < iAddrCount; i++)
|
||||||
if (!pAddrs[i].isIPNull())
|
if (!pAddrs[i].isIPNull())
|
||||||
{
|
{
|
||||||
|
auto addr = pAddrs[i].getAddr();
|
||||||
|
std::vector<C4NetIO::addr_t> addrs;
|
||||||
|
if (addr.IsLocal())
|
||||||
|
{
|
||||||
|
// Local IPv6 addresses need a scope id.
|
||||||
|
for (auto& id : Clients.GetLocal()->getInterfaceIDs())
|
||||||
|
{
|
||||||
|
addr.SetScopeId(id);
|
||||||
|
addrs.push_back(addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
addrs.push_back(addr);
|
||||||
// connection
|
// connection
|
||||||
if (!NetIO.Connect(pAddrs[i].getAddr(), pAddrs[i].getProtocol(), HostCore, szPassword))
|
int cnt = 0;
|
||||||
continue;
|
for (auto& a : addrs)
|
||||||
|
if (NetIO.Connect(a, pAddrs[i].getProtocol(), HostCore, szPassword))
|
||||||
|
cnt++;
|
||||||
|
if (cnt == 0) continue;
|
||||||
// format for message
|
// format for message
|
||||||
if (strAddresses.getLength())
|
if (strAddresses.getLength())
|
||||||
strAddresses.Append(", ");
|
strAddresses.Append(", ");
|
||||||
|
|
|
@ -231,6 +231,8 @@ void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
||||||
addr.SetPort(iPortUDP);
|
addr.SetPort(iPortUDP);
|
||||||
AddAddr(C4Network2Address(addr, P_UDP), false);
|
AddAddr(C4Network2Address(addr, P_UDP), false);
|
||||||
}
|
}
|
||||||
|
if (addr.GetScopeId())
|
||||||
|
InterfaceIDs.insert(addr.GetScopeId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,6 +259,8 @@ void C4Network2Client::AddLocalAddrs(int16_t iPortTCP, int16_t iPortUDP)
|
||||||
addr.SetPort(iPortUDP);
|
addr.SetPort(iPortUDP);
|
||||||
AddAddr(C4Network2Address(addr, P_UDP), false);
|
AddAddr(C4Network2Address(addr, P_UDP), false);
|
||||||
}
|
}
|
||||||
|
if (addr.GetScopeId())
|
||||||
|
InterfaceIDs.insert(addr.GetScopeId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
freeifaddrs(addrs);
|
freeifaddrs(addrs);
|
||||||
|
|
|
@ -57,6 +57,9 @@ protected:
|
||||||
int32_t AddrAttempts[C4ClientMaxAddr];
|
int32_t AddrAttempts[C4ClientMaxAddr];
|
||||||
int32_t iAddrCnt;
|
int32_t iAddrCnt;
|
||||||
|
|
||||||
|
// interface ids
|
||||||
|
std::set<int> InterfaceIDs;
|
||||||
|
|
||||||
// status
|
// status
|
||||||
C4Network2ClientStatus eStatus;
|
C4Network2ClientStatus eStatus;
|
||||||
|
|
||||||
|
@ -88,6 +91,8 @@ public:
|
||||||
int32_t getAddrCnt() const { return iAddrCnt; }
|
int32_t getAddrCnt() const { return iAddrCnt; }
|
||||||
const C4Network2Address &getAddr(int32_t i) const { return Addr[i]; }
|
const C4Network2Address &getAddr(int32_t i) const { return Addr[i]; }
|
||||||
|
|
||||||
|
const std::set<int> &getInterfaceIDs() const { return InterfaceIDs; }
|
||||||
|
|
||||||
C4Network2ClientStatus getStatus() const { return eStatus; }
|
C4Network2ClientStatus getStatus() const { return eStatus; }
|
||||||
bool hasJoinData() const { return getStatus() != NCS_Joining; }
|
bool hasJoinData() const { return getStatus() != NCS_Joining; }
|
||||||
bool isChasing() const { return getStatus() == NCS_Chasing; }
|
bool isChasing() const { return getStatus() == NCS_Chasing; }
|
||||||
|
|
Loading…
Reference in New Issue